[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
This commit is contained in:
Akkadius 2017-03-28 02:30:06 -05:00
parent 4b6ce1c19e
commit bf45a5a44f
7 changed files with 86 additions and 73 deletions

View File

@ -1,5 +1,9 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 03/27/2017 ==
Akkadius: [Performance] Reworked how client to NPC aggro checks are made 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 - Before when reverse aggro checks were done (client to NPC), checks would happen every 750 millseconds where a client would

View File

@ -54,7 +54,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
return; return;
} }
AA_SwarmPet pet; SwarmPet_Struct pet;
pet.count = 1; pet.count = 1;
pet.duration = 1; pet.duration = 1;
@ -114,41 +114,43 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
memcpy(npc_dup, made_npc, sizeof(NPCType)); 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 (npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); FlyMode3);
if (followme) if (followme)
npca->SetFollowID(GetID()); swarm_pet_npc->SetFollowID(GetID());
if(!npca->GetSwarmInfo()){ if (!swarm_pet_npc->GetSwarmInfo()) {
auto nSI = new AA_SwarmPetInfo; auto nSI = new SwarmPet;
npca->SetSwarmInfo(nSI); swarm_pet_npc->SetSwarmInfo(nSI);
npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration * 1000);
} }
else { else {
npca->GetSwarmInfo()->duration->Start(pet_duration*1000); swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration * 1000);
} }
swarm_pet_npc->StartSwarmTimer(pet_duration * 1000);
//removing this prevents the pet from attacking //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" //give the pets somebody to "love"
if (targ != nullptr) { if (targ != nullptr) {
npca->AddToHateList(targ, 1000, 1000); swarm_pet_npc->AddToHateList(targ, 1000, 1000);
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
npca->GetSwarmInfo()->target = targ->GetID(); swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
else 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 //we allocated a new NPC type object, give the NPC ownership of that memory
if (npc_dup != nullptr) 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--; summon_count--;
} }
@ -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) { 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.count = 1;
pet.duration = 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)); 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 (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); FlyMode3);
if (followme) if (followme)
npca->SetFollowID(GetID()); swarm_pet_npc->SetFollowID(GetID());
if(!npca->GetSwarmInfo()){ if(!swarm_pet_npc->GetSwarmInfo()){
auto nSI = new AA_SwarmPetInfo; auto nSI = new SwarmPet;
npca->SetSwarmInfo(nSI); swarm_pet_npc->SetSwarmInfo(nSI);
npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration*1000);
} }
else { else {
npca->GetSwarmInfo()->duration->Start(pet_duration*1000); swarm_pet_npc->GetSwarmInfo()->duration->Start(pet_duration*1000);
} }
swarm_pet_npc->StartSwarmTimer(pet_duration * 1000);
//removing this prevents the pet from attacking //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" //give the pets somebody to "love"
if(targ != nullptr){ if(targ != nullptr){
npca->AddToHateList(targ, 1000, 1000); swarm_pet_npc->AddToHateList(targ, 1000, 1000);
if (RuleB(Spells, SwarmPetTargetLock) || sticktarg) if (RuleB(Spells, SwarmPetTargetLock) || sticktarg)
npca->GetSwarmInfo()->target = targ->GetID(); swarm_pet_npc->GetSwarmInfo()->target = targ->GetID();
else 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 //we allocated a new NPC type object, give the NPC ownership of that memory
if(npc_dup != nullptr) 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--; 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); auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3);
if(!npca->GetSwarmInfo()){ if(!npca->GetSwarmInfo()){
auto nSI = new AA_SwarmPetInfo; auto nSI = new SwarmPet;
npca->SetSwarmInfo(nSI); npca->SetSwarmInfo(nSI);
npca->GetSwarmInfo()->duration = new Timer(duration*1000); npca->GetSwarmInfo()->duration = new Timer(duration*1000);
} }
@ -793,21 +797,21 @@ void Client::RefundAA() {
SendAlternateAdvancementStats(); SendAlternateAdvancementStats();
} }
AA_SwarmPetInfo::AA_SwarmPetInfo() SwarmPet::SwarmPet()
{ {
target = 0; target = 0;
owner_id = 0; owner_id = 0;
duration = nullptr; duration = nullptr;
} }
AA_SwarmPetInfo::~AA_SwarmPetInfo() SwarmPet::~SwarmPet()
{ {
target = 0; target = 0;
owner_id = 0; owner_id = 0;
safe_delete(duration); safe_delete(duration);
} }
Mob *AA_SwarmPetInfo::GetOwner() Mob *SwarmPet::GetOwner()
{ {
return entity_list.GetMobID(owner_id); return entity_list.GetMobID(owner_id);
} }

View File

