From 49d0c308e88db272fc31ca9e80ce420c5378faf5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 15:46:16 -0400 Subject: [PATCH] Limit aura spawns This is probably not the best performance, but it's the only solution that is easy to implement. --- zone/aura.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- zone/aura.h | 7 +++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 62441415e..0812a8109 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -538,6 +538,32 @@ void Aura::ProcessExitTrap(Mob *owner) Shout("Stub 6"); } +// this is less than ideal, but other solutions are a bit all over the place +// and hard to reason about +void Aura::ProcessSpawns() +{ + const auto &clients = entity_list.GetClientList(); + for (auto &e : clients) { + auto c = e.second; + bool spawned = spawned_for.find(c->GetID()) != spawned_for.end(); + if (ShouldISpawnFor(c)) { + if (!spawned) { + EQApplicationPacket app; + CreateSpawnPacket(&app, this); + c->QueuePacket(&app); + SendArmorAppearance(c); + spawned_for.insert(c->GetID()); + } + } else if (spawned) { + EQApplicationPacket app; + CreateDespawnPacket(&app, false); + c->QueuePacket(&app); + spawned_for.erase(c->GetID()); + } + } + return; +} + bool Aura::Process() { // Aura::Depop clears buffs @@ -564,6 +590,8 @@ bool Aura::Process() if (!process_timer.Check()) return true; + ProcessSpawns(); // bit of a hack + if (process_func) process_func(*this, owner); @@ -571,6 +599,60 @@ bool Aura::Process() return true; } +bool Aura::ShouldISpawnFor(Client *c) +{ + if (spawn_type == AuraSpawns::Noone) + return false; + + if (spawn_type == AuraSpawns::Everyone) + return true; + + // hey, it's our owner! + if (c->GetID() == m_owner) + return true; + + // so this one is a bit trickier + auto owner = GetOwner(); + if (owner == nullptr) + return false; // hmm + + owner = owner->GetOwnerOrSelf(); // pet auras we need the pet's owner + if (owner == nullptr) // shouldn't really be needed + return false; + + // gotta check again for pet aura case -.- + if (owner == c) + return true; + + if (owner->IsRaidGrouped() && owner->IsClient()) { + auto raid = owner->GetRaid(); + if (raid == nullptr) + return false; // hmm + auto group_id = raid->GetGroup(owner->CastToClient()); + if (group_id == 0xFFFFFFFF) // owner handled above, and they're in a raid and groupless + return false; + + auto idx = raid->GetPlayerIndex(c); + if (idx == 0xFFFFFFFF) // they're not in our raid! + return false; + + if (raid->members[idx].GroupNumber != group_id) // in our raid, but not our group + return false; + + return true; // we got here so we know that 1 they're in our raid and 2 they're in our group! + } else if (owner->IsGrouped()) { + auto group = owner->GetGroup(); + if (group == nullptr) + return false; // hmm + + // easy, in our group + return group->IsGroupMember(c); + } + + // our owner is not raided or grouped, and they're handled above so we don't spawn! + return false; +} + void Aura::Depop(bool skip_strip) { // NEC trap casts a dot, so we need some way to not strip :P @@ -642,7 +724,7 @@ void Mob::MakeAura(uint16 spell_id) auto npc = new Aura(npc_type, this, record); npc->SetAuraID(spell_id); - entity_list.AddNPC(npc, true, true); + entity_list.AddNPC(npc, false); if (trap) AddTrap(npc, record); diff --git a/zone/aura.h b/zone/aura.h index da5f610c9..7156f7531 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -56,12 +56,18 @@ public: void ProcessTotem(Mob *owner); void ProcessEnterTrap(Mob *owner); void ProcessExitTrap(Mob *owner); + void ProcessSpawns(); // we only save auras that follow you, and player casted inline bool AuraZones() { return movement_type == AuraMovement::Follow && aura_id > -1; } inline int GetSpellID() { return spell_id; } inline int GetAuraID() { return aura_id; } inline void SetAuraID(int in) { aura_id = in; } + + bool ShouldISpawnFor(Client *c); + // so when we join a group, we need to spawn not already spawned auras + // This is only possible when spawn type is GroupMembers + inline bool JoinGroupSpawnCheck() { return spawn_type == AuraSpawns::GroupMembers; } private: int m_owner; int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell @@ -77,6 +83,7 @@ private: std::function process_func; std::set casted_on; // we keep track of the other entities we've casted on + std::set spawned_for; }; #endif /* !AURA_H */