fix: Weapons cleanup (#857)

* Removes linq
* Removes list allocation for area effect
* Removes redundant swing overload
* Cleans up code
This commit is contained in:
Kamron Batman 2021-11-21 09:19:09 -08:00 committed by GitHub
parent 09613e2536
commit 43db0d09c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 173 additions and 215 deletions

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Collections;
using Server.Engines.Craft;
using Server.Ethics;
using Server.Factions;
@ -695,8 +695,6 @@ namespace Server.Items
}
}
public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender) => OnSwing(attacker, defender, 1.0);
public virtual void GetStatusDamage(Mobile from, out int min, out int max)
{
GetBaseDamageRange(from, out var baseMin, out var baseMax);
@ -713,7 +711,7 @@ namespace Server.Items
}
}
public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus)
public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0)
{
var canSwing = true;
@ -723,12 +721,12 @@ namespace Server.Items
if (canSwing)
{
canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement;
canSwing = attacker.Spell is not Spell sp || !sp.IsCasting || !sp.BlocksMovement;
}
if (canSwing)
{
canSwing = !(attacker is PlayerMobile p) || p.PeacedUntil <= Core.Now;
canSwing = attacker is not PlayerMobile p || p.PeacedUntil <= Core.Now;
}
}
@ -786,7 +784,7 @@ namespace Server.Items
public override void OnAfterDuped(Item newItem)
{
if (!(newItem is BaseWeapon weap))
if (newItem is not BaseWeapon weap)
{
return;
}
@ -877,8 +875,8 @@ namespace Server.Items
return true;
}
if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) &&
!(item is BaseEquipableLight))
if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && item is not BaseShield &&
item is not BaseEquipableLight)
{
m.SendLocalizedMessage(500215); // You can only wield one weapon at a time.
return true;
@ -1096,7 +1094,6 @@ namespace Server.Items
var defWeapon = defender.Weapon as BaseWeapon;
var atkSkill = attacker.Skills[atkWeapon?.Skill ?? SkillName.Wrestling];
// Skill defSkill = defender.Skills[defWeapon.Skill];
var atkValue = atkWeapon?.GetAttackSkillValue(attacker, defender) ?? 0.0;
var defValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0;
@ -1209,23 +1206,11 @@ namespace Server.Items
}
else
{
if (atkValue <= -50.0)
{
atkValue = -49.9;
}
if (defValue <= -50.0)
{
defValue = -49.9;
}
ourValue = atkValue + 50.0;
theirValue = defValue + 50.0;
ourValue = Math.Max(0.1, atkValue + 50.0);
theirValue = Math.Max(0.1, defValue + 50.0);
}
var chance = ourValue / (theirValue * 2.0);
chance *= 1.0 + (double)bonus / 100;
var chance = ourValue / (theirValue * 2.0) * 1.0 + (double)bonus / 100;
if (Core.AOS && chance < 0.02)
{
@ -1418,7 +1403,7 @@ namespace Server.Items
return defender.CheckSkill(SkillName.Parry, chance);
}
if (defender.Weapon is Fists || defender.Weapon is BaseRanged)
if (defender.Weapon is Server.Items.Fists or BaseRanged)
{
return false;
}
@ -1459,9 +1444,8 @@ namespace Server.Items
return defender.CheckSkill(SkillName.Parry, chance);
}
return
aosChance > Utility
.RandomDouble(); // Only skillcheck if wielding a shield & there's no effect from Bushido
// Only skillcheck if wielding a shield & there's no effect from Bushido
return aosChance > Utility.RandomDouble();
}
public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage)
@ -1493,9 +1477,8 @@ namespace Server.Items
if (Confidence.IsConfident(defender))
{
defender.SendLocalizedMessage(
1063117
); // Your confidence reassures you as you successfully block your opponent's blow.
// Your confidence reassures you as you successfully block your opponent's blow.
defender.SendLocalizedMessage(1063117);
var bushido = defender.Skills.Bushido.Value;
@ -1590,7 +1573,7 @@ namespace Server.Items
return 0;
}
if (!(attacker is BaseCreature bc) || bc.PackInstinct == PackInstinct.None || !bc.Controlled && !bc.Summoned)
if (attacker is not BaseCreature bc || bc.PackInstinct == PackInstinct.None || !bc.Controlled && !bc.Summoned)
{
return 0;
}
@ -1603,16 +1586,26 @@ namespace Server.Items
}
var eable = defender.GetMobilesInRange<BaseCreature>(1);
var inPack = 1 + eable
.Where(m => m != attacker && (m.PackInstinct & bc.PackInstinct) != 0 && (m.Controlled || m.Summoned))
.Count(m => master == (m.ControlMaster ?? m.SummonMaster) && m.Combatant == defender);
var inPack = 1;
foreach (var m in eable)
{
if (m != attacker && (m.PackInstinct & bc.PackInstinct) != 0 && (m.Controlled || m.Summoned) &&
master == (m.ControlMaster ?? m.SummonMaster) && m.Combatant == defender)
{
inPack++;
}
}
eable.Free();
return inPack >= 5 ? 100 :
inPack >= 4 ? 75 :
inPack >= 3 ? 50 :
inPack >= 2 ? 25 : 0;
return inPack switch
{
>= 5 => 100,
4 => 75,
3 => 50,
2 => 25,
_ => 0
};
}
public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1.0)
@ -1688,12 +1681,9 @@ namespace Server.Items
if (!attacker.Player)
{
if (defender is PlayerMobile pm)
if (defender is PlayerMobile pm && pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType())
{
if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType())
{
percentageBonus += 100;
}
percentageBonus += 100;
}
}
else if (!defender.Player)
@ -1769,16 +1759,14 @@ namespace Server.Items
{
damage = 1;
}
else if (Core.AOS && damage == 0) // parried
// Parried
else if (Core.AOS && damage == 0 && a?.Validate(attacker) == true)
{
if (a?.Validate(attacker) == true) /*&& a.CheckMana( attacker, true )*/
// Parried special moves have no mana cost
{
a = null;
WeaponAbility.ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1061140); // Your attack was parried!
}
/*&& a.CheckMana( attacker, true )*/
// Parried special moves have no mana cost
a = null;
WeaponAbility.ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1061140); // Your attack was parried!
}
AddBlood(attacker, defender, damage);
@ -1936,9 +1924,8 @@ namespace Server.Items
if (context?.Type == typeof(WraithFormSpell))
{
wraithLeech =
5 + (int)(15 * attacker.Skills.SpiritSpeak.Value /
100); // Wraith form gives an additional 5-20% mana leech
// Wraith form gives an additional 5-20% mana leech
wraithLeech = 5 + (int)(15 * attacker.Skills.SpiritSpeak.Value / 100);
// Mana leeched by the Wraith Form spell is actually stolen, not just leeched.
defender.Mana -= AOS.Scale(damageGiven, wraithLeech);
@ -1967,10 +1954,10 @@ namespace Server.Items
}
}
if (m_MaxHits > 0 && (MaxRange <= 1 && (defender is Slime || defender is AcidElemental) ||
Utility.RandomDouble() < .04)) // Stratics says 50% chance, seems more like 4%..
// Stratics says 50% chance, seems more like 4%..
if (m_MaxHits > 0 && MaxRange <= 1 && defender is Slime or AcidElemental |Utility.RandomDouble() < .04)
{
if (MaxRange <= 1 && (defender is Slime || defender is AcidElemental))
if (MaxRange <= 1 && defender is Slime or AcidElemental)
{
attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!*
}
@ -1979,29 +1966,23 @@ namespace Server.Items
{
HitPoints += 2;
}
else if (m_Hits > 0)
{
--HitPoints;
}
else if (m_MaxHits > 1)
{
--MaxHitPoints;
if (Parent is Mobile mobile)
{
// Your equipment is severely damaged.
mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121);
}
}
else
{
if (m_Hits > 0)
{
--HitPoints;
}
else if (m_MaxHits > 1)
{
--MaxHitPoints;
if (Parent is Mobile mobile)
{
mobile.LocalOverheadMessage(
MessageType.Regular,
0x3B2,
1061121 // Your equipment is severely damaged.
);
}
}
else
{
Delete();
}
Delete();
}
}
@ -2021,16 +2002,20 @@ namespace Server.Items
if (Core.AOS)
{
var physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) *
propertyBonus);
var physChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * propertyBonus);
var fireChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus);
var coldChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus);
var poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) *
propertyBonus);
var nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) *
propertyBonus);
var poisChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * propertyBonus);
var nrgyChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * propertyBonus);
if (physChance != 0 && physChance > Utility.Random(100))
{
@ -2092,10 +2077,10 @@ namespace Server.Items
DoDispel(attacker, defender);
}
var laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) *
propertyBonus);
var ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) *
propertyBonus);
var laChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * propertyBonus);
var ldChance =
(int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * propertyBonus);
if (laChance != 0 && laChance > Utility.Random(100))
{
@ -2121,7 +2106,7 @@ namespace Server.Items
it.ReceivedHonorContext?.OnTargetHit(attacker);
}
if (!(this is BaseRanged))
if (this is not BaseRanged)
{
if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent)))
{
@ -2157,7 +2142,7 @@ namespace Server.Items
// SDI bonus
damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage);
if(PsychicAttack.Registry.TryGetValue(attacker,out var timer))
if (PsychicAttack.Registry.TryGetValue(attacker,out var timer))
{
damageBonus -= timer.SpellDamageMalus;
}
@ -2319,13 +2304,8 @@ namespace Server.Items
attacker.PlaySound(GetMissAttackSound(attacker, defender));
defender.PlaySound(GetMissDefendSound(attacker, defender));
var ability = WeaponAbility.GetCurrentAbility(attacker);
ability?.OnMiss(attacker, defender);
var move = SpecialMove.GetCurrentMove(attacker);
move?.OnMiss(attacker, defender);
WeaponAbility.GetCurrentAbility(attacker)?.OnMiss(attacker, defender);
SpecialMove.GetCurrentMove(attacker)?.OnMiss(attacker, defender);
if (defender is IHonorTarget target)
{
@ -2417,56 +2397,38 @@ namespace Server.Items
{
var bonus = VirtualDamageBonus;
switch (m_Quality)
bonus += m_Quality switch
{
case WeaponQuality.Low:
bonus -= 20;
break;
case WeaponQuality.Exceptional:
bonus += 20;
break;
}
WeaponQuality.Low => -20,
WeaponQuality.Exceptional => 20,
_ => 0
};
switch (m_DamageLevel)
return bonus + m_DamageLevel switch
{
case WeaponDamageLevel.Ruin:
bonus += 15;
break;
case WeaponDamageLevel.Might:
bonus += 20;
break;
case WeaponDamageLevel.Force:
bonus += 25;
break;
case WeaponDamageLevel.Power:
bonus += 30;
break;
case WeaponDamageLevel.Vanq:
bonus += 35;
break;
}
return bonus;
WeaponDamageLevel.Ruin => 15,
WeaponDamageLevel.Might => 20,
WeaponDamageLevel.Force => 25,
WeaponDamageLevel.Power => 30,
WeaponDamageLevel.Vanq => 35,
_ => bonus
};
}
public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills)
{
if (checkSkills)
{
attacker.CheckSkill(
SkillName.Tactics,
0.0,
attacker.Skills.Tactics.Cap
); // Passively check tactics for gain
attacker.CheckSkill(
SkillName.Anatomy,
0.0,
attacker.Skills.Anatomy.Cap
); // Passively check Anatomy for gain
// Passively check tactics for gain
attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills.Tactics.Cap);
// Passively check Anatomy for gain
attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills.Anatomy.Cap);
if (Type == WeaponType.Axe)
{
attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
// Passively check Lumberjacking for gain
attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0);
}
}
@ -2536,20 +2498,16 @@ namespace Server.Items
{
if (checkSkills)
{
attacker.CheckSkill(
SkillName.Tactics,
0.0,
attacker.Skills.Tactics.Cap
); // Passively check tactics for gain
attacker.CheckSkill(
SkillName.Anatomy,
0.0,
attacker.Skills.Anatomy.Cap
); // Passively check Anatomy for gain
// Passively check tactics for gain
attacker.CheckSkill(SkillName.Tactics, 0.0, attacker.Skills.Tactics.Cap);
// Passively check Anatomy for gain
attacker.CheckSkill(SkillName.Anatomy, 0.0, attacker.Skills.Anatomy.Cap);
if (Type == WeaponType.Axe)
{
attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain
// Passively check Lumberjacking for gain
attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0);
}
}
@ -2633,9 +2591,9 @@ namespace Server.Items
var damage = (int)ScaleDamageOld(attacker, GetBaseDamage(attacker), true);
// pre-AOS, halve damage if the defender is a player or the attacker is not a player
if (defender is PlayerMobile || !(attacker is PlayerMobile))
if (defender is PlayerMobile || attacker is not PlayerMobile)
{
damage = (int)(damage / 2.0);
damage /= 2;
}
return damage;
@ -2643,6 +2601,11 @@ namespace Server.Items
public virtual void PlayHurtAnimation(Mobile from)
{
if (from.Mounted)
{
return;
}
int action;
int frames;
@ -2667,12 +2630,10 @@ namespace Server.Items
frames = 5;
break;
}
default: return;
}
if (from.Mounted)
{
return;
default:
{
return;
}
}
from.Animate(action, frames, 1, true, false, 0);
@ -2695,10 +2656,18 @@ namespace Server.Items
switch (Animation)
{
default:
action = Utility.Random(4, 3);
break;
case WeaponAnimation.ShootBow: return; // 7
case WeaponAnimation.ShootXBow: return; // 8
{
action = Utility.Random(4, 3);
break;
}
case WeaponAnimation.ShootBow:
{
return; // 7
}
case WeaponAnimation.ShootXBow:
{
return; // 8
}
}
break;
@ -2728,7 +2697,10 @@ namespace Server.Items
break;
}
default: return;
default:
{
return;
}
}
from.Animate(action, 7, 1, true, false, 0);
@ -2739,11 +2711,11 @@ namespace Server.Items
public int GetElementalDamageHue()
{
GetDamageTypes(null, out _, out var fire, out var cold, out var pois, out var nrgy, out _, out _);
// Order is Cold, Energy, Fire, Poison, Physical left
var currentMax = 50;
var hue = 0;
// Order is Cold, Energy, Fire, Poison, Physical
if (pois >= currentMax)
{
hue = 1267 + (pois - 50) / 10;
@ -2812,7 +2784,7 @@ namespace Server.Items
* formatting show, and remove CLILOCs embedded: more like OSI
* did with the books that had markup, etc.
*
* This will have a negative effect on a few event things imgame
* This will have a negative effect on a few event things in-game
* as is.
*
* If we cant find a more OSI-ish way to clean it up, we can
@ -2828,29 +2800,10 @@ namespace Server.Items
/* list.Add( 1062613, Utility.FixHtml( m_EngravedText ) ); */
}
public override bool AllowEquippedCast(Mobile from)
{
if (base.AllowEquippedCast(from))
{
return true;
}
public override bool AllowEquippedCast(Mobile from) =>
base.AllowEquippedCast(from) || Attributes.SpellChanneling != 0;
return Attributes.SpellChanneling != 0;
}
public virtual int GetLuckBonus()
{
var resInfo = CraftResources.GetInfo(m_Resource);
var attrInfo = resInfo?.AttributeInfo;
if (attrInfo == null)
{
return 0;
}
return attrInfo.WeaponLuck;
}
public virtual int GetLuckBonus() => CraftResources.GetInfo(m_Resource)?.AttributeInfo?.WeaponLuck ?? 0;
public override void GetProperties(ObjectPropertyList list)
{
@ -3235,17 +3188,25 @@ namespace Server.Items
switch (Skill)
{
case SkillName.Swords:
list.Add(1061172);
break; // skill required: swordsmanship
{
list.Add(1061172); // skill required: swordsmanship
break;
}
case SkillName.Macing:
list.Add(1061173);
break; // skill required: mace fighting
{
list.Add(1061173); // skill required: mace fighting
break;
}
case SkillName.Fencing:
list.Add(1061174);
break; // skill required: fencing
{
list.Add(1061174); // skill required: fencing
break;
}
case SkillName.Archery:
list.Add(1061175);
break; // skill required: archery
{
list.Add(1061175); // skill required: archery
break;
}
}
}
@ -3351,13 +3312,7 @@ namespace Server.Items
public virtual int GetHitAttackSound(Mobile attacker, Mobile defender)
{
var sound = attacker.GetAttackSound();
if (sound == -1)
{
sound = HitSound;
}
return sound;
return sound == -1 ? HitSound : sound;
}
public virtual int GetHitDefendSound(Mobile attacker, Mobile defender) => defender.GetHurtSound();
@ -3518,33 +3473,37 @@ namespace Server.Items
var range = Core.ML ? 5 : 10;
var eable = from.GetMobilesInRange(range);
var list = eable.Where(
m =>
from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m)
&& from.CanBeHarmful(m, false) && (!Core.ML || from.InLOS(m))
)
.ToList();
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var m in eable)
{
if (from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m)
&& from.CanBeHarmful(m, false) && (!Core.ML || from.InLOS(m)))
{
queue.Enqueue(m);
}
}
eable.Free();
if (list.Count == 0)
if (queue.Count == 0)
{
return;
}
Effects.PlaySound(from.Location, map, sound);
for (var i = 0; i < list.Count; ++i)
while (queue.Count > 0)
{
var m = list[i];
var m = queue.Dequeue();
var scalar = Core.ML ? 1.0 : (11 - from.GetDistanceToSqrt(m)) / 10;
var damage = GetBaseDamage(from);
if (scalar <= 0)
{
continue;
}
var damage = GetBaseDamage(from);
if (scalar < 1.0)
{
damage *= (11 - from.GetDistanceToSqrt(m)) / 10;