@ -1511,7 +1511,7 @@ typedef enum { //AA IDs
} aaID; } aaID;
//Structure representing the database's swarm pet configs //Structure representing the database's swarm pet configs
struct AA_SwarmPet { struct SwarmPet_Struct {
uint8 count; //number to summon uint8 count; //number to summon
uint32 npc_id; //id from npc_types to represent it. uint32 npc_id; //id from npc_types to represent it.
uint16 duration; //how long they last, in seconds uint16 duration; //how long they last, in seconds
@ -1526,10 +1526,10 @@ enum { //values of AA_Action.action
class Timer; class Timer;
class Mob; class Mob;
class AA_SwarmPetInfo { class SwarmPet {
public: public:
AA_SwarmPetInfo(); SwarmPet();
~AA_SwarmPetInfo(); ~SwarmPet();
Mob * GetOwner(); Mob * GetOwner();
Timer *duration; Timer *duration;
uint32 target; //the target ID uint32 target; //the target ID

View File

@ -6356,7 +6356,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
return; return;
} }
AA_SwarmPet pet; SwarmPet_Struct pet;
pet.count = pet_count; pet.count = pet_count;
pet.duration = pet_duration; pet.duration = pet_duration;
pet.npc_id = record.npc_type; 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)); 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 (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
0, 0,
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f), GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
FlyMode3); FlyMode3);
if(!npca->GetSwarmInfo()){ if(!swarm_pet_npc->GetSwarmInfo()){
auto nSI = new AA_SwarmPetInfo; auto nSI = new SwarmPet;
npca->SetSwarmInfo(nSI); swarm_pet_npc->SetSwarmInfo(nSI);
npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); swarm_pet_npc->GetSwarmInfo()->duration = new Timer(pet_duration*1000);
} }
else{ 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 // 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)); target->AddToHateList(swarm_pet_npc, (target->GetHateAmount(this) + 100), (target->GetDamageAmount(this) + 100));
npca->AddToHateList(target, 1000, 1000); swarm_pet_npc->AddToHateList(target, 1000, 1000);
npca->GetSwarmInfo()->target = target->GetID(); swarm_pet_npc->GetSwarmInfo()->target = target->GetID();
//we allocated a new NPC type object, give the NPC ownership of that memory //we allocated a new NPC type object, give the NPC ownership of that memory
if(npc_dup != nullptr) 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--; summon_count--;
} }
} }

View File

@ -2557,6 +2557,7 @@ void NPC::ClearLastName()
void NPC::DepopSwarmPets() void NPC::DepopSwarmPets()
{ {
if (GetSwarmInfo()) { if (GetSwarmInfo()) {
if (GetSwarmInfo()->duration->Check(false)){ if (GetSwarmInfo()->duration->Check(false)){
Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id); Mob* owner = entity_list.GetMobID(GetSwarmInfo()->owner_id);

View File

@ -85,7 +85,7 @@ struct AISpellsVar_Struct {
uint8 idle_beneficial_chance; uint8 idle_beneficial_chance;
}; };
class AA_SwarmPetInfo; class SwarmPet;
class Client; class Client;
class Group; class Group;
class Raid; class Raid;
@ -330,8 +330,8 @@ public:
QGlobalCache *GetQGlobals() { return qGlobals; } QGlobalCache *GetQGlobals() { return qGlobals; }
QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; } QGlobalCache *CreateQGlobals() { qGlobals = new QGlobalCache(); return qGlobals; }
AA_SwarmPetInfo *GetSwarmInfo() { return (swarmInfoPtr); } SwarmPet *GetSwarmInfo() { return (swarmInfoPtr); }
void SetSwarmInfo(AA_SwarmPetInfo *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; } void SetSwarmInfo(SwarmPet *mSwarmInfo) { swarmInfoPtr = mSwarmInfo; }
int32 GetAccuracyRating() const { return (accuracy_rating); } int32 GetAccuracyRating() const { return (accuracy_rating); }
void SetAccuracyRating(int32 d) { accuracy_rating = d;} 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 sec_melee_type; //Sets the Secondary Weapon attack message and animation
uint8 ranged_type; //Sets the Ranged Weapon attack message and animation uint8 ranged_type; //Sets the Ranged Weapon attack message and animation
AA_SwarmPetInfo *swarmInfoPtr; SwarmPet *swarmInfoPtr;
bool ldon_trapped; bool ldon_trapped;
uint8 ldon_trap_type; uint8 ldon_trap_type;

View File

@ -131,8 +131,10 @@ void Mob::SpellProcess()
void NPC::SpellProcess() void NPC::SpellProcess()
{ {
Mob::SpellProcess(); Mob::SpellProcess();
if (swarm_timer.Check()) {
DepopSwarmPets(); DepopSwarmPets();
} }
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// functions related to begin/finish casting, fizzling etc // functions related to begin/finish casting, fizzling etc