Core/Unit: Spell focusing now no longer nonsensical. HasSpellFocus always const. Error logs for various stuff.

Port From (https://github.com/TrinityCore/TrinityCore/commit/14c38a1c529e634b068a67b3e7475ddcf599086b)
This commit is contained in:
hondacrx
2022-01-02 19:49:21 -05:00
parent 82d3e3d8f4
commit 92c90bf777
6 changed files with 76 additions and 91 deletions
+2 -2
View File
@@ -254,7 +254,7 @@ namespace Game.AI
{
Unit victim = me.SelectVictim();
if (victim != null)
if (!me.HandleSpellFocus(null, true) && victim != me.GetVictim())
if (!me.HasSpellFocus() && victim != me.GetVictim())
AttackStart(victim);
return me.GetVictim() != null;
@@ -313,7 +313,7 @@ namespace Game.AI
me.ResetPlayerDamageReq();
me.SetLastDamagedTime(0);
me.SetCannotReachTarget(false);
me.DoNotReacquireTarget();
me.DoNotReacquireSpellFocusTarget();
EngagementOver();
return true;
@@ -27,11 +27,7 @@ namespace Game.Entities
CreatureTemplate m_creatureInfo;
CreatureData m_creatureData;
Spell _focusSpell; // Locks the target during spell cast for proper facing
uint _spellFocusDelay;
bool _shouldReacquireSpellFocusTarget;
ObjectGuid _suppressedSpellFocusTarget; // Stores the creature's "real" target while casting
float _suppressedSpellFocusOrientation; // Stores the creature's "real" orientation while casting
SpellFocusInfo _spellFocusInfo;
long _lastDamagedTime; // Part of Evade mechanics
MultiMap<byte, byte> m_textRepeat = new();
@@ -104,4 +100,12 @@ namespace Game.Entities
Active, // in move list
Inactive // in move list but should not move
}
struct SpellFocusInfo
{
public Spell spell;
public uint delay; // ms until the creature's target should snap back (0 = no snapback scheduled)
public ObjectGuid target; // the creature's "real" target while casting
public float orientation; // the creature's "real" orientation while casting
}
}
+58 -75
View File
@@ -532,23 +532,12 @@ namespace Game.Entities
GetThreatManager().Update(diff);
if (_shouldReacquireSpellFocusTarget && !HandleSpellFocus(null, true))
if (_spellFocusInfo.delay != 0)
{
SetTarget(_suppressedSpellFocusTarget);
if (!HasUnitFlag2(UnitFlags2.DisableTurn))
{
if (!_suppressedSpellFocusTarget.IsEmpty())
{
WorldObject objTarget = Global.ObjAccessor.GetWorldObject(this, _suppressedSpellFocusTarget);
if (objTarget)
SetFacingToObject(objTarget);
}
else
SetFacingTo(_suppressedSpellFocusOrientation);
}
_shouldReacquireSpellFocusTarget = false;
if (_spellFocusInfo.delay <= diff)
ReacquireSpellFocusTarget();
else
_spellFocusInfo.delay -= 0;
}
// periodic check to see if the creature has passed an evade boundary
@@ -932,7 +921,7 @@ namespace Game.Entities
if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target))
{
if (!HandleSpellFocus(null, true))
if (!HasSpellFocus())
SetInFront(target);
return target;
}
@@ -1121,7 +1110,7 @@ namespace Game.Entities
return true;
}
if (HasSpellFocusTarget())
if (HasSpellFocus())
return true;
if (HasUnitState(UnitState.Casting))
@@ -1820,8 +1809,8 @@ namespace Game.Entities
SaveRespawnTime();
ReleaseSpellFocus(null, false); // remove spellcast focus
DoNotReacquireTarget(); // cancel delayed re-target
SetTarget(ObjectGuid.Empty); // drop target - dead mobs shouldn't ever target things
DoNotReacquireSpellFocusTarget(); // cancel delayed re-target
SetTarget(ObjectGuid.Empty); // drop target - dead mobs shouldn't ever target things
SetNpcFlags(NPCFlags.None);
SetNpcFlags2(NPCFlags2.None);
@@ -2919,16 +2908,16 @@ namespace Game.Entities
public override void SetTarget(ObjectGuid guid)
{
if (HandleSpellFocus(null, true))
_suppressedSpellFocusTarget = guid;
if (HasSpellFocus())
_spellFocusInfo.target = guid;
else
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Target), guid);
}
public void SetSpellFocusTarget(Spell focusSpell, WorldObject target)
public void SetSpellFocus(Spell focusSpell, WorldObject target)
{
// already focused
if (_focusSpell != null)
if (_spellFocusInfo.spell != null)
return;
// Prevent dead/feigning death creatures from setting a focus target, so they won't turn
@@ -2953,14 +2942,17 @@ namespace Game.Entities
return;
// store pre-cast values for target and orientation (used to later restore)
if (!HandleSpellFocus(null, true))
if (_spellFocusInfo.delay == 0)
{ // only overwrite these fields if we aren't transitioning from one spell focus to another
_suppressedSpellFocusTarget = GetTarget();
_suppressedSpellFocusOrientation = GetOrientation();
_spellFocusInfo.target = GetTarget();
_spellFocusInfo.orientation = GetOrientation();
}
else // don't automatically reacquire target for the previous spellcast
_spellFocusInfo.delay = 0;
_focusSpell = focusSpell;
_spellFocusInfo.spell = focusSpell;
bool noTurnDuringCast = spellInfo.HasAttribute(SpellAttr5.DontTurnDuringCast);
// set target, then force send update packet to players if it changed to provide appropriate facing
ObjectGuid newTarget = target ? target.GetGUID() : ObjectGuid.Empty;
if (GetTarget() != newTarget)
@@ -2970,7 +2962,7 @@ namespace Game.Entities
// here we determine if the (relatively expensive) forced update is worth it, or whether we can afford to wait until the scheduled update tick
// only require instant update for spells that actually have a visual
if (spellInfo.GetSpellVisual() != 0 && (focusSpell.GetCastTime() == 0 || // if the spell is instant cast
spellInfo.HasAttribute(SpellAttr5.DontTurnDuringCast))) // client gets confused if we attempt to turn at the regularly scheduled update packet
noTurnDuringCast)) // client gets confused if we attempt to turn at the regularly scheduled update packet
{
List<Unit> playersNearby = GetPlayerListInGrid(GetVisibilityRange());
foreach (Player player in playersNearby)
@@ -2982,8 +2974,6 @@ namespace Game.Entities
}
}
bool noTurnDuringCast = spellInfo.HasAttribute(SpellAttr5.DontTurnDuringCast);
if (!HasUnitFlag2(UnitFlags2.DisableTurn))
{
// Face the target - we need to do this before the unit state is modified for no-turn spells
@@ -3001,75 +2991,68 @@ namespace Game.Entities
AddUnitState(UnitState.Focusing);
}
public override bool HandleSpellFocus(Spell focusSpell = null, bool withDelay = false)
public override bool HasSpellFocus(Spell focusSpell = null)
{
if (!IsAlive()) // dead creatures cannot focus
{
ReleaseSpellFocus(null, false);
if (_spellFocusInfo.spell != null || _spellFocusInfo.delay != 0)
Log.outWarn(LogFilter.Unit, $"Creature '{GetName()}' (entry {GetEntry()}) has spell focus (spell id {(_spellFocusInfo.spell != null ? _spellFocusInfo.spell.GetSpellInfo().Id : 0)}, delay {_spellFocusInfo.delay}ms) despite being dead.");
return false;
}
if (focusSpell && (focusSpell != _focusSpell))
return false;
if (!_focusSpell)
{
if (!withDelay || _spellFocusDelay == 0)
return false;
if (Time.GetMSTimeDiffToNow(_spellFocusDelay) > 1000) // @todo figure out if we can get rid of this magic number somehow
{
_spellFocusDelay = 0; // save checks in the future
return false;
}
}
return true;
if (focusSpell)
return focusSpell == _spellFocusInfo.spell;
else
return _spellFocusInfo.spell != null || _spellFocusInfo.delay != 0;
}
public void ReleaseSpellFocus(Spell focusSpell = null, bool withDelay = true)
{
if (_focusSpell == null)
if (!_spellFocusInfo.spell)
return;
// focused to something else
if (focusSpell && focusSpell != _focusSpell)
if (focusSpell && focusSpell != _spellFocusInfo.spell)
return;
if (IsPet() && !HasUnitFlag2(UnitFlags2.DisableTurn))// player pets do not use delay system
if (_spellFocusInfo.spell.GetSpellInfo().HasAttribute(SpellAttr5.DontTurnDuringCast))
ClearUnitState(UnitState.Focusing);
if (IsPet()) // player pets do not use delay system
{
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Target), _suppressedSpellFocusTarget);
if (!_suppressedSpellFocusTarget.IsEmpty())
if (!HasUnitFlag2(UnitFlags2.DisableTurn))
ReacquireSpellFocusTarget();
}
else // don't allow re-target right away to prevent visual bugs
_spellFocusInfo.delay = withDelay ? 1000 : 1u;
_spellFocusInfo.spell = null;
}
void ReacquireSpellFocusTarget()
{
if (!HasSpellFocus())
return;
SetTarget(_spellFocusInfo.target);
if (!HasUnitFlag2(UnitFlags2.DisableTurn))
{
if (!_spellFocusInfo.target.IsEmpty())
{
WorldObject objTarget = Global.ObjAccessor.GetWorldObject(this, _suppressedSpellFocusTarget);
WorldObject objTarget = Global.ObjAccessor.GetWorldObject(this, _spellFocusInfo.target);
if (objTarget)
SetFacingToObject(objTarget, false);
}
else
SetFacingTo(_suppressedSpellFocusOrientation, false);
SetFacingTo(_spellFocusInfo.orientation, false);
}
else
// tell the creature that it should reacquire its actual target after the delay expires (this is handled in ::Update)
// player pets don't need to do this, as they automatically reacquire their target on focus release
MustReacquireTarget();
if (_focusSpell.GetSpellInfo().HasAttribute(SpellAttr5.DontTurnDuringCast))
ClearUnitState(UnitState.Focusing);
_focusSpell = null;
_spellFocusDelay = (!IsPet() && withDelay) ? GameTime.GetGameTimeMS() : 0; // don't allow re-target right away to prevent visual bugs
_spellFocusInfo.delay = 0;
}
public override bool HasSpellFocusTarget() { return IsAlive() && (_focusSpell != null || _spellFocusDelay != 0); }
public void MustReacquireTarget() { _shouldReacquireSpellFocusTarget = true; } // flags the Creature for forced (client displayed) target reacquisition in the next Update call
public void DoNotReacquireTarget()
{
_shouldReacquireSpellFocusTarget = false;
_suppressedSpellFocusTarget = ObjectGuid.Empty;
SetTarget(ObjectGuid.Empty);
_suppressedSpellFocusOrientation = 0.0f;
}
public void DoNotReacquireSpellFocusTarget() { _spellFocusInfo.delay = 0; }
public ulong GetSpawnId() { return m_spawnId; }
+1 -3
View File
@@ -1041,9 +1041,7 @@ namespace Game.Entities
return 0;
}
public virtual bool HandleSpellFocus(Spell focusSpell = null, bool withDelay = false) { return false; }
public virtual bool HasSpellFocusTarget() { return false; }
public virtual bool HasSpellFocus(Spell focusSpell = null) { return false; }
/// <summary>
/// Check if our current channel spell has attribute SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
+2 -2
View File
@@ -327,7 +327,7 @@ namespace Game
Unit unit_target2 = spell.m_targets.GetUnitTarget();
if (unit_target)
{
if (!pet.HandleSpellFocus())
if (!pet.HasSpellFocus())
pet.SetInFront(unit_target);
Player player = unit_target.ToPlayer();
if (player)
@@ -335,7 +335,7 @@ namespace Game
}
else if (unit_target2)
{
if (!pet.HandleSpellFocus())
if (!pet.HasSpellFocus())
pet.SetInFront(unit_target2);
Player player = unit_target2.ToPlayer();
if (player)
+4 -4
View File
@@ -2343,9 +2343,9 @@ namespace Game.Spells
if (!(m_spellInfo.IsNextMeleeSwingSpell() || IsAutoRepeat()))
{
if (m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
m_caster.ToCreature().SetSpellFocusTarget(this, m_targets.GetObjectTarget());
m_caster.ToCreature().SetSpellFocus(this, m_targets.GetObjectTarget());
else if (m_spellInfo.HasAttribute(SpellAttr5.DontTurnDuringCast))
m_caster.ToCreature().SetSpellFocusTarget(this, null);
m_caster.ToCreature().SetSpellFocus(this, null);
}
}
@@ -3998,8 +3998,8 @@ namespace Game.Spells
{
Creature creatureCaster = unitCaster.ToCreature();
if (creatureCaster != null)
if (!creatureCaster.HandleSpellFocus(this))
creatureCaster.SetSpellFocusTarget(this, Global.ObjAccessor.GetWorldObject(creatureCaster, target.TargetGUID));
if (!creatureCaster.HasSpellFocus())
creatureCaster.SetSpellFocus(this, Global.ObjAccessor.GetWorldObject(creatureCaster, target.TargetGUID));
}
}
}