fix: Fixes first/second scrolls crashing (#891)

* Fixes first/second circle scrolls crashing
* Consolidates some resistance logic
* Removes unnecessary multiple lookups for items on layer
This commit is contained in:
Kamron Batman 2021-12-24 15:26:12 -08:00 committed by GitHub
parent f634ee2748
commit 171df32257
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 39 additions and 49 deletions

View file

@ -6,9 +6,11 @@ namespace Server.Spells
public abstract class MagerySpell : Spell
{
private static readonly int[] _manaTable = { 4, 6, 9, 11, 14, 20, 40, 50 };
// Starts at Circle -2 to account for scrolls
private static readonly double[] _requiredSkill = Core.ML ?
new[] { 0.0, -4.0, 10.0, 24.0, 38.0, 52.0, 66.0, 80.0 } :
new[] { 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0 };
new[] { -46.0, -32.0, 0.0, -4.0, 10.0, 24.0, 38.0, 52.0, 66.0, 80.0 } :
new[] { -50.0, -30.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0 };
public MagerySpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info)
{
@ -23,13 +25,6 @@ namespace Server.Spells
public override void GetCastSkills(out double min, out double max)
{
var circle = (int)Circle;
if (Scroll != null)
{
circle -= 2;
}
// Original RunUO algorithm for required skill
// const double chanceOffset = 20.0
// const double chanceLength = 100.0 / 7.0
@ -37,9 +32,9 @@ namespace Server.Spells
// min = avg - chanceOffset;
// max = avg + chanceOffset;
// Correct algorithm according to OSI.
// Correct algorithm according to OSI for UOR/UOML
// TODO: Verify this algorithm on OSI for latest expansion.
min = _requiredSkill[circle];
min = _requiredSkill[(int)(Scroll == null ? Circle + 2 : Circle)];
max = min + 40;
}
@ -47,8 +42,9 @@ namespace Server.Spells
public override double GetResistSkill(Mobile m)
{
var maxSkill = (1 + (int)Circle) * 10;
maxSkill += (1 + (int)Circle / 6) * 25;
var circle = (int)Circle;
var maxSkill = 1 + circle * 10 + (1 + circle / 6) * 25;
if (m.Skills.MagicResist.Value < maxSkill)
{
@ -60,9 +56,7 @@ namespace Server.Spells
public virtual bool CheckResisted(Mobile target)
{
var n = GetResistPercent(target);
n /= 100.0;
var n = GetResistPercent(target) / 100.0;
if (n <= 0.0)
{
@ -74,8 +68,10 @@ namespace Server.Spells
return true;
}
var maxSkill = (1 + (int)Circle) * 10;
maxSkill += (1 + (int)Circle / 6) * 25;
// Even though this calculation matches AOS+, we don't combine with GetResistSkills because of an assumption
// about how it is used.
var circle = (int)Circle;
var maxSkill = (1 + circle) * 10 + (1 + circle / 6) * 25;
if (target.Skills.MagicResist.Value < maxSkill)
{

View file

@ -31,17 +31,12 @@ namespace Server.Spells.Bushido
return false;
}
if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield)
{
return true;
}
if (Caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon)
{
return true;
}
if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseWeapon)
if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield or BaseWeapon)
{
return true;
}

View file

@ -33,7 +33,7 @@ namespace Server.Spells.Bushido
return false;
}
if (!(caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap))
if (caster.FindItemOnLayer(Layer.OneHanded) is not BaseWeapon weap)
{
weap = caster.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon;
}
@ -44,15 +44,14 @@ namespace Server.Spells.Bushido
{
if (messages)
{
caster.SendLocalizedMessage(
1076206
); // Your skill with your equipped weapon must be 50 or higher to use Evasion.
// Your skill with your equipped weapon must be 50 or higher to use Evasion.
caster.SendLocalizedMessage(1076206);
}
return false;
}
}
else if (!(caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield))
else if (caster.FindItemOnLayer(Layer.TwoHanded) is not BaseShield)
{
if (messages)
{
@ -77,7 +76,7 @@ namespace Server.Spells.Bushido
public static bool CheckSpellEvasion(Mobile defender)
{
if (!(defender.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap))
if (defender.FindItemOnLayer(Layer.OneHanded) is not BaseWeapon weap)
{
weap = defender.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon;
}
@ -96,7 +95,7 @@ namespace Server.Spells.Bushido
return false;
}
}
else if (!(defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield))
else if (defender.FindItemOnLayer(Layer.TwoHanded) is not BaseShield)
{
return false;
}
@ -162,8 +161,8 @@ namespace Server.Spells.Bushido
seconds += (m.Skills.Bushido.Value - 60) / 20;
}
if (m.Skills.Anatomy.Value >= 100.0 && m.Skills.Tactics.Value >= 100.0 && m.Skills.Bushido.Value > 100.0
) // Bushido being HIGHER than 100 for bonus is intended
// Bushido being HIGHER than 100 for bonus is intended
if (m.Skills.Anatomy.Value >= 100.0 && m.Skills.Tactics.Value >= 100.0 && m.Skills.Bushido.Value > 100.0)
{
seconds++;
}
@ -194,8 +193,8 @@ namespace Server.Spells.Bushido
bonus += (m.Skills.Bushido.Value - 60) * .004 + 0.16;
}
if (m.Skills.Anatomy.Value >= 100 && m.Skills.Tactics.Value >= 100 && m.Skills.Bushido.Value > 100
) // Bushido being HIGHER than 100 for bonus is intended
// Bushido being HIGHER than 100 for bonus is intended
if (m.Skills.Anatomy.Value >= 100 && m.Skills.Tactics.Value >= 100 && m.Skills.Bushido.Value > 100)
{
bonus += 0.10;
}

