Core/Spells: SPELL_AURA_48 implementation

Port From (https://github.com/TrinityCore/TrinityCore/commit/37178ff311af95c4a2035a38839b5e8a9afe2af5)
This commit is contained in:
hondacrx
2022-01-06 00:17:58 -05:00
parent a4ace1e181
commit e89a36a232
6 changed files with 162 additions and 117 deletions
+108 -99
View File
@@ -1627,51 +1627,51 @@ namespace Game.Entities
switch (CSpellType) switch (CSpellType)
{ {
case CurrentSpellTypes.Generic: case CurrentSpellTypes.Generic:
{
// generic spells always break channeled not delayed spells
InterruptSpell(CurrentSpellTypes.Channeled, false);
// autorepeat breaking
if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null)
{ {
// generic spells always break channeled not delayed spells // break autorepeat if not Auto Shot
InterruptSpell(CurrentSpellTypes.Channeled, false); if (m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75)
// autorepeat breaking
if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null)
{
// break autorepeat if not Auto Shot
if (m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75)
InterruptSpell(CurrentSpellTypes.AutoRepeat);
m_AutoRepeatFirstCast = true;
}
if (pSpell.m_spellInfo.CalcCastTime() > 0)
AddUnitState(UnitState.Casting);
break;
}
case CurrentSpellTypes.Channeled:
{
// channel spells always break generic non-delayed and any channeled spells
InterruptSpell(CurrentSpellTypes.Generic, false);
InterruptSpell(CurrentSpellTypes.Channeled);
// it also does break autorepeat if not Auto Shot
if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null &&
m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75)
InterruptSpell(CurrentSpellTypes.AutoRepeat); InterruptSpell(CurrentSpellTypes.AutoRepeat);
m_AutoRepeatFirstCast = true;
}
if (pSpell.m_spellInfo.CalcCastTime() > 0)
AddUnitState(UnitState.Casting); AddUnitState(UnitState.Casting);
break; break;
} }
case CurrentSpellTypes.AutoRepeat: case CurrentSpellTypes.Channeled:
{ {
// only Auto Shoot does not break anything // channel spells always break generic non-delayed and any channeled spells
if (pSpell.m_spellInfo.Id != 75) InterruptSpell(CurrentSpellTypes.Generic, false);
{ InterruptSpell(CurrentSpellTypes.Channeled);
// generic autorepeats break generic non-delayed and channeled non-delayed spells
InterruptSpell(CurrentSpellTypes.Generic, false);
InterruptSpell(CurrentSpellTypes.Channeled, false);
}
// special action: set first cast flag
m_AutoRepeatFirstCast = true;
break; // it also does break autorepeat if not Auto Shot
if (GetCurrentSpell(CurrentSpellTypes.AutoRepeat) != null &&
m_currentSpells[CurrentSpellTypes.AutoRepeat].m_spellInfo.Id != 75)
InterruptSpell(CurrentSpellTypes.AutoRepeat);
AddUnitState(UnitState.Casting);
break;
}
case CurrentSpellTypes.AutoRepeat:
{
// only Auto Shoot does not break anything
if (pSpell.m_spellInfo.Id != 75)
{
// generic autorepeats break generic non-delayed and channeled non-delayed spells
InterruptSpell(CurrentSpellTypes.Generic, false);
InterruptSpell(CurrentSpellTypes.Channeled, false);
} }
// special action: set first cast flag
m_AutoRepeatFirstCast = true;
break;
}
default: default:
break; // other spell types don't break anything now break; // other spell types don't break anything now
} }
@@ -1948,74 +1948,74 @@ namespace Game.Entities
// Melee and Ranged Spells // Melee and Ranged Spells
case SpellDmgClass.Ranged: case SpellDmgClass.Ranged:
case SpellDmgClass.Melee: case SpellDmgClass.Melee:
{
// Physical Damage
if (damageSchoolMask.HasAnyFlag(SpellSchoolMask.Normal))
{ {
// Physical Damage // Spells with this attribute were already calculated in MeleeSpellHitResult
if (damageSchoolMask.HasAnyFlag(SpellSchoolMask.Normal)) if (!spellInfo.HasAttribute(SpellAttr3.BlockableSpell))
{ {
// Spells with this attribute were already calculated in MeleeSpellHitResult // Get blocked status
if (!spellInfo.HasAttribute(SpellAttr3.BlockableSpell)) blocked = IsSpellBlocked(victim, spellInfo, attackType);
{
// Get blocked status
blocked = IsSpellBlocked(victim, spellInfo, attackType);
}
} }
if (crit)
{
damageInfo.HitInfo |= HitInfo.CriticalHit;
// Calculate crit bonus
uint crit_bonus = (uint)damage;
// Apply crit_damage bonus for melee spells
Player modOwner = GetSpellModOwner();
if (modOwner != null)
modOwner.ApplySpellMod(spellInfo, SpellModOp.CritDamageAndHealing, ref crit_bonus);
damage += (int)crit_bonus;
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
float critPctDamageMod = (GetTotalAuraMultiplierByMiscMask(AuraType.ModCritDamageBonus, (uint)spellInfo.GetSchoolMask()) - 1.0f) * 100;
if (critPctDamageMod != 0)
MathFunctions.AddPct(ref damage, (int)critPctDamageMod);
}
// Spell weapon based damage CAN BE crit & blocked at same time
if (blocked)
{
// double blocked amount if block is critical
float value = victim.GetBlockPercent(GetLevel());
if (victim.IsBlockCritical())
value *= 2; // double blocked percent
damageInfo.blocked = (uint)MathFunctions.CalculatePct(damage, value);
if (damage <= damageInfo.blocked)
{
damageInfo.blocked = (uint)damage;
damageInfo.fullBlock = true;
}
damage -= (int)damageInfo.blocked;
}
if (CanApplyResilience())
ApplyResilience(victim, ref damage);
break;
} }
if (crit)
{
damageInfo.HitInfo |= HitInfo.CriticalHit;
// Calculate crit bonus
uint crit_bonus = (uint)damage;
// Apply crit_damage bonus for melee spells
Player modOwner = GetSpellModOwner();
if (modOwner != null)
modOwner.ApplySpellMod(spellInfo, SpellModOp.CritDamageAndHealing, ref crit_bonus);
damage += (int)crit_bonus;
// Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
float critPctDamageMod = (GetTotalAuraMultiplierByMiscMask(AuraType.ModCritDamageBonus, (uint)spellInfo.GetSchoolMask()) - 1.0f) * 100;
if (critPctDamageMod != 0)
MathFunctions.AddPct(ref damage, (int)critPctDamageMod);
}
// Spell weapon based damage CAN BE crit & blocked at same time
if (blocked)
{
// double blocked amount if block is critical
float value = victim.GetBlockPercent(GetLevel());
if (victim.IsBlockCritical())
value *= 2; // double blocked percent
damageInfo.blocked = (uint)MathFunctions.CalculatePct(damage, value);
if (damage <= damageInfo.blocked)
{
damageInfo.blocked = (uint)damage;
damageInfo.fullBlock = true;
}
damage -= (int)damageInfo.blocked;
}
if (CanApplyResilience())
ApplyResilience(victim, ref damage);
break;
}
// Magical Attacks // Magical Attacks
case SpellDmgClass.None: case SpellDmgClass.None:
case SpellDmgClass.Magic: case SpellDmgClass.Magic:
{
// If crit add critical bonus
if (crit)
{ {
// If crit add critical bonus damageInfo.HitInfo |= HitInfo.CriticalHit;
if (crit) damage = (int)SpellCriticalDamageBonus(this, spellInfo, (uint)damage, victim);
{
damageInfo.HitInfo |= HitInfo.CriticalHit;
damage = (int)SpellCriticalDamageBonus(this, spellInfo, (uint)damage, victim);
}
if (CanApplyResilience())
ApplyResilience(victim, ref damage);
break;
} }
if (CanApplyResilience())
ApplyResilience(victim, ref damage);
break;
}
default: default:
break; break;
} }
@@ -2568,7 +2568,7 @@ namespace Game.Entities
{ {
int[] bp = new int[SpellConst.MaxEffects]; int[] bp = new int[SpellConst.MaxEffects];
foreach (var spellEffectInfo in spellEntry.GetEffects()) foreach (var spellEffectInfo in spellEntry.GetEffects())
bp[spellEffectInfo.EffectIndex] = spellEffectInfo.BasePoints; bp[spellEffectInfo.EffectIndex] = spellEffectInfo.BasePoints;
bp[i] = seatId; bp[i] = seatId;
@@ -2678,6 +2678,15 @@ namespace Game.Entities
return false; return false;
} }
public bool HasAuraTypeWithTriggerSpell(AuraType auratype, uint triggerSpell)
{
foreach (var aura in GetAuraEffectsByType(auratype))
if (aura.GetSpellEffectInfo().TriggerSpell == triggerSpell)
return true;
return false;
}
public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags flag, ObjectGuid guid = default) public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags flag, ObjectGuid guid = default)
{ {
if (!HasInterruptFlag(flag)) if (!HasInterruptFlag(flag))
+22 -5
View File
@@ -677,13 +677,30 @@ namespace Game
return; return;
} }
// do not cast not learned spells
if (!caster.HasSpell(spellInfo.Id) || spellInfo.IsPassive())
return;
SpellCastTargets targets = new(caster, petCastSpell.Cast); SpellCastTargets targets = new(caster, petCastSpell.Cast);
Spell spell = new(caster, spellInfo, TriggerCastFlags.None); TriggerCastFlags triggerCastFlags = TriggerCastFlags.None;
if (spellInfo.IsPassive())
return;
// cast only learned spells
if (!caster.HasSpell(spellInfo.Id))
{
bool allow = false;
// allow casting of spells triggered by clientside periodic trigger auras
if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id))
{
allow = true;
triggerCastFlags = TriggerCastFlags.FullMask;
}
if (!allow)
return;
}
Spell spell = new(caster, spellInfo, triggerCastFlags);
spell.m_fromClient = true; spell.m_fromClient = true;
spell.m_misc.Data0 = petCastSpell.Cast.Misc[0]; spell.m_misc.Data0 = petCastSpell.Cast.Misc[0];
spell.m_misc.Data1 = petCastSpell.Cast.Misc[1]; spell.m_misc.Data1 = petCastSpell.Cast.Misc[1];
+2 -5
View File
@@ -314,15 +314,12 @@ namespace Game
if (go.GetSpellForLock(caster.ToPlayer()) == spellInfo) if (go.GetSpellForLock(caster.ToPlayer()) == spellInfo)
allow = true; allow = true;
// TODO: Preparation for #23204
// allow casting of spells triggered by clientside periodic trigger auras // allow casting of spells triggered by clientside periodic trigger auras
/* if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id))
if (caster->HasAuraTypeWithTriggerSpell(SPELL_AURA_PERIODIC_TRIGGER_SPELL_FROM_CLIENT, spellId))
{ {
allow = true; allow = true;
triggerFlag = TRIGGERED_FULL_MASK; triggerFlag = TriggerCastFlags.FullMask;
} }
*/
if (!allow) if (!allow)
return; return;
+4
View File
@@ -188,6 +188,7 @@ namespace Game.Spells
case AuraType.PeriodicHeal: case AuraType.PeriodicHeal:
case AuraType.ObsModHealth: case AuraType.ObsModHealth:
case AuraType.PeriodicTriggerSpell: case AuraType.PeriodicTriggerSpell:
case AuraType.PeriodicTriggerSpellFromClient:
case AuraType.PeriodicEnergize: case AuraType.PeriodicEnergize:
case AuraType.PeriodicLeech: case AuraType.PeriodicLeech:
case AuraType.PeriodicHealthFunnel: case AuraType.PeriodicHealthFunnel:
@@ -520,6 +521,9 @@ namespace Game.Spells
case AuraType.PeriodicTriggerSpell: case AuraType.PeriodicTriggerSpell:
HandlePeriodicTriggerSpellAuraTick(target, caster); HandlePeriodicTriggerSpellAuraTick(target, caster);
break; break;
case AuraType.PeriodicTriggerSpellFromClient:
// Don't actually do anything - client will trigger casts of these spells by itself
break;
case AuraType.PeriodicTriggerSpellWithValue: case AuraType.PeriodicTriggerSpellWithValue:
HandlePeriodicTriggerSpellWithValueAuraTick(target, caster); HandlePeriodicTriggerSpellWithValueAuraTick(target, caster);
break; break;
+2 -1
View File
@@ -2705,7 +2705,7 @@ namespace Game.Spells
case AuraType.PeriodicHeal: case AuraType.PeriodicHeal:
case AuraType.ObsModHealth: case AuraType.ObsModHealth:
case AuraType.ObsModPower: case AuraType.ObsModPower:
case AuraType.Unk48: case AuraType.PeriodicTriggerSpellFromClient:
case AuraType.PowerBurn: case AuraType.PowerBurn:
case AuraType.PeriodicLeech: case AuraType.PeriodicLeech:
case AuraType.PeriodicManaLeech: case AuraType.PeriodicManaLeech:
@@ -3530,6 +3530,7 @@ namespace Game.Spells
case AuraType.AddTargetTrigger: case AuraType.AddTargetTrigger:
return true; return true;
case AuraType.PeriodicTriggerSpellWithValue: case AuraType.PeriodicTriggerSpellWithValue:
case AuraType.PeriodicTriggerSpellFromClient:
case AuraType.PeriodicTriggerSpell: case AuraType.PeriodicTriggerSpell:
if (!_isPositiveTarget(effect)) if (!_isPositiveTarget(effect))
{ {
+18 -1
View File
@@ -2935,6 +2935,7 @@ namespace Game.Entities
switch (spellEffectInfo.ApplyAuraName) switch (spellEffectInfo.ApplyAuraName)
{ {
case AuraType.PeriodicTriggerSpell: case AuraType.PeriodicTriggerSpell:
case AuraType.PeriodicTriggerSpellFromClient:
case AuraType.PeriodicTriggerSpellWithValue: case AuraType.PeriodicTriggerSpellWithValue:
SpellInfo triggerSpell = Global.SpellMgr.GetSpellInfo(spellEffectInfo.TriggerSpell, Difficulty.None); SpellInfo triggerSpell = Global.SpellMgr.GetSpellInfo(spellEffectInfo.TriggerSpell, Difficulty.None);
if (triggerSpell != null) if (triggerSpell != null)
@@ -3257,7 +3258,8 @@ namespace Game.Entities
43109, // Throw Torch 43109, // Throw Torch
58552, // Return to Orgrimmar 58552, // Return to Orgrimmar
58533, // Return to Stormwind 58533, // Return to Stormwind
21855 // Challenge Flag 21855, // Challenge Flag
51122 // Fierce Lightning Stike
}, spellInfo => }, spellInfo =>
{ {
spellInfo.MaxAffectedTargets = 1; spellInfo.MaxAffectedTargets = 1;
@@ -3578,6 +3580,14 @@ namespace Game.Entities
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(13); // 50000yd spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(13); // 50000yd
}); });
ApplySpellFix(new[] {
44327, // Trained Rock Falcon/Hawk Hunting
44408 // Trained Rock Falcon/Hawk Hunting
}, spellInfo =>
{
spellInfo.Speed = 0.0f;
});
// Summon Corpse Scarabs // Summon Corpse Scarabs
ApplySpellFix(new[] { 28864, 29105 }, spellInfo => ApplySpellFix(new[] { 28864, 29105 }, spellInfo =>
{ {
@@ -3917,6 +3927,13 @@ namespace Game.Entities
}); });
}); });
// Mutated Transformation (Professor Putricide)
ApplySpellFix(new[] { 70402 }, spellInfo =>
{
// Resistance is calculated inside of SpellScript
spellInfo.AttributesEx4 |= SpellAttr4.IgnoreResistances;
});
// Empowered Flare (Blood Prince Council) // Empowered Flare (Blood Prince Council)
ApplySpellFix(new[] { 71708 }, spellInfo => ApplySpellFix(new[] { 71708 }, spellInfo =>
{ {