diff --git a/Projects/UOContent/Misc/FoodDecay.cs b/Projects/UOContent/Misc/FoodDecay.cs index 8cb1c21d2..ec12f8173 100644 --- a/Projects/UOContent/Misc/FoodDecay.cs +++ b/Projects/UOContent/Misc/FoodDecay.cs @@ -1,17 +1,21 @@ using System; +using Server; using Server.Network; +using Server.Mobiles; +using Server.Regions; namespace Server.Misc { public class FoodDecayTimer : Timer { - public FoodDecayTimer() : base(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)) - { - } - public static void Initialize() { new FoodDecayTimer().Start(); + new EatDecayTimer().Start(); + } + + public FoodDecayTimer() : base(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)) + { } protected override void OnTick() @@ -23,24 +27,155 @@ namespace Server.Misc { foreach (var state in NetState.Instances) { - HungerDecay(state.Mobile); - ThirstDecay(state.Mobile); + if (state.Mobile != null) + { + HungerDecay(state.Mobile); + } } } public static void HungerDecay(Mobile m) { - if (m?.Hunger >= 1) + if (m is PlayerMobile && m.AccessLevel == AccessLevel.Player) { - m.Hunger -= 1; + if (m.Region is HouseRegion || m.Region is GreetingBusinessRegion) + return; + + if (m.Hunger >= 1) + { + m.Hunger -= 1; + if (m.Hunger == 15) + m.SendMessage("Your stomach gives a slight rumble."); + else if (m.Hunger == 10) + m.SendMessage("You are starting to feel hungry."); + else if (m.Hunger == 5) + m.SendMessage("You are getting extremely hungry. You should eat soon!"); + } + + if (m.Thirst >= 1) + { + m.Thirst -= 1; + if (m.Thirst == 15) + m.SendMessage("Your mouth feels a little dry."); + else if (m.Thirst == 10) + m.SendMessage("You are starting to feel thirsty."); + else if (m.Thirst == 5) + m.SendMessage("You are getting extremely thirsty. You should drink soon!"); + } + } + } + } + + public class EatDecayTimer : Timer + { + public EatDecayTimer() : base(TimeSpan.FromSeconds(11.0), TimeSpan.FromSeconds(11.0)) + { + } + + protected override void OnTick() + { + EatDecay(); + } + + public static void EatDecay() + { + foreach (var state in NetState.Instances) + { + if (state.Mobile != null) + { + EatDecaying(state.Mobile); + } } } - public static void ThirstDecay(Mobile m) + public static void EatDecaying(Mobile m) { - if (m?.Thirst >= 1) + if (m is PlayerMobile pm && pm.Alive && pm.AccessLevel == AccessLevel.Player) { - m.Thirst -= 1; + if (m.Region is HouseRegion || m.Region is GreetingBusinessRegion) + return; + + if (m.Hunger < 5 || m.Thirst < 5) + { + if (m.Hunger < 5) + { + int hits = 0; + + if (m.Hunger >= 4) hits = 2; + else if (m.Hunger >= 3) hits = 3; + else if (m.Hunger >= 2) hits = 4; + else if (m.Hunger >= 1) hits = 5; + else + { + hits = 6; + m.SendMessage("You are starving to death!"); + m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am so hungry!"); + } + + if (m.Hits < hits) + hits = m.Hits - 1; + + if (hits > 0) + m.Hits -= hits; + + if (m.Hunger < 3 && m.Hunger > 0) + { + if (Utility.RandomDouble() < 0.10) m.SendMessage("You are getting very hungry!"); + if (Utility.RandomMinMax(1, 20) == 1) m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting hungry!"); + } + } + + if (m.Thirst < 5) + { + if (m.Thirst >= 4) m.Stam -= 2; + else if (m.Thirst >= 3) m.Stam -= 3; + else if (m.Thirst >= 2) m.Stam -= 4; + else if (m.Thirst >= 1) m.Stam -= 5; + else + { + m.Stam -= 6; + m.SendMessage("You are exhausted from thirst!"); + m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am so thirsty!"); + } + + if (m.Thirst < 3 && m.Thirst > 0) + { + if (Utility.RandomDouble() < 0.10) m.SendMessage("You are getting exhausted from thirst!"); + if (Utility.RandomMinMax(1, 20) == 1) m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting thirsty!"); + } + + if (m.Stam < 0) + m.Stam = 0; + } + + int test = Math.Min(m.Hunger, m.Thirst); + + if (test >= 4) m.Mana -= 2; + else if (test >= 3) m.Mana -= 3; + else if (test >= 2) m.Mana -= 4; + else if (test >= 1) m.Mana -= 5; + else m.Mana -= 6; + + if (m.Mana < 0) + m.Mana = 0; + } + else + { + if (m.Hunger >= 15 && m.Hits < m.HitsMax) + { + m.Hits += 2; + } + + if (m.Thirst >= 15 && m.Stam < m.StamMax) + { + m.Stam += 2; + } + + if (m.Hunger >= 15 && m.Thirst >= 15 && m.Mana < m.ManaMax) + { + m.Mana += 2; + } + } } } } diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index f4085d5aa..c3fa4433b 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -770,6 +770,14 @@ namespace Server.Mobiles set => m_TotalPlayerDeaths = value; } + private int m_ExhaustionDamageTracker; + [CommandProperty(AccessLevel.GameMaster)] + public int ExhaustionDamageTracker + { + get => m_ExhaustionDamageTracker; + set => m_ExhaustionDamageTracker = value; + } + public HonorContext ReceivedHonorContext { get; set; } public QuestArrow QuestArrow @@ -2417,6 +2425,35 @@ namespace Server.Mobiles SentHonorContext?.OnSourceDamaged(from, amount); base.OnDamage(amount, from, willKill); + if (this.Alive && amount > 0) + { + m_ExhaustionDamageTracker += amount; + + if (m_ExhaustionDamageTracker >= 200) + { + int drops = m_ExhaustionDamageTracker / 200; + bool statsDropped = false; + + if (this.Hunger > 0) + { + this.Hunger = Math.Max(0, this.Hunger - drops); + statsDropped = true; + } + + if (this.Thirst > 0) + { + this.Thirst = Math.Max(0, this.Thirst - drops); + statsDropped = true; + } + + if (statsDropped) + { + this.SendMessage(33, "The physical toll of combat leaves you exhausted."); + StatusBar.Refresh(this); + } + m_ExhaustionDamageTracker %= 200; + } + } } public override void Resurrect()