diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2018-01-03 20:04:19 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-03 20:04:19 +0100 |
| commit | 532ab1c7f8653d1a2e48aa1f1f8a9ba1041d4bb7 (patch) | |
| tree | 81e2f7eb89b3144c14dd488ea6304f6d44d19848 /src/server/scripts/Northrend | |
| parent | 425b181544a21d2246fdf0261ba76a37e2510883 (diff) | |
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.
Diffstat (limited to 'src/server/scripts/Northrend')
10 files changed, 61 insertions, 79 deletions
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index c6cae404478..1d6eed64946 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -41,6 +41,7 @@ enum Spells SPELL_FLAME_SPHERE_DEATH_EFFECT = 55947, SPELL_EMBRACE_OF_THE_VAMPYR = 55959, SPELL_VANISH = 55964, + SPELL_SHADOWSTEP = 55966, NPC_FLAME_SPHERE_1 = 30106, NPC_FLAME_SPHERE_2 = 31686, @@ -77,9 +78,8 @@ enum Events EVENT_CONJURE_FLAME_SPHERES = 1, EVENT_BLOODTHIRST, EVENT_VANISH, - EVENT_JUST_VANISHED, - EVENT_VANISHED, - EVENT_FEEDING, + EVENT_START_FEEDING, + EVENT_DONE_FEEDING, // Flame Sphere EVENT_START_MOVE, @@ -97,6 +97,7 @@ class boss_prince_taldaram : public CreatureScript { me->SetDisableGravity(true); _embraceTakenDamage = 0; + _initialCheckTimer = 3000; } void Reset() override @@ -140,8 +141,30 @@ class boss_prince_taldaram : public CreatureScript void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) - return; + if (_initialCheckTimer) + { + if (_initialCheckTimer <= diff) + { + CheckSpheres(); + _initialCheckTimer = 0; + } + else + _initialCheckTimer -= diff; + } + + if (me->HasAura(SPELL_VANISH)) + { + if (me->GetThreatManager().IsThreatListEmpty(true)) + { + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); + return; + } + } + else + { + if (!UpdateVictim()) + return; + } events.Update(diff); @@ -167,47 +190,29 @@ class boss_prince_taldaram : public CreatureScript break; case EVENT_VANISH: { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - uint32 targets = 0; - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* player = i->GetSource(); - if (player && player->IsAlive()) - ++targets; - } - - if (targets > 2) + if (me->GetThreatManager().GetThreatListSize() > 1) { + if (Unit* embraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + _embraceTargetGUID = embraceTarget->GetGUID(); Talk(SAY_VANISH); DoCast(me, SPELL_VANISH); - me->SetInCombatState(true); // Prevents the boss from resetting events.DelayEvents(500); - events.ScheduleEvent(EVENT_JUST_VANISHED, 500); - if (Unit* embraceTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) - _embraceTargetGUID = embraceTarget->GetGUID(); + events.ScheduleEvent(EVENT_START_FEEDING, 2000); } events.ScheduleEvent(EVENT_VANISH, urand(25000, 35000)); break; } - case EVENT_JUST_VANISHED: + case EVENT_START_FEEDING: + me->RemoveAurasDueToSpell(SPELL_VANISH); if (Unit* embraceTarget = GetEmbraceTarget()) { - me->GetMotionMaster()->Clear(); - me->SetSpeedRate(MOVE_WALK, 2.0f); - me->GetMotionMaster()->MoveChase(embraceTarget); - } - events.ScheduleEvent(EVENT_VANISHED, 1300); - break; - case EVENT_VANISHED: - if (Unit* embraceTarget = GetEmbraceTarget()) + DoCast(embraceTarget, SPELL_SHADOWSTEP); DoCast(embraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); - Talk(SAY_FEED); - me->GetMotionMaster()->Clear(); - me->SetSpeedRate(MOVE_WALK, 1.0f); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - events.ScheduleEvent(EVENT_FEEDING, 20000); + Talk(SAY_FEED); + events.ScheduleEvent(EVENT_DONE_FEEDING, 20000); + } break; - case EVENT_FEEDING: + case EVENT_DONE_FEEDING: _embraceTargetGUID.Clear(); break; default: @@ -289,6 +294,7 @@ class boss_prince_taldaram : public CreatureScript ObjectGuid _flameSphereTargetGUID; ObjectGuid _embraceTargetGUID; uint32 _embraceTakenDamage; + uint32 _initialCheckTimer; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp index 9ba7cce3130..8ce416a5eba 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -163,13 +163,9 @@ public: bool IsInCombatWithPlayer() const { - std::list<HostileReference*> const& refs = me->GetThreatManager().getThreatList(); - for (HostileReference const* hostileRef : refs) - { - if (Unit const* target = hostileRef->getTarget()) - if (target->IsControlledByPlayer()) - return true; - } + for (auto const& pair : me->GetCombatManager().GetPvECombatRefs()) + if (pair.second->GetOther(me)->IsControlledByPlayer()) + return true; return false; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 1c4f444234b..6f77a251f31 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -822,7 +822,7 @@ class npc_anubarak_spike : public CreatureScript DoCast(who, SPELL_MARK); me->SetSpeedRate(MOVE_RUN, 0.5f); // make sure the Spine will really follow the one he should - ResetThreatList(); + me->GetThreatManager().ResetAllThreat(); me->SetInCombatWithZone(); AddThreat(who, 1000000.0f); me->GetMotionMaster()->Clear(true); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 7ea01046763..6bc1bdc9e10 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -673,14 +673,10 @@ struct boss_faction_championsAI : public BossAI Unit* SelectEnemyCaster(bool /*casting*/) { - std::list<HostileReference*> const& tList = me->GetThreatManager().getThreatList(); - std::list<HostileReference*>::const_iterator iter; - for (iter = tList.begin(); iter!=tList.end(); ++iter) - { - Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); - if (target && target->getPowerType() == POWER_MANA) - return target; - } + for (auto const& pair : me->GetCombatManager().GetPvECombatRefs()) + if (Player* player = pair.second->GetOther(me)->ToPlayer()) + if (player->getPowerType() == POWER_MANA) + return player; return nullptr; } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index e87248ddff0..1a78118b7c1 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1342,7 +1342,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript AttackStart(victim); return me->GetVictim() != nullptr; } - else if (me->GetThreatManager().GetThreatListSize() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER)) + else if (me->GetCombatManager().GetPvECombatRefs().size() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER)) { EnterEvadeMode(EVADE_REASON_OTHER); return false; diff --git a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp index 02afc219aa3..4ac7f99e2c2 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_drakkari_colossus.cpp @@ -148,15 +148,12 @@ class boss_drakkari_colossus : public CreatureScript if (me->GetReactState() == REACT_AGGRESSIVE) return; - me->SetReactState(REACT_AGGRESSIVE); me->SetImmuneToPC(false); + me->SetReactState(REACT_AGGRESSIVE); me->RemoveAura(SPELL_FREEZE_ANIM); me->SetInCombatWithZone(); - if (me->GetVictim()) - me->GetMotionMaster()->MoveChase(me->GetVictim(), 0, 0); - break; } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 90c9224669f..f940d67f8c7 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -560,25 +560,15 @@ class npc_green_dragon_combat_trigger : public CreatureScript if (!me->IsInCombat()) return; - // @TODO check out of bounds on all encounter creatures, evade if matched - - std::list<HostileReference*> const& threatList = me->GetThreatManager().getThreatList(); - if (threatList.empty()) - { - EnterEvadeMode(); - return; - } - // check evade every second tick _evadeCheck ^= true; if (!_evadeCheck) return; - // check if there is any player on threatlist, if not - evade - for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) - if (Unit* target = (*itr)->getTarget()) - if (target->GetTypeId() == TYPEID_PLAYER) - return; // found any player, return + // check if there is any player engaged, if not - evade + for (auto const& pair : me->GetCombatManager().GetPvECombatRefs()) + if (pair.second->GetOther(me)->GetTypeId() == TYPEID_PLAYER) + return; EnterEvadeMode(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 777b9a8cf1a..3bbb13258f1 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -487,12 +487,11 @@ class boss_hodir : public CreatureScript if (gettingColdInHereTimer <= diff && gettingColdInHere) { - std::list<HostileReference*> ThreatList = me->GetThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) + for (auto const& pair : me->GetCombatManager().GetPvECombatRefs()) + if (Player* target = pair.second->GetOther(me)->ToPlayer()) if (Aura* BitingColdAura = target->GetAura(SPELL_BITING_COLD_TRIGGERED)) - if ((target->GetTypeId() == TYPEID_PLAYER) && (BitingColdAura->GetStackAmount() > 2)) - SetData(DATA_GETTING_COLD_IN_HERE, 0); + if (BitingColdAura->GetStackAmount() > 2) + SetData(DATA_GETTING_COLD_IN_HERE, 0); gettingColdInHereTimer = 1000; } else diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 53850b38f54..c67c88a397d 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -198,7 +198,7 @@ class boss_ingvar_the_plunderer : public CreatureScript void UpdateAI(uint32 diff) override { - if (!events.IsInPhase(PHASE_EVENT) && !UpdateVictim()) + if (!UpdateVictim()) return; events.Update(diff); @@ -231,9 +231,7 @@ class boss_ingvar_the_plunderer : public CreatureScript ScheduleSecondPhase(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->SetImmuneToPC(false); - if (Unit* target = me->GetThreatManager().SelectVictim()) - AttackStart(target); - else + if (!me->IsThreatened()) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp index eba719e957e..bcc0f7c0c51 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -184,7 +184,7 @@ class spell_toravon_random_aggro : public SpellScript if (!caster->IsAIEnabled) return; - caster->GetThreatManager().resetAllAggro(); + caster->GetThreatManager().ResetAllThreat(); if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1)) caster->GetThreatManager().AddThreat(target, 1000000); |