View file

@ -29,7 +29,7 @@ namespace Server.Spells.Chivalry
public override void OnCast()
{
if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists)
if (Caster.Weapon is not (BaseWeapon weapon and not Fists))
{
Caster.SendLocalizedMessage(501078); // You must be holding a weapon.
}

View file

@ -40,7 +40,7 @@ namespace Server.Spells.Chivalry
continue;
}
if (Caster != m && m.InLOS(Caster) && Caster.CanBeBeneficial(m, false, true) && !(m is Golem))
if (Caster != m && m.InLOS(Caster) && Caster.CanBeBeneficial(m, false, true) && m is not Golem)
{
targets.Add(m);
}

View file

@ -28,7 +28,7 @@ namespace Server.Spells.Fifth
{
Caster.SendLocalizedMessage(1005049); // That cannot be dispelled.
}
else if (item is Moongate moongate && !moongate.Dispellable)
else if (item is Moongate { Dispellable: false })
{
Caster.SendLocalizedMessage(1005047); // That magic is too chaotic
}

View file

@ -127,7 +127,7 @@ namespace Server.Spells.Fourth
return false;
}
if (feluccaRules && !(target is PlayerMobile))
if (feluccaRules && target is not PlayerMobile)
{
return false;
}

View file

@ -142,7 +142,7 @@ namespace Server.Spells.Necromancy
return;
}
if (!(item is Corpse c))
if (item is not Corpse c)
{
Caster.SendLocalizedMessage(1061084); // You cannot animate that.
}

View file

@ -34,7 +34,7 @@ namespace Server.Spells.Necromancy
Caster.SendLocalizedMessage(1060508); // You can't curse that.
}
// only PlayerMobile and BaseCreature implement blood oath checking
else if (Caster == m || !(m is PlayerMobile || m is BaseCreature))
else if (Caster == m || m is not (PlayerMobile or BaseCreature))
{
Caster.SendLocalizedMessage(1060508); // You can't curse that.
}

View file

@ -27,7 +27,7 @@ namespace Server.Spells.Necromancy
public override void OnCast()
{
if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists)
if (Caster.Weapon is not BaseWeapon weapon || weapon is Fists)
{
Caster.SendLocalizedMessage(501078); // You must be holding a weapon.
}

View file

@ -30,7 +30,7 @@ namespace Server.Spells.Necromancy
public void Target(Mobile m)
{
if (!(m is BaseCreature || m is PlayerMobile))
if (m is not (BaseCreature or PlayerMobile))
{
Caster.SendLocalizedMessage(1060508); // You can't curse that.
}

View file

@ -140,7 +140,7 @@ namespace Server.Spells.Seventh
public override bool OnMoveOver(Mobile m)
{
if (!(m is PlayerMobile))
if (m is not PlayerMobile)
{
return base.OnMoveOver(m);
}

View file

@ -24,7 +24,7 @@ namespace Server.Spells.Third
public void Target(Item item)
{
if (!(item is LockableContainer cont))
if (item is not LockableContainer cont)
{
Caster.SendLocalizedMessage(501762); // Target must be an unlocked chest.
}

View file

@ -98,8 +98,8 @@ namespace Server.Spells.Third
foreach (var item in eable)
{
if (item is ParalyzeFieldSpell.InternalItem || item is PoisonFieldSpell.InternalItem ||
item is FireFieldSpell.FireFieldItem)
if (item is ParalyzeFieldSpell.InternalItem or
PoisonFieldSpell.InternalItem or FireFieldSpell.FireFieldItem)
{
item.OnMoveOver(m);
}

View file

@ -42,7 +42,7 @@ namespace Server.Spells.Third
{
Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503101); // That did not need to be unlocked.
}
else if (!(p is LockableContainer cont))
else if (p is not LockableContainer cont)
{
Caster.SendLocalizedMessage(501666); // You can't unlock that!
}

View file

@ -149,7 +149,7 @@ namespace Server.Spells.Third
if (m is PlayerMobile)
{
var noto = Notoriety.Compute(m_Caster, m);
if (noto == Notoriety.Enemy || noto == Notoriety.Ally)
if (noto is Notoriety.Enemy or Notoriety.Ally)
{
return false;
}