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

@ -22,8 +22,7 @@ namespace Server
{ {
int MaxRange { get; } int MaxRange { get; }
void OnBeforeSwing(Mobile attacker, Mobile defender); void OnBeforeSwing(Mobile attacker, Mobile defender);
TimeSpan OnSwing(Mobile attacker, Mobile defender); TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0);
TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus);
void GetStatusDamage(Mobile from, out int min, out int max); void GetStatusDamage(Mobile from, out int min, out int max);
} }

View file

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

View file

@ -157,7 +157,7 @@ namespace Server.Items
} }
} }
public override TimeSpan OnSwing(Mobile attacker, Mobile defender) public override TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0)
{ {
if (!Core.AOS) if (!Core.AOS)
{ {

View file

@ -37,7 +37,7 @@ namespace Server.Items
public override SkillName AccuracySkill => SkillName.Archery; public override SkillName AccuracySkill => SkillName.Archery;
public override TimeSpan OnSwing(Mobile attacker, Mobile defender) public override TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0)
{ {
// WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker ); // WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker );