From 532ab1c7f8653d1a2e48aa1f1f8a9ba1041d4bb7 Mon Sep 17 00:00:00 2001 From: Treeston Date: Wed, 3 Jan 2018 20:04:19 +0100 Subject: Core: Combat/threat system rewrite (PR #19930) - PvE combat is now always mutual. UNIT_FLAG_IN_COMBAT is backed by actual references to the units we're in combat with. - PvP combat is now also tracked, and almost always mutual; spells like Vanish and Feign Death can break this rule. That means we can easily determine a list of players we're fighting. - By extension, IsInCombatWith now has sensible behavior when invoked on nonplayers. - Threat and combat systems are no longer the same. - They still have an enforced relationship (threat implies combat - clearing combat clears threat)... - ...but we can have combat without threat. A creature (with threat list) isn't considered to be engaged until it has an entry on its threat list... - ...which means we can now faithfully replicate retail engage behavior. Combat on projectile launch - engagement start on projectile impact. Yay for progress! - AI method refactor, as already ported in 6113b9d - `JustEngagedWith`, `JustEnteredCombat` and `JustExitedCombat`. - Vehicle threat is now properly pooled on the main vehicle body (fixes #16542). - Various edge case bug fixes for threat redirects (Misdirection "cancelling" Vigilance and similar). - Target re-selection is now significantly faster. - Fixed a ton of other smaller edge case bugs, probably. Closes #7951 and #19998. --- src/server/scripts/Commands/cs_debug.cpp | 97 ++++++++++++++++++++++++-------- src/server/scripts/Commands/cs_misc.cpp | 1 - 2 files changed, 73 insertions(+), 25 deletions(-) (limited to 'src/server/scripts/Commands') diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 9cb8e554372..54f80e6abb4 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -842,23 +842,73 @@ public: static bool HandleDebugThreatListCommand(ChatHandler* handler, char const* /*args*/) { - Creature* target = handler->getSelectedCreature(); - if (!target || target->IsTotem() || target->IsPet()) - return false; + Unit* target = handler->getSelectedUnit(); + if (!target) + target = handler->GetSession()->GetPlayer(); + + ThreatManager& mgr = target->GetThreatManager(); + if (!target->IsAlive()) + { + handler->PSendSysMessage("%s (guid %u) is not alive.", target->GetName().c_str(), target->GetGUID().GetCounter()); + return true; + } + if (!target->CanHaveThreatList()) + handler->PSendSysMessage("%s (guid %u) cannot have a threat list.", target->GetName().c_str(), target->GetGUID().GetCounter()); - ThreatContainer::StorageType const& threatList = target->GetThreatManager().getThreatList(); - ThreatContainer::StorageType::const_iterator itr; uint32 count = 0; - handler->PSendSysMessage("Threat list of %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); - for (itr = threatList.begin(); itr != threatList.end(); ++itr) + auto const& threatenedByMe = target->GetThreatManager().GetThreatenedByMeList(); + if (threatenedByMe.empty()) + handler->PSendSysMessage("%s (guid %u) does not threaten any units.", target->GetName().c_str(), target->GetGUID().GetCounter()); + else { - Unit* unit = (*itr)->getTarget(); - if (!unit) - continue; - ++count; - handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), (*itr)->getThreat()); + handler->PSendSysMessage("List of units threatened by %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); + for (auto const& pair : threatenedByMe) + { + Unit* unit = pair.second->GetOwner(); + handler->PSendSysMessage(" %u. %s (current guid %u, DB guid %u) - threat %f", ++count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0, pair.second->GetThreat()); + } + handler->SendSysMessage("End of threatened-by-me list."); } - handler->SendSysMessage("End of threat list."); + + if (!mgr.CanHaveThreatList()) + return true; + if (mgr.IsEngaged()) + { + count = 0; + handler->PSendSysMessage("Threat list of %s (guid %u, DB GUID %u)", target->GetName().c_str(), target->GetGUID().GetCounter(), target->GetTypeId() == TYPEID_UNIT ? target->ToCreature()->GetSpawnId() : 0); + for (ThreatReference const* ref : mgr.GetSortedThreatList()) + { + Unit* unit = ref->GetVictim(); + char const* onlineStr; + switch (ref->GetOnlineState()) + { + case ThreatReference::ONLINE_STATE_SUPPRESSED: + onlineStr = " [SUPPRESSED]"; + break; + case ThreatReference::ONLINE_STATE_OFFLINE: + onlineStr = " [OFFLINE]"; + break; + default: + onlineStr = ""; + } + char const* tauntStr; + switch (ref->GetTauntState()) + { + case ThreatReference::TAUNT_STATE_TAUNT: + tauntStr = " [TAUNT]"; + break; + case ThreatReference::TAUNT_STATE_DETAUNT: + tauntStr = " [DETAUNT]"; + break; + default: + tauntStr = ""; + } + handler->PSendSysMessage(" %u. %s (guid %u) - threat %f%s%s", ++count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), ref->GetThreat(), tauntStr, onlineStr); + } + handler->SendSysMessage("End of threat list."); + } + else + handler->PSendSysMessage("%s (guid %u, DB GUID %u) is not currently engaged.", target->GetName().c_str(), target->GetGUID().GetCounter(), target->GetTypeId() == TYPEID_UNIT ? target->ToCreature()->GetSpawnId() : 0); return true; } @@ -867,19 +917,18 @@ public: Unit* target = handler->getSelectedUnit(); if (!target) target = handler->GetSession()->GetPlayer(); - HostileReference* ref = target->getHostileRefManager().getFirst(); - uint32 count = 0; - handler->PSendSysMessage("Hostil reference list of %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); - while (ref) + + handler->PSendSysMessage("Combat refs: (Combat state: %d | Manager state: %d)", target->IsInCombat(), target->GetCombatManager().HasCombat()); + for (auto const& ref : target->GetCombatManager().GetPvPCombatRefs()) { - if (Unit* unit = ref->GetSource()->GetOwner()) - { - ++count; - handler->PSendSysMessage(" %u. %s (current guid %u, DB guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0, ref->getThreat()); - } - ref = ref->next(); + Unit* unit = ref.second->GetOther(target); + handler->PSendSysMessage("[PvP] %s (DBGUID %u)", unit->GetName().c_str(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0); + } + for (auto const& ref : target->GetCombatManager().GetPvECombatRefs()) + { + Unit* unit = ref.second->GetOther(target); + handler->PSendSysMessage("[PvE] %s (DBGUID %u)", unit->GetName().c_str(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0); } - handler->SendSysMessage("End of hostil reference list."); return true; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index aecef71a961..cc28b2da8ab 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2420,7 +2420,6 @@ public: return false; target->CombatStop(); - target->getHostileRefManager().deleteReferences(); return true; } -- cgit v1.2.3