Moved common NPC summoning logic into a helper function

This commit is contained in:
dongresource 2020-12-15 23:15:39 +01:00
parent 0dd478b9f0
commit 3359ca0c3e
4 changed files with 48 additions and 91 deletions

View File

@ -213,45 +213,17 @@ void summonWCommand(std::string full, std::vector<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& 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);
}

View File

@ -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);
}
}

View File

@ -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<Chunk*>* chunks, int X, int Y, int Z);

View File

@ -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