Limit aura spawns

This is probably not the best performance, but it's the only solution
that is easy to implement.
This commit is contained in:
Michael Cook (mackal) 2017-07-22 15:46:16 -04:00
parent ceb0fe22f1
commit 49d0c308e8
2 changed files with 90 additions and 1 deletions

View File

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

View File

@ -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<void(Aura &, Mob *)> process_func;
std::set<int> casted_on; // we keep track of the other entities we've casted on
std::set<int> spawned_for;
};
#endif /* !AURA_H */