Core/Spells: Implement SpellMisc.LaunchDelay

Port From (https://github.com/TrinityCore/TrinityCore/commit/c924840ce7fa7289fe73fb15b0f022bc74618ee1)
This commit is contained in:
hondacrx
2019-09-04 13:13:59 -04:00
parent 7066a959f1
commit 0877e73ff2
4 changed files with 61 additions and 36 deletions
+8 -2
View File
@@ -723,10 +723,16 @@ namespace Game.Entities
if (spellInfo.CheckExplicitTarget(this, magnet) == SpellCastResult.SpellCastOk && _IsValidAttackTarget(magnet, spellInfo))
{
// @todo handle this charge drop by proc in cast phase on explicit target
if (spellInfo.Speed > 0.0f)
if (spellInfo.HasHitDelay())
{
// Set up missile speed based delay
uint delay = (uint)Math.Floor(Math.Max(victim.GetDistance(this), 5.0f) / spellInfo.Speed * 1000.0f);
float hitDelay = spellInfo.LaunchDelay;
if (spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
hitDelay += spellInfo.Speed;
else if (spellInfo.Speed > 0.0f)
hitDelay += Math.Max(victim.GetDistance(this), 5.0f) / spellInfo.Speed;
uint delay = (uint)Math.Floor(hitDelay * 1000.0f);
// Schedule charge drop
eff.GetBase().DropChargeDelayed(delay, AuraRemoveMode.Expire);
}
+35 -34
View File
@@ -292,17 +292,18 @@ namespace Game.Spells
{
float speed = m_targets.GetSpeedXY();
if (speed > 0.0f)
return (ulong)Math.Floor(m_targets.GetDist2d() / speed * 1000.0f);
return (ulong)(Math.Floor((m_targets.GetDist2d() / speed + m_spellInfo.LaunchDelay) * 1000.0f));
}
else if (m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
return (ulong)(Math.Floor((m_spellInfo.Speed + m_spellInfo.LaunchDelay) * 1000.0f));
else if (m_spellInfo.Speed > 0.0f)
{
// We should not subtract caster size from dist calculation (fixes execution time desync with animation on client, eg. Malleable Goo cast by PP)
float dist = m_caster.GetExactDist(m_targets.GetDstPos());
if (!m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
return (ulong)Math.Floor(dist / m_spellInfo.Speed * 1000.0f);
else
return (ulong)(m_spellInfo.Speed * 1000.0f);
return (ulong)(Math.Floor((dist / m_spellInfo.Speed + m_spellInfo.LaunchDelay) * 1000.0f));
}
return (ulong)(Math.Floor(m_spellInfo.LaunchDelay * 1000.0f));
}
return 0;
@@ -1554,19 +1555,20 @@ namespace Game.Spells
// Spell have speed - need calculate incoming time
// Incoming time is zero for self casts. At least I think so.
if (m_spellInfo.Speed > 0.0f && m_caster != target)
if (m_caster != target)
{
// calculate spell incoming interval
// @todo this is a hack
float dist = m_caster.GetDistance(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ());
float hitDelay = m_spellInfo.LaunchDelay;
if (m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
hitDelay += m_spellInfo.Speed;
else if (m_spellInfo.Speed > 0.0f)
{
// calculate spell incoming interval
/// @todo this is a hack
float dist = Math.Max(m_caster.GetDistance(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ()), 5.0f);
hitDelay += dist / m_spellInfo.Speed;
}
if (dist < 5.0f)
dist = 5.0f;
if (!(m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation)))
targetInfo.timeDelay = (ulong)Math.Floor((dist / m_spellInfo.Speed) * 1000.0f);
else
targetInfo.timeDelay = (ulong)(m_spellInfo.Speed * 1000.0f);
targetInfo.timeDelay = (ulong)Math.Floor(hitDelay * 1000.0f);
}
else
targetInfo.timeDelay = 0L;
@@ -1626,23 +1628,22 @@ namespace Game.Spells
target.processed = false; // Effects not apply on target
// Spell have speed - need calculate incoming time
if (m_spellInfo.Speed > 0.0f)
if (m_caster != go)
{
// calculate spell incoming interval
float dist = m_caster.GetDistance(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
if (dist < 5.0f)
dist = 5.0f;
float hitDelay = m_spellInfo.LaunchDelay;
if (m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
hitDelay += m_spellInfo.Speed;
else if (m_spellInfo.Speed > 0.0f)
{
// calculate spell incoming interval
float dist = Math.Max(m_caster.GetDistance(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ()), 5.0f);
hitDelay += dist / m_spellInfo.Speed;
}
if (!m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
target.timeDelay = (ulong)Math.Floor(dist / m_spellInfo.Speed * 1000.0f);
else
target.timeDelay = (ulong)(m_spellInfo.Speed * 1000.0f);
if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
m_delayMoment = target.timeDelay;
target.timeDelay = (ulong)Math.Floor(hitDelay * 1000.0f);
}
else
target.timeDelay = 0L;
target.timeDelay = 0UL;
// Add target to list
m_UniqueGOTargetInfo.Add(target);
@@ -1982,7 +1983,7 @@ namespace Game.Spells
return SpellMissInfo.Evade;
// For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
if (m_spellInfo.Speed != 0.0f && unit.IsImmunedToSpell(m_spellInfo, m_caster))
if (m_spellInfo.HasHitDelay() && unit.IsImmunedToSpell(m_spellInfo, m_caster))
return SpellMissInfo.Immune;
// disable effects to which unit is immune
@@ -2013,7 +2014,7 @@ namespace Game.Spells
if (m_caster != unit)
{
// Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells
if (m_spellInfo.Speed > 0.0f && unit.HasUnitFlag(UnitFlags.NonAttackable) && unit.GetCharmerOrOwnerGUID() != m_caster.GetGUID())
if (m_spellInfo.HasHitDelay() && unit.HasUnitFlag(UnitFlags.NonAttackable) && unit.GetCharmerOrOwnerGUID() != m_caster.GetGUID())
return SpellMissInfo.Evade;
if (m_caster._IsValidAttackTarget(unit, m_spellInfo))
@@ -2023,7 +2024,7 @@ namespace Game.Spells
// for delayed spells ignore negative spells (after duel end) for friendly targets
// @todo this cause soul transfer bugged
// 63881 - Malady of the Mind jump spell (Yogg-Saron)
if (m_spellInfo.Speed > 0.0f && unit.IsTypeId(TypeId.Player) && !m_spellInfo.IsPositive() && m_spellInfo.Id != 63881)
if (m_spellInfo.HasHitDelay() && unit.IsTypeId(TypeId.Player) && !m_spellInfo.IsPositive() && m_spellInfo.Id != 63881)
return SpellMissInfo.Evade;
// assisting case, healing and resurrection
@@ -2738,7 +2739,7 @@ namespace Game.Spells
SendSpellGo();
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
if ((m_spellInfo.Speed > 0.0f && !m_spellInfo.IsChanneled()) || m_spellInfo.HasAttribute(SpellAttr4.Unk4))
if ((m_spellInfo.HasHitDelay() && !m_spellInfo.IsChanneled()) || m_spellInfo.HasAttribute(SpellAttr4.Unk4))
{
// Remove used for cast item if need (it can be already NULL after TakeReagents call
// in case delayed spell remove item at cast delay start
@@ -6524,7 +6525,7 @@ namespace Game.Spells
bool IsNeedSendToClient()
{
return m_SpellVisual != 0 || m_spellInfo.IsChanneled() ||
m_spellInfo.HasAttribute(SpellAttr8.AuraSendAmount) || m_spellInfo.Speed > 0.0f || (m_triggeredByAuraSpell == null && !IsTriggered());
m_spellInfo.HasAttribute(SpellAttr8.AuraSendAmount) || m_spellInfo.HasHitDelay() || (m_triggeredByAuraSpell == null && !IsTriggered());
}
bool HaveTargetsForEffect(byte effect)
+11
View File
@@ -4114,10 +4114,21 @@ namespace Game.Spells
if (m_preGeneratedPath.GetPathType() == PathType.Blank)
{
Position pos = unitTarget.GetFirstCollisionPosition(unitTarget.GetObjectSize(), unitTarget.GetRelativeAngle(m_caster.GetPosition()));
if (m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
speed = pos.GetExactDist(m_caster) / speed;
m_caster.GetMotionMaster().MoveCharge(pos.posX, pos.posY, pos.posZ, speed, EventId.Charge, false, unitTarget, spellEffectExtraData);
}
else
{
if (m_spellInfo.HasAttribute(SpellAttr9.SpecialDelayCalculation))
{
Vector3 pos = m_preGeneratedPath.GetActualEndPosition();
speed = new Position(pos.X, pos.Y, pos.Z).GetExactDist(m_caster) / speed;
}
m_caster.GetMotionMaster().MoveCharge(m_preGeneratedPath, speed, unitTarget, spellEffectExtraData);
}
}
if (effectHandleMode == SpellEffectHandleMode.HitTarget)
+7
View File
@@ -78,6 +78,7 @@ namespace Game.Spells
RangeIndex = _misc.RangeIndex;
RangeEntry = CliDB.SpellRangeStorage.LookupByKey(_misc.RangeIndex);
Speed = _misc.Speed;
LaunchDelay = _misc.LaunchDelay;
SchoolMask = (SpellSchoolMask)_misc.SchoolMask;
AttributesCu = 0;
@@ -636,6 +637,11 @@ namespace Game.Spells
return !(HasAttribute(SpellAttr1.NoThreat) || HasAttribute(SpellAttr3.NoInitialAggro));
}
public bool HasHitDelay()
{
return Speed > 0.0f || LaunchDelay > 0.0f;
}
public WeaponAttackType GetAttackType()
{
WeaponAttackType result;
@@ -3751,6 +3757,7 @@ namespace Game.Spells
public uint RangeIndex { get; set; }
public SpellRangeRecord RangeEntry { get; set; }
public float Speed { get; set; }
public float LaunchDelay { get; set; }
public uint StackAmount { get; set; }
public uint[] Totem = new uint[SpellConst.MaxTotems];
public int[] Reagent = new int[SpellConst.MaxReagents];