Core/Spells: Named and implemented most of SpellAttr8
Port From (https://github.com/TrinityCore/TrinityCore/commit/dc9361fcc2eb16a59b52dfd8b0d47dfc1bf639be)
This commit is contained in:
@@ -143,7 +143,7 @@ namespace Game.Spells
|
||||
|
||||
bool effectNeedsAmount(AuraEffect effect) => effect != null && (GetEffectsToApply() & (1 << (int)effect.GetEffIndex())) != 0 && Aura.EffectTypeNeedsSendingAmount(effect.GetAuraType());
|
||||
|
||||
if (GetBase().GetSpellInfo().HasAttribute(SpellAttr8.AuraSendAmount) || GetBase().GetAuraEffects().Any(effectNeedsAmount))
|
||||
if (GetBase().GetSpellInfo().HasAttribute(SpellAttr8.AuraPointsOnClient) || GetBase().GetAuraEffects().Any(effectNeedsAmount))
|
||||
_flags |= AuraFlags.Scalable;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Game.Spells
|
||||
// default amount calculation
|
||||
int amount = 0;
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr8.MasteryAffectPoints) || MathFunctions.fuzzyEq(GetSpellEffectInfo().BonusCoefficient, 0.0f))
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr8.MasteryAffectsPoints) || MathFunctions.fuzzyEq(GetSpellEffectInfo().BonusCoefficient, 0.0f))
|
||||
amount = GetSpellEffectInfo().CalcValue(caster, m_baseAmount, GetBase().GetOwner().ToUnit(), GetBase().GetCastItemId(), GetBase().GetCastItemLevel());
|
||||
else if (caster != null && caster.IsTypeId(TypeId.Player))
|
||||
amount = (int)(caster.ToPlayer().m_activePlayerData.Mastery * GetSpellEffectInfo().BonusCoefficient);
|
||||
@@ -169,6 +169,8 @@ namespace Game.Spells
|
||||
caster.ModSpellDurationTime(spellInfo, ref period);
|
||||
else if (spellInfo.HasAttribute(SpellAttr5.SpellHasteAffectsPeriodic))
|
||||
period = (int)(period * caster.m_unitData.ModCastingSpeed);
|
||||
else if (spellInfo.HasAttribute(SpellAttr8.MeleeHasteAffectsPeriodic))
|
||||
period = (int)(period * caster.m_unitData.ModHaste);
|
||||
|
||||
if (period == 0)
|
||||
return 0.0f;
|
||||
@@ -179,7 +181,7 @@ namespace Game.Spells
|
||||
|
||||
return totalTicks * CalculateEstimatedAmount(caster, target, spellInfo, spellEffectInfo, (int)amount, stack, null).GetValueOrDefault(amount);
|
||||
}
|
||||
|
||||
|
||||
public uint GetTotalTicks()
|
||||
{
|
||||
uint totalTicks = 0;
|
||||
@@ -252,6 +254,8 @@ namespace Game.Spells
|
||||
caster.ModSpellDurationTime(m_spellInfo, ref _period);
|
||||
else if (m_spellInfo.HasAttribute(SpellAttr5.SpellHasteAffectsPeriodic))
|
||||
_period = (int)(_period * caster.m_unitData.ModCastingSpeed);
|
||||
else if (m_spellInfo.HasAttribute(SpellAttr8.MeleeHasteAffectsPeriodic))
|
||||
_period = (int)(_period * caster.m_unitData.ModHaste);
|
||||
}
|
||||
}
|
||||
else // prevent infinite loop on Update
|
||||
@@ -365,7 +369,7 @@ namespace Game.Spells
|
||||
HandleEffect(aurApp, handleMask, true, triggeredBy);
|
||||
}
|
||||
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr8.AuraSendAmount) || Aura.EffectTypeNeedsSendingAmount(GetAuraType()))
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr8.AuraPointsOnClient) || Aura.EffectTypeNeedsSendingAmount(GetAuraType()))
|
||||
GetBase().SetNeedClientUpdateForTargets();
|
||||
}
|
||||
|
||||
@@ -2519,7 +2523,7 @@ namespace Game.Spells
|
||||
if (!apply && !target.IsFlying())
|
||||
target.GetMotionMaster().MoveFall();
|
||||
}
|
||||
|
||||
|
||||
[AuraEffectHandler(AuraType.ModStunDisableGravity)]
|
||||
void HandleAuraModStunAndDisableGravity(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
|
||||
{
|
||||
@@ -4826,7 +4830,7 @@ namespace Game.Spells
|
||||
uint casterType = (uint)GetMiscValue();
|
||||
if (casterType > 0)
|
||||
caster = GetCaster();
|
||||
|
||||
|
||||
caster?.CastSpell(aurApp.GetTarget(), GetSpellEffectInfo().TriggerSpell, new CastSpellExtraArgs(this));
|
||||
}
|
||||
|
||||
@@ -5558,6 +5562,8 @@ namespace Game.Spells
|
||||
{
|
||||
Unit triggerCaster = aurApp.GetTarget();
|
||||
Unit triggerTarget = eventInfo.GetProcTarget();
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr8.TargetProcsOnCaster) && eventInfo.GetTypeMask().HasFlag(ProcFlags.TakenHitMask))
|
||||
triggerTarget = eventInfo.GetActor();
|
||||
|
||||
uint triggerSpellId = GetSpellEffectInfo().TriggerSpell;
|
||||
if (triggerSpellId == 0)
|
||||
@@ -5580,6 +5586,8 @@ namespace Game.Spells
|
||||
{
|
||||
Unit triggerCaster = aurApp.GetTarget();
|
||||
Unit triggerTarget = eventInfo.GetProcTarget();
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr8.TargetProcsOnCaster) && eventInfo.GetTypeMask().HasFlag(ProcFlags.TakenHitMask))
|
||||
triggerTarget = eventInfo.GetActor();
|
||||
|
||||
uint triggerSpellId = GetSpellEffectInfo().TriggerSpell;
|
||||
if (triggerSpellId == 0)
|
||||
@@ -5993,7 +6001,7 @@ namespace Game.Spells
|
||||
playerTarget.ReplaceAllRequiredMountCapabilityFlags((byte)mountCapabilityFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[AuraEffectHandler(AuraType.SuppressItemPassiveEffectBySpellLabel)]
|
||||
void HandleSuppressItemPassiveEffectBySpellLabel(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
|
||||
{
|
||||
|
||||
+126
-28
@@ -305,6 +305,21 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_targets.HasDst())
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr8.RequiresLocationToBeOnLiquidSurface))
|
||||
{
|
||||
ZLiquidStatus status = m_caster.GetMap().GetLiquidStatus(m_caster.GetPhaseShift(), m_targets.GetDstPos().GetPositionX(), m_targets.GetDstPos().GetPositionY(), m_targets.GetDstPos().GetPositionZ(), LiquidHeaderTypeFlags.AllLiquids);
|
||||
if (!status.HasAnyFlag(ZLiquidStatus.WaterWalk | ZLiquidStatus.InWater))
|
||||
{
|
||||
SendCastResult(SpellCastResult.NoLiquid);
|
||||
Finish(SpellCastResult.NoLiquid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ulong dstDelay = CalculateDelayMomentForDst(m_spellInfo.LaunchDelay);
|
||||
if (dstDelay != 0)
|
||||
m_delayMoment = dstDelay;
|
||||
@@ -3806,6 +3821,9 @@ namespace Game.Spells
|
||||
if (HasPowerTypeCost(PowerType.Runes))
|
||||
castFlags |= SpellCastFlags.NoGCD; // not needed, but Blizzard sends it
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr8.HealPrediction) && m_casttime != 0 && m_caster.IsUnit())
|
||||
castFlags |= SpellCastFlags.HealPrediction;
|
||||
|
||||
SpellStart packet = new();
|
||||
SpellCastData castData = packet.Cast;
|
||||
|
||||
@@ -3874,13 +3892,7 @@ namespace Game.Spells
|
||||
castData.Immunities.Value = (uint)mechanicImmunityMask;
|
||||
}
|
||||
|
||||
/** @todo implement heal prediction packet data
|
||||
if (castFlags & CAST_FLAG_HEAL_PREDICTION)
|
||||
{
|
||||
castData.Predict.BeconGUID = ??
|
||||
castData.Predict.Points = 0;
|
||||
castData.Predict.Type = 0;
|
||||
}**/
|
||||
UpdateSpellHealPrediction(castData.Predict, false);
|
||||
|
||||
m_caster.SendMessageToSet(packet, true);
|
||||
}
|
||||
@@ -4093,6 +4105,77 @@ namespace Game.Spells
|
||||
return ammoDisplayID;
|
||||
}
|
||||
|
||||
static (int, SpellHealPredictionType) CalcPredictedHealing(SpellInfo spellInfo, Unit unitCaster, Unit target, uint castItemEntry, int castItemLevel, Spell spell, bool withPeriodic)
|
||||
{
|
||||
int points = 0;
|
||||
SpellHealPredictionType type = SpellHealPredictionType.Target;
|
||||
foreach (SpellEffectInfo spellEffectInfo in spellInfo.GetEffects())
|
||||
{
|
||||
switch (spellEffectInfo.Effect)
|
||||
{
|
||||
case SpellEffectName.Heal:
|
||||
case SpellEffectName.HealPct:
|
||||
points += unitCaster.SpellHealingBonusDone(target, spellInfo, spellEffectInfo.CalcValue(unitCaster, null, target, castItemEntry, castItemLevel), DamageEffectType.Direct, spellEffectInfo, 1, spell);
|
||||
|
||||
if (target != unitCaster && (spellEffectInfo.TargetA.GetTarget() == Targets.UnitCaster || spellEffectInfo.TargetB.GetTarget() == Targets.UnitCaster))
|
||||
type = SpellHealPredictionType.TargetAndCaster; // Binding Heal-like spells
|
||||
else if (spellEffectInfo.TargetA.GetCheckType() == SpellTargetCheckTypes.Party || spellEffectInfo.TargetB.GetCheckType() == SpellTargetCheckTypes.Party)
|
||||
type = SpellHealPredictionType.TargetParty; // Prayer of Healing (old party-wide targeting)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (withPeriodic)
|
||||
{
|
||||
switch (spellEffectInfo.ApplyAuraName)
|
||||
{
|
||||
case AuraType.PeriodicHeal:
|
||||
case AuraType.ObsModHealth:
|
||||
points += (int)(unitCaster.SpellHealingBonusDone(target, spellInfo, spellEffectInfo.CalcValue(unitCaster, null, target, castItemEntry, castItemLevel), DamageEffectType.Direct, spellEffectInfo, 1, spell) * spellInfo.GetMaxTicks());
|
||||
break;
|
||||
case AuraType.PeriodicTriggerSpell:
|
||||
SpellInfo triggered = Global.SpellMgr.GetSpellInfo(spellEffectInfo.TriggerSpell, spellInfo.Difficulty);
|
||||
if (triggered != null)
|
||||
points += CalcPredictedHealing(triggered, unitCaster, target, castItemEntry, castItemLevel, null, withPeriodic).Item1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (points, type);
|
||||
}
|
||||
|
||||
void UpdateSpellHealPrediction(SpellHealPrediction healPrediction, bool withPeriodic)
|
||||
{
|
||||
healPrediction.BeaconGUID = ObjectGuid.Empty;
|
||||
healPrediction.Points = 0;
|
||||
healPrediction.Type = SpellHealPredictionType.Target;
|
||||
|
||||
Unit unitCaster = m_caster.ToUnit();
|
||||
Unit target = m_targets.GetUnitTarget();
|
||||
if (target != null)
|
||||
{
|
||||
var (points, type) = CalcPredictedHealing(m_spellInfo, unitCaster, target, m_castItemEntry, m_castItemLevel, this, withPeriodic);
|
||||
healPrediction.Points = (uint)points;
|
||||
healPrediction.Type = type;
|
||||
}
|
||||
|
||||
uint beaconSpellId = 53651;
|
||||
|
||||
if (healPrediction.Type == SpellHealPredictionType.Target && unitCaster.HasAura(beaconSpellId, unitCaster.GetGUID()))
|
||||
{
|
||||
var beacon = unitCaster.GetSingleCastAuras().Find(aura => aura.GetSpellInfo().GetEffects().Count > 1 && aura.GetSpellInfo().GetEffect(1).TriggerSpell == beaconSpellId);
|
||||
if (beacon != null)
|
||||
{
|
||||
healPrediction.BeaconGUID = beacon.GetOwner().GetGUID();
|
||||
healPrediction.Type = SpellHealPredictionType.TargetAndBeacon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendSpellExecuteLog()
|
||||
{
|
||||
if (_executeLogEffects.Empty())
|
||||
@@ -4256,25 +4339,6 @@ namespace Game.Spells
|
||||
if (unitCaster == null)
|
||||
return;
|
||||
|
||||
SpellChannelStart spellChannelStart = new();
|
||||
spellChannelStart.CasterGUID = unitCaster.GetGUID();
|
||||
spellChannelStart.SpellID = (int)m_spellInfo.Id;
|
||||
spellChannelStart.Visual = m_SpellVisual;
|
||||
spellChannelStart.ChannelDuration = duration;
|
||||
|
||||
uint schoolImmunityMask = unitCaster.GetSchoolImmunityMask();
|
||||
ulong mechanicImmunityMask = unitCaster.GetMechanicImmunityMask();
|
||||
|
||||
if (schoolImmunityMask != 0 || mechanicImmunityMask != 0)
|
||||
{
|
||||
SpellChannelStartInterruptImmunities interruptImmunities = new();
|
||||
interruptImmunities.SchoolImmunities = (int)schoolImmunityMask;
|
||||
interruptImmunities.Immunities = (int)mechanicImmunityMask;
|
||||
|
||||
spellChannelStart.InterruptImmunities = interruptImmunities;
|
||||
}
|
||||
unitCaster.SendMessageToSet(spellChannelStart, true);
|
||||
|
||||
m_timer = (int)duration;
|
||||
|
||||
if (!m_targets.HasDst())
|
||||
@@ -4320,6 +4384,37 @@ namespace Game.Spells
|
||||
|
||||
unitCaster.SetChannelSpellId(m_spellInfo.Id);
|
||||
unitCaster.SetChannelVisual(m_SpellVisual);
|
||||
|
||||
SpellChannelStart spellChannelStart = new();
|
||||
spellChannelStart.CasterGUID = unitCaster.GetGUID();
|
||||
spellChannelStart.SpellID = (int)m_spellInfo.Id;
|
||||
spellChannelStart.Visual = m_SpellVisual;
|
||||
spellChannelStart.ChannelDuration = duration;
|
||||
|
||||
uint schoolImmunityMask = unitCaster.GetSchoolImmunityMask();
|
||||
ulong mechanicImmunityMask = unitCaster.GetMechanicImmunityMask();
|
||||
|
||||
if (schoolImmunityMask != 0 || mechanicImmunityMask != 0)
|
||||
{
|
||||
SpellChannelStartInterruptImmunities interruptImmunities = new();
|
||||
interruptImmunities.SchoolImmunities = (int)schoolImmunityMask;
|
||||
interruptImmunities.Immunities = (int)mechanicImmunityMask;
|
||||
|
||||
spellChannelStart.InterruptImmunities = interruptImmunities;
|
||||
}
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr8.HealPrediction) && m_casttime != 0 && m_caster.IsUnit())
|
||||
{
|
||||
SpellTargetedHealPrediction healPrediction = new();
|
||||
if (unitCaster.m_unitData.ChannelObjects.Size() == 1 && unitCaster.m_unitData.ChannelObjects[0].IsUnit())
|
||||
healPrediction.TargetGUID = unitCaster.m_unitData.ChannelObjects[0];
|
||||
|
||||
UpdateSpellHealPrediction(healPrediction.Predict, true);
|
||||
|
||||
spellChannelStart.HealPrediction = healPrediction;
|
||||
}
|
||||
|
||||
unitCaster.SendMessageToSet(spellChannelStart, true);
|
||||
}
|
||||
|
||||
void SendResurrectRequest(Player target)
|
||||
@@ -4746,6 +4841,9 @@ namespace Game.Spells
|
||||
return SpellCastResult.CustomError;
|
||||
}
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr8.OnlyPlayersCanCastThisSpell) && !m_caster.IsPlayer())
|
||||
return SpellCastResult.CasterAurastate;
|
||||
|
||||
// Check global cooldown
|
||||
if (strict && !Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreGCD) && HasGlobalCooldown())
|
||||
return !m_spellInfo.HasAttribute(SpellAttr0.CooldownOnEvent) ? SpellCastResult.NotReady : SpellCastResult.DontReport;
|
||||
@@ -7195,7 +7293,7 @@ namespace Game.Spells
|
||||
bool IsNeedSendToClient()
|
||||
{
|
||||
return m_SpellVisual.SpellXSpellVisualID != 0 || m_SpellVisual.ScriptVisualID != 0 || m_spellInfo.IsChanneled() ||
|
||||
(m_spellInfo.HasAttribute(SpellAttr8.AuraSendAmount)) || m_spellInfo.HasHitDelay() || (m_triggeredByAuraSpell == null && !IsTriggered()) ||
|
||||
(m_spellInfo.HasAttribute(SpellAttr8.AuraPointsOnClient)) || m_spellInfo.HasHitDelay() || (m_triggeredByAuraSpell == null && !IsTriggered()) ||
|
||||
m_spellInfo.HasAttribute(SpellAttr7.AlwaysCastLog);
|
||||
}
|
||||
|
||||
@@ -8474,7 +8572,7 @@ namespace Game.Spells
|
||||
if (unit.IsAlive() != IsAlive)
|
||||
return;
|
||||
|
||||
if (spell.GetState() == SpellState.Delayed && !spell.IsPositive() && (GameTime.GetGameTimeMS() - TimeDelay) <= unit.LastSanctuaryTime)
|
||||
if (!spell.m_spellInfo.HasAttribute(SpellAttr8.IgnoreSanctuary) && spell.GetState() == SpellState.Delayed && !spell.IsPositive() && (GameTime.GetGameTimeMS() - TimeDelay) <= unit.LastSanctuaryTime)
|
||||
return; // No missinfo in that case
|
||||
|
||||
if (_spellHitTarget != null)
|
||||
|
||||
@@ -877,6 +877,18 @@ namespace Game.Spells
|
||||
return SpellCastResult.NotInRaidInstance;
|
||||
}
|
||||
|
||||
if (HasAttribute(SpellAttr8.RemoveOutsideDungeonsAndRaids))
|
||||
{
|
||||
if (mapEntry == null || !mapEntry.IsDungeon())
|
||||
return SpellCastResult.TargetNotInInstance;
|
||||
}
|
||||
|
||||
if (HasAttribute(SpellAttr8.NotInBattleground))
|
||||
{
|
||||
if (mapEntry == null || mapEntry.IsBattleground())
|
||||
return SpellCastResult.NotInBattleground;
|
||||
}
|
||||
|
||||
// DB base check (if non empty then must fit at least single for allow)
|
||||
var saBounds = Global.SpellMgr.GetSpellAreaMapBounds(Id);
|
||||
if (!saBounds.Empty())
|
||||
@@ -993,6 +1005,10 @@ namespace Game.Spells
|
||||
|
||||
Unit unitTarget = target.ToUnit();
|
||||
|
||||
if (HasAttribute(SpellAttr8.OnlyTargetIfSameCreator))
|
||||
if (caster != target && caster.GetGUID() != target.GetOwnerGUID())
|
||||
return SpellCastResult.BadTargets;
|
||||
|
||||
// creature/player specific target checks
|
||||
if (unitTarget != null)
|
||||
{
|
||||
@@ -1046,6 +1062,10 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HasAttribute(SpellAttr8.OnlyTargetOwnSummons))
|
||||
if (!unitTarget.IsSummon() || unitTarget.ToTempSummon().GetSummonerGUID() != caster.GetGUID())
|
||||
return SpellCastResult.BadTargets;
|
||||
}
|
||||
// corpse specific target checks
|
||||
else if (target.IsTypeId(TypeId.Corpse))
|
||||
@@ -1137,7 +1157,7 @@ namespace Game.Spells
|
||||
if (HasEffect(SpellEffectName.SelfResurrect) || HasEffect(SpellEffectName.Resurrect))
|
||||
return SpellCastResult.TargetCannotBeResurrected;
|
||||
|
||||
if (HasAttribute(SpellAttr8.BattleResurrection))
|
||||
if (HasAttribute(SpellAttr8.EnforceInCombatRessurectionLimit))
|
||||
{
|
||||
Map map = caster.GetMap();
|
||||
if (map != null)
|
||||
@@ -4248,7 +4268,7 @@ namespace Game.Spells
|
||||
if (Scaling.Coefficient != 0.0f)
|
||||
{
|
||||
uint level = _spellInfo.SpellLevel;
|
||||
if (target != null && _spellInfo.IsPositiveEffect(EffectIndex) && (Effect == SpellEffectName.ApplyAura))
|
||||
if (target != null && _spellInfo.HasAttribute(SpellAttr8.UseTargetsLevelForSpellScaling))
|
||||
level = target.GetLevel();
|
||||
else if (caster != null && caster.IsUnit())
|
||||
level = caster.ToUnit().GetLevel();
|
||||
@@ -4333,7 +4353,12 @@ namespace Game.Spells
|
||||
if (contentTuning != null)
|
||||
expansion = contentTuning.ExpansionID;
|
||||
|
||||
uint level = caster != null && caster.IsUnit() ? caster.ToUnit().GetLevel() : 1;
|
||||
uint level = 1;
|
||||
if (target != null && _spellInfo.HasAttribute(SpellAttr8.UseTargetsLevelForSpellScaling))
|
||||
level = target.GetLevel();
|
||||
else if (caster != null && caster.IsUnit())
|
||||
level = caster.ToUnit().GetLevel();
|
||||
|
||||
tempValue = Global.DB2Mgr.EvaluateExpectedStat(stat, level, expansion, 0, Class.None, 0) * BasePoints / 100.0f;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user