From 0ffea2e91282dcdeb7378c54c9cbae1d64e8cf1c Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 11 Jan 2024 00:01:52 -0800 Subject: [PATCH] fix: Fixes Feint so it properly reduces damage (#1657) --- .../Items/Weapons/Abilities/Feint.cs | 119 ++++++++++-------- .../UOContent/Items/Weapons/BaseWeapon.cs | 11 +- Projects/UOContent/Spells/Base/SpellHelper.cs | 6 + 3 files changed, 78 insertions(+), 58 deletions(-) diff --git a/Projects/UOContent/Items/Weapons/Abilities/Feint.cs b/Projects/UOContent/Items/Weapons/Abilities/Feint.cs index dfdf2d2f5..d50532787 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Feint.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Feint.cs @@ -1,65 +1,78 @@ using System; using System.Collections.Generic; -namespace Server.Items +namespace Server.Items; + +/// +/// Gain a defensive advantage over your primary opponent for a short time. +/// +public class Feint : WeaponAbility { - /// - /// Gain a defensive advantage over your primary opponent for a short time. - /// - public class Feint : WeaponAbility + public static Dictionary Registry { get; } = new(); + + public override int BaseMana => 30; + public override bool RequiresSecondarySkill(Mobile from) => true; + + public override void OnHit(Mobile attacker, Mobile defender, int damage, WorldLocation worldLocation) { - public static Dictionary Registry { get; } = new(); - - public override int BaseMana => 30; - public override bool RequiresSecondarySkill(Mobile from) => true; - - public override void OnHit(Mobile attacker, Mobile defender, int damage, WorldLocation worldLocation) + if (!Validate(attacker) || !CheckMana(attacker, true)) { - if (!Validate(attacker) || !CheckMana(attacker, true)) - { - return; - } - - if (Registry.TryGetValue(defender, out var timer)) - { - timer.Stop(); - Registry.Remove(defender); - } - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063360); // You baffle your target with a feint! - defender.SendLocalizedMessage(1063361); // You were deceived by an attacker's feint! - - attacker.FixedParticles(0x3728, 1, 13, 0x7F3, 0x962, 0, EffectLayer.Waist); - - timer = new FeintTimer( - defender, - (int)(20.0 + 3.0 * - (Math.Max(attacker.Skills.Ninjitsu.Value, attacker.Skills.Bushido.Value) - 50.0) / 7.0) - ); // 20-50 % decrease - - timer.Start(); - Registry.Add(defender, timer); + return; } - public class FeintTimer : Timer + if (Registry.Remove(defender, out var timer)) { - private readonly Mobile m_Defender; - - public FeintTimer(Mobile defender, int swingSpeedReduction) - : base(TimeSpan.FromSeconds(6.0)) - { - m_Defender = defender; - SwingSpeedReduction = swingSpeedReduction; - } - - public int SwingSpeedReduction { get; } - - protected override void OnTick() - { - Registry.Remove(m_Defender); - } + timer.Stop(); } + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063360); // You baffle your target with a feint! + defender.SendLocalizedMessage(1063361); // You were deceived by an attacker's feint! + + attacker.FixedParticles(0x3728, 1, 13, 0x7F3, 0x962, 0, EffectLayer.Waist); + + var skill = Math.Max(attacker.Skills.Ninjitsu.Value, attacker.Skills.Bushido.Value); + + // 20-50 % decrease in damage taken for 6 seconds + timer = new FeintTimer( + attacker, + defender, + (int)(20.0 + 3.0 * (skill - 50.0) / 7.0) + ); + + timer.Start(); + Registry.Add(defender, timer); + + // TODO: Add buff icon (Publish 100) + } + + public static bool GetDamageReduction(Mobile attacker, Mobile defender, out int damageReduction) + { + if (Registry.TryGetValue(attacker, out var timer) && timer.Defender == defender) + { + damageReduction = timer.DamageReduction; + return true; + } + + damageReduction = 0; + return false; + } + + public class FeintTimer : Timer + { + private readonly Mobile _attacker; + public Mobile Defender { get; } + + public FeintTimer(Mobile attacker, Mobile defender, int damageReduction) : base(TimeSpan.FromSeconds(6.0)) + { + _attacker = attacker; + Defender = defender; + DamageReduction = damageReduction; + } + + public int DamageReduction { get; } + + protected override void OnTick() => Registry.Remove(_attacker); } } diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index 3c5bc16b7..13232f808 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -1385,11 +1385,6 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab bonus += duelWield.BonusSwingSpeed; } - if (Feint.Registry.TryGetValue(m, out var feint)) - { - bonus -= feint.SwingSpeedReduction; - } - var context = TransformationSpellHelper.GetContext(m); if (context?.Spell is ReaperFormSpell spell) @@ -1985,6 +1980,12 @@ public abstract partial class BaseWeapon : Item, IWeapon, IFactionItem, ICraftab move = null; } + if (Feint.GetDamageReduction(attacker, defender, out var feintReduction)) + { + // example: 35 damage * 50 / 100 = 17 damage + damage -= damage * feintReduction / 100; + } + var ignoreArmor = a is ArmorIgnore || move?.IgnoreArmor(attacker) == true || Bladeweave.BladeWeaving(attacker, out var bladeweavingAbi) && diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 16bf662b2..09a6e452e 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -1013,6 +1013,12 @@ namespace Server.Spells bcTarget?.AlterSpellDamageFrom(from, ref dmg); + if (Feint.GetDamageReduction(from, target, out int feintReduction)) + { + // example: 35 damage * 50 / 100 = 17 damage + dmg -= dmg * feintReduction / 100; + } + StaminaSystem.DFA = dfa; var damageGiven = AOS.Damage(target, from, dmg, phys, fire, cold, pois, nrgy, chaos);