From a254b9db25759f0f62422a3b739c628fefeb0d31 Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Thu, 27 Aug 2026 21:35:43 -0400 Subject: [PATCH] #W# Exhaustion system and some Food changes. --- Scripts/Misc/FoodDecay.cs | 234 ++++++++++++++++++++++++++------ Scripts/Mobiles/PlayerMobile.cs | 36 +++++ 2 files changed, 225 insertions(+), 45 deletions(-) diff --git a/Scripts/Misc/FoodDecay.cs b/Scripts/Misc/FoodDecay.cs index d53851d..3940f92 100644 --- a/Scripts/Misc/FoodDecay.cs +++ b/Scripts/Misc/FoodDecay.cs @@ -1,45 +1,189 @@ -using System; -using Server.Network; -using Server; - -namespace Server.Misc -{ - public class FoodDecayTimer : Timer - { - public static void Initialize() - { - new FoodDecayTimer().Start(); - } - - public FoodDecayTimer() : base( TimeSpan.FromMinutes( 5 ), TimeSpan.FromMinutes( 5 ) ) - { - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - FoodDecay(); - } - - public static void FoodDecay() - { - foreach ( NetState state in NetState.Instances ) - { - HungerDecay( state.Mobile ); - ThirstDecay( state.Mobile ); - } - } - - public static void HungerDecay( Mobile m ) - { - if ( m != null && m.Hunger >= 1 ) - m.Hunger -= 1; - } - - public static void ThirstDecay( Mobile m ) - { - if ( m != null && m.Thirst >= 1 ) - m.Thirst -= 1; - } - } -} \ No newline at end of file +using System; +using Server.Network; +using Server; +using Server.Mobiles; +using Server.Regions; + +namespace Server.Misc +{ + public class FoodDecayTimer : Timer + { + public static void Initialize() + { + new FoodDecayTimer().Start(); + } + + public FoodDecayTimer() : base( TimeSpan.FromMinutes( 5 ), TimeSpan.FromMinutes( 5 ) ) + { + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + FoodDecay(); + } + + public static void FoodDecay() + { + foreach ( NetState state in NetState.Instances ) + { + HungerDecay( state.Mobile ); + } + } + + public static void HungerDecay( Mobile m ) + { + // Ensures it only affects living players + if ( m != null && m is PlayerMobile && m.Alive && m.AccessLevel == AccessLevel.Player ) + { + // The Safe Zone Check: Pauses decay if in an Inn or a House + if ( !m.Region.IsPartOf(typeof(InnRegion)) && !m.Region.IsPartOf(typeof(HouseRegion)) ) + { + 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 static void Initialize() + { + new EatDecayTimer().Start(); + } + + public EatDecayTimer() : base( TimeSpan.FromSeconds( 11.0 ), TimeSpan.FromSeconds( 11.0 ) ) + { + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + EatDecay(); + } + + public static void EatDecay() + { + foreach ( NetState state in NetState.Instances ) + { + EatDecaying( state.Mobile ); + } + } + + public static void EatDecaying( Mobile m ) + { + if ( m is PlayerMobile && m.Alive ) + { + // If they run into a house or inn, the 11-second starvation damage stops + if ( m.Region.IsPartOf(typeof(InnRegion)) || m.Region.IsPartOf(typeof(HouseRegion)) ) + return; + + // Starvation penalties begin when stats fall below 6 (The 0 to 5 range) + if ( m.Hunger < 6 || m.Thirst < 6 ) + { + if ( m.Hunger < 6 ) + { + int hits = 0; + + if ( m.Hunger == 5 ) hits = 2; + else if ( m.Hunger == 4 ) hits = 3; + else if ( m.Hunger == 3 ) hits = 4; + else if ( m.Hunger == 2 ) 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 < 4 && m.Hunger > 0 ) + { + if ( Utility.RandomBool() ) m.SendMessage( "You are getting very hungry!" ); + if ( Utility.RandomMinMax(1,5) == 1 ) m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting hungry!"); + } + } + + if ( m.Thirst < 6 ) + { + if ( m.Thirst == 5 ) m.Stam -= 2; + else if ( m.Thirst == 4 ) m.Stam -= 3; + else if ( m.Thirst == 3 ) m.Stam -= 4; + else if ( m.Thirst == 2 ) 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 < 4 && m.Thirst > 0 ) + { + if ( Utility.RandomBool() ) m.SendMessage( "You are getting exhausted from thirst!" ); + if ( Utility.RandomMinMax(1,5) == 1 ) m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting thirsty!"); + } + + if ( m.Stam < 0 ) + m.Stam = 0; + } + + int test = m.Thirst; + if ( m.Hunger < m.Thirst ) + test = m.Hunger; + + if ( test == 5 ) m.Mana -= 2; + else if ( test == 4 ) m.Mana -= 3; + else if ( test == 3 ) m.Mana -= 4; + else if ( test == 2 ) m.Mana -= 5; + else m.Mana -= 6; + + if ( m.Mana < 0 ) + m.Mana = 0; + } + else + { + // Well-Fed Regeneration starts when stats are 16 or higher (The 16 to 20 range) + if ( m.Hunger >= 16 && m.Hits < m.HitsMax ) + { + m.Hits += 2; + } + + if ( m.Thirst >= 16 && m.Stam < m.StamMax ) + { + m.Stam += 2; + } + + if ( m.Hunger >= 16 && m.Thirst >= 16 && m.Mana < m.ManaMax ) + { + m.Mana += 2; + } + } + } + } + } +} diff --git a/Scripts/Mobiles/PlayerMobile.cs b/Scripts/Mobiles/PlayerMobile.cs index f5c23c0..3002af4 100644 --- a/Scripts/Mobiles/PlayerMobile.cs +++ b/Scripts/Mobiles/PlayerMobile.cs @@ -206,6 +206,9 @@ namespace Server.Mobiles private Point3D m_LastInnLocation; private Map m_LastInnMap; // -- Inn Room End + // -- Exhaustion System Start + private int m_ExhaustionDamageTracker; + // -- Exhaustion System End #region Getters & Setters @@ -2638,6 +2641,39 @@ namespace Server.Mobiles if ( willKill && from is PlayerMobile ) Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( ((PlayerMobile) from).RecoverAmmo ) ); + // -- Exhaustion System Start + 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 and parched." ); + } + + // Save the leftover damage for the next cycle + m_ExhaustionDamageTracker %= 200; + } + } + // -- Exhaustion System End + base.OnDamage( amount, from, willKill ); }