From a236617ad93bfff45be2f90b59e43cc1dacc0df8 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 13 Sep 2020 20:20:44 -0700 Subject: [PATCH] Some cleanup of contains keys and try get values (#246) --- Projects/Server/ContextMenus/ContextMenu.cs | 4 +- Projects/Server/Items/Container.cs | 8 +- Projects/Server/Items/Item.cs | 26 +- Projects/Server/Mobiles/Mobile.cs | 34 +- Projects/Server/Network/PacketHandlers.cs | 38 +- Projects/Server/SecureTrade.cs | 18 +- Projects/Server/Targeting/Target.cs | 14 +- Projects/UOContent/Accounting/Account.cs | 178 +++- .../UOContent/Accounting/AccountHandler.cs | 57 +- Projects/UOContent/Commands/HelpInfo.cs | 55 +- .../UOContent/Engines/Craft/Core/Recipes.cs | 2 + .../Engines/Spawners/SpawnerEntry.cs | 14 +- Projects/UOContent/Gumps/AdminGump.cs | 460 +++++++++- Projects/UOContent/Gumps/Props/PropsGump.cs | 214 ++++- .../Halloween/2012/Engines/PlayerZombies.cs | 18 +- .../Items/Containers/FurnitureContainer.cs | 13 +- Projects/UOContent/Items/Food/Beverage.cs | 105 ++- .../UOContent/Items/Misc/Corpses/Corpse.cs | 146 ++- Projects/UOContent/Items/Misc/Key.cs | 53 +- Projects/UOContent/Items/Misc/KeyRing.cs | 25 +- Projects/UOContent/Items/Misc/Teleporter.cs | 12 +- .../BaseConflagrationPotion.cs | 3 +- .../BaseConfusionBlastPotion.cs | 3 +- .../Magical/Potions/InvisibilityPotion.cs | 6 +- .../Items/Skill Items/Thief/DisguiseKit.cs | 3 +- .../Items/Weapons/Abilities/BleedAttack.cs | 13 +- .../Items/Weapons/Abilities/Block.cs | 13 +- .../Items/Weapons/Abilities/MortalStrike.cs | 12 +- .../Items/Weapons/Abilities/ParalyzingBlow.cs | 13 +- .../UOContent/Items/Weapons/BaseWeapon.cs | 864 +++++++++++++++++- .../Items/Weapons/Ranged/BaseRanged.cs | 26 +- Projects/UOContent/Misc/AOS.cs | 2 +- Projects/UOContent/Misc/Guild.cs | 225 ++++- Projects/UOContent/Misc/InhumanSpeech.cs | 60 ++ Projects/UOContent/Mobiles/AI/SpeedInfo.cs | 4 +- .../Mobiles/Monsters/LBR/Meers/MeerMage.cs | 3 +- .../UOContent/Mobiles/Monsters/SE/Kappa.cs | 3 +- Projects/UOContent/Mobiles/PlayerMobile.cs | 34 +- .../Mobiles/Townfolk/BaseEscortable.cs | 84 +- Projects/UOContent/Multis/ContestHouses.cs | 43 +- Projects/UOContent/Multis/HouseFoundation.cs | 304 +++++- Projects/UOContent/Regions/GuardedRegion.cs | 3 +- Projects/UOContent/Skills/Tracking.cs | 42 +- .../SpecialSystems/Engines/PreventInaccess.cs | 10 +- Projects/UOContent/Spells/Base/SpecialMove.cs | 42 +- Projects/UOContent/Spells/Base/Spell.cs | 120 ++- Projects/UOContent/Spells/Base/SpellHelper.cs | 150 ++- .../UOContent/Spells/Base/SpellRegistry.cs | 3 +- .../UOContent/Spells/Bushido/Confidence.cs | 6 +- .../UOContent/Spells/Bushido/CounterAttack.cs | 3 +- Projects/UOContent/Spells/Bushido/Evasion.cs | 3 +- .../Spells/Bushido/HonorableExecution.cs | 21 +- .../UOContent/Spells/Fifth/MagicReflect.cs | 17 +- .../UOContent/Spells/First/ReactiveArmor.cs | 17 +- .../UOContent/Spells/Fourth/ArchProtection.cs | 3 +- .../Spells/Mysticism/StoneFormSpell.cs | 12 +- .../Spells/Necromancy/AnimateDeadSpell.cs | 48 +- .../Spells/Necromancy/BloodOathSpell.cs | 15 +- .../UOContent/Spells/Necromancy/EvilOmen.cs | 7 +- .../UOContent/Spells/Necromancy/MindRot.cs | 5 +- .../UOContent/Spells/Necromancy/Strangle.cs | 25 +- .../UOContent/Spells/Ninjitsu/DeathStrike.cs | 32 +- .../UOContent/Spells/Ninjitsu/KiAttack.cs | 9 +- .../Spells/Ninjitsu/SurpriseAttack.cs | 4 +- .../UOContent/Spells/Second/Protection.cs | 14 +- .../UOContent/Spells/Sixth/Invisibility.cs | 9 +- .../Spells/Spellweaving/GiftOfRenewal.cs | 10 +- .../Spells/Spellweaving/ImmolatingWeapon.cs | 7 +- .../Spells/Spellweaving/Thunderstorm.cs | 9 +- 69 files changed, 3508 insertions(+), 350 deletions(-) diff --git a/Projects/Server/ContextMenus/ContextMenu.cs b/Projects/Server/ContextMenus/ContextMenu.cs index d3cb9207c..65f771282 100644 --- a/Projects/Server/ContextMenus/ContextMenu.cs +++ b/Projects/Server/ContextMenus/ContextMenu.cs @@ -31,11 +31,11 @@ namespace Server.ContextMenus if (target is Mobile mobile) { - mobile.GetContextMenuEntries(@from, list); + mobile.GetContextMenuEntries(from, list); } else if (target is Item item) { - item.GetContextMenuEntries(@from, list); + item.GetContextMenuEntries(from, list); } Entries = list.ToArray(); diff --git a/Projects/Server/Items/Container.cs b/Projects/Server/Items/Container.cs index a079e36b3..164d03bb6 100644 --- a/Projects/Server/Items/Container.cs +++ b/Projects/Server/Items/Container.cs @@ -570,7 +570,7 @@ namespace Server.Items for (var i = 0; i < stackItems.Count; i++) { - stackItems[i].m_StackItem.StackWith(@from, stackItems[i].m_DropItem, false); + stackItems[i].m_StackItem.StackWith(from, stackItems[i].m_DropItem, false); } return true; @@ -674,7 +674,7 @@ namespace Server.Items if (CheckContentDisplay(from)) { - LabelTo(@from, "({0} item{2}, {1} stones)", TotalItems, TotalWeight, TotalItems != 1 ? "s" : string.Empty); + LabelTo(from, "({0} item{2}, {1} stones)", TotalItems, TotalWeight, TotalItems != 1 ? "s" : string.Empty); } // LabelTo( from, 1050044, String.Format( "{0}\t{1}", TotalItems.ToString(), TotalWeight.ToString() ) ); @@ -824,11 +824,11 @@ namespace Server.Items { if (from.AccessLevel > AccessLevel.Player || from.InRange(GetWorldLocation(), 2)) { - DisplayTo(@from); + DisplayTo(from); } else { - @from.SendLocalizedMessage(500446); // That is too far away. + from.SendLocalizedMessage(500446); // That is too far away. } } diff --git a/Projects/Server/Items/Item.cs b/Projects/Server/Items/Item.cs index 9cf08fc5e..c04ef3817 100644 --- a/Projects/Server/Items/Item.cs +++ b/Projects/Server/Items/Item.cs @@ -2254,11 +2254,11 @@ namespace Server { if (m_Parent is Item parentItem) { - parentItem.GetChildContextMenuEntries(@from, list, item); + parentItem.GetChildContextMenuEntries(from, list, item); } else if (m_Parent is Mobile parentMobile) { - parentMobile.GetChildContextMenuEntries(@from, list, item); + parentMobile.GetChildContextMenuEntries(from, list, item); } } @@ -2266,11 +2266,11 @@ namespace Server { if (m_Parent is Item item) { - item.GetChildContextMenuEntries(@from, list, this); + item.GetChildContextMenuEntries(from, list, this); } else if (m_Parent is Mobile mobile) { - mobile.GetChildContextMenuEntries(@from, list, this); + mobile.GetChildContextMenuEntries(from, list, this); } } @@ -3241,7 +3241,7 @@ namespace Server // OSI sends 1074769, bug! if (QuestItem) { - @from.SendLocalizedMessage( + from.SendLocalizedMessage( 1049343 ); // You can only drop quest items into the top-most level of your backpack while you still need them for your quest. } @@ -3667,7 +3667,7 @@ namespace Server if (target is Container container && p.m_X != -1 && p.m_Y != -1) { - return OnDroppedInto(@from, container, p); + return OnDroppedInto(from, container, p); } return OnDroppedOnto(from, target); @@ -4212,11 +4212,11 @@ namespace Server { if (m_Parent is Item parentItem) { - parentItem.OnItemUsed(@from, item); + parentItem.OnItemUsed(from, item); } else if (m_Parent is Mobile parentMobile) { - parentMobile.OnItemUsed(@from, item); + parentMobile.OnItemUsed(from, item); } } @@ -4234,11 +4234,11 @@ namespace Server { if (m_Parent is Item parentItem) { - parentItem.OnItemLifted(@from, item); + parentItem.OnItemLifted(from, item); } else if (m_Parent is Mobile parentMobile) { - parentMobile.OnItemLifted(@from, item); + parentMobile.OnItemLifted(from, item); } } @@ -4261,7 +4261,7 @@ namespace Server { if (m_Parent is Item parentItem) { - parentItem.OnSingleClickContained(@from, item); + parentItem.OnSingleClickContained(from, item); } } @@ -4271,7 +4271,7 @@ namespace Server if (opl.Header > 0) { - @from.Send( + from.Send( new MessageLocalized( Serial, m_ItemID, @@ -4295,7 +4295,7 @@ namespace Server if (DisplayLootType) { - LabelLootTypeTo(@from); + LabelLootTypeTo(from); } var ns = from.NetState; diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index 5b1e30d17..a4cbef921 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -3758,7 +3758,7 @@ namespace Server } else { - hue = Notoriety.GetHue(Notoriety.Compute(@from, this)); + hue = Notoriety.GetHue(Notoriety.Compute(from, this)); } from.Send(new MessageLocalized(Serial, Body, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); @@ -5571,7 +5571,7 @@ namespace Server { if (item.QuestItem) { - @from.SendLocalizedMessage(1074868); // Stacks of quest items cannot be unstacked. + from.SendLocalizedMessage(1074868); // Stacks of quest items cannot be unstacked. } reject = LRReason.CannotLift; @@ -5634,7 +5634,7 @@ namespace Server foreach (var ns in eable) { - if (ns.Mobile != @from && ns.Mobile.CanSee(@from) && ns.Mobile.InLOS(@from) && + if (ns.Mobile != from && ns.Mobile.CanSee(from) && ns.Mobile.InLOS(from) && ns.Mobile.CanSee(root)) { if (p == null) @@ -5645,7 +5645,7 @@ namespace Server map ); - p = Packet.Acquire(new DragEffect(src, @from, item.ItemID, item.Hue, amount)); + p = Packet.Acquire(new DragEffect(src, from, item.ItemID, item.Hue, amount)); } ns.Send(p); @@ -5671,7 +5671,7 @@ namespace Server if (liftSound != -1) { - @from.Send(new PlaySound(liftSound, @from)); + from.Send(new PlaySound(liftSound, from)); } from.NextActionTime = Core.TickCount + ActionDelay; @@ -5845,7 +5845,7 @@ namespace Server if (to == null || !item.DropToItem(from, to, loc)) { - item.Bounce(@from); + item.Bounce(from); } else { @@ -5882,7 +5882,7 @@ namespace Server if (!item.DropToWorld(from, loc)) { - item.Bounce(@from); + item.Bounce(from); } else { @@ -5919,7 +5919,7 @@ namespace Server if (to == null || !item.DropToMobile(from, to, loc)) { - item.Bounce(@from); + item.Bounce(from); } else { @@ -6443,7 +6443,7 @@ namespace Server if (from != null) { - RegisterDamage(amount, @from); + RegisterDamage(amount, from); } DisruptiveAction(); @@ -6473,7 +6473,7 @@ namespace Server if (informMount) { - Mount?.OnRiderDamaged(amount, @from, newHits < 0); + Mount?.OnRiderDamaged(amount, from, newHits < 0); } if (newHits < 0) @@ -8624,7 +8624,7 @@ namespace Server { if (from.Map == Map && Utility.InUpdateRange(this, from) && from.CanSee(this)) { - @from.Send(new MobileStatus(@from, this, m_NetState)); + from.Send(new MobileStatus(from, this, m_NetState)); } if (from == this) @@ -8634,7 +8634,7 @@ namespace Server if (Party is IParty ip) { - ip.OnStatsQuery(@from, this); + ip.OnStatsQuery(from, this); } } @@ -8708,7 +8708,7 @@ namespace Server } else { - hue = Notoriety.GetHue(Notoriety.Compute(@from, this)); + hue = Notoriety.GetHue(Notoriety.Compute(from, this)); } var name = Name ?? string.Empty; @@ -10143,7 +10143,7 @@ namespace Server if (CanPaperdollBeOpenedBy(from)) { - DisplayPaperdollTo(@from); + DisplayPaperdollTo(from); } } @@ -10175,7 +10175,7 @@ namespace Server { if (CanPaperdollBeOpenedBy(from)) { - DisplayPaperdollTo(@from); + DisplayPaperdollTo(from); } } @@ -10590,11 +10590,11 @@ namespace Server { if (m_CallbackHandlesCancel && m_Callback != null) { - m_Callback(@from, ""); + m_Callback(from, ""); } else { - m_CancelCallback?.Invoke(@from, ""); + m_CancelCallback?.Invoke(from, ""); } } } diff --git a/Projects/Server/Network/PacketHandlers.cs b/Projects/Server/Network/PacketHandlers.cs index de5cb0336..8f41acf22 100644 --- a/Projects/Server/Network/PacketHandlers.cs +++ b/Projects/Server/Network/PacketHandlers.cs @@ -433,7 +433,7 @@ namespace Server.Network if (targ != null) { - EventSink.InvokeRenameRequest(@from, targ, pvSrc.ReadStringSafe()); + EventSink.InvokeRenameRequest(from, targ, pvSrc.ReadStringSafe()); } } @@ -631,7 +631,7 @@ namespace Server.Network if (item != null && from.Map == item.Map && Utility.InUpdateRange(item.GetWorldLocation(), from.Location) && from.CanSee(item)) { - item.OnHelpRequest(@from); + item.OnHelpRequest(from); } } else if (serial.IsMobile) @@ -668,7 +668,7 @@ namespace Server.Network if (m != null) { - @from.Attack(m); + from.Attack(m); } } @@ -827,11 +827,11 @@ namespace Server.Network if (type == 0) { - p.OnCancel(@from); + p.OnCancel(from); } else { - p.OnResponse(@from, text); + p.OnResponse(from, text); } } } @@ -858,11 +858,11 @@ namespace Server.Network if (type == 0) { - p.OnCancel(@from); + p.OnCancel(from); } else { - p.OnResponse(@from, text); + p.OnResponse(from, text); } } } @@ -970,7 +970,7 @@ namespace Server.Network if (!to.AllowEquipFrom(from) || !to.EquipItem(item)) { - item.Bounce(@from); + item.Bounce(from); } item.ClearBounce(); @@ -1458,7 +1458,7 @@ namespace Server.Network if (m?.Deleted == false) { - @from.Use(m); + from.Use(m); } } else if (s.IsItem) @@ -1467,7 +1467,7 @@ namespace Server.Network if (item?.Deleted == false) { - @from.Use(item); + from.Use(item); } } } @@ -1500,7 +1500,7 @@ namespace Server.Network { if (from.Region.OnSingleClick(from, m)) { - m.OnSingleClick(@from); + m.OnSingleClick(from); } } } @@ -1520,7 +1520,7 @@ namespace Server.Network { if (item.Parent is Item parentItem) { - parentItem.OnSingleClickContained(@from, item); + parentItem.OnSingleClickContained(from, item); } item.OnSingleClick(from); @@ -1581,7 +1581,7 @@ namespace Server.Network if (from != null && ok && from.Alive && from.Body.IsHuman && !from.Mounted) { - @from.Animate(action, 7, 1, true, false, 0); + from.Animate(action, 7, 1, true, false, 0); } } @@ -1711,7 +1711,7 @@ namespace Server.Network if (m != null && from.CanSee(m) && Utility.InUpdateRange(from, m)) { - m.SendPropertiesTo(@from); + m.SendPropertiesTo(from); } } else if (s.IsItem) @@ -1721,7 +1721,7 @@ namespace Server.Network if (item?.Deleted == false && from.CanSee(item) && Utility.InUpdateRange(from.Location, item.GetWorldLocation())) { - item.SendPropertiesTo(@from); + item.SendPropertiesTo(from); } } } @@ -1744,7 +1744,7 @@ namespace Server.Network if (m != null && from.CanSee(m) && Utility.InUpdateRange(from, m)) { - m.SendPropertiesTo(@from); + m.SendPropertiesTo(from); } } else if (s.IsItem) @@ -1754,7 +1754,7 @@ namespace Server.Network if (item?.Deleted == false && from.CanSee(item) && Utility.InUpdateRange(from.Location, item.GetWorldLocation())) { - item.SendPropertiesTo(@from); + item.SendPropertiesTo(from); } } } @@ -2031,12 +2031,12 @@ namespace Server.Network { case 0x04: // Stats { - m.OnStatsQuery(@from); + m.OnStatsQuery(from); break; } case 0x05: { - m.OnSkillsQuery(@from); + m.OnSkillsQuery(from); break; } default: diff --git a/Projects/Server/SecureTrade.cs b/Projects/Server/SecureTrade.cs index c82101e92..382c73277 100644 --- a/Projects/Server/SecureTrade.cs +++ b/Projects/Server/SecureTrade.cs @@ -25,22 +25,22 @@ namespace Server if (from6017) { - @from.Send(new SecureTradeEquip6017(To.Container, to)); + from.Send(new SecureTradeEquip6017(To.Container, to)); } else { - @from.Send(new SecureTradeEquip(To.Container, to)); + from.Send(new SecureTradeEquip(To.Container, to)); } from.Send(new UpdateSecureTrade(From.Container, false, false)); if (from6017) { - @from.Send(new SecureTradeEquip6017(From.Container, @from)); + from.Send(new SecureTradeEquip6017(From.Container, from)); } else { - @from.Send(new SecureTradeEquip(From.Container, @from)); + from.Send(new SecureTradeEquip(From.Container, from)); } from.Send(new DisplaySecureTrade(to, From.Container, To.Container, to.Name)); @@ -48,12 +48,12 @@ namespace Server if (from.Account != null && from704565) { - @from.Send( + from.Send( new UpdateSecureTrade( From.Container, TradeFlag.UpdateLedger, - @from.Account.TotalGold, - @from.Account.TotalPlat + from.Account.TotalGold, + from.Account.TotalPlat ) ); } @@ -63,11 +63,11 @@ namespace Server if (to6017) { - to.Send(new SecureTradeEquip6017(From.Container, @from)); + to.Send(new SecureTradeEquip6017(From.Container, from)); } else { - to.Send(new SecureTradeEquip(From.Container, @from)); + to.Send(new SecureTradeEquip(From.Container, from)); } to.Send(new UpdateSecureTrade(To.Container, false, false)); diff --git a/Projects/Server/Targeting/Target.cs b/Projects/Server/Targeting/Target.cs index 4b3480cba..afc912c05 100644 --- a/Projects/Server/Targeting/Target.cs +++ b/Projects/Server/Targeting/Target.cs @@ -168,31 +168,31 @@ namespace Server.Targeting { if (!from.CanSee(targeted)) { - OnCantSeeTarget(@from, targeted); + OnCantSeeTarget(from, targeted); } else if (CheckLOS && !from.InLOS(targeted)) { - OnTargetOutOfLOS(@from, targeted); + OnTargetOutOfLOS(from, targeted); } else if (item?.InSecureTrade == true) { - OnTargetInSecureTrade(@from, targeted); + OnTargetInSecureTrade(from, targeted); } else if (item?.IsAccessibleTo(from) == false) { - OnTargetNotAccessible(@from, targeted); + OnTargetNotAccessible(from, targeted); } else if (item?.CheckTarget(from, this, targeted) == false) { - OnTargetUntargetable(@from, targeted); + OnTargetUntargetable(from, targeted); } else if (mobile?.CheckTarget(from, this, mobile) == false) { - OnTargetUntargetable(@from, mobile); + OnTargetUntargetable(from, mobile); } else if (from.Region.OnTarget(from, this, targeted)) { - OnTarget(@from, targeted); + OnTarget(from, targeted); } } diff --git a/Projects/UOContent/Accounting/Account.cs b/Projects/UOContent/Accounting/Account.cs index ded506daa..a4ef8e9de 100644 --- a/Projects/UOContent/Accounting/Account.cs +++ b/Projects/UOContent/Accounting/Account.cs @@ -63,7 +63,9 @@ namespace Server.Accounting // Automatically upgrade plain passwords to current algorithm. if (!upgraded) + { SetPassword(Utility.GetText(node["password"], null)); + } } else { @@ -85,19 +87,31 @@ namespace Server.Accounting IPRestrictions = LoadAccessCheck(node); for (var i = 0; i < m_Mobiles.Length; ++i) + { if (m_Mobiles[i] != null) + { m_Mobiles[i].Account = this; + } + } var totalGameTime = Utility.GetXMLTimeSpan(Utility.GetText(node["totalGameTime"], null), TimeSpan.Zero); if (totalGameTime == TimeSpan.Zero) + { for (var i = 0; i < m_Mobiles.Length; i++) + { if (m_Mobiles[i] is PlayerMobile m) + { totalGameTime += m.GameTime; + } + } + } m_TotalGameTime = totalGameTime; if (Young) + { CheckYoung(); + } Accounts.Add(this); } @@ -148,15 +162,19 @@ namespace Server.Accounting var isBanned = GetFlag(0); if (!isBanned) + { return false; + } if (GetBanTags(out var banTime, out var banDuration)) + { if (banDuration != TimeSpan.MaxValue && DateTime.UtcNow >= banTime + banDuration) { SetUnspecifiedBan(null); // clear Banned = false; return false; } + } return true; } @@ -197,7 +215,9 @@ namespace Server.Accounting get { if (AccessLevel != AccessLevel.Player) + { return false; + } var inactiveLength = DateTime.UtcNow - LastLogin; @@ -214,8 +234,12 @@ namespace Server.Accounting get { for (var i = 0; i < m_Mobiles.Length; i++) + { if (m_Mobiles[i] is PlayerMobile m && m.NetState != null) + { return m_TotalGameTime + (DateTime.UtcNow - m.SessionStart); + } + } return m_TotalGameTime; } @@ -231,12 +255,16 @@ namespace Server.Accounting var m = this[i]; if (m == null) + { continue; + } var list = BaseHouse.GetHouses(m); for (var j = 0; j < list.Count; ++j) + { list[j].Delete(); + } m.Delete(); @@ -245,7 +273,9 @@ namespace Server.Accounting } if (LoginIPs.Length != 0 && AccountHandler.IPTable.ContainsKey(LoginIPs[0])) + { --AccountHandler.IPTable[LoginIPs[0]]; + } Accounts.Remove(Username); } @@ -283,11 +313,15 @@ namespace Server.Accounting var ok = AccountSecurity.GetPasswordProtection(m_PasswordAlgorithm).ValidatePassword(Password, phrase); if (!ok) + { return false; + } // Upgrade the password protection in case we change the algorithm if (m_PasswordAlgorithm != AccountSecurity.CurrentAlgorithm) + { SetPassword(plainPassword); + } return true; } @@ -302,8 +336,12 @@ namespace Server.Accounting var count = 0; for (var i = 0; i < Length; i++) + { if (this[i] != null) + { count++; + } + } return count; } @@ -334,7 +372,9 @@ namespace Server.Accounting var m = m_Mobiles[index]; if (m?.Deleted != true) + { return m; + } // This is the only place that clears a mobile for garbage collection // outside of an entire account deletion. @@ -349,12 +389,16 @@ namespace Server.Accounting if (index >= 0 && index < m_Mobiles.Length) { if (m_Mobiles[index] != null) + { m_Mobiles[index].Account = null; + } m_Mobiles[index] = value; if (m_Mobiles[index] != null) + { m_Mobiles[index].Account = this; + } } } } @@ -387,7 +431,10 @@ namespace Server.Accounting /// True if successful, false if amount given is less than or equal to zero. public bool DepositGold(int amount) { - if (amount <= 0) return false; + if (amount <= 0) + { + return false; + } var plat = Math.DivRem(amount, AccountGold.CurrencyThreshold, out var gold); TotalPlat += plat; @@ -403,7 +450,10 @@ namespace Server.Accounting /// True if successful, false if amount given is less than or equal to zero. public bool DepositPlat(int amount) { - if (amount <= 0) return false; + if (amount <= 0) + { + return false; + } TotalPlat += amount; return true; @@ -418,8 +468,15 @@ namespace Server.Accounting /// True if successful, false if balance was too low. public bool WithdrawGold(int amount) { - if (amount <= 0) return true; - if (amount > TotalGold) return false; + if (amount <= 0) + { + return true; + } + + if (amount > TotalGold) + { + return false; + } TotalGold -= amount; @@ -433,8 +490,15 @@ namespace Server.Accounting /// True if successful, false if balance was too low. public bool WithdrawPlat(int amount) { - if (amount <= 0) return true; - if (amount > TotalPlat) return false; + if (amount <= 0) + { + return true; + } + + if (amount > TotalPlat) + { + return false; + } TotalPlat -= amount; @@ -464,9 +528,13 @@ namespace Server.Accounting public void SetFlag(int index, bool value) { if (value) + { Flags |= 1 << index; + } else + { Flags &= ~(1 << index); + } } /// @@ -488,12 +556,16 @@ namespace Server.Accounting for (var i = Tags.Count - 1; i >= 0; --i) { if (i >= Tags.Count) + { continue; + } var tag = Tags[i]; if (tag.Name == name) + { Tags.RemoveAt(i); + } } } @@ -529,7 +601,9 @@ namespace Server.Accounting var tag = Tags[i]; if (tag.Name == name) + { return tag.Value; + } } return null; @@ -543,19 +617,31 @@ namespace Server.Accounting public void SetBanTags(Mobile from, DateTime banTime, TimeSpan banDuration) { if (from == null) + { RemoveTag("BanDealer"); + } else + { SetTag("BanDealer", from.ToString()); + } if (banTime == DateTime.MinValue) + { RemoveTag("BanTime"); + } else + { SetTag("BanTime", XmlConvert.ToString(banTime, XmlDateTimeSerializationMode.Utc)); + } if (banDuration == TimeSpan.Zero) + { RemoveTag("BanDuration"); + } else + { SetTag("BanDuration", banDuration.ToString()); + } } public bool GetBanTags(out DateTime banTime, out TimeSpan banDuration) @@ -565,11 +651,17 @@ namespace Server.Accounting banTime = Utility.GetXMLDateTime(GetTag("BanTime"), DateTime.MinValue); if (tagDuration == "Infinite") + { banDuration = TimeSpan.MaxValue; + } else if (tagDuration != null) + { banDuration = Utility.ToTimeSpan(tagDuration); + } else + { banDuration = TimeSpan.Zero; + } return banTime != DateTime.MinValue && banDuration != TimeSpan.Zero; } @@ -584,7 +676,9 @@ namespace Server.Accounting private static void EventSink_Connected(Mobile m) { if (!(m.Account is Account acc)) + { return; + } if (acc.Young && acc.m_YoungTimer == null) { @@ -596,7 +690,9 @@ namespace Server.Accounting private static void EventSink_Disconnected(Mobile m) { if (!(m.Account is Account acc)) + { return; + } if (acc.m_YoungTimer != null) { @@ -605,7 +701,9 @@ namespace Server.Accounting } if (!(m is PlayerMobile pm)) + { return; + } acc.m_TotalGameTime += DateTime.UtcNow - pm.SessionStart; } @@ -613,10 +711,14 @@ namespace Server.Accounting private static void EventSink_Login(Mobile m) { if (!(m is PlayerMobile pm)) + { return; + } if (!(m.Account is Account acc)) + { return; + } if (pm.Young && acc.Young) { @@ -636,6 +738,7 @@ namespace Server.Accounting Young = false; for (var i = 0; i < m_Mobiles.Length; i++) + { if (m_Mobiles[i] is PlayerMobile m && m.Young) { m.Young = false; @@ -643,26 +746,34 @@ namespace Server.Accounting if (m.NetState != null) { if (message > 0) + { m.SendLocalizedMessage(message); + } m.SendLocalizedMessage( 1019039 ); // You are no longer considered a young player of Ultima Online, and are no longer subject to the limitations and benefits of being in that caste. } } + } } public void CheckYoung() { if (TotalGameTime >= YoungDuration) + { RemoveYoungStatus( 1019038 ); // You are old enough to be considered an adult, and have outgrown your status as a young player! + } } private bool UpgradePassword(string password, PasswordProtectionAlgorithm algorithm) { - if (password == null || algorithm < m_PasswordAlgorithm) return false; + if (password == null || algorithm < m_PasswordAlgorithm) + { + return false; + } m_PasswordAlgorithm = algorithm; Password = password?.Replace("-", string.Empty); @@ -688,7 +799,9 @@ namespace Server.Accounting var text = Utility.GetText(ip, null); if (text != null) + { list.Add(text); + } } stringList = list.ToArray(); @@ -720,12 +833,16 @@ namespace Server.Accounting count = 0; foreach (XmlElement ip in addressList.GetElementsByTagName("ip")) + { if (count < list.Length) + { if (IPAddress.TryParse(Utility.GetText(ip, null), out var address)) { list[count] = Utility.Intern(address); count++; } + } + } if (count != list.Length) { @@ -733,7 +850,9 @@ namespace Server.Accounting list = new IPAddress[count]; for (var i = 0; i < count && i < old.Length; ++i) + { list[i] = old[i]; + } } } else @@ -759,19 +878,25 @@ namespace Server.Accounting // Above is legacy, no longer used if (chars != null) + { foreach (XmlElement ele in chars.GetElementsByTagName("char")) + { try { var index = Utility.GetXMLInt32(Utility.GetAttribute(ele, "index", "0"), 0); var serial = Utility.GetXMLUInt32(Utility.GetText(ele, "0"), 0); if (index >= 0 && index < list.Length) + { list[index] = World.FindMobile(serial); + } } catch { // ignored } + } + } return list; } @@ -791,6 +916,7 @@ namespace Server.Accounting list = new List(); foreach (XmlElement comment in comments.GetElementsByTagName("comment")) + { try { list.Add(new AccountComment(comment)); @@ -799,6 +925,7 @@ namespace Server.Accounting { // ignored } + } } return list; @@ -819,6 +946,7 @@ namespace Server.Accounting list = new List(); foreach (XmlElement tag in tags.GetElementsByTagName("tag")) + { try { list.Add(new AccountTag(tag)); @@ -827,6 +955,7 @@ namespace Server.Accounting { // ignored } + } } return list; @@ -848,26 +977,36 @@ namespace Server.Accounting var hasAccess = false; if (m_AccessLevel >= level) + { hasAccess = true; + } else + { for (var i = 0; !hasAccess && i < Length; ++i) { var m = this[i]; if (m?.AccessLevel >= level) + { hasAccess = true; + } } + } Console.WriteLine("{0} {1}", hasAccess ? "yes" : "no", m_AccessLevel); if (!hasAccess) + { return false; + } } var accessAllowed = IPRestrictions.Length == 0 || IPLimiter.IsExempt(ipAddress); for (var i = 0; !accessAllowed && i < IPRestrictions.Length; ++i) + { accessAllowed = Utility.IPMatch(IPRestrictions[i], ipAddress); + } return accessAllowed; } @@ -878,35 +1017,44 @@ namespace Server.Accounting /// NetState instance to record. public void LogAccess(NetState ns) { - if (ns != null) LogAccess(ns.Address); + if (ns != null) + { + LogAccess(ns.Address); + } } public void LogAccess(IPAddress ipAddress) { if (IPLimiter.IsExempt(ipAddress)) + { return; + } if (LoginIPs.Length == 0) { - if (AccountHandler.IPTable.ContainsKey(ipAddress)) - AccountHandler.IPTable[ipAddress]++; - else - AccountHandler.IPTable[ipAddress] = 1; + AccountHandler.IPTable.TryGetValue(ipAddress, out var result); + AccountHandler.IPTable[ipAddress] = result + 1; } var contains = false; for (var i = 0; !contains && i < LoginIPs.Length; ++i) + { contains = LoginIPs[i].Equals(ipAddress); + } if (contains) + { return; + } var old = LoginIPs; LoginIPs = new IPAddress[old.Length + 1]; for (var i = 0; i < old.Length; ++i) + { LoginIPs[i] = old[i]; + } LoginIPs[old.Length] = ipAddress; } @@ -924,7 +1072,9 @@ namespace Server.Accounting var hasAccess = HasAccess(ipAddress); if (hasAccess) + { LogAccess(ipAddress); + } return hasAccess; } @@ -997,7 +1147,9 @@ namespace Server.Accounting xml.WriteStartElement("comments"); for (var i = 0; i < m_Comments.Count; ++i) + { m_Comments[i].Save(xml); + } xml.WriteEndElement(); } @@ -1007,7 +1159,9 @@ namespace Server.Accounting xml.WriteStartElement("tags"); for (var i = 0; i < m_Tags.Count; ++i) + { m_Tags[i].Save(xml); + } xml.WriteEndElement(); } diff --git a/Projects/UOContent/Accounting/AccountHandler.cs b/Projects/UOContent/Accounting/AccountHandler.cs index 2b7926e25..5ac1e407a 100644 --- a/Projects/UOContent/Accounting/AccountHandler.cs +++ b/Projects/UOContent/Accounting/AccountHandler.cs @@ -38,7 +38,7 @@ namespace Server.Misc // Jhelom // .. new CityInfo( "Haven", "Buckler's Hideaway", 3667, 2625, 0 ) - + if (Core.AOS) { //CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3618, 2591, 0 ); @@ -65,11 +65,13 @@ namespace Server.Misc m_IPTable = new Dictionary(); foreach (Account a in Accounts.GetAccounts()) + { if (a.LoginIPs.Length > 0) { var ip = a.LoginIPs[0]; m_IPTable[ip] = (m_IPTable.TryGetValue(ip, out var value) ? value : 0) + 1; } + } } return m_IPTable; @@ -93,7 +95,9 @@ namespace Server.Misc EventSink.GameLogin += EventSink_GameLogin; if (PasswordCommandEnabled) + { CommandSystem.Register("Password", AccessLevel.Player, Password_OnCommand); + } } [Usage("Password ")] @@ -105,17 +109,23 @@ namespace Server.Misc var from = e.Mobile; if (!(from.Account is Account acct)) + { return; + } var accessList = acct.LoginIPs; if (accessList.Length == 0) + { return; + } var ns = from.NetState; if (ns == null) + { return; + } if (e.Length == 0) { @@ -142,7 +152,9 @@ namespace Server.Misc var isSafe = true; for (var i = 0; isSafe && i < pass.Length; ++i) + { isSafe = pass[i] >= 0x20 && pass[i] < 0x7F; + } if (!isSafe) { @@ -166,9 +178,13 @@ namespace Server.Misc if (entry != null) { if (entry.Message.StartsWith("[Automated: Change Password]")) + { from.SendMessage("You already have a password change request in the help system queue."); + } else + { from.SendMessage("Your IP address does not match that which created this account."); + } } else if (PageQueue.CheckAllowedToPage(from)) { @@ -246,19 +262,18 @@ namespace Server.Misc } } - public static bool CanCreate(IPAddress ip) - { - if (!IPTable.ContainsKey(ip)) - return true; - - return IPTable[ip] < MaxAccountsPerIP; - } + public static bool CanCreate(IPAddress ip) => + !IPTable.TryGetValue(ip, out var result) || result < MaxAccountsPerIP; private static bool IsForbiddenChar(char c) { for (var i = 0; i < m_ForbiddenChars.Length; ++i) + { if (c == m_ForbiddenChars[i]) + { return true; + } + } return false; } @@ -266,18 +281,26 @@ namespace Server.Misc private static Account CreateAccount(NetState state, string un, string pw) { if (un.Length == 0 || pw.Length == 0) + { return null; + } var isSafe = !(un.StartsWith(" ") || un.EndsWith(" ") || un.EndsWith(".")); for (var i = 0; isSafe && i < un.Length; ++i) + { isSafe = un[i] >= 0x20 && un[i] < 0x7F && !IsForbiddenChar(un[i]); + } for (var i = 0; isSafe && i < pw.Length; ++i) + { isSafe = pw[i] >= 0x20 && pw[i] < 0x7F; + } if (!isSafe) + { return null; + } if (!CanCreate(state.Address)) { @@ -307,10 +330,8 @@ namespace Server.Misc Console.WriteLine("Login: {0}: Past IP limit threshold", e.State); - using (var op = new StreamWriter("ipLimits.log", true)) - { - op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); - } + using var op = new StreamWriter("ipLimits.log", true); + op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); return; } @@ -329,7 +350,9 @@ namespace Server.Misc e.Accepted = acct?.CheckAccess(e.State) ?? false; if (!e.Accepted) + { e.RejectReason = ALRReason.BadComm; + } } else { @@ -362,7 +385,9 @@ namespace Server.Misc } if (!e.Accepted) + { AccountAttackLimiter.RegisterInvalidAccess(e.State); + } } public static void EventSink_GameLogin(GameLoginEventArgs e) @@ -414,15 +439,23 @@ namespace Server.Misc } if (!e.Accepted) + { AccountAttackLimiter.RegisterInvalidAccess(e.State); + } } public static bool CheckAccount(Mobile mobCheck, Mobile accCheck) { if (accCheck?.Account is Account a) + { for (var i = 0; i < a.Length; ++i) + { if (a[i] == mobCheck) + { return true; + } + } + } return false; } diff --git a/Projects/UOContent/Commands/HelpInfo.cs b/Projects/UOContent/Commands/HelpInfo.cs index 78729ceda..7a0239e3b 100644 --- a/Projects/UOContent/Commands/HelpInfo.cs +++ b/Projects/UOContent/Commands/HelpInfo.cs @@ -36,9 +36,13 @@ namespace Server.Commands var m = e.Mobile; if (m.AccessLevel >= c.AccessLevel) + { m.SendGump(new CommandInfoGump(c)); + } else + { m.SendMessage("You don't have access to that command."); + } return; } @@ -67,17 +71,23 @@ namespace Server.Commands var attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false); if (attrs.Length == 0) + { continue; + } var usage = attrs[0] as UsageAttribute; attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs.Length == 0) + { continue; + } if (usage == null || !(attrs[0] is DescriptionAttribute desc)) + { continue; + } attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false); @@ -114,14 +124,18 @@ namespace Server.Commands var desc = command.Description; if (usage == null || desc == null) + { continue; + } var cmds = command.Commands; var cmd = cmds[0]; var aliases = new string[cmds.Length - 1]; for (var j = 0; j < aliases.Length; ++j) + { aliases[j] = cmds[j + 1]; + } desc = desc.Replace("<", "(").Replace(">", ")"); @@ -132,25 +146,39 @@ namespace Server.Commands sb.Append("Modifiers: "); if ((command.Supports & CommandSupport.Global) != 0) + { sb.Append("Global, "); + } if ((command.Supports & CommandSupport.Online) != 0) + { sb.Append("Online, "); + } if ((command.Supports & CommandSupport.Region) != 0) + { sb.Append("Region, "); + } if ((command.Supports & CommandSupport.Contained) != 0) + { sb.Append("Contained, "); + } if ((command.Supports & CommandSupport.Multi) != 0) + { sb.Append("Multi, "); + } if ((command.Supports & CommandSupport.Area) != 0) + { sb.Append("Area, "); + } if ((command.Supports & CommandSupport.Self) != 0) + { sb.Append("Self, "); + } sb.Remove(sb.Length - 2, 2); sb.Append("
"); @@ -183,14 +211,18 @@ namespace Server.Commands var desc = command.Description; if (usage == null || desc == null) + { continue; + } var cmds = command.Accessors; var cmd = cmds[0]; var aliases = new string[cmds.Length - 1]; for (var j = 0; j < aliases.Length; ++j) + { aliases[j] = cmds[j + 1]; + } desc = desc.Replace("<", ")").Replace(">", ")"); @@ -213,8 +245,9 @@ namespace Server.Commands SortedHelpInfo = list; foreach (var c in SortedHelpInfo) - if (!HelpInfos.ContainsKey(c.Name.ToLower())) - HelpInfos.Add(c.Name.ToLower(), c); + { + HelpInfos.TryAdd(c.Name.ToLower(), c); + } } public class CommandListGump : BaseGridGump @@ -234,8 +267,12 @@ namespace Server.Commands m_List = new List(); foreach (var c in SortedHelpInfo) + { if (from.AccessLevel >= c.AccessLevel) + { m_List.Add(c); + } + } } else { @@ -245,9 +282,13 @@ namespace Server.Commands AddNewPage(); if (m_Page > 0) + { AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); + } else + { AddEntryHeader(20); + } AddEntryHtml( 160, @@ -257,9 +298,13 @@ namespace Server.Commands ); if ((m_Page + 1) * EntriesPerPage < m_List.Count) + { AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); + } else + { AddEntryHeader(20); + } var last = (int)AccessLevel.Player - 1; @@ -300,14 +345,18 @@ namespace Server.Commands case 1: { if (m_Page > 0) + { m.SendGump(new CommandListGump(m_Page - 1, m, m_List)); + } break; } case 2: { if ((m_Page + 1) * EntriesPerPage < SortedHelpInfo.Count) + { m.SendGump(new CommandListGump(m_Page + 1, m, m_List)); + } break; } @@ -369,7 +418,9 @@ namespace Server.Commands for (var i = 0; i < aliases.Length; ++i) { if (i != 0) + { sb.Append(", "); + } sb.Append(aliases[i]); } diff --git a/Projects/UOContent/Engines/Craft/Core/Recipes.cs b/Projects/UOContent/Engines/Craft/Core/Recipes.cs index 93d9c9854..77c5874d5 100644 --- a/Projects/UOContent/Engines/Craft/Core/Recipes.cs +++ b/Projects/UOContent/Engines/Craft/Core/Recipes.cs @@ -16,7 +16,9 @@ namespace Server.Engines.Craft CraftItem = item; if (Recipes.ContainsKey(id)) + { throw new Exception("Attempting to create recipe with preexisting ID."); + } Recipes.Add(id, this); LargestRecipeID = Math.Max(id, LargestRecipeID); diff --git a/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs b/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs index 683ae7686..5f8ca8338 100644 --- a/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs +++ b/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs @@ -33,18 +33,20 @@ namespace Server.Engines.Spawners for (var i = 0; i < count; ++i) // IEntity e = World.FindEntity( reader.ReadInt() ); + { if (reader.ReadEntity() is ISpawnable e) { e.Spawner = parent; if (e is BaseCreature creature) + { creature.RemoveIfUntamed = true; + } Spawned.Add(e); - - if (!parent.Spawned.ContainsKey(e)) - parent.Spawned.Add(e, this); + parent.Spawned.TryAdd(e, this); } + } } [JsonPropertyName("probability")] public int SpawnedProbability { get; set; } @@ -81,11 +83,17 @@ namespace Server.Engines.Spawners object o = Spawned[i]; if (o is Item item) + { writer.Write(item); + } else if (o is Mobile mobile) + { writer.Write(mobile); + } else + { writer.Write(Serial.MinusOne); + } } } diff --git a/Projects/UOContent/Gumps/AdminGump.cs b/Projects/UOContent/Gumps/AdminGump.cs index 621190c25..94fd09144 100644 --- a/Projects/UOContent/Gumps/AdminGump.cs +++ b/Projects/UOContent/Gumps/AdminGump.cs @@ -137,7 +137,9 @@ namespace Server.Gumps AddPageButton(10, 90, GetButtonID(0, 4), "FIREWALL", AdminGumpPage.Firewall, AdminGumpPage.FirewallInfo); if (notice != null) + { AddHtml(12, 392, 396, 36, Color(notice, LabelColor32)); + } switch (pageType) { @@ -147,10 +149,16 @@ namespace Server.Gumps var active = 0; foreach (Account acct in Accounts.GetAccounts()) + { if (acct.Banned) + { ++banned; + } else + { ++active; + } + } AddLabel(20, 130, LabelHue, "Active Accounts:"); AddLabel(150, 130, LabelHue, active.ToString()); @@ -194,16 +202,16 @@ namespace Server.Gumps AddLabel(150, 350, LabelHue, os); /*string str; - + try{ str = FormatTimeSpan( Core.Process.TotalProcessorTime ); } catch{ str = "(unable to retrieve)"; } - + AddLabel( 20, 330, LabelHue, "Process Time:" ); AddLabel( 250, 330, LabelHue, str );*/ /*try{ str = Core.Process.PriorityClass.ToString(); } catch{ str = "(unable to retrieve)"; } - + AddLabel( 20, 350, LabelHue, "Process Priority:" ); AddLabel( 250, 350, LabelHue, str );*/ @@ -374,7 +382,9 @@ namespace Server.Gumps AddButtonLabeled(220, 290, GetButtonID(3, 315), "Make Developer"); if (from.AccessLevel >= AccessLevel.Owner) + { AddButtonLabeled(220, 310, GetButtonID(3, 316), "Make Owner"); + } } } @@ -450,31 +460,48 @@ namespace Server.Gumps AddLabelCropped(273, 120, 109, 20, LabelHue, "IP Address"); if (listPage > 0) + { AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(375, 122, 0x25EA); + } if ((listPage + 1) * 12 < m_List.Count) + { AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(392, 122, 0x25E6); + } if (m_List.Count == 0) + { AddLabel(12, 140, LabelHue, "There are no clients to display."); + } for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) { if (!(m_List[index] is NetState ns)) + { continue; + } var m = ns.Mobile; var a = ns.Account as Account; var offset = 140 + i * 20; if (m == null) + { AddLabelCropped(12, offset, 81, 20, LabelHue, "(logging in)"); + } else + { AddLabelCropped(12, offset, 81, 20, GetHueFor(m), m.Name); + } + AddLabelCropped(95, offset, 81, 20, LabelHue, a == null ? "(no account)" : a.Username); AddLabelCropped( 178, @@ -489,7 +516,9 @@ namespace Server.Gumps AddLabelCropped(273, offset, 109, 20, LabelHue, ns.ToString()); if (a != null || m != null) + { AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(4, index + 2)); + } } break; @@ -497,7 +526,9 @@ namespace Server.Gumps case AdminGumpPage.ClientInfo: { if (!(state is Mobile m)) + { break; + } AddClientHeader(); @@ -596,17 +627,27 @@ namespace Server.Gumps AddLabelCropped(192, 120, 180, 20, LabelHue, "Accounts"); if (listPage > 0) + { AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(375, 122, 0x25EA); + } if ((listPage + 1) * 12 < sharedAccounts.Count) + { AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(392, 122, 0x25E6); + } if (sharedAccounts.Count == 0) + { AddLabel(12, 140, LabelHue, "There are no accounts to display."); + } var sb = new StringBuilder(); @@ -625,12 +666,16 @@ namespace Server.Gumps AddLabelCropped(72, offset, 120, 20, LabelHue, ipAddr.ToString()); if (sb.Length > 0) + { sb.Length = 0; + } for (var j = 0; j < accts.Count; ++j) { if (j > 0) + { sb.Append(", "); + } if (j < 4) { @@ -661,25 +706,39 @@ namespace Server.Gumps AddAccountHeader(); if (rads == null) + { AddLabelCropped(12, 120, 120, 20, LabelHue, "Name"); + } else + { AddLabelCropped(32, 120, 100, 20, LabelHue, "Name"); + } AddLabelCropped(132, 120, 120, 20, LabelHue, "Access Level"); AddLabelCropped(252, 120, 120, 20, LabelHue, "Status"); if (listPage > 0) + { AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(375, 122, 0x25EA); + } if ((listPage + 1) * 12 < m_List.Count) + { AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(392, 122, 0x25E6); + } if (m_List.Count == 0) + { AddLabel(12, 140, LabelHue, "There are no accounts to display."); + } if (rads != null && notice == null) { @@ -693,7 +752,9 @@ namespace Server.Gumps for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) { if (!(m_List[index] is Account a)) + { continue; + } var offset = 140 + i * 20; @@ -712,11 +773,17 @@ namespace Server.Gumps AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); if (online) + { AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + } else if (a.Banned) + { AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); + } else + { AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + } AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); } @@ -751,7 +818,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_ChangePassword: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Change Password"), LabelColor32)); @@ -771,7 +840,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_ChangeAccess: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Change Access Level"), LabelColor32)); @@ -795,7 +866,9 @@ namespace Server.Gumps AddButtonLabeled(20, 300, GetButtonID(5, 33), "Developer"); if (from.AccessLevel >= AccessLevel.Owner) + { AddButtonLabeled(20, 320, GetButtonID(5, 34), "Owner"); + } } } @@ -804,13 +877,19 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Information: { if (!(state is Account a)) + { break; + } var charCount = 0; for (var i = 0; i < a.Length; ++i) + { if (a[i] != null) + { ++charCount; + } + } AddHtml(10, 125, 400, 20, Color(Center("Information"), LabelColor32)); @@ -838,9 +917,13 @@ namespace Server.Gumps var remaining = DateTime.UtcNow - banTime; if (remaining < TimeSpan.Zero) + { remaining = TimeSpan.Zero; + } else if (remaining > banDuration) + { remaining = banDuration; + } var remMinutes = remaining.TotalMinutes; var totMinutes = banDuration.TotalMinutes; @@ -874,9 +957,13 @@ namespace Server.Gumps AddButtonLabeled(200, 320, GetButtonID(5, 9), "Change Access Level"); if (!a.Banned) + { AddButtonLabeled(20, 350, GetButtonID(5, 10), "Ban Account"); + } else + { AddButtonLabeled(20, 350, GetButtonID(5, 11), "Unban Account"); + } AddButtonLabeled(200, 350, GetButtonID(5, 25), "Delete Account"); @@ -885,7 +972,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Access: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Access"), LabelColor32)); @@ -909,7 +998,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Access_ClientIPs: { if (!(state is Account a)) + { break; + } List ipAddresses; @@ -944,17 +1035,27 @@ namespace Server.Gumps AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); if (listPage > 0) + { AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(184, 223, 0x25EA); + } if ((listPage + 1) * 6 < ipAddresses.Count) + { AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(201, 223, 0x25E6); + } if (ipAddresses.Count == 0) + { AddHtml(18, 243, 200, 60, Color("This account has not yet been accessed.", LabelColor32)); + } for (int i = 0, index = listPage * 6; i < 6 && index >= 0 && index < ipAddresses.Count; ++i, ++index) { @@ -969,7 +1070,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Access_Restrictions: { if (!(state is Account a)) + { break; + } List ipRestrictions; @@ -1006,17 +1109,27 @@ namespace Server.Gumps AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); if (listPage > 0) + { AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(184, 223, 0x25EA); + } if ((listPage + 1) * 6 < ipRestrictions.Count) + { AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(201, 223, 0x25E6); + } if (ipRestrictions.Count == 0) + { AddHtml(18, 243, 200, 60, Color("There are no addresses in this list.", LabelColor32)); + } for (int i = 0, index = listPage * 6; i < 6 && index >= 0 && index < ipRestrictions.Count; @@ -1031,7 +1144,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Characters: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Characters"), LabelColor32)); @@ -1046,7 +1161,9 @@ namespace Server.Gumps var m = a[i]; if (m == null) + { continue; + } var offset = 170 + index * 20; @@ -1054,9 +1171,13 @@ namespace Server.Gumps AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(m.AccessLevel)); if (m.NetState != null) + { AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + } else + { AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + } AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, i + 50)); @@ -1064,14 +1185,18 @@ namespace Server.Gumps } if (index == 0) + { AddLabel(12, 170, LabelHue, "The character list is empty."); + } goto case AdminGumpPage.AccountDetails; } case AdminGumpPage.AccountDetails_Comments: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Comments"), LabelColor32)); @@ -1080,12 +1205,16 @@ namespace Server.Gumps var sb = new StringBuilder(); if (a.Comments.Count == 0) + { sb.Append("There are no comments for this account."); + } for (var i = 0; i < a.Comments.Count; ++i) { if (i > 0) + { sb.Append("

"); + } var c = a.Comments[i]; @@ -1099,7 +1228,9 @@ namespace Server.Gumps case AdminGumpPage.AccountDetails_Tags: { if (!(state is Account a)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center("Tags"), LabelColor32)); @@ -1108,12 +1239,16 @@ namespace Server.Gumps var sb = new StringBuilder(); if (a.Tags.Count == 0) + { sb.Append("There are no tags for this account."); + } for (var i = 0; i < a.Tags.Count; ++i) { if (i > 0) + { sb.Append("
"); + } var tag = a.Tags[i]; @@ -1143,17 +1278,27 @@ namespace Server.Gumps AddLabelCropped(12, 120, 358, 20, LabelHue, "IP Address"); if (listPage > 0) + { AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(375, 122, 0x25EA); + } if ((listPage + 1) * 12 < firewallEntries.Count) + { AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(392, 122, 0x25E6); + } if (firewallEntries.Count == 0) + { AddLabel(12, 140, LabelHue, "The firewall list is empty."); + } for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < firewallEntries.Count; @@ -1174,7 +1319,9 @@ namespace Server.Gumps AddFirewallHeader(); if (!(state is Firewall.IFirewallEntry firewallEntry)) + { break; + } AddHtml(10, 125, 400, 20, Color(Center(firewallEntry.ToString()), LabelColor32)); @@ -1197,11 +1344,13 @@ namespace Server.Gumps var contains = false; for (var i = 0; !contains && i < loginList.Length; ++i) + { if (firewallEntry.IsBlocked(loginList[i])) { blockedAccts.Add(acct); break; } + } } blockedAccts.Sort(AccountComparer.Instance); @@ -1213,17 +1362,27 @@ namespace Server.Gumps } if (listPage > 0) + { AddButton(375, 177, 0x15E3, 0x15E7, GetButtonID(1, 0)); + } else + { AddImage(375, 177, 0x25EA); + } if ((listPage + 1) * 12 < blockedAccts.Count) + { AddButton(392, 177, 0x15E1, 0x15E5, GetButtonID(1, 1)); + } else + { AddImage(392, 177, 0x25E6); + } if (blockedAccts.Count == 0) + { AddLabelCropped(12, 200, 398, 20, LabelHue, "No accounts found."); + } for (int i = 0, index = listPage * 9; i < 9 && index >= 0 && index < blockedAccts.Count; @@ -1239,11 +1398,17 @@ namespace Server.Gumps AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); if (online) + { AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + } else if (a.Banned) + { AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); + } else + { AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + } AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); } @@ -1261,7 +1426,9 @@ namespace Server.Gumps var isSelection = m_PageType == page; for (var i = 0; !isSelection && i < subPages.Length; ++i) + { isSelection = m_PageType == subPages[i]; + } AddSelectedButton(x, y, buttonID, text, isSelection); } @@ -1296,13 +1463,19 @@ namespace Server.Gumps public static string FormatByteAmount(long totalBytes) { if (totalBytes > 1000000000) + { return $"{(double)totalBytes / 1073741824:F1} GB"; + } if (totalBytes > 1000000) + { return $"{(double)totalBytes / 1048576:F1} MB"; + } if (totalBytes > 1000) + { return $"{(double)totalBytes / 1024:F1} KB"; + } return $"{totalBytes} Bytes"; } @@ -1324,7 +1497,9 @@ namespace Server.Gumps public static int GetHueFor(Mobile m) { if (m == null) + { return LabelHue; + } switch (m.AccessLevel) { @@ -1337,7 +1512,9 @@ namespace Server.Gumps default: { if (m.Kills >= 5) + { return 0x21; + } return m.Criminal ? 0x3B1 : 0x58; } @@ -1349,7 +1526,9 @@ namespace Server.Gumps var v = (int)level; if (v >= 0 && v < m_AccessLevelStrings.Length) + { return m_AccessLevelStrings[v]; + } return "Unknown"; } @@ -1411,8 +1590,9 @@ namespace Server.Gumps var theirAddresses = acct.LoginIPs; for (var i = 0; i < theirAddresses.Length; ++i) - if (!table.ContainsKey(theirAddresses[i])) - table[theirAddresses[i]] = new List { acct }; + { + table.TryAdd(theirAddresses[i], new List { acct }); + } } var tableEntries = table.ToList(); @@ -1423,9 +1603,13 @@ namespace Server.Gumps var list = kvp.Value; if (kvp.Value.Count == 1) + { list.RemoveAt(i--); + } else + { list.Sort(AccountComparer.Instance); + } } tableEntries.Sort(SharedAccountComparer.Instance); @@ -1445,10 +1629,14 @@ namespace Server.Gumps var contains = false; for (var i = 0; !contains && i < theirAddresses.Length; ++i) + { contains = ipAddress.Equals(theirAddresses[i]); + } if (contains) + { list.Add(acct); + } } list.Sort(AccountComparer.Instance); @@ -1469,11 +1657,15 @@ namespace Server.Gumps var check = theirAddresses[i]; for (var j = 0; !contains && j < ipAddresses.Length; ++j) + { contains = check.Equals(ipAddresses[j]); + } } if (contains) + { list.Add(acct); + } } list.Sort(AccountComparer.Instance); @@ -1483,7 +1675,9 @@ namespace Server.Gumps public static void BanShared_Callback(Mobile from, bool okay, Account a) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } string notice; List list = null; @@ -1508,13 +1702,17 @@ namespace Server.Gumps from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); if (okay) + { from.SendGump(new BanDurationGump(list)); + } } public static void AccountDelete_Callback(Mobile from, bool okay, Account a) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } if (okay) { @@ -1555,7 +1753,9 @@ namespace Server.Gumps public static void ResendGump_Callback(Mobile from, List list, List rads, int page) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, page, list, null, rads)); } @@ -1563,12 +1763,16 @@ namespace Server.Gumps public static void Marked_Callback(Mobile from, bool okay, bool ban, List list, List rads, int page) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } if (okay) { if (!ban) + { NetState.Pause(); + } for (var i = 0; i < rads.Count; ++i) { @@ -1602,7 +1806,9 @@ namespace Server.Gumps } if (!ban) + { NetState.Resume(); + } from.SendGump( new NoticeGump( @@ -1617,7 +1823,9 @@ namespace Server.Gumps ); if (ban) + { from.SendGump(new BanDurationGump(rads)); + } } else { @@ -1638,14 +1846,18 @@ namespace Server.Gumps public static void FirewallShared_Callback(Mobile from, bool okay, Account a) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } string notice; if (okay) { for (var i = 0; i < a.LoginIPs.Length; ++i) + { Firewall.Add(a.LoginIPs[i]); + } notice = "All addresses in the list have been firewalled."; } @@ -1660,7 +1872,9 @@ namespace Server.Gumps public static void Firewall_Callback(Mobile from, bool okay, Account a, object toFirewall) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } string notice; @@ -1681,7 +1895,9 @@ namespace Server.Gumps public static void RemoveLoginIP_Callback(Mobile from, bool okay, Account a, IPAddress ip) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } string notice; @@ -1690,7 +1906,9 @@ namespace Server.Gumps var ips = a.LoginIPs; if (ips.Length != 0 && Equals(ip, ips[0]) && AccountHandler.IPTable.ContainsKey(ips[0])) + { --AccountHandler.IPTable[ip]; + } var newList = new List(ips); newList.Remove(ip); @@ -1709,7 +1927,9 @@ namespace Server.Gumps public static void RemoveLoginIPs_Callback(Mobile from, bool okay, Account a) { if (from.AccessLevel < AccessLevel.Administrator) + { return; + } string notice; @@ -1718,7 +1938,9 @@ namespace Server.Gumps var ips = a.LoginIPs; if (ips.Length != 0 && AccountHandler.IPTable.ContainsKey(ips[0])) + { --AccountHandler.IPTable[ips[0]]; + } a.LoginIPs = Array.Empty(); @@ -1737,18 +1959,23 @@ namespace Server.Gumps var val = info.ButtonID - 1; if (val < 0) + { return; + } var from = m_From; if (from.AccessLevel < AccessLevel.Administrator) + { return; + } if (m_PageType == AdminGumpPage.Accounts) { var list = Utility.CastListCovariant(m_List); if (list != null && m_State is List rads) + { for (int i = 0, v = m_ListPage * 12; i < 12 && v < list.Count; ++i, ++v) { var obj = list[v]; @@ -1756,13 +1983,16 @@ namespace Server.Gumps if (info.IsSwitched(v)) { if (!rads.Contains(obj)) + { rads.Add(obj); + } } else if (rads.Contains(obj)) { rads.Remove(obj); } } + } } var type = val % 11; @@ -1807,18 +2037,22 @@ namespace Server.Gumps case 0: { if (m_List != null && m_ListPage > 0) + { from.SendGump( new AdminGump(from, m_PageType, m_ListPage - 1, m_List, null, m_State) ); + } break; } case 1: { if (m_List != null /*&& (m_ListPage + 1) * 12 < m_List.Count*/) + { from.SendGump( new AdminGump(from, m_PageType, m_ListPage + 1, m_List, null, m_State) ); + } break; } @@ -1832,15 +2066,25 @@ namespace Server.Gumps var page = AdminGumpPage.Administer; if (index >= 500) + { page = AdminGumpPage.Administer_Access_Lockdown; + } else if (index >= 400) + { page = AdminGumpPage.Administer_Commands; + } else if (index >= 300) + { page = AdminGumpPage.Administer_Access; + } else if (index >= 200) + { page = AdminGumpPage.Administer_Server; + } else if (index >= 100) + { page = AdminGumpPage.Administer_WorldBuilding; + } switch (index) { @@ -2089,9 +2333,13 @@ namespace Server.Gumps AccountHandler.LockdownLevel = (AccessLevel)(index - 500); if (AccountHandler.LockdownLevel > AccessLevel.Player) + { notice = "The lockdown level has been changed."; + } else + { notice = "The server is now accessible to everyone."; + } break; } @@ -2111,20 +2359,28 @@ namespace Server.Gumps var a = ns.Account; if (a == null) + { continue; + } var hasAccess = false; if (a.AccessLevel >= level) + { hasAccess = true; + } else + { for (var j = 0; !hasAccess && j < a.Length; ++j) { var m = a[j]; if (m?.AccessLevel >= level) + { hasAccess = true; + } } + } if (!hasAccess) { @@ -2134,9 +2390,13 @@ namespace Server.Gumps } if (count == 0) + { notice = "Nobody without access was found to disconnect."; + } else + { notice = $"Number of players disconnected: {count}"; + } } else { @@ -2212,7 +2472,9 @@ namespace Server.Gumps } if (isMatch) + { results.Add(ns); + } } results.Sort(NetStateComparer.Instance); @@ -2224,6 +2486,7 @@ namespace Server.Gumps var state = ns.Mobile ?? (object)ns.Account; if (state is Mobile) + { from.SendGump( new AdminGump( from, @@ -2234,7 +2497,9 @@ namespace Server.Gumps state ) ); + } else if (state is Account) + { from.SendGump( new AdminGump( from, @@ -2245,7 +2510,9 @@ namespace Server.Gumps state ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2255,6 +2522,7 @@ namespace Server.Gumps "One match found." ) ); + } } else { @@ -2278,14 +2546,19 @@ namespace Server.Gumps if (m_List != null && index >= 0 && index < m_List.Count) { if (!(m_List[index] is NetState ns)) + { break; + } var m = ns.Mobile; var a = ns.Account as Account; if (m != null) + { from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); + } else if (a != null) + { from.SendGump( new AdminGump( from, @@ -2296,6 +2569,7 @@ namespace Server.Gumps a ) ); + } } break; @@ -2457,6 +2731,7 @@ namespace Server.Gumps } if (results.Count == 1) + { from.SendGump( new AdminGump( from, @@ -2467,7 +2742,9 @@ namespace Server.Gumps results[0] ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2478,6 +2755,7 @@ namespace Server.Gumps new List() ) ); + } break; } @@ -2509,7 +2787,9 @@ namespace Server.Gumps case 11: { if (!(m_State is Account a)) + { break; + } a.SetUnspecifiedBan(from); a.Banned = index == 10; @@ -2533,14 +2813,18 @@ namespace Server.Gumps ); if (index == 10) + { from.SendGump(new BanDurationGump(a)); + } break; } case 12: { if (!(m_State is Account a)) + { break; + } var passwordEntry = info.GetTextEntry(0); var confirmEntry = info.GetTextEntry(1); @@ -2581,11 +2865,14 @@ namespace Server.Gumps case 16: // view shared { if (!(m_State is Account a)) + { break; + } var list = GetSharedAccounts(a.LoginIPs); if (list.Count > 1 || list.Count == 1 && !list.Contains(a)) + { from.SendGump( new AdminGump( from, @@ -2596,7 +2883,9 @@ namespace Server.Gumps new List() ) ); + } else if (a.LoginIPs.Length > 0) + { from.SendGump( new AdminGump( from, @@ -2607,7 +2896,9 @@ namespace Server.Gumps m_State ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2618,13 +2909,16 @@ namespace Server.Gumps m_State ) ); + } break; } case 17: // ban shared { if (!(m_State is Account a)) + { break; + } var list = GetSharedAccounts(a.LoginIPs); @@ -2639,7 +2933,9 @@ namespace Server.Gumps ); for (var i = 0; i < list.Count; ++i) + { sb.AppendFormat("
- {0}", list[i].Username); + } from.SendGump( new WarningGump( @@ -2685,9 +2981,12 @@ namespace Server.Gumps case 18: // firewall all { if (!(m_State is Account a)) + { break; + } if (a.LoginIPs.Length > 0) + { from.SendGump( new WarningGump( 1060635, @@ -2699,7 +2998,9 @@ namespace Server.Gumps okay => FirewallShared_Callback(from, okay, a) ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2710,13 +3011,16 @@ namespace Server.Gumps m_State ) ); + } break; } case 19: // add { if (!(m_State is Account a)) + { break; + } var entry = info.GetTextEntry(0); var ip = entry?.Text.Trim(); @@ -2733,7 +3037,9 @@ namespace Server.Gumps var contains = false; for (var i = 0; !contains && i < list.Length; ++i) + { contains = list[i] == ip; + } if (contains) { @@ -2744,7 +3050,9 @@ namespace Server.Gumps var newList = new string[list.Length + 1]; for (var i = 0; i < list.Length; ++i) + { newList[i] = list[i]; + } newList[list.Length] = ip; @@ -2774,7 +3082,9 @@ namespace Server.Gumps case 24: { if (!(m_State is Account a)) + { break; + } var newLevel = index switch { @@ -2816,7 +3126,9 @@ namespace Server.Gumps case 25: { if (!(m_State is Account a)) + { break; + } from.SendGump( new WarningGump( @@ -2841,9 +3153,12 @@ namespace Server.Gumps var list = m_List; if (list == null || !(m_State is List rads)) + { break; + } if (rads.Count > 0) + { from.SendGump( new WarningGump( 1060635, @@ -2855,7 +3170,9 @@ namespace Server.Gumps okay => Marked_Callback(from, okay, true, list, rads, m_ListPage) ) ); + } else + { from.SendGump( new NoticeGump( 1060637, @@ -2867,6 +3184,7 @@ namespace Server.Gumps () => ResendGump_Callback(from, list, rads, m_ListPage) ) ); + } break; } @@ -2875,9 +3193,12 @@ namespace Server.Gumps var list = m_List; if (list == null || !(m_State is List rads)) + { break; + } if (rads.Count > 0) + { from.SendGump( new WarningGump( 1060635, @@ -2893,7 +3214,9 @@ namespace Server.Gumps okay => Marked_Callback(from, okay, false, list, rads, m_ListPage) ) ); + } else + { from.SendGump( new NoticeGump( 1060637, @@ -2905,13 +3228,16 @@ namespace Server.Gumps () => ResendGump_Callback(from, list, rads, m_ListPage) ) ); + } break; } case 29: // Mark all { if (m_List == null || !(m_State is List)) + { break; + } from.SendGump( new AdminGump( @@ -2935,13 +3261,18 @@ namespace Server.Gumps var empty = true; for (var i = 0; empty && i < acct.Length; ++i) + { empty = acct[i] == null; + } if (empty) + { results.Add(acct); + } } if (results.Count == 1) + { from.SendGump( new AdminGump( from, @@ -2952,7 +3283,9 @@ namespace Server.Gumps results[0] ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2963,6 +3296,7 @@ namespace Server.Gumps new List() ) ); + } break; } @@ -2971,10 +3305,15 @@ namespace Server.Gumps var results = new List(); foreach (Account acct in Accounts.GetAccounts()) + { if (acct.Inactive) + { results.Add(acct); + } + } if (results.Count == 1) + { from.SendGump( new AdminGump( from, @@ -2985,7 +3324,9 @@ namespace Server.Gumps results[0] ) ); + } else + { from.SendGump( new AdminGump( from, @@ -2996,6 +3337,7 @@ namespace Server.Gumps new List() ) ); + } break; } @@ -3004,10 +3346,15 @@ namespace Server.Gumps var results = new List(); foreach (Account acct in Accounts.GetAccounts()) + { if (acct.Banned) + { results.Add(acct); + } + } if (results.Count == 1) + { from.SendGump( new AdminGump( from, @@ -3018,7 +3365,9 @@ namespace Server.Gumps results[0] ) ); + } else + { from.SendGump( new AdminGump( from, @@ -3029,6 +3378,7 @@ namespace Server.Gumps new List() ) ); + } break; } @@ -3043,7 +3393,9 @@ namespace Server.Gumps var rads = m_State as List; if (list == null || rads == null) + { break; + } var newRads = new List(); @@ -3052,11 +3404,17 @@ namespace Server.Gumps var hasHouse = false; for (var i = 0; i < acct.Length && !hasHouse; ++i) + { if (acct[i] != null && BaseHouse.HasHouse(acct[i])) + { hasHouse = true; + } + } if (!hasHouse) + { newRads.Add(acct); + } } from.SendGump( @@ -3068,11 +3426,14 @@ namespace Server.Gumps case 36: // Clear login addresses { if (!(m_State is Account a)) + { break; + } var ips = a.LoginIPs; if (ips.Length == 0) + { from.SendGump( new AdminGump( from, @@ -3083,7 +3444,9 @@ namespace Server.Gumps m_State ) ); + } else + { from.SendGump( new WarningGump( 1060635, @@ -3095,6 +3458,7 @@ namespace Server.Gumps okay => RemoveLoginIPs_Callback(from, okay, a) ) ); + } break; } @@ -3107,7 +3471,9 @@ namespace Server.Gumps var m = a[index]; if (m != null) + { from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); + } } else { @@ -3116,6 +3482,7 @@ namespace Server.Gumps if (m_List != null && index >= 0 && index < m_List.Count) { if (m_List[index] is Account) + { from.SendGump( new AdminGump( from, @@ -3126,7 +3493,9 @@ namespace Server.Gumps m_List[index] ) ); + } else if (m_List[index] is KeyValuePair> kvp) + { from.SendGump( new AdminGump( from, @@ -3137,6 +3506,7 @@ namespace Server.Gumps new List() ) ); + } } } @@ -3159,17 +3529,24 @@ namespace Server.Gumps var results = new List(); if (string.IsNullOrEmpty(match)) + { notice = "You must enter a username to search."; + } else + { for (var i = 0; i < Firewall.List.Count; ++i) { var check = Firewall.List[i].ToString(); if (check?.IndexOf(match) >= 0) + { results.Add(Firewall.List[i]); + } } + } if (results.Count == 1) + { from.SendGump( new AdminGump( from, @@ -3180,7 +3557,9 @@ namespace Server.Gumps results[0] ) ); + } else if (results.Count > 1) + { from.SendGump( new AdminGump( from, @@ -3191,7 +3570,9 @@ namespace Server.Gumps m_State ) ); + } else + { from.SendGump( new AdminGump( from, @@ -3202,6 +3583,7 @@ namespace Server.Gumps m_State ) ); + } break; } @@ -3309,9 +3691,11 @@ namespace Server.Gumps index -= 4; if (m_List != null && index >= 0 && index < m_List.Count) + { from.SendGump( new AdminGump(from, AdminGumpPage.FirewallInfo, 0, null, null, m_List[index]) ); + } break; } @@ -3322,7 +3706,9 @@ namespace Server.Gumps case 7: { if (!(m_State is Mobile m)) + { break; + } string notice = null; var sendGump = true; @@ -3481,14 +3867,18 @@ namespace Server.Gumps } if (sendGump) + { from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, notice, m_State)); + } switch (index) { case 3: { if (m.Account is Account a) + { from.SendGump(new BanDurationGump(a)); + } break; } @@ -3511,7 +3901,9 @@ namespace Server.Gumps if (m_List != null && index >= 0 && index < m_List.Count) { if (!(m_State is Account a)) + { break; + } if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) { @@ -3551,19 +3943,25 @@ namespace Server.Gumps case 9: { if (m_List != null && index >= 0 && index < m_List.Count) + { if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) { var obj = m_List[index]; if (!(obj is IPAddress ip)) + { break; + } if (!(m_State is Account a)) + { break; + } var list = GetSharedAccounts(ip); if (list.Count > 1 || list.Count == 1 && !list.Contains(a)) + { from.SendGump( new AdminGump( from, @@ -3574,7 +3972,9 @@ namespace Server.Gumps new List() ) ); + } else + { from.SendGump( new AdminGump( from, @@ -3585,22 +3985,29 @@ namespace Server.Gumps a ) ); + } } + } break; } case 10: { if (m_List != null && index >= 0 && index < m_List.Count) + { if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) { var ip = m_List[index] as IPAddress; if (ip == null) + { break; + } if (!(m_State is Account a)) + { break; + } from.SendGump( new WarningGump( @@ -3614,6 +4021,7 @@ namespace Server.Gumps ) ); } + } break; } @@ -3632,7 +4040,9 @@ namespace Server.Gumps ); if (save) + { InvokeCommand("Save"); + } Core.Kill(restart); } @@ -3652,13 +4062,19 @@ namespace Server.Gumps var check = a[j]; if (check == null) + { continue; + } if (check.AccessLevel > accessLevel) + { accessLevel = check.AccessLevel; + } if (check.NetState != null) + { online = true; + } } } @@ -3778,24 +4194,42 @@ namespace Server.Gumps public int Compare(NetState x, NetState y) { if (x == null && y == null) + { return 0; + } + if (x == null) + { return -1; + } + if (y == null) + { return 1; + } var aMob = x.Mobile; var bMob = y.Mobile; if (aMob == null && bMob == null) + { return 0; + } + if (aMob == null) + { return 1; + } + if (bMob == null) + { return -1; + } if (aMob.AccessLevel > bMob.AccessLevel) + { return -1; + } return aMob.AccessLevel < bMob.AccessLevel ? 1 : Insensitive.Compare(aMob.Name, bMob.Name); } @@ -3808,21 +4242,37 @@ namespace Server.Gumps public int Compare(IAccount x, IAccount y) { if (x == null && y == null) + { return 0; + } + if (x == null) + { return -1; + } + if (y == null) + { return 1; + } GetAccountInfo(x, out var aLevel, out var aOnline); GetAccountInfo(y, out var bLevel, out var bOnline); if (aOnline && !bOnline) + { return -1; + } + if (bOnline && !aOnline) + { return 1; + } + if (aLevel > bLevel) + { return -1; + } return aLevel < bLevel ? 1 : Insensitive.Compare(x.Username, y.Username); } diff --git a/Projects/UOContent/Gumps/Props/PropsGump.cs b/Projects/UOContent/Gumps/Props/PropsGump.cs index 2a0d40ee3..fbce9d1e7 100644 --- a/Projects/UOContent/Gumps/Props/PropsGump.cs +++ b/Projects/UOContent/Gumps/Props/PropsGump.cs @@ -172,7 +172,9 @@ namespace Server.Gumps m_Object = o; if (o != null) + { m_Type = o.GetType(); + } m_List = list; m_Stack = stack; @@ -189,7 +191,9 @@ namespace Server.Gumps var lastIndex = page * EntryCount + count - 1; if (lastIndex >= 0 && lastIndex < m_List.Count && m_List[lastIndex] == null) + { --count; + } var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); @@ -210,24 +214,33 @@ namespace Server.Gumps var emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); if (OldStyle) + { AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + } else + { AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + } if (page > 0) { AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); if (PrevLabel) + { AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } } x += PrevWidth + OffsetSize; if (!OldStyle) + { AddImageTiled(x, y, emptyWidth, EntryHeight, HeaderGumpID); + } if (TypeLabel && m_Type != null) + { AddHtml( x, y, @@ -235,18 +248,23 @@ namespace Server.Gumps EntryHeight, $"
{m_Type.Name}
" ); + } x += emptyWidth + OffsetSize; if (!OldStyle) + { AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + } if ((page + 1) * EntryCount < m_List.Count) { AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1); if (NextLabel) + { AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } } for (int i = 0, index = page * EntryCount; i < count && index < m_List.Count; ++i, ++index) @@ -267,7 +285,9 @@ namespace Server.Gumps x += TypeWidth + OffsetSize; if (SetGumpID != 0) + { AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + } } else if (o is PropertyInfo prop) { @@ -279,13 +299,17 @@ namespace Server.Gumps x += ValueWidth + OffsetSize; if (SetGumpID != 0) + { AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + } var cpa = GetCPA(prop); if ((!prop.GetType().IsValueType || prop.CanWrite) && cpa != null && m_Mobile.AccessLevel >= cpa.WriteLevel && !cpa.ReadOnly) + { AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3); + } } } } @@ -315,14 +339,18 @@ namespace Server.Gumps case 1: // Previous { if (m_Page > 0) + { from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page - 1)); + } break; } case 2: // Next { if ((m_Page + 1) * EntryCount < m_List.Count) + { from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page + 1)); + } break; } @@ -335,13 +363,17 @@ namespace Server.Gumps var prop = m_List[index] as PropertyInfo; if (prop == null) + { return; + } var attr = GetCPA(prop); if (prop.GetType().IsValueType && !prop.CanWrite || attr == null || from.AccessLevel < attr.WriteLevel || attr.ReadOnly) + { return; + } var type = prop.PropertyType; @@ -454,9 +486,13 @@ namespace Server.Gumps var obj = prop.GetValue(m_Object, null); if (obj != null) + { from.SendGump(new PropertiesGump(from, obj, m_Stack, new StackEntry(m_Object, prop))); + } else + { from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page)); + } } } @@ -470,7 +506,9 @@ namespace Server.Gumps var list = new object[a.Length]; for (var i = 0; i < list.Length; ++i) + { list[i] = a.GetValue(i); + } return list; } @@ -480,15 +518,21 @@ namespace Server.Gumps public static void OnValueChanged(object obj, PropertyInfo prop, Stack stack) { if (stack == null || stack.Count == 0) + { return; + } if (!prop.PropertyType.IsValueType) + { return; + } var peek = stack.Peek(); if (peek.m_Property.CanWrite) + { peek.m_Property.SetValue(peek.m_Object, obj, null); + } } private static string[] GetCustomEnumNames(Type type) @@ -496,10 +540,14 @@ namespace Server.Gumps var attrs = type.GetCustomAttributes(typeofCustomEnum, false); if (attrs.Length == 0) + { return Array.Empty(); + } if (!(attrs[0] is CustomEnumAttribute ce)) + { return Array.Empty(); + } return ce.Names; } @@ -512,8 +560,12 @@ namespace Server.Gumps private static bool IsType(Type type, Type[] check) { for (var i = 0; i < check.Length; ++i) + { if (IsType(type, check[i])) + { return true; + } + } return false; } @@ -534,27 +586,68 @@ namespace Server.Gumps public static string ValueToString(object o) { - if (o == null) return "-null-"; - if (o is string s) return $"\"{s}\""; - if (o is bool) return o.ToString(); - if (o is char c) return $"0x{(int)c:X} '{c}'"; + if (o == null) + { + return "-null-"; + } + + if (o is string s) + { + return $"\"{s}\""; + } + + if (o is bool) + { + return o.ToString(); + } + + if (o is char c) + { + return $"0x{(int)c:X} '{c}'"; + } + if (o is Serial serial) { if (serial.IsValid) { - if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; - if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; + if (serial.IsItem) + { + return $"(I) 0x{serial.Value:X}"; + } + + if (serial.IsMobile) + { + return $"(M) 0x{serial.Value:X}"; + } } return $"(?) 0x{serial.Value:X}"; } if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) + { return $"{o} (0x{o:X})"; - if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; - if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; - if (o is Type type) return type.Name; - if (o is TextDefinition definition) return definition.Format(true); + } + + if (o is Mobile mobile) + { + return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; + } + + if (o is Item item) + { + return $"(I) 0x{item.Serial.Value:X}"; + } + + if (o is Type type) + { + return type.Name; + } + + if (o is TextDefinition definition) + { + return definition.Format(true); + } return o.ToString(); } @@ -564,7 +657,9 @@ namespace Server.Gumps var list = new List(); if (m_Type == null) + { return list; + } var props = m_Type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); @@ -575,10 +670,14 @@ namespace Server.Gumps var kvp = groups[i]; if (!HasAttribute(kvp.Key, typeofNoSort, false)) + { kvp.Value.Sort(PropertySorter.Instance); + } if (i != 0) + { list.Add(null); + } list.Add(kvp.Key); list.AddRange(kvp.Value); @@ -592,7 +691,10 @@ namespace Server.Gumps var attrs = prop.GetCustomAttributes(typeofCPA, false); if (attrs.Length > 0) + { return attrs[0] as CPA; + } + return null; } @@ -617,15 +719,24 @@ namespace Server.Gumps var baseType = type?.BaseType; if (baseType == typeofObject || baseType?.GetProperty(prop.Name, prop.PropertyType) == null) + { break; + } type = baseType; } - if (type != null && !groups.ContainsKey(type)) - groups[type] = new List { prop }; - else - groups[type].Add(prop); + if (type != null) + { + if (groups.TryGetValue(type, out var result)) + { + result.Add(prop); + } + else + { + groups[type] = new List { prop }; + } + } } } } @@ -638,7 +749,10 @@ namespace Server.Gumps public static object GetObjectFromString(Type t, string s) { - if (t == typeof(string)) return s; + if (t == typeof(string)) + { + return s; + } if (t == typeof(byte) || t == typeof(sbyte) || t == typeof(short) || t == typeof(ushort) || t == typeof(int) || t == typeof(uint) || t == typeof(long) || t == typeof(ulong)) @@ -646,7 +760,9 @@ namespace Server.Gumps if (s.StartsWith("0x")) { if (t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte)) + { return Convert.ChangeType(Convert.ToUInt64(s.Substring(2), 16), t); + } return Convert.ChangeType(Convert.ToInt64(s.Substring(2), 16), t); } @@ -654,7 +770,11 @@ namespace Server.Gumps return Convert.ChangeType(s, t); } - if (t == typeof(double) || t == typeof(float)) return Convert.ChangeType(s, t); + if (t == typeof(double) || t == typeof(float)) + { + return Convert.ChangeType(s, t); + } + if (t.IsDefined(typeof(ParsableAttribute), false)) { var parseMethod = t.GetMethod("Parse", new[] { typeof(string) }); @@ -667,26 +787,63 @@ namespace Server.Gumps private static string GetStringFromObject(object o) { - if (o == null) return "-null-"; - if (o is string s) return $"\"{s}\""; - if (o is bool) return o.ToString(); - if (o is char c) return $"0x{(int)c:X} '{c}'"; + if (o == null) + { + return "-null-"; + } + + if (o is string s) + { + return $"\"{s}\""; + } + + if (o is bool) + { + return o.ToString(); + } + + if (o is char c) + { + return $"0x{(int)c:X} '{c}'"; + } + if (o is Serial serial) { if (serial.IsValid) { - if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; - if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; + if (serial.IsItem) + { + return $"(I) 0x{serial.Value:X}"; + } + + if (serial.IsMobile) + { + return $"(M) 0x{serial.Value:X}"; + } } return $"(?) 0x{serial.Value:X}"; } if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) + { return $"{o} (0x{o:X})"; - if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; - if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; - if (o is Type type) return type.Name; + } + + if (o is Mobile mobile) + { + return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; + } + + if (o is Item item) + { + return $"(I) 0x{item.Serial.Value:X}"; + } + + if (o is Type type) + { + return type.Name; + } return o.ToString(); } @@ -702,9 +859,14 @@ namespace Server.Gumps public int Compare(PropertyInfo x, PropertyInfo y) { if (x == null && y == null) + { return 0; + } + if (x == null) + { return -1; + } return y == null ? 1 : x.Name.CompareTo(x.Name); } @@ -726,7 +888,9 @@ namespace Server.Gumps int dist; for (dist = 0; current != null && current != typeofObject && current != type; ++dist) + { current = current.BaseType; + } return dist; } diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs b/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs index 7c0a8cc0d..ff391b05b 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs @@ -69,7 +69,9 @@ namespace Server.Engines.Events { if (m is PlayerMobile pm && !pm.Deleted && m_Timer.Running && !m_DeathQueue.Contains(pm) && m_DeathQueue.Count < m_DeathQueueLimit) + { m_DeathQueue.Add(pm); + } } private static void Clear_Callback() @@ -78,7 +80,10 @@ namespace Server.Engines.Events m_DeathQueue.Clear(); - if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) m_ClearTimer.Stop(); + if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) + { + m_ClearTimer.Stop(); + } } private static void Timer_Callback() @@ -88,12 +93,15 @@ namespace Server.Engines.Events if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) { for (var index = 0; m_DeathQueue.Count > 0 && index < m_DeathQueue.Count; index++) - if (!ReAnimated.ContainsKey(m_DeathQueue[index])) - { - player = m_DeathQueue[index]; + { + var entry = m_DeathQueue[index]; + if (!ReAnimated.ContainsKey(entry)) + { + player = entry; break; } + } if (player?.Deleted == false && ReAnimated.Count < m_TotalZombieLimit) { @@ -244,7 +252,9 @@ namespace Server.Engines.Events public override void OnDelete() { if (m_DeadPlayer?.Deleted == false) + { HalloweenHauntings.ReAnimated?.Remove(m_DeadPlayer); + } } public override void Serialize(IGenericWriter writer) diff --git a/Projects/UOContent/Items/Containers/FurnitureContainer.cs b/Projects/UOContent/Items/Containers/FurnitureContainer.cs index 5169dc43b..2432ac979 100644 --- a/Projects/UOContent/Items/Containers/FurnitureContainer.cs +++ b/Projects/UOContent/Items/Containers/FurnitureContainer.cs @@ -197,7 +197,9 @@ namespace Server.Items var version = reader.ReadInt(); if (version == 0 && Weight == 1.0) + { Weight = -1; + } } } @@ -263,7 +265,9 @@ namespace Server.Items public override void DisplayTo(Mobile m) { if (DynamicFurniture.Open(this, m)) + { base.DisplayTo(m); + } } public override void Serialize(IGenericWriter writer) @@ -295,7 +299,9 @@ namespace Server.Items public override void DisplayTo(Mobile m) { if (DynamicFurniture.Open(this, m)) + { base.DisplayTo(m); + } } public override void Serialize(IGenericWriter writer) @@ -349,13 +355,13 @@ namespace Server.Items public static void Close(Container c) { - if (m_Table.TryGetValue(c, out var t)) + if (m_Table.Remove(c, out var t)) { t.Stop(); - m_Table.Remove(c); } if (c is Armoire || c is FancyArmoire) + { c.ItemID = c.ItemID switch { 0xA4C => 0xA4D, @@ -364,6 +370,7 @@ namespace Server.Items 0xA52 => 0xA53, _ => c.ItemID }; + } } } @@ -383,7 +390,9 @@ namespace Server.Items protected override void OnTick() { if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3)) + { DynamicFurniture.Close(m_Container); + } } } } diff --git a/Projects/UOContent/Items/Food/Beverage.cs b/Projects/UOContent/Items/Food/Beverage.cs index 3a345f06a..8789fa60e 100644 --- a/Projects/UOContent/Items/Food/Beverage.cs +++ b/Projects/UOContent/Items/Food/Beverage.cs @@ -52,6 +52,7 @@ namespace Server.Items public override int ComputeItemID() { if (!IsEmpty) + { switch (Content) { case BeverageType.Ale: return 0x99F; @@ -61,6 +62,7 @@ namespace Server.Items case BeverageType.Wine: return 0x9C7; case BeverageType.Water: return 0x99B; } + } return 0; } @@ -127,7 +129,9 @@ namespace Server.Items public override int ComputeItemID() { if (!IsEmpty) + { return 0x9C8; + } return 0; } @@ -168,9 +172,14 @@ namespace Server.Items public override int ComputeItemID() { if (ItemID >= 0x995 && ItemID <= 0x999) + { return ItemID; + } + if (ItemID == 0x9CA) + { return ItemID; + } return 0x995; } @@ -211,7 +220,9 @@ namespace Server.Items public override int ComputeItemID() { if (ItemID >= 0xFFF && ItemID <= 0x1002) + { return ItemID; + } return 0xFFF; } @@ -252,7 +263,9 @@ namespace Server.Items public override int ComputeItemID() { if (ItemID == 0x99A || ItemID == 0x9B3 || ItemID == 0x9BF || ItemID == 0x9CB) + { return ItemID; + } return 0x99A; } @@ -302,7 +315,9 @@ namespace Server.Items public override int ComputeItemID() { if (IsEmpty) + { return ItemID >= 0x1F81 && ItemID <= 0x1F84 ? ItemID : 0x1F81; + } return Content switch { @@ -406,7 +421,9 @@ namespace Server.Items if (IsEmpty) { if (ItemID == 0x9A7 || ItemID == 0xFF7) + { return ItemID; + } return 0xFF6; } @@ -416,42 +433,54 @@ namespace Server.Items case BeverageType.Ale: { if (ItemID == 0x1F96) + { return ItemID; + } return 0x1F95; } case BeverageType.Cider: { if (ItemID == 0x1F98) + { return ItemID; + } return 0x1F97; } case BeverageType.Liquor: { if (ItemID == 0x1F9A) + { return ItemID; + } return 0x1F99; } case BeverageType.Milk: { if (ItemID == 0x9AD) + { return ItemID; + } return 0x9F0; } case BeverageType.Wine: { if (ItemID == 0x1F9C) + { return ItemID; + } return 0x1F9B; } case BeverageType.Water: { if (ItemID == 0xFF8 || ItemID == 0xFF9 || ItemID == 0x1F9E) + { return ItemID; + } return 0x1F9D; } @@ -470,9 +499,13 @@ namespace Server.Items public override void Deserialize(IGenericReader reader) { if (CheckType("PitcherWater") || CheckType("GlassPitcher")) + { InternalDeserialize(reader, false); + } else + { InternalDeserialize(reader, true); + } var version = reader.ReadInt(); @@ -565,7 +598,9 @@ namespace Server.Items var num = BaseLabelNumber; if (IsEmpty || num == 0) + { return EmptyLabelNumber; + } return BaseLabelNumber + (int)m_Content; } @@ -608,9 +643,13 @@ namespace Server.Items var itemID = ComputeItemID(); if (itemID > 0) + { ItemID = itemID; + } else + { Delete(); + } } } @@ -627,9 +666,13 @@ namespace Server.Items var itemID = ComputeItemID(); if (itemID > 0) + { ItemID = itemID; + } else + { Delete(); + } } } @@ -640,11 +683,20 @@ namespace Server.Items var perc = m_Quantity * 100 / MaxQuantity; if (perc <= 0) + { return 1042975; // It's empty. + } + if (perc <= 33) + { return 1042974; // It's nearly empty. + } + if (perc <= 66) + { return 1042973; // It's half full. + } + return 1042972; // It's full. } @@ -653,7 +705,9 @@ namespace Server.Items base.GetProperties(list); if (ShowQuantity) + { list.Add(GetQuantityDescription()); + } } public override void OnSingleClick(Mobile from) @@ -661,13 +715,17 @@ namespace Server.Items base.OnSingleClick(from); if (ShowQuantity) + { LabelTo(from, GetQuantityDescription()); + } } public virtual bool ValidateUse(Mobile from, bool message) { if (Deleted) + { return false; + } if (!Movable && !Fillable) { @@ -676,7 +734,9 @@ namespace Server.Items if (house?.HasLockedDownItem(this) != true) { if (message) + { from.SendLocalizedMessage(502946, "", 0x59); // That belongs to someone else. + } return false; } @@ -685,7 +745,9 @@ namespace Server.Items if (from.Map != Map || !from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) { if (message) + { from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } return false; } @@ -696,12 +758,16 @@ namespace Server.Items public virtual void Fill_OnTarget(Mobile from, object targ) { if (!IsEmpty || !Fillable || !ValidateUse(from, false)) + { return; + } if (targ is BaseBeverage bev) { if (bev.IsEmpty || !bev.ValidateUse(from, true)) + { return; + } Content = bev.Content; Poison = bev.Poison; @@ -739,10 +805,14 @@ namespace Server.Items var src = item as IWaterSource; if (src == null && item is AddonComponent component) + { src = component.Addon as IWaterSource; + } if (src == null || src.Quantity <= 0) + { return; + } if (from.Map != item.Map || !from.InRange(item.GetWorldLocation(), 2) || !from.InLOS(item)) { @@ -785,7 +855,9 @@ namespace Server.Items var qs = player.Quest; if (!(qs is WitchApprenticeQuest)) + { return; + } var obj = qs.FindObjective(); @@ -794,7 +866,9 @@ namespace Server.Items var contains = false; for (var i = 0; !contains && i < m_SwampTiles.Length; i += 2) + { contains = tileID >= m_SwampTiles[i] && tileID <= m_SwampTiles[i + 1]; + } if (contains) { @@ -813,12 +887,16 @@ namespace Server.Items public virtual void Pour_OnTarget(Mobile from, object targ) { if (IsEmpty || !Pourable || !ValidateUse(from, false)) + { return; + } if (targ is BaseBeverage bev) { if (!bev.ValidateUse(from, true)) + { return; + } if (bev.IsFull && bev.Content == Content) { @@ -851,7 +929,9 @@ namespace Server.Items else if (from == targ) { if (from.Thirst < 20) + { from.Thirst += 1; + } if (ContainsAlchohol) { @@ -872,7 +952,9 @@ namespace Server.Items from.PlaySound(Utility.RandomList(0x30, 0x2D6)); if (Poison != null) + { from.ApplyPoison(Poisoner, Poison); + } --Quantity; } @@ -908,6 +990,7 @@ namespace Server.Items Content == BeverageType.Water) { if (from is PlayerMobile player) + { if (player.Quest is SolenMatriarchQuest qs) { QuestObjective obj = qs.FindObjective(); @@ -934,6 +1017,7 @@ namespace Server.Items } } } + } } else { @@ -946,7 +1030,9 @@ namespace Server.Items if (IsEmpty) { if (!Fillable || !ValidateUse(from, true)) + { return; + } from.BeginTarget(-1, true, TargetFlags.None, Fill_OnTarget); SendLocalizedMessageTo(from, 500837); // Fill from what? @@ -969,8 +1055,12 @@ namespace Server.Items var total = 0; for (var i = 0; i < items.Length; ++i) + { if (items[i] is BaseBeverage bev && bev.Content == content && !bev.IsEmpty) + { total += bev.Quantity; + } + } if (total >= quantity) { @@ -981,7 +1071,9 @@ namespace Server.Items for (var i = 0; i < items.Length; ++i) { if (!(items[i] is BaseBeverage bev) || bev.Content != content || bev.IsEmpty) + { continue; + } var theirQuantity = bev.Quantity; @@ -1026,7 +1118,9 @@ namespace Server.Items base.Deserialize(reader); if (!read) + { return; + } var version = reader.ReadInt(); @@ -1062,20 +1156,23 @@ namespace Server.Items if (from.BAC > 0 && from.Map != Map.Internal && !from.Deleted) { if (m_Table.ContainsKey(from)) + { return; + } if (from.BAC > 60) + { from.BAC = 60; + } Timer t = new HeaveTimer(from); t.Start(); m_Table[from] = t; } - else if (m_Table.TryGetValue(from, out var t)) + else if (m_Table.Remove(from, out var t)) { t.Stop(); - m_Table.Remove(from); from.SendLocalizedMessage(500850); // You feel sober. } @@ -1103,11 +1200,15 @@ namespace Server.Items else if (m_Drunk.Alive) { if (m_Drunk.BAC > 60) + { m_Drunk.BAC = 60; + } // chance to get sober if (Utility.Random(100) < 10) + { --m_Drunk.BAC; + } // lose some stats m_Drunk.Stam -= 1; diff --git a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs index 375556546..c04c52b6e 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs @@ -147,7 +147,9 @@ namespace Server.Items } if (!isBaseCreature && !info.CriminalAggression) + { Aggressors.Add(info.Attacker); + } } for (var i = 0; i < owner.Aggressed.Count; ++i) @@ -161,7 +163,9 @@ namespace Server.Items } if (!isBaseCreature) + { Aggressors.Add(info.Defender); + } } if (isBaseCreature) @@ -170,7 +174,9 @@ namespace Server.Items var master = bc.GetMaster(); if (master != null) + { Aggressors.Add(master); + } var rights = BaseCreature.GetLootingRights(bc.DamageEntries, bc.HitsMax); for (var i = 0; i < rights.Count; ++i) @@ -178,7 +184,9 @@ namespace Server.Items var ds = rights[i]; if (ds.m_HasRight) + { Aggressors.Add(ds.m_Mobile); + } } } @@ -282,9 +290,13 @@ namespace Server.Items if (IsCriminalAction(from) && (Map?.Rules & MapRules.HarmfulRestrictions) != 0) { if (Owner?.Player != true) + { from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! + } else + { from.SendLocalizedMessage(1010049); // You may not loot this corpse. + } return; } @@ -315,7 +327,9 @@ namespace Server.Items ProcessDelta(); if (IsCriminalAction(from)) + { from.CriminalAction(true); + } } else if (dead is BaseCreature creature) { @@ -335,7 +349,9 @@ namespace Server.Items private void AssignInstancedLoot() { if (Aggressors.Count == 0 || Items.Count == 0) + { return; + } m_InstancedItems ??= new Dictionary(); @@ -349,9 +365,13 @@ namespace Server.Items if (item.LootType != LootType.Cursed) // Don't have cursed items take up someone's item spot.. (?) { if (item.Stackable) + { m_Stackables.Add(item); + } else + { m_Unstackables.Add(item); + } } } @@ -392,9 +412,13 @@ namespace Server.Items } if (remainder == 0) + { m_InstancedItems.Add(item, new InstancedItemInfo(item, attackers[^1])); + } else + { m_Unstackables.Add(item); + } } else { @@ -427,7 +451,9 @@ namespace Server.Items public void TurnToBones() { if (Deleted) + { return; + } ProcessDelta(); SendRemovePacket(); @@ -481,18 +507,28 @@ namespace Server.Items var item = initialContent[i]; if (Core.AOS && owner.Player && item.Parent == owner.Backpack) + { c.AddItem(item); + } else + { c.DropItem(item); + } if (owner.Player && Core.AOS) + { c.SetRestoreInfo(item, item.Location); + } } if (Core.SE && !owner.Player) + { c.AssignInstancedLoot(); + } else if (Core.AOS && owner is PlayerMobile pm) + { c.RestoreEquip = pm.EquipSnapshot; + } var loc = owner.Location; var map = owner.Map; @@ -539,6 +575,7 @@ namespace Server.Items writer.Write(count); if (m_RestoreTable != null) + { foreach (var (item, loc) in m_RestoreTable) { writer.Write(item); @@ -553,11 +590,14 @@ namespace Server.Items writer.Write(loc); } } + } writer.Write(m_DecayTimer != null); if (m_DecayTimer != null) + { writer.WriteDeltaTime(m_DecayTime); + } writer.Write(Looters); writer.Write(Killer); @@ -586,7 +626,9 @@ namespace Server.Items case 12: { if (reader.ReadBool()) + { RestoreEquip = reader.ReadStrongItemList(); + } goto case 11; } @@ -604,13 +646,19 @@ namespace Server.Items var item = reader.ReadItem(); if (reader.ReadBool()) + { SetRestoreInfo(item, reader.ReadPoint3D()); + } else if (item != null) + { SetRestoreInfo(item, item.Location); + } } if (reader.ReadBool()) + { BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); + } Looters = reader.ReadStrongMobileList(); Killer = reader.ReadMobile(); @@ -642,9 +690,13 @@ namespace Server.Items var item = reader.ReadItem(); if (reader.ReadBool()) + { SetRestoreInfo(item, reader.ReadPoint3D()); + } else if (item != null) + { SetRestoreInfo(item, item.Location); + } } goto case 8; @@ -658,7 +710,9 @@ namespace Server.Items case 7: { if (reader.ReadBool()) + { BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); + } goto case 6; } @@ -702,16 +756,24 @@ namespace Server.Items case 0: { if (version < 10) + { TimeOfDeath = DateTime.UtcNow; + } if (version < 7) + { BeginDecay(m_DefaultDecayTime); + } if (version < 6) + { Looters = new List(); + } if (version < 4) + { Aggressors = new List(); + } AccessLevel = (AccessLevel)reader.ReadInt(); reader.ReadInt(); // guild reserve @@ -729,7 +791,9 @@ namespace Server.Items { if (Devoured || Deleted || Killer?.Deleted != false || !Killer.Alive || !(Killer is IDevourer devourer) || Owner?.Deleted != false) + { return false; + } m_Devourer = devourer; // Set the devourer the killer return m_Devourer.Devour(this); // Devour the corpse if it hasn't @@ -740,12 +804,18 @@ namespace Server.Items base.SendInfoTo(state, sendOplPacket); if (!(((Body)Amount).IsHuman && ItemID == 0x2006)) + { return; + } if (state.ContainerGridLines) + { state.Send(new CorpseContent6017(state.Mobile, this)); + } else + { state.Send(new CorpseContent(state.Mobile, this)); + } state.Send(new CorpseEquip(state.Mobile, this)); } @@ -753,7 +823,9 @@ namespace Server.Items public bool IsCriminalAction(Mobile from) { if (from == Owner || from.AccessLevel >= AccessLevel.GameMaster) + { return false; + } var p = Party.Get(Owner); @@ -762,7 +834,9 @@ namespace Server.Items var pmi = p[Owner]; if (pmi?.CanLoot == true) + { return false; + } } return NotorietyHandlers.CorpseNotoriety(from, this) == Notoriety.Innocent; @@ -779,16 +853,22 @@ namespace Server.Items base.OnItemUsed(from, item); if (item is Food) + { from.RevealingAction(); + } if (item != this && IsCriminalAction(from)) + { from.CriminalAction(true); + } if (!Looters.Contains(from)) + { Looters.Add(from); + } + + m_InstancedItems?.Remove(item); - if (m_InstancedItems?.ContainsKey(item) == true) - m_InstancedItems.Remove(item); } public override void OnItemLifted(Mobile from, Item item) @@ -796,16 +876,21 @@ namespace Server.Items base.OnItemLifted(from, item); if (item != this && from != Owner) + { from.RevealingAction(); + } if (item != this && IsCriminalAction(from)) + { from.CriminalAction(true); + } if (!Looters.Contains(from)) + { Looters.Add(from); + } - if (m_InstancedItems?.ContainsKey(item) == true) - m_InstancedItems.Remove(item); + m_InstancedItems?.Remove(item); } public override void GetContextMenuEntries(Mobile from, List list) @@ -813,7 +898,9 @@ namespace Server.Items base.GetContextMenuEntries(from, list); if (Core.AOS && Owner == from && from.Alive) + { list.Add(new OpenCorpseEntry()); + } } public bool GetRestoreInfo(Item item, ref Point3D loc) => @@ -822,7 +909,9 @@ namespace Server.Items public void SetRestoreInfo(Item item, Point3D loc) { if (item == null) + { return; + } m_RestoreTable ??= new Dictionary(); @@ -832,12 +921,16 @@ namespace Server.Items public void ClearRestoreInfo(Item item) { if (m_RestoreTable == null || item == null) + { return; + } m_RestoreTable.Remove(item); if (m_RestoreTable.Count == 0) + { m_RestoreTable = null; + } } public bool CanLoot(Mobile from, Item item) => @@ -848,9 +941,13 @@ namespace Server.Items if (!CanLoot(from, item)) { if (Owner?.Player != true) + { from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! + } else + { from.SendLocalizedMessage(1010049); // You may not loot this corpse. + } return false; } @@ -858,9 +955,13 @@ namespace Server.Items if (IsCriminalAction(from)) { if (Owner?.Player != true) + { from.SendLocalizedMessage(1005036); // Looting this monster corpse will be a criminal act! + } else + { from.SendLocalizedMessage(1005038); // Looting this corpse will be a criminal act! + } } return true; @@ -898,7 +999,9 @@ namespace Server.Items var packItem = packItems[i]; if (RestoreEquip.Contains(packItem) && packItem.Movable) + { from.EquipItem(packItem); + } } } @@ -913,7 +1016,9 @@ namespace Server.Items if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable || !GetRestoreInfo(item, ref loc)) + { continue; + } if (pack?.CheckHold(from, item, false, true) == true) { @@ -921,7 +1026,9 @@ namespace Server.Items pack.AddItem(item); if (RestoreEquip?.Contains(item) == true) + { from.EquipItem(item); + } } else { @@ -955,9 +1062,14 @@ namespace Server.Items } if (!CheckLoot(from, null)) + { return; + } - if (!(from is PlayerMobile player)) return; + if (!(from is PlayerMobile player)) + { + return; + } var qs = player.Quest; @@ -978,7 +1090,9 @@ namespace Server.Items ); // You rummage through the bones and find a Daemon Bone! You quickly place the item in your pack. if (!obj.Completed) + { obj.Complete(); + } } else { @@ -1033,9 +1147,13 @@ namespace Server.Items if (ItemID == 0x2006) // Corpse form { if (m_CorpseName != null) + { list.Add(m_CorpseName); + } else + { list.Add(1046414, Name); // the remains of ~1_NAME~ + } } else // Bone form { @@ -1049,7 +1167,9 @@ namespace Server.Items var opl = PropertyList; if (opl.Header > 0) + { from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); + } } public override void OnSingleClick(Mobile from) @@ -1059,9 +1179,13 @@ namespace Server.Items if (ItemID == 0x2006) // Corpse form { if (m_CorpseName != null) + { from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName)); + } else + { from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); + } } else // Bone form { @@ -1085,13 +1209,19 @@ namespace Server.Items public bool IsOwner(Mobile m) { if (m_Item.LootType == LootType.Cursed) // Cursed Items are part of everyone's instanced corpse... (?) + { return true; + } if (m == null) + { return false; // sanity + } if (m_Mobile == m) + { return true; + } var myParty = Party.Get(m_Mobile); @@ -1112,9 +1242,13 @@ namespace Server.Items protected override void OnTick() { if (!m_Corpse.GetFlag(CorpseFlag.NoBones)) + { m_Corpse.TurnToBones(); + } else + { m_Corpse.Delete(); + } } } @@ -1127,7 +1261,9 @@ namespace Server.Items public override void OnClick() { if (Owner.Target is Corpse corpse && Owner.From.CheckAlive()) + { corpse.Open(Owner.From, false); + } } } } diff --git a/Projects/UOContent/Items/Misc/Key.cs b/Projects/UOContent/Items/Misc/Key.cs index 8c2fc3566..2f33ebe5b 100644 --- a/Projects/UOContent/Items/Misc/Key.cs +++ b/Projects/UOContent/Items/Misc/Key.cs @@ -75,7 +75,9 @@ namespace Server.Items public static void RemoveKeys(Mobile m, uint keyValue) { if (keyValue == 0) + { return; + } RemoveKeys(m.Backpack, keyValue); RemoveKeys(m.BankBox, keyValue); @@ -84,15 +86,20 @@ namespace Server.Items public static void RemoveKeys(Container cont, uint keyValue) { if (cont == null || keyValue == 0) + { return; + } var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); foreach (var item in items) + { if (item is Key key) { if (key.KeyValue == keyValue) + { key.Delete(); + } } else { @@ -100,28 +107,37 @@ namespace Server.Items keyRing.RemoveKeys(keyValue); } + } } public static bool ContainsKey(Container cont, uint keyValue) { if (cont == null) + { return false; + } var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); foreach (var item in items) + { if (item is Key key) { if (key.KeyValue == keyValue) + { return true; + } } else { var keyRing = (KeyRing)item; if (keyRing.ContainsKey(keyValue)) + { return true; + } } + } return false; } @@ -163,7 +179,9 @@ namespace Server.Items case 0: { if (version < 2 || MaxRange == 0) + { MaxRange = 3; + } m_Description = reader.ReadString(); @@ -207,12 +225,18 @@ namespace Server.Items string desc; if (m_KeyVal == 0) + { desc = "(blank)"; + } else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) + { desc = null; + } if (desc != null) + { list.Add(desc); + } } public override void OnSingleClick(Mobile from) @@ -222,12 +246,18 @@ namespace Server.Items string desc; if (m_KeyVal == 0) + { desc = "(blank)"; + } else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) + { desc = ""; + } if (desc.Length > 0) + { from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc)); + } } public bool UseOn(Mobile from, ILockable o) @@ -235,30 +265,44 @@ namespace Server.Items if (o.KeyValue == KeyValue) { if (o is BaseDoor door && !door.UseLocks()) + { return false; + } o.Locked = !o.Locked; if (o is LockableContainer cont1) + { if (cont1.LockLevel == -255) + { cont1.LockLevel = cont1.RequiredSkill - 10; + } + } if (o is Item item) { if (o.Locked) + { item.SendLocalizedMessageTo(from, 1048000); // You lock it. + } else + { item.SendLocalizedMessageTo(from, 1048001); // You unlock it. + } if (item is LockableContainer cont && cont.TrapType != TrapType.None && cont.TrapOnLockpick) { if (o.Locked) + { cont.SendLocalizedMessageTo(from, 501673); // You re-enable the trap. + } else + { cont.SendLocalizedMessageTo( from, 501672 ); // You disable the trap temporarily. Lock it again to re-enable it. + } } } @@ -315,16 +359,23 @@ namespace Server.Items else if (targeted is ILockable lockable) { if (m_Key.UseOn(from, lockable)) + { number = -1; + } else + { number = 501668; // This key doesn't seem to unlock that. + } } else { number = 501666; // You can't unlock that! } - if (number != -1) from.SendLocalizedMessage(number); + if (number != -1) + { + from.SendLocalizedMessage(number); + } } } diff --git a/Projects/UOContent/Items/Misc/KeyRing.cs b/Projects/UOContent/Items/Misc/KeyRing.cs index 3b1946410..eaf21416b 100644 --- a/Projects/UOContent/Items/Misc/KeyRing.cs +++ b/Projects/UOContent/Items/Misc/KeyRing.cs @@ -62,7 +62,10 @@ namespace Server.Items { base.OnDelete(); - foreach (var key in Keys) key.Delete(); + foreach (var key in Keys) + { + key.Delete(); + } Keys.Clear(); } @@ -78,14 +81,18 @@ namespace Server.Items public void Open(Mobile from) { if (!(Parent is Container cont)) + { return; + } for (var i = Keys.Count - 1; i >= 0; i--) { var key = Keys[i]; if (!key.Deleted && !cont.TryDropItem(from, key, true)) + { break; + } Keys.RemoveAt(i); } @@ -112,8 +119,12 @@ namespace Server.Items public bool ContainsKey(uint keyValue) { foreach (var key in Keys) + { if (key.KeyValue == keyValue) + { return true; + } + } return false; } @@ -121,13 +132,21 @@ namespace Server.Items private void UpdateItemID() { if (Keys.Count < 1) + { ItemID = 0x1011; + } else if (Keys.Count < 3) + { ItemID = 0x1769; + } else if (Keys.Count < 5) + { ItemID = 0x176A; + } else + { ItemID = 0x176B; + } } public override void Serialize(IGenericWriter writer) @@ -170,8 +189,12 @@ namespace Server.Items else if (targeted is ILockable o) { foreach (var key in m_KeyRing.Keys) + { if (key.UseOn(from, o)) + { return; + } + } from.SendLocalizedMessage(1008140); // You do not have a key for that. } diff --git a/Projects/UOContent/Items/Misc/Teleporter.cs b/Projects/UOContent/Items/Misc/Teleporter.cs index c4bfe95b5..e561a6c27 100644 --- a/Projects/UOContent/Items/Misc/Teleporter.cs +++ b/Projects/UOContent/Items/Misc/Teleporter.cs @@ -652,11 +652,10 @@ namespace Server.Items public static void EventSink_Logout(Mobile from) { - if (from == null || !m_Table.TryGetValue(from, out var info)) - return; - - info.Timer.Stop(); - m_Table.Remove(from); + if (from != null && m_Table.Remove(from, out var info)) + { + info.Timer.Stop(); + } } public static string FormatTime(TimeSpan ts) @@ -802,10 +801,9 @@ namespace Server.Items public void StopTimer(Mobile m) { - if (m_Teleporting.TryGetValue(m, out var t)) + if (m_Teleporting.Remove(m, out var t)) { t.Stop(); - m_Teleporting.Remove(m); } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs index 48dee863d..b54790352 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs @@ -107,10 +107,9 @@ namespace Server.Items public static void EndDelay(Mobile m) { - if (m_Delay.TryGetValue(m, out var timer)) + if (m_Delay.Remove(m, out var timer)) { timer.Stop(); - m_Delay.Remove(m); } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs index 4eb6efeee..01a2a99fd 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs @@ -123,10 +123,9 @@ namespace Server.Items public static void EndDelay(Mobile m) { - if (m_Delay.TryGetValue(m, out var timer)) + if (m_Delay.Remove(m, out var timer)) { timer.Stop(); - m_Delay.Remove(m); } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs index 97f588dc3..0c53c41a1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs @@ -66,12 +66,14 @@ namespace Server.Items public static void RemoveTimer(Mobile m, bool interrupted = false) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { if (interrupted) + { m.SendLocalizedMessage(1073187); // The invisibility effect is interrupted. + } + timer.Stop(); - m_Table.Remove(m); } } diff --git a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs index 376d4f6cc..a11578f84 100644 --- a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs +++ b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs @@ -283,10 +283,9 @@ namespace Server.Items public static void RemoveTimer(Mobile m) { - if (Timers.TryGetValue(m, out var t)) + if (Timers.Remove(m, out var t)) { t.Stop(); - Timers.Remove(m); } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs b/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs index 8d0aaf2fc..2c1c4c046 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs @@ -21,7 +21,9 @@ namespace Server.Items public override void OnHit(Mobile attacker, Mobile defender, int damage) { if (!Validate(attacker) || !CheckMana(attacker, true)) + { return; + } ClearCurrentAbility(attacker); @@ -73,7 +75,9 @@ namespace Server.Items var damage = Utility.RandomMinMax(level, level * 2); if (!m.Player) + { damage *= 2; + } m.PlaySound(0x133); m.Damage(damage, from); @@ -89,14 +93,17 @@ namespace Server.Items public static void EndBleed(Mobile m, bool message) { - if (!m_Table.TryGetValue(m, out var t)) + if (!m_Table.Remove(m, out var t)) + { return; + } t.Stop(); - m_Table.Remove(m); if (message) + { m.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding! + } } private class InternalTimer : Timer @@ -117,7 +124,9 @@ namespace Server.Items DoBleed(m_Mobile, m_From, 5 - m_Count); if (++m_Count == 5) + { EndBleed(m_Mobile, true); + } } } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Block.cs b/Projects/UOContent/Items/Weapons/Abilities/Block.cs index 4647e9c54..947b485e8 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Block.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Block.cs @@ -29,7 +29,9 @@ namespace Server.Items public override void OnHit(Mobile attacker, Mobile defender, int damage) { if (!Validate(attacker) || !CheckMana(attacker, true)) + { return; + } ClearCurrentAbility(attacker); @@ -49,7 +51,9 @@ namespace Server.Items public static bool GetBonus(Mobile targ, ref int bonus) { if (!m_Table.TryGetValue(targ, out var info)) + { return false; + } bonus = info.m_Bonus; return true; @@ -63,11 +67,10 @@ namespace Server.Items public static void EndBlock(Mobile m) { - if (!m_Table.TryGetValue(m, out var info)) - return; - - info.m_Timer?.Stop(); - m_Table.Remove(m); + if (m_Table.Remove(m, out var info)) + { + info.m_Timer?.Stop(); + } } private class BlockInfo diff --git a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs index bcf82f46a..0a9130f4b 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs @@ -19,7 +19,10 @@ namespace Server.Items public override void OnHit(Mobile attacker, Mobile defender, int damage) { - if (!Validate(attacker) || !CheckMana(attacker, true)) return; + if (!Validate(attacker) || !CheckMana(attacker, true)) + { + return; + } ClearCurrentAbility(attacker); @@ -31,7 +34,9 @@ namespace Server.Items // Do not reset timer if one is already in place. if (!IsWounded(defender)) + { BeginWound(defender, defender.Player ? PlayerDuration : NPCDuration); + } } public static bool IsWounded(Mobile m) => m_Table.ContainsKey(m); @@ -39,7 +44,9 @@ namespace Server.Items public static void BeginWound(Mobile m, TimeSpan duration) { if (m_Table.TryGetValue(m, out var timer)) + { timer?.Stop(); + } m_Table[m] = timer = new InternalTimer(m, duration); timer.Start(); @@ -49,10 +56,9 @@ namespace Server.Items public static void EndWound(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer.Stop(); - m_Table.Remove(m); } m.YellowHealthbar = false; diff --git a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs index 305f653ac..c007c2c86 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs @@ -22,17 +22,17 @@ namespace Server.Items { if (!base.CheckSkills( from )) return false; - + if (!(from.Weapon is Fists)) return true; - + Skill skill = from.Skills.Anatomy; - + if (skill?.Base >= 80.0) return true; - + from.SendLocalizedMessage( 1061811 ); // You lack the required anatomy skill to perform that attack! - + return false; }*/ @@ -91,10 +91,9 @@ namespace Server.Items public static void EndImmunity(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer?.Stop(); - m_Table.Remove(m); } } diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index eb335fa90..1b3fc7760 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -367,12 +367,19 @@ namespace Server.Items get { if (m_Speed != -1) + { return m_Speed; + } if (Core.ML) + { return MlSpeed; + } + if (Core.AOS) + { return AosSpeed; + } return OldSpeed; } @@ -450,7 +457,9 @@ namespace Server.Items Quality = (WeaponQuality)quality; if (makersMark) + { Crafter = from; + } PlayerConstructed = true; @@ -463,24 +472,34 @@ namespace Server.Items var context = craftSystem.GetContext(from); if (context?.DoNotColor == true) + { Hue = 0; + } if (tool is BaseRunicTool runicTool) + { runicTool.ApplyAttributesTo(this); + } if (Quality == WeaponQuality.Exceptional) { if (Attributes.WeaponDamage > 35) + { Attributes.WeaponDamage -= 20; + } else + { Attributes.WeaponDamage = 15; + } if (Core.ML) { Attributes.WeaponDamage += (int)(from.Skills.ArmsLore.Value / 20); if (Attributes.WeaponDamage > 50) + { Attributes.WeaponDamage = 50; + } from.CheckSkill(SkillName.ArmsLore, 0, 100); } @@ -497,7 +516,9 @@ namespace Server.Items var context = craftSystem.GetContext(from); if (context?.DoNotColor == true) + { Hue = 0; + } switch (thisResource) { @@ -600,10 +621,14 @@ namespace Server.Items set { if (m_Hits == value) + { return; + } if (value > m_MaxHits) + { value = m_MaxHits; + } m_Hits = value; @@ -630,7 +655,9 @@ namespace Server.Items m_FactionState = value; if (m_FactionState == null) + { Hue = CraftResources.GetHue(Resource); + } LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; } @@ -661,10 +688,14 @@ namespace Server.Items public virtual void OnBeforeSwing(Mobile attacker, Mobile defender) { if (WeaponAbility.GetCurrentAbility(attacker)?.OnBeforeSwing(attacker, defender) == false) + { WeaponAbility.ClearCurrentAbility(attacker); + } if (SpecialMove.GetCurrentMove(attacker)?.OnBeforeSwing(attacker, defender) == false) + { SpecialMove.ClearCurrentMove(attacker); + } } public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender) => OnSwing(attacker, defender, 1.0); @@ -693,20 +724,30 @@ namespace Server.Items { canSwing = !attacker.Paralyzed && !attacker.Frozen; - if (canSwing) canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; + if (canSwing) + { + canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; + } - if (canSwing) canSwing = !(attacker is PlayerMobile p) || p.PeacedUntil <= DateTime.UtcNow; + if (canSwing) + { + canSwing = !(attacker is PlayerMobile p) || p.PeacedUntil <= DateTime.UtcNow; + } } if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) + { canSwing = false; + } if (canSwing && attacker.HarmfulCheck(defender)) { attacker.DisruptiveAction(); if (attacker.NetState != null) + { attacker.Send(new Swing(attacker.Serial, defender.Serial)); + } if (attacker is BaseCreature bc) { @@ -715,16 +756,24 @@ namespace Server.Items if (ab != null) { if (bc.WeaponAbilityChance > Utility.RandomDouble()) + { WeaponAbility.SetCurrentAbility(bc, ab); + } else + { WeaponAbility.ClearCurrentAbility(bc); + } } } if (CheckHit(attacker, defender)) + { OnHit(attacker, defender, damageBonus); + } else + { OnMiss(attacker, defender); + } } return GetDelay(attacker); @@ -744,7 +793,9 @@ namespace Server.Items public override void OnAfterDuped(Item newItem) { if (!(newItem is BaseWeapon weap)) + { return; + } weap.Attributes = new AosAttributes(newItem, Attributes); weap.AosElementDamages = new AosElementAttributes(newItem, AosElementDamages); @@ -757,7 +808,9 @@ namespace Server.Items var bonus = 0; if (m_Quality == WeaponQuality.Exceptional) + { bonus += 20; + } switch (m_DurabilityLevel) { @@ -786,10 +839,14 @@ namespace Server.Items CraftAttributeInfo attrInfo = null; if (resInfo != null) + { attrInfo = resInfo.AttributeInfo; + } if (attrInfo != null) + { bonus += attrInfo.WeaponDurability; + } } return bonus; @@ -798,17 +855,23 @@ namespace Server.Items public int GetLowerStatReq() { if (!Core.AOS) + { return 0; + } var v = WeaponAttributes.LowerStatReq; var attrInfo = CraftResources.GetInfo(m_Resource)?.AttributeInfo; if (attrInfo != null) + { v += attrInfo.WeaponLowerRequirements; + } if (v > 100) + { v = 100; + } return v; } @@ -816,13 +879,17 @@ namespace Server.Items public static void BlockEquip(Mobile m, TimeSpan duration) { if (m.BeginAction()) + { new ResetEquipTimer(m, duration).Start(); + } } public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer) { if (base.CheckConflictingLayer(m, item, layer)) + { return true; + } if (Layer == Layer.TwoHanded && layer == Layer.OneHanded) { @@ -847,14 +914,20 @@ namespace Server.Items public override bool CanEquip(Mobile from) { if (!Ethic.CheckEquip(from, this)) + { return false; + } if (RequiredRace != null && from.Race != RequiredRace) { if (RequiredRace == Race.Elf) + { from.SendLocalizedMessage(1072203); // Only Elves may use this. + } else + { from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); + } return false; } @@ -893,13 +966,19 @@ namespace Server.Items var modName = Serial.ToString(); if (strBonus != 0) + { m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + } if (dexBonus != 0) + { m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + } if (intBonus != 0) + { m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } } from.NextCombatTime = Core.TickCount + (int)GetDelay(from).TotalMilliseconds; @@ -930,7 +1009,9 @@ namespace Server.Items if (parent is Mobile from) { if (Core.AOS) + { SkillBonuses.AddTo(from); + } from.CheckStatTimers(); from.Delta(MobileDelta.WeaponDamage); @@ -950,7 +1031,9 @@ namespace Server.Items m.RemoveStatMod($"{modName}Int"); if (weapon != null) + { m.NextCombatTime = Core.TickCount + (int)weapon.GetDelay(m).TotalMilliseconds; + } if (UseSkillMod && m_SkillMod != null) { @@ -965,7 +1048,9 @@ namespace Server.Items } if (Core.AOS) + { SkillBonuses.Remove(); + } ImmolatingWeaponSpell.StopImmolating(this); @@ -995,14 +1080,21 @@ namespace Server.Items val = fenc; } - if (mcng > val) sk = SkillName.Macing; + if (mcng > val) + { + sk = SkillName.Macing; + } } else if (WeaponAttributes.MageWeapon != 0) { if (m.Skills.Magery.Value > m.Skills[Skill].Value) + { sk = SkillName.Magery; + } else + { sk = Skill; + } } else { @@ -1010,7 +1102,9 @@ namespace Server.Items if (sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman && m.Skills.Wrestling.Value > m.Skills[sk].Value) + { sk = SkillName.Wrestling; + } } return sk; @@ -1042,65 +1136,93 @@ namespace Server.Items if (Core.AOS) { if (atkValue <= -20.0) + { atkValue = -19.9; + } if (defValue <= -20.0) + { defValue = -19.9; + } bonus += AosAttributes.GetValue(attacker, AosAttribute.AttackChance); if (DivineFurySpell.UnderEffect(attacker)) + { bonus += 10; // attacker gets 10% bonus when they're under divine fury + } if (CheckAnimal(attacker, typeof(GreyWolf)) || CheckAnimal(attacker, typeof(BakeKitsune))) + { bonus += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form + } if (HitLower.IsUnderAttackEffect(attacker)) + { bonus -= 25; // Under Hit Lower Attack effect -> 25% malus + } var ability = WeaponAbility.GetCurrentAbility(attacker); if (ability != null) + { bonus += ability.AccuracyBonus; + } var move = SpecialMove.GetCurrentMove(attacker); if (move != null) + { bonus += move.GetAccuracyBonus(attacker); + } // Max Hit Chance Increase = 45% if (bonus > 45) + { bonus = 45; + } ourValue = (atkValue + 20.0) * (100 + bonus); bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance); if (DivineFurySpell.UnderEffect(defender)) + { bonus -= 20; // defender loses 20% bonus when they're under divine fury + } if (HitLower.IsUnderDefenseEffect(defender)) + { bonus -= 25; // Under Hit Lower Defense effect -> 25% malus + } var blockBonus = 0; if (Block.GetBonus(defender, ref blockBonus)) + { bonus += blockBonus; + } var surpriseMalus = 0; if (SurpriseAttack.GetMalus(defender, ref surpriseMalus)) + { bonus -= surpriseMalus; + } var discordanceEffect = 0; // Defender loses -0/-28% if under the effect of Discordance. if (Discordance.GetEffect(attacker, ref discordanceEffect)) + { bonus -= discordanceEffect; + } // Defense Chance Increase = 45% if (bonus > 45) + { bonus = 45; + } theirValue = (defValue + 20.0) * (100 + bonus); @@ -1109,10 +1231,14 @@ 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; @@ -1123,7 +1249,9 @@ namespace Server.Items chance *= 1.0 + (double)bonus / 100; if (Core.AOS && chance < 0.02) + { chance = 0.02; + } return attacker.CheckSkill(atkSkill.SkillName, chance); } @@ -1133,7 +1261,9 @@ namespace Server.Items double speed = Speed; if (speed == 0) + { return TimeSpan.FromHours(1.0); + } double delayInSeconds; @@ -1148,33 +1278,47 @@ namespace Server.Items var bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); if (DivineFurySpell.UnderEffect(m)) + { bonus += 10; + } // Bonus granted by successful use of Honorable Execution. bonus += HonorableExecution.GetSwingBonus(m); - if (DualWield.Registry.ContainsKey(m)) - bonus += DualWield.Registry[m].BonusSwingSpeed; + if (DualWield.Registry.TryGetValue(m, out var duelWield)) + { + bonus += duelWield.BonusSwingSpeed; + } - if (Feint.Registry.ContainsKey(m)) - bonus -= Feint.Registry[m].SwingSpeedReduction; + if (Feint.Registry.TryGetValue(m, out var feint)) + { + bonus -= feint.SwingSpeedReduction; + } var context = TransformationSpellHelper.GetContext(m); if (context?.Spell is ReaperFormSpell spell) + { bonus += spell.SwingSpeedBonus; + } var discordanceEffect = 0; // Discordance gives a malus of -0/-28% to swing speed. if (Discordance.GetEffect(m, ref discordanceEffect)) + { bonus -= discordanceEffect; + } if (EssenceOfWindSpell.IsDebuffed(m)) + { bonus -= EssenceOfWindSpell.GetSSIMalus(m); + } if (bonus > 60) + { bonus = 60; + } double ticks; @@ -1190,14 +1334,18 @@ namespace Server.Items speed = Math.Floor(speed * (bonus + 100.0) / 100.0); if (speed <= 0) + { speed = 1; + } ticks = Math.Floor(80000.0 / ((m.Stam + 100) * speed) - 2); } // Swing speed currently capped at one swing every 1.25 seconds (5 ticks). if (ticks < 5) + { ticks = 5; + } delayInSeconds = ticks * 0.25; } @@ -1208,32 +1356,42 @@ namespace Server.Items var bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); if (DivineFurySpell.UnderEffect(m)) + { bonus += 10; + } var discordanceEffect = 0; // Discordance gives a malus of -0/-28% to swing speed. if (Discordance.GetEffect(m, ref discordanceEffect)) + { bonus -= discordanceEffect; + } v += AOS.Scale(v, bonus); if (v <= 0) + { v = 1; + } delayInSeconds = Math.Floor(40000.0 / v) * 0.5; // Maximum swing rate capped at one swing per second // OSI dev said that it has and is supposed to be 1.25 if (delayInSeconds < 1.25) + { delayInSeconds = 1.25; + } } else { var v = (m.Stam + 100) * (int)speed; if (v <= 0) + { v = 1; + } delayInSeconds = 15000.0 / v; } @@ -1244,7 +1402,9 @@ namespace Server.Items public static bool CheckParry(Mobile defender) { if (defender == null) + { return false; + } var shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield; @@ -1260,21 +1420,29 @@ namespace Server.Items // Parry/Bushido over 100 grants a 5% bonus. if (parry >= 100.0 || bushido >= 100.0) + { chance += 0.05; + } // Evasion grants a variable bonus post ML. 50% prior. if (Evasion.IsEvading(defender)) + { chance *= Evasion.GetParryScalar(defender); + } // Low dexterity lowers the chance. if (defender.Dex < 80) + { chance = chance * (20 + defender.Dex) / 100; + } return defender.CheckSkill(SkillName.Parry, chance); } if (defender.Weapon is Fists || defender.Weapon is BaseRanged) + { return false; + } var weapon = defender.Weapon as BaseWeapon; @@ -1297,14 +1465,20 @@ namespace Server.Items // Evasion grants a variable bonus post ML. 50% prior. if (Evasion.IsEvading(defender)) + { chance *= Evasion.GetParryScalar(defender); + } // Low dexterity lowers the chance. if (defender.Dex < 80) + { chance = chance * (20 + defender.Dex) / 100; + } if (chance > aosChance) + { return defender.CheckSkill(SkillName.Parry, chance); + } return aosChance > Utility @@ -1363,20 +1537,34 @@ namespace Server.Items Item armorItem; if (positionChance < 0.07) + { armorItem = defender.NeckArmor; + } else if (positionChance < 0.14) + { armorItem = defender.HandArmor; + } else if (positionChance < 0.28) + { armorItem = defender.ArmsArmor; + } else if (positionChance < 0.43) + { armorItem = defender.HeadArmor; + } else if (positionChance < 0.65) + { armorItem = defender.LegsArmor; + } else + { armorItem = defender.ChestArmor; + } if (armorItem is IWearableDurability armor) + { armor.OnHit(this, damage); // call OnHit to lose durability + } } return damage; @@ -1385,30 +1573,48 @@ namespace Server.Items public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage) { if (Core.AOS) + { return AbsorbDamageAOS(attacker, defender, damage); + } if (defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield shield) + { damage = shield.OnHit(this, damage); + } var chance = Utility.RandomDouble(); Item armorItem; if (chance < 0.07) + { armorItem = defender.NeckArmor; + } else if (chance < 0.14) + { armorItem = defender.HandArmor; + } else if (chance < 0.28) + { armorItem = defender.ArmsArmor; + } else if (chance < 0.43) + { armorItem = defender.HeadArmor; + } else if (chance < 0.65) + { armorItem = defender.LegsArmor; + } else + { armorItem = defender.ChestArmor; + } if (armorItem is IWearableDurability armor) + { damage = armor.OnHit(this, damage); + } var virtualArmor = defender.VirtualArmor + defender.VirtualArmorMod; @@ -1417,15 +1623,25 @@ namespace Server.Items double scalar; if (chance < 0.14) + { scalar = 0.07; + } else if (chance < 0.28) + { scalar = 0.14; + } else if (chance < 0.43) + { scalar = 0.15; + } else if (chance < 0.65) + { scalar = 0.22; + } else + { scalar = 0.35; + } var from = (int)(virtualArmor * scalar) / 2; var to = (int)(virtualArmor * scalar); @@ -1439,15 +1655,21 @@ namespace Server.Items public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender) { if (attacker.Player || defender.Player) + { return 0; + } if (!(attacker is BaseCreature bc) || bc.PackInstinct == PackInstinct.None || !bc.Controlled && !bc.Summoned) + { return 0; + } var master = bc.ControlMaster ?? bc.SummonMaster; if (master == null) + { return 0; + } var eable = defender.GetMobilesInRange(1); var inPack = 1 + eable @@ -1468,6 +1690,7 @@ namespace Server.Items { var eable = defender.GetMobilesInRange(4); foreach (var m in eable) + { if (m?.Summoned == true && m.SummonMaster == defender) { attacker.SendLocalizedMessage( @@ -1486,6 +1709,7 @@ namespace Server.Items defender = m; break; } + } eable.Free(); } @@ -1507,9 +1731,15 @@ namespace Server.Items var a = WeaponAbility.GetCurrentAbility(attacker); var move = SpecialMove.GetCurrentMove(attacker); - if (a != null) percentageBonus += (int)(a.DamageScalar * 100) - 100; + if (a != null) + { + percentageBonus += (int)(a.DamageScalar * 100) - 100; + } - if (move != null) percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100; + if (move != null) + { + percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100; + } percentageBonus += (int)(damageBonus * 100) - 100; @@ -1518,7 +1748,9 @@ namespace Server.Items if (cs != CheckSlayerResult.None) { if (cs == CheckSlayerResult.Slayer) + { defender.FixedEffect(0x37B9, 10, 5); + } percentageBonus += 100; } @@ -1526,8 +1758,12 @@ namespace Server.Items if (!attacker.Player) { if (defender is PlayerMobile pm) + { if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType()) + { percentageBonus += 100; + } + } } else if (!defender.Player) { @@ -1550,25 +1786,41 @@ namespace Server.Items var packInstinctBonus = GetPackInstinctBonus(attacker, defender); - if (packInstinctBonus != 0) percentageBonus += packInstinctBonus; + if (packInstinctBonus != 0) + { + percentageBonus += packInstinctBonus; + } - if (InDoubleStrike) percentageBonus -= 10; + if (InDoubleStrike) + { + percentageBonus -= 10; + } var context = TransformationSpellHelper.GetContext(defender); if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver) && context?.Spell is NecromancerSpell && - context.Type != typeof(HorrificBeastSpell)) percentageBonus += 25; + context.Type != typeof(HorrificBeastSpell)) + { + percentageBonus += 25; + } if (attacker is PlayerMobile pmAttacker && !(Core.ML && defender is PlayerMobile)) { - if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1)) percentageBonus += 25; + if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1)) + { + percentageBonus += 25; + } if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender) + { percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus; + } } if (attacker.Talisman is BaseTalisman talisman && talisman.Killer != null) + { percentageBonus += talisman.Killer.DamageBonus(defender); + } percentageBonus = Math.Min(percentageBonus, 300); @@ -1583,8 +1835,11 @@ namespace Server.Items damage = AbsorbDamage(attacker, defender, damage); if (!Core.AOS && damage < 1) + { damage = 1; + } else if (Core.AOS && damage == 0) // parried + { if (a?.Validate(attacker) == true) /*&& a.CheckMana( attacker, true )*/ // Parried special moves have no mana cost { @@ -1593,6 +1848,7 @@ namespace Server.Items attacker.SendLocalizedMessage(1061140); // Your attack was parried! } + } AddBlood(attacker, defender, damage); @@ -1608,8 +1864,12 @@ namespace Server.Items ); if (Core.ML && this is BaseRanged) + { if (attacker.FindItemOnLayer(Layer.Cloak) is BaseQuiver quiver) + { quiver.AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct); + } + } if (Consecrated) { @@ -1639,20 +1899,40 @@ namespace Server.Items type = 3; } - if (nrgy < low) type = 4; + if (nrgy < low) + { + type = 4; + } phys = fire = cold = pois = nrgy = chaos = direct = 0; - if (type == 0) phys = 100; - else if (type == 1) fire = 100; - else if (type == 2) cold = 100; - else if (type == 3) pois = 100; - else if (type == 4) nrgy = 100; + if (type == 0) + { + phys = 100; + } + else if (type == 1) + { + fire = 100; + } + else if (type == 2) + { + cold = 100; + } + else if (type == 3) + { + pois = 100; + } + else if (type == 4) + { + nrgy = 100; + } } // TODO: Scale damage, alongside the leech effects below, to weapon speed. if (ImmolatingWeaponSpell.IsImmolating(this) && damage > 0) + { ImmolatingWeaponSpell.DoEffect(this, defender); + } var damageGiven = damage; @@ -1697,23 +1977,33 @@ namespace Server.Items if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) > Utility.Random(100)) + { lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points + } if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) > Utility.Random(100)) + { stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina + } if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) > Utility.Random(100)) + { manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana + } if (Cursed) + { lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell) + } context = TransformationSpellHelper.GetContext(attacker); if (context?.Type == typeof(VampiricEmbraceSpell)) + { lifeLeech += 20; // Vampiric embrace gives an additional 20% life leech + } if (context?.Type == typeof(WraithFormSpell)) { @@ -1728,23 +2018,33 @@ namespace Server.Items } if (lifeLeech != 0) + { attacker.Hits += AOS.Scale(damageGiven, lifeLeech); + } if (stamLeech != 0) + { attacker.Stam += AOS.Scale(damageGiven, stamLeech); + } if (manaLeech != 0) + { attacker.Mana += AOS.Scale(damageGiven, manaLeech); + } if (lifeLeech != 0 || stamLeech != 0 || manaLeech != 0) + { attacker.PlaySound(0x44D); + } } if (m_MaxHits > 0 && (MaxRange <= 1 && (defender is Slime || defender is AcidElemental) || Utility.RandomDouble() < .04)) // Stratics says 50% chance, seems more like 4%.. { if (MaxRange <= 1 && (defender is Slime || defender is AcidElemental)) + { attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!* + } if (Core.AOS && WeaponAttributes.SelfRepair > Utility.Random(10)) { @@ -1761,11 +2061,13 @@ namespace Server.Items --MaxHitPoints; if (Parent is Mobile mobile) + { mobile.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1061121 ); // Your equipment is severely damaged. + } } else { @@ -1779,9 +2081,13 @@ namespace Server.Items var caster = bc.ControlMaster ?? bc.SummonMaster; if (caster != null && caster.Map == bc.Map && caster.InRange(bc, 2)) + { caster.Hits += damage; + } else + { bc.Hits += damage; + } } if (Core.AOS) @@ -1798,19 +2104,29 @@ namespace Server.Items propertyBonus); if (physChance != 0 && physChance > Utility.Random(100)) + { DoAreaAttack(attacker, defender, 0x10E, 50, 100, 0, 0, 0, 0); + } if (fireChance != 0 && fireChance > Utility.Random(100)) + { DoAreaAttack(attacker, defender, 0x11D, 1160, 0, 100, 0, 0, 0); + } if (coldChance != 0 && coldChance > Utility.Random(100)) + { DoAreaAttack(attacker, defender, 0x0FC, 2100, 0, 0, 100, 0, 0); + } if (poisChance != 0 && poisChance > Utility.Random(100)) + { DoAreaAttack(attacker, defender, 0x205, 1166, 0, 0, 0, 100, 0); + } if (nrgyChance != 0 && nrgyChance > Utility.Random(100)) + { DoAreaAttack(attacker, defender, 0x1F1, 120, 0, 0, 0, 0, 100); + } var maChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus); @@ -1823,19 +2139,29 @@ namespace Server.Items (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus); if (maChance != 0 && maChance > Utility.Random(100)) + { DoMagicArrow(attacker, defender); + } if (harmChance != 0 && harmChance > Utility.Random(100)) + { DoHarm(attacker, defender); + } if (fireballChance != 0 && fireballChance > Utility.Random(100)) + { DoFireball(attacker, defender); + } if (lightningChance != 0 && lightningChance > Utility.Random(100)) + { DoLightning(attacker, defender); + } if (dispelChance != 0 && dispelChance > Utility.Random(100)) + { DoDispel(attacker, defender); + } var laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * propertyBonus); @@ -1843,10 +2169,14 @@ namespace Server.Items propertyBonus); if (laChance != 0 && laChance > Utility.Random(100)) + { DoLowerAttack(attacker, defender); + } if (ldChance != 0 && ldChance > Utility.Random(100)) + { DoLowerDefense(attacker, defender); + } } bcAtt?.OnGaveMeleeAttack(defender); @@ -1856,15 +2186,21 @@ namespace Server.Items move?.OnHit(attacker, defender, damage); if (defender is IHonorTarget it) + { it.ReceivedHonorContext?.OnTargetHit(attacker); + } if (!(this is BaseRanged)) { if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent))) + { defender.ApplyPoison(attacker, Poison.Lesser); + } if (AnimalForm.UnderTransformation(defender, typeof(BullFrog))) + { attacker.ApplyPoison(defender, Poison.Regular); + } } } @@ -1878,7 +2214,9 @@ namespace Server.Items var damageBonus = inscribeSkill / 200; if (inscribeSkill >= 1000) + { damageBonus += 5; + } if (attacker.Player) { @@ -1891,7 +2229,9 @@ namespace Server.Items var context = TransformationSpellHelper.GetContext(attacker); if (context?.Spell is ReaperFormSpell spell) + { damageBonus += spell.SpellDamageBonus; + } } damage = AOS.Scale(damage, 100 + damageBonus); @@ -1906,13 +2246,19 @@ namespace Server.Items var atkSlayer2 = SlayerGroup.GetEntryByName(atkWeapon?.Slayer2 ?? SlayerName.None); if (atkWeapon is ButchersWarCleaver && TalismanSlayer.Slays(TalismanSlayerName.Bovine, defender)) + { return CheckSlayerResult.Slayer; + } if (atkSlayer?.Slays(defender) == true || atkSlayer2?.Slays(defender) == true) + { return CheckSlayerResult.Slayer; + } if (attacker.Talisman is BaseTalisman talisman && TalismanSlayer.Slays(talisman.Slayer, defender)) + { return CheckSlayerResult.Slayer; + } if (!Core.SE) { @@ -1925,7 +2271,9 @@ namespace Server.Items if (defSlayer?.Group.OppositionSuperSlays(attacker) == true || defSlayer2?.Group.OppositionSuperSlays(attacker) == true) + { return CheckSlayerResult.Opposition; + } } } @@ -1935,13 +2283,16 @@ namespace Server.Items public virtual void AddBlood(Mobile attacker, Mobile defender, int damage) { if (damage <= 0) + { return; + } new Blood().MoveToWorld(defender.Location, defender.Map); var extraBlood = Core.SE ? Utility.RandomMinMax(3, 4) : Utility.RandomMinMax(0, 1); for (var i = 0; i < extraBlood; i++) + { new Blood().MoveToWorld( new Point3D( defender.X + Utility.RandomMinMax(-1, 1), @@ -1950,6 +2301,7 @@ namespace Server.Items ), defender.Map ); + } } public virtual void GetDamageTypes( @@ -1999,18 +2351,26 @@ namespace Server.Items private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining) { if (totalRemaining <= 0) + { return 0; + } if (attrDamage <= 0) + { return totalRemaining; + } var appliedDamage = attrDamage; if (appliedDamage + element > 100) + { appliedDamage = 100 - element; + } if (appliedDamage > totalRemaining) + { appliedDamage = totalRemaining; + } element += appliedDamage; @@ -2031,7 +2391,10 @@ namespace Server.Items move?.OnMiss(attacker, defender); - if (defender is IHonorTarget target) target.ReceivedHonorContext?.OnTargetMissed(attacker); + if (defender is IHonorTarget target) + { + target.ReceivedHonorContext?.OnTargetMissed(attacker); + } } public virtual void GetBaseDamageRange(Mobile attacker, out int min, out int max) @@ -2063,7 +2426,10 @@ namespace Server.Items var damage = Utility.RandomMinMax(min, max); - if (Core.AOS) return damage; + if (Core.AOS) + { + return damage; + } /* Apply damage level offset * : Regular : 0 @@ -2074,7 +2440,9 @@ namespace Server.Items * : Vanq : 9 */ if (m_DamageLevel != WeaponDamageLevel.Regular) + { damage += 2 * (int)m_DamageLevel - 1; + } return damage; } @@ -2084,7 +2452,9 @@ namespace Server.Items var bonus = value * scalar; if (value >= threshold) + { bonus += offset; + } return bonus / 100; } @@ -2092,7 +2462,9 @@ namespace Server.Items public virtual int GetHitChanceBonus() { if (!Core.AOS) + { return 0; + } var bonus = 0; @@ -2170,7 +2542,9 @@ namespace Server.Items ); // Passively check Anatomy for gain if (Type == WeaponType.Axe) + { attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain + } } /* @@ -2183,7 +2557,9 @@ namespace Server.Items var lumberBonus = GetBonus(attacker.Skills.Lumberjacking.Value, 0.200, 100.0, 10.00); if (Type != WeaponType.Axe) + { lumberBonus = 0.0; + } /* * The following are damage modifiers whose effect shows on the status bar. @@ -2193,26 +2569,36 @@ namespace Server.Items // Horrific Beast transformation gives a +25% bonus to damage. if (TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell))) + { damageBonus += 25; + } // Divine Fury gives a +10% bonus to damage. if (DivineFurySpell.UnderEffect(attacker)) + { damageBonus += 10; + } var defenseMasteryMalus = 0; // Defense Mastery gives a -50%/-80% malus to damage. if (DefenseMastery.GetMalus(attacker, ref defenseMasteryMalus)) + { damageBonus -= defenseMasteryMalus; + } var discordanceEffect = 0; // Discordance gives a -2%/-48% malus to damage. if (Discordance.GetEffect(attacker, ref discordanceEffect)) + { damageBonus -= discordanceEffect * 2; + } if (damageBonus > 100) + { damageBonus = 100; + } var totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus + (GetDamageBonus() + damageBonus) / 100.0; @@ -2239,7 +2625,9 @@ namespace Server.Items ); // Passively check Anatomy for gain if (Type == WeaponType.Axe) + { attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain + } } /* Compute tactics modifier @@ -2262,7 +2650,9 @@ namespace Server.Items modifiers += anatomyValue / 5.0 / 100.0; if (anatomyValue >= 100.0) + { modifiers += 0.1; + } /* Compute lumberjacking bonus * : 1% bonus for every 5 points of lumberjacking @@ -2275,16 +2665,22 @@ namespace Server.Items modifiers += lumberValue / 5.0 / 100.0; if (lumberValue >= 100.0) + { modifiers += 0.1; + } } // New quality bonus: if (m_Quality != WeaponQuality.Regular) + { modifiers += ((int)m_Quality - 1) * 0.2; + } // Virtual damage bonus: if (VirtualDamageBonus != 0) + { modifiers += VirtualDamageBonus / 100.0; + } // Apply bonuses damage += damage * modifiers; @@ -2297,7 +2693,9 @@ namespace Server.Items var scale = 100; if (m_MaxHits > 0 && m_Hits < m_MaxHits) + { scale = 50 + 50 * m_Hits / m_MaxHits; + } return AOS.Scale(damage, scale); } @@ -2305,13 +2703,17 @@ namespace Server.Items public virtual int ComputeDamage(Mobile attacker, Mobile defender) { if (Core.AOS) + { return ComputeDamageAOS(attacker, defender); + } 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)) + { damage = (int)(damage / 2.0); + } return damage; } @@ -2346,7 +2748,9 @@ namespace Server.Items } if (from.Mounted) + { return; + } from.Animate(action, frames, 1, true, false, 0); } @@ -2379,8 +2783,11 @@ namespace Server.Items case BodyType.Human: { if (!from.Mounted) + { action = (int)Animation; + } else + { action = Animation switch { WeaponAnimation.Wrestle => 26, @@ -2394,6 +2801,7 @@ namespace Server.Items WeaponAnimation.ShootXBow => 28, _ => 26 }; + } break; } @@ -2431,7 +2839,10 @@ namespace Server.Items currentMax = nrgy; } - if (cold >= currentMax) hue = 1261 + (cold - 50) / 10; + if (cold >= currentMax) + { + hue = 1261 + (cold - 50) / 10; + } return hue; } @@ -2461,11 +2872,17 @@ namespace Server.Items }; if (oreType != 0) + { list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ + } else if (Name == null) + { list.Add(LabelNumber); + } else + { list.Add(Name); + } /* * Want to move this to the engraving tool, let the non-harmful @@ -2481,7 +2898,9 @@ namespace Server.Items */ if (!string.IsNullOrEmpty(m_EngravedText)) + { list.Add(1062613, m_EngravedText); + } /* list.Add( 1062613, Utility.FixHtml( m_EngravedText ) ); */ } @@ -2489,7 +2908,9 @@ namespace Server.Items public override bool AllowEquippedCast(Mobile from) { if (base.AllowEquippedCast(from)) + { return true; + } return Attributes.SpellChanneling != 0; } @@ -2501,7 +2922,9 @@ namespace Server.Items var attrInfo = resInfo?.AttributeInfo; if (attrInfo == null) + { return 0; + } return attrInfo.WeaponLuck; } @@ -2511,40 +2934,58 @@ namespace Server.Items base.GetProperties(list); if (m_Crafter != null) + { list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + } if (m_FactionState != null) + { list.Add(1041350); // faction item + } SkillBonuses?.GetProperties(list); if (m_Quality == WeaponQuality.Exceptional) + { list.Add(1060636); // exceptional + } if (RequiredRace == Race.Elf) + { list.Add(1075086); // Elves Only + } if (ArtifactRarity > 0) + { list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ + } if (this is IUsesRemaining usesRemaining && usesRemaining.ShowUsesRemaining) + { list.Add(1060584, usesRemaining.UsesRemaining.ToString()); // uses remaining: ~1_val~ + } if (m_Poison != null && m_PoisonCharges > 0) + { list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); + } if (m_Slayer != SlayerName.None) { var entry = SlayerGroup.GetEntryByName(m_Slayer); if (entry != null) + { list.Add(entry.Title); + } } if (m_Slayer2 != SlayerName.None) { var entry = SlayerGroup.GetEntryByName(m_Slayer2); if (entry != null) + { list.Add(entry.Title); + } } AddResistanceProperties(list); @@ -2554,142 +2995,234 @@ namespace Server.Items var ranged = this as BaseRanged; if (Core.ML && ranged?.Balanced == true) + { list.Add(1072792); // Balanced + } if (WeaponAttributes.UseBestSkill != 0) + { list.Add(1060400); // use best weapon skill + } if ((prop = GetDamageBonus() + Attributes.WeaponDamage) != 0) + { list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + } if ((prop = Attributes.DefendChance) != 0) + { list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + } if ((prop = Attributes.EnhancePotions) != 0) + { list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + } if ((prop = Attributes.CastRecovery) != 0) + { list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + } if ((prop = Attributes.CastSpeed) != 0) + { list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + } if ((prop = GetHitChanceBonus() + Attributes.AttackChance) != 0) + { list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + } if ((prop = WeaponAttributes.HitColdArea) != 0) + { list.Add(1060416, prop.ToString()); // hit cold area ~1_val~% + } if ((prop = WeaponAttributes.HitDispel) != 0) + { list.Add(1060417, prop.ToString()); // hit dispel ~1_val~% + } if ((prop = WeaponAttributes.HitEnergyArea) != 0) + { list.Add(1060418, prop.ToString()); // hit energy area ~1_val~% + } if ((prop = WeaponAttributes.HitFireArea) != 0) + { list.Add(1060419, prop.ToString()); // hit fire area ~1_val~% + } if ((prop = WeaponAttributes.HitFireball) != 0) + { list.Add(1060420, prop.ToString()); // hit fireball ~1_val~% + } if ((prop = WeaponAttributes.HitHarm) != 0) + { list.Add(1060421, prop.ToString()); // hit harm ~1_val~% + } if ((prop = WeaponAttributes.HitLeechHits) != 0) + { list.Add(1060422, prop.ToString()); // hit life leech ~1_val~% + } if ((prop = WeaponAttributes.HitLightning) != 0) + { list.Add(1060423, prop.ToString()); // hit lightning ~1_val~% + } if ((prop = WeaponAttributes.HitLowerAttack) != 0) + { list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~% + } if ((prop = WeaponAttributes.HitLowerDefend) != 0) + { list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~% + } if ((prop = WeaponAttributes.HitMagicArrow) != 0) + { list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~% + } if ((prop = WeaponAttributes.HitLeechMana) != 0) + { list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~% + } if ((prop = WeaponAttributes.HitPhysicalArea) != 0) + { list.Add(1060428, prop.ToString()); // hit physical area ~1_val~% + } if ((prop = WeaponAttributes.HitPoisonArea) != 0) + { list.Add(1060429, prop.ToString()); // hit poison area ~1_val~% + } if ((prop = WeaponAttributes.HitLeechStam) != 0) + { list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~% + } if (ImmolatingWeaponSpell.IsImmolating(this)) + { list.Add(1111917); // Immolated + } if (Core.ML && (ranged?.Velocity ?? 0) != 0) + { list.Add(1072793, prop.ToString()); // Velocity ~1_val~% + } if ((prop = Attributes.BonusDex) != 0) + { list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + } if ((prop = Attributes.BonusHits) != 0) + { list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + } if ((prop = Attributes.BonusInt) != 0) + { list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + } if ((prop = Attributes.LowerManaCost) != 0) + { list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + } if ((prop = Attributes.LowerRegCost) != 0) + { list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + } if ((prop = GetLowerStatReq()) != 0) + { list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% + } if ((prop = GetLuckBonus() + Attributes.Luck) != 0) + { list.Add(1060436, prop.ToString()); // luck ~1_val~ + } if ((prop = WeaponAttributes.MageWeapon) != 0) + { list.Add(1060438, (30 - prop).ToString()); // mage weapon -~1_val~ skill + } if ((prop = Attributes.BonusMana) != 0) + { list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + } if ((prop = Attributes.RegenMana) != 0) + { list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + } if (Attributes.NightSight != 0) + { list.Add(1060441); // night sight + } if ((prop = Attributes.ReflectPhysical) != 0) + { list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + } if ((prop = Attributes.RegenStam) != 0) + { list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + } if ((prop = Attributes.RegenHits) != 0) + { list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + } if ((prop = WeaponAttributes.SelfRepair) != 0) + { list.Add(1060450, prop.ToString()); // self repair ~1_val~ + } if (Attributes.SpellChanneling != 0) + { list.Add(1060482); // spell channeling + } if ((prop = Attributes.SpellDamage) != 0) + { list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + } if ((prop = Attributes.BonusStam) != 0) + { list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + } if ((prop = Attributes.BonusStr) != 0) + { list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + } if ((prop = Attributes.WeaponSpeed) != 0) + { list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + } if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + { list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + } GetDamageTypes( null, @@ -2703,47 +3236,74 @@ namespace Server.Items ); if (phys != 0) + { list.Add(1060403, phys.ToString()); // physical damage ~1_val~% + } if (fire != 0) + { list.Add(1060405, fire.ToString()); // fire damage ~1_val~% + } if (cold != 0) + { list.Add(1060404, cold.ToString()); // cold damage ~1_val~% + } if (pois != 0) + { list.Add(1060406, pois.ToString()); // poison damage ~1_val~% + } if (nrgy != 0) + { list.Add(1060407, nrgy.ToString()); // energy damage ~1_val + } if (Core.ML && chaos != 0) + { list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~% + } if (Core.ML && direct != 0) + { list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~% + } list.Add(1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString()); // weapon damage ~1_val~ - ~2_val~ if (Core.ML) + { list.Add(1061167, $"{Speed}s"); // weapon speed ~1_val~ + } else + { list.Add(1061167, Speed.ToString()); + } if (MaxRange > 1) + { list.Add(1061169, MaxRange.ToString()); // range ~1_val~ + } var strReq = AOS.Scale(StrRequirement, 100 - GetLowerStatReq()); if (strReq > 0) + { list.Add(1061170, strReq.ToString()); // strength requirement ~1_val~ + } if (Layer == Layer.TwoHanded) + { list.Add(1061171); // two-handed weapon + } else + { list.Add(1061824); // one-handed weapon + } if (Core.SE || WeaponAttributes.UseBestSkill == 0) + { switch (Skill) { case SkillName.Swords: @@ -2759,9 +3319,12 @@ namespace Server.Items list.Add(1061175); break; // skill required: archery } + } if (m_Hits >= 0 && m_MaxHits > 0) + { list.Add(1060639, "{0}\t{1}", m_Hits, m_MaxHits); // durability ~1_val~ / ~2_val~ + } } public override void OnSingleClick(Mobile from) @@ -2771,16 +3334,24 @@ namespace Server.Items if (DisplayLootType) { if (LootType == LootType.Blessed) + { attrs.Add(new EquipInfoAttribute(1038021)); // blessed + } else if (LootType == LootType.Cursed) + { attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } } if (m_FactionState != null) + { attrs.Add(new EquipInfoAttribute(1041350)); // faction item + } if (m_Quality == WeaponQuality.Exceptional) + { attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); + } if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster) { @@ -2788,24 +3359,34 @@ namespace Server.Items { var entry = SlayerGroup.GetEntryByName(m_Slayer); if (entry != null) + { attrs.Add(new EquipInfoAttribute(entry.Title)); + } } if (m_Slayer2 != SlayerName.None) { var entry = SlayerGroup.GetEntryByName(m_Slayer2); if (entry != null) + { attrs.Add(new EquipInfoAttribute(entry.Title)); + } } if (m_DurabilityLevel != WeaponDurabilityLevel.Regular) + { attrs.Add(new EquipInfoAttribute(1038000 + (int)m_DurabilityLevel)); + } if (m_DamageLevel != WeaponDamageLevel.Regular) + { attrs.Add(new EquipInfoAttribute(1038015 + (int)m_DamageLevel)); + } if (m_AccuracyLevel != WeaponAccuracyLevel.Regular) + { attrs.Add(new EquipInfoAttribute(1038010 + (int)m_AccuracyLevel)); + } } else if (m_Slayer != SlayerName.None || m_Slayer2 != SlayerName.None || m_DurabilityLevel != WeaponDurabilityLevel.Regular || m_DamageLevel != WeaponDamageLevel.Regular || @@ -2815,7 +3396,9 @@ namespace Server.Items } if (m_Poison != null && m_PoisonCharges > 0) + { attrs.Add(new EquipInfoAttribute(1017383, m_PoisonCharges)); + } int number; @@ -2830,7 +3413,9 @@ namespace Server.Items } if (attrs.Count == 0 && Crafter == null && Name != null) + { return; + } var eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); @@ -2842,7 +3427,9 @@ namespace Server.Items var sound = attacker.GetAttackSound(); if (sound == -1) + { sound = HitSound; + } return sound; } @@ -2857,7 +3444,9 @@ namespace Server.Items public virtual void DoMagicArrow(Mobile attacker, Mobile defender) { if (!attacker.CanBeHarmful(defender, false)) + { return; + } attacker.DoHarmful(defender); @@ -2872,16 +3461,22 @@ namespace Server.Items public virtual void DoHarm(Mobile attacker, Mobile defender) { if (!attacker.CanBeHarmful(defender, false)) + { return; + } attacker.DoHarmful(defender); var damage = GetAosDamage(attacker, 17, 1, 5); if (!defender.InRange(attacker, 2)) + { damage *= 0.25; // 1/4 damage at > 2 tile range + } else if (!defender.InRange(attacker, 1)) + { damage *= 0.50; // 1/2 damage at 2 tile range + } defender.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); defender.PlaySound(0x0FC); @@ -2892,7 +3487,9 @@ namespace Server.Items public virtual void DoFireball(Mobile attacker, Mobile defender) { if (!attacker.CanBeHarmful(defender, false)) + { return; + } attacker.DoHarmful(defender); @@ -2907,7 +3504,9 @@ namespace Server.Items public virtual void DoLightning(Mobile attacker, Mobile defender) { if (!attacker.CanBeHarmful(defender, false)) + { return; + } attacker.DoHarmful(defender); @@ -2923,13 +3522,19 @@ namespace Server.Items var dispellable = false; if (defender is BaseCreature creature) + { dispellable = creature.Summoned && !creature.IsAnimatedDead; + } if (!dispellable) + { return; + } if (!attacker.CanBeHarmful(defender, false)) + { return; + } attacker.DoHarmful(defender); @@ -2980,7 +3585,9 @@ namespace Server.Items var map = from.Map; if (map == null) + { return; + } var range = Core.ML ? 5 : 10; @@ -2994,7 +3601,9 @@ namespace Server.Items eable.Free(); if (list.Count == 0) + { return; + } Effects.PlaySound(from.Location, map, sound); @@ -3005,9 +3614,15 @@ namespace Server.Items var scalar = Core.ML ? 1.0 : (11 - from.GetDistanceToSqrt(m)) / 10; var damage = GetBaseDamage(from); - if (scalar <= 0) continue; + if (scalar <= 0) + { + continue; + } - if (scalar < 1.0) damage *= (11 - from.GetDistanceToSqrt(m)) / 10; + if (scalar < 1.0) + { + damage *= (11 - from.GetDistanceToSqrt(m)) / 10; + } from.DoHarmful(m, true); m.FixedEffect(0x3779, 1, 15, hue, 0); @@ -3018,7 +3633,9 @@ namespace Server.Items private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) { if (setIf) + { flags |= toSet; + } } private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; @@ -3066,91 +3683,149 @@ namespace Server.Items writer.Write((int)flags); if (GetSaveFlag(flags, SaveFlag.DamageLevel)) + { writer.Write((int)m_DamageLevel); + } if (GetSaveFlag(flags, SaveFlag.AccuracyLevel)) + { writer.Write((int)m_AccuracyLevel); + } if (GetSaveFlag(flags, SaveFlag.DurabilityLevel)) + { writer.Write((int)m_DurabilityLevel); + } if (GetSaveFlag(flags, SaveFlag.Quality)) + { writer.Write((int)m_Quality); + } if (GetSaveFlag(flags, SaveFlag.Hits)) + { writer.Write(m_Hits); + } if (GetSaveFlag(flags, SaveFlag.MaxHits)) + { writer.Write(m_MaxHits); + } if (GetSaveFlag(flags, SaveFlag.Slayer)) + { writer.Write((int)m_Slayer); + } if (GetSaveFlag(flags, SaveFlag.Poison)) + { Poison.Serialize(m_Poison, writer); + } if (GetSaveFlag(flags, SaveFlag.PoisonCharges)) + { writer.Write(m_PoisonCharges); + } if (GetSaveFlag(flags, SaveFlag.Crafter)) + { writer.Write(m_Crafter); + } if (GetSaveFlag(flags, SaveFlag.StrReq)) + { writer.Write(m_StrReq); + } if (GetSaveFlag(flags, SaveFlag.DexReq)) + { writer.Write(m_DexReq); + } if (GetSaveFlag(flags, SaveFlag.IntReq)) + { writer.Write(m_IntReq); + } if (GetSaveFlag(flags, SaveFlag.MinDamage)) + { writer.Write(m_MinDamage); + } if (GetSaveFlag(flags, SaveFlag.MaxDamage)) + { writer.Write(m_MaxDamage); + } if (GetSaveFlag(flags, SaveFlag.HitSound)) + { writer.Write(m_HitSound); + } if (GetSaveFlag(flags, SaveFlag.MissSound)) + { writer.Write(m_MissSound); + } if (GetSaveFlag(flags, SaveFlag.Speed)) + { writer.Write(m_Speed); + } if (GetSaveFlag(flags, SaveFlag.MaxRange)) + { writer.Write(m_MaxRange); + } if (GetSaveFlag(flags, SaveFlag.Skill)) + { writer.Write((int)m_Skill); + } if (GetSaveFlag(flags, SaveFlag.Type)) + { writer.Write((int)m_Type); + } if (GetSaveFlag(flags, SaveFlag.Animation)) + { writer.Write((int)m_Animation); + } if (GetSaveFlag(flags, SaveFlag.Resource)) + { writer.Write((int)m_Resource); + } if (GetSaveFlag(flags, SaveFlag.xAttributes)) + { Attributes.Serialize(writer); + } if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes)) + { WeaponAttributes.Serialize(writer); + } if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + { SkillBonuses.Serialize(writer); + } if (GetSaveFlag(flags, SaveFlag.Slayer2)) + { writer.Write((int)m_Slayer2); + } if (GetSaveFlag(flags, SaveFlag.ElementalDamages)) + { AosElementDamages.Serialize(writer); + } if (GetSaveFlag(flags, SaveFlag.EngravedText)) + { writer.Write(m_EngravedText); + } } public override void Deserialize(IGenericReader reader) @@ -3176,7 +3851,9 @@ namespace Server.Items m_DamageLevel = (WeaponDamageLevel)reader.ReadInt(); if (m_DamageLevel > WeaponDamageLevel.Vanq) + { m_DamageLevel = WeaponDamageLevel.Ruin; + } } if (GetSaveFlag(flags, SaveFlag.AccuracyLevel)) @@ -3184,7 +3861,9 @@ namespace Server.Items m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); if (m_AccuracyLevel > WeaponAccuracyLevel.Supremely) + { m_AccuracyLevel = WeaponAccuracyLevel.Accurate; + } } if (GetSaveFlag(flags, SaveFlag.DurabilityLevel)) @@ -3192,76 +3871,128 @@ namespace Server.Items m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); if (m_DurabilityLevel > WeaponDurabilityLevel.Indestructible) + { m_DurabilityLevel = WeaponDurabilityLevel.Durable; + } } if (GetSaveFlag(flags, SaveFlag.Quality)) + { m_Quality = (WeaponQuality)reader.ReadInt(); + } else + { m_Quality = WeaponQuality.Regular; + } if (GetSaveFlag(flags, SaveFlag.Hits)) + { m_Hits = reader.ReadInt(); + } if (GetSaveFlag(flags, SaveFlag.MaxHits)) + { m_MaxHits = reader.ReadInt(); + } if (GetSaveFlag(flags, SaveFlag.Slayer)) + { m_Slayer = (SlayerName)reader.ReadInt(); + } if (GetSaveFlag(flags, SaveFlag.Poison)) + { m_Poison = Poison.Deserialize(reader); + } if (GetSaveFlag(flags, SaveFlag.PoisonCharges)) + { m_PoisonCharges = reader.ReadInt(); + } if (GetSaveFlag(flags, SaveFlag.Crafter)) + { m_Crafter = reader.ReadMobile(); + } if (GetSaveFlag(flags, SaveFlag.Identified)) + { m_Identified = version >= 6 || reader.ReadBool(); + } if (GetSaveFlag(flags, SaveFlag.StrReq)) + { m_StrReq = reader.ReadInt(); + } else + { m_StrReq = -1; + } if (GetSaveFlag(flags, SaveFlag.DexReq)) + { m_DexReq = reader.ReadInt(); + } else + { m_DexReq = -1; + } if (GetSaveFlag(flags, SaveFlag.IntReq)) + { m_IntReq = reader.ReadInt(); + } else + { m_IntReq = -1; + } if (GetSaveFlag(flags, SaveFlag.MinDamage)) + { m_MinDamage = reader.ReadInt(); + } else + { m_MinDamage = -1; + } if (GetSaveFlag(flags, SaveFlag.MaxDamage)) + { m_MaxDamage = reader.ReadInt(); + } else + { m_MaxDamage = -1; + } if (GetSaveFlag(flags, SaveFlag.HitSound)) + { m_HitSound = reader.ReadInt(); + } else + { m_HitSound = -1; + } if (GetSaveFlag(flags, SaveFlag.MissSound)) + { m_MissSound = reader.ReadInt(); + } else + { m_MissSound = -1; + } if (GetSaveFlag(flags, SaveFlag.Speed)) { if (version < 9) + { m_Speed = reader.ReadInt(); + } else + { m_Speed = reader.ReadFloat(); + } } else { @@ -3269,39 +4000,67 @@ namespace Server.Items } if (GetSaveFlag(flags, SaveFlag.MaxRange)) + { m_MaxRange = reader.ReadInt(); + } else + { m_MaxRange = -1; + } if (GetSaveFlag(flags, SaveFlag.Skill)) + { m_Skill = (SkillName)reader.ReadInt(); + } else + { m_Skill = (SkillName)(-1); + } if (GetSaveFlag(flags, SaveFlag.Type)) + { m_Type = (WeaponType)reader.ReadInt(); + } else + { m_Type = (WeaponType)(-1); + } if (GetSaveFlag(flags, SaveFlag.Animation)) + { m_Animation = (WeaponAnimation)reader.ReadInt(); + } else + { m_Animation = (WeaponAnimation)(-1); + } if (GetSaveFlag(flags, SaveFlag.Resource)) + { m_Resource = (CraftResource)reader.ReadInt(); + } else + { m_Resource = CraftResource.Iron; + } if (GetSaveFlag(flags, SaveFlag.xAttributes)) + { Attributes = new AosAttributes(this, reader); + } else + { Attributes = new AosAttributes(this); + } if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes)) + { WeaponAttributes = new AosWeaponAttributes(this, reader); + } else + { WeaponAttributes = new AosWeaponAttributes(this); + } if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) { @@ -3310,7 +4069,9 @@ namespace Server.Items } if (version < 7 && WeaponAttributes.MageWeapon != 0) + { WeaponAttributes.MageWeapon = 30 - WeaponAttributes.MageWeapon; + } if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30 && parentMobile != null) @@ -3320,23 +4081,37 @@ namespace Server.Items } if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) + { PlayerConstructed = true; + } if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + { SkillBonuses = new AosSkillBonuses(this, reader); + } else + { SkillBonuses = new AosSkillBonuses(this); + } if (GetSaveFlag(flags, SaveFlag.Slayer2)) + { m_Slayer2 = (SlayerName)reader.ReadInt(); + } if (GetSaveFlag(flags, SaveFlag.ElementalDamages)) + { AosElementDamages = new AosElementAttributes(this, reader); + } else + { AosElementDamages = new AosElementAttributes(this); + } if (GetSaveFlag(flags, SaveFlag.EngravedText)) + { m_EngravedText = reader.ReadString(); + } break; } @@ -3369,7 +4144,9 @@ namespace Server.Items case 0: { if (version == 0) + { m_MaxRange = 1; // default + } if (version < 5) { @@ -3402,40 +4179,64 @@ namespace Server.Items m_PoisonCharges = reader.ReadInt(); if (m_StrReq == OldStrengthReq) + { m_StrReq = -1; + } if (m_DexReq == OldDexterityReq) + { m_DexReq = -1; + } if (m_IntReq == OldIntelligenceReq) + { m_IntReq = -1; + } if (m_MinDamage == OldMinDamage) + { m_MinDamage = -1; + } if (m_MaxDamage == OldMaxDamage) + { m_MaxDamage = -1; + } if (m_HitSound == OldHitSound) + { m_HitSound = -1; + } if (m_MissSound == OldMissSound) + { m_MissSound = -1; + } if (m_Speed == OldSpeed) + { m_Speed = -1; + } if (m_MaxRange == OldMaxRange) + { m_MaxRange = -1; + } if (m_Skill == OldSkill) + { m_Skill = (SkillName)(-1); + } if (m_Type == OldType) + { m_Type = (WeaponType)(-1); + } if (m_Animation == OldAnimation) + { m_Animation = (WeaponAnimation)(-1); + } if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) { @@ -3448,7 +4249,9 @@ namespace Server.Items } if (Core.AOS && parentMobile != null) + { SkillBonuses.AddTo(parentMobile); + } var strBonus = Attributes.BonusStr; var dexBonus = Attributes.BonusDex; @@ -3459,21 +4262,32 @@ namespace Server.Items var modName = Serial.ToString(); if (strBonus != 0) + { parentMobile.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + } if (dexBonus != 0) + { parentMobile.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + } if (intBonus != 0) + { parentMobile.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } } parentMobile?.CheckStatTimers(); - if (m_Hits <= 0 && m_MaxHits <= 0) m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); + if (m_Hits <= 0 && m_MaxHits <= 0) + { + m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); + } if (version < 6) + { PlayerConstructed = true; // we don't know, so, assume it's crafted + } } private class ResetEquipTimer : Timer diff --git a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs index e9339e29e..78c768692 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs @@ -71,11 +71,15 @@ namespace Server.Items canSwing = !attacker.Paralyzed && !attacker.Frozen; if (canSwing) + { canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; + } } if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) + { canSwing = false; + } if (canSwing && attacker.HarmfulCheck(defender)) { @@ -85,9 +89,13 @@ namespace Server.Items if (OnFired(attacker, defender)) { if (CheckHit(attacker, defender)) + { OnHit(attacker, defender); + } else + { OnMiss(attacker, defender); + } } } @@ -105,7 +113,9 @@ namespace Server.Items { if (attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && Utility.RandomDouble() <= 0.4) + { defender.AddToBackpack(Ammo); + } if (Core.ML && m_Velocity > 0) { @@ -116,10 +126,14 @@ namespace Server.Items AOS.Damage(defender, attacker, bonus * 3, 100, 0, 0, 0, 0); if (attacker.Player) + { attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity! + } if (defender.Player) + { defender.SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity! + } } } @@ -136,17 +150,17 @@ namespace Server.Items { var ammo = AmmoType; - if (pm.RecoverableAmmo.ContainsKey(ammo)) - pm.RecoverableAmmo[ammo]++; - else - pm.RecoverableAmmo.Add(ammo, 1); + pm.RecoverableAmmo.TryGetValue(ammo, out var result); + pm.RecoverableAmmo[ammo] = result + 1; if (!pm.Warmode) { m_RecoveryTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(10), pm.RecoverAmmo); if (!m_RecoveryTimer.Running) + { m_RecoveryTimer.Start(); + } } } } @@ -177,9 +191,13 @@ namespace Server.Items { // consume ammo if (quiver?.ConsumeTotal(AmmoType) == true) + { quiver.InvalidateWeight(); + } else if (pack?.ConsumeTotal(AmmoType) != true) + { return false; + } } else if (quiver.FindItemByType(AmmoType) == null && pack?.FindItemByType(AmmoType) == null) { diff --git a/Projects/UOContent/Misc/AOS.cs b/Projects/UOContent/Misc/AOS.cs index b480e3848..af0f9b4fe 100644 --- a/Projects/UOContent/Misc/AOS.cs +++ b/Projects/UOContent/Misc/AOS.cs @@ -100,7 +100,7 @@ namespace Server if (archer && from != null) { - quiver = @from.FindItemOnLayer(Layer.Cloak) as BaseQuiver; + quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver; } int totalDamage; diff --git a/Projects/UOContent/Misc/Guild.cs b/Projects/UOContent/Misc/Guild.cs index ad8ffff75..44539bbdb 100644 --- a/Projects/UOContent/Misc/Guild.cs +++ b/Projects/UOContent/Misc/Guild.cs @@ -66,9 +66,13 @@ namespace Server.Guilds public void SetFlag(RankFlags flag, bool value) { if (value) + { Flags |= flag; + } else + { Flags &= ~flag; + } } } @@ -89,8 +93,7 @@ namespace Server.Guilds leader.Alliance = this; partner.Alliance = this; - if (!Alliances.ContainsKey(Name.ToLower())) - Alliances.Add(Name.ToLower(), this); + Alliances.TryAdd(Name.ToLower(), this); } public AllianceInfo(IGenericReader reader) @@ -126,12 +129,16 @@ namespace Server.Guilds set { if (m_Leader != value && value != null) + { AllianceMessage(1070765, value.Name); // Your Alliance is now led by ~1_GUILDNAME~ + } m_Leader = value; if (m_Leader == null) + { CalculateAllianceLeader(); + } } } @@ -147,14 +154,18 @@ namespace Server.Guilds CalculateAllianceLeader(); if (m_Leader == null) + { Disband(); + } } } public bool IsPendingMember(Guild g) { if (g.Alliance != this) + { return false; + } return m_PendingMembers.Contains(g); } @@ -162,7 +173,9 @@ namespace Server.Guilds public bool IsMember(Guild g) { if (g.Alliance != this) + { return false; + } return m_Members.Contains(g); } @@ -177,14 +190,15 @@ namespace Server.Guilds writer.WriteGuildList(m_Members, true); writer.WriteGuildList(m_PendingMembers, true); - if (!Alliances.ContainsKey(Name.ToLower())) - Alliances.Add(Name.ToLower(), this); + Alliances.TryAdd(Name.ToLower(), this); } public void AddPendingGuild(Guild g) { if (g.Alliance != this || m_PendingMembers.Contains(g) || m_Members.Contains(g)) + { return; + } m_PendingMembers.Add(g); } @@ -192,7 +206,9 @@ namespace Server.Guilds public void TurnToMember(Guild g) { if (g.Alliance != this || !m_PendingMembers.Contains(g) || m_Members.Contains(g)) + { return; + } g.GuildMessage(1070760, Name); // Your Guild has joined the ~1_ALLIANCENAME~ Alliance. AllianceMessage(1070761, g.Name); // A new Guild has joined your Alliance: ~1_GUILDNAME~ @@ -204,7 +220,10 @@ namespace Server.Guilds public void RemoveGuild(Guild g) { - if (m_PendingMembers.Contains(g)) m_PendingMembers.Remove(g); + if (m_PendingMembers.Contains(g)) + { + m_PendingMembers.Remove(g); + } if (m_Members.Contains(g)) // Sanity, just incase someone with a custom script adds a character to BOTH arrays { @@ -219,10 +238,15 @@ namespace Server.Guilds // to check on OSI: have 3 guilds, make 2 of them a member, one pending. remove one of the memebers. alliance still exist? // ANSWER: NO - if (g == m_Leader) CalculateAllianceLeader(); + if (g == m_Leader) + { + CalculateAllianceLeader(); + } if (m_Members.Count < 2) + { Disband(); + } } public void Disband() @@ -230,13 +254,21 @@ namespace Server.Guilds AllianceMessage(1070762); // Your Alliance has dissolved. for (var i = 0; i < m_PendingMembers.Count; i++) + { m_PendingMembers[i].Alliance = null; + } for (var i = 0; i < m_Members.Count; i++) + { m_Members[i].Alliance = null; + } - if (Alliances.TryGetValue(Name.ToLower(), out var aInfo) && aInfo == this) - Alliances.Remove(Name.ToLower()); + var lowerName = Name.ToLower(); + + if (Alliances.TryGetValue(lowerName, out var aInfo) && aInfo == this) + { + Alliances.Remove(lowerName); + } } public void InvalidateMemberProperties(bool onlyOPL = false) @@ -252,7 +284,9 @@ namespace Server.Guilds public void InvalidateMemberNotoriety() { for (var i = 0; i < m_Members.Count; i++) + { m_Members[i].InvalidateMemberNotoriety(); + } } public void AllianceMessage(int num, bool append, string format, params object[] args) @@ -263,19 +297,25 @@ namespace Server.Guilds public void AllianceMessage(int number) { for (var i = 0; i < m_Members.Count; ++i) + { m_Members[i].GuildMessage(number); + } } public void AllianceMessage(int number, string args, int hue = 0x3B2) { for (var i = 0; i < m_Members.Count; ++i) + { m_Members[i].GuildMessage(number, args, hue); + } } public void AllianceMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) { for (var i = 0; i < m_Members.Count; ++i) + { m_Members[i].GuildMessage(number, append, affix, args, hue); + } } public void AllianceTextMessage(string text) @@ -291,7 +331,9 @@ namespace Server.Guilds public void AllianceTextMessage(int hue, string text) { for (var i = 0; i < m_Members.Count; ++i) + { m_Members[i].GuildTextMessage(hue, text); + } } public void AllianceTextMessage(int hue, string format, params object[] args) @@ -383,7 +425,9 @@ namespace Server.Guilds public override void OnResponse(NetState sender, RelayInfo info) { if (info.ButtonID != 8) // So that they can't get to the AdvancedSearch button + { base.OnResponse(sender, info); + } } } } @@ -451,23 +495,33 @@ namespace Server.Guilds get { if (Opponent?.Disbanded != false) + { return WarStatus.Win; + } if (Guild?.Disbanded != false) + { return WarStatus.Lose; + } var w = Opponent.FindActiveWar(Guild); if (Opponent.FindPendingWar(Guild) != null && Guild.FindPendingWar(Opponent) != null) + { return WarStatus.Pending; + } if (w == null) + { return WarStatus.Win; + } if (WarLength != TimeSpan.Zero && WarBeginning + WarLength < DateTime.UtcNow) { if (Kills > w.Kills) + { return WarStatus.Win; + } return Kills < w.Kills ? WarStatus.Lose : WarStatus.Draw; } @@ -475,9 +529,14 @@ namespace Server.Guilds if (MaxKills > 0) { if (Kills >= MaxKills) + { return WarStatus.Win; + } + if (w.Kills >= w.MaxKills) + { return WarStatus.Lose; + } } return WarStatus.InProgress; @@ -509,13 +568,17 @@ namespace Server.Guilds public static void Initialize() { if (Guild.NewGuildSystem) + { new WarTimer().Start(); + } } protected override void OnTick() { foreach (var g in BaseGuild.List.Values) + { (g as Guild)?.CheckExpiredWars(); + } } } @@ -561,7 +624,9 @@ namespace Server.Guilds AddMember(m_Leader); if (m_Leader is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Leader; + } AcceptedWars = new List(); PendingWars = new List(); @@ -580,22 +645,30 @@ namespace Server.Guilds get { if (Disbanded || m_Leader.Guild != this) + { CalculateGuildmaster(); + } return m_Leader; } set { if (value != null) + { AddMember(value); // Also removes from old guild. + } if (m_Leader is PlayerMobile leader && leader.Guild == this) + { leader.GuildRank = RankDefinition.Member; + } m_Leader = value; if (m_Leader is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Leader; + } } } @@ -606,7 +679,9 @@ namespace Server.Guilds get { if (m_AllianceInfo != null) + { return m_AllianceInfo; + } return m_AllianceLeader?.m_AllianceInfo; } @@ -615,16 +690,22 @@ namespace Server.Guilds var current = Alliance; if (value == current) + { return; + } current?.RemoveGuild(this); if (value != null) { if (value.Leader == this) + { m_AllianceInfo = value; + } else + { m_AllianceLeader = value.Leader; + } value.AddPendingGuild(this); } @@ -748,14 +829,18 @@ namespace Server.Guilds m.InvalidateProperties(); if (!onlyOPL) + { m.Delta(MobileDelta.Noto); + } } } public void InvalidateMemberNotoriety() { for (var i = 0; i < Members?.Count; i++) + { Members[i].Delta(MobileDelta.Noto); + } } public void InvalidateWarNotoriety() @@ -763,21 +848,31 @@ namespace Server.Guilds var g = GetAllianceLeader(this); if (g.Alliance != null) + { g.Alliance.InvalidateMemberNotoriety(); + } else + { g.InvalidateMemberNotoriety(); + } if (g.AcceptedWars == null) + { return; + } foreach (var warDec in g.AcceptedWars) { var opponent = warDec.Opponent; if (opponent.Alliance != null) + { opponent.Alliance.InvalidateMemberNotoriety(); + } else + { opponent.InvalidateMemberNotoriety(); + } } } @@ -797,7 +892,9 @@ namespace Server.Guilds m.SendLocalizedMessage(502131); // Your guild has disbanded. if (m is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Lowest; + } m.Guild = null; } @@ -805,15 +902,25 @@ namespace Server.Guilds Members.Clear(); for (var i = Allies.Count - 1; i >= 0; --i) + { if (i < Allies.Count) + { RemoveAlly(Allies[i]); + } + } for (var i = Enemies.Count - 1; i >= 0; --i) + { if (i < Enemies.Count) + { RemoveEnemy(Enemies[i]); + } + } if (!NewGuildSystem) + { Guildstone?.Delete(); + } Guildstone = null; @@ -846,7 +953,9 @@ namespace Server.Guilds from.SendGump(new PropertiesGump(from, g)); if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile mobile) + { mobile.SendGump(new GuildInfoGump(mobile, g)); + } } } } @@ -854,12 +963,18 @@ namespace Server.Guilds public static void EventSink_GuildGumpRequest(Mobile m) { if (!NewGuildSystem || !(m is PlayerMobile pm)) + { return; + } if (pm.Guild == null) + { pm.SendGump(new CreateGuildGump(pm)); + } else + { pm.SendGump(new GuildInfoGump(pm, pm.Guild as Guild)); + } } public static void EventSink_CreateGuild(CreateGuildEventArgs args) @@ -872,7 +987,9 @@ namespace Server.Guilds var alliance = g.Alliance; if (alliance?.Leader != null && alliance.IsMember(g)) + { return alliance.Leader; + } return g; } @@ -884,7 +1001,9 @@ namespace Server.Guilds var w = PendingWars[i]; if (w.Opponent == g) + { return w; + } } return null; @@ -897,7 +1016,9 @@ namespace Server.Guilds var w = AcceptedWars[i]; if (w.Opponent == g) + { return w; + } } return null; @@ -942,10 +1063,14 @@ namespace Server.Guilds AcceptedWars.Remove(w); if (g == null) + { continue; + } if (status != WarStatus.Draw) + { status = (WarStatus)((int)status + 1 % 2); + } if (otherInAlliance) { @@ -980,12 +1105,16 @@ namespace Server.Guilds public static void HandleDeath(Mobile victim, Mobile killer = null) { if (!NewGuildSystem) + { return; + } killer ??= victim.FindMostRecentDamager(false); if (killer?.Guild == null || victim.Guild == null) + { return; + } var victimGuild = GetAllianceLeader(victim.Guild as Guild); var killerGuild = GetAllianceLeader(killer.Guild as Guild); @@ -993,14 +1122,20 @@ namespace Server.Guilds var war = killerGuild.FindActiveWar(victimGuild); if (war == null) + { return; + } war.Kills++; if (war.Opponent == victimGuild) + { killerGuild.CheckExpiredWars(); + } else + { victimGuild.CheckExpiredWars(); + } } public bool IsMember(Mobile m) => Members.Contains(m); @@ -1014,10 +1149,14 @@ namespace Server.Guilds public bool IsWar(Guild g) { if (g == null) + { return false; + } if (!NewGuildSystem) + { return Enemies.Contains(g); + } var guild = GetAllianceLeader(this); var otherGuild = GetAllianceLeader(g); @@ -1028,7 +1167,9 @@ namespace Server.Guilds public override void Serialize(IGenericWriter writer) { if (LastFealty + TimeSpan.FromDays(1.0) < DateTime.UtcNow) + { CalculateGuildmaster(); + } CheckExpiredWars(); @@ -1038,19 +1179,29 @@ namespace Server.Guilds writer.Write(PendingWars.Count); - for (var i = 0; i < PendingWars.Count; i++) PendingWars[i].Serialize(writer); + for (var i = 0; i < PendingWars.Count; i++) + { + PendingWars[i].Serialize(writer); + } writer.Write(AcceptedWars.Count); - for (var i = 0; i < AcceptedWars.Count; i++) AcceptedWars[i].Serialize(writer); + for (var i = 0; i < AcceptedWars.Count; i++) + { + AcceptedWars[i].Serialize(writer); + } var isAllianceLeader = m_AllianceLeader == null && m_AllianceInfo != null; writer.Write(isAllianceLeader); if (isAllianceLeader) + { m_AllianceInfo.Serialize(writer); + } else + { writer.Write(m_AllianceLeader); + } // @@ -1094,18 +1245,28 @@ namespace Server.Guilds var count = reader.ReadInt(); PendingWars = new List(); - for (var i = 0; i < count; i++) PendingWars.Add(new WarDeclaration(reader)); + for (var i = 0; i < count; i++) + { + PendingWars.Add(new WarDeclaration(reader)); + } count = reader.ReadInt(); AcceptedWars = new List(); - for (var i = 0; i < count; i++) AcceptedWars.Add(new WarDeclaration(reader)); + for (var i = 0; i < count; i++) + { + AcceptedWars.Add(new WarDeclaration(reader)); + } var isAllianceLeader = reader.ReadBool(); if (isAllianceLeader) + { m_AllianceInfo = new AllianceInfo(reader); + } else + { m_AllianceLeader = reader.ReadGuild() as Guild; + } goto case 4; } @@ -1139,7 +1300,9 @@ namespace Server.Guilds m_Leader = reader.ReadMobile(); if (m_Leader is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Leader; + } m_Name = reader.ReadString(); m_Abbreviation = reader.ReadString(); @@ -1174,7 +1337,9 @@ namespace Server.Guilds private void VerifyGuild_Callback() { if (!NewGuildSystem && Guildstone == null || Members.Count == 0) + { Disband(); + } CheckExpiredWars(); @@ -1186,7 +1351,9 @@ namespace Server.Guilds if (alliance?.IsMember(this) == false && !alliance.IsPendingMember(this) ) // This block is there to fix a bug in the code in an older version. + { Alliance = null; // Will call Alliance.RemoveGuild which will set it null & perform all the pertient checks as far as alliacne disbanding + } } public void AddMember(Mobile m) @@ -1194,7 +1361,9 @@ namespace Server.Guilds if (!Members.Contains(m)) { if (m.Guild != null && m.Guild != this) + { ((Guild)m.Guild).RemoveMember(m); + } Members.Add(m); m.Guild = this; @@ -1202,7 +1371,9 @@ namespace Server.Guilds m.GuildFealty = !NewGuildSystem ? m_Leader : null; if (m is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Lowest; + } ((Guild)m.Guild).InvalidateWarNotoriety(); } @@ -1219,21 +1390,29 @@ namespace Server.Guilds m.Guild = null; if (m is PlayerMobile mobile) + { mobile.GuildRank = RankDefinition.Lowest; + } if (message > 0) + { m.SendLocalizedMessage(message); + } if (m == m_Leader) { CalculateGuildmaster(); if (m_Leader == null) + { Disband(); + } } if (Members.Count == 0) + { Disband(); + } guild?.InvalidateWarNotoriety(); @@ -1289,19 +1468,25 @@ namespace Server.Guilds public void GuildMessage(int number) { for (var i = 0; i < Members.Count; ++i) + { Members[i].SendLocalizedMessage(number); + } } public void GuildMessage(int number, string args, int hue = 0x3B2) { for (var i = 0; i < Members.Count; ++i) + { Members[i].SendLocalizedMessage(number, args, hue); + } } public void GuildMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) { for (var i = 0; i < Members.Count; ++i) + { Members[i].SendLocalizedMessage(number, append, affix, args, hue); + } } public void GuildTextMessage(string text) @@ -1317,7 +1502,9 @@ namespace Server.Guilds public void GuildTextMessage(int hue, string text) { for (var i = 0; i < Members.Count; ++i) + { Members[i].SendMessage(hue, text); + } } public void GuildTextMessage(int hue, string format, params object[] args) @@ -1371,20 +1558,28 @@ namespace Server.Guilds var memb = Members[i]; if (!CanVote(memb)) + { continue; + } var m = memb.GuildFealty; if (!CanBeVotedFor(m)) { if (!Disbanded && m_Leader.Guild == this) + { m = m_Leader; + } else + { m = memb; + } } if (m == null) + { continue; + } votes[m] = 1 + (votes.TryGetValue(m, out var v) ? v : 0); votingMembers++; @@ -1407,10 +1602,14 @@ namespace Server.Guilds if (NewGuildSystem && highVotes * 100 / Math.Max(votingMembers, 1) < MajorityPercentage && !Disbanded && winner != m_Leader && m_Leader.Guild == this) + { winner = m_Leader; + } if (m_Leader != winner && winner != null) + { GuildMessage(1018015, true, winner.Name); // Guild Message: Guildmaster changed to: + } Leader = winner; LastFealty = DateTime.UtcNow; @@ -1456,7 +1655,9 @@ namespace Server.Guilds from.SendGump(new PropertiesGump(from, g)); if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile pm) + { pm.SendGump(new GuildInfoGump(pm, g)); + } } } } diff --git a/Projects/UOContent/Misc/InhumanSpeech.cs b/Projects/UOContent/Misc/InhumanSpeech.cs index 58a3ccd16..76736bbcb 100644 --- a/Projects/UOContent/Misc/InhumanSpeech.cs +++ b/Projects/UOContent/Misc/InhumanSpeech.cs @@ -288,7 +288,9 @@ namespace Server.Misc m_Keywords = value; m_KeywordHash = new Dictionary(m_Keywords.Length, StringComparer.OrdinalIgnoreCase); for (var i = 0; i < m_Keywords.Length; ++i) + { m_KeywordHash[m_Keywords[i]] = m_Keywords[i]; + } } } @@ -307,7 +309,9 @@ namespace Server.Misc var syllables = new string[syllableCount]; for (var i = 0; i < syllableCount; ++i) + { syllables[i] = GetRandomSyllable(); + } return string.Concat(syllables); } @@ -333,33 +337,47 @@ namespace Server.Misc needUpperCase = true; if (random > 13) + { sentance.Append("! "); + } else + { sentance.Append(". "); + } } } int syllableCount; if (Utility.Random(100) < 30) + { syllableCount = Utility.Random(1, 5); + } else + { syllableCount = Utility.Random(1, 3); + } var word = ConstructWord(syllableCount); sentance.Append(word); if (needUpperCase) + { sentance.Replace(word[0], char.ToUpper(word[0]), sentance.Length - word.Length, 1); + } needUpperCase = false; } if (Utility.RandomMinMax(1, 5) == 1) + { sentance.Append('!'); + } else + { sentance.Append('.'); + } return sentance.ToString(); } @@ -380,35 +398,53 @@ namespace Server.Misc public bool OnSpeech(Mobile mob, Mobile speaker, string text) { if ((Flags & IHSFlags.OnSpeech) == 0 || m_Keywords == null || Responses == null || m_KeywordHash == null) + { return false; // not enabled + } if (!speaker.Alive) + { return false; + } if (!speaker.InRange(mob, 3)) + { return false; + } if ((speaker.Direction & Direction.Mask) != speaker.GetDirectionTo(mob)) + { return false; + } if ((mob.Direction & Direction.Mask) != mob.GetDirectionTo(speaker)) + { return false; + } var split = text.Split(' '); var keywordsFound = new List(); for (var i = 0; i < split.Length; ++i) + { if (m_KeywordHash.TryGetValue(split[i], out var keyword)) + { keywordsFound.Add(keyword); + } + } if (keywordsFound.Count > 0) { string responseWord; if (Utility.RandomBool()) + { responseWord = GetRandomResponseWord(keywordsFound); + } else + { responseWord = keywordsFound.RandomElement(); + } var secondResponseWord = GetRandomResponseWord(keywordsFound); @@ -469,9 +505,13 @@ namespace Server.Misc var maxWords = split.Length / 2 + 1; if (maxWords < 2) + { maxWords = 2; + } else if (maxWords > 6) + { maxWords = 6; + } SaySentance(mob, Utility.RandomMinMax(2, maxWords)); mob.Say(response.ToString()); @@ -485,10 +525,14 @@ namespace Server.Misc public void OnDeath(Mobile mob) { if ((Flags & IHSFlags.OnDeath) == 0) + { return; // not enabled + } if (Utility.Random(100) < 90) + { return; // 90% chance to do nothing; 10% chance to talk + } SayRandomTranslate( mob, @@ -506,16 +550,24 @@ namespace Server.Misc public void OnMovement(Mobile mob, Mobile mover, Point3D oldLocation) { if ((Flags & IHSFlags.OnMovement) == 0) + { return; // not enabled + } if (!mover.Player || mover.Hidden && mover.AccessLevel > AccessLevel.Player) + { return; + } if (!mob.InRange(mover, 5) || mob.InRange(oldLocation, 5)) + { return; // only talk when they enter 5 tile range + } if (Utility.Random(100) < 90) + { return; // 90% chance to do nothing; 10% chance to talk + } SaySentance(mob, 6); } @@ -523,12 +575,17 @@ namespace Server.Misc public void OnDamage(Mobile mob, int amount) { if ((Flags & IHSFlags.OnDamaged) == 0) + { return; // not enabled + } if (Utility.Random(100) < 90) + { return; // 90% chance to do nothing; 10% chance to talk + } if (amount < 5) + { SayRandomTranslate( mob, "Ouch!", @@ -537,7 +594,9 @@ namespace Server.Misc "Thy blows soft!", "You bad with weapon!" ); + } else + { SayRandomTranslate( mob, "Ouch! Me hurt!", @@ -548,6 +607,7 @@ namespace Server.Misc "Aaah! That hurt...", "Good blow!" ); + } } public void OnConstruct(Mobile mob) diff --git a/Projects/UOContent/Mobiles/AI/SpeedInfo.cs b/Projects/UOContent/Mobiles/AI/SpeedInfo.cs index 6d1b7fd9c..c892da74f 100644 --- a/Projects/UOContent/Mobiles/AI/SpeedInfo.cs +++ b/Projects/UOContent/Mobiles/AI/SpeedInfo.cs @@ -179,7 +179,7 @@ namespace Server if (m_Table == null) LoadTable(); - return m_Table.ContainsKey(obj.GetType()); + return m_Table!.ContainsKey(obj.GetType()); } public static bool GetSpeeds(object obj, ref double activeSpeed, ref double passiveSpeed) @@ -190,7 +190,7 @@ namespace Server if (m_Table == null) LoadTable(); - if (!m_Table.TryGetValue(obj.GetType(), out var sp)) + if (!m_Table!.TryGetValue(obj.GetType(), out var sp)) return false; activeSpeed = sp.ActiveSpeed; diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs index bf0792677..afdf14575 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs @@ -146,7 +146,7 @@ namespace Server.Mobiles public static void StopEffect(Mobile m, bool message) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { if (message) m.PublicOverheadMessage( @@ -157,7 +157,6 @@ namespace Server.Mobiles ); timer.Stop(); - m_Table.Remove(m); } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs index 120a462e8..908b20112 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs @@ -120,10 +120,9 @@ namespace Server.Mobiles public static void EndLifeDrain(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer?.Stop(); - m_Table.Remove(m); m.SendLocalizedMessage(1070849); // The drain on your life force is gone. } } diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 70c69179a..d37a3d1e2 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -1050,7 +1050,7 @@ namespace Server.Mobiles if (from.UseSkill(skillId)) { - @from.Target?.Invoke(@from, target); + from.Target?.Invoke(from, target); } if (skillId == 35) @@ -1294,7 +1294,7 @@ namespace Server.Mobiles if (from.NetState != null) { - Timer.DelayCall(TimeSpan.FromSeconds(1.0), @from.NetState.Dispose); + Timer.DelayCall(TimeSpan.FromSeconds(1.0), from.NetState.Dispose); } } else if (from.AccessLevel >= AccessLevel.Administrator) @@ -1470,11 +1470,11 @@ namespace Server.Mobiles if (armor is BaseShield) { - @from.SendLocalizedMessage(1062003, name); // You can no longer equip your ~1_SHIELD~ + from.SendLocalizedMessage(1062003, name); // You can no longer equip your ~1_SHIELD~ } else { - @from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~ + from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~ } from.AddToBackpack(armor); @@ -1547,7 +1547,7 @@ namespace Server.Mobiles if (moved) { - @from.SendLocalizedMessage(500647); // Some equipment has been moved to your backpack. + from.SendLocalizedMessage(500647); // Some equipment has been moved to your backpack. } } catch (Exception e) @@ -2011,7 +2011,7 @@ namespace Server.Mobiles { if (Core.TOL && from.InRange(this, 2)) { - list.Add(new CallbackEntry(1077728, () => OpenTrade(@from))); // Trade + list.Add(new CallbackEntry(1077728, () => OpenTrade(from))); // Trade } if (Alive && Core.Expansion >= Expansion.AOS) @@ -2027,11 +2027,11 @@ namespace Server.Mobiles { if (ourParty == null) { - list.Add(new AddToPartyEntry(@from, this)); + list.Add(new AddToPartyEntry(from, this)); } else if (ourParty == theirParty) { - list.Add(new RemoveFromPartyEntry(@from, this)); + list.Add(new RemoveFromPartyEntry(from, this)); } } } @@ -2041,7 +2041,7 @@ namespace Server.Mobiles if (curhouse != null && Alive && Core.Expansion >= Expansion.AOS && curhouse.IsAosRules && curhouse.IsFriend(from)) { - list.Add(new EjectPlayerEntry(@from, this)); + list.Add(new EjectPlayerEntry(from, this)); } } } @@ -2902,11 +2902,11 @@ namespace Server.Mobiles if (Core.ML) { - @from.Damage((int)(amount * (1 - (@from.Skills.MagicResist.Value * .5 + 10) / 100)), this); + from.Damage((int)(amount * (1 - (from.Skills.MagicResist.Value * .5 + 10) / 100)), this); } else { - @from.Damage(amount, this); + from.Damage(amount, this); } } @@ -2916,7 +2916,7 @@ namespace Server.Mobiles { var type = talisman.Protection.Type; - if (type.IsInstanceOfType(@from)) + if (type.IsInstanceOfType(from)) { amount = (int)(amount * (1 - (double)talisman.Protection.Amount / 100)); } @@ -4188,7 +4188,7 @@ namespace Server.Mobiles if (from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer timer) { - timer.From = @from; + timer.From = from; } return result; @@ -4207,7 +4207,7 @@ namespace Server.Mobiles } else { - base.OnPoisonImmunity(@from, poison); + base.OnPoisonImmunity(from, poison); } } @@ -4685,20 +4685,16 @@ namespace Server.Mobiles public void RemoveBuff(BuffIcon b) { - if (m_BuffTable?.ContainsKey(b) != true) + if (!m_BuffTable.Remove(b, out var info)) { return; } - var info = m_BuffTable[b]; - if (info.Timer?.Running == true) { info.Timer.Stop(); } - m_BuffTable.Remove(b); - if (NetState?.BuffIcon == true) { NetState.Send(new RemoveBuffPacket(this, b)); diff --git a/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs b/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs index e67521399..d066e9278 100644 --- a/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs +++ b/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs @@ -149,11 +149,13 @@ namespace Server.Mobiles var okay = true; foreach (var obj in quest.Objectives) + { if (obj is EscortObjective objective && objective.Destination.Contains(reg)) { okay = false; // We're already there! break; } + } if (okay) { @@ -175,7 +177,9 @@ namespace Server.Mobiles if (m_MLQuest == null) { if (MLQuestSystem.Debug) + { Console.WriteLine("Warning: No suitable quest found for escort {0}", Serial); + } return null; } @@ -232,7 +236,9 @@ namespace Server.Mobiles var dest = GetDestination(); if (dest == null || !m.Alive) + { return false; + } var escorter = GetEscorter(); @@ -262,10 +268,14 @@ namespace Server.Mobiles var dest = GetDestination(); if (dest == null) + { return false; + } if (GetEscorter() != null || !m.Alive) + { return false; + } if (EscortTable.TryGetValue(m, out var escortable) && escortable?.Deleted == false && escortable.GetEscorter() == m) @@ -288,7 +298,9 @@ namespace Server.Mobiles m_LastSeenEscorter = DateTime.UtcNow; if (m is PlayerMobile playerMobile) + { playerMobile.LastEscortTime = DateTime.UtcNow; + } Say( "Lead on! Payment will be made when we arrive in {0}.", @@ -310,12 +322,18 @@ namespace Server.Mobiles base.OnSpeech(e); if (GetDestination() == null || e.Handled || !e.Mobile.InRange(Location, 3)) + { return; + } if (e.HasKeyword(0x1D)) // *destination* + { e.Handled = SayDestinationTo(e.Mobile); + } else if (e.HasKeyword(0x1E)) // *i will take thee* + { e.Handled = AcceptEscorter(e.Mobile); + } } public override void OnAfterDelete() @@ -336,7 +354,9 @@ namespace Server.Mobiles protected override bool OnMove(Direction d) { if (!base.OnMove(d)) + { return false; + } CheckAtDestination(); @@ -353,7 +373,9 @@ namespace Server.Mobiles public virtual void StartFollow(Mobile escorter) { if (escorter == null) + { return; + } ActiveSpeed = 0.1; PassiveSpeed = 0.2; @@ -361,7 +383,11 @@ namespace Server.Mobiles ControlOrder = OrderType.Follow; ControlTarget = escorter; - if (IsPrisoner && CantWalk) CantWalk = false; + if (IsPrisoner && CantWalk) + { + CantWalk = false; + } + CurrentSpeed = 0.1; } @@ -379,12 +405,16 @@ namespace Server.Mobiles public virtual Mobile GetEscorter() { if (!Controlled) + { return null; + } var master = ControlMaster; if (MLQuestSystem.Enabled || master == null) + { return master; + } if (master.Deleted || master.Map != Map || !master.InRange(Location, 30) || !master.Alive) { @@ -409,7 +439,9 @@ namespace Server.Mobiles } if (ControlOrder != OrderType.Follow) + { StartFollow(master); + } m_LastSeenEscorter = DateTime.UtcNow; return master; @@ -428,17 +460,23 @@ namespace Server.Mobiles public virtual bool CheckAtDestination() { if (MLQuestSystem.Enabled) + { return false; + } var dest = GetDestination(); if (dest == null) + { return false; + } var escorter = GetEscorter(); if (escorter == null) + { return false; + } if (dest.Contains(Location)) { @@ -456,7 +494,9 @@ namespace Server.Mobiles var gold = new Gold(500, 1000); if (!cont.TryDropItem(escorter, gold, false)) + { gold.MoveToWorld(escorter.Location, escorter.Map); + } StopFollow(); SetControlMaster(null); @@ -484,18 +524,24 @@ namespace Server.Mobiles else if (VirtueHelper.Award(pm, VirtueName.Compassion, IsPrisoner ? 400 : 200, ref gainedPath)) { if (gainedPath) + { pm.SendLocalizedMessage(1053005); // You have achieved a path in compassion! + } else + { pm.SendLocalizedMessage(1053002); // You have gained in compassion. + } pm.NextCompassionDay = DateTime.UtcNow + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0 ++pm.CompassionGains; if (pm.CompassionGains >= 5) + { pm.SendLocalizedMessage( 1053004 ); // You must wait about a day before you can gain in compassion again. + } } else { @@ -529,12 +575,16 @@ namespace Server.Mobiles writer.Write(dest != null); if (dest != null) + { writer.Write(dest.Name); + } writer.Write(m_DeleteTimer != null); if (m_DeleteTimer != null) + { writer.WriteDeltaTime(m_DeleteTime); + } MLQuestSystem.WriteQuestRef(writer, StaticMLQuester ? null : m_MLQuest); } @@ -546,8 +596,10 @@ namespace Server.Mobiles var version = reader.ReadInt(); if (reader.ReadBool()) + { m_DestinationString = reader.ReadString(); // NOTE: We cannot EDI.Find here, regions have not yet been loaded :-( + } if (reader.ReadBool()) { @@ -561,7 +613,9 @@ namespace Server.Mobiles var quest = MLQuestSystem.ReadQuestRef(reader); if (MLQuestSystem.Enabled && quest != null && !StaticMLQuester) + { m_MLQuest = quest; + } } } @@ -576,14 +630,20 @@ namespace Server.Mobiles if (!MLQuestSystem.Enabled && GetDestination() != null) { if (escorter == null || escorter == from) + { list.Add(new AskDestinationEntry(this, from)); + } if (escorter == null) + { list.Add(new AcceptEscortEntry(this, from)); + } } if (escorter == from) + { list.Add(new AbandonEscortEntry(this)); + } } base.AddCustomContextEntries(from, list); @@ -594,7 +654,9 @@ namespace Server.Mobiles public virtual string PickRandomDestination() { if (Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero) + { return null; // Not yet fully initialized + } var possible = GetPossibleDestinations(); string picked = null; @@ -605,7 +667,9 @@ namespace Server.Mobiles var test = EDI.Find(picked); if (test.Contains(Location)) + { picked = null; + } } return picked; @@ -614,16 +678,24 @@ namespace Server.Mobiles public EDI GetDestination() { if (MLQuestSystem.Enabled) + { return null; + } if (m_DestinationString == null && m_DeleteTimer == null) + { m_DestinationString = PickRandomDestination(); + } if (m_Destination != null && m_Destination.Name == m_DestinationString) + { return m_Destination; + } if (Map.Felucca.Regions.Count > 0) + { return m_Destination = EDI.Find(m_DestinationString); + } return m_Destination = null; } @@ -668,22 +740,32 @@ namespace Server.Mobiles ICollection list = Map.Felucca.Regions.Values; if (list.Count == 0) + { return; + } m_Table = new Dictionary(); foreach (Region r in list) + { if (r.Name != null && (r is DungeonRegion || r is TownRegion)) + { m_Table[r.Name] = new EscortDestinationInfo(r.Name, r); + } + } } public static EDI Find(string name) { if (m_Table == null) + { LoadTable(); + } if (name == null || m_Table == null) + { return null; + } m_Table.TryGetValue(name, out var info); return info; diff --git a/Projects/UOContent/Multis/ContestHouses.cs b/Projects/UOContent/Multis/ContestHouses.cs index 8ed17a1c7..65839941b 100644 --- a/Projects/UOContent/Multis/ContestHouses.cs +++ b/Projects/UOContent/Multis/ContestHouses.cs @@ -68,10 +68,15 @@ namespace Server.Multis { base.OnAfterDelete(); - if (Fixtures == null) return; + if (Fixtures == null) + { + return; + } foreach (var item in Fixtures) + { item.Delete(); + } } public override void OnLocationChange(Point3D oldLocation) @@ -82,20 +87,30 @@ namespace Server.Multis var y = Location.Y - oldLocation.Y; var z = Location.Z - oldLocation.Z; - if (Fixtures == null) return; + if (Fixtures == null) + { + return; + } foreach (var item in Fixtures) + { item.Location = new Point3D(item.X + x, item.Y + y, item.Z + z); + } } public override void OnMapChange() { base.OnMapChange(); - if (Fixtures == null) return; + if (Fixtures == null) + { + return; + } foreach (var item in Fixtures) + { item.Map = Map; + } } public void AddTeleporters(int id, Point3D offset1, Point3D offset2) @@ -131,12 +146,17 @@ namespace Server.Multis foreach (var entry in components.List.Where(e => e.Flags == 0)) // Teleporters + { if (entry.ItemId >= 0x181D && entry.ItemId <= 0x1828) { - if (teleporters.ContainsKey(entry.ItemId)) - teleporters[entry.ItemId].Add(entry); + if (teleporters.TryGetValue(entry.ItemId, out var result)) + { + result.Add(entry); + } else - teleporters[entry.ItemId] = new List { entry }; + { + teleporters.Add(entry.ItemId, new List { entry }); + } } else { @@ -155,14 +175,19 @@ namespace Server.Multis AddFixture(st); } } + } foreach (var door in Doors) + { foreach (var check in Doors.Where(d => d != door)) + { if (door.InRange(check.Location, 1)) { door.Link = check; check.Link = door; } + } + } foreach (var (key, value) in teleporters) { @@ -195,9 +220,13 @@ namespace Server.Multis writer.Write((int)HouseType); if (Fixtures != null) + { writer.WriteItemList(Fixtures, true); + } else + { writer.Write(0); + } } public override void Deserialize(IGenericReader reader) @@ -210,7 +239,9 @@ namespace Server.Multis var count = reader.ReadInt(); for (var i = 0; i < count; i++) + { AddFixture(reader.ReadItem()); + } } } diff --git a/Projects/UOContent/Multis/HouseFoundation.cs b/Projects/UOContent/Multis/HouseFoundation.cs index 76d848332..ed0b52bed 100644 --- a/Projects/UOContent/Multis/HouseFoundation.cs +++ b/Projects/UOContent/Multis/HouseFoundation.cs @@ -125,7 +125,9 @@ namespace Server.Multis get { if (m_Current == null) + { SetInitialState(); + } return m_Current.Components; } @@ -135,7 +137,11 @@ namespace Server.Multis { get { - if (m_Current == null) SetInitialState(); + if (m_Current == null) + { + SetInitialState(); + } + return m_Current; } set => m_Current = value; @@ -145,7 +151,11 @@ namespace Server.Multis { get { - if (m_Design == null) SetInitialState(); + if (m_Design == null) + { + SetInitialState(); + } + return m_Design; } set => m_Design = value; @@ -155,7 +165,11 @@ namespace Server.Multis { get { - if (m_Backup == null) SetInitialState(); + if (m_Backup == null) + { + SetInitialState(); + } + return m_Backup; } set => m_Backup = value; @@ -183,7 +197,10 @@ namespace Server.Multis var mcl = Components; if (mcl.Width >= 14 || mcl.Height >= 14) + { return 4; + } + return 3; } } @@ -201,9 +218,13 @@ namespace Server.Multis var v = 18 + (w > h ? w : h) / 2; if (v > 24) + { v = 24; + } else if (v < 18) + { v = 18; + } return v; } @@ -225,7 +246,9 @@ namespace Server.Multis Signpost?.Delete(); if (Fixtures == null) + { return; + } for (var i = 0; i < Fixtures.Count; ++i) { @@ -250,14 +273,18 @@ namespace Server.Multis Signpost?.MoveToWorld(new Point3D(Signpost.X + x, Signpost.Y + y, Signpost.Z + z), Map); if (Fixtures == null) + { return; + } for (var i = 0; i < Fixtures.Count; ++i) { var item = Fixtures[i]; if (item is BaseDoor door && Doors.Contains(door)) + { continue; + } item.MoveToWorld(new Point3D(item.X + x, item.Y + y, item.Z + z), Map); } @@ -268,22 +295,32 @@ namespace Server.Multis base.OnMapChange(); if (SignHanger != null) + { SignHanger.Map = Map; + } if (Signpost != null) + { Signpost.Map = Map; + } if (Fixtures == null) + { return; + } for (var i = 0; i < Fixtures.Count; ++i) + { Fixtures[i].Map = Map; + } } public void ClearFixtures(Mobile from) { if (Fixtures == null) + { return; + } RemoveKeys(from); @@ -293,7 +330,9 @@ namespace Server.Multis item.Delete(); if (item is BaseDoor door) + { Doors.Remove(door); + } } Fixtures.Clear(); @@ -425,9 +464,13 @@ namespace Server.Multis DoorFacing facing; if (itemID == 0x31AA || itemID == 0x31A8) + { facing = mod == 0 ? DoorFacing.NorthCW : DoorFacing.EastCW; + } else + { facing = mod == 0 ? DoorFacing.EastCW : DoorFacing.NorthCW; + } var type = (itemID - 0x319C) / 4; @@ -495,7 +538,9 @@ namespace Server.Multis if (door != null) { if (keyValue == 0) + { keyValue = CreateKeys(from); + } door.Locked = true; door.KeyValue = keyValue; @@ -513,16 +558,20 @@ namespace Server.Multis if (fixture is HouseTeleporter tp) { for (var j = 1; j <= Fixtures.Count; ++j) + { if (Fixtures[(i + j) % Fixtures.Count] is HouseTeleporter check && check.ItemID == tp.ItemID) { tp.Target = check; break; } + } } else if (fixture is BaseHouseDoor door) { if (door.Link != null) + { continue; + } DoorFacing linkFacing; int xOffset, yOffset; @@ -592,6 +641,7 @@ namespace Server.Multis } for (var j = i + 1; j < Fixtures.Count; ++j) + { if (Fixtures[j] is BaseHouseDoor check && check.Link == null && check.Facing == linkFacing && check.X - door.X == xOffset && check.Y - door.Y == yOffset && check.Z == door.Z) { @@ -599,6 +649,7 @@ namespace Server.Multis door.Link = check; break; } + } } } } @@ -692,7 +743,9 @@ namespace Server.Multis mcl.Add(south, x - xCenter, 0 - yCenter, 0); if (x < mcl.Width - 1) + { mcl.Add(south, x - xCenter, mcl.Height - 2 - yCenter, 0); + } } for (var y = 1; y < mcl.Height - 1; ++y) @@ -700,7 +753,9 @@ namespace Server.Multis mcl.Add(east, 0 - xCenter, y - yCenter, 0); if (y < mcl.Height - 2) + { mcl.Add(east, mcl.Width - 1 - xCenter, y - yCenter, 0); + } } } @@ -716,7 +771,9 @@ namespace Server.Multis var y = mcl.Height - 1; for (var x = 0; x < mcl.Width; ++x) + { mcl.Add(0x63, x - xCenter, y - yCenter, 0); + } } public MultiComponentList GetEmptyFoundation() @@ -733,7 +790,9 @@ namespace Server.Multis ApplyFoundation(Type, mcl); for (var x = 1; x < mcl.Width; ++x) + { mcl.Add(0x751, x - xCenter, y - yCenter, 0); + } return mcl; } @@ -777,7 +836,9 @@ namespace Server.Multis var tile = tiles[i]; if (tile.Z == 7 && tile.Height == 20) + { return true; + } } } @@ -787,7 +848,9 @@ namespace Server.Multis public void BeginCustomize(Mobile m) { if (!m.CheckAlive()) + { return; + } if (SpellHelper.CheckCombat(m)) { @@ -797,18 +860,27 @@ namespace Server.Multis RelocateEntities(); - foreach (var item in GetItems()) item.Location = BanLocation; + foreach (var item in GetItems()) + { + item.Location = BanLocation; + } foreach (var mobile in GetMobiles()) + { if (mobile != m) + { mobile.Location = BanLocation; + } + } DesignContext.Add(m, this); m.Send(new BeginHouseCustomization(this)); var ns = m.NetState; if (ns != null) + { SendInfoTo(ns); + } DesignState.SendDetailedInfoTo(ns); } @@ -871,17 +943,23 @@ namespace Server.Multis case 1: { if (version < 5) + { m_DefaultPrice = reader.ReadInt(); + } goto case 0; } case 0: { if (version < 3) + { Type = FoundationType.Stone; + } if (version < 4) + { SignpostGraphic = 9; + } LastRevision = reader.ReadInt(); Fixtures = reader.ReadStrongItemList(); @@ -950,7 +1028,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to clear the design * - Restore empty foundation @@ -980,7 +1060,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to restore design to the last backup state * - Restore backup @@ -1010,7 +1092,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to backup design state * - Construct a copy of the current design state @@ -1030,7 +1114,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to revert design state to currently visible state * - Revert design state @@ -1103,12 +1189,16 @@ namespace Server.Multis else if (cost < 0) { if (Banker.Deposit(from, -cost)) + { from.SendLocalizedMessage( 1060397, (-cost).ToString() ); // ~1_AMOUNT~ gold has been deposited into your bank box. + } else + { return; + } } } } @@ -1165,10 +1255,14 @@ namespace Server.Multis from.RevealingAction(); foreach (var item in GetItems()) + { item.Location = BanLocation; + } foreach (var mobile in GetMobiles()) + { mobile.Location = BanLocation; + } // Restore relocated entities RestoreRelocatedEntities(); @@ -1195,7 +1289,9 @@ namespace Server.Multis public static int GetLevelZ(int level, HouseFoundation house) { if (level < 1 || level > house.MaxLevels) + { level = 1; + } return (level - 1) * 20 + 7; } @@ -1205,7 +1301,9 @@ namespace Server.Multis var level = (z - 7) / 20 + 1; if (level < 1 || level > house.MaxLevels) + { level = 1; + } return level; } @@ -1221,7 +1319,9 @@ namespace Server.Multis var delta = -1; for (var i = 0; delta < 0 && i < m_BlockIDs.Length; ++i) + { delta = m_BlockIDs[i] - id; + } return delta == 0; } @@ -1232,7 +1332,9 @@ namespace Server.Multis var delta = -4; for (var i = 0; delta < -3 && i < m_StairSeqs.Length; ++i) + { delta = m_StairSeqs[i] - id; + } if (delta >= -3 && delta <= 0) { @@ -1241,11 +1343,13 @@ namespace Server.Multis } for (var i = 0; i < m_StairIDs.Length; ++i) + { if (m_StairIDs[i] == id) { dir = i % 4; return true; } + } return false; } @@ -1256,7 +1360,9 @@ namespace Server.Multis var ay = y + mcl.Center.Y; if (ax < 0 || ay < 0 || ax >= mcl.Width || ay >= mcl.Height - 1 || z < 7 || (z - 7) % 5 != 0) + { return false; + } if (IsStairBlock(id)) { @@ -1272,7 +1378,9 @@ namespace Server.Multis z = tile.Z; if (!IsStairBlock(id)) + { break; + } } } } @@ -1280,10 +1388,14 @@ namespace Server.Multis var dir = 0; if (!IsStair(id, ref dir)) + { return false; + } if (AllowStairSectioning) + { return true; // skip deletion + } var height = (z - 7) % 20 / 5; @@ -1334,7 +1446,9 @@ namespace Server.Multis y = yStart + i * yInc; for (var j = 0; j <= i; ++j) + { mcl.RemoveXYZH(x, y, zStart + j * 5, 5); + } ax = x + mcl.Center.X; ay = y + mcl.Center.Y; @@ -1346,10 +1460,14 @@ namespace Server.Multis var hasBaseFloor = false; for (var j = 0; !hasBaseFloor && j < tiles.Length; ++j) + { hasBaseFloor = tiles[j].Z == 7 && tiles[j].ID != 1; + } if (!hasBaseFloor) + { mcl.Add(0x31F4, x, y, 7); + } } } @@ -1362,7 +1480,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to delete a component * - Read data detailing which component to delete @@ -1402,14 +1522,18 @@ namespace Server.Multis if (AllowStairSectioning) { if (DeleteStairs(mcl, itemID, x, y, z)) + { fixState = true; // The client removes the entire set of stairs locally, resend state + } mcl.Remove(itemID, x, y, z); } else { if (!DeleteStairs(mcl, itemID, x, y, z)) + { mcl.Remove(itemID, x, y, z); + } } // If needed, replace removed component with a dirt tile @@ -1420,9 +1544,14 @@ namespace Server.Multis var hasBaseFloor = false; for (var i = 0; !hasBaseFloor && i < tiles.Length; ++i) + { hasBaseFloor = tiles[i].Z == 7 && tiles[i].ID != 1; + } - if (!hasBaseFloor) mcl.Add(0x31F4, x, y, 7); + if (!hasBaseFloor) + { + mcl.Add(0x31F4, x, y, 7); + } } // Update revision @@ -1430,7 +1559,9 @@ namespace Server.Multis // Resend design state if (fixState) + { design.SendDetailedInfoTo(state); + } } public static void Designer_Stairs(NetState state, IEntity e, EncodedReader pvSrc) @@ -1439,7 +1570,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to add stairs * - Read data detailing stair type and location @@ -1484,7 +1617,9 @@ namespace Server.Multis var entry = stairs.List[i]; if (entry.ItemId != 1) + { mcl.Add(entry.ItemId, x + entry.OffsetX, y + entry.OffsetY, z + entry.OffsetZ); + } } // Update revision @@ -1510,7 +1645,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client chose to add a component * - Read data detailing component graphic and location @@ -1538,7 +1675,9 @@ namespace Server.Multis var z = GetLevelZ(context.Level, context.Foundation); if (y + mcl.Center.Y == mcl.Height - 1) + { z = 0; // Tiles placed on the far-south of the house are at 0 Z + } mcl.Add(itemID, x, y, z); @@ -1552,7 +1691,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client closed his house design window * - Remove design context @@ -1580,10 +1721,14 @@ namespace Server.Multis from.RevealingAction(); foreach (var item in context.Foundation.GetItems()) + { item.Location = context.Foundation.BanLocation; + } foreach (var mobile in context.Foundation.GetMobiles()) + { mobile.Location = context.Foundation.BanLocation; + } // Restore relocated entities context.Foundation.RestoreRelocatedEntities(); @@ -1595,7 +1740,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null) + { return; + } /* Client is moving to a new floor level * - Read data detailing the target level @@ -1611,7 +1758,9 @@ namespace Server.Multis // Validate target level if (newLevel < 1 || newLevel > context.MaxLevels) + { newLevel = 1; + } // Update design context with new level context.Level = newLevel; @@ -1644,7 +1793,9 @@ namespace Server.Multis var context = DesignContext.Find(from); if (context == null || !Core.SE && from.AccessLevel < AccessLevel.GameMaster) + { return; + } // Read data detailing component graphic and location var itemID = pvSrc.ReadInt32(); @@ -1665,7 +1816,10 @@ namespace Server.Multis var mcl = design.Components; if (z < -3 || z > 12 || z % 3 != 0) + { z = -3; + } + z += GetLevelZ(context.Level, context.Foundation); var list = mcl.List; @@ -1676,7 +1830,9 @@ namespace Server.Multis if (mte.OffsetX == x && mte.OffsetY == y && GetZLevel(mte.OffsetZ, context.Foundation) == context.Level && (TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Flags & TileFlag.Roof) != 0) + { mcl.Remove(mte.ItemId, x, y, mte.OffsetZ); + } } mcl.Add(itemID, x, y, z); @@ -1692,7 +1848,9 @@ namespace Server.Multis // No need to check for Core.SE if trying to remove something that shouldn't be able to be placed anyways if (context == null) + { return; + } // Read data detailing which component to delete var itemID = pvSrc.ReadInt32(); @@ -1735,7 +1893,9 @@ namespace Server.Multis Fixtures = new MultiTileEntry[toCopy.Fixtures.Length]; for (var i = 0; i < Fixtures.Length; ++i) + { Fixtures[i] = toCopy.Fixtures[i]; + } } public DesignState(HouseFoundation foundation, IGenericReader reader) @@ -1776,7 +1936,9 @@ namespace Server.Multis set { if (m_PacketCache == value) + { return; + } m_PacketCache?.Release(); @@ -1834,13 +1996,19 @@ namespace Server.Multis public void SendDetailedInfoTo(NetState state) { if (state != null) + { lock (this) { if (m_PacketCache == null) + { DesignStateDetailed.SendDetails(state, Foundation, this); + } else + { state.Send(m_PacketCache); + } } + } } public void FreezeFixtures() @@ -1869,7 +2037,9 @@ namespace Server.Multis var mte = list[i]; if (IsFixture(mte.ItemId)) + { ++length; + } } Fixtures = new MultiTileEntry[length]; @@ -1889,62 +2059,142 @@ namespace Server.Multis public static bool IsFixture(int itemID) { if (itemID >= 0x675 && itemID < 0x6F5) + { return true; + } + if (itemID >= 0x314 && itemID < 0x364) + { return true; + } + if (itemID >= 0x824 && itemID < 0x834) + { return true; + } + if (itemID >= 0x839 && itemID < 0x849) + { return true; + } + if (itemID >= 0x84C && itemID < 0x85C) + { return true; + } + if (itemID >= 0x866 && itemID < 0x876) + { return true; + } + if (itemID >= 0x0E8 && itemID < 0x0F8) + { return true; + } + if (itemID >= 0x1FED && itemID < 0x1FFD) + { return true; + } + if (itemID >= 0x181D && itemID < 0x1829) + { return true; + } + if (itemID >= 0x241F && itemID < 0x2421) + { return true; + } + if (itemID >= 0x2423 && itemID < 0x2425) + { return true; + } + if (itemID >= 0x2A05 && itemID < 0x2A1D) + { return true; + } + if (itemID >= 0x319C && itemID < 0x31B0) + { return true; + } + // ML doors if (itemID == 0x2D46 || itemID == 0x2D48 || itemID == 0x2FE2 || itemID == 0x2FE4) + { return true; + } + if (itemID >= 0x2D63 && itemID < 0x2D70) + { return true; + } + if (itemID >= 0x319C && itemID < 0x31AF) + { return true; + } + if (itemID >= 0x367B && itemID < 0x369B) + { return true; + } + // SA doors if (itemID >= 0x409B && itemID < 0x40A3) + { return true; + } + if (itemID >= 0x410C && itemID < 0x4114) + { return true; + } + if (itemID >= 0x41C2 && itemID < 0x41CA) + { return true; + } + if (itemID >= 0x41CF && itemID < 0x41D7) + { return true; + } + if (itemID >= 0x436E && itemID < 0x437E) + { return true; + } + if (itemID >= 0x46DD && itemID < 0x46E5) + { return true; + } + if (itemID >= 0x4D22 && itemID < 0x4D2A) + { return true; + } + if (itemID >= 0x50C8 && itemID < 0x50D8) + { return true; + } + if (itemID >= 0x5142 && itemID < 0x514A) + { return true; + } + // TOL doors if (itemID >= 0x9AD7 && itemID < 0x9AE7) + { return true; + } return itemID >= 0x9B3C && itemID < 0x9B4C; } @@ -2003,7 +2253,9 @@ namespace Server.Multis public override void OnResponse(NetState sender, RelayInfo info) { if (info.ButtonID == 1) + { m_Foundation.EndConfirmCommit(sender.Mobile); + } } } @@ -2026,7 +2278,9 @@ namespace Server.Multis public static DesignContext Find(Mobile from) { if (from == null) + { return null; + } Table.TryGetValue(from, out var d); @@ -2036,7 +2290,9 @@ namespace Server.Multis public static bool Check(Mobile m) { if (Find(m) == null) + { return true; + } m.SendLocalizedMessage(1062206); // You cannot do that while customizing a house. return false; @@ -2045,14 +2301,18 @@ namespace Server.Multis public static void Add(Mobile from, HouseFoundation foundation) { if (from == null) + { return; + } var c = new DesignContext(foundation); Table[from] = c; if (from is PlayerMobile pm) + { pm.DesignContext = c; + } foundation.Customizer = from; @@ -2062,7 +2322,9 @@ namespace Server.Multis var state = from.NetState; if (state == null) + { return; + } var fixtures = foundation.Fixtures; @@ -2074,13 +2336,19 @@ namespace Server.Multis } if (foundation.Signpost != null) + { state.Send(foundation.Signpost.RemovePacket); + } if (foundation.SignHanger != null) + { state.Send(foundation.SignHanger.RemovePacket); + } if (foundation.Sign != null) + { state.Send(foundation.Sign.RemovePacket); + } } public static void Remove(Mobile from) @@ -2088,19 +2356,25 @@ namespace Server.Multis var context = Find(from); if (context == null) + { return; + } Table.Remove(from); if (from is PlayerMobile pm) + { pm.DesignContext = null; + } context.Foundation.Customizer = null; var state = from.NetState; if (state == null) + { return; + } var fixtures = context.Foundation.Fixtures; @@ -2208,12 +2482,16 @@ namespace Server.Multis m_PlaneBuffers = new byte[9][]; for (var i = 0; i < m_PlaneBuffers.Length; ++i) + { m_PlaneBuffers[i] = ArrayPool.Shared.Rent(0x400); + } m_StairBuffers = new byte[6][]; for (var i = 0; i < m_StairBuffers.Length; ++i) + { m_StairBuffers[i] = ArrayPool.Shared.Rent(MaxItemsPerStairBuffer * 5); + } Clear(m_PlaneBuffers[0], width * height * 2); @@ -2330,11 +2608,17 @@ namespace Server.Multis int size; if (i == 0) + { size = width * height * 2; + } else if (i < 5) + { size = (width - 1) * (height - 2) * 2; + } else + { size = width * (height - 1) * 2; + } var inflatedBuffer = m_PlaneBuffers[i]; @@ -2373,7 +2657,9 @@ namespace Server.Multis var count = totalStairsUsed - i * MaxItemsPerStairBuffer; if (count > MaxItemsPerStairBuffer) + { count = MaxItemsPerStairBuffer; + } var size = count * 5; @@ -2405,7 +2691,9 @@ namespace Server.Multis } for (var i = 0; i < m_StairBuffers.Length; ++i) + { ArrayPool.Shared.Return(m_StairBuffers[i]); + } ArrayPool.Shared.Return(m_DeflatedBuffer); @@ -2456,7 +2744,9 @@ namespace Server.Multis public static void Clear(byte[] buffer, int size) { for (var i = 0; i < size; ++i) + { buffer[i] = 0; + } } public static void ProcessCompression() @@ -2468,6 +2758,7 @@ namespace Server.Multis var count = m_SendQueue.Count; while (count > 0 && m_SendQueue.TryDequeue(out var sqe)) + { try { Packet p; @@ -2493,7 +2784,9 @@ namespace Server.Multis lock (sqe.m_Root) { if (sqe.m_Revision == sqe.m_Root.Revision) + { sqe.m_Root.PacketCache = p; + } } } @@ -2517,6 +2810,7 @@ namespace Server.Multis { count = m_SendQueue.Count; } + } } } diff --git a/Projects/UOContent/Regions/GuardedRegion.cs b/Projects/UOContent/Regions/GuardedRegion.cs index 3e8872079..413f991bd 100644 --- a/Projects/UOContent/Regions/GuardedRegion.cs +++ b/Projects/UOContent/Regions/GuardedRegion.cs @@ -311,10 +311,9 @@ namespace Server.Regions if (IsGuardCandidate(m) && (!AllowReds && m.Kills >= 5 && m.Region.IsPartOf(this) || m_GuardCandidates.ContainsKey(m))) { - if (m_GuardCandidates.TryGetValue(m, out var timer)) + if (m_GuardCandidates.Remove(m, out var timer)) { timer.Stop(); - m_GuardCandidates.Remove(m); } MakeGuard(m); diff --git a/Projects/UOContent/Skills/Tracking.cs b/Projects/UOContent/Skills/Tracking.cs index 7e1141c85..b9fd57f03 100644 --- a/Projects/UOContent/Skills/Tracking.cs +++ b/Projects/UOContent/Skills/Tracking.cs @@ -36,16 +36,16 @@ namespace Server.SkillHandlers public static double GetStalkingBonus(Mobile tracker, Mobile target) { - if (!m_Table.TryGetValue(tracker, out var info) || info.m_Target != target || info.m_Map != target.Map) + if (!m_Table.Remove(tracker, out var info) || info.m_Target != target || info.m_Map != target.Map) + { return 0.0; + } var xDelta = info.m_Location.X - target.X; var yDelta = info.m_Location.Y - target.Y; var bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta); - m_Table.Remove(tracker); // Reset as of Pub 40, counting it as bug for Core.SE. - return Core.ML ? Math.Min(bonus, 10 + tracker.Skills.Tracking.Value / 10) : bonus; } @@ -108,7 +108,9 @@ namespace Server.SkillHandlers public override void OnResponse(NetState state, RelayInfo info) { if (info.ButtonID >= 1 && info.ButtonID <= 4) + { TrackWhoGump.DisplayTo(m_Success, m_From, info.ButtonID - 1); + } } } @@ -166,7 +168,9 @@ namespace Server.SkillHandlers AddButton(20 + i % 4 * 100, 130 + i / 4 * 155, 4005, 4007, i + 1); if (m.Name != null) + { AddHtml(20 + i % 4 * 100, 90 + i / 4 * 155, 90, 40, m.Name); + } } } @@ -181,7 +185,9 @@ namespace Server.SkillHandlers var map = from.Map; if (map == null) + { return; + } var check = m_Delegates[type]; @@ -207,11 +213,17 @@ namespace Server.SkillHandlers else { if (type == 0) + { from.SendLocalizedMessage(502991); // You see no evidence of animals in the area. + } else if (type == 1) + { from.SendLocalizedMessage(502993); // You see no evidence of creatures in the area. + } else + { from.SendLocalizedMessage(502995); // You see no evidence of people in the area. + } } } @@ -219,13 +231,17 @@ namespace Server.SkillHandlers private static bool CheckDifficulty(Mobile from, Mobile m) { if (!Core.AOS || !m.Player) + { return true; + } var tracking = from.Skills.Tracking.Fixed; var detectHidden = from.Skills.DetectHidden.Fixed; if (Core.ML && m.Race == Race.Elf) + { tracking /= 2; // The 'Guide' says that it requires twice as Much tracking SKILL to track an elf. Not the total difficulty to track. + } var hiding = m.Skills.Hiding.Fixed; var stealth = m.Skills.Stealth.Fixed; @@ -233,19 +249,29 @@ namespace Server.SkillHandlers // Necromancy forms affect tracking difficulty if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell))) + { divisor -= 200; + } else if (TransformationSpellHelper.UnderTransformation(m, typeof(VampiricEmbraceSpell)) && divisor < 500) + { divisor = 500; + } else if (TransformationSpellHelper.UnderTransformation(m, typeof(WraithFormSpell)) && divisor <= 2000) + { divisor += 200; + } int chance; if (divisor > 0) { if (Core.SE) + { chance = 50 * (tracking * 2 + detectHidden) / divisor; + } else + { chance = 50 * (tracking + detectHidden + 10 * Utility.RandomMinMax(1, 20)) / divisor; + } } else { @@ -274,7 +300,9 @@ namespace Server.SkillHandlers m_From.QuestArrow = new TrackArrow(m_From, m, m_Range * 2); if (Core.SE) + { Tracking.AddInfo(m_From, m); + } } } @@ -287,11 +315,19 @@ namespace Server.SkillHandlers public int Compare(Mobile x, Mobile y) { if (x == null && y == null) + { return 0; + } + if (x == null) + { return -1; + } + if (y == null) + { return 1; + } return m_From.GetDistanceToSqrt(x).CompareTo(m_From.GetDistanceToSqrt(y)); } diff --git a/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs b/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs index e7c945525..1a212a9b4 100644 --- a/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs +++ b/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs @@ -34,33 +34,37 @@ namespace Server.Misc m_MoveHistory = new Dictionary(); if (Enabled) + { EventSink.Login += OnLogin; + } } public static void OnLogin(Mobile from) { if (from == null || from.AccessLevel < AccessLevel.Counselor) + { return; + } if (HasDisconnected(from)) { if (!m_MoveHistory.ContainsKey(from)) + { m_MoveHistory[from] = new LocationInfo(from.Location, from.Map); + } var dest = GetRandomDestination(); from.Location = dest.Location; from.Map = dest.Map; } - else if (m_MoveHistory.TryGetValue(from, out var orig)) + else if (m_MoveHistory.Remove(from, out var orig)) { from.SendMessage( "Your character was moved from {0} ({1}) due to a detected client crash.", orig.Location, orig.Map ); - - m_MoveHistory.Remove(from); } } diff --git a/Projects/UOContent/Spells/Base/SpecialMove.cs b/Projects/UOContent/Spells/Base/SpecialMove.cs index 24a09c8cd..8410e017c 100644 --- a/Projects/UOContent/Spells/Base/SpecialMove.cs +++ b/Projects/UOContent/Spells/Base/SpecialMove.cs @@ -82,7 +82,9 @@ namespace Server.Spells var scalar = 1.0; if (!MindRotSpell.GetMindRotScalar(m, ref scalar)) + { scalar = 1.0; + } // Lower Mana Cost = 40% var lmc = Math.Min(AosAttributes.GetValue(m, AosAttribute.LowerManaCost), 40); @@ -92,7 +94,9 @@ namespace Server.Spells var total = (int)(mana * scalar); if (m.Skills[MoveSkill].Value < 50.0 && GetContext(m) != null) + { total *= 2; + } return total; } @@ -113,7 +117,9 @@ namespace Server.Spells if (consume) { if (!DelayedContext) + { SetContext(from); + } from.Mana -= mana; } @@ -124,6 +130,7 @@ namespace Server.Spells public virtual void SetContext(Mobile from) { if (GetContext(from) == null) + { if (DelayedContext || from.Skills[MoveSkill].Value < 50.0) { Timer timer = new SpecialMoveTimer(from); @@ -131,12 +138,15 @@ namespace Server.Spells AddContext(from, new SpecialMoveContext(timer, GetType())); } + } } public virtual bool Validate(Mobile from) { if (!from.Player) + { return true; + } if (HonorableExecution.IsUnderPenalty(from)) { @@ -153,24 +163,42 @@ namespace Server.Spells string option = null; if (this is Backstab) + { option = "Backstab"; + } else if (this is DeathStrike) + { option = "Death Strike"; + } else if (this is FocusAttack) + { option = "Focus Attack"; + } else if (this is KiAttack) + { option = "Ki Attack"; + } else if (this is SurpriseAttack) + { option = "Surprise Attack"; + } else if (this is HonorableExecution) + { option = "Honorable Execution"; + } else if (this is LightningStrike) + { option = "Lightning Strike"; + } else if (this is MomentumStrike) + { option = "Momentum Strike"; + } if (option != null && !DuelContext.AllowSpecialMove(from, option, this)) + { return false; + } return CheckSkills(from) && CheckMana(from, false); } @@ -187,14 +215,18 @@ namespace Server.Spells var moveID = kvp.Key; if (moveID != -1) + { m.Send(new ToggleSpecialAbility(moveID + 1, false)); + } } } public static SpecialMove GetCurrentMove(Mobile m) { if (m == null) + { return null; + } if (!Core.SE) { @@ -230,7 +262,9 @@ namespace Server.Spells ClearCurrentMove(m); if (sameMove) + { return true; + } if (move != null) { @@ -243,7 +277,9 @@ namespace Server.Spells var moveID = SpellRegistry.GetRegistryNumber(move); if (moveID > 0) + { m.Send(new ToggleSpecialAbility(moveID + 1, true)); + } TextDefinition.SendMessageTo(m, move.AbilityMessage); } @@ -253,17 +289,17 @@ namespace Server.Spells public static void ClearCurrentMove(Mobile m) { - if (Table.TryGetValue(m, out var move)) + if (Table.Remove(m, out var move)) { move.OnClearMove(m); var moveID = SpellRegistry.GetRegistryNumber(move); if (moveID > 0) + { m.Send(new ToggleSpecialAbility(moveID + 1, false)); + } } - - Table.Remove(m); } private static void AddContext(Mobile m, SpecialMoveContext context) diff --git a/Projects/UOContent/Spells/Base/Spell.cs b/Projects/UOContent/Spells/Base/Spell.cs index f55ea9b47..f8132ced2 100644 --- a/Projects/UOContent/Spells/Base/Spell.cs +++ b/Projects/UOContent/Spells/Base/Spell.cs @@ -86,7 +86,9 @@ namespace Server.Spells // Confirm: Monsters and pets cannot be disturbed. if (Caster.Player && IsCasting && ProtectionSpell.Registry.TryGetValue(Caster, out var d) && d <= Utility.RandomDouble() * 100.0) + { Disturb(DisturbType.Hurt, false, true); + } } public virtual void OnCasterKilled() @@ -113,7 +115,9 @@ namespace Server.Spells public virtual bool OnCasterEquipping(Item item) { if (IsCasting) + { Disturb(DisturbType.EquipRequest); + } return true; } @@ -121,7 +125,9 @@ namespace Server.Spells public virtual bool OnCasterUsingObject(IEntity entity) { if (State == SpellState.Sequencing) + { Disturb(DisturbType.UseRequest); + } return true; } @@ -133,16 +139,22 @@ namespace Server.Spells State = SpellState.None; if (Caster.Spell == this) + { Caster.Spell = null; + } } public void StartDelayedDamageContext(Mobile m, Timer t) { if (DelayedDamageStacking) + { return; // Sanity + } if (!m_ContextTable.TryGetValue(GetType(), out var contexts)) + { m_ContextTable[GetType()] = contexts = new DelayedDamageContextWrapper(); + } contexts.Add(m, t); } @@ -150,7 +162,9 @@ namespace Server.Spells public void RemoveDelayedDamageContext(Mobile m) { if (m_ContextTable.TryGetValue(GetType(), out var contexts)) + { contexts.Remove(m); + } } public void HarmfulSpell(Mobile m) @@ -161,6 +175,7 @@ namespace Server.Spells public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, Mobile singleTarget) { if (singleTarget != null) + { return GetNewAosDamage( bonus, dice, @@ -168,6 +183,7 @@ namespace Server.Spells Caster.Player && singleTarget.Player, GetDamageScalar(singleTarget) ); + } return GetNewAosDamage(bonus, dice, sides, false); } @@ -189,14 +205,18 @@ namespace Server.Spells var sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); // PvP spell damage increase cap of 15% from an item�s magic property if (playerVsPlayer && sdiBonus > 15) + { sdiBonus = 15; + } damageBonus += sdiBonus; var context = TransformationSpellHelper.GetContext(Caster); if (context?.Spell is ReaperFormSpell spell) + { damageBonus += spell.SpellDamageBonus; + } damage = AOS.Scale(damage, 100 + damageBonus); @@ -242,15 +262,21 @@ namespace Server.Spells // m_Caster.CheckSkill( DamageSkill, 0.0, 120.0 ); if (casterEI > targetRS) + { scalar = 1.0 + (casterEI - targetRS) / 500.0; + } else + { scalar = 1.0 + (casterEI - targetRS) / 200.0; + } // magery damage bonus, -25% at 0 skill, +0% at 100 skill, +5% at 120 skill scalar += (Caster.Skills[CastSkill].Value - 100.0) / 400.0; if (!target.Player && !target.Body.IsHuman /*&& !Core.AOS*/) + { scalar *= 2.0; // Double magery damage to monsters/animals if not AOS + } } (target as BaseCreature)?.AlterDamageScalarFrom(Caster, ref scalar); @@ -258,12 +284,16 @@ namespace Server.Spells (Caster as BaseCreature)?.AlterDamageScalarTo(target, ref scalar); if (Core.SE) + { scalar *= GetSlayerDamageScalar(target); + } target.Region.SpellDamageScalar(Caster, target, ref scalar); if (Evasion.CheckSpellEvasion(target)) // Only single target spells an be evaded + { scalar = 0; + } return scalar; } @@ -288,10 +318,14 @@ namespace Server.Spells if ((atkBook.Slayer == SlayerName.Silver || atkBook.Slayer2 == SlayerName.Silver) && context != null && context.Type != typeof(HorrificBeastSpell)) + { scalar += .25; // Every necromancer transformation other than horrific beast take an additional 25% damage + } if (scalar != 1.0) + { return scalar; + } } var defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer; @@ -303,7 +337,9 @@ namespace Server.Spells if (defSlayer?.Group.OppositionSuperSlays(Caster) == true || defSlayer2?.Group.OppositionSuperSlays(Caster) == true) + { scalar = 2.0; + } } return scalar; @@ -316,9 +352,13 @@ namespace Server.Spells if (Caster.Player) { if (Core.AOS) + { Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist); + } else + { Caster.FixedEffect(0x3735, 6, 30); + } Caster.PlaySound(0x5C); } @@ -330,12 +370,16 @@ namespace Server.Spells public void Disturb(DisturbType type, bool firstCircle = true, bool resistable = false) { if (!CheckDisturb(type, firstCircle, resistable)) + { return; + } if (State == SpellState.Casting) { if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) + { return; + } State = SpellState.None; Caster.Spell = null; @@ -347,14 +391,18 @@ namespace Server.Spells m_AnimTimer?.Stop(); if (Core.AOS && Caster.Player && type == DisturbType.Hurt) + { DoHurtFizzle(); + } Caster.NextSpellTime = Core.TickCount + (int)GetDisturbRecovery().TotalMilliseconds; } else if (State == SpellState.Sequencing) { if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) + { return; + } State = SpellState.None; Caster.Spell = null; @@ -364,7 +412,9 @@ namespace Server.Spells Target.Cancel(Caster); if (Core.AOS && Caster.Player && type == DisturbType.Hurt) + { DoHurtFizzle(); + } } } @@ -377,7 +427,9 @@ namespace Server.Spells public virtual void OnDisturb(DisturbType type, bool message) { if (message) + { Caster.SendLocalizedMessage(500641); // Your concentration is disturbed, thus ruining thy spell. + } } public virtual bool CheckCast() => true; @@ -385,10 +437,14 @@ namespace Server.Spells public virtual void SayMantra() { if (Scroll is BaseWand) + { return; + } if (!string.IsNullOrEmpty(Info.Mantra) && Caster.Player) + { Caster.PublicOverheadMessage(MessageType.Spell, Caster.SpeechHue, true, Info.Mantra, false); + } } public bool Cast() @@ -396,9 +452,14 @@ namespace Server.Spells StartCastTime = Core.TickCount; if (Core.AOS && Caster.Spell is Spell spell && spell.State == SpellState.Sequencing) + { spell.Disturb(DisturbType.NewCast); + } - if (!Caster.CheckAlive()) return false; + if (!Caster.CheckAlive()) + { + return false; + } if (Scroll is BaseWand && Caster.Spell?.IsCasting == true) { @@ -438,7 +499,9 @@ namespace Server.Spells Caster.Spell = this; if (!(Scroll is BaseWand) && RevealOnCast) + { Caster.RevealingAction(); + } SayMantra(); @@ -455,17 +518,25 @@ namespace Server.Spells } if (Info.LeftHandEffect > 0) + { Caster.FixedParticles(0, 10, 5, Info.LeftHandEffect, EffectLayer.LeftHand); + } if (Info.RightHandEffect > 0) + { Caster.FixedParticles(0, 10, 5, Info.RightHandEffect, EffectLayer.RightHand); + } } if (ClearHandsOnCast) + { Caster.ClearHands(); + } if (Core.ML) + { WeaponAbility.ClearCurrentAbility(Caster); + } m_CastTimer = new CastTimer(this, castDelay); // m_CastTimer.Start(); @@ -473,9 +544,13 @@ namespace Server.Spells OnBeginCast(); if (castDelay > TimeSpan.Zero) + { m_CastTimer.Start(); + } else + { m_CastTimer.Tick(); + } return true; } @@ -504,12 +579,16 @@ namespace Server.Spells public virtual bool CheckFizzle() { if (Scroll is BaseWand) + { return true; + } GetCastSkills(out var minSkill, out var maxSkill); if (DamageSkill != CastSkill) + { Caster.CheckSkill(DamageSkill, 0.0, Caster.Skills[DamageSkill].Cap); + } return Caster.CheckSkill(CastSkill, minSkill, maxSkill); } @@ -521,12 +600,16 @@ namespace Server.Spells var scalar = 1.0; if (!MindRotSpell.GetMindRotScalar(Caster, ref scalar)) + { scalar = 1.0; + } // Lower Mana Cost = 40% var lmc = AosAttributes.GetValue(Caster, AosAttribute.LowerManaCost); if (lmc > 40) + { lmc = 40; + } scalar -= (double)lmc / 100; @@ -536,7 +619,9 @@ namespace Server.Spells public virtual TimeSpan GetDisturbRecovery() { if (Core.AOS) + { return TimeSpan.Zero; + } var delay = Math.Max( 1.0 - Math.Sqrt((Core.TickCount - StartCastTime) / 1000.0 / GetCastDelay().TotalSeconds), @@ -549,7 +634,9 @@ namespace Server.Spells public virtual TimeSpan GetCastRecovery() { if (!Core.AOS) + { return NextSpellDelay; + } var fcr = AosAttributes.GetValue(Caster, AosAttribute.CastRecovery) - ThunderstormSpell.GetCastRecoveryMalus(Caster); @@ -559,7 +646,9 @@ namespace Server.Spells var delay = CastRecoveryBase + fcrDelay; if (delay < CastRecoveryMinimum) + { delay = CastRecoveryMinimum; + } return TimeSpan.FromSeconds((double)delay / CastRecoveryPerSecond); } @@ -572,7 +661,9 @@ namespace Server.Spells public virtual TimeSpan GetCastDelay() { if (Scroll is BaseWand) + { return Core.ML ? CastDelayBase : TimeSpan.Zero; // TODO: Should FC apply to wands? + } // Faster casting cap of 2 (if not using the protection spell) // Faster casting cap of 0 (if using the protection spell) @@ -582,15 +673,21 @@ namespace Server.Spells if (CastSkill == SkillName.Magery || CastSkill == SkillName.Necromancy || CastSkill == SkillName.Chivalry && Caster.Skills.Magery.Value >= 70.0) + { fcMax = 2; + } var fc = Math.Min(AosAttributes.GetValue(Caster, AosAttribute.CastSpeed), fcMax); if (ProtectionSpell.Registry.ContainsKey(Caster)) + { fc -= 2; + } if (EssenceOfWindSpell.IsDebuffed(Caster)) + { fc -= EssenceOfWindSpell.GetFCMalus(Caster); + } var fcDelay = TimeSpan.FromSeconds(-(CastDelayFastScalar * fc * CastDelaySecondsPerTick)); @@ -652,27 +749,35 @@ namespace Server.Spells Scroll.Movable = false; if (ClearHandsOnCast) + { Caster.ClearHands(); + } Scroll.Movable = m; } else { if (ClearHandsOnCast) + { Caster.ClearHands(); + } } var karma = ComputeKarmaAward(); if (karma != 0) + { Titles.AwardKarma(Caster, karma, true); + } if (TransformationSpellHelper.UnderTransformation(Caster, typeof(VampiricEmbraceSpell))) { var garlic = false; for (var i = 0; !garlic && i < Info.Reagents.Length; ++i) + { garlic = Info.Reagents[i] == Reagent.Garlic; + } if (garlic) { @@ -770,13 +875,19 @@ namespace Server.Spells if (!m_Spell.Caster.Mounted && m_Spell.Info.Action >= 0) { if (m_Spell.Caster.Body.IsHuman) + { m_Spell.Caster.Animate(m_Spell.Info.Action, 7, 1, true, false, 0); + } else if (m_Spell.Caster.Player && m_Spell.Caster.Body.IsMonster) + { m_Spell.Caster.Animate(12, 7, 1, true, false, 0); + } } if (!Running) + { m_Spell.m_AnimTimer = null; + } } } @@ -793,7 +904,10 @@ namespace Server.Spells protected override void OnTick() { - if (m_Spell?.Caster == null) return; + if (m_Spell?.Caster == null) + { + return; + } if (m_Spell.State == SpellState.Casting && m_Spell.Caster.Spell == m_Spell) { @@ -809,7 +923,9 @@ namespace Server.Spells m_Spell.OnCast(); if (m_Spell.Caster.Player && m_Spell.Caster.Target != originalTarget) + { m_Spell.Caster.Target?.BeginTimeout(m_Spell.Caster, TimeSpan.FromSeconds(30.0)); + } m_Spell.m_CastTimer = null; } diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 68d07f96e..49236f3fb 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -23,7 +23,9 @@ namespace Server public static void Nullify(Mobile from) { if (!from.CanBeginAction()) + { new InternalTimer(from).Start(); + } } private class InternalTimer : Timer @@ -155,7 +157,9 @@ namespace Server.Spells public static bool CheckMulti(Point3D p, Map map, bool houses = true, int housingrange = 0) { if (map == null || map == Map.Internal) + { return false; + } var sector = map.GetSector(p.X, p.Y); @@ -166,7 +170,9 @@ namespace Server.Spells if (multi is BaseHouse bh) { if (houses && bh.IsInside(p, 16) || housingrange > 0 && bh.InRange(p, housingrange)) + { return true; + } } else if (multi.Contains(p)) { @@ -180,12 +186,16 @@ namespace Server.Spells public static void Turn(Mobile from, object to) { if (!(to is IPoint3D target)) + { return; + } if (target is Item item) { if (item.RootParent != from) + { from.Direction = from.GetDirectionTo(item.GetWorldLocation()); + } } else if (from != target) { @@ -196,24 +206,32 @@ namespace Server.Spells public static bool CheckCombat(Mobile m) { if (!RestrictTravelCombat) + { return false; + } for (var i = 0; i < m.Aggressed.Count; ++i) { var info = m.Aggressed[i]; if (info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) + { return true; + } } if (Core.Expansion == Expansion.AOS) + { for (var i = 0; i < m.Aggressors.Count; ++i) { var info = m.Aggressors[i]; if (info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) + { return true; + } } + } return false; } @@ -221,7 +239,9 @@ namespace Server.Spells public static bool AdjustField(ref Point3D p, Map map, int height, bool mobsBlock) { if (map == null) + { return false; + } for (var offset = 0; offset < 10; ++offset) { @@ -250,7 +270,9 @@ namespace Server.Spells var z = t.Z; if ((t.Flags & TileFlag.Surface) == 0) + { z -= TileData.ItemTable[t.ItemID & TileData.MaxItemValue].CalcHeight; + } p = new Point3D(t.X, t.Y, z); } @@ -331,9 +353,13 @@ namespace Server.Spells double percent; if (curse) + { percent = 8 + caster.Skills.EvalInt.Fixed / 100 - target.Skills.MagicResist.Fixed / 100; + } else + { percent = 1 + caster.Skills.EvalInt.Fixed / 100; + } percent *= 0.01; @@ -349,7 +375,9 @@ namespace Server.Spells caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0); if (curse) + { target.CheckSkill(SkillName.MagicResist, 0.0, 120.0); + } } var percent = GetOffsetScalar(caster, target, curse); @@ -377,14 +405,18 @@ namespace Server.Spells m = c.ControlMaster; if (m != null) + { g = m.Guild as Guild; + } if (g == null) { m = c.SummonMaster; if (m != null) + { g = m.Guild as Guild; + } } } @@ -394,10 +426,14 @@ namespace Server.Spells public static bool ValidIndirectTarget(Mobile from, Mobile to) { if (from == to) + { return true; + } if (to.Hidden && to.AccessLevel > from.AccessLevel) + { return false; + } var bcFrom = from as BaseCreature; var bcTarg = to as BaseCreature; @@ -406,48 +442,70 @@ namespace Server.Spells PlayerMobile pmTarg; if (bcFrom?.Summoned == true) + { pmFrom = bcFrom.SummonMaster as PlayerMobile; + } else + { pmFrom = from as PlayerMobile; + } if (bcTarg?.Summoned == true) + { pmTarg = bcTarg.SummonMaster as PlayerMobile; + } else + { pmTarg = to as PlayerMobile; + } if (pmFrom?.DuelContext != null && pmFrom.DuelContext == pmTarg?.DuelContext && pmFrom.DuelContext.Started && pmFrom.DuelPlayer != null && pmTarg?.DuelPlayer != null) + { return pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant; + } var fromGuild = GetGuildFor(from); var toGuild = GetGuildFor(to); if (fromGuild != null && toGuild != null && (fromGuild == toGuild || fromGuild.IsAlly(toGuild))) + { return false; + } var p = Party.Get(from); if (p?.Contains(to) == true) + { return false; + } if (bcTarg != null && (bcTarg.Controlled || bcTarg.Summoned)) { if (bcTarg.ControlMaster == from || bcTarg.SummonMaster == from) + { return false; + } if (p != null && (p.Contains(bcTarg.ControlMaster) || p.Contains(bcTarg.SummonMaster))) + { return false; + } } if (bcFrom != null && (bcFrom.Controlled || bcFrom.Summoned)) { if (bcFrom.ControlMaster == to || bcFrom.SummonMaster == to) + { return false; + } p = Party.Get(to); if (p != null && (p.Contains(bcFrom.ControlMaster) || p.Contains(bcFrom.SummonMaster))) + { return false; + } } return bcTarg?.Controlled == false && bcTarg.InitialInnocent || @@ -462,12 +520,16 @@ namespace Server.Spells var map = caster.Map; if (map == null) + { return; + } var scale = 1.0 + (caster.Skills.Magery.Value - 100.0) / 200.0; if (scaleDuration) + { duration = TimeSpan.FromSeconds(duration.TotalSeconds * scale); + } if (scaleStats) { @@ -491,12 +553,12 @@ namespace Server.Spells /* int offset = Utility.Random( 8 ) * 2; - + for ( int i = 0; i < m_Offsets.Length; i += 2 ) { int x = caster.X + m_Offsets[(offset + i) % m_Offsets.Length]; int y = caster.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - + if (map.CanSpawnMobile( x, y, caster.Z )) { BaseCreature.Summon( creature, caster, new Point3D( x, y, caster.Z ), sound, duration ); @@ -505,7 +567,7 @@ namespace Server.Spells else { int z = map.GetAverageZ( x, y ); - + if (map.CanSpawnMobile( x, y, z )) { BaseCreature.Summon( creature, caster, new Point3D( x, y, z ), sound, duration ); @@ -522,7 +584,9 @@ namespace Server.Spells public static bool FindValidSpawnLocation(Map map, ref Point3D p, bool surroundingsOnly) { if (map == null) // sanity + { return false; + } if (!surroundingsOnly) { @@ -569,11 +633,17 @@ namespace Server.Spells public static void SendInvalidMessage(Mobile caster, TravelCheckType type) { if (type == TravelCheckType.RecallTo || type == TravelCheckType.GateTo) + { caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } else if (type == TravelCheckType.TeleportTo) + { caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination. + } else + { caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work... + } } public static bool CheckTravel(Mobile caster, TravelCheckType type) => @@ -586,7 +656,9 @@ namespace Server.Spells if (IsInvalid(map, loc)) // null, internal, out of bounds { if (caster != null) + { SendInvalidMessage(caster, type); + } return false; } @@ -594,7 +666,9 @@ namespace Server.Spells // Always allow monsters to teleport if (caster is BaseCreature bc && !bc.Controlled && !bc.Summoned && (type == TravelCheckType.TeleportTo || type == TravelCheckType.TeleportFrom)) + { return true; + } m_TravelCaster = caster; m_TravelType = type; @@ -608,14 +682,20 @@ namespace Server.Spells var current = Region.Find(caster.Location, map) as BaseRegion; if (destination?.CheckTravel(caster, loc, type) == false || current?.CheckTravel(caster, loc, type) == false) + { isValid = false; + } } for (var i = 0; isValid && i < m_Validators.Length; ++i) + { isValid = m_Rules[v, i] || !m_Validators[i](map, loc); + } if (!isValid && caster != null) + { SendInvalidMessage(caster, type); + } return isValid; } @@ -669,7 +749,9 @@ namespace Server.Spells public static bool IsCrystalCave(Map map, Point3D loc) { if (map != Map.Malas || loc.Z >= -80) + { return false; + } int x = loc.X, y = loc.Y; @@ -691,7 +773,9 @@ namespace Server.Spells public static bool IsDoomFerry(Map map, Point3D loc) { if (map != Map.Malas) + { return false; + } int x = loc.X, y = loc.Y; @@ -702,7 +786,9 @@ namespace Server.Spells { // The tokuno dungeons are really inside malas if (map != Map.Malas) + { return false; + } int x = loc.X, y = loc.Y, z = loc.Z; @@ -715,7 +801,9 @@ namespace Server.Spells public static bool IsDoomGauntlet(Map map, Point3D loc) { if (map != Map.Malas) + { return false; + } int x = loc.X - 256, y = loc.Y - 304; @@ -725,7 +813,9 @@ namespace Server.Spells public static bool IsLampRoom(Map map, Point3D loc) { if (map != Map.Malas) + { return false; + } int x = loc.X, y = loc.Y; @@ -735,7 +825,9 @@ namespace Server.Spells public static bool IsGuardianRoom(Map map, Point3D loc) { if (map != Map.Malas) + { return false; + } int x = loc.X, y = loc.Y; @@ -754,7 +846,9 @@ namespace Server.Spells public static bool IsInvalid(Map map, Point3D loc) { if (map == null || map == Map.Internal) + { return true; + } int x = loc.X, y = loc.Y; @@ -765,7 +859,9 @@ namespace Server.Spells public static bool IsTown(IPoint3D ip, Mobile caster) { if (ip is Item item) + { ip = item.GetWorldLocation(); + } return IsTown(new Point3D(ip), caster); } @@ -775,11 +871,17 @@ namespace Server.Spells var map = caster.Map; if (map == null) + { return false; + } if (Region.Find(loc, map).GetRegion() != null) + { if (caster is PlayerMobile pm && (pm.DuelContext?.Started != true || pm.DuelPlayer?.Eliminated != false)) + { return true; + } + } var reg = Region.Find(loc, map).GetRegion(); @@ -789,7 +891,9 @@ namespace Server.Spells public static bool CheckTown(IPoint3D ip, Mobile caster) { if (ip is Item item) + { ip = item.GetWorldLocation(); + } return CheckTown(new Point3D(ip), caster); } @@ -953,7 +1057,9 @@ namespace Server.Spells var damageGiven = AOS.Damage(target, from, dmg, phys, fire, cold, pois, nrgy, chaos); if (from != null) // sanity check + { DoLeech(damageGiven, from, target); + } WeightOverloading.DFA = DFAlgorithm.Standard; } @@ -974,7 +1080,9 @@ namespace Server.Spells var context = TransformationSpellHelper.GetContext(from); if (context == null) /* cleanup */ + { return; + } if (context.Type == typeof(WraithFormSpell)) { @@ -1019,7 +1127,9 @@ namespace Server.Spells m_Spell = s; if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) + { m_Spell.StartDelayedDamageContext(target, this); + } Priority = TimerPriority.TwentyFiveMS; } @@ -1067,7 +1177,9 @@ namespace Server.Spells m_DFA = dfa; m_Spell = s; if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) + { m_Spell.StartDelayedDamageContext(target, this); + } Priority = TimerPriority.TwentyFiveMS; } @@ -1078,17 +1190,23 @@ namespace Server.Spells var bcTarg = m_Target as BaseCreature; if (bcFrom != null && m_Target != null) + { bcFrom.AlterSpellDamageTo(m_Target, ref m_Damage); + } if (bcTarg != null && m_From != null) + { bcTarg.AlterSpellDamageFrom(m_From, ref m_Damage); + } WeightOverloading.DFA = m_DFA; var damageGiven = AOS.Damage(m_Target, m_From, m_Damage, m_Phys, m_Fire, m_Cold, m_Pois, m_Nrgy, m_Chaos); if (m_From != null) // sanity check + { DoLeech(damageGiven, m_From, m_Target); + } WeightOverloading.DFA = DFAlgorithm.Standard; @@ -1133,7 +1251,9 @@ namespace Server.Spells public static bool OnCast(Mobile caster, Spell spell) { if (!(spell is ITransformationSpell transformSpell)) + { return false; + } if (Sigil.ExistsOn(caster)) { @@ -1180,33 +1300,47 @@ namespace Server.Spells var mods = new List(); if (transformSpell.PhysResistOffset != 0) + { mods.Add(new ResistanceMod(ResistanceType.Physical, transformSpell.PhysResistOffset)); + } if (transformSpell.FireResistOffset != 0) + { mods.Add(new ResistanceMod(ResistanceType.Fire, transformSpell.FireResistOffset)); + } if (transformSpell.ColdResistOffset != 0) + { mods.Add(new ResistanceMod(ResistanceType.Cold, transformSpell.ColdResistOffset)); + } if (transformSpell.PoisResistOffset != 0) + { mods.Add(new ResistanceMod(ResistanceType.Poison, transformSpell.PoisResistOffset)); + } if (transformSpell.NrgyResistOffset != 0) + { mods.Add(new ResistanceMod(ResistanceType.Energy, transformSpell.NrgyResistOffset)); + } if (!((Body)transformSpell.Body).IsHuman) { var mt = caster.Mount; if (mt != null) + { mt.Rider = null; + } } caster.BodyMod = transformSpell.Body; caster.HueMod = transformSpell.Hue; for (var i = 0; i < mods.Count; ++i) + { caster.AddResistanceMod(mods[i]); + } transformSpell.DoEffect(caster); @@ -1231,20 +1365,24 @@ namespace Server.Spells var context = GetContext(m); if (context != null) + { RemoveContext(m, context, resetGraphics); + } } public static void RemoveContext(Mobile m, TransformContext context, bool resetGraphics) { - if (!m_Table.ContainsKey(m)) + if (!m_Table.Remove(m)) + { return; - - m_Table.Remove(m); + } var mods = context.Mods; for (var i = 0; i < mods.Count; ++i) + { m.RemoveResistanceMod(mods[i]); + } if (resetGraphics) { diff --git a/Projects/UOContent/Spells/Base/SpellRegistry.cs b/Projects/UOContent/Spells/Base/SpellRegistry.cs index 64b0a6834..2352db892 100644 --- a/Projects/UOContent/Spells/Base/SpellRegistry.cs +++ b/Projects/UOContent/Spells/Base/SpellRegistry.cs @@ -75,8 +75,7 @@ namespace Server.Spells m_Types[spellID] = type; - if (!m_IDsFromTypes.ContainsKey(type)) - m_IDsFromTypes.Add(type, spellID); + m_IDsFromTypes.TryAdd(type, spellID); if (type.IsSubclassOf(typeof(SpecialMove))) { diff --git a/Projects/UOContent/Spells/Bushido/Confidence.cs b/Projects/UOContent/Spells/Bushido/Confidence.cs index 27e000a9b..cf248f006 100644 --- a/Projects/UOContent/Spells/Bushido/Confidence.cs +++ b/Projects/UOContent/Spells/Bushido/Confidence.cs @@ -62,10 +62,9 @@ namespace Server.Spells.Bushido public static void EndConfidence(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer.Stop(); - m_Table.Remove(m); } OnEffectEnd(m, typeof(Confidence)); @@ -85,10 +84,9 @@ namespace Server.Spells.Bushido public static void StopRegenerating(Mobile m) { - if (m_RegenTable.TryGetValue(m, out var timer)) + if (m_RegenTable.Remove(m, out var timer)) { timer.Stop(); - m_RegenTable.Remove(m); } } diff --git a/Projects/UOContent/Spells/Bushido/CounterAttack.cs b/Projects/UOContent/Spells/Bushido/CounterAttack.cs index 9fb48b224..9652c64de 100644 --- a/Projects/UOContent/Spells/Bushido/CounterAttack.cs +++ b/Projects/UOContent/Spells/Bushido/CounterAttack.cs @@ -77,10 +77,9 @@ namespace Server.Spells.Bushido public static void StopCountering(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer.Stop(); - m_Table.Remove(m); } OnEffectEnd(m, typeof(CounterAttack)); diff --git a/Projects/UOContent/Spells/Bushido/Evasion.cs b/Projects/UOContent/Spells/Bushido/Evasion.cs index 7dff6688c..9de5596ef 100644 --- a/Projects/UOContent/Spells/Bushido/Evasion.cs +++ b/Projects/UOContent/Spells/Bushido/Evasion.cs @@ -181,10 +181,9 @@ namespace Server.Spells.Bushido public static void EndEvasion(Mobile m) { - if (m_Table.TryGetValue(m, out var timer)) + if (m_Table.Remove(m, out var timer)) { timer.Stop(); - m_Table.Remove(m); } OnEffectEnd(m, typeof(Evasion)); diff --git a/Projects/UOContent/Spells/Bushido/HonorableExecution.cs b/Projects/UOContent/Spells/Bushido/HonorableExecution.cs index 2e09403c3..08df46f42 100644 --- a/Projects/UOContent/Spells/Bushido/HonorableExecution.cs +++ b/Projects/UOContent/Spells/Bushido/HonorableExecution.cs @@ -25,7 +25,9 @@ namespace Server.Spells.Bushido public override void OnHit(Mobile attacker, Mobile defender, int damage) { if (!Validate(attacker) || !CheckMana(attacker, true)) + { return; + } ClearCurrentMove(attacker); @@ -64,7 +66,9 @@ namespace Server.Spells.Bushido var resSpells = attacker.Skills.MagicResist.Value; if (resSpells > 0.0) + { mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells)); + } info = new HonorableExecutionInfo(attacker, mods); info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(7.0), RemovePenalty, info.m_Mobile); @@ -81,12 +85,13 @@ namespace Server.Spells.Bushido public static void RemovePenalty(Mobile target) { - if (!m_Table.TryGetValue(target, out var info) || !info.m_Penalty) + if (!m_Table.Remove(target, out var info) || !info.m_Penalty) + { return; + } info.Clear(); info.m_Timer?.Stop(); - m_Table.Remove(target); } private class HonorableExecutionInfo @@ -114,32 +119,44 @@ namespace Server.Spells.Bushido public void Apply() { if (m_Mods == null) + { return; + } for (var i = 0; i < m_Mods.Count; ++i) { var mod = m_Mods[i]; if (mod is ResistanceMod resistanceMod) + { m_Mobile.AddResistanceMod(resistanceMod); + } else if (mod is SkillMod skillMod) + { m_Mobile.AddSkillMod(skillMod); + } } } public void Clear() { if (m_Mods == null) + { return; + } for (var i = 0; i < m_Mods.Count; ++i) { var mod = m_Mods[i]; if (mod is ResistanceMod resistanceMod) + { m_Mobile.RemoveResistanceMod(resistanceMod); + } else if (mod is SkillMod skillMod) + { m_Mobile.RemoveSkillMod(skillMod); + } } } } diff --git a/Projects/UOContent/Spells/Fifth/MagicReflect.cs b/Projects/UOContent/Spells/Fifth/MagicReflect.cs index 29ea60180..c28cfa001 100644 --- a/Projects/UOContent/Spells/Fifth/MagicReflect.cs +++ b/Projects/UOContent/Spells/Fifth/MagicReflect.cs @@ -25,7 +25,9 @@ namespace Server.Spells.Fifth public override bool CheckCast() { if (Core.AOS) + { return true; + } if (Caster.MagicDamageAbsorb > 0) { @@ -57,15 +59,15 @@ namespace Server.Spells.Fifth { var targ = Caster; - if (m_Table.TryGetValue(targ, out var mods)) + if (m_Table.Remove(targ, out var mods)) { targ.PlaySound(0x1ED); targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); - m_Table.Remove(targ); - for (var i = 0; i < mods.Length; ++i) + { targ.RemoveResistanceMod(mods[i]); + } BuffInfo.RemoveBuff(targ, BuffIcon.MagicReflection); } @@ -89,7 +91,9 @@ namespace Server.Spells.Fifth m_Table[targ] = mods; for (var i = 0; i < mods.Length; ++i) + { targ.AddResistanceMod(mods[i]); + } var buffFormat = $"{physiMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}"; @@ -133,13 +137,16 @@ namespace Server.Spells.Fifth public static void EndReflect(Mobile m) { - if (!m_Table.TryGetValue(m, out var mods)) + if (!m_Table.Remove(m, out var mods)) + { return; + } for (var i = 0; i < mods?.Length; ++i) + { m.RemoveResistanceMod(mods[i]); + } - m_Table.Remove(m); BuffInfo.RemoveBuff(m, BuffIcon.MagicReflection); } } diff --git a/Projects/UOContent/Spells/First/ReactiveArmor.cs b/Projects/UOContent/Spells/First/ReactiveArmor.cs index 081ed6c83..738f4f067 100644 --- a/Projects/UOContent/Spells/First/ReactiveArmor.cs +++ b/Projects/UOContent/Spells/First/ReactiveArmor.cs @@ -26,7 +26,9 @@ namespace Server.Spells.First public override bool CheckCast() { if (Core.AOS) + { return true; + } if (Caster.MeleeDamageAbsorb > 0) { @@ -59,15 +61,15 @@ namespace Server.Spells.First { var targ = Caster; - if (m_Table.TryGetValue(targ, out var mods)) + if (m_Table.Remove(targ, out var mods)) { targ.PlaySound(0x1ED); targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); - m_Table.Remove(targ); - for (var i = 0; i < mods.Length; ++i) + { targ.RemoveResistanceMod(mods[i]); + } BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor); } @@ -91,7 +93,9 @@ namespace Server.Spells.First m_Table[targ] = mods; for (var i = 0; i < mods.Length; ++i) + { targ.AddResistanceMod(mods[i]); + } var physresist = 15 + (int)(targ.Skills.Inscribe.Value / 20); var args = $"{physresist}\t{5}\t{5}\t{5}\t{5}"; @@ -140,13 +144,16 @@ namespace Server.Spells.First public static void EndArmor(Mobile m) { - if (!m_Table.TryGetValue(m, out var mods)) + if (!m_Table.Remove(m, out var mods)) + { return; + } for (var i = 0; i < mods?.Length; ++i) + { m.RemoveResistanceMod(mods[i]); + } - m_Table.Remove(m); BuffInfo.RemoveBuff(m, BuffIcon.ReactiveArmor); } } diff --git a/Projects/UOContent/Spells/Fourth/ArchProtection.cs b/Projects/UOContent/Spells/Fourth/ArchProtection.cs index f848292d3..8ad3b3dfb 100644 --- a/Projects/UOContent/Spells/Fourth/ArchProtection.cs +++ b/Projects/UOContent/Spells/Fourth/ArchProtection.cs @@ -97,9 +97,8 @@ namespace Server.Spells.Fourth public static void RemoveEntry(Mobile m) { - if (_Table.TryGetValue(m, out var v)) + if (_Table.Remove(m, out var v)) { - _Table.Remove(m); m.EndAction(); m.VirtualArmorMod -= Math.Min(v, m.VirtualArmorMod); } diff --git a/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs b/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs index 2b45c1156..a5ae827d4 100644 --- a/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs @@ -95,7 +95,9 @@ namespace Server.Spells.Mysticism var mount = Caster.Mount; if (mount != null) + { mount.Rider = null; + } Caster.BodyMod = 0x2C1; Caster.HueMod = 0; @@ -112,7 +114,9 @@ namespace Server.Spells.Mysticism }; for (var i = 0; i < mods.Length; ++i) + { Caster.AddResistanceMod(mods[i]); + } m_Table[Caster] = mods; @@ -141,17 +145,19 @@ namespace Server.Spells.Mysticism public static void RemoveEffects(Mobile m) { - if (!m_Table.TryGetValue(m, out var mods)) + if (!m_Table.Remove(m, out var mods)) + { return; + } for (var i = 0; i < mods.Length; ++i) + { m.RemoveResistanceMod(mods[i]); + } m.BodyMod = 0; m.HueMod = -1; - m_Table.Remove(m); - BuffInfo.RemoveBuff(m, BuffIcon.StoneForm); } diff --git a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs index 6b0915d72..cc5190c7b 100644 --- a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs @@ -151,7 +151,10 @@ namespace Server.Spells.Necromancy { Type type = null; - if (c.Owner != null) type = c.Owner.GetType(); + if (c.Owner != null) + { + type = c.Owner.GetType(); + } if (c.ItemID != 0x2006 || c.Animated || type == typeof(PlayerMobile) || type == null || c.Owner != null && c.Owner.Fame < 100 || @@ -217,10 +220,14 @@ namespace Server.Spells.Necromancy var contains = types.Length == 0; for (var j = 0; !contains && j < types.Length; ++j) + { contains = types[j].IsAssignableFrom(type); + } if (contains) - return group; + { + return @group; + } } return null; @@ -228,41 +235,52 @@ namespace Server.Spells.Necromancy public static void Unregister(Mobile master, Mobile summoned) { - if (master == null) - return; - - if (!m_Table.TryGetValue(master, out var list)) + if (master == null || !m_Table.TryGetValue(master, out var list)) + { return; + } list.Remove(summoned); if (list.Count == 0) + { m_Table.Remove(master); + } } public static void Register(Mobile master, Mobile summoned) { if (master == null) + { return; + } if (!m_Table.TryGetValue(master, out var list)) + { m_Table[master] = list = new List(); + } for (var i = list.Count - 1; i >= 0; --i) { if (i >= list.Count) + { continue; + } var mob = list[i]; if (mob.Deleted) + { list.RemoveAt(i--); + } } list.Add(summoned); if (list.Count > 3) + { Timer.DelayCall(list[0].Kill); + } Timer.DelayCall(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), Summoned_Damage, summoned); } @@ -270,20 +288,28 @@ namespace Server.Spells.Necromancy private static void Summoned_Damage(Mobile mob) { if (mob.Hits > 0) + { --mob.Hits; + } else + { mob.Kill(); + } } private static void SummonDelay_Callback(Mobile caster, Corpse corpse, Point3D loc, Map map, CreatureGroup group) { if (corpse.Animated) + { return; + } var owner = corpse.Owner; if (owner == null) + { return; + } var necromancy = caster.Skills.Necromancy.Value; var spiritSpeak = caster.Skills.SpiritSpeak.Value; @@ -299,7 +325,9 @@ namespace Server.Spells.Necromancy var entry = entries[i]; if (casterAbility < entry.m_Requirement) + { continue; + } var animates = entry.m_ToSummon; @@ -307,7 +335,9 @@ namespace Server.Spells.Necromancy } if (toSummon == null) + { return; + } Mobile summoned = null; @@ -321,7 +351,9 @@ namespace Server.Spells.Necromancy } if (summoned == null) + { return; + } if (summoned is BaseCreature bc) { @@ -336,7 +368,9 @@ namespace Server.Spells.Necromancy } if (summoned is SkeletalDragon dragon) + { Scale(dragon, 50); // lose 50% hp and strength + } summoned.Fame = 0; summoned.Karma = -1500; @@ -357,7 +391,9 @@ namespace Server.Spells.Necromancy toScale = bc.HitsMaxSeed; if (toScale > 0) + { bc.HitsMaxSeed = AOS.Scale(toScale, scalar); + } bc.Hits = bc.Hits; // refresh hits } diff --git a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs index fdc8c52f0..19c91e7ff 100644 --- a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs @@ -45,9 +45,13 @@ namespace Server.Spells.Necromancy else if (m_OathTable.ContainsKey(m)) { if (m.Player) + { Caster.SendLocalizedMessage(1061608); // That player is already bonded in a Blood Oath. + } else + { Caster.SendLocalizedMessage(1061609); // That creature is already bonded in a Blood Oath. + } } else if (CheckHSequence(m)) { @@ -128,21 +132,22 @@ namespace Server.Spells.Necromancy protected override void OnTick() { if (m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive || - DateTime.UtcNow >= m_End) DoExpire(); + DateTime.UtcNow >= m_End) + { + DoExpire(); + } } public void DoExpire() { - if (m_OathTable.ContainsKey(m_Caster)) + if (m_OathTable.Remove(m_Caster)) { m_Caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - m_OathTable.Remove(m_Caster); } - if (m_OathTable.ContainsKey(m_Target)) + if (m_OathTable.Remove(m_Target)) { m_Target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - m_OathTable.Remove(m_Target); } Stop(); diff --git a/Projects/UOContent/Spells/Necromancy/EvilOmen.cs b/Projects/UOContent/Spells/Necromancy/EvilOmen.cs index 8db928e1f..a83d349bc 100644 --- a/Projects/UOContent/Spells/Necromancy/EvilOmen.cs +++ b/Projects/UOContent/Spells/Necromancy/EvilOmen.cs @@ -57,7 +57,9 @@ namespace Server.Spells.Necromancy var mod = new DefaultSkillMod(SkillName.MagicResist, false, 50.0); if (m.Skills.MagicResist.Base > 50.0) + { m.AddSkillMod(mod); + } m_Table[m] = mod; } @@ -81,10 +83,11 @@ namespace Server.Spells.Necromancy public static bool TryEndEffect(Mobile m) { - if (!m_Table.TryGetValue(m, out var mod)) + if (!m_Table.Remove(m, out var mod)) + { return false; + } - m_Table.Remove(m); mod?.Remove(); return true; diff --git a/Projects/UOContent/Spells/Necromancy/MindRot.cs b/Projects/UOContent/Spells/Necromancy/MindRot.cs index d4f4ea31c..9b4ab9253 100644 --- a/Projects/UOContent/Spells/Necromancy/MindRot.cs +++ b/Projects/UOContent/Spells/Necromancy/MindRot.cs @@ -73,12 +73,13 @@ namespace Server.Spells.Necromancy public static void ClearMindRotScalar(Mobile m) { - if (!m_Table.TryGetValue(m, out var tmpB)) + if (!m_Table.Remove(m, out var tmpB)) + { return; + } BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); tmpB.m_MRExpireTimer.Stop(); - m_Table.Remove(m); m.SendLocalizedMessage(1060872); // Your mind feels normal again. } diff --git a/Projects/UOContent/Spells/Necromancy/Strangle.cs b/Projects/UOContent/Spells/Necromancy/Strangle.cs index 2be755ff5..61767c7be 100644 --- a/Projects/UOContent/Spells/Necromancy/Strangle.cs +++ b/Projects/UOContent/Spells/Necromancy/Strangle.cs @@ -29,7 +29,9 @@ namespace Server.Spells.Necromancy public void Target(Mobile m) { if (m == null) + { return; + } if (CheckHSequence(m)) { @@ -70,7 +72,10 @@ namespace Server.Spells.Necromancy // Calculations for the buff bar var spiritlevel = Caster.Skills.SpiritSpeak.Value / 10; if (spiritlevel < 4) + { spiritlevel = 4; + } + var d_MinDamage = 4; var d_MaxDamage = ((int)spiritlevel + 1) * 3; var args = $"{d_MinDamage}\t{d_MaxDamage}"; @@ -113,13 +118,13 @@ namespace Server.Spells.Necromancy public static bool RemoveCurse(Mobile m) { - if (!m_Table.TryGetValue(m, out var timer)) + if (!m_Table.Remove(m, out var timer)) + { return false; + } timer.Stop(); m.SendLocalizedMessage(1061687); // You can breath normally again. - - m_Table.Remove(m); return true; } @@ -153,7 +158,9 @@ namespace Server.Spells.Necromancy m_Count = (int)spiritLevel; if (m_Count < 4) + { m_Count = 4; + } m_MaxCount = m_Count; } @@ -167,7 +174,9 @@ namespace Server.Spells.Necromancy } if (!m_Target.Alive || DateTime.UtcNow < m_NextHit) + { return; + } --m_Count; @@ -182,9 +191,13 @@ namespace Server.Spells.Necromancy var delay = (int)Math.Ceiling((1.0 + 5 * m_Count) / m_MaxCount); if (delay <= 5) + { m_HitDelay = delay; + } else + { m_HitDelay = 5; + } } } @@ -203,16 +216,22 @@ namespace Server.Spells.Necromancy damage *= 3 - (double)m_Target.Stam / m_Target.StamMax * 2; if (damage < 1) + { damage = 1; + } if (!m_Target.Player) + { damage *= 1.75; + } AOS.Damage(m_Target, m_From, (int)damage, 0, 0, 0, 100, 0); if (Utility.RandomDouble() >= 0.60 ) // OSI: randomly revealed between first and third damage tick, guessing 60% chance + { m_Target.RevealingAction(); + } } } } diff --git a/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs b/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs index 21f634bea..dcf7be3e2 100644 --- a/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs +++ b/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs @@ -20,7 +20,9 @@ namespace Server.Spells.Ninjitsu public override void OnHit(Mobile attacker, Mobile defender, int damage) { if (!Validate(attacker) || !CheckMana(attacker, true)) + { return; + } ClearCurrentMove(attacker); @@ -32,9 +34,13 @@ namespace Server.Spells.Ninjitsu var isRanged = attacker.Weapon is BaseRanged; if (ninjitsu < 100) // This formula is an approximation from OSI data. TODO: find correct formula + { chance = 30 + (ninjitsu - 85) * 2.2; + } else + { chance = 63 + (ninjitsu - 100) * 1.1; + } if (chance / 100 < Utility.RandomDouble()) { @@ -44,16 +50,16 @@ namespace Server.Spells.Ninjitsu var damageBonus = 0; - if (m_Table.TryGetValue(defender, out var info)) + if (m_Table.Remove(defender, out var info)) { defender.SendLocalizedMessage(1063092); // Your opponent lands another Death Strike! if (info.m_Steps > 0) + { damageBonus = attacker.Skills.Ninjitsu.Fixed / 150; + } info.m_Timer?.Stop(); - - m_Table.Remove(defender); } else { @@ -78,13 +84,17 @@ namespace Server.Spells.Ninjitsu public static void AddStep(Mobile m) { if (m_Table.TryGetValue(m, out var info) && ++info.m_Steps >= 5) + { ProcessDeathStrike(m); + } } private static void ProcessDeathStrike(Mobile defender) { - if (!m_Table.TryGetValue(defender, out var info)) + if (!m_Table.Remove(defender, out var info)) + { return; + } int damage; @@ -97,16 +107,24 @@ namespace Server.Spells.Ninjitsu info.m_Attacker.Skills.Stealth.Value) / 220; if (scalar > 1) + { scalar = 1; + } // New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30. if (info.m_Steps >= 5) + { damage = (int)Math.Floor(Math.Min(60, ninjitsu / 3 * (0.3 + 0.7 * scalar) + stalkingBonus)); + } else + { damage = (int)Math.Floor(Math.Min(30, ninjitsu / 9 * (0.3 + 0.7 * scalar) + stalkingBonus)); + } if (info.m_isRanged) + { damage /= 2; + } } else { @@ -118,8 +136,11 @@ namespace Server.Spells.Ninjitsu } if (Core.ML) + { info.m_Target.Damage(damage, info.m_Attacker); // Damage is direct. + } else + { AOS.Damage( info.m_Target, info.m_Attacker, @@ -136,10 +157,9 @@ namespace Server.Spells.Ninjitsu false, true ); // Damage is physical. + } info.m_Timer?.Stop(); - - m_Table.Remove(info.m_Target); } private class DeathStrikeInfo diff --git a/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs b/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs index a139c8c27..20fa9e9d4 100644 --- a/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs +++ b/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs @@ -81,11 +81,10 @@ namespace Server.Spells.Ninjitsu public override void OnClearMove(Mobile from) { - if (!m_Table.TryGetValue(from, out var info)) - return; - - info.m_Timer.Stop(); - m_Table.Remove(info.m_Mobile); + if (m_Table.Remove(from, out var info)) + { + info.m_Timer.Stop(); + } } public static double GetBonus(Mobile from) diff --git a/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs b/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs index 51bcbf692..83c993028 100644 --- a/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs +++ b/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs @@ -53,11 +53,9 @@ namespace Server.Spells.Ninjitsu attacker.RevealingAction(); - if (m_Table.TryGetValue(defender, out var info)) + if (m_Table.Remove(defender, out var info)) { info.m_Timer?.Stop(); - - m_Table.Remove(defender); } var ninjitsu = attacker.Skills.Ninjitsu.Fixed; diff --git a/Projects/UOContent/Spells/Second/Protection.cs b/Projects/UOContent/Spells/Second/Protection.cs index 722ceb6a5..8941d765a 100644 --- a/Projects/UOContent/Spells/Second/Protection.cs +++ b/Projects/UOContent/Spells/Second/Protection.cs @@ -29,7 +29,9 @@ namespace Server.Spells.Second public override bool CheckCast() { if (Core.AOS) + { return true; + } if (Registry.ContainsKey(Caster)) { @@ -38,7 +40,9 @@ namespace Server.Spells.Second } if (Caster.CanBeginAction()) + { return true; + } Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. return false; @@ -55,12 +59,11 @@ namespace Server.Spells.Second * even after dying�until you �turn them off� by casting them again. */ - if (m_Table.TryGetValue(target, out var mods)) + if (m_Table.Remove(target, out var mods)) { target.PlaySound(0x1ED); target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); - m_Table.Remove(target); Registry.Remove(target); target.RemoveResistanceMod(mods.Item1); @@ -100,10 +103,11 @@ namespace Server.Spells.Second public static void EndProtection(Mobile m) { - if (!m_Table.TryGetValue(m, out var mods)) + if (!m_Table.Remove(m, out var mods)) + { return; + } - m_Table.Remove(m); Registry.Remove(m); m.RemoveResistanceMod(mods.Item1); @@ -117,7 +121,9 @@ namespace Server.Spells.Second if (Core.AOS) { if (CheckSequence()) + { Toggle(Caster, Caster); + } FinishSequence(); } diff --git a/Projects/UOContent/Spells/Sixth/Invisibility.cs b/Projects/UOContent/Spells/Sixth/Invisibility.cs index 5e2c2e17b..2c1f7ea88 100644 --- a/Projects/UOContent/Spells/Sixth/Invisibility.cs +++ b/Projects/UOContent/Spells/Sixth/Invisibility.cs @@ -93,11 +93,10 @@ namespace Server.Spells.Sixth public static void RemoveTimer(Mobile m) { - if (!m_Table.TryGetValue(m, out var t)) - return; - - t.Stop(); - m_Table.Remove(m); + if (m_Table.Remove(m, out var t)) + { + t.Stop(); + } } private class InternalTimer : Timer diff --git a/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs b/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs index 0c0dfe8ff..4e8b554ec 100644 --- a/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs +++ b/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs @@ -27,7 +27,9 @@ namespace Server.Spells.Spellweaving public void Target(Mobile m) { if (m == null) + { return; + } if (!Caster.CanSee(m)) { @@ -94,10 +96,10 @@ namespace Server.Spells.Spellweaving public static bool StopEffect(Mobile m) { - if (!m_Table.TryGetValue(m, out var info)) + if (!m_Table.Remove(m, out var info)) + { return false; - - m_Table.Remove(m); + } info.m_Timer.Stop(); BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal); @@ -151,7 +153,9 @@ namespace Server.Spells.Spellweaving } if (m.Hits >= m.HitsMax) + { return; + } var toHeal = m_GiftInfo.m_HitsPerRound; diff --git a/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs b/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs index 34f6844c6..5a58e62d7 100644 --- a/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs +++ b/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs @@ -77,17 +77,20 @@ namespace Server.Spells.Spellweaving private static void FinishEffect(DelayedEffectEntry effect) { if (m_WeaponDamageTable.TryGetValue(effect.m_Weapon, out var entry)) + { AOS.Damage(effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0); + } } public static void StopImmolating(BaseWeapon weapon) { - if (!m_WeaponDamageTable.TryGetValue(weapon, out var entry)) + if (!m_WeaponDamageTable.Remove(weapon, out var entry)) + { return; + } entry.m_Caster?.PlaySound(0x27); entry.m_Timer.Stop(); - m_WeaponDamageTable.Remove(weapon); weapon.InvalidateProperties(); } diff --git a/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs b/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs index 88e6f1b24..9103e10b3 100644 --- a/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs +++ b/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs @@ -48,7 +48,9 @@ namespace Server.Spells.Spellweaving { if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanBeHarmful(m, false) || !Caster.InLOS(m)) + { continue; + } Caster.DoHarmful(m); @@ -57,7 +59,9 @@ namespace Server.Spells.Spellweaving SpellHelper.Damage(this, m, m.Player && Caster.Player ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100); if (oldSpell == null || oldSpell == m.Spell || CheckResisted(m)) + { continue; + } m_Table[m] = Timer.DelayCall(duration, DoExpire, m); @@ -77,11 +81,12 @@ namespace Server.Spells.Spellweaving public static void DoExpire(Mobile m) { - if (!m_Table.TryGetValue(m, out var t)) + if (!m_Table.Remove(m, out var t)) + { return; + } t.Stop(); - m_Table.Remove(m); BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm); }