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

@ -15,10 +15,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}

View file

@ -14,7 +14,7 @@ namespace Server.Items
/// </summary>
public class BleedAttack : WeaponAbility
{
private static readonly Dictionary<Mobile, Timer> m_Table = new();
private static readonly Dictionary<Mobile, Timer> _table = new();
public override int BaseMana => 30;
@ -46,9 +46,9 @@ namespace Server.Items
defender.NonlocalOverheadMessage(
MessageType.Regular,
0x21,
1060758,
1060758, // ~1_NAME~ is bleeding profusely
defender.Name
); // ~1_NAME~ is bleeding profusely
);
}
defender.PlaySound(0x133);
@ -57,15 +57,15 @@ namespace Server.Items
BeginBleed(defender, attacker);
}
public static bool IsBleeding(Mobile m) => m_Table.ContainsKey(m);
public static bool IsBleeding(Mobile m) => _table.ContainsKey(m);
public static void BeginBleed(Mobile m, Mobile from)
{
m_Table.TryGetValue(m, out var t);
t?.Stop();
_table.TryGetValue(m, out var timer);
timer?.Stop();
m_Table[m] = t = new InternalTimer(from, m);
t.Start();
_table[m] = timer = new InternalTimer(from, m);
timer.Start();
}
public static void DoBleed(Mobile m, Mobile from, int level)
@ -93,7 +93,7 @@ namespace Server.Items
public static void EndBleed(Mobile m, bool message)
{
if (!m_Table.Remove(m, out var t))
if (!_table.Remove(m, out var t))
{
return;
}
@ -110,9 +110,8 @@ namespace Server.Items
{
private readonly Mobile m_From;
private readonly Mobile m_Mobile;
private int m_Count;
public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0))
public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), 5)
{
m_From = from;
m_Mobile = m;
@ -121,9 +120,9 @@ namespace Server.Items
protected override void OnTick()
{
DoBleed(m_Mobile, m_From, 5 - m_Count);
DoBleed(m_Mobile, m_From, 5 - Index);
if (++m_Count == 5)
if (Index == 4)
{
EndBleed(m_Mobile, true);
}

View file

@ -8,7 +8,7 @@ namespace Server.Items
/// </summary>
public class Block : WeaponAbility
{
private static readonly Dictionary<Mobile, BlockInfo> m_Table = new();
private static readonly Dictionary<Mobile, InternalTimer> _table = new();
public override int BaseMana => 30;
@ -16,10 +16,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}
@ -50,7 +48,7 @@ namespace Server.Items
public static bool GetBonus(Mobile targ, ref int bonus)
{
if (!m_Table.TryGetValue(targ, out var info))
if (!_table.TryGetValue(targ, out var info))
{
return false;
}
@ -62,35 +60,25 @@ namespace Server.Items
public static void BeginBlock(Mobile m, int bonus)
{
EndBlock(m);
m_Table[m] = new BlockInfo(m, bonus);
_table[m] = new InternalTimer(m, bonus);
}
public static void EndBlock(Mobile m)
{
if (m_Table.Remove(m, out var info))
if (_table.Remove(m, out var timer))
{
info.m_Timer?.Stop();
}
}
private class BlockInfo
{
public readonly int m_Bonus;
public readonly Timer m_Timer;
public BlockInfo(Mobile target, int bonus)
{
m_Bonus = bonus;
m_Timer = new InternalTimer(target);
timer?.Stop();
}
}
private class InternalTimer : Timer
{
private readonly Mobile m_Mobile;
public readonly int m_Bonus;
public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(6.0))
public InternalTimer(Mobile m, int bonus) : base(TimeSpan.FromSeconds(6.0))
{
m_Bonus = bonus;
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}

View file

@ -9,8 +9,7 @@ namespace Server.Items
/// </summary>
public class DefenseMastery : WeaponAbility
{
private static readonly Dictionary<Mobile, DefenseMasteryInfo>
m_Table = new();
private static readonly Dictionary<Mobile, DefenseMasteryInfo> _table = new();
public override int BaseMana => 30;
@ -18,10 +17,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}
@ -46,7 +43,7 @@ namespace Server.Items
((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) -
50.0) / 70.0));
if (m_Table.TryGetValue(attacker, out var info))
if (_table.TryGetValue(attacker, out var info))
{
EndDefense(info);
}
@ -57,14 +54,14 @@ namespace Server.Items
info = new DefenseMasteryInfo(attacker, 80 - modifier, mod);
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3.0), EndDefense, info);
m_Table[attacker] = info;
_table[attacker] = info;
attacker.Delta(MobileDelta.WeaponDamage);
}
public static bool GetMalus(Mobile targ, ref int damageMalus)
{
if (!m_Table.TryGetValue(targ, out var info))
if (!_table.TryGetValue(targ, out var info))
{
return false;
}
@ -84,7 +81,7 @@ namespace Server.Items
// No message is sent to the player.
m_Table.Remove(info.m_From);
_table.Remove(info.m_From);
info.m_From.Delta(MobileDelta.WeaponDamage);
}

