Core: Combat/threat system rewrite
Port From (https://github.com/TrinityCore/TrinityCore/commit/34c7810fe507eca1b8b9389630db5d5d26d92e77)
This commit is contained in:
@@ -1522,6 +1522,8 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModScale)]
|
||||
@@ -1596,13 +1598,21 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
}
|
||||
target.CombatStop();
|
||||
|
||||
if (target.GetMap().IsDungeon()) // feign death does not remove combat in dungeons
|
||||
{
|
||||
target.AttackStop();
|
||||
Player targetPlayer = target.ToPlayer();
|
||||
if (targetPlayer != null)
|
||||
targetPlayer.SendAttackSwingCancelAttack();
|
||||
}
|
||||
else
|
||||
target.CombatStop(false, false);
|
||||
|
||||
// prevent interrupt message
|
||||
if (GetCasterGUID() == target.GetGUID() && target.GetCurrentSpell(CurrentSpellTypes.Generic) != null)
|
||||
target.FinishSpell(CurrentSpellTypes.Generic, false);
|
||||
target.InterruptNonMeleeSpells(true);
|
||||
target.GetHostileRefManager().DeleteReferences();
|
||||
|
||||
// stop handling the effect if it was removed by linked event
|
||||
if (aurApp.HasRemoveMode())
|
||||
@@ -1612,6 +1622,10 @@ namespace Game.Spells
|
||||
target.AddUnitFlag2(UnitFlags2.FeignDeath);
|
||||
target.AddDynamicFlag(UnitDynFlags.Dead);
|
||||
target.AddUnitState(UnitState.Died);
|
||||
|
||||
Creature creature = target.ToCreature();
|
||||
if (creature != null)
|
||||
creature.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1619,7 +1633,13 @@ namespace Game.Spells
|
||||
target.RemoveUnitFlag2(UnitFlags2.FeignDeath);
|
||||
target.RemoveDynamicFlag(UnitDynFlags.Dead);
|
||||
target.ClearUnitState(UnitState.Died);
|
||||
|
||||
Creature creature = target.ToCreature();
|
||||
if (creature != null)
|
||||
creature.InitializeReactState();
|
||||
}
|
||||
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModUnattackable)]
|
||||
@@ -1641,7 +1661,17 @@ namespace Game.Spells
|
||||
|
||||
// call functions which may have additional effects after chainging state of unit
|
||||
if (apply && mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||
target.CombatStop();
|
||||
{
|
||||
if (target.GetMap().IsDungeon())
|
||||
{
|
||||
target.AttackStop();
|
||||
Player targetPlayer = target.ToPlayer();
|
||||
if (targetPlayer != null)
|
||||
targetPlayer.SendAttackSwingCancelAttack();
|
||||
}
|
||||
else
|
||||
target.CombatStop();
|
||||
}
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModDisarm)]
|
||||
@@ -2239,18 +2269,7 @@ namespace Game.Spells
|
||||
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask))
|
||||
return;
|
||||
|
||||
Unit target = aurApp.GetTarget();
|
||||
for (byte i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
|
||||
{
|
||||
if (apply)
|
||||
MathFunctions.AddPct(ref target.m_threatModifier[i], GetAmount());
|
||||
else
|
||||
{
|
||||
float amount = target.GetTotalAuraMultiplierByMiscMask(AuraType.ModThreat, 1u << i);
|
||||
target.m_threatModifier[i] = amount;
|
||||
}
|
||||
}
|
||||
aurApp.GetTarget().GetThreatManager().UpdateMySpellSchoolModifiers();
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModTotalThreat)]
|
||||
@@ -2266,7 +2285,7 @@ namespace Game.Spells
|
||||
|
||||
Unit caster = GetCaster();
|
||||
if (caster != null && caster.IsAlive())
|
||||
target.GetHostileRefManager().AddTempThreat(GetAmount(), apply);
|
||||
caster.GetThreatManager().UpdateMyTempModifiers();
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModTaunt)]
|
||||
@@ -2280,17 +2299,22 @@ namespace Game.Spells
|
||||
if (!target.IsAlive() || !target.CanHaveThreatList())
|
||||
return;
|
||||
|
||||
Unit caster = GetCaster();
|
||||
if (caster == null || !caster.IsAlive())
|
||||
target.GetThreatManager().TauntUpdate();
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModDetaunt)]
|
||||
void HandleModDetaunt(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
|
||||
{
|
||||
if (!mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
target.TauntApply(caster);
|
||||
else
|
||||
{
|
||||
// When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
|
||||
target.TauntFadeOut(caster);
|
||||
}
|
||||
Unit caster = GetCaster();
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
if (!caster || !caster.IsAlive() || !target.IsAlive() || !caster.CanHaveThreatList())
|
||||
return;
|
||||
|
||||
caster.GetThreatManager().TauntUpdate();
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
@@ -2305,6 +2329,7 @@ namespace Game.Spells
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
target.SetControlled(apply, UnitState.Confused);
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModFear)]
|
||||
@@ -2316,6 +2341,7 @@ namespace Game.Spells
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
target.SetControlled(apply, UnitState.Fleeing);
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModStun)]
|
||||
@@ -2327,6 +2353,7 @@ namespace Game.Spells
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
target.SetControlled(apply, UnitState.Stunned);
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModRoot)]
|
||||
@@ -2339,6 +2366,7 @@ namespace Game.Spells
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
target.SetControlled(apply, UnitState.Root);
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.PreventsFleeing)]
|
||||
@@ -2743,6 +2771,8 @@ namespace Game.Spells
|
||||
&& GetSpellInfo().HasAttribute(SpellAttr2.DamageReducedShield))
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
||||
}
|
||||
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.DamageImmunity)]
|
||||
@@ -2753,6 +2783,8 @@ namespace Game.Spells
|
||||
|
||||
Unit target = aurApp.GetTarget();
|
||||
m_spellInfo.ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), apply);
|
||||
|
||||
target.GetThreatManager().UpdateOnlineStates(true, false);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.DispelImmunity)]
|
||||
@@ -4466,7 +4498,7 @@ namespace Game.Spells
|
||||
player.GetReputationMgr().ApplyForceReaction(factionId, factionRank, apply);
|
||||
player.GetReputationMgr().SendForceReactions();
|
||||
|
||||
// stop fighting if at apply forced rank friendly or at remove real rank friendly
|
||||
// stop fighting at apply (if forced rank friendly) or at remove (if real rank friendly)
|
||||
if ((apply && factionRank >= ReputationRank.Friendly) || (!apply && player.GetReputationRank(factionId) >= ReputationRank.Friendly))
|
||||
player.StopAttackFaction(factionId);
|
||||
}
|
||||
|
||||
@@ -2033,7 +2033,7 @@ namespace Game.Spells
|
||||
// spellHitTarget can be null if spell is missed in DoSpellHitOnUnit
|
||||
if (missInfo != SpellMissInfo.Evade && spellHitTarget && !m_caster.IsFriendlyTo(unit) && (!IsPositive() || m_spellInfo.HasEffect(SpellEffectName.Dispel)))
|
||||
{
|
||||
m_caster.CombatStart(unit, m_spellInfo.HasInitialAggro());
|
||||
m_caster.AttackedTarget(unit, m_spellInfo.HasInitialAggro());
|
||||
|
||||
if (!unit.IsStandState())
|
||||
unit.SetStandState(UnitStandStateType.Stand);
|
||||
@@ -2133,7 +2133,8 @@ namespace Game.Spells
|
||||
}
|
||||
if (unit.IsInCombat() && m_spellInfo.HasInitialAggro())
|
||||
{
|
||||
m_caster.SetInCombatState(unit.GetCombatTimer() > 0, unit);
|
||||
if (m_caster.HasUnitFlag(UnitFlags.PvpAttackable)) // only do explicit combat forwarding for PvP enabled units
|
||||
m_caster.GetCombatManager().InheritCombatStatesFrom(unit); // for creature v creature combat, the threat forward does it for us
|
||||
unit.GetThreatManager().ForwardThreatForAssistingMe(m_caster, 0.0f, null, true);
|
||||
}
|
||||
}
|
||||
@@ -6849,6 +6850,10 @@ namespace Game.Spells
|
||||
if (unit == null)
|
||||
return;
|
||||
|
||||
// This will only cause combat - the target will engage once the projectile hits (in DoAllEffectOnTarget)
|
||||
if (targetInfo.missCondition != SpellMissInfo.Evade && !m_caster.IsFriendlyTo(unit) && (!m_spellInfo.IsPositive() || m_spellInfo.HasEffect(SpellEffectName.Dispel)) && (m_spellInfo.HasInitialAggro() || unit.IsEngaged()))
|
||||
m_caster.SetInCombatWith(unit);
|
||||
|
||||
foreach (SpellEffectInfo effect in m_spellInfo.GetEffects())
|
||||
{
|
||||
if (effect != null && Convert.ToBoolean(targetInfo.effectMask & (1 << (int)effect.EffectIndex)))
|
||||
|
||||
@@ -788,7 +788,7 @@ namespace Game.Spells
|
||||
|
||||
int gain = (int)(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, (uint)newDamage, gainMultiplier);
|
||||
}
|
||||
@@ -1229,7 +1229,7 @@ namespace Game.Spells
|
||||
break;
|
||||
}
|
||||
|
||||
m_caster.EnergizeBySpell(unitTarget, m_spellInfo.Id, damage, power);
|
||||
m_caster.EnergizeBySpell(unitTarget, m_spellInfo, damage, power);
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.EnergizePct)]
|
||||
@@ -1252,7 +1252,7 @@ namespace Game.Spells
|
||||
return;
|
||||
|
||||
int gain = (int)MathFunctions.CalculatePct(maxPower, damage);
|
||||
m_caster.EnergizeBySpell(unitTarget, m_spellInfo.Id, gain, power);
|
||||
m_caster.EnergizeBySpell(unitTarget, m_spellInfo, gain, power);
|
||||
}
|
||||
|
||||
void SendLoot(ObjectGuid guid, LootType loottype)
|
||||
@@ -2411,28 +2411,22 @@ namespace Game.Spells
|
||||
|
||||
// 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 == null || !unitTarget.CanHaveThreatList() || unitTarget.GetVictim() == m_caster)
|
||||
if (unitTarget == null || !unitTarget.CanHaveThreatList())
|
||||
{
|
||||
SendCastResult(SpellCastResult.DontReport);
|
||||
return;
|
||||
}
|
||||
|
||||
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().AddThreat(m_caster, topThreat - myThreat);
|
||||
|
||||
//Set aggro victim to caster
|
||||
HostileReference forcedVictim = unitTarget.GetThreatManager().GetOnlineContainer().GetReferenceByTarget(m_caster);
|
||||
if (forcedVictim != null)
|
||||
unitTarget.GetThreatManager().SetCurrentVictim(forcedVictim);
|
||||
SendCastResult(SpellCastResult.DontReport);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unitTarget.ToCreature().IsAIEnabled && !unitTarget.ToCreature().HasReactState(ReactStates.Passive))
|
||||
unitTarget.ToCreature().GetAI().AttackStart(m_caster);
|
||||
if (!mgr.IsThreatListEmpty())
|
||||
// Set threat equal to highest threat currently on target
|
||||
mgr.MatchUnitThreatToHighestThreat(m_caster);
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.WeaponDamageNoSchool)]
|
||||
@@ -2654,13 +2648,13 @@ namespace Game.Spells
|
||||
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
|
||||
return;
|
||||
|
||||
if (unitTarget == null || !unitTarget.IsAlive() || !m_caster.IsAlive())
|
||||
if (unitTarget == null || !m_caster.IsAlive())
|
||||
return;
|
||||
|
||||
if (!unitTarget.CanHaveThreatList())
|
||||
return;
|
||||
|
||||
unitTarget.GetThreatManager().AddThreat(m_caster, damage);
|
||||
unitTarget.GetThreatManager().AddThreat(m_caster, damage, m_spellInfo, true);
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.HealMaxHealth)]
|
||||
@@ -3241,19 +3235,19 @@ namespace Game.Spells
|
||||
if (unitTarget == null)
|
||||
return;
|
||||
|
||||
if (unitTarget.IsTypeId(TypeId.Player))
|
||||
unitTarget.ToPlayer().SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
|
||||
|
||||
unitTarget.GetHostileRefManager().UpdateVisibility();
|
||||
|
||||
var attackers = unitTarget.GetAttackers();
|
||||
for (var i = 0; i < attackers.Count; ++i)
|
||||
if (unitTarget.IsPlayer() && !unitTarget.GetMap().IsDungeon())
|
||||
{
|
||||
var unit = attackers[i];
|
||||
if (!unit.CanSeeOrDetect(unitTarget))
|
||||
unit.AttackStop();
|
||||
// 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
|
||||
foreach (var pair in unitTarget.GetThreatManager().GetThreatenedByMeList())
|
||||
pair.Value.SetThreat(0.0f);
|
||||
}
|
||||
|
||||
// makes spells cast before this time fizzle
|
||||
unitTarget.LastSanctuaryTime = GameTime.GetGameTimeMS();
|
||||
}
|
||||
|
||||
@@ -4808,7 +4802,7 @@ namespace Game.Spells
|
||||
return;
|
||||
|
||||
if (unitTarget != null)
|
||||
m_caster.SetRedirectThreat(unitTarget.GetGUID(), (uint)damage);
|
||||
m_caster.GetThreatManager().RegisterRedirectThreat(m_spellInfo.Id, unitTarget.GetGUID(), (uint)damage);
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.GameObjectDamage)]
|
||||
|
||||
@@ -1022,8 +1022,8 @@ namespace Game.Spells
|
||||
// creature/player specific target checks
|
||||
if (unitTarget != null)
|
||||
{
|
||||
// spells cannot be cast if player is in fake combat also
|
||||
if (HasAttribute(SpellAttr1.CantTargetInCombat) && (unitTarget.IsInCombat() || unitTarget.IsPetInCombat()))
|
||||
// spells cannot be cast if target has a pet in combat either
|
||||
if (HasAttribute(SpellAttr1.CantTargetInCombat) && (unitTarget.IsInCombat() || unitTarget.HasUnitFlag(UnitFlags.PetInCombat)))
|
||||
return SpellCastResult.TargetAffectingCombat;
|
||||
|
||||
// only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
|
||||
|
||||
Reference in New Issue
Block a user