diff --git a/ClimatesOfFerngill/ClimatesOfFerngillRebuild.cs b/ClimatesOfFerngill/ClimatesOfFerngillRebuild.cs index e822bea..5db6455 100644 --- a/ClimatesOfFerngill/ClimatesOfFerngillRebuild.cs +++ b/ClimatesOfFerngill/ClimatesOfFerngillRebuild.cs @@ -20,6 +20,7 @@ using Microsoft.Xna.Framework.Graphics; using System.Reflection; +using StardewValley.TerrainFeatures; namespace ClimatesOfFerngillRebuild { @@ -86,6 +87,13 @@ public class ClimatesOfFerngill : Mod private int TicksOutside; private int TicksTotal; + //for events + private int ExpireTime; + private List CropList; + + //queued string + private HUDMessage queuedMsg; + /// /// This is used to allow the menu to revert back to a previous menu /// @@ -117,10 +125,13 @@ public override void Entry(IModHelper helper) DebugOutput = new StringBuilder(); OurMoon = new SDVMoon(Dice); OurIcons = new Sprites.Icons(Helper.Content); + CropList = new List(); StaminaMngr = new StaminaDrain(WeatherOpt, Helper.Translation); + queuedMsg = null; TicksOutside = 0; TicksTotal = 0; + ExpireTime = 0; if (WeatherOpt.Verbose) Monitor.Log($"Loading climate type: {WeatherOpt.ClimateType} from file", LogLevel.Trace); @@ -161,10 +172,45 @@ private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged /// private void OnEndOfDay(object sender, EventArgs e) { + if (CurrentWeather.UnusualWeather == SpecialWeather.Frost) + { + Farm f = Game1.getFarm(); + int count = 0, maxCrops = (int)Math.Floor(SDVUtilities.CropCountInFarm(f) * WeatherOpt.DeadCropPercentage); + + foreach (KeyValuePair tf in f.terrainFeatures) + { + + if (count >= maxCrops) + break; + + if (tf.Value is HoeDirt curr && curr.crop != null) + { + if (Dice.NextDouble() <= (WeatherOpt.CropResistance / 2)) + { + CropList.Add(tf.Key); + count++; + } + } + } + + if (count > 0) + { + foreach (Vector2 v in CropList) + { + HoeDirt hd = (HoeDirt)f.terrainFeatures[v]; + hd.crop.dead = true; + } + + queuedMsg = new HUDMessage(Helper.Translation.Get("hud - text.desc_frost_killed")); + } + } + + //moon works after frost does OurMoon.HandleMoonAtSleep(Game1.getFarm(), Helper.Translation); } + #region TVOverride public void TryHookTelevision() { @@ -327,15 +373,69 @@ private void TenMinuteUpdate(object sender, EventArgsIntChanged e) && Game1.timeOfDay < 2400) Utility.performLightningUpdate(); + //queued messages clear + if (Game1.timeOfDay == 610 && queuedMsg != null) + { + Game1.hudMessages.Add(queuedMsg); + queuedMsg = null; + } + //frost works at night, heatwave works during the day if (Game1.timeOfDay == 1700) { if (CurrentWeather.IsHeatwave()) { + ExpireTime = 2000; + Farm f = Game1.getFarm(); + int count = 0, maxCrops = (int)Math.Floor(SDVUtilities.CropCountInFarm(f) * WeatherOpt.DeadCropPercentage); + + foreach (KeyValuePair tf in f.terrainFeatures) + { + if (count >= maxCrops) + break; + + if (tf.Value is HoeDirt curr && curr.crop != null) + { + if (Dice.NextDouble() <= WeatherOpt.CropResistance) + { + CropList.Add(tf.Key); + curr.state = HoeDirt.dry; + count++; + } + } + } + + if (CropList.Count > 0) + { + if (!WeatherOpt.AllowCropDeath) + SDVUtilities.ShowMessage(Helper.Translation.Get("hud-text.desc_heatwave_dry")); + else + SDVUtilities.ShowMessage(Helper.Translation.Get("hud-text.desc_heatwave_kill")); + } } } + if (Game1.timeOfDay == ExpireTime && WeatherOpt.AllowCropDeath) + { + //if it's still de watered - kill it. + Farm f = Game1.getFarm(); + bool cDead = false; + + foreach (Vector2 v in CropList) + { + HoeDirt hd = (HoeDirt)f.terrainFeatures[v]; + if (hd.state == HoeDirt.dry) + { + hd.crop.dead = true; + cDead = true; + } + } + + if (cDead) + SDVUtilities.ShowMessage("Some of the crops have died due to lack of water!"); + } + Game1.player.stamina += StaminaMngr.TenMinuteTick(CurrentWeather.UnusualWeather, TicksOutside, TicksTotal); if (Game1.player.stamina <= 0) @@ -366,6 +466,8 @@ private void DrawObjects(object sender, EventArgs e) private void ResetMod(object sender, EventArgs e) { CurrentWeather.Reset(); + ExpireTime = 0; + CropList.Clear(); DebugOutput.Clear(); OurFog.Reset(); StaminaMngr.Reset(); @@ -376,12 +478,15 @@ private void ResetMod(object sender, EventArgs e) private void HandleNewDay(object sender, EventArgs e) { + CropList.Clear(); //clear the crop list DebugOutput.Clear(); OurMoon.UpdateForNewDay(); + CurrentWeather.OnNewDay(); UpdateWeatherOnNewDay(); OurMoon.HandleMoonAfterWake(Helper.Translation); StaminaMngr.OnNewDay(CurrentWeather); TicksOutside = 0; + ExpireTime = 0; TicksTotal = 0; } @@ -394,8 +499,6 @@ private void UpdateWeatherOnNewDay() int TmrwWeather = Game1.weatherForTomorrow; //reset for new day - CurrentWeather.WillFog = false; - CurrentWeather.UnusualWeather = SpecialWeather.None; OurFog.Reset(); //Set Temperature for today and tommorow. Get today's conditions. @@ -498,7 +601,6 @@ private void UpdateWeatherOnNewDay() } } - //Dry Lightning is also here for such like the dry and arid climates // which have so low rain chances they may never storm. if (CurrentWeather.TodayWeather == Game1.weather_snow) @@ -514,7 +616,7 @@ private void UpdateWeatherOnNewDay() } if (WeatherOpt.Verbose) - Monitor.Log("Testing for special weathers - dry lightning."); + Monitor.Log("Testing for special weathers - dry lightning and heatwave"); if (CurrentWeather.TodayWeather == Game1.weather_sunny) { @@ -527,7 +629,7 @@ private void UpdateWeatherOnNewDay() Monitor.Log($"With roll {oddsRoll.ToString("N3")} against {WeatherOpt.DryLightning}, there will be dry lightning today."); } - if (CurrentWeather.GetTodayHigh() > WeatherOpt.TooHotOutside) + if (CurrentWeather.GetTodayHigh() > WeatherOpt.TooHotOutside && WeatherOpt.HazardousWeather) { if (CurrentWeather.UnusualWeather == SpecialWeather.DryLightning) CurrentWeather.UnusualWeather = SpecialWeather.DryLightningAndHeatwave; @@ -536,6 +638,18 @@ private void UpdateWeatherOnNewDay() } } + if (WeatherOpt.Verbose) + Monitor.Log("Testing for special weathers - frost."); + + if (CurrentWeather.GetTodayLow() < WeatherOpt.TooColdOutside && !Game1.IsWinter) + { + if (WeatherOpt.HazardousWeather) + { + CurrentWeather.UnusualWeather = SpecialWeather.Frost; + } + } + + //if tomorrow is a festival or wedding, we need to set the weather and leave. if (Utility.isFestivalDay(Game1.dayOfMonth + 1, Game1.currentSeason)) { diff --git a/ClimatesOfFerngill/README.md b/ClimatesOfFerngill/README.md index 6e3b932..fc21376 100644 --- a/ClimatesOfFerngill/README.md +++ b/ClimatesOfFerngill/README.md @@ -92,4 +92,8 @@ over a certain value.). Valid 0-1, but it's recommended that this is kept low. D - 'Tier1Drain' - A tier 1 cold drains this much stamina per ten minutes. Default: '2' - - 'Tier2Drain' - A tier 2 cold drains this much stamina per ten minutes. Default: '4' \ No newline at end of file + - 'Tier2Drain' - A tier 2 cold drains this much stamina per ten minutes. Default: '4' + + - 'DeadCropPercentage' - The amount of crops that a heatwave and frost can kill. (Note: Frost will kill more than heatwaves). Default: '.1' Valid range is 0 to 1. + + - 'CropResistance' - This represents the resistance an averagecrop has to heatwaves. Frosts have half this resistance. Default: '.4' Valid Range is 0 to 1. \ No newline at end of file diff --git a/ClimatesOfFerngill/WeatherConditions.cs b/ClimatesOfFerngill/WeatherConditions.cs index 5928b6f..923514d 100644 --- a/ClimatesOfFerngill/WeatherConditions.cs +++ b/ClimatesOfFerngill/WeatherConditions.cs @@ -61,6 +61,16 @@ public bool IsDangerousWeather() return false; } + public void OnNewDay() + { + TodayWeather = 0; + TomorrowWeather = 0; + UnusualWeather = SpecialWeather.None; + WillFog = false; + TodayTemps = null; + TomorrowTemps = null; + } + public void Reset() { TodayTemps = null; diff --git a/ClimatesOfFerngill/WeatherConfig.cs b/ClimatesOfFerngill/WeatherConfig.cs index 57be84c..1907e5b 100644 --- a/ClimatesOfFerngill/WeatherConfig.cs +++ b/ClimatesOfFerngill/WeatherConfig.cs @@ -24,6 +24,8 @@ class WeatherConfig public int Tier1Drain { get; set; } public int Tier2Drain { get; set; } public bool SickMoreThanOnce { get; set; } + public double DeadCropPercentage { get; set; } + public double CropResistance { get; set; } public bool Verbose { get; set; } @@ -48,6 +50,8 @@ public WeatherConfig() StormTotemChange = true; //rain totems may spawn storms instead of rain totems. AllowStormsSpringYear1 = false; //default setting - maintains the fact that starting players may not ShowBothScales = true; //default setting. + DeadCropPercentage = .1; //default setting + CropResistance = .4; //default settting // be able to deal with lightning strikes diff --git a/ClimatesOfFerngill/i18n/default.json b/ClimatesOfFerngill/i18n/default.json index 43fadfd..a6fe239 100644 --- a/ClimatesOfFerngill/i18n/default.json +++ b/ClimatesOfFerngill/i18n/default.json @@ -19,6 +19,9 @@ "hud-text.desc_stormtotem": "You hear a roll of thunder...", "hud-text.desc_sick": "You have caught a cold...!", "hud-text.desc_flu": "You have caught the flu and better take some medicine soon!", + "hud-text.desc_frost_killed": "Some of your crops died in the night due to the cold..!", + "hud-text.desc_heatwave_dry" :"The extreme heat has caused some of your crops to become dry....!", + "hud-text.desc_heatwave_kill" : "The extreme heat has caused some of your crops to dry out. If you don't water them, they'll die!", //Lunar Messages "moon-text.phase-full": "Full Moon", @@ -72,14 +75,14 @@ "weather-desc.summer_debris2": "a wind blowing through today will bring some small relief from the heat", "weather-desc.summer_wedding1": "a warm summer Stardew Valley wedding", "weather-desc.summer_wedding2": "a clear ideal summer Stardew Valley wedding", - + "weather-desc.fall_sunny1": "a cool autumn day", "weather-desc.fall_rainy1": "chilly showers", "weather-desc.fall_stormy1": "a blustery thundery day ", "weather-desc.fall_snowy1": "an early snow", "weather-desc.fall_debris1": "a day full of whirling leaves", "weather-desc.fall_wedding1": "a cool pleasent Stardew Valley wedding", - + "weather-desc.winter_sunny1": "a cold sunny day", "weather-desc.winter_rainy1": "too warm for snow, a freezing rain", "weather-desc.winter_stormy1": "a rare winter thunderstorm ", diff --git a/TwilightCore/Stardew Valley/SDVUtilities.cs b/TwilightCore/Stardew Valley/SDVUtilities.cs index 7290224..26b01bd 100644 --- a/TwilightCore/Stardew Valley/SDVUtilities.cs +++ b/TwilightCore/Stardew Valley/SDVUtilities.cs @@ -5,6 +5,7 @@ using StardewValley.Locations; using StardewValley.Monsters; using TwilightCore.PRNG; +using StardewValley.TerrainFeatures; namespace TwilightCore.StardewValley { @@ -116,6 +117,21 @@ public static string WeatherToString(int weather) } } + public static int CropCountInFarm(Farm f) + { + int count = 0; + + foreach (KeyValuePair tf in f.terrainFeatures) + { + if (tf.Value is HoeDirt curr && curr.crop != null) + { + count++; + } + } + + return count; + } + public static void SpawnGhostOffScreen(MersenneTwister Dice) { Vector2 zero = Vector2.Zero;