Core/Spells: Delay combat flagging for spell targets until spell missile lands
(cherry picked from commit b59706c8b6856bdfe084a38330773725d3404f05)
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user