aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellEffects.cpp
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2018-01-03 20:04:19 +0100
committerGitHub <noreply@github.com>2018-01-03 20:04:19 +0100
commit532ab1c7f8653d1a2e48aa1f1f8a9ba1041d4bb7 (patch)
tree81e2f7eb89b3144c14dd488ea6304f6d44d19848 /src/server/game/Spells/SpellEffects.cpp
parent425b181544a21d2246fdf0261ba76a37e2510883 (diff)
Core: Combat/threat system rewrite (PR #19930)
- PvE combat is now always mutual. UNIT_FLAG_IN_COMBAT is backed by actual references to the units we're in combat with. - PvP combat is now also tracked, and almost always mutual; spells like Vanish and Feign Death can break this rule. That means we can easily determine a list of players we're fighting. - By extension, IsInCombatWith now has sensible behavior when invoked on nonplayers. - Threat and combat systems are no longer the same. - They still have an enforced relationship (threat implies combat - clearing combat clears threat)... - ...but we can have combat without threat. A creature (with threat list) isn't considered to be engaged until it has an entry on its threat list... - ...which means we can now faithfully replicate retail engage behavior. Combat on projectile launch - engagement start on projectile impact. Yay for progress! - AI method refactor, as already ported in 6113b9d - `JustEngagedWith`, `JustEnteredCombat` and `JustExitedCombat`. - Vehicle threat is now properly pooled on the main vehicle body (fixes #16542). - Various edge case bug fixes for threat redirects (Misdirection "cancelling" Vigilance and similar). - Target re-selection is now significantly faster. - Fixed a ton of other smaller edge case bugs, probably. Closes #7951 and #19998.
Diffstat (limited to 'src/server/game/Spells/SpellEffects.cpp')
-rw-r--r--src/server/game/Spells/SpellEffects.cpp61
1 files changed, 28 insertions, 33 deletions
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 45ecb4a8e15..59f5d9b764a 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1229,7 +1229,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
int32 gain = int32(newDamage* gainMultiplier);
- m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, powerType);
+ m_caster->EnergizeBySpell(m_caster, m_spellInfo, gain, powerType);
}
ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, gainMultiplier);
}
@@ -1781,7 +1781,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
if (damage < 0)
return;
- m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power);
+ m_caster->EnergizeBySpell(unitTarget, m_spellInfo, damage, power);
}
void Spell::EffectEnergizePct(SpellEffIndex effIndex)
@@ -1807,7 +1807,7 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex)
return;
uint32 gain = CalculatePct(maxPower, damage);
- m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power);
+ m_caster->EnergizeBySpell(unitTarget, m_spellInfo, gain, power);
}
void Spell::SendLoot(ObjectGuid guid, LootType loottype)
@@ -3040,30 +3040,26 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
// this effect use before aura Taunt apply for prevent taunt already attacking target
// for spell as marked "non effective at already attacking target"
- if (!unitTarget || !unitTarget->CanHaveThreatList() || unitTarget->GetVictim() == m_caster)
+ if (!unitTarget || !unitTarget->CanHaveThreatList())
{
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
}
- if (m_spellInfo->Id == 62124 && (!unitTarget->IsPet() || !unitTarget->GetOwnerGUID().IsPlayer()))
- m_caster->CastSpell(unitTarget, 67485, true);
-
- if (!unitTarget->GetThreatManager().getOnlineContainer().empty())
+ ThreatManager& mgr = unitTarget->GetThreatManager();
+ if (mgr.GetCurrentVictim() == m_caster)
{
- // Also use this effect to set the taunter's threat to the taunted creature's highest value
- float myThreat = unitTarget->GetThreatManager().getThreat(m_caster);
- float topThreat = unitTarget->GetThreatManager().getOnlineContainer().getMostHated()->getThreat();
- if (topThreat > myThreat)
- unitTarget->GetThreatManager().doAddThreat(m_caster, topThreat - myThreat);
-
- //Set aggro victim to caster
- if (HostileReference* forcedVictim = unitTarget->GetThreatManager().getOnlineContainer().getReferenceByTarget(m_caster))
- unitTarget->GetThreatManager().setCurrentVictim(forcedVictim);
+ SendCastResult(SPELL_FAILED_DONT_REPORT);
+ return;
}
- if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE))
- unitTarget->ToCreature()->AI()->AttackStart(m_caster);
+ // Hand of Reckoning
+ if (m_spellInfo->Id == 62124)
+ m_caster->CastSpell(unitTarget, 67485, true);
+
+ if (!mgr.IsThreatListEmpty())
+ // Set threat equal to highest threat currently on target
+ mgr.MatchUnitThreatToHighestThreat(m_caster);
}
void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
@@ -3354,13 +3350,13 @@ void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
return;
- if (!unitTarget || !unitTarget->IsAlive() || !m_caster->IsAlive())
+ if (!unitTarget || !m_caster->IsAlive())
return;
if (!unitTarget->CanHaveThreatList())
return;
- unitTarget->GetThreatManager().AddThreat(m_caster, float(damage));
+ unitTarget->GetThreatManager().AddThreat(m_caster, float(damage), m_spellInfo, true);
}
void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
@@ -3925,20 +3921,19 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
- if (unitTarget->GetTypeId() == TYPEID_PLAYER)
- unitTarget->ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
-
- unitTarget->getHostileRefManager().UpdateVisibility();
-
- Unit::AttackerSet const& attackers = unitTarget->getAttackers();
- for (Unit::AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->GetMap()->IsDungeon())
{
- if (!(*itr)->CanSeeOrDetect(unitTarget))
- (*(itr++))->AttackStop();
- else
- ++itr;
+ // stop all pve combat for players outside dungeons, suppress pvp combat
+ unitTarget->CombatStop(false, false);
+ }
+ else
+ {
+ // in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
+ for (auto const& pair : unitTarget->GetThreatManager().GetThreatenedByMeList())
+ pair.second->SetThreat(0.0f);
}
+ // makes spells cast before this time fizzle
unitTarget->m_lastSanctuaryTime = GameTime::GetGameTimeMS();
}
@@ -5478,7 +5473,7 @@ void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/)
return;
if (unitTarget)
- m_caster->SetRedirectThreat(unitTarget->GetGUID(), uint32(damage));
+ m_caster->GetThreatManager().RegisterRedirectThreat(m_spellInfo->Id, unitTarget->GetGUID(), uint32(damage));
}
void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)