diff options
author | Alan Deutscher <adeutscher@gmail.com> | 2022-07-10 18:55:15 -0700 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-09-05 22:23:02 +0200 |
commit | ff99952dfb7d2b532de2d1aedc825fb96038f4c2 (patch) | |
tree | 3d71265e0562a366e0d358ebfe20322ec1f51a97 | |
parent | a1ddf5195b8d03ea87248b7037a3e50e3e793d8e (diff) |
Core/Spells: Delay combat flagging for spell targets until spell missile lands
(cherry picked from commit b59706c8b6856bdfe084a38330773725d3404f05)
-rw-r--r-- | src/server/game/Combat/CombatManager.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Combat/CombatManager.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 51 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 2 |
5 files changed, 57 insertions, 9 deletions
diff --git a/src/server/game/Combat/CombatManager.cpp b/src/server/game/Combat/CombatManager.cpp index 4a82b5e98b2..96508afa938 100644 --- a/src/server/game/Combat/CombatManager.cpp +++ b/src/server/game/Combat/CombatManager.cpp @@ -171,7 +171,7 @@ Unit* CombatManager::GetAnyTarget() const return nullptr; } -bool CombatManager::SetInCombatWith(Unit* who) +bool CombatManager::SetInCombatWith(Unit* who, bool suppressPvpSecond) { // Are we already in combat? If yes, refresh pvp combat auto it = _pvpRefs.find(who->GetGUID()); @@ -190,7 +190,12 @@ bool CombatManager::SetInCombatWith(Unit* who) // ...then create new reference CombatReference* ref; if (_owner->IsControlledByPlayer() && who->IsControlledByPlayer()) - ref = new PvPCombatReference(_owner, who); + { + PvPCombatReference* refPvp = new PvPCombatReference(_owner, who); + if (suppressPvpSecond) + refPvp->SuppressFor(who); + ref = refPvp; + } else ref = new CombatReference(_owner, who); diff --git a/src/server/game/Combat/CombatManager.h b/src/server/game/Combat/CombatManager.h index 6939062ee10..7745458788c 100644 --- a/src/server/game/Combat/CombatManager.h +++ b/src/server/game/Combat/CombatManager.h @@ -114,7 +114,7 @@ class TC_GAME_API CombatManager Unit* GetAnyTarget() const; // return value is the same as calling IsInCombatWith immediately after this returns - bool SetInCombatWith(Unit* who); + bool SetInCombatWith(Unit* who, bool suppressPvpSecond = false); bool IsInCombatWith(ObjectGuid const& who) const; bool IsInCombatWith(Unit const* who) const; void InheritCombatStatesFrom(Unit const* who); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index d6a239b2273..4a26e5b2691 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1150,7 +1150,7 @@ class TC_GAME_API Unit : public WorldObject bool IsInCombat() const { return HasUnitFlag(UNIT_FLAG_IN_COMBAT); } bool IsInCombatWith(Unit const* who) const { return who && m_combatManager.IsInCombatWith(who); } - void SetInCombatWith(Unit* enemy) { if (enemy) m_combatManager.SetInCombatWith(enemy); } + void SetInCombatWith(Unit* enemy, bool suppressPvpTargetCombat = false) { if (enemy) m_combatManager.SetInCombatWith(enemy, suppressPvpTargetCombat); } void ClearInCombat() { m_combatManager.EndAllCombat(); } void UpdatePetCombatState(); // Threat handling diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f49f0495339..c5b7ee28286 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2253,6 +2253,37 @@ void Spell::CleanupTargetList() m_delayMoment = 0; } +class ProcImpactDelayed : public BasicEvent +{ +public: + ProcImpactDelayed(Unit* owner, ObjectGuid casterGUID, const bool enterCombat, bool enablePVP) : _owner(owner), _casterGUID(casterGUID), _enterCombat(enterCombat), _enablePVP(enablePVP) { } + + bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override + { + if(!_owner) + return true; + + Unit* caster = ObjectAccessor::GetUnit(*_owner, _casterGUID); + if (!caster) + return true; + + // This will only cause combat - the target will engage once the projectile hits (in DoAllEffectOnTarget) + if (_enterCombat) + _owner->SetInCombatWith(caster); + + if (_enablePVP && caster->ToPlayer()) + caster->ToPlayer()->UpdatePvP(true); + + return true; + } + +private: + Unit* _owner; + ObjectGuid _casterGUID; + bool _enterCombat; + bool _enablePVP; +}; + class ProcReflectDelayed : public BasicEvent { public: @@ -2322,8 +2353,13 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= // Calculate hit result WorldObject* caster = m_originalCaster ? m_originalCaster : m_caster; + Unit* unitCaster = m_caster->ToUnit(); targetInfo.MissCondition = caster->SpellHitResult(target, m_spellInfo, m_canReflect && !(IsPositive() && m_caster->IsFriendlyTo(target))); + // This will only cause combat - the target will engage once the projectile hits (in DoAllEffectOnTarget) + if (m_originalCaster && targetInfo.MissCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(target) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || target->IsEngaged())) + m_originalCaster->SetInCombatWith(target, true); + // Spell have speed - need calculate incoming time // Incoming time is zero for self casts. At least I think so. if (m_caster != target) @@ -2358,6 +2394,15 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= } targetInfo.TimeDelay += uint64(std::floor(hitDelay * 1000.0f)); + + if (unitCaster && targetInfo.MissCondition != SPELL_MISS_EVADE) + { + bool enterCombat = !caster->IsFriendlyTo(target) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || target->IsEngaged()); + bool enablePVP = targetInfo.IsPVPEnabling(); + + if (enterCombat || enablePVP) + target->m_Events.AddEvent(new ProcImpactDelayed(target, m_originalCasterGUID, enterCombat, enablePVP), target->m_Events.CalculateTime(Milliseconds(targetInfo.TimeDelay))); + } } else targetInfo.TimeDelay = 0ULL; @@ -2366,7 +2411,7 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= if (targetInfo.MissCondition == SPELL_MISS_REFLECT) { // Calculate reflected spell result on caster (shouldn't be able to reflect gameobject spells) - Unit* unitCaster = ASSERT_NOTNULL(m_caster->ToUnit()); + ASSERT(unitCaster); targetInfo.ReflectResult = unitCaster->SpellHitResult(unitCaster, m_spellInfo, false); // can't reflect twice // Proc spell reflect aura when missile hits the original target @@ -8181,10 +8226,6 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe if (!unit) return; - // This will only cause combat - the target will engage once the projectile hits (in DoAllEffectOnTarget) - if (m_originalCaster && targetInfo.MissCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || unit->IsEngaged())) - m_originalCaster->SetInCombatWith(unit); - m_damage = 0; m_healing = 0; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 0fda5253439..0e438a4f961 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -742,6 +742,8 @@ class TC_GAME_API Spell void DoTargetSpellHit(Spell* spell, SpellEffectInfo const& spellEffectInfo) override; void DoDamageAndTriggers(Spell* spell) override; + bool IsPVPEnabling() const { return _enablePVP; } + ObjectGuid TargetGUID; uint64 TimeDelay = 0ULL; int32 Damage = 0; |