Initial Academy support

Support for the Academy's Nano system is complete, but they're not being
saved to the DB yet.
This commit is contained in:
dongresource 2020-11-25 23:36:30 +01:00 committed by Gent S
parent 49158360ca
commit a99f95d15f
11 changed files with 4993 additions and 10 deletions

View File

@ -189,6 +189,11 @@ void CNLoginServer::login(CNSocket* sock, CNPacketData* data) {
resp.iOpenBetaFlag = 0;
resp.uiSvrTime = getTime();
#ifdef ACADEMY
// do not prompt player to "enable freechat", which would only close the client
resp.iChatEnabled = 1;
#endif
// send the resp in with original key
sock->sendPacket((void*)&resp, P_LS2CL_REP_LOGIN_SUCC, sizeof(sP_LS2CL_REP_LOGIN_SUCC));

View File

@ -50,6 +50,8 @@ void terminate(int);
#include "structs/0728.hpp"
#elif PROTOCOL_VERSION == 104
#include "structs/0104.hpp"
#elif PROTOCOL_VERSION == 1013
#include "structs/1013.hpp"
#else
#error Invalid PROTOCOL_VERSION
#endif

View File

@ -729,6 +729,7 @@ void ChatManager::init() {
registerCommand("toggleai", 30, toggleAiCommand, "enable/disable mob AI");
registerCommand("flush", 30, flushCommand, "save gruntwork to file");
registerCommand("level", 50, levelCommand, "change your character's level");
registerCommand("levelx", 50, levelCommand, "change your character's level"); // for Academy
registerCommand("population", 100, populationCommand, "check how many players are online");
registerCommand("refresh", 100, refreshCommand, "teleport yourself to your current location");
registerCommand("minfo", 30, minfoCommand, "show details of the current mission and task.");

View File

@ -458,15 +458,17 @@ void MissionManager::updateFusionMatter(CNSocket* sock, int fusion) {
if (plr->level >= 36)
return;
// don't give the Blossom nano mission until the player's in the Past
if (plr->level == 4 && plr->PCStyle2.iPayzoneFlag == 0)
return;
// TODO: lower the player's FM immediately on level up in the Academy
#ifndef ACADEMY
// check if it is enough for the nano mission
int fmNano = AvatarGrowth[plr->level]["m_iReqBlob_NanoCreate"];
if (plr->fusionmatter < fmNano)
return;
// don't give the Blossom nano mission until the player's in the Past
if (plr->level == 4 && plr->PCStyle2.iPayzoneFlag == 0)
return;
// check if the nano task is already started
for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) {
TaskData& task = *Tasks[plr->tasks[i]];
@ -480,6 +482,7 @@ void MissionManager::updateFusionMatter(CNSocket* sock, int fusion) {
INITSTRUCT(sP_FE2CL_REP_PC_TASK_START_SUCC, response);
response.iTaskNum = AvatarGrowth[plr->level]["m_iNanoQuestTaskID"];
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_START_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_START_SUCC));
#endif
// play the beam animation for other players
INITSTRUCT(sP_FE2CL_PC_EVENT, bcast);

View File

@ -230,12 +230,15 @@ void NanoManager::nanoPotionHandler(CNSocket* sock, CNPacketData* data) {
#pragma region Helper methods
void NanoManager::addNano(CNSocket* sock, int16_t nanoID, int16_t slot, bool spendfm) {
if (nanoID > 36)
if (nanoID > NANO_COUNT)
return;
Player *plr = PlayerManager::getPlayer(sock);
int level = nanoID < plr->level ? plr->level : nanoID;
int level = plr->level;
#ifndef ACADEMY
level = nanoID < plr->level ? plr->level : nanoID;
/*
* Spend the necessary Fusion Matter.
@ -246,6 +249,7 @@ void NanoManager::addNano(CNSocket* sock, int16_t nanoID, int16_t slot, bool spe
if (spendfm)
MissionManager::updateFusionMatter(sock, -(int)MissionManager::AvatarGrowth[plr->level-1]["m_iReqBlob_NanoCreate"]);
#endif
// Send to client
INITSTRUCT(sP_FE2CL_REP_PC_NANO_CREATE_SUCC, resp);
@ -304,7 +308,7 @@ void NanoManager::summonNano(CNSocket *sock, int slot, bool silent) {
nanoUnbuff(sock, targetData, pwr.bitFlag, pwr.timeBuffID, 0,(SkillTable[skillID].targetType == 3));
}
if (nanoID > 36 || nanoID < 0)
if (nanoID > NANO_COUNT || nanoID < 0)
return; // sanity check
plr->activeNano = nanoID;
@ -339,7 +343,7 @@ void NanoManager::summonNano(CNSocket *sock, int slot, bool silent) {
}
void NanoManager::setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill) {
if (skill->iNanoID > 36)
if (skill->iNanoID > NANO_COUNT)
return;
Player *plr = PlayerManager::getPlayer(sock);
@ -367,8 +371,10 @@ void NanoManager::setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill) {
}
}
#ifndef ACADEMY
if (plr->fusionmatter < (int)MissionManager::AvatarGrowth[plr->level]["m_iReqBlob_NanoTune"]) // sanity check
return;
#endif
plr->fusionmatter -= (int)MissionManager::AvatarGrowth[plr->level]["m_iReqBlob_NanoTune"];
@ -410,7 +416,7 @@ void NanoManager::setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill) {
}
void NanoManager::resetNanoSkill(CNSocket* sock, int16_t nanoID) {
if (nanoID > 36)
if (nanoID > NANO_COUNT)
return;
Player *plr = PlayerManager::getPlayer(sock);

View File

@ -28,7 +28,7 @@ struct Player {
int32_t batteryN;
sPCStyle PCStyle;
sPCStyle2 PCStyle2;
sNano Nanos[37]; // acquired nanos
sNano Nanos[NANO_COUNT]; // acquired nanos
int equippedNanos[3];
int activeNano; // active nano (index into Nanos)
int8_t iPCState;

View File

@ -243,6 +243,7 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
// nanos
for (int i = 1; i < SIZEOF_NANO_BANK_SLOT; i++) {
response.PCLoadData2CL.aNanoBank[i] = plr.Nanos[i];
//response.PCLoadData2CL.aNanoBank[i] = plr.Nanos[i] = {0};
}
for (int i = 0; i < 3; i++) {
response.PCLoadData2CL.aNanoSlots[i] = plr.equippedNanos[i];
@ -304,6 +305,8 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
MissionManager::failInstancedMissions(sock);
sendNanoBookSubset(sock);
// initial buddy sync
BuddyManager::refreshBuddyList(sock);
@ -312,6 +315,49 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
ChatManager::sendServerMessage(pair.first, "[ADMIN]" + getPlayerName(&plr) + " has joined.");
}
/*
* Sends all nanos, from 0 to 58 (the contents of the Nanos array in PC_ENTER_SUCC are totally irrelevant).
* The first Nano in the in-game nanobook is the Unstable Nano, which is Van Kleiss.
* 0 (in plr->Nanos) is the null nano entry.
* 58 is a "Coming Soon" duplicate entry for an actual Van Kleiss nano, identical to the Unstable Nano.
* Nanos the player hasn't unlocked will (and should) be greyed out. Thus, all nanos should be accounted
* for in these packets, even if the player hasn't unlocked them.
*/
void PlayerManager::sendNanoBookSubset(CNSocket *sock) {
#ifdef ACADEMY
//#if 0
Player *plr = getPlayer(sock);
#define P_FE2CL_REP_NANO_BOOK_SUBSET 822083892
int16_t id = 0;
INITSTRUCT(sP_FE2CL_REP_NANO_BOOK_SUBSET, pkt);
pkt.PCUID = plr->iID;
pkt.bookSize = NANO_COUNT;
while (id < NANO_COUNT) {
pkt.elementOffset = id;
for (int i = id - pkt.elementOffset; id < NANO_COUNT && i < 10; id++, i = id - pkt.elementOffset) {
// change between these two lines to either get all nanos or none
//pkt.element[i] = plr->Nanos[id] = {id, 36, 150};
//pkt.element[i] = plr->Nanos[id] = {0};
// this one should be kept
pkt.element[i] = plr->Nanos[id];
std::cout << "adding " << (int) id << std::endl;
}
std::cout << "sending subset" << std::endl;
sock->sendPacket((void*)&pkt, P_FE2CL_REP_NANO_BOOK_SUBSET, sizeof(sP_FE2CL_REP_NANO_BOOK_SUBSET));
}
// TODO: possibly send a player refresh packet from here
#endif
}
void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) {
Player* plr = getPlayer(sock);
for (auto it = plr->viewableChunks->begin(); it != plr->viewableChunks->end(); it++) {

View File

@ -61,4 +61,6 @@ namespace PlayerManager {
void setSpecialState(CNSocket* sock, CNPacketData* data);
Player *getPlayerFromID(int32_t iID);
CNSocket *getSockFromID(int32_t iID);
void sendNanoBookSubset(CNSocket *sock);
}

View File

@ -5,6 +5,9 @@
#define AQINVEN_COUNT 50
#define ABANK_COUNT 119
// includes zeroeth entry
#define NANO_COUNT 37
#pragma pack(push)
#pragma pack(4)

View File

@ -5,6 +5,9 @@
#define AQINVEN_COUNT 50
#define ABANK_COUNT 200
// includes zeroeth entry
#define NANO_COUNT 37
#pragma pack(push)
#pragma pack(4)

4912
src/structs/1013.hpp Normal file

File diff suppressed because it is too large Load Diff