aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Combat/CombatManager.cpp9
-rw-r--r--src/server/game/Combat/CombatManager.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Spells/Spell.cpp51
-rw-r--r--src/server/game/Spells/Spell.h2
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;