From 220d8497dd7f853b4813906f91a1d83c8b36f963 Mon Sep 17 00:00:00 2001 From: mmcgarvey Date: Sun, 2 Jan 2022 22:07:57 -0500 Subject: [PATCH] [XTarget] Disallow Corpses in XTarget Auto Slots (#1881) * [XTarget] Disallow Corpses in XTarget Auto Slots Why: There exists an odd state where corpses will fill up your XTarget window. This is reproducable using a combination of a pet to kill a mob and timely feign death to wipe the owner's aggro. What: Added an IsCorpse check to IsXTarget. Added a block to mark corpse XTargets as dirty to ProcessXTargetAutoHaters * fixup! [XTarget] Disallow Corpses in XTarget Auto Slots * fixup! [XTarget] Disallow Corpses in XTarget Auto Slots * [XTarget] Disallow Corpses Code Cleanup Added some safety, performance, and code readability changes per PR request. --- zone/attack.cpp | 5 +++++ zone/client.cpp | 16 +++++++++++++--- zone/mob.cpp | 4 ++++ zone/mob.h | 2 ++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index ff9f85264..173574641 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1799,6 +1799,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQ::skills::Skill entity_list.RemoveFromTargets(this, true); hate_list.RemoveEntFromHateList(this); RemoveAutoXTargets(); + ProcessXTargetAutoHaters(); //remove ourself from all proximities ClearAllProximities(); @@ -2569,6 +2570,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy } entity_list.RemoveFromAutoXTargets(this); + + if (killer->GetUltimateOwner() && killer->GetUltimateOwner()->IsClient()) { + killer->GetUltimateOwner()->CastToClient()->ProcessXTargetAutoHaters(); + } uint16 emoteid = this->GetEmoteID(); auto corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, level > 54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) diff --git a/zone/client.cpp b/zone/client.cpp index 62ffafd17..2bf75bf7f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7172,7 +7172,7 @@ void Client::OpenLFGuildWindow() bool Client::IsXTarget(const Mob *m) const { - if(!XTargettingAvailable() || !m || (m->GetID() == 0)) + if(!XTargettingAvailable() || !m || !m->IsValidXTarget()) return false; for(int i = 0; i < GetMaxXTargets(); ++i) @@ -7215,10 +7215,10 @@ void Client::UpdateClientXTarget(Client *c) // IT IS NOT SAFE TO CALL THIS IF IT'S NOT INITIAL AGGRO void Client::AddAutoXTarget(Mob *m, bool send) { - m_activeautohatermgr->increment_count(m); - if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m)) return; + + m_activeautohatermgr->increment_count(m); for(int i = 0; i < GetMaxXTargets(); ++i) { @@ -7428,8 +7428,17 @@ void Client::ProcessXTargetAutoHaters() if (XTargets[i].Type != Auto) continue; + auto *mob = entity_list.GetMob(XTargets[i].ID); + if (XTargets[i].ID != 0 && !GetXTargetAutoMgr()->contains_mob(XTargets[i].ID)) { XTargets[i].ID = 0; + XTargets[i].Name[0] = 0; + XTargets[i].dirty = true; + } + + if (XTargets[i].ID != 0 && mob && !mob->IsValidXTarget()) { + XTargets[i].ID = 0; + XTargets[i].Name[0] = 0; XTargets[i].dirty = true; } @@ -7465,6 +7474,7 @@ void Client::ProcessXTargetAutoHaters() break; } } + m_dirtyautohaters = false; SendXTargetUpdates(); } diff --git a/zone/mob.cpp b/zone/mob.cpp index f1aebb7f2..48893ae6b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -6649,3 +6649,7 @@ void Mob::SetBucket(std::string bucket_name, std::string bucket_value, std::stri std::string full_bucket_name = fmt::format("{}-{}", GetBucketKey(), bucket_name); DataBucket::SetData(full_bucket_name, bucket_value, expiration); } + +bool Mob::IsValidXTarget() const { + return (GetID() > 0 || !IsCorpse()); +} diff --git a/zone/mob.h b/zone/mob.h index 50ad8af58..dd5c29b70 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1307,6 +1307,8 @@ public: std::string GetBucketRemaining(std::string bucket_name); void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); + bool IsValidXTarget() const; + #ifdef BOTS // Bots HealRotation methods bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }