diff --git a/changelog.txt b/changelog.txt index 841cc96b1..caae41f03 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/28/2017 == +Akkadius: [Performance] Fixed a large overhead issue where every single NPC in a zone was checking to depop themselves + as a swarm pet every 3ms regardless of being a swarm pet or not. Swarm pets now check to depop only when their timer is up + == 03/27/2017 == Akkadius: [Performance] Reworked how client to NPC aggro checks are made - Before when reverse aggro checks were done (client to NPC), checks would happen every 750 millseconds where a client would diff --git a/zone/aa.cpp b/zone/aa.cpp index 3c6f11f6e..e4e5aa4b3 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -47,20 +47,20 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u return; PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) + if (!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) { Log.Out(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); return; } - AA_SwarmPet pet; + SwarmPet_Struct pet; pet.count = 1; pet.duration = 1; - for(int x = 0; x < MAX_SWARM_PETS; x++) + for (int x = 0; x < MAX_SWARM_PETS; x++) { - if(spells[spell_id].effectid[x] == SE_TemporaryPets) + if (spells[spell_id].effectid[x] == SE_TemporaryPets) { pet.count = spells[spell_id].base[x]; pet.duration = spells[spell_id].max[x]; @@ -74,14 +74,14 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u NPCType *made_npc = nullptr; const NPCType *npc_type = database.LoadNPCTypesData(pet.npc_id); - if(npc_type == nullptr) { + if (npc_type == nullptr) { //log write Log.Out(Logs::General, Logs::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); - Message(0,"Unable to find pet!"); + Message(0, "Unable to find pet!"); return; } - if(name_override != nullptr) { + if (name_override != nullptr) { //we have to make a custom NPC type for this name change made_npc = new NPCType; memcpy(made_npc, npc_type, sizeof(NPCType)); @@ -92,7 +92,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u int summon_count = 0; summon_count = pet.count; - if(summon_count > MAX_SWARM_PETS) + if (summon_count > MAX_SWARM_PETS) summon_count = MAX_SWARM_PETS; static const glm::vec2 swarmPetLocations[MAX_SWARM_PETS] = { @@ -101,59 +101,61 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u glm::vec2(8, 8), glm::vec2(-8, 8), glm::vec2(8, -8), glm::vec2(-8, -8) }; - while(summon_count > 0) { + while (summon_count > 0) { int pet_duration = pet.duration; - if(duration_override > 0) + if (duration_override > 0) pet_duration = duration_override; //this is a little messy, but the only way to do it right //it would be possible to optimize out this copy for the last pet, but oh well NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { + if (made_npc != nullptr) { npc_dup = new NPCType; memcpy(npc_dup, made_npc, sizeof(NPCType)); } - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), - FlyMode3); + NPC* swarm_pet_npc = new NPC( + (npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer + 0, + GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), + FlyMode3); if (followme) - npca->SetFollowID(GetID()); + swarm_pet_npc->SetFollowID(GetID()); - if(!npca->GetSwarmInfo()){ - auto nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + if (!swarm_pet_npc->GetSwarmInfo()) { + auto nSI = new SwarmPet; + swarm_pet_npc->SetSwarmInfo(nSI); + swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration * 1000); } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + else { + swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration * 1000); } + swarm_pet_npc->StartSwarmTimer(pet_duration * 1000); + //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); + swarm_pet_npc->GetSwarmInfo()->owner_id = GetID(); //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); + if (targ != nullptr) { + swarm_pet_npc->AddToHateList(targ, 1000, 1000); if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) - npca->GetSwarmInfo()->target = targ->GetID(); + swarm_pet_npc->GetSwarmInfo()->target = targ->GetID(); else - npca->GetSwarmInfo()->target = 0; + swarm_pet_npc->GetSwarmInfo()->target = 0; } //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); + if (npc_dup != nullptr) + swarm_pet_npc->GiveNPCTypeData(npc_dup); - entity_list.AddNPC(npca, true, true); + entity_list.AddNPC(swarm_pet_npc, true, true); summon_count--; } //the target of these swarm pets will take offense to being cast on... - if(targ != nullptr) + if (targ != nullptr) targ->AddToHateList(this, 1, 0); // The other pointers we make are handled elsewhere. @@ -162,7 +164,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) { - AA_SwarmPet pet; + SwarmPet_Struct pet; pet.count = 1; pet.duration = 1; @@ -211,42 +213,44 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid memcpy(npc_dup, made_npc, sizeof(NPCType)); } - NPC* npca = new NPC( + NPC* swarm_pet_npc = new NPC( (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer 0, GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), FlyMode3); if (followme) - npca->SetFollowID(GetID()); + swarm_pet_npc->SetFollowID(GetID()); - if(!npca->GetSwarmInfo()){ - auto nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + if(!swarm_pet_npc->GetSwarmInfo()){ + auto nSI = new SwarmPet; + swarm_pet_npc->SetSwarmInfo(nSI); + swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration*1000); } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + else { + swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration*1000); } + swarm_pet_npc->StartSwarmTimer(pet_duration * 1000); + //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); + swarm_pet_npc->GetSwarmInfo()->owner_id = GetID(); //give the pets somebody to "love" if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); + swarm_pet_npc->AddToHateList(targ, 1000, 1000); if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) - npca->GetSwarmInfo()->target = targ->GetID(); + swarm_pet_npc->GetSwarmInfo()->target = targ->GetID(); else - npca->GetSwarmInfo()->target = 0; + swarm_pet_npc->GetSwarmInfo()->target = 0; } //we allocated a new NPC type object, give the NPC ownership of that memory if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); + swarm_pet_npc->GiveNPCTypeData(npc_dup); - entity_list.AddNPC(npca, true, true); + entity_list.AddNPC(swarm_pet_npc, true, true); summon_count--; } @@ -404,7 +408,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3); if(!npca->GetSwarmInfo()){ - auto nSI = new AA_SwarmPetInfo; + auto nSI = new SwarmPet; npca->SetSwarmInfo(nSI); npca->GetSwarmInfo()->duration = new Timer(duration*1000); } @@ -793,21 +797,21 @@ void Client::RefundAA() { SendAlternateAdvancementStats(); } -AA_SwarmPetInfo::AA_SwarmPetInfo() +SwarmPet::SwarmPet() { target = 0; owner_id = 0; duration = nullptr; } -AA_SwarmPetInfo::~AA_SwarmPetInfo() +SwarmPet::~SwarmPet() { target = 0; owner_id = 0; safe_delete(duration); } -Mob *AA_SwarmPetInfo::GetOwner() +Mob *SwarmPet::GetOwner() { return entity_list.GetMobID(owner_id); } diff --git a/zone/aa.h b/zone/aa.h index 280f56d53..0ce16a787 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -1511,7 +1511,7 @@ typedef enum { //AA IDs } aaID; //Structure representing the database's swarm pet configs -struct AA_SwarmPet { +struct SwarmPet_Struct { uint8 count; //number to summon uint32 npc_id; //id from npc_types to represent it. uint16 duration; //how long they last, in seconds @@ -1526,10 +1526,10 @@ enum { //values of AA_Action.action class Timer; class Mob; -class AA_SwarmPetInfo { +class SwarmPet { public: - AA_SwarmPetInfo(); - ~AA_SwarmPetInfo(); + SwarmPet(); + ~SwarmPet(); Mob * GetOwner(); Timer *duration; uint32 target; //the target ID diff --git a/zone/client.cpp b/zone/client.cpp index fb9d6a5d9..97abb3e55 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6356,7 +6356,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid return; } - AA_SwarmPet pet; + SwarmPet_Struct pet; pet.count = pet_count; pet.duration = pet_duration; pet.npc_id = record.npc_type; @@ -6431,33 +6431,35 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid memcpy(npc_dup, made_npc, sizeof(NPCType)); } - NPC* npca = new NPC( + NPC* swarm_pet_npc = new NPC( (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer 0, GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), FlyMode3); - if(!npca->GetSwarmInfo()){ - auto nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + if(!swarm_pet_npc->GetSwarmInfo()){ + auto nSI = new SwarmPet; + swarm_pet_npc->SetSwarmInfo(nSI); + swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration*1000); } else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration*1000); } - npca->GetSwarmInfo()->owner_id = GetID(); + swarm_pet_npc->StartSwarmTimer(pet_duration * 1000); + + swarm_pet_npc->GetSwarmInfo()->owner_id = GetID(); // Give the pets alittle more agro than the caster and then agro them on the target - target->AddToHateList(npca, (target->GetHateAmount(this) + 100), (target->GetDamageAmount(this) + 100)); - npca->AddToHateList(target, 1000, 1000); - npca->GetSwarmInfo()->target = target->GetID(); + target->AddToHateList(swarm_pet_npc, (target->GetHateAmount(this) + 100), (target->GetDamageAmount(this) + 100)); + swarm_pet_npc->AddToHateList(target, 1000, 1000); + swarm_pet_npc->GetSwarmInfo()->target = target->GetID(); //we allocated a new NPC type object, give the NPC ownership of that memory if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); + swarm_pet_npc->GiveNPCTypeData(npc_dup); - entity_list.AddNPC(npca); + entity_list.AddNPC(swarm_pet_npc); summon_count--; } } diff --git a/zone/npc.cpp b/zone/npc.cpp index c327db11f..142dc3120 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2557,6 +2557,7 @@ void NPC::ClearLastName() void NPC::DepopSwarmPets() { + if (GetSwarmInfo()) { if (GetSwarmInfo()->duration->Check(false)){ Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id); diff --git a/zone/npc.h b/zone/npc.h index 5dcc7eac9..015128340 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -85,7 +85,7 @@ struct AISpellsVar_Struct { uint8 idle_beneficial_chance; }; -class AA_SwarmPetInfo; +class SwarmPet; class Client; class Group; class Raid; @@ -330,8 +330,8 @@ public: QGlobalCache *GetQGlobals() { return qGlobals; } QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; } - AA_SwarmPetInfo *GetSwarmInfo() { return (swarmInfoPtr); } - void SetSwarmInfo(AA_SwarmPetInfo *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; } + SwarmPet *GetSwarmInfo() { return (swarmInfoPtr); } + void SetSwarmInfo(SwarmPet *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; } int32 GetAccuracyRating() const { return (accuracy_rating); } void SetAccuracyRating(int32 d) { accuracy_rating = d;} @@ -515,7 +515,7 @@ protected: uint8 sec_melee_type; //Sets the Secondary Weapon attack message and animation uint8 ranged_type; //Sets the Ranged Weapon attack message and animation - AA_SwarmPetInfo *swarmInfoPtr; + SwarmPet *swarmInfoPtr; bool ldon_trapped; uint8 ldon_trap_type; diff --git a/zone/spells.cpp b/zone/spells.cpp index e3ec41f30..fface82ce 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -131,7 +131,9 @@ void Mob::SpellProcess() void NPC::SpellProcess() { Mob::SpellProcess(); - DepopSwarmPets(); + if (swarm_timer.Check()) { + DepopSwarmPets(); + } } ///////////////////////////////////////////////////////////////////////////////