diff --git a/src/ChatManager.cpp b/src/ChatManager.cpp index 108d2fe..9da9397 100644 --- a/src/ChatManager.cpp +++ b/src/ChatManager.cpp @@ -213,45 +213,17 @@ void summonWCommand(std::string full, std::vector& args, CNSocket* if (type >= 3314) return; - int team = NPCManager::NPCData[type]["m_iTeam"]; - - assert(NPCManager::nextId < INT32_MAX); - -#define EXTRA_HEIGHT 200 - BaseNPC *npc = nullptr; - int id = NPCManager::nextId++; - if (team == 2) { - npc = new Mob(plr->x, plr->y, plr->z + EXTRA_HEIGHT, plr->instanceID, type, NPCManager::NPCData[type], id); - MobManager::Mobs[npc->appearanceData.iNPC_ID] = (Mob*)npc; - - // re-enable respawning - ((Mob*)npc)->summoned = false; - } else { - npc = new BaseNPC(plr->x, plr->y, plr->z + EXTRA_HEIGHT, 0, plr->instanceID, type, id); - } + BaseNPC *npc = NPCManager::summonNPC(plr->x, plr->y, plr->z, plr->instanceID, type, true); + // update angle npc->appearanceData.iAngle = (plr->angle + 180) % 360; - NPCManager::NPCs[npc->appearanceData.iNPC_ID] = npc; - NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, plr->x, plr->y, plr->z, plr->instanceID, npc->appearanceData.iAngle); // if we're in a lair, we need to spawn the NPC in both the private instance and the template if (PLAYERID(plr->instanceID) != 0) { - id = NPCManager::nextId++; - - if (team == 2) { - npc = new Mob(plr->x, plr->y, plr->z + EXTRA_HEIGHT, MAPNUM(plr->instanceID), type, NPCManager::NPCData[type], id); - - MobManager::Mobs[npc->appearanceData.iNPC_ID] = (Mob*)npc; - - ((Mob*)npc)->summoned = false; - } else { - npc = new BaseNPC(plr->x, plr->y, plr->z + EXTRA_HEIGHT, 0, MAPNUM(plr->instanceID), type, id); - } + npc = NPCManager::summonNPC(plr->x, plr->y, plr->z, plr->instanceID, type, true, true); npc->appearanceData.iAngle = (plr->angle + 180) % 360; - NPCManager::NPCs[npc->appearanceData.iNPC_ID] = npc; - NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, plr->x, plr->y, plr->z, npc->instanceID, npc->appearanceData.iAngle); } @@ -578,15 +550,10 @@ void summonGroupCommand(std::string full, std::vector& args, CNSock for (int i = 0; i < count; i++) { int team = NPCManager::NPCData[type]["m_iTeam"]; - assert(NPCManager::nextId < INT32_MAX); - -#define EXTRA_HEIGHT 200 - BaseNPC *npc = nullptr; - int id = NPCManager::nextId++; - int x = plr->x; int y = plr->y; int z = plr->z; + if (i > 0) { int angle = 360.0f / (count-1) * (i-1); if (count == 3) @@ -599,11 +566,23 @@ void summonGroupCommand(std::string full, std::vector& args, CNSock z = plr->z; } - if (team == 2) { - npc = new Mob(x, y, z + EXTRA_HEIGHT, plr->instanceID, type, NPCManager::NPCData[type], id); - MobManager::Mobs[npc->appearanceData.iNPC_ID] = (Mob*)npc; + BaseNPC *npc = NPCManager::summonNPC(x, y, z, plr->instanceID, type, wCommand); + if (team == 2 && i > 0) { + leadNpc->groupMember[i-1] = npc->appearanceData.iNPC_ID; + Mob* mob = MobManager::Mobs[npc->appearanceData.iNPC_ID]; + mob->groupLeader = leadNpc->appearanceData.iNPC_ID; + mob->offsetX = x - plr->x; + mob->offsetY = y - plr->y; + } - if (i > 0) { + npc->appearanceData.iAngle = (plr->angle + 180) % 360; + NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, x, y, z, plr->instanceID, npc->appearanceData.iAngle); + + // if we're in a lair, we need to spawn the NPC in both the private instance and the template + if (PLAYERID(plr->instanceID) != 0) { + npc = NPCManager::summonNPC(plr->x, plr->y, plr->z, plr->instanceID, type, wCommand, true); + + if (team == 2 && i > 0) { leadNpc->groupMember[i-1] = npc->appearanceData.iNPC_ID; Mob* mob = MobManager::Mobs[npc->appearanceData.iNPC_ID]; mob->groupLeader = leadNpc->appearanceData.iNPC_ID; @@ -611,43 +590,7 @@ void summonGroupCommand(std::string full, std::vector& args, CNSock mob->offsetY = y - plr->y; } - // re-enable respawning - if (wCommand) - ((Mob*)npc)->summoned = false; - } else { - npc = new BaseNPC(x, y, z + EXTRA_HEIGHT, 0, plr->instanceID, type, id); - } - - npc->appearanceData.iAngle = (plr->angle + 180) % 360; - NPCManager::NPCs[npc->appearanceData.iNPC_ID] = npc; - - NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, x, y, z, plr->instanceID, npc->appearanceData.iAngle); - - // if we're in a lair, we need to spawn the NPC in both the private instance and the template - if (PLAYERID(plr->instanceID) != 0) { - id = NPCManager::nextId++; - - if (team == 2) { - npc = new Mob(x, y, z + EXTRA_HEIGHT, MAPNUM(plr->instanceID), type, NPCManager::NPCData[type], id); - - MobManager::Mobs[npc->appearanceData.iNPC_ID] = (Mob*)npc; - - if (i > 0) { - leadNpc->groupMember[i-1] = npc->appearanceData.iNPC_ID; - Mob* mob = MobManager::Mobs[npc->appearanceData.iNPC_ID]; - mob->groupLeader = leadNpc->appearanceData.iNPC_ID; - mob->offsetX = x - plr->x; - mob->offsetY = y - plr->y; - } - if (wCommand) - ((Mob*)npc)->summoned = false; - } else { - npc = new BaseNPC(x, y, z + EXTRA_HEIGHT, 0, MAPNUM(plr->instanceID), type, id); - } - npc->appearanceData.iAngle = (plr->angle + 180) % 360; - NPCManager::NPCs[npc->appearanceData.iNPC_ID] = npc; - NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, x, y, z, plr->instanceID, npc->appearanceData.iAngle); } diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index eddd5f5..f7961b6 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -446,6 +446,30 @@ void NPCManager::npcUnsummonHandler(CNSocket* sock, CNPacketData* data) { NPCManager::destroyNPC(req->iNPC_ID); } +// type must already be checked and updateNPCPosition() must be called on the result +BaseNPC *NPCManager::summonNPC(int x, int y, int z, uint64_t instance, int type, bool respawn, bool baseInstance) { + uint64_t inst = baseInstance ? MAPNUM(instance) : instance; +#define EXTRA_HEIGHT 0 + + assert(nextId < INT32_MAX); + int id = nextId++; + int team = NPCData[type]["m_iTeam"]; + BaseNPC *npc = nullptr; + + if (team == 2) { + npc = new Mob(x, y, z + EXTRA_HEIGHT, inst, type, NPCData[type], id); + MobManager::Mobs[id] = (Mob*)npc; + + // re-enable respawning, if desired + ((Mob*)npc)->summoned = !respawn; + } else + npc = new BaseNPC(x, y, z + EXTRA_HEIGHT, 0, inst, type, id); + + NPCs[id] = npc; + + return npc; +} + void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_NPC_SUMMON)) return; // malformed packet @@ -457,19 +481,9 @@ void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) { if (plr->accountLevel > 30 || req->iNPCType >= 3314 || req->iNPCCnt > 100) return; - int team = NPCData[req->iNPCType]["m_iTeam"]; - for (int i = 0; i < req->iNPCCnt; i++) { - assert(nextId < INT32_MAX); - int id = nextId++; - - if (team == 2) { - NPCs[id] = new Mob(plr->x, plr->y, plr->z, plr->instanceID, req->iNPCType, NPCData[req->iNPCType], id); - MobManager::Mobs[id] = (Mob*)NPCs[id]; - } else - NPCs[id] = new BaseNPC(plr->x, plr->y, plr->z, 0, plr->instanceID, req->iNPCType, id); - - updateNPCPosition(id, plr->x, plr->y, plr->z, plr->instanceID, 0); + BaseNPC *npc = summonNPC(plr->x, plr->y, plr->z, plr->instanceID, req->iNPCType); + updateNPCPosition(npc->appearanceData.iNPC_ID, plr->x, plr->y, plr->z, plr->instanceID, 0); } } diff --git a/src/NPCManager.hpp b/src/NPCManager.hpp index 7aa22ed..95ed318 100644 --- a/src/NPCManager.hpp +++ b/src/NPCManager.hpp @@ -67,6 +67,7 @@ namespace NPCManager { void npcCombineItems(CNSocket* sock, CNPacketData* data); void handleWarp(CNSocket* sock, int32_t warpId); + BaseNPC *summonNPC(int x, int y, int z, uint64_t instance, int type, bool respawn=false, bool baseInstance=false); BaseNPC* getNearestNPC(std::set* chunks, int X, int Y, int Z); diff --git a/suppr.txt b/suppr.txt index 2bad37e..ede1afc 100644 --- a/suppr.txt +++ b/suppr.txt @@ -1,9 +1,8 @@ leak:TableData::init leak:NPCManager::updateNPCPosition -leak:NPCManager::npcSummonHandler +leak:NPCManager::summonNPC leak:NanoManager::doBuff leak:NanoManager::doDebuff leak:NanoManager::doDamageNDebuff -leak:summonWCommand leak:TableData::loadGruntwork leak:nlohmann::basic_json