diff options
author | Treeston <treeston.mmoc@gmail.com> | 2019-08-04 01:26:20 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-12-18 11:36:50 +0100 |
commit | 14c38a1c529e634b068a67b3e7475ddcf599086b (patch) | |
tree | 3ebb031d953f9d1b03ac7466eb4b86b0dff295bb /src | |
parent | 82d62a3d4c11d408623d7624de798f810ca4c2d9 (diff) |
Core/Unit: Spell focusing now no longer nonsensical. HasSpellFocus always const. Error logs for various stuff.
(cherry picked from commit 4a219eda07c353139608065f7d0a016094ee4ce0)
Diffstat (limited to 'src')
9 files changed, 82 insertions, 93 deletions
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 8f09c34fbc8..49ff7661302 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -256,7 +256,7 @@ bool CreatureAI::UpdateVictim() if (!me->HasReactState(REACT_PASSIVE)) { if (Unit* victim = me->SelectVictim()) - if (!me->HandleSpellFocus(nullptr, true) && victim != me->GetVictim()) + if (!me->HasSpellFocus() && victim != me->GetVictim()) AttackStart(victim); return me->GetVictim() != nullptr; @@ -314,7 +314,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->ResetPlayerDamageReq(); me->SetLastDamagedTime(0); me->SetCannotReachTarget(false); - me->DoNotReacquireTarget(); + me->DoNotReacquireSpellFocusTarget(); EngagementOver(); return true; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 468f2d81f0f..eabe2fdf4f7 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -306,7 +306,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_grou m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0), - m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _focusSpell(nullptr), _spellFocusDelay(0), _shouldReacquireSpellFocusTarget(false), _suppressedSpellFocusOrientation(0.0f), _lastDamagedTime(0), + m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _lastDamagedTime(0), _regenerateHealth(true), _regenerateHealthLock(false) { m_regenTimer = CREATURE_REGEN_INTERVAL; @@ -800,22 +800,12 @@ void Creature::Update(uint32 diff) break; GetThreatManager().Update(diff); - - if (_shouldReacquireSpellFocusTarget && !HandleSpellFocus(nullptr, true)) + if (_spellFocusInfo.delay) { - SetTarget(_suppressedSpellFocusTarget); - - if (!HasUnitFlag2(UNIT_FLAG2_DISABLE_TURN)) - { - if (!_suppressedSpellFocusTarget.IsEmpty()) - { - if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, _suppressedSpellFocusTarget)) - SetFacingToObject(objTarget, false); - } - else - SetFacingTo(_suppressedSpellFocusOrientation, false); - } - _shouldReacquireSpellFocusTarget = false; + if (_spellFocusInfo.delay <= diff) + ReacquireSpellFocusTarget(); + else + _spellFocusInfo.delay -= 0; } // periodic check to see if the creature has passed an evade boundary @@ -1220,7 +1210,7 @@ Unit* Creature::SelectVictim() if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target)) { - if (!HandleSpellFocus(nullptr, true)) + if (!HasSpellFocus()) SetInFront(target); return target; } @@ -2117,8 +2107,8 @@ void Creature::setDeathState(DeathState s) SaveRespawnTime(); ReleaseSpellFocus(nullptr, false); // remove spellcast focus - DoNotReacquireTarget(); // cancel delayed re-target - SetTarget(ObjectGuid::Empty); // drop target - dead mobs shouldn't ever target things + DoNotReacquireSpellFocusTarget(); // cancel delayed re-target + SetTarget(ObjectGuid::Empty); // drop target - dead mobs shouldn't ever target things SetNpcFlags(UNIT_NPC_FLAG_NONE); SetNpcFlags2(UNIT_NPC_FLAG_2_NONE); @@ -3194,16 +3184,16 @@ void Creature::SetDisplayFromModel(uint32 modelIdx) void Creature::SetTarget(ObjectGuid const& guid) { - if (HandleSpellFocus(nullptr, true)) - _suppressedSpellFocusTarget = guid; + if (HasSpellFocus()) + _spellFocusInfo.target = guid; else SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::Target), guid); } -void Creature::SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* target) +void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target) { // already focused - if (_focusSpell) + if (_spellFocusInfo.spell) return; // Prevent dead/feigning death creatures from setting a focus target, so they won't turn @@ -3228,14 +3218,17 @@ void Creature::SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* t return; // store pre-cast values for target and orientation (used to later restore) - if (!HandleSpellFocus(nullptr, true)) + if (!_spellFocusInfo.delay) { // only overwrite these fields if we aren't transitioning from one spell focus to another - _suppressedSpellFocusTarget = GetTarget(); - _suppressedSpellFocusOrientation = GetOrientation(); + _spellFocusInfo.target = GetTarget(); + _spellFocusInfo.orientation = GetOrientation(); } + else // don't automatically reacquire target for the previous spellcast + _spellFocusInfo.delay = 0; - _focusSpell = focusSpell; + _spellFocusInfo.spell = focusSpell; + bool const noTurnDuringCast = spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST); // set target, then force send update packet to players if it changed to provide appropriate facing ObjectGuid newTarget = target ? target->GetGUID() : ObjectGuid::Empty; if (GetTarget() != newTarget) @@ -3247,7 +3240,7 @@ void Creature::SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* t spellInfo->GetSpellVisual() ) && ( !focusSpell->GetCastTime() || // if the spell is instant cast - spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST) // client gets confused if we attempt to turn at the regularly scheduled update packet + noTurnDuringCast // client gets confused if we attempt to turn at the regularly scheduled update packet ) ) { @@ -3262,8 +3255,6 @@ void Creature::SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* t } } - bool const noTurnDuringCast = spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST); - if (!HasUnitFlag2(UNIT_FLAG2_DISABLE_TURN)) { // Face the target - we need to do this before the unit state is modified for no-turn spells @@ -3278,61 +3269,65 @@ void Creature::SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* t AddUnitState(UNIT_STATE_FOCUSING); } -bool Creature::HandleSpellFocus(Spell const* focusSpell, bool withDelay) +bool Creature::HasSpellFocus(Spell const* focusSpell) const { if (!IsAlive()) // dead creatures cannot focus { - ReleaseSpellFocus(nullptr, false); - return false; - } - - if (focusSpell && (focusSpell != _focusSpell)) - return false; - - if (!_focusSpell) - { - if (!withDelay || !_spellFocusDelay) - return false; - if (GetMSTimeDiffToNow(_spellFocusDelay) > 1000) // @todo figure out if we can get rid of this magic number somehow + if (_spellFocusInfo.spell || _spellFocusInfo.delay) { - _spellFocusDelay = 0; // save checks in the future - return false; + TC_LOG_WARN("entities.unit", "Creature '%s' (entry %u) has spell focus (spell id %u, delay %ums) despite being dead.", + GetName().c_str(), GetEntry(), _spellFocusInfo.spell ? _spellFocusInfo.spell->GetSpellInfo()->Id : 0, _spellFocusInfo.delay); } + return false; } - return true; + if (focusSpell) + return (focusSpell == _spellFocusInfo.spell); + else + return (_spellFocusInfo.spell || _spellFocusInfo.delay); } void Creature::ReleaseSpellFocus(Spell const* focusSpell, bool withDelay) { - if (!_focusSpell) + if (!_spellFocusInfo.spell) return; // focused to something else - if (focusSpell && focusSpell != _focusSpell) + if (focusSpell && focusSpell != _spellFocusInfo.spell) return; - if (IsPet() && !HasUnitFlag2(UNIT_FLAG2_DISABLE_TURN)) // player pets do not use delay system + if (_spellFocusInfo.spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST)) + ClearUnitState(UNIT_STATE_FOCUSING); + + if (IsPet()) // player pets do not use delay system { - SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::Target), _suppressedSpellFocusTarget); - if (!_suppressedSpellFocusTarget.IsEmpty()) + if (!HasUnitFlag2(UNIT_FLAG2_DISABLE_TURN)) + ReacquireSpellFocusTarget(); + } + else // don't allow re-target right away to prevent visual bugs + _spellFocusInfo.delay = withDelay ? 1000 : 1; + + _spellFocusInfo.spell = nullptr; +} + +void Creature::ReacquireSpellFocusTarget() +{ + if (!HasSpellFocus()) + return; + + SetTarget(_spellFocusInfo.target); + + if (!HasUnitFlag2(UNIT_FLAG2_DISABLE_TURN)) + { + if (!_spellFocusInfo.target.IsEmpty()) { - if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, _suppressedSpellFocusTarget)) + if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, _spellFocusInfo.target)) SetFacingToObject(objTarget, false); } else - SetFacingTo(_suppressedSpellFocusOrientation, false); + SetFacingTo(_spellFocusInfo.orientation, false); } - else - // tell the creature that it should reacquire its actual target after the delay expires (this is handled in ::Update) - // player pets don't need to do this, as they automatically reacquire their target on focus release - MustReacquireTarget(); - - if (_focusSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST)) - ClearUnitState(UNIT_STATE_FOCUSING); - - _focusSpell = nullptr; - _spellFocusDelay = (!IsPet() && withDelay) ? GameTime::GetGameTimeMS() : 0; // don't allow re-target right away to prevent visual bugs + _spellFocusInfo.delay = 0; } bool Creature::IsMovementPreventedByCasting() const @@ -3345,7 +3340,7 @@ bool Creature::IsMovementPreventedByCasting() const return false; } - if (HasSpellFocusTarget()) + if (HasSpellFocus()) return true; if (HasUnitState(UNIT_STATE_CASTING)) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 9cc915d3e63..7ccc16b7c7a 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -348,18 +348,11 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma // Handling caster facing during spellcast void SetTarget(ObjectGuid const& guid) override; - void MustReacquireTarget() { _shouldReacquireSpellFocusTarget = true; } // flags the Creature for forced (client displayed) target reacquisition in the next ::Update call - void DoNotReacquireTarget() - { - _shouldReacquireSpellFocusTarget = false; - _suppressedSpellFocusTarget = ObjectGuid::Empty; - SetTarget(ObjectGuid::Empty); - _suppressedSpellFocusOrientation = 0.0f; - } - void SetSpellFocusTarget(Spell const* focusSpell, WorldObject const* target); - bool HandleSpellFocus(Spell const* focusSpell = nullptr, bool withDelay = false) override; + void ReacquireSpellFocusTarget(); + void DoNotReacquireSpellFocusTarget() { _spellFocusInfo.delay = 0; } + void SetSpellFocus(Spell const* focusSpell, WorldObject const* target); + bool HasSpellFocus(Spell const* focusSpell = nullptr) const override; void ReleaseSpellFocus(Spell const* focusSpell = nullptr, bool withDelay = true); - bool HasSpellFocusTarget() const override { return IsAlive() && (_focusSpell || _spellFocusDelay); } bool IsMovementPreventedByCasting() const override; @@ -446,11 +439,13 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool m_respawnCompatibilityMode; /* Spell focus system */ - Spell const* _focusSpell; // Locks the target during spell cast for proper facing - uint32 _spellFocusDelay; - bool _shouldReacquireSpellFocusTarget; - ObjectGuid _suppressedSpellFocusTarget; // Stores the creature's "real" target while casting - float _suppressedSpellFocusOrientation; // Stores the creature's "real" orientation while casting + struct + { + Spell const* spell = nullptr; + uint32 delay = 0; // ms until the creature's target should snap back (0 = no snapback scheduled) + ObjectGuid target; // the creature's "real" target while casting + float orientation = 0.0f; // the creature's "real" orientation while casting + } _spellFocusInfo; time_t _lastDamagedTime; // Part of Evade mechanics CreatureTextRepeatGroup m_textRepeat; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 23624766dbb..50444e4efa6 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1503,8 +1503,7 @@ class TC_GAME_API Unit : public WorldObject virtual SpellInfo const* GetCastSpellInfo(SpellInfo const* spellInfo) const; uint32 GetCastSpellXSpellVisualId(SpellInfo const* spellInfo) const override; - virtual bool HandleSpellFocus(Spell const* /*focusSpell*/ = nullptr, bool /*withDelay*/ = false) { return false; } - virtual bool HasSpellFocusTarget() const { return false; } + virtual bool HasSpellFocus(Spell const* /*focusSpell*/ = nullptr) const { return false; } virtual bool IsMovementPreventedByCasting() const; bool CanCastSpellWhileMoving(SpellInfo const* spellInfo) const; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 79c30717004..7556d124765 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -337,14 +337,14 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe { if (unit_target) { - if (!pet->HandleSpellFocus()) + if (!pet->HasSpellFocus()) pet->SetInFront(unit_target); if (Player* player = unit_target->ToPlayer()) pet->SendUpdateToPlayer(player); } else if (Unit* unit_target2 = spell->m_targets.GetUnitTarget()) { - if (!pet->HandleSpellFocus()) + if (!pet->HasSpellFocus()) pet->SetInFront(unit_target2); if (Player* player = unit_target2->ToPlayer()) pet->SendUpdateToPlayer(player); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 813a68ce6ba..59cf6e00210 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3167,9 +3167,9 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const if (!(m_spellInfo->IsNextMeleeSwingSpell() || IsAutoRepeat())) { if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget()) - m_caster->ToCreature()->SetSpellFocusTarget(this, m_targets.GetObjectTarget()); + m_caster->ToCreature()->SetSpellFocus(this, m_targets.GetObjectTarget()); else if (m_spellInfo->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST)) - m_caster->ToCreature()->SetSpellFocusTarget(this, nullptr); + m_caster->ToCreature()->SetSpellFocus(this, nullptr); } } @@ -4778,8 +4778,8 @@ void Spell::SendChannelStart(uint32 duration) if (m_UniqueTargetInfo.size() == 1 && m_UniqueGOTargetInfo.empty()) if(target.TargetGUID != unitCaster->GetGUID()) if (Creature* creatureCaster = unitCaster->ToCreature()) - if (!creatureCaster->HandleSpellFocus(this)) - creatureCaster->SetSpellFocusTarget(this, ObjectAccessor::GetWorldObject(*creatureCaster, target.TargetGUID)); + if (!creatureCaster->HasSpellFocus(this)) + creatureCaster->SetSpellFocus(this, ObjectAccessor::GetWorldObject(*creatureCaster, target.TargetGUID)); } for (GOTargetInfo const& target : m_UniqueGOTargetInfo) 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 e22e075624a..d68de052a17 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1363,7 +1363,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript if (!me->HasReactState(REACT_PASSIVE)) { if (Unit* victim = me->SelectVictim()) - if (!me->HandleSpellFocus(nullptr, true) && victim != me->GetVictim()) + if (!me->HasSpellFocus() && victim != me->GetVictim()) AttackStart(victim); return me->GetVictim() != nullptr; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 4eedcff833e..181c5724448 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -630,7 +630,7 @@ protected: if (!me->HasReactState(REACT_PASSIVE)) { if (Unit* victim = me->SelectVictim()) - if (!me->HandleSpellFocus(nullptr, true) && victim != me->GetVictim()) + if (!me->HasSpellFocus() && victim != me->GetVictim()) AttackStart(victim); return me->GetVictim() != nullptr; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index c9f65448fb3..6637dc7746c 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -1802,7 +1802,7 @@ class spell_thorim_lightning_charge : public SpellScriptLoader { /// @workaround: focus target is not working because spell is triggered and instant if (Creature* creature = GetCaster()->ToCreature()) - creature->SetSpellFocusTarget(GetSpell(), GetExplTargetWorldObject()); + creature->SetSpellFocus(GetSpell(), GetExplTargetWorldObject()); } void HandleCharge() |