diff --git a/Source/Framework/Constants/ScriptsConst.cs b/Source/Framework/Constants/ScriptsConst.cs index ba61b434f..cfca4b5db 100644 --- a/Source/Framework/Constants/ScriptsConst.cs +++ b/Source/Framework/Constants/ScriptsConst.cs @@ -45,7 +45,8 @@ namespace Framework.Constants OnResistAbsorbCalculation, AfterCast, CalcCritChance, - OnPrecast + OnPrecast, + CalcCastTime } // AuraScript interface - enum used for runtime checks of script function calls diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 58d361735..0920fdbba 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1887,8 +1887,9 @@ namespace Game.Entities if (!unitCaster) return; - if (!(spellInfo.HasAttribute(SpellAttr0.IsAbility) || spellInfo.HasAttribute(SpellAttr0.IsTradeskill) || spellInfo.HasAttribute(SpellAttr3.IgnoreCasterModifiers)) && - ((IsPlayer() && spellInfo.SpellFamilyName != 0) || IsCreature())) + if (unitCaster.IsPlayer() && unitCaster.ToPlayer().GetCommandStatus(PlayerCommandStates.Casttime)) + castTime = 0; + else if (!(spellInfo.HasAttribute(SpellAttr0.IsAbility) || spellInfo.HasAttribute(SpellAttr0.IsTradeskill) || spellInfo.HasAttribute(SpellAttr3.IgnoreCasterModifiers)) && ((IsPlayer() && spellInfo.SpellFamilyName != 0) || IsCreature())) castTime = unitCaster.CanInstantCast() ? 0 : (int)(castTime * unitCaster.m_unitData.ModCastingSpeed); else if (spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) && !spellInfo.HasAttribute(SpellAttr2.AutoRepeat)) castTime = (int)(castTime * unitCaster.m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]); diff --git a/Source/Game/Scripting/SpellScript.cs b/Source/Game/Scripting/SpellScript.cs index 41841a0f2..0f2dd5105 100644 --- a/Source/Game/Scripting/SpellScript.cs +++ b/Source/Game/Scripting/SpellScript.cs @@ -517,6 +517,9 @@ namespace Game.Scripting // where function is SpellCastResult function() public List OnCheckCast = new(); + // example: int32 CalcCastTime(int32 castTime) override { return 1500; } + public virtual int CalcCastTime(int castTime) { return castTime; } + // where function is void function(DamageInfo damageInfo, ref uint resistAmount, ref int absorbAmount) public List OnCalculateResistAbsorb = new(); diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index fdb4c0585..14b6e50ee 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -2505,18 +2505,7 @@ namespace Game.Spells // Prepare data for triggers PrepareDataForTriggerSystem(); - if (m_caster.IsTypeId(TypeId.Player)) - { - if (!m_caster.ToPlayer().GetCommandStatus(PlayerCommandStates.Casttime)) - { - // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) - m_casttime = m_spellInfo.CalcCastTime(this); - } - else - m_casttime = 0; - } - else - m_casttime = m_spellInfo.CalcCastTime(this); + m_casttime = CallScriptCalcCastTimeHandlers(m_spellInfo.CalcCastTime(this)); if (m_caster.IsUnit() && m_caster.ToUnit().IsMoving()) { @@ -7462,6 +7451,17 @@ namespace Game.Spells return retVal; } + int CallScriptCalcCastTimeHandlers(int castTime) + { + foreach (var script in m_loadedScripts) + { + script._PrepareScriptCall(SpellScriptHookType.CalcCastTime); + castTime = script.CalcCastTime(castTime); + script._FinishScriptCall(); + } + return castTime; + } + bool CallScriptEffectHandlers(uint effIndex, SpellEffectHandleMode mode) { // execute script effect handler hooks and check if effects was prevented