From 060edaa76a370448f14e03a4aef69e80719b0f31 Mon Sep 17 00:00:00 2001 From: mark1145 Date: Wed, 28 Sep 2022 15:19:15 +1000 Subject: [PATCH] fix: Fixes disarm, strangle, curse, summons, looting rights, creatures attacking, and items going to the floor (#1174) * Fixes disarm * Fixes strangle not refreshing * Fixes curse not refreshing * Fixes 125% bonus to looting rights * Fixes mobs attacking each other, or not attacking each other * Fixes items dropping to the floor * Fixes protection spell * Fixes cure sending wrong message --- Projects/Server/Items/Item.cs | 6 +- .../Items/Weapons/Abilities/Disarm.cs | 2 +- Projects/UOContent/Misc/Notoriety.cs | 13 +++- Projects/UOContent/Mobiles/AI/BaseAI.cs | 6 +- Projects/UOContent/Mobiles/BaseCreature.cs | 22 ++++-- Projects/UOContent/Mobiles/PlayerMobile.cs | 4 +- Projects/UOContent/Spells/Base/SpellHelper.cs | 76 +++++++++---------- .../Spells/Chivalry/CleanseByFire.cs | 2 +- .../UOContent/Spells/Eighth/AirElemental.cs | 2 +- .../UOContent/Spells/Eighth/EarthElemental.cs | 2 +- .../UOContent/Spells/Eighth/FireElemental.cs | 2 +- .../UOContent/Spells/Eighth/SummonDaemon.cs | 2 +- .../UOContent/Spells/Eighth/WaterElemental.cs | 2 +- Projects/UOContent/Spells/First/Clumsy.cs | 4 +- Projects/UOContent/Spells/First/Feeblemind.cs | 4 +- Projects/UOContent/Spells/First/Weaken.cs | 4 +- Projects/UOContent/Spells/Fourth/Curse.cs | 35 +++++---- .../UOContent/Spells/Necromancy/Strangle.cs | 14 ++-- Projects/UOContent/Spells/Second/Agility.cs | 4 +- Projects/UOContent/Spells/Second/Cunning.cs | 4 +- Projects/UOContent/Spells/Second/Cure.cs | 2 +- .../UOContent/Spells/Second/Protection.cs | 4 +- Projects/UOContent/Spells/Second/Strength.cs | 4 +- Projects/UOContent/Spells/Sixth/MassCurse.cs | 9 +-- Projects/UOContent/Spells/Third/Bless.cs | 10 +-- 25 files changed, 127 insertions(+), 112 deletions(-) diff --git a/Projects/Server/Items/Item.cs b/Projects/Server/Items/Item.cs index cf220e7bb..911557ede 100644 --- a/Projects/Server/Items/Item.cs +++ b/Projects/Server/Items/Item.cs @@ -2050,9 +2050,9 @@ namespace Server var root = ip.RootParent; var rpm = root as Mobile; - if (ip.IsAccessibleTo(from) && - rpm?.CheckNonlocalDrop(from, this, ip) == true && - (!ip.Movable || rpm == from || ip.Map == bounce.Map && root.Location == bounce.WorldLoc) + if (ip.IsAccessibleTo(from) + && rpm?.CheckNonlocalDrop(from, this, ip) != false + && (!ip.Movable || rpm == from || ip.Map == bounce.Map && root.Location == bounce.WorldLoc) ) { Location = bounce.Location; diff --git a/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs b/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs index f3ede2c1d..d6aab6fdb 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs @@ -44,7 +44,7 @@ namespace Server.Items var toDisarm = defender.FindItemOnLayer(Layer.OneHanded); - if (toDisarm?.Movable != false) + if (toDisarm?.Movable != true) { toDisarm = defender.FindItemOnLayer(Layer.TwoHanded); } diff --git a/Projects/UOContent/Misc/Notoriety.cs b/Projects/UOContent/Misc/Notoriety.cs index 3579e988b..3dfd5d0a5 100644 --- a/Projects/UOContent/Misc/Notoriety.cs +++ b/Projects/UOContent/Misc/Notoriety.cs @@ -176,11 +176,12 @@ namespace Server.Misc return true; } + var bcFrom = from as BaseCreature; var pmFrom = from as PlayerMobile; var pmTarg = target as PlayerMobile; var bcTarg = target as BaseCreature; - if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned) + if (pmFrom == null && bcFrom?.Summoned == true) { pmFrom = bcFrom.SummonMaster as PlayerMobile; } @@ -257,9 +258,15 @@ namespace Server.Misc return true; // Guild allies or enemies can be harmful } - if (bcTarg?.Controlled == true || bcTarg?.Summoned == true && bcTarg.SummonMaster != from) + if (bcTarg?.Controlled == true + || (bcTarg?.Summoned == true && bcTarg.SummonMaster != from && bcTarg.SummonMaster.Player)) { - return false; // Cannot harm other controlled mobiles + return false; // Cannot harm other controlled mobiles from players + } + + if (pmFrom == null && bcFrom != null && bcFrom.Summoned && target.Player) + { + return true; // Summons from monsters can attack players } if (target.Player) diff --git a/Projects/UOContent/Mobiles/AI/BaseAI.cs b/Projects/UOContent/Mobiles/AI/BaseAI.cs index 3011a84f1..1c3af5465 100644 --- a/Projects/UOContent/Mobiles/AI/BaseAI.cs +++ b/Projects/UOContent/Mobiles/AI/BaseAI.cs @@ -2734,13 +2734,13 @@ public abstract class BaseAI private bool IsHostile(Mobile from) { - var count = Math.Max(m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count); - - if (count <= 0 || m_Mobile.Combatant == from || from.Combatant == m_Mobile) + if (m_Mobile.Combatant == from || from.Combatant == m_Mobile) { return true; } + var count = Math.Max(m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count); + for (var a = 0; a < count; ++a) { if (a < m_Mobile.Aggressed.Count && m_Mobile.Aggressed[a].Attacker == from) diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs index 77fd6749a..c22c2a9e6 100644 --- a/Projects/UOContent/Mobiles/BaseCreature.cs +++ b/Projects/UOContent/Mobiles/BaseCreature.cs @@ -125,7 +125,7 @@ namespace Server.Mobiles m_Damage = damage; } - public int CompareTo(DamageStore ds) => ds?.m_Damage ?? 0 - m_Damage; + public int CompareTo(DamageStore ds) => (ds?.m_Damage ?? 0).CompareTo(m_Damage); } [AttributeUsage(AttributeTargets.Class)] @@ -2977,6 +2977,7 @@ namespace Server.Mobiles public static List GetLootingRights(List damageEntries, int hitsMax) { var rights = new List(); + DamageStore firstDamager = null; for (var i = damageEntries.Count - 1; i >= 0; --i) { @@ -3017,12 +3018,15 @@ namespace Server.Mobiles { ds.m_Damage += subEntry.DamageGiven; needNewSubEntry = false; + firstDamager = ds; } } if (needNewSubEntry) { - rights.Add(new DamageStore(master, subEntry.DamageGiven)); + var ds = new DamageStore(master, subEntry.DamageGiven); + rights.Add(ds); + firstDamager = ds; } damage -= subEntry.DamageGiven; @@ -3030,7 +3034,7 @@ namespace Server.Mobiles var m = de.Damager; - if (m?.Deleted != false || !m.Player) + if (m is not { Deleted: false, Player: true }) { continue; } @@ -3050,19 +3054,25 @@ namespace Server.Mobiles { ds.m_Damage += damage; needNewEntry = false; + firstDamager = ds; } } if (needNewEntry) { - rights.Add(new DamageStore(m, damage)); + var ds = new DamageStore(m, damage); + rights.Add(ds); + firstDamager = ds; } } + // Handle damage rights per Five on Friday: https://www.uoguide.com/Five_on_Friday_-_January_19,_2007 if (rights.Count > 0) { - // This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday - rights[0].m_Damage = (int)(rights[0].m_Damage * 1.25); + if (firstDamager != null) + { + firstDamager.m_Damage = (int)(firstDamager.m_Damage * 1.25); + } if (rights.Count > 1) { diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index be6ffe14e..8366e4d05 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -1143,9 +1143,9 @@ namespace Server.Mobiles var max = base.GetMaxResistance(type); - if (type != ResistanceType.Physical && max > 60 && CurseSpell.UnderEffect(this)) + if (type != ResistanceType.Physical && CurseSpell.UnderEffect(this)) { - max = 60; + max -= 10; } if (Core.ML && Race == Race.Elf && type == ResistanceType.Energy) diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 1acb95a58..2452dff8d 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -147,8 +147,6 @@ namespace Server.Spells private static Mobile m_TravelCaster; private static TravelCheckType m_TravelType; - public static bool DisableSkillCheck { get; set; } - public static TimeSpan GetDamageDelayForSpell(Spell sp) => !sp.DelayedDamage ? TimeSpan.Zero : Core.AOS ? AosDamageDelay : OldDamageDelay; @@ -225,7 +223,7 @@ namespace Server.Spells { var info = m.Aggressors[i]; - if (info.Attacker.Player && Core.Now - info.LastCombatTime < CombatHeatDelay) + if (info.Attacker.Player && info.Attacker == m && Core.Now - info.LastCombatTime < CombatHeatDelay) { return true; } @@ -292,13 +290,14 @@ namespace Server.Spells ? AddStatBonus(m, m, type, offset, duration) : offset >= 0 || AddStatCurse(m, m, type, -offset, duration); - public static bool AddStatBonus(Mobile caster, Mobile target, StatType type) => AddStatBonus( - caster, - target, - type, - GetOffset(caster, target, type, false), - GetDuration(caster, target) - ); + public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, TimeSpan duration, bool skillCheck = true) => + AddStatBonus( + caster, + target, + type, + GetOffset(caster, target, type, false, skillCheck), + duration + ); public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, int bonus, TimeSpan duration) { @@ -322,13 +321,14 @@ namespace Server.Spells return false; } - public static bool AddStatCurse(Mobile caster, Mobile target, StatType type) => AddStatCurse( - caster, - target, - type, - GetOffset(caster, target, type, true), - GetDuration(caster, target) - ); + public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, TimeSpan duration, bool skillCheck = true) => + AddStatCurse( + caster, + target, + type, + GetOffset(caster, target, type, true, skillCheck), + duration + ); public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, int curse, TimeSpan duration) { @@ -374,34 +374,32 @@ namespace Server.Spells return Math.Max(percent, 0); } - public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse) + public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse, bool skillCheck) { - if (Core.AOS) + if (!Core.AOS) { - if (!DisableSkillCheck) + return 1 + (int)(caster.Skills.Magery.Value * 0.1); + } + + if (skillCheck) + { + caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0); + + if (curse) { - caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0); - - if (curse) - { - target.CheckSkill(SkillName.MagicResist, 0.0, 120.0); - } - } - - var percent = GetOffsetScalar(caster, target, curse); - - switch (type) - { - case StatType.Str: - return (int)(target.RawStr * percent); - case StatType.Dex: - return (int)(target.RawDex * percent); - case StatType.Int: - return (int)(target.RawInt * percent); + target.CheckSkill(SkillName.MagicResist, 0.0, 120.0); } } - return 1 + (int)(caster.Skills.Magery.Value * 0.1); + var percent = GetOffsetScalar(caster, target, curse); + + return type switch + { + StatType.Str => (int)(target.RawStr * percent), + StatType.Dex => (int)(target.RawDex * percent), + StatType.Int => (int)(target.RawInt * percent), + _ => 1 + (int)(caster.Skills.Magery.Value * 0.1) + }; } public static Guild GetGuildFor(Mobile m) diff --git a/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs b/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs index 952dd7ce9..e184d2b9e 100644 --- a/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs +++ b/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs @@ -65,7 +65,7 @@ namespace Server.Spells.Chivalry } else { - m.SendLocalizedMessage(1010060); // You have failed to cure your target! + Caster.SendLocalizedMessage(1010060); // You have failed to cure your target! } } diff --git a/Projects/UOContent/Spells/Eighth/AirElemental.cs b/Projects/UOContent/Spells/Eighth/AirElemental.cs index 7da080b32..e88c35fff 100644 --- a/Projects/UOContent/Spells/Eighth/AirElemental.cs +++ b/Projects/UOContent/Spells/Eighth/AirElemental.cs @@ -46,7 +46,7 @@ namespace Server.Spells.Eighth { Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value), // T2A -> Current - _ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)), + _ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)), }; if (Core.AOS) diff --git a/Projects/UOContent/Spells/Eighth/EarthElemental.cs b/Projects/UOContent/Spells/Eighth/EarthElemental.cs index 0ab19a94c..6298728b5 100644 --- a/Projects/UOContent/Spells/Eighth/EarthElemental.cs +++ b/Projects/UOContent/Spells/Eighth/EarthElemental.cs @@ -46,7 +46,7 @@ namespace Server.Spells.Eighth { Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value), // T2A -> Current - _ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)), + _ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)), }; if (Core.AOS) diff --git a/Projects/UOContent/Spells/Eighth/FireElemental.cs b/Projects/UOContent/Spells/Eighth/FireElemental.cs index 7a599a7a1..718c547a7 100644 --- a/Projects/UOContent/Spells/Eighth/FireElemental.cs +++ b/Projects/UOContent/Spells/Eighth/FireElemental.cs @@ -47,7 +47,7 @@ namespace Server.Spells.Eighth { Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value), // T2A -> Current - _ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)), + _ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)), }; if (Core.AOS) diff --git a/Projects/UOContent/Spells/Eighth/SummonDaemon.cs b/Projects/UOContent/Spells/Eighth/SummonDaemon.cs index d5634b546..430114d01 100644 --- a/Projects/UOContent/Spells/Eighth/SummonDaemon.cs +++ b/Projects/UOContent/Spells/Eighth/SummonDaemon.cs @@ -47,7 +47,7 @@ namespace Server.Spells.Eighth { Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value), // T2A -> Current - _ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)), + _ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)), }; if (Core.AOS) /* Why two diff daemons? TODO: solve this */ diff --git a/Projects/UOContent/Spells/Eighth/WaterElemental.cs b/Projects/UOContent/Spells/Eighth/WaterElemental.cs index 26c9e1042..12c6325bc 100644 --- a/Projects/UOContent/Spells/Eighth/WaterElemental.cs +++ b/Projects/UOContent/Spells/Eighth/WaterElemental.cs @@ -46,7 +46,7 @@ namespace Server.Spells.Eighth { Expansion.None => TimeSpan.FromSeconds(Caster.Skills.Magery.Value), // T2A -> Current - _ => TimeSpan.FromSeconds(4 * Math.Min(5, Caster.Skills.Magery.Value)), + _ => TimeSpan.FromSeconds(4 * Math.Max(5, Caster.Skills.Magery.Value)), }; if (Core.AOS) diff --git a/Projects/UOContent/Spells/First/Clumsy.cs b/Projects/UOContent/Spells/First/Clumsy.cs index e777ea455..0626ce762 100644 --- a/Projects/UOContent/Spells/First/Clumsy.cs +++ b/Projects/UOContent/Spells/First/Clumsy.cs @@ -27,7 +27,8 @@ namespace Server.Spells.First SpellHelper.CheckReflect((int)Circle, Caster, ref m); - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length, false); m.Spell?.OnCasterHurt(); @@ -37,7 +38,6 @@ namespace Server.Spells.First m.PlaySound(0x1DF); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Clumsy, 1075831, length, m, percentage.ToString())); diff --git a/Projects/UOContent/Spells/First/Feeblemind.cs b/Projects/UOContent/Spells/First/Feeblemind.cs index 674c71b3e..ab0f8aa24 100644 --- a/Projects/UOContent/Spells/First/Feeblemind.cs +++ b/Projects/UOContent/Spells/First/Feeblemind.cs @@ -29,7 +29,8 @@ namespace Server.Spells.First // TODO: StoneForm immunity - SpellHelper.AddStatCurse(Caster, m, StatType.Int); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatCurse(Caster, m, StatType.Int, length, false); m.Spell?.OnCasterHurt(); @@ -39,7 +40,6 @@ namespace Server.Spells.First m.PlaySound(0x1E4); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.FeebleMind, 1075833, length, m, percentage.ToString())); diff --git a/Projects/UOContent/Spells/First/Weaken.cs b/Projects/UOContent/Spells/First/Weaken.cs index cdac84af0..5af8168f5 100644 --- a/Projects/UOContent/Spells/First/Weaken.cs +++ b/Projects/UOContent/Spells/First/Weaken.cs @@ -27,7 +27,8 @@ namespace Server.Spells.First SpellHelper.CheckReflect((int)Circle, Caster, ref m); - SpellHelper.AddStatCurse(Caster, m, StatType.Str); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false); m.Spell?.OnCasterHurt(); @@ -37,7 +38,6 @@ namespace Server.Spells.First m.PlaySound(0x1E6); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Weaken, 1075837, length, m, percentage.ToString())); diff --git a/Projects/UOContent/Spells/Fourth/Curse.cs b/Projects/UOContent/Spells/Fourth/Curse.cs index 2eb06c82d..0e0cb518b 100644 --- a/Projects/UOContent/Spells/Fourth/Curse.cs +++ b/Projects/UOContent/Spells/Fourth/Curse.cs @@ -15,7 +15,7 @@ namespace Server.Spells.Fourth Reagent.SulfurousAsh ); - private static readonly HashSet _underEffect = new(); + private static readonly Dictionary _table = new(); public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, _info) { @@ -30,20 +30,16 @@ namespace Server.Spells.Fourth SpellHelper.Turn(Caster, m); SpellHelper.CheckReflect((int)Circle, Caster, ref m); + var length = SpellHelper.GetDuration(Caster, m); - SpellHelper.AddStatCurse(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); - SpellHelper.AddStatCurse(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; + SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false); + SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length); + SpellHelper.AddStatCurse(Caster, m, StatType.Int, length); - // On OSI you CAN curse yourself and get this effect. - if (Caster.Player && m.Player /*&& Caster != m */ && !UnderEffect(m)) + if (Caster.Player && m.Player) { - var duration = SpellHelper.GetDuration(Caster, m); - _underEffect.Add(m); - Timer.StartTimer(duration, () => RemoveEffect(m)); - m.UpdateResistances(); + RemoveEffect(m); + _table[m] = Timer.DelayCall(length, () => RemoveEffect(m)); } m.Spell?.OnCasterHurt(); @@ -54,8 +50,6 @@ namespace Server.Spells.Fourth m.PlaySound(0x1E1); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - var length = SpellHelper.GetDuration(Caster, m); - var args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}"; BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args)); @@ -73,11 +67,16 @@ namespace Server.Spells.Fourth public static bool RemoveEffect(Mobile m) { - var effectRemoved = _underEffect.Remove(m); - m.UpdateResistances(); - return effectRemoved; + if (_table.Remove(m, out var timer)) + { + timer.Stop(); + m.UpdateResistances(); + return true; + } + + return false; } - public static bool UnderEffect(Mobile m) => _underEffect.Contains(m); + public static bool UnderEffect(Mobile m) => _table.ContainsKey(m); } } diff --git a/Projects/UOContent/Spells/Necromancy/Strangle.cs b/Projects/UOContent/Spells/Necromancy/Strangle.cs index 39c012493..8c1fff766 100644 --- a/Projects/UOContent/Spells/Necromancy/Strangle.cs +++ b/Projects/UOContent/Spells/Necromancy/Strangle.cs @@ -38,9 +38,9 @@ namespace Server.Spells.Necromancy SpellHelper.Turn(Caster, m); // SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m ); - // Irrelevent after AoS + // Irrelevant after AoS - /* Temporarily chokes off the air suply of the target with poisonous fumes. + /* Temporarily chokes off the air supply of the target with poisonous fumes. * The target is inflicted with poison damage over time. * The amount of damage dealt each "hit" is based off of the caster's Spirit Speak skill and the Target's current Stamina. * The less Stamina the target has, the more damage is done by Strangle. @@ -60,12 +60,16 @@ namespace Server.Spells.Necromancy m.FixedParticles(0x36CB, 1, 9, 9911, 67, 5, EffectLayer.Head); m.FixedParticles(0x374A, 1, 17, 9502, 1108, 4, (EffectLayer)255); - if (!_table.TryGetValue(m, out var timer)) + // According to testing on OSI, it is refreshed. + if (_table.TryGetValue(m, out var timer)) { - _table[m] = timer = new InternalTimer(m, Caster); - timer.Start(); + timer.Stop(); } + timer = new InternalTimer(m, Caster); + _table[m] = timer; + timer.Start(); + HarmfulSpell(m); } diff --git a/Projects/UOContent/Spells/Second/Agility.cs b/Projects/UOContent/Spells/Second/Agility.cs index c7843437f..9479245be 100644 --- a/Projects/UOContent/Spells/Second/Agility.cs +++ b/Projects/UOContent/Spells/Second/Agility.cs @@ -26,13 +26,13 @@ namespace Server.Spells.Second { SpellHelper.Turn(Caster, m); - SpellHelper.AddStatBonus(Caster, m, StatType.Dex); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatBonus(Caster, m, StatType.Dex, length, false); m.FixedParticles(0x375A, 10, 15, 5010, EffectLayer.Waist); m.PlaySound(0x1e7); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString())); } diff --git a/Projects/UOContent/Spells/Second/Cunning.cs b/Projects/UOContent/Spells/Second/Cunning.cs index 353ff9715..ad3aeac36 100644 --- a/Projects/UOContent/Spells/Second/Cunning.cs +++ b/Projects/UOContent/Spells/Second/Cunning.cs @@ -26,13 +26,13 @@ namespace Server.Spells.Second { SpellHelper.Turn(Caster, m); - SpellHelper.AddStatBonus(Caster, m, StatType.Int); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatBonus(Caster, m, StatType.Int, length, false); m.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head); m.PlaySound(0x1EB); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString())); } diff --git a/Projects/UOContent/Spells/Second/Cure.cs b/Projects/UOContent/Spells/Second/Cure.cs index 895f9eb89..c6ffde6b9 100644 --- a/Projects/UOContent/Spells/Second/Cure.cs +++ b/Projects/UOContent/Spells/Second/Cure.cs @@ -48,7 +48,7 @@ namespace Server.Spells.Second } else { - m.SendLocalizedMessage(1010060); // You have failed to cure your target! + Caster.SendLocalizedMessage(1010060); // You have failed to cure your target! } } diff --git a/Projects/UOContent/Spells/Second/Protection.cs b/Projects/UOContent/Spells/Second/Protection.cs index 8271276b5..3e76b0a97 100644 --- a/Projects/UOContent/Spells/Second/Protection.cs +++ b/Projects/UOContent/Spells/Second/Protection.cs @@ -77,8 +77,8 @@ namespace Server.Spells.Second target.PlaySound(0x1E9); target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); - var physLoss = Math.Max(0, -15 + (int)(caster.Skills.Inscribe.Value / 20)); - var resistLoss = Math.Max(0, -35 + (int)(caster.Skills.Inscribe.Value / 20)); + var physLoss = -15 + (int)(caster.Skills.Inscribe.Value / 20); + var resistLoss = -35 + (int)(caster.Skills.Inscribe.Value / 20); var physMod = new ResistanceMod(ResistanceType.Physical, physLoss); var resistMod = new DefaultSkillMod(SkillName.MagicResist, true, resistLoss); diff --git a/Projects/UOContent/Spells/Second/Strength.cs b/Projects/UOContent/Spells/Second/Strength.cs index 0896c0402..22f665a45 100644 --- a/Projects/UOContent/Spells/Second/Strength.cs +++ b/Projects/UOContent/Spells/Second/Strength.cs @@ -26,13 +26,13 @@ namespace Server.Spells.Second { SpellHelper.Turn(Caster, m); - SpellHelper.AddStatBonus(Caster, m, StatType.Str); + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatBonus(Caster, m, StatType.Str, length, false); m.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist); m.PlaySound(0x1EE); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - var length = SpellHelper.GetDuration(Caster, m); BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString())); } diff --git a/Projects/UOContent/Spells/Sixth/MassCurse.cs b/Projects/UOContent/Spells/Sixth/MassCurse.cs index 069805a0f..1bdb9d20b 100644 --- a/Projects/UOContent/Spells/Sixth/MassCurse.cs +++ b/Projects/UOContent/Spells/Sixth/MassCurse.cs @@ -44,11 +44,10 @@ namespace Server.Spells.Sixth Caster.DoHarmful(m); - SpellHelper.AddStatCurse(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); - SpellHelper.AddStatCurse(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatCurse(Caster, m, StatType.Str, length, false); + SpellHelper.AddStatCurse(Caster, m, StatType.Dex, length); + SpellHelper.AddStatCurse(Caster, m, StatType.Int, length); m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); m.PlaySound(0x1FB); diff --git a/Projects/UOContent/Spells/Third/Bless.cs b/Projects/UOContent/Spells/Third/Bless.cs index 8bf3803ed..09ea960e7 100644 --- a/Projects/UOContent/Spells/Third/Bless.cs +++ b/Projects/UOContent/Spells/Third/Bless.cs @@ -26,17 +26,15 @@ namespace Server.Spells.Third { SpellHelper.Turn(Caster, m); - SpellHelper.AddStatBonus(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatBonus(Caster, m, StatType.Dex); - SpellHelper.AddStatBonus(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; + var length = SpellHelper.GetDuration(Caster, m); + SpellHelper.AddStatBonus(Caster, m, StatType.Str, length, false); + SpellHelper.AddStatBonus(Caster, m, StatType.Dex, length); + SpellHelper.AddStatBonus(Caster, m, StatType.Int, length); m.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); m.PlaySound(0x1EA); var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - var length = SpellHelper.GetDuration(Caster, m); var args = $"{percentage}\t{percentage}\t{percentage}";