chore(content): Cleans up abilities and some spell timers (#427)

- [X] Exposes Index/Count on the timer.
- [X] Cleans up abilities
- [X] Combines some spell context/info objects with their timers to reduce allocations
- [X] Fixes a bug where immolating weapon both finishes effect or stops in the wrong order due to a race condition.
This commit is contained in:
Kamron Batman 2021-01-23 16:40:53 -08:00 • committed by GitHub
parent 9ef7752beb
commit 178f71c6dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 469 additions and 677 deletions

View file

@ -78,9 +78,7 @@ namespace Server.Spells.Bushido
m_Table.TryGetValue(m, out var timer);
timer?.Stop();
m_Table[m] = timer = new InternalTimer(m);
timer.Start();
m_Table[m] = Timer.DelayCall(TimeSpan.FromSeconds(30.0), EndCountering, m);
}
public static void StopCountering(Mobile m)
@ -93,21 +91,10 @@ namespace Server.Spells.Bushido
OnEffectEnd(m, typeof(CounterAttack));
}
private class InternalTimer : Timer
private static void EndCountering(Mobile m)
{
private readonly Mobile m_Mobile;
public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(30.0))
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
StopCountering(m_Mobile);
m_Mobile.SendLocalizedMessage(1063119); // You return to your normal stance.
}
StopCountering(m);
m.SendLocalizedMessage(1063119); // You return to your normal stance.
}
}
}

View file

@ -5,8 +5,7 @@ namespace Server.Spells.Bushido
{
public class HonorableExecution : SamuraiMove
{
private static readonly Dictionary<Mobile, HonorableExecutionInfo> m_Table =
new();
private static readonly Dictionary<Mobile, HonorableExecutionTimer> m_Table = new();
public override int BaseMana => 0;
public override double RequiredSkill => 25.0;
@ -14,13 +13,9 @@ namespace Server.Spells.Bushido
public override TextDefinition AbilityMessage =>
new(1063122); // You better kill your enemy with your next hit or you'll be rather sorry...
public override double GetDamageScalar(Mobile attacker, Mobile defender)
{
var bushido = attacker.Skills.Bushido.Value;
public override double GetDamageScalar(Mobile attacker, Mobile defender) =>
// TODO: 20 -> Perfection
return 1.0 + bushido * 20 / 10000;
}
1.0 + attacker.Skills.Bushido.Value * 20 / 10000;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
@ -30,27 +25,20 @@ namespace Server.Spells.Bushido
}
ClearCurrentMove(attacker);
if (m_Table.TryGetValue(attacker, out var info))
{
info.Clear();
info.m_Timer?.Stop();
}
RemovePenalty(attacker);
if (!defender.Alive)
{
attacker.FixedParticles(0x373A, 1, 17, 0x7E2, EffectLayer.Waist);
var bushido = attacker.Skills.Bushido.Value;
bushido *= bushido;
attacker.Hits += 20 + (int)(bushido * bushido / 480.0);
attacker.Hits += 20 + (int)(bushido / 480.0);
var swingBonus = Math.Max((int)(bushido * bushido / 720.0), 1);
var swingBonus = Math.Max(1, (int)(bushido / 720.0));
info = new HonorableExecutionInfo(attacker, swingBonus);
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(20.0), RemovePenalty, info.m_Mobile);
m_Table[attacker] = info;
m_Table[attacker] = new HonorableExecutionTimer(attacker, swingBonus);
}
else
{
@ -70,12 +58,10 @@ namespace Server.Spells.Bushido
mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells));
}
info = new HonorableExecutionInfo(attacker, mods);
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(7.0), RemovePenalty, info.m_Mobile);
m_Table[attacker] = info;
m_Table[attacker] = new HonorableExecutionTimer(attacker, mods);
}
attacker.Delta(MobileDelta.WeaponDamage);
CheckGain(attacker);
}
@ -85,28 +71,30 @@ namespace Server.Spells.Bushido
public static void RemovePenalty(Mobile target)
{
if (!m_Table.Remove(target, out var info) || !info.m_Penalty)
if (m_Table.Remove(target, out var timer))
{
return;
timer.Clear();
}
info.Clear();
info.m_Timer?.Stop();
}
private class HonorableExecutionInfo
private class HonorableExecutionTimer : Timer
{
public readonly Mobile m_Mobile;
public readonly List<object> m_Mods;
public readonly bool m_Penalty;
public readonly int m_SwingBonus;
public Timer m_Timer;
public HonorableExecutionInfo(Mobile from, List<object> mods) : this(from, 0, mods, mods != null)
public HonorableExecutionTimer(Mobile from, List<object> mods) : this(TimeSpan.FromSeconds(7.0), from, 0, mods, mods != null)
{
}
public HonorableExecutionInfo(Mobile from, int swingBonus, List<object> mods = null, bool penalty = false)
public HonorableExecutionTimer(Mobile from, int swingBonus) : this(TimeSpan.FromSeconds(20.0), from, swingBonus)
{
}
public HonorableExecutionTimer(
TimeSpan duration, Mobile from, int swingBonus, List<object> mods = null, bool penalty = false)
: base(duration)
{
m_Mobile = from;
m_SwingBonus = swingBonus;
@ -116,6 +104,12 @@ namespace Server.Spells.Bushido
Apply();
}
protected override void OnTick()
{
m_Mobile?.Delta(MobileDelta.WeaponDamage);
RemovePenalty(m_Mobile);
}
public void Apply()
{
if (m_Mods == null)
@ -140,6 +134,8 @@ namespace Server.Spells.Bushido
public void Clear()
{
Stop();
if (m_Mods == null)
{
return;
@ -151,11 +147,11 @@ namespace Server.Spells.Bushido
if (mod is ResistanceMod resistanceMod)
{
m_Mobile.RemoveResistanceMod(resistanceMod);
m_Mobile?.RemoveResistanceMod(resistanceMod);
}
else if (mod is SkillMod skillMod)
{
m_Mobile.RemoveSkillMod(skillMod);
m_Mobile?.RemoveSkillMod(skillMod);
}
}
}