From 9014f3d4dca1efbe6f66506e19fd9c09859072e0 Mon Sep 17 00:00:00 2001 From: Guyute Date: Tue, 6 Aug 2024 22:17:33 -0400 Subject: [PATCH] fix: Converts ResurrectGump to Static/Dynamic Gumps (#1904) --- .../Power Faction Items/UrnOfAscension.cs | 2 +- .../UOContent/Engines/Virtues/Sacrifice.cs | 2 +- .../UOContent/Gumps/PricedResurrectGump.cs | 144 ++++++++ Projects/UOContent/Gumps/ResurrectGump.cs | 307 +++++++----------- .../Items/Skill Items/Misc/Bandage.cs | 2 +- .../Veteran Rewards/AnkhOfSacrifice.cs | 30 +- .../UOContent/Mobiles/Healers/PricedHealer.cs | 4 +- .../Spells/Chivalry/NobleSacrifice.cs | 2 +- .../UOContent/Spells/Eighth/Resurrection.cs | 2 +- 9 files changed, 276 insertions(+), 219 deletions(-) create mode 100644 Projects/UOContent/Gumps/PricedResurrectGump.cs diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs index 6e056bc26c..8374604576 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs @@ -35,7 +35,7 @@ public override bool Use(Mobile from) { Faction.ClearSkillLoss(mob); - mob.SendGump(new ResurrectGump(mob, from)); + mob.SendGump(new ResurrectGump(from)); used = true; } } diff --git a/Projects/UOContent/Engines/Virtues/Sacrifice.cs b/Projects/UOContent/Engines/Virtues/Sacrifice.cs index fd2d91d1cc..8f31e9acc3 100644 --- a/Projects/UOContent/Engines/Virtues/Sacrifice.cs +++ b/Projects/UOContent/Engines/Virtues/Sacrifice.cs @@ -75,7 +75,7 @@ public static void Resurrect(PlayerMobile from) * Sacrifice and cancel to have items in their backpack for free. */ from.CloseGump(); - from.SendGump(new ResurrectGump(from, true)); + from.SendGump(new ResurrectGump(from, fromSacrifice: true)); } else { diff --git a/Projects/UOContent/Gumps/PricedResurrectGump.cs b/Projects/UOContent/Gumps/PricedResurrectGump.cs new file mode 100644 index 0000000000..8151f4c2a0 --- /dev/null +++ b/Projects/UOContent/Gumps/PricedResurrectGump.cs @@ -0,0 +1,144 @@ +using Server.Engines.Virtues; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps; + +public class PricedResurrectGump : StaticGump +{ + private readonly Mobile _healer; + private readonly int _price; + + public PricedResurrectGump(Mobile healer, int price) : base(150, 50) + { + _healer = healer; + _price = price; + } + + protected override void BuildLayout(ref StaticGumpBuilder builder) + { + builder.SetNoClose(); + + builder.AddPage(); + + builder.AddImage(0, 0, 3600); + + builder.AddImageTiled(0, 14, 15, 200, 3603); + builder.AddImageTiled(380, 14, 14, 200, 3605); + + builder.AddImage(0, 201, 3606); + + builder.AddImageTiled(15, 201, 370, 16, 3607); + builder.AddImageTiled(15, 0, 370, 16, 3601); + + builder.AddImage(380, 0, 3602); + + builder.AddImage(380, 201, 3608); + + builder.AddImageTiled(15, 15, 365, 190, 2624); + + builder.AddRadio(30, 140, 9727, 9730, true, 1); + builder.AddHtmlLocalized(65, 145, 300, 25, 1060015, 0x7FFF); // Grudgingly pay the money + + builder.AddRadio(30, 175, 9727, 9730, false, 0); + builder.AddHtmlLocalized(65, 178, 300, 25, 1060016, 0x7FFF); // I'd rather stay dead, you scoundrel!!! + + // Wishing to rejoin the living, are you? I can restore your body... for a price of course... + builder.AddHtmlLocalized(30, 20, 360, 35, 1060017, 0x7FFF); + + // Do you accept the fee, which will be withdrawn from your bank? + builder.AddHtmlLocalized(30, 105, 345, 40, 1060018, 0x5B2D); + + builder.AddImage(65, 72, 5605); + + builder.AddImageTiled(80, 90, 200, 1, 9107); + builder.AddImageTiled(95, 92, 200, 1, 9157); + + builder.AddLabelPlaceholder(90, 70, 1645, "resurrectionPrice"); + builder.AddHtmlLocalized(140, 70, 100, 25, 1023823, 0x7FFF); // gold coins + + builder.AddButton(290, 175, 247, 248, 2); + + builder.AddImageTiled(15, 14, 365, 1, 9107); + builder.AddImageTiled(380, 14, 1, 190, 9105); + builder.AddImageTiled(15, 205, 365, 1, 9107); + builder.AddImageTiled(15, 14, 1, 190, 9105); + builder.AddImageTiled(0, 0, 395, 1, 9157); + builder.AddImageTiled(394, 0, 1, 217, 9155); + builder.AddImageTiled(0, 216, 395, 1, 9157); + builder.AddImageTiled(0, 0, 1, 217, 9155); + } + + protected override void BuildStrings(ref GumpStringsBuilder builder) + { + builder.SetStringSlot("resurrectionPrice", $"{_price}"); + } + + public override void OnResponse(NetState state, in RelayInfo info) + { + if (info.ButtonID is not 1 and not 2) + { + return; + } + + var from = state.Mobile; + + if (from.Map?.CanFit(from.Location, 16, false, false) != true) + { + from.SendLocalizedMessage(502391); // Thou can not be resurrected there! + return; + } + + if (!info.IsSwitched(1)) + { + from.SendLocalizedMessage(1060019); // You decide against paying the healer, and thus remain dead. + return; + } + + if (Banker.Withdraw(from, _price)) + { + // ~1_AMOUNT~ gold has been withdrawn from your bank box. + from.SendLocalizedMessage(1060398, _price.ToString()); + + // You have ~1_AMOUNT~ gold in cash remaining in your bank box. + from.SendLocalizedMessage(1060022, Banker.GetBalance(from).ToString()); + } + else + { + // Unfortunately, you do not have enough cash in your bank to cover the cost of the healing. + from.SendLocalizedMessage(1060020); + return; + } + + from.PlaySound(0x214); + from.FixedEffect(0x376A, 10, 16); + + from.Resurrect(); + + if (_healer != null && from != _healer) + { + var level = VirtueSystem.GetLevel(_healer, VirtueName.Compassion); + + from.Hits = level switch + { + VirtueLevel.Seeker => AOS.Scale(from.HitsMax, 20), + VirtueLevel.Follower => AOS.Scale(from.HitsMax, 40), + VirtueLevel.Knight => AOS.Scale(from.HitsMax, 80), + _ => from.Hits + }; + } + + if (from.Fame > 0) + { + var amount = from.Fame / 10; + + Titles.AwardFame(from, -amount, true); + } + + if (from is PlayerMobile player) + { + ResurrectGump.TryGiveStatLoss(player); + } + } +} diff --git a/Projects/UOContent/Gumps/ResurrectGump.cs b/Projects/UOContent/Gumps/ResurrectGump.cs index f3c1322b9a..cd3f51f7a4 100644 --- a/Projects/UOContent/Gumps/ResurrectGump.cs +++ b/Projects/UOContent/Gumps/ResurrectGump.cs @@ -1,191 +1,139 @@ -using System.Collections.Generic; +using System; using Server.Engines.Virtues; using Server.Misc; using Server.Mobiles; using Server.Network; -namespace Server.Gumps +namespace Server.Gumps; + +public enum ResurrectMessage { - public enum ResurrectMessage - { - ChaosShrine = 0, - VirtueShrine = 1, - Healer = 2, - Generic = 3 - } + ChaosShrine = 0, + VirtueShrine = 1, + Healer = 2, + Generic = 3 +} - public class ResurrectGump : Gump - { - private readonly bool m_FromSacrifice; - private readonly Mobile m_Healer; - private readonly double m_HitsScalar; - private readonly int m_Price; +public class ResurrectGump : DynamicGump +{ + public const int ShortMurdersForStatLoss = 5; - public ResurrectGump(Mobile owner, double hitsScalar) - : this(owner, owner, ResurrectMessage.Generic, false, hitsScalar) + private readonly bool _fromSacrifice; + private readonly Mobile _healer; + private readonly double _hitsScalar; + private readonly ResurrectMessage _resurrectMessage; + + public static void TryGiveStatLoss(PlayerMobile player) + { + if (Core.AOS || player.ShortTermMurders < ShortMurdersForStatLoss) { + return; } - public ResurrectGump(Mobile owner, ResurrectMessage msg) : this(owner, owner, msg) + var loss = Math.Clamp((100.0 - (4.0 + player.ShortTermMurders / (double)ShortMurdersForStatLoss)) / 100.0, 0.85, 0.95); // 5 to 15% loss + var lossStr = (int)(player.RawStr * loss); + var lossInt = (int)(player.RawInt * loss); + var lossDex = (int)(player.RawDex * loss); + + if (lossStr >= 10) { + player.RawStr = lossStr; } - public ResurrectGump(Mobile owner, bool fromSacrifice = false) - : this(owner, owner, ResurrectMessage.Generic, fromSacrifice) + if (lossInt >= 10) { + player.RawInt = lossInt; } - public ResurrectGump( - Mobile owner, Mobile healer, ResurrectMessage msg = ResurrectMessage.Generic, - bool fromSacrifice = false, double hitsScalar = 0.0 - ) - : base(100, 0) + if (lossDex >= 10) { - m_Healer = healer; - m_FromSacrifice = fromSacrifice; - m_HitsScalar = hitsScalar; - - AddPage(0); - - AddBackground(0, 0, 400, 350, 2600); - - AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
- - /* It is possible for you to be resurrected here by this healer. Do you wish to try?
- * CONTINUE - You chose to try to come back to life now.
- * CANCEL - You prefer to remain a ghost for now. - */ - AddHtmlLocalized(50, 55, 300, 140, 1011023 + (int)msg, true, true); - - AddButton(200, 227, 4005, 4007, 0); - AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL - - AddButton(65, 227, 4005, 4007, 1); - AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE + player.RawDex = lossDex; } - public ResurrectGump(Mobile owner, Mobile healer, int price) - : base(150, 50) + for (var s = 0; s < player.Skills.Length; s++) { - m_Healer = healer; - m_Price = price; - - Closable = false; - - AddPage(0); - - AddImage(0, 0, 3600); - - AddImageTiled(0, 14, 15, 200, 3603); - AddImageTiled(380, 14, 14, 200, 3605); - - AddImage(0, 201, 3606); - - AddImageTiled(15, 201, 370, 16, 3607); - AddImageTiled(15, 0, 370, 16, 3601); - - AddImage(380, 0, 3602); - - AddImage(380, 201, 3608); - - AddImageTiled(15, 15, 365, 190, 2624); - - AddRadio(30, 140, 9727, 9730, true, 1); - AddHtmlLocalized(65, 145, 300, 25, 1060015, 0x7FFF); // Grudgingly pay the money + var skill = player.Skills[s]; + var skillLoss = (int)(skill.BaseFixedPoint * loss); + if (skillLoss >= 350) + { + skill.BaseFixedPoint = skillLoss; + } + } + } - AddRadio(30, 175, 9727, 9730, false, 0); - AddHtmlLocalized(65, 178, 300, 25, 1060016, 0x7FFF); // I'd rather stay dead, you scoundrel!!! + public ResurrectGump(Mobile healer, double hitsScalar) + : this(healer, ResurrectMessage.Generic, false, hitsScalar) + { + } - // Wishing to rejoin the living, are you? I can restore your body... for a price of course... - AddHtmlLocalized(30, 20, 360, 35, 1060017, 0x7FFF); + public ResurrectGump( + Mobile healer, ResurrectMessage msg = ResurrectMessage.Generic, + bool fromSacrifice = false, double hitsScalar = 0.0 + ) : base(100, 0) + { + _healer = healer; + _fromSacrifice = fromSacrifice; + _hitsScalar = hitsScalar; + _resurrectMessage = msg; + } - // Do you accept the fee, which will be withdrawn from your bank? - AddHtmlLocalized(30, 105, 345, 40, 1060018, 0x5B2D); + protected override void BuildLayout(ref DynamicGumpBuilder builder) + { + builder.AddPage(); - AddImage(65, 72, 5605); + builder.AddBackground(0, 0, 400, 350, 2600); - AddImageTiled(80, 90, 200, 1, 9107); - AddImageTiled(95, 92, 200, 1, 9157); + builder.AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
- AddLabel(90, 70, 1645, price.ToString()); - AddHtmlLocalized(140, 70, 100, 25, 1023823, 0x7FFF); // gold coins + /* It is possible for you to be resurrected here by this healer. Do you wish to try?
+ * CONTINUE - You chose to try to come back to life now.
+ * CANCEL - You prefer to remain a ghost for now. + */ + builder.AddHtmlLocalized(50, 55, 300, 140, 1011023 + (int)_resurrectMessage, true, true); - AddButton(290, 175, 247, 248, 2); + builder.AddButton(200, 227, 4005, 4007, 0); + builder.AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL - AddImageTiled(15, 14, 365, 1, 9107); - AddImageTiled(380, 14, 1, 190, 9105); - AddImageTiled(15, 205, 365, 1, 9107); - AddImageTiled(15, 14, 1, 190, 9105); - AddImageTiled(0, 0, 395, 1, 9157); - AddImageTiled(394, 0, 1, 217, 9155); - AddImageTiled(0, 216, 395, 1, 9157); - AddImageTiled(0, 0, 1, 217, 9155); - } + builder.AddButton(65, 227, 4005, 4007, 1); + builder.AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE + } - public override void OnResponse(NetState state, in RelayInfo info) + public override void OnResponse(NetState state, in RelayInfo info) + { + if (info.ButtonID is not 1 and not 2) { - var from = state.Mobile; - - from.CloseGump(); + return; + } - if (info.ButtonID != 1 && info.ButtonID != 2) - { - return; - } + var from = state.Mobile; - if (from.Map?.CanFit(from.Location, 16, false, false) != true) - { - from.SendLocalizedMessage(502391); // Thou can not be resurrected there! - return; - } - - if (m_Price > 0) - { - if (info.IsSwitched(1)) - { - if (Banker.Withdraw(from, m_Price)) - { - // ~1_AMOUNT~ gold has been withdrawn from your bank box. - from.SendLocalizedMessage(1060398, m_Price.ToString()); + if (from.Map?.CanFit(from.Location, 16, false, false) != true) + { + from.SendLocalizedMessage(502391); // Thou can not be resurrected there! + return; + } - // You have ~1_AMOUNT~ gold in cash remaining in your bank box. - from.SendLocalizedMessage(1060022, Banker.GetBalance(from).ToString()); - } - else - { - // Unfortunately, you do not have enough cash in your bank to cover the cost of the healing. - from.SendLocalizedMessage(1060020); - return; - } - } - else - { - from.SendLocalizedMessage(1060019); // You decide against paying the healer, and thus remain dead. - return; - } - } + from.PlaySound(0x214); + from.FixedEffect(0x376A, 10, 16); - from.PlaySound(0x214); - from.FixedEffect(0x376A, 10, 16); + from.Resurrect(); - from.Resurrect(); + if (_healer != null && from != _healer) + { + var level = VirtueSystem.GetLevel(_healer, VirtueName.Compassion); - if (m_Healer != null && from != m_Healer) + from.Hits = level switch { - var level = VirtueSystem.GetLevel(m_Healer, VirtueName.Compassion); - - from.Hits = level switch - { - VirtueLevel.Seeker => AOS.Scale(from.HitsMax, 20), - VirtueLevel.Follower => AOS.Scale(from.HitsMax, 40), - VirtueLevel.Knight => AOS.Scale(from.HitsMax, 80), - _ => from.Hits - }; - } - - var player = from as PlayerMobile; + VirtueLevel.Seeker => AOS.Scale(from.HitsMax, 20), + VirtueLevel.Follower => AOS.Scale(from.HitsMax, 40), + VirtueLevel.Knight => AOS.Scale(from.HitsMax, 80), + _ => from.Hits + }; + } - if (m_FromSacrifice && player != null) + if (from is PlayerMobile player) + { + if (_fromSacrifice) { player.Virtues.AvailableResurrects -= 1; @@ -194,11 +142,9 @@ public override void OnResponse(NetState state, in RelayInfo info) if (pack != null && corpse != null) { - var items = new List(corpse.Items); - - for (var i = 0; i < items.Count; ++i) + for (var i = corpse.Items.Count - 1; i >= 0; --i) { - var item = items[i]; + var item = corpse.Items[i]; if (item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && item.Movable) { @@ -208,54 +154,19 @@ public override void OnResponse(NetState state, in RelayInfo info) } } - if (from.Fame > 0) - { - var amount = from.Fame / 10; - - Titles.AwardFame(from, -amount, true); - } - - if (!Core.AOS && player?.ShortTermMurders >= 5) - { - var loss = (100.0 - (4.0 + player.ShortTermMurders / 5.0)) / 100.0; // 5 to 15% loss - - if (loss < 0.85) - { - loss = 0.85; - } - else if (loss > 0.95) - { - loss = 0.95; - } - - if (from.RawStr * loss > 10) - { - from.RawStr = (int)(from.RawStr * loss); - } - - if (from.RawInt * loss > 10) - { - from.RawInt = (int)(from.RawInt * loss); - } + TryGiveStatLoss(player); + } - if (from.RawDex * loss > 10) - { - from.RawDex = (int)(from.RawDex * loss); - } + if (from.Fame > 0) + { + var amount = from.Fame / 10; - for (var s = 0; s < from.Skills.Length; s++) - { - if (from.Skills[s].Base * loss > 35) - { - from.Skills[s].Base *= loss; - } - } - } + Titles.AwardFame(from, -amount, true); + } - if (from.Alive && m_HitsScalar > 0) - { - from.Hits = (int)(from.HitsMax * m_HitsScalar); - } + if (from.Alive && _hitsScalar > 0) + { + from.Hits = (int)(from.HitsMax * _hitsScalar); } } } diff --git a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs index d6e94a1f7c..0c0d4cf030 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs @@ -311,7 +311,7 @@ protected override void OnTick() else { Patient.CloseGump(); - Patient.SendGump(new ResurrectGump(Patient, Healer)); + Patient.SendGump(new ResurrectGump(Healer)); } } else if (Patient.Poisoned) diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs index 5f34b2c5b6..fad9d5eb9c 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs @@ -83,29 +83,31 @@ public override void OnClick(Mobile from, IEntity target) private class AnkhResurrectGump : ResurrectGump { - public AnkhResurrectGump(Mobile owner, ResurrectMessage msg) : base(owner, owner, msg) + public AnkhResurrectGump(Mobile owner, ResurrectMessage msg) : base(owner, msg) { } public override void OnResponse(NetState state, in RelayInfo info) { + if (info.ButtonID is not 1 and not 2) + { + return; + } + var from = state.Mobile; - if (info.ButtonID is 1 or 2) + if (from.Map?.CanFit(from.Location, 16, false, false) != true) { - if (from.Map?.CanFit(from.Location, 16, false, false) != true) - { - from.SendLocalizedMessage(502391); // Thou can not be resurrected there! - return; - } - - if (from is PlayerMobile mobile) - { - mobile.AnkhNextUse = Core.Now + TimeSpan.FromHours(1); - } - - base.OnResponse(state, info); + from.SendLocalizedMessage(502391); // Thou can not be resurrected there! + return; } + + if (from is PlayerMobile mobile) + { + mobile.AnkhNextUse = Core.Now + TimeSpan.FromHours(1); + } + + base.OnResponse(state, info); } } } diff --git a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs index e6ce63efa8..2648cec2d4 100644 --- a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs @@ -36,8 +36,8 @@ public override void OfferResurrection(Mobile m) m.PlaySound(0x214); m.FixedEffect(0x376A, 10, 16); - m.CloseGump(); - m.SendGump(new ResurrectGump(m, this, Price)); + m.CloseGump(); + m.SendGump(new PricedResurrectGump(this, Price)); } public override bool CheckResurrect(Mobile m) => true; diff --git a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs index ac8d1b6e1d..b50df416e6 100644 --- a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs +++ b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs @@ -75,7 +75,7 @@ public override void OnCast() { m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); m.CloseGump(); - m.SendGump(new ResurrectGump(m, Caster)); + m.SendGump(new ResurrectGump(Caster)); sacrifice = true; } } diff --git a/Projects/UOContent/Spells/Eighth/Resurrection.cs b/Projects/UOContent/Spells/Eighth/Resurrection.cs index 96f7dd2be4..b4f2c26048 100644 --- a/Projects/UOContent/Spells/Eighth/Resurrection.cs +++ b/Projects/UOContent/Spells/Eighth/Resurrection.cs @@ -62,7 +62,7 @@ public void Target(Mobile m) m.FixedEffect(0x376A, 10, 16); m.CloseGump(); - m.SendGump(new ResurrectGump(m, Caster)); + m.SendGump(new ResurrectGump(Caster)); } }