Core/Spells: Delay combat flagging for spell targets until spell missile lands

(cherry picked from commit b59706c8b6856bdfe084a38330773725d3404f05)
This commit is contained in:
Alan Deutscher
2022-09-05 22:23:02 +02:00
committed by Shauren
parent a1ddf5195b
commit ff99952dfb
5 changed files with 57 additions and 9 deletions
+7 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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
+46 -5
View File
@@ -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;
+2
View File
@@ -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;