#include "CNShardServer.hpp" #include "CNStructs.hpp" #include "NanoManager.hpp" #include "PlayerManager.hpp" void NanoManager::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_EQUIP, nanoEquipHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_UNEQUIP, nanoUnEquipHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_NANO, nanoGMGiveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_TUNE, nanoSkillSetHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_NANO_SKILL, nanoSkillSetGMHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_SKILL_USE, nanoSkillUseHandler); } void NanoManager::nanoEquipHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NANO_EQUIP)) return; // malformed packet sP_CL2FE_REQ_NANO_EQUIP* nano = (sP_CL2FE_REQ_NANO_EQUIP*)data->buf; INITSTRUCT(sP_FE2CL_REP_NANO_EQUIP_SUCC, resp); Player *plr = PlayerManager::getPlayer(sock); // sanity check if (nano->iNanoSlotNum > 2 || nano->iNanoSlotNum < 0) return; resp.iNanoID = nano->iNanoID; resp.iNanoSlotNum = nano->iNanoSlotNum; // Update player plr->equippedNanos[nano->iNanoSlotNum] = nano->iNanoID; // unsummon nano if replaced if (plr->activeNano == plr->equippedNanos[nano->iNanoSlotNum]) summonNano(sock, -1); sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_EQUIP_SUCC, sizeof(sP_FE2CL_REP_NANO_EQUIP_SUCC)); } void NanoManager::nanoUnEquipHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NANO_UNEQUIP)) return; // malformed packet sP_CL2FE_REQ_NANO_UNEQUIP* nano = (sP_CL2FE_REQ_NANO_UNEQUIP*)data->buf; INITSTRUCT(sP_FE2CL_REP_NANO_UNEQUIP_SUCC, resp); Player *plr = PlayerManager::getPlayer(sock); // sanity check if (nano->iNanoSlotNum > 2 || nano->iNanoSlotNum < 0) return; resp.iNanoSlotNum = nano->iNanoSlotNum; // unsummon nano if removed if (plr->equippedNanos[nano->iNanoSlotNum] == plr->activeNano) summonNano(sock, -1); // update player plr->equippedNanos[nano->iNanoSlotNum] = 0; sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_UNEQUIP_SUCC, sizeof(sP_FE2CL_REP_NANO_UNEQUIP_SUCC)); } void NanoManager::nanoGMGiveHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_PC_GIVE_NANO)) return; // ignore the malformed packet // Cmd: /nano sP_CL2FE_REQ_PC_GIVE_NANO* nano = (sP_CL2FE_REQ_PC_GIVE_NANO*)data->buf; Player *plr = PlayerManager::getPlayer(sock); // Add nano to player addNano(sock, nano->iNanoID, 0); DEBUGLOG( std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " requested to add nano id: " << nano->iNanoID << std::endl; ) } void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NANO_ACTIVE)) return; // malformed packet sP_CL2FE_REQ_NANO_ACTIVE* pkt = (sP_CL2FE_REQ_NANO_ACTIVE*)data->buf; Player *plr = PlayerManager::getPlayer(sock); summonNano(sock, pkt->iNanoSlotNum); // Send to client DEBUGLOG( std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " requested to summon nano slot: " << pkt->iNanoSlotNum << std::endl; ) } void NanoManager::nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NANO_SKILL_USE)) return; // malformed packet sP_CL2FE_REQ_NANO_SKILL_USE* skill = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf; Player *plr = PlayerManager::getPlayer(sock); // Send to client INITSTRUCT(sP_FE2CL_NANO_SKILL_USE_SUCC, resp); resp.iArg1 = skill->iArg1; resp.iArg2 = skill->iArg2; resp.iArg3 = skill->iArg3; resp.iBulletID = skill->iBulletID; resp.iTargetCnt = skill->iTargetCnt; resp.iPC_ID = plr->iID; resp.iNanoStamina = 150; // Hardcoded for now sock->sendPacket((void*)&resp, P_FE2CL_NANO_SKILL_USE_SUCC, sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC)); DEBUGLOG( std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " requested to summon nano skill " << std::endl; ) } void NanoManager::nanoSkillSetHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NANO_TUNE)) return; // malformed packet sP_CL2FE_REQ_NANO_TUNE* skill = (sP_CL2FE_REQ_NANO_TUNE*)data->buf; setNanoSkill(sock, skill->iNanoID, skill->iTuneID); } void NanoManager::nanoSkillSetGMHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_PC_GIVE_NANO_SKILL)) return; // malformed packet sP_CL2FE_REQ_NANO_TUNE* skillGM = (sP_CL2FE_REQ_NANO_TUNE*)data->buf; setNanoSkill(sock, skillGM->iNanoID, skillGM->iTuneID); } #pragma region Helper methods void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot) { if (nanoId > 36) return; Player *plr = PlayerManager::getPlayer(sock); // Send to client INITSTRUCT(sP_FE2CL_REP_PC_NANO_CREATE_SUCC, resp); resp.Nano.iID = nanoId; resp.Nano.iStamina = 150; resp.iQuestItemSlotNum = slot; sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_NANO_CREATE_SUCC, sizeof(sP_FE2CL_REP_PC_NANO_CREATE_SUCC)); // Update player plr->Nanos[nanoId] = resp.Nano; // After a nano gets added, setting the level seems to be important so we are doing that if (nanoId < plr->level) nanoId = plr->level; // Even if player level is unchanged, this packet still needs to be sent as using /nano always sets the player to 0 INITSTRUCT(sP_FE2CL_REP_PC_CHANGE_LEVEL, resp2); resp2.iPC_ID = plr->iID; resp2.iPC_Level = nanoId; sock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL)); for (CNSocket* s : PlayerManager::players[sock].viewable) s->sendPacket((void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL)); plr->level = nanoId; } void NanoManager::summonNano(CNSocket *sock, int slot) { INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp); resp.iActiveNanoSlotNum = slot; sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_ACTIVE_SUCC, sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC)); Player *plr = PlayerManager::getPlayer(sock); std::cout << "summon nano\n"; if (slot > 2 || slot < 0) // TODO: implement proper way to dismiss nano if slot = -1 return; // sanity check int nanoId = plr->equippedNanos[slot]; if (nanoId > 36 || nanoId < 0) return; // sanity check sNano nano = plr->Nanos[nanoId]; // Send to other players INITSTRUCT(sP_FE2CL_NANO_ACTIVE, pkt1); pkt1.iPC_ID = plr->iID; pkt1.Nano = nano; for (CNSocket* s : PlayerManager::players[sock].viewable) s->sendPacket((void*)&pkt1, P_FE2CL_NANO_ACTIVE, sizeof(sP_FE2CL_NANO_ACTIVE)); // update player plr->activeNano = nanoId; } void NanoManager::setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId) { if (nanoId > 36) return; Player *plr = PlayerManager::getPlayer(sock); sNano nano = plr->Nanos[nanoId]; nano.iSkillID = skillId; plr->Nanos[nanoId] = nano; // Send to client INITSTRUCT(sP_FE2CL_REP_NANO_TUNE_SUCC, resp); resp.iNanoID = nanoId; resp.iSkillID = skillId; sock->sendPacket((void*)&resp, P_FE2CL_REP_NANO_TUNE_SUCC, sizeof(sP_FE2CL_REP_NANO_TUNE_SUCC)); DEBUGLOG( std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " set skill id " << skillId << " for nano: " << nanoId << std::endl; ) } void NanoManager::resetNanoSkill(CNSocket* sock, int16_t nanoId) { if (nanoId > 36) return; Player *plr = PlayerManager::getPlayer(sock); sNano nano = plr->Nanos[nanoId]; // 0 is reset nano.iSkillID = 0; plr->Nanos[nanoId] = nano; } #pragma endregion