Core/Spells: Autorepeat casting fixes

Port From (https://github.com/TrinityCore/TrinityCore/commit/de592386dcd6ac85feb11d2af85538d62c192696)
This commit is contained in:
hondacrx
2022-06-01 16:28:01 -04:00
parent e9fcfd6f26
commit 95d134b512
5 changed files with 32 additions and 32 deletions
-1
View File
@@ -92,7 +92,6 @@ namespace Game.Entities
SpellAuraInterruptFlags m_interruptMask; SpellAuraInterruptFlags m_interruptMask;
SpellAuraInterruptFlags2 m_interruptMask2; SpellAuraInterruptFlags2 m_interruptMask2;
protected int m_procDeep; protected int m_procDeep;
bool m_AutoRepeatFirstCast;
SpellHistory _spellHistory; SpellHistory _spellHistory;
//Auras //Auras
+5 -7
View File
@@ -1627,14 +1627,13 @@ namespace Game.Entities
if (pSpell == GetCurrentSpell(CSpellType)) // avoid breaking self if (pSpell == GetCurrentSpell(CSpellType)) // avoid breaking self
return; return;
// break same type spell if it is not delayed
InterruptSpell(CSpellType, false);
// special breakage effects: // special breakage effects:
switch (CSpellType) switch (CSpellType)
{ {
case CurrentSpellTypes.Generic: case CurrentSpellTypes.Generic:
{ {
InterruptSpell(CurrentSpellTypes.Generic, false);
// generic spells always break channeled not delayed spells // generic spells always break channeled not delayed spells
if (GetCurrentSpell(CurrentSpellTypes.Channeled) != null && !GetCurrentSpell(CurrentSpellTypes.Channeled).GetSpellInfo().HasAttribute(SpellAttr5.AllowActionsDuringChannel)) if (GetCurrentSpell(CurrentSpellTypes.Channeled) != null && !GetCurrentSpell(CurrentSpellTypes.Channeled).GetSpellInfo().HasAttribute(SpellAttr5.AllowActionsDuringChannel))
InterruptSpell(CurrentSpellTypes.Channeled, false); InterruptSpell(CurrentSpellTypes.Channeled, false);
@@ -1645,7 +1644,6 @@ namespace Game.Entities
// break autorepeat if not Auto Shot // break autorepeat if not Auto Shot
if (m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75) if (m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75)
InterruptSpell(CurrentSpellTypes.AutoRepeat); InterruptSpell(CurrentSpellTypes.AutoRepeat);
m_AutoRepeatFirstCast = true;
} }
if (pSpell.m_spellInfo.CalcCastTime() > 0) if (pSpell.m_spellInfo.CalcCastTime() > 0)
AddUnitState(UnitState.Casting); AddUnitState(UnitState.Casting);
@@ -1668,6 +1666,9 @@ namespace Game.Entities
} }
case CurrentSpellTypes.AutoRepeat: case CurrentSpellTypes.AutoRepeat:
{ {
if (GetCurrentSpell(CSpellType) && GetCurrentSpell(CSpellType).GetState() == SpellState.Idle)
GetCurrentSpell(CSpellType).SetState(SpellState.Finished);
// only Auto Shoot does not break anything // only Auto Shoot does not break anything
if (pSpell.m_spellInfo.Id != 75) if (pSpell.m_spellInfo.Id != 75)
{ {
@@ -1675,9 +1676,6 @@ namespace Game.Entities
InterruptSpell(CurrentSpellTypes.Generic, false); InterruptSpell(CurrentSpellTypes.Generic, false);
InterruptSpell(CurrentSpellTypes.Channeled, false); InterruptSpell(CurrentSpellTypes.Channeled, false);
} }
// special action: set first cast flag
m_AutoRepeatFirstCast = true;
break; break;
} }
default: default:
+4 -13
View File
@@ -215,6 +215,8 @@ namespace Game.Entities
void _UpdateSpells(uint diff) void _UpdateSpells(uint diff)
{ {
_spellHistory.Update();
if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null) if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null)
_UpdateAutoRepeatSpell(); _UpdateAutoRepeatSpell();
@@ -264,8 +266,6 @@ namespace Game.Entities
} }
} }
} }
_spellHistory.Update();
} }
public void HandleEmoteCommand(Emote emoteId, Player target = null, uint[] spellVisualKitIds = null, int sequenceVariation = 0) public void HandleEmoteCommand(Emote emoteId, Player target = null, uint[] spellVisualKitIds = null, int sequenceVariation = 0)
@@ -1568,17 +1568,11 @@ namespace Game.Entities
// cancel wand shoot // cancel wand shoot
if (autoRepeatSpellInfo.Id != 75) if (autoRepeatSpellInfo.Id != 75)
InterruptSpell(CurrentSpellTypes.AutoRepeat); InterruptSpell(CurrentSpellTypes.AutoRepeat);
m_AutoRepeatFirstCast = true;
return; return;
} }
// apply delay (Auto Shot (spellID 75) not affected)
if (m_AutoRepeatFirstCast && GetAttackTimer(WeaponAttackType.RangedAttack) < 500 && autoRepeatSpellInfo.Id != 75)
SetAttackTimer(WeaponAttackType.RangedAttack, 500);
m_AutoRepeatFirstCast = false;
// castroutine // castroutine
if (IsAttackReady(WeaponAttackType.RangedAttack)) if (IsAttackReady(WeaponAttackType.RangedAttack) && GetCurrentSpell(CurrentSpellTypes.AutoRepeat).GetState() != SpellState.Preparing)
{ {
// Check if able to cast // Check if able to cast
SpellCastResult result = m_currentSpells[CurrentSpellTypes.AutoRepeat].CheckCast(true); SpellCastResult result = m_currentSpells[CurrentSpellTypes.AutoRepeat].CheckCast(true);
@@ -1593,11 +1587,8 @@ namespace Game.Entities
} }
// we want to shoot // we want to shoot
Spell spell = new(this, autoRepeatSpellInfo, TriggerCastFlags.FullMask); Spell spell = new(this, autoRepeatSpellInfo, TriggerCastFlags.IgnoreGCD);
spell.Prepare(m_currentSpells[CurrentSpellTypes.AutoRepeat].m_targets); spell.Prepare(m_currentSpells[CurrentSpellTypes.AutoRepeat].m_targets);
// all went good, reset attack
ResetAttackTimer(WeaponAttackType.RangedAttack);
} }
} }
+23 -6
View File
@@ -2474,7 +2474,7 @@ namespace Game.Spells
// handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks // handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks
if (Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreTargetCheck) && result == SpellCastResult.BadTargets) if (Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreTargetCheck) && result == SpellCastResult.BadTargets)
result = SpellCastResult.SpellCastOk; result = SpellCastResult.SpellCastOk;
if (result != SpellCastResult.SpellCastOk && !IsAutoRepeat()) //always cast autorepeat dummy for triggering if (result != SpellCastResult.SpellCastOk)
{ {
// Periodic auras should be interrupted when aura triggers a spell which can't be cast // Periodic auras should be interrupted when aura triggers a spell which can't be cast
// for example bladestorm aura should be removed on disarm as of patch 3.3.5 // for example bladestorm aura should be removed on disarm as of patch 3.3.5
@@ -2491,6 +2491,10 @@ namespace Game.Spells
else else
SendCastResult(result); SendCastResult(result);
// queue autorepeat spells for future repeating
if (GetCurrentContainer() == CurrentSpellTypes.AutoRepeat && m_caster.IsUnit())
m_caster.ToUnit().SetCurrentCastSpell(this);
Finish(false); Finish(false);
return result; return result;
} }
@@ -3259,6 +3263,9 @@ namespace Game.Spells
m_caster.ToUnit().GetSpellHistory().HandleCooldowns(m_spellInfo, m_CastItem, this); m_caster.ToUnit().GetSpellHistory().HandleCooldowns(m_spellInfo, m_CastItem, this);
else else
m_caster.ToUnit().GetSpellHistory().HandleCooldowns(m_spellInfo, m_castItemEntry, this); m_caster.ToUnit().GetSpellHistory().HandleCooldowns(m_spellInfo, m_castItemEntry, this);
if (IsAutoRepeat())
m_caster.ToUnit().ResetAttackTimer(WeaponAttackType.RangedAttack);
} }
public void Update(uint difftime) public void Update(uint difftime)
@@ -3300,7 +3307,7 @@ namespace Game.Spells
m_timer -= (int)difftime; m_timer -= (int)difftime;
} }
if (m_timer == 0 && !m_spellInfo.IsNextMeleeSwingSpell() && !IsAutoRepeat()) if (m_timer == 0 && !m_spellInfo.IsNextMeleeSwingSpell())
// don't CheckCast for instant spells - done in spell.prepare, skip duplicate checks, needed for range checks for example // don't CheckCast for instant spells - done in spell.prepare, skip duplicate checks, needed for range checks for example
Cast(m_casttime == 0); Cast(m_casttime == 0);
break; break;
@@ -3365,6 +3372,10 @@ namespace Game.Spells
if (unitCaster != null) if (unitCaster != null)
return; return;
// successful cast of the initial autorepeat spell is moved to idle state so that it is not deleted as long as autorepeat is active
if (IsAutoRepeat() && unitCaster.GetCurrentSpell(CurrentSpellTypes.AutoRepeat) == this)
m_spellState = SpellState.Idle;
if (m_spellInfo.IsChanneled()) if (m_spellInfo.IsChanneled())
unitCaster.UpdateInterruptMask(); unitCaster.UpdateInterruptMask();
@@ -4651,12 +4662,18 @@ namespace Game.Spells
return SpellCastResult.NotReady; return SpellCastResult.NotReady;
} }
if (!IsIgnoringCooldowns() && m_caster.ToUnit() != null && !m_caster.ToUnit().GetSpellHistory().IsReady(m_spellInfo, m_castItemEntry)) if (!IsIgnoringCooldowns() && m_caster.ToUnit() != null)
{ {
if (m_triggeredByAuraSpell != null) if (!m_caster.ToUnit().GetSpellHistory().IsReady(m_spellInfo, m_castItemEntry))
{
if (m_triggeredByAuraSpell != null)
return SpellCastResult.DontReport;
else
return SpellCastResult.NotReady;
}
if ((IsAutoRepeat() || m_spellInfo.CategoryId == 76) && !m_caster.ToUnit().IsAttackReady(WeaponAttackType.RangedAttack))
return SpellCastResult.DontReport; return SpellCastResult.DontReport;
else
return SpellCastResult.NotReady;
} }
} }
-5
View File
@@ -365,11 +365,6 @@ namespace Game.Spells
{ {
if (!forcedCooldown.HasValue) if (!forcedCooldown.HasValue)
{ {
// shoot spells used equipped item cooldown values already assigned in SetBaseAttackTime(RANGED_ATTACK)
// prevent 0 cooldowns set by another way
if (cooldown <= TimeSpan.Zero && categoryCooldown <= TimeSpan.Zero && (categoryId == 76 || (spellInfo.IsAutoRepeatRangedSpell() && spellInfo.Id != 75)))
cooldown = TimeSpan.FromMilliseconds(_owner.m_unitData.RangedAttackRoundBaseTime);
// Now we have cooldown data (if found any), time to apply mods // Now we have cooldown data (if found any), time to apply mods
Player modOwner = _owner.GetSpellModOwner(); Player modOwner = _owner.GetSpellModOwner();
if (modOwner) if (modOwner)