View file

@ -17,17 +17,17 @@ namespace Server.Items
{
if (!base.CheckSkills( from ))
return false;
if (!(from.Weapon is Fists))
return true;
Skill skill = from.Skills.ArmsLore;
if (skill?.Base >= 80.0)
return true;
from.SendLocalizedMessage( 1061812 ); // You lack the required skill in armslore to perform that attack!
return false;
}*/
@ -43,7 +43,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -67,7 +67,7 @@ namespace Server.Items
{
attacker.SendLocalizedMessage(1060849); // Your target is already unarmed!
}
else if (CheckMana(attacker, true))
else
{
attacker.SendLocalizedMessage(1060092); // You disarm their weapon!
defender.SendLocalizedMessage(1060093); // Your weapon has been disarmed!

View file

@ -34,7 +34,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -60,11 +60,6 @@ namespace Server.Items
return;
}
if (!CheckMana(attacker, true))
{
return;
}
if (Core.ML && attacker is LesserHiryu && Utility.RandomDouble() <= 0.8)
{
return; // Lesser Hiryu have an 80% chance of missing this attack

View file

@ -13,7 +13,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -32,7 +32,7 @@ namespace Server.Items
{
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
}
else if (CheckMana(attacker, true))
else
{
// attacker.SendLocalizedMessage( 1060092 ); // You disarm their weapon!
defender.SendLocalizedMessage(1062002); // You can no longer wear your ~1_ARMOR~

View file

@ -11,10 +11,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}

View file

@ -16,10 +16,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
{
from.SendLocalizedMessage(
1063352,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063352, "50");
return false;
}

View file

@ -16,10 +16,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}

View file

@ -19,10 +19,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1063347,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063347, "50");
return false;
}
@ -31,7 +29,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker)) // Mana check after check that there are targets
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}

View file

@ -23,7 +23,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -39,14 +39,8 @@ namespace Server.Items
if (p == null || weapon.PoisonCharges <= 0)
{
attacker.SendLocalizedMessage(
1061141
); // Your weapon must have a dose of poison to perform an infectious strike!
return;
}
if (!CheckMana(attacker, true))
{
// Your weapon must have a dose of poison to perform an infectious strike!
attacker.SendLocalizedMessage(1061141);
return;
}

View file

@ -13,7 +13,7 @@ namespace Server.Items
public static readonly TimeSpan PlayerDuration = TimeSpan.FromSeconds(6.0);
public static readonly TimeSpan NPCDuration = TimeSpan.FromSeconds(12.0);
private static readonly Dictionary<Mobile, InternalTimer> m_Table = new();
private static readonly Dictionary<Mobile, Timer> _table = new();
public override int BaseMana => 30;
@ -39,16 +39,16 @@ namespace Server.Items
}
}
public static bool IsWounded(Mobile m) => m_Table.ContainsKey(m);
public static bool IsWounded(Mobile m) => _table.ContainsKey(m);
public static void BeginWound(Mobile m, TimeSpan duration)
{
if (m_Table.TryGetValue(m, out var timer))
if (_table.TryGetValue(m, out var timer))
{
timer?.Stop();
}
m_Table[m] = timer = new InternalTimer(m, duration);
_table[m] = timer = Timer.DelayCall(duration, EndWound, m);
timer.Start();
m.YellowHealthbar = true;
@ -56,7 +56,7 @@ namespace Server.Items
public static void EndWound(Mobile m)
{
if (m_Table.Remove(m, out var timer))
if (_table.Remove(m, out var timer))
{
timer.Stop();
}
@ -64,21 +64,5 @@ namespace Server.Items
m.YellowHealthbar = false;
m.SendLocalizedMessage(1060208); // You are no longer mortally wounded.
}
private class InternalTimer : Timer
{
private readonly Mobile m_Mobile;
public InternalTimer(Mobile m, TimeSpan duration) : base(duration)
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
EndWound(m_Mobile);
}
}
}
}

View file

@ -13,10 +13,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1070768,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
from.SendLocalizedMessage(1070768, "50");
return false;
}

View file

@ -13,7 +13,7 @@ namespace Server.Items
public static readonly TimeSpan FreezeDelayDuration = TimeSpan.FromSeconds(8.0);
private static readonly Dictionary<Mobile, InternalTimer> m_Table = new();
private static readonly Dictionary<Mobile, Timer> _table = new();
public override int BaseMana => 30;
@ -80,41 +80,25 @@ namespace Server.Items
BeginImmunity(defender, duration + FreezeDelayDuration);
}
public static bool IsImmune(Mobile m) => m_Table.ContainsKey(m);
public static bool IsImmune(Mobile m) => _table.ContainsKey(m);
public static void BeginImmunity(Mobile m, TimeSpan duration)
{
if (m_Table.TryGetValue(m, out var timer))
if (_table.TryGetValue(m, out var timer))
{
timer?.Stop();
}
m_Table[m] = timer = new InternalTimer(m, duration);
_table[m] = timer = Timer.DelayCall(duration, EndImmunity, m);
timer.Start();
}
public static void EndImmunity(Mobile m)
{
if (m_Table.Remove(m, out var timer))
if (_table.Remove(m, out var timer))
{
timer?.Stop();
}
}
private class InternalTimer : Timer
{
private readonly Mobile m_Mobile;
public InternalTimer(Mobile m, TimeSpan duration) : base(duration)
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
EndImmunity(m_Mobile);
}
}
}
}

View file

@ -18,10 +18,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(
1070768,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
from.SendLocalizedMessage(1070768, "50");
return false;
}

View file

@ -8,7 +8,7 @@ namespace Server.Items
/// </summary>
public class TalonStrike : WeaponAbility
{
private static readonly HashSet<Mobile> m_Table = new();
private static readonly HashSet<Mobile> _defenders = new();
public override int BaseMana => 30;
public override double DamageScalar => 1.2;
@ -17,10 +17,8 @@ namespace Server.Items
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
{
from.SendLocalizedMessage(
1063352,
"50"
); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
// You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
from.SendLocalizedMessage(1063352, "50");
return false;
}
@ -29,7 +27,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (m_Table.Contains(defender) || !Validate(attacker) || !CheckMana(attacker, true))
if (_defenders.Contains(defender) || !Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -48,7 +46,7 @@ namespace Server.Items
timer.Start();
m_Table.Add(defender);
_defenders.Add(defender);
}
private class InternalTimer : Timer
@ -58,12 +56,12 @@ namespace Server.Items
private double m_DamageRemaining;
private double m_DamageToDo;
public InternalTimer(Mobile defender, int totalDamage)
: base(
TimeSpan.Zero,
TimeSpan.FromSeconds(0.25),
12
) // 3 seconds at .25 seconds apart = 12. Confirm delay inbetween of .25 each.
// 3 seconds at 0.25 seconds apart = 12. Confirm delay in between of 0.25 each.
public InternalTimer(Mobile defender, int totalDamage) : base(
TimeSpan.Zero,
TimeSpan.FromSeconds(0.25),
12
)
{
m_Defender = defender;
m_DamageRemaining = totalDamage;
@ -77,7 +75,7 @@ namespace Server.Items
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
m_Table.Remove(m_Defender);
_defenders.Remove(m_Defender);
return;
}
@ -101,7 +99,7 @@ namespace Server.Items
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
m_Table.Remove(m_Defender);
_defenders.Remove(m_Defender);
}
}
}

View file

@ -185,10 +185,8 @@ namespace Server.Items
if (Core.ML && reqTactics && from.Skills.Tactics.Base < reqSkill)
{
from.SendLocalizedMessage(
1079308,
reqSkill.ToString()
); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
// You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
from.SendLocalizedMessage(1079308, reqSkill.ToString());
return false;
}
@ -208,17 +206,13 @@ namespace Server.Items
if (reqTactics)
{
from.SendLocalizedMessage(
1079308,
reqSkill.ToString()
); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
// You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
from.SendLocalizedMessage(1079308, reqSkill.ToString());
}
else
{
from.SendLocalizedMessage(
1060182,
reqSkill.ToString()
); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
// You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
from.SendLocalizedMessage(1060182, reqSkill.ToString());
}
return false;
@ -239,10 +233,8 @@ namespace Server.Items
return true;
}
from.SendLocalizedMessage(
1060181,
mana.ToString()
); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack
// You need ~1_MANA_REQUIREMENT~ mana to perform that attack
from.SendLocalizedMessage(1060181, mana.ToString());
return false;
}

View file

@ -14,7 +14,7 @@ namespace Server.Items
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
if (!Validate(attacker) || !CheckMana(attacker, true))
{
return;
}
@ -33,11 +33,6 @@ namespace Server.Items
return;
}
if (!CheckMana(attacker, true))
{
return;
}
attacker.FixedEffect(0x3728, 10, 15);
attacker.PlaySound(0x2A1);