Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Seasons v1.9.2
Seasons.dll
Decompiled 6 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ConditionalConfigSync; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Seasons; using Seasons.Compatibility; using Seasons.Controllers; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Seasons")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Seasons")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("076e7e5f-9182-41e5-a76b-5c051d6b3957")] [assembly: AssemblyFileVersion("1.9.2")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.9.2.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } public struct HSLColor { public float h; public float s; public float l; public float a; public HSLColor(float h, float s, float l, float a) { this.h = h; this.s = s; this.l = l; this.a = a; } public HSLColor(float h, float s, float l) { this.h = h; this.s = s; this.l = l; a = 1f; } public HSLColor(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HSLColor hSLColor = FromRGBA(c); h = hSLColor.h; s = hSLColor.s; l = hSLColor.l; a = hSLColor.a; } public static HSLColor FromRGBA(Color c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) float num = c.a; float num2 = Mathf.Min(Mathf.Min(c.r, c.g), c.b); float num3 = Mathf.Max(Mathf.Max(c.r, c.g), c.b); float num4 = (num2 + num3) / 2f; float num5; float num6; if (num2 == num3) { num5 = 0f; num6 = 0f; } else { float num7 = num3 - num2; num5 = ((num4 <= 0.5f) ? (num7 / (num3 + num2)) : (num7 / (2f - (num3 + num2)))); num6 = 0f; if (c.r == num3) { num6 = (c.g - c.b) / num7; } else if (c.g == num3) { num6 = 2f + (c.b - c.r) / num7; } else if (c.b == num3) { num6 = 4f + (c.r - c.g) / num7; } num6 = Mathf.Repeat(num6 * 60f, 360f); } return new HSLColor(num6, num5, num4, num); } public Color ToRGBA() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) float num = a; float num2 = ((l <= 0.5f) ? (l * (1f + s)) : (l + s - l * s)); float n = 2f * l - num2; float num3; float num4; float num5; if (s == 0f) { num3 = (num4 = (num5 = l)); } else { num3 = Value(n, num2, h + 120f); num4 = Value(n, num2, h); num5 = Value(n, num2, h - 120f); } return new Color(num3, num4, num5, num); } private static float Value(float n1, float n2, float hue) { hue = Mathf.Repeat(hue, 360f); if (hue < 60f) { return n1 + (n2 - n1) * hue / 60f; } if (hue < 180f) { return n2; } if (hue < 240f) { return n1 + (n2 - n1) * (240f - hue) / 60f; } return n1; } public static implicit operator HSLColor(Color src) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FromRGBA(src); } public static implicit operator Color(HSLColor src) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) return src.ToRGBA(); } } namespace LocalizationManager { [PublicAPI] public class Localizer { private const string defaultLanguage = "English"; private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin Plugin { get { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out string value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2)) { text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static IEnumerator Load() { yield return (object)new WaitUntil((Func<bool>)(() => PlatformManager.DistributionPlatform != null && PlatformInitializer.PreferencesInitialized)); if (string.IsNullOrEmpty(PlatformPrefs.GetString("language", ""))) { PlatformPrefs.SetString("language", "English"); } LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> localizationFiles = new Dictionary<string, string>(); string[] prefixes = new string[2] { Plugin.Info.Metadata.Name + ".", Plugin.Info.Metadata.Name.Replace(" ", "") + "." }; Scan(Paths.ConfigPath, warn: true); Scan(Paths.PluginPath, warn: false); byte[] array = LoadTranslationFromAssembly("English"); if (array == null) { throw new Exception("Found no English localizations in mod " + Plugin.Info.Metadata.Name + ". Expected an embedded resource Translations/English.json or Translations/English.yml."); } Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(Encoding.UTF8.GetString(array)) ?? throw new Exception("Localization for mod " + Plugin.Info.Metadata.Name + " failed: Localization file was empty."); string text = null; if (language != "English") { if (localizationFiles.ContainsKey(language)) { text = File.ReadAllText(localizationFiles[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text = Encoding.UTF8.GetString(array2); } } } if (text == null && localizationFiles.ContainsKey("English")) { text = File.ReadAllText(localizationFiles["English"]); } if (text != null) { foreach (KeyValuePair<string, string> item in JsonConvert.DeserializeObject<Dictionary<string, string>>(text) ?? new Dictionary<string, string>()) { dictionary[item.Key] = item.Value; } } loadedTexts[language] = dictionary; foreach (KeyValuePair<string, string> item2 in dictionary) { UpdatePlaceholderText(__instance, item2.Key); } void Scan(string root, bool warn) { foreach (string item3 in from f in Directory.GetFiles(root, "*.*", SearchOption.AllDirectories) where fileExtensions.Contains(Path.GetExtension(f)) select f) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item3); string[] array3 = prefixes; foreach (string text2 in array3) { if (fileNameWithoutExtension.StartsWith(text2)) { string text3 = fileNameWithoutExtension.Substring(text2.Length); if (!string.IsNullOrWhiteSpace(text3)) { if (localizationFiles.ContainsKey(text3)) { if (warn) { global::Seasons.Seasons.LogWarning("Duplicate localization '" + text3 + "' for " + Plugin.Info.Metadata.Name + ". Skipping " + item3); } } else { localizationFiles[text3] = item3; } } break; } } } } } static Localizer() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string> { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("Translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } } namespace Seasons { public static class LoadingTips { [HarmonyPatch(typeof(Hud), "Awake")] public static class Hud_Awake_LoadingTips { private static void Postfix() { UpdateLoadingTips(); } } private static readonly List<string> summerHeatCombinedTips = new List<string>(); public static void UpdateLoadingTips() { if (Seasons.UseTextureControllers() && !((Object)(object)Hud.instance == (Object)null) && SeasonState.IsActive) { UpdateTipBasedOnValue("$seasons_loadscreen_tip_ice", Seasons.enableFrozenWater.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_torch", Seasons.seasonState.GetSeasonSettings(Seasons.Season.Winter).m_torchAsFiresource); UpdateTipBasedOnValue("$seasons_loadscreen_tip_harvests", Seasons.seasonState.GetSeasonSettings(Seasons.Season.Spring).m_plantsGrowthMultiplier != 1f || Seasons.seasonState.GetSeasonSettings(Seasons.Season.Summer).m_plantsGrowthMultiplier != 1f); UpdateTipBasedOnValue("$seasons_loadscreen_tip_nights", Seasons.seasonState.GetSeasonSettings(Seasons.Season.Winter).m_nightLength > 30 || Seasons.controlLightings.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_overheat", !Seasons.summerHeatEnabled.Value && Seasons.summerHeatAddsExtraWarmCloth.Value && Seasons.seasonState.GetSeasonSettings(Seasons.Season.Summer).m_overheatIn2WarmClothes); UpdateTipBasedOnValue("$seasons_loadscreen_tip_summer_heat", Seasons.summerHeatEnabled.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_summer_heat_cold_food", Seasons.summerHeatEnabled.Value && !string.IsNullOrWhiteSpace(Seasons.summerHeatCoolingFoods.Value)); UpdateTipBasedOnValue("$seasons_loadscreen_tip_summer_heat_risk", Seasons.summerHeatEnabled.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_firewood", Seasons.seasonState.GetSeasonSettings(Seasons.Season.Winter).m_fireplaceDrainMultiplier > 1f); UpdateTipBasedOnValue("$seasons_loadscreen_tip_perish", Seasons.cropsDiesAfterSetDayInWinter.Value != 0); UpdateTipBasedOnValue("$seasons_loadscreen_tip_traders", Seasons.controlTraders.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_stats", Seasons.controlStats.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_wolves", Seasons.controlRandomEvents.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_swimming", Seasons.freezingSwimmingInWinter.Value); UpdateTipBasedOnValue("$seasons_loadscreen_tip_clutter", Seasons.controlGrass.Value); UpdateSummerHeatCombinedTips(); Hud.instance.m_haveSetupLoadScreen = false; Seasons.LogInfo("Loading tips updated."); } } private static void UpdateTipBasedOnValue(string tip, bool value) { if (Seasons.enableLoadingTips.Value && value && !Hud.instance.m_loadingTips.Contains(tip)) { Hud.instance.m_loadingTips.Add(tip); } else if ((!Seasons.enableLoadingTips.Value || !value) && Hud.instance.m_loadingTips.Contains(tip)) { Hud.instance.m_loadingTips.Remove(tip); } } private static void UpdateSummerHeatCombinedTips() { foreach (string summerHeatCombinedTip in summerHeatCombinedTips) { Hud.instance.m_loadingTips.Remove(summerHeatCombinedTip); } summerHeatCombinedTips.Clear(); if (Seasons.enableLoadingTips.Value && Seasons.summerHeatEnabled.Value) { AddSummerHeatCombinedTips(BuildSummerHeatOutfitTipParts()); AddSummerHeatCombinedTips(BuildSummerHeatBehaviorTipParts()); } } private static IEnumerable<string> BuildSummerHeatOutfitTipParts() { bool armorHeatEnabled = Seasons.summerHeatArmorHeatEnabled.Value; bool hasOutfitSpecificRules = HasText(Seasons.summerHeatOpenHelmetItems.Value) || HasText(Seasons.summerHeatOpenChestItems.Value) || HasText(Seasons.summerHeatOpenLegItems.Value) || HasText(Seasons.summerHeatLightCloakItems.Value) || HasColdWeatherArmorHeatRules(); if (armorHeatEnabled) { yield return "$seasons_loadscreen_tip_summer_heat_clothing"; } if (armorHeatEnabled && hasOutfitSpecificRules) { yield return "$seasons_loadscreen_tip_summer_heat_cold_clothing"; } if (armorHeatEnabled && HasText(Seasons.summerHeatBareHeadHairItems.Value)) { yield return "$seasons_loadscreen_tip_summer_heat_hairstyle"; } } private static IEnumerable<string> BuildSummerHeatBehaviorTipParts() { if (Seasons.summerHeatInstantHeatSources.Value || Seasons.summerHeatEncumberedAddsHeat.Value) { yield return "$seasons_loadscreen_tip_summer_heat_activity"; } if (Seasons.summerHeatCampFireAddsHeat.Value) { yield return "$seasons_loadscreen_tip_summer_heat_campfire"; } if (Seasons.summerHeatNoonEffectPercent.Value > 0f || Seasons.summerHeatNightFactor.Value < 1f) { yield return "$seasons_loadscreen_tip_summer_heat_day_night"; } } private static void AddSummerHeatCombinedTips(IEnumerable<string> parts) { List<string> list = parts.Where((string part) => !string.IsNullOrWhiteSpace(part)).ToList(); if (list.Count == 0) { return; } string text = "$seasons_loadscreen_tip_summer_heat_prefix"; for (int num = 0; num < list.Count; num += 3) { string item = text + " " + string.Join(" ", list.Skip(num).Take(3)); summerHeatCombinedTips.Add(item); if (!Hud.instance.m_loadingTips.Contains(item)) { Hud.instance.m_loadingTips.Add(item); } } } private static bool HasText(string value) { return !string.IsNullOrWhiteSpace(value); } private static bool HasColdWeatherArmorHeatRules() { return Seasons.summerHeatColdArmorHeating.Value > 0f || Seasons.summerHeatColdArmorCoolingPenalty.Value > 0f || Seasons.summerHeatColdCloakHeating.Value > 0f || Seasons.summerHeatColdCloakCoolingPenalty.Value > 0f; } } public static class ControlledComponentsExtentions { public static string Localize(this string text) { return Localization.instance.Localize(text); } public static bool ShouldBePickedInWinter(this Pickable pickable) { return pickable.CanBePicked() && !pickable.GetPicked() && pickable.IsVulnerableToWinter() && Seasons.seasonState.GetCurrentDay() >= Seasons.cropsDiesAfterSetDayInWinter.Value && !((MonoBehaviour)(object)pickable).IsProtectedPosition() && !((MonoBehaviour)(object)pickable).ProtectedWithHeat(); } public static bool IsVulnerableToWinter(this Pickable pickable) { return Seasons.seasonState.GetPlantsGrowthMultiplier() == 0f && Seasons.seasonState.GetCurrentSeason() == Seasons.Season.Winter && !((MonoBehaviour)(object)pickable).ShouldSurviveWinter() && !pickable.SurvivedCurrentWinter(); } public static bool SurvivedCurrentWinter(this Pickable pickable) { return Object.op_Implicit((Object)(object)pickable.m_nview) && pickable.m_nview.IsValid() && Seasons.seasonState.GetCurrentSeason() == Seasons.Season.Winter && Mathf.Abs(pickable.m_nview.GetZDO().GetInt(SeasonsVars.s_cropSurvivedWinterDayHash, 0) - Seasons.seasonState.GetCurrentWorldDay()) <= Seasons.seasonState.GetDaysInSeason(); } public static bool IsFreezingToDeath(this Pickable pickable) { return Object.op_Implicit((Object)(object)pickable.m_nview) && pickable.m_nview.IsValid() && Seasons.seasonState.GetCurrentSeason() == Seasons.Season.Winter && pickable.GetSecondsToFreeze() > 0.0; } public static double GetSecondsToFreeze(this Pickable pickable) { if (Object.op_Implicit((Object)(object)pickable.m_nview) && pickable.m_nview.IsValid() && Object.op_Implicit((Object)(object)ZNet.instance)) { long num = pickable.m_nview.GetZDO().GetLong(SeasonsVars.s_cropStartedFreezingHash, 0L); if (num <= 0) { return 0.0; } float num2 = Seasons.secondsToFreezeForCropInWinter.Value; if (num2 % 60f == 0f) { num2 -= 2f; } return (new DateTime(num).AddSeconds(num2) - ZNet.instance.GetTime()).TotalSeconds; } return 0.0; } public static bool CheckForPerishInWinter(this Pickable pickable) { if (!pickable.ShouldBePickedInWinter()) { pickable.SetFreezing(freezing: false); return false; } if (Seasons.secondsToFreezeForCropInWinter.Value > 0f) { pickable.SetFreezing(freezing: true); } if (pickable.IsFreezingToDeath()) { return false; } ((MonoBehaviour)pickable).StartCoroutine(Seasons.PickableSetPickedInWinter(pickable)); return true; } public static void SetFreezing(this Pickable pickable, bool freezing) { if (!Object.op_Implicit((Object)(object)pickable.m_nview) || !pickable.m_nview.IsValid() || !Object.op_Implicit((Object)(object)ZNet.instance)) { return; } ZDO zDO = pickable.m_nview.GetZDO(); if (zDO != null) { if (freezing && zDO.GetLong(SeasonsVars.s_cropStartedFreezingHash, 0L) == 0L && Seasons.seasonState.GetCurrentSeason() == Seasons.Season.Winter && Seasons.seasonState.GetCurrentDay() >= Seasons.cropsDiesAfterSetDayInWinter.Value) { zDO.Set(SeasonsVars.s_cropStartedFreezingHash, ZNet.instance.GetTime().Ticks); } else if (!freezing) { zDO.Set(SeasonsVars.s_cropStartedFreezingHash, 0L); } } } public static bool IsIgnored(this Pickable pickable) { return (Object)(object)pickable.m_nview == (Object)null || !pickable.m_nview.IsValid() || (pickable.m_nview.HasOwner() && !pickable.m_nview.IsOwner()) || !((MonoBehaviour)(object)pickable).ControlPlantGrowth() || ((MonoBehaviour)(object)pickable).IsIgnoredPosition(); } public static string GetColdStatus(this Pickable pickable) { if (((MonoBehaviour)(object)pickable).ShouldSurviveWinter()) { return "$seasons_plant_frost_resistant"; } if (((MonoBehaviour)(object)pickable).ProtectedWithHeat()) { return "$seasons_plant_heat_protected"; } if (pickable.SurvivedCurrentWinter()) { return "$seasons_plant_survived_winter"; } double secondsToFreeze = pickable.GetSecondsToFreeze(); if (secondsToFreeze != 0.0 && Seasons.secondsToFreezeForCropInWinter.Value > 0f) { if (secondsToFreeze > 0.0) { return "$seasons_plant_is_freezing\n" + Seasons.FromPercent(secondsToFreeze / (double)Seasons.secondsToFreezeForCropInWinter.Value); } return "$seasons_plant_is_frozen"; } if (Seasons.seasonState.GetCurrentDay() > Seasons.cropsDiesAfterSetDayInWinter.Value) { return "$seasons_plant_will_perish"; } return "$seasons_plant_is_exposed"; } public static bool ControlPlantGrowth(this MonoBehaviour behaviour) { return Seasons.ControlPlantGrowth(((Component)behaviour).gameObject); } public static bool ShouldSurviveWinter(this MonoBehaviour behaviour) { return Seasons.PlantWillSurviveWinter(((Component)behaviour).gameObject); } public static bool IsIgnoredPosition(this MonoBehaviour behaviour) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Seasons.IsIgnoredPosition(((Component)behaviour).transform.position); } public static bool IsProtectedPosition(this MonoBehaviour behaviour) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Seasons.IsProtectedPosition(((Component)behaviour).transform.position); } public static bool ProtectedWithHeat(this MonoBehaviour behaviour) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return Seasons.ProtectedWithHeat(((Component)behaviour).transform.position); } } public static class TerrainDecultivation { private sealed class FailedAttempt { public uint Revision; public int WorldDay; } [HarmonyPatch(typeof(TerrainComp), "Update")] private static class TerrainComp_Update_DecultivateOwnedTerrain { private static void Prefix(TerrainComp __instance) { if (!SeasonState.IsActive || !ZoneSystemVariantController.IsTimeToDecultivateGround() || !__instance.m_initialized || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner()) { return; } ZDO zDO = __instance.m_nview.GetZDO(); int currentWorldDay = Seasons.seasonState.GetCurrentWorldDay(); if (!IsDecultivationDue(zDO, currentWorldDay, Seasons.seasonState.GetYearLengthInDays())) { return; } WorldGenerator instance = WorldGenerator.instance; if (instance == null) { return; } World world = instance.m_world; bool? obj; if (world == null) { obj = null; } else { AltBiomeWorldData biomeData = world.m_biomeData; obj = ((biomeData != null) ? new bool?(biomeData.IsReady) : ((bool?)null)); } bool? flag = obj; if (flag != true || (failedAttempts.TryGetValue(__instance, out var value) && value.Revision == zDO.DataRevision && value.WorldDay == currentWorldDay)) { return; } if (TryDecultivateGround(zDO, out var _)) { zDO.Set(SeasonsVars.s_terrainDecultivated, currentWorldDay, false); failedAttempts.Remove(__instance); return; } FailedAttempt value2 = failedAttempts.GetValue(__instance, (TerrainComp _) => new FailedAttempt()); value2.Revision = zDO.DataRevision; value2.WorldDay = currentWorldDay; } } private static ConditionalWeakTable<TerrainComp, FailedAttempt> failedAttempts = new ConditionalWeakTable<TerrainComp, FailedAttempt>(); public static int terrainCompVersion; public static int m_operations; public static Vector3 m_lastOpPoint; public static float m_lastOpRadius; public static bool[] m_modifiedHeight; public static float[] m_levelDelta; public static float[] m_smoothDelta; public static bool[] m_modifiedPaint; public static Color[] m_paintMask; public static void ResetRuntimeState() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) failedAttempts = new ConditionalWeakTable<TerrainComp, FailedAttempt>(); terrainCompVersion = 0; m_operations = 0; m_lastOpPoint = Vector3.zero; m_lastOpRadius = 0f; m_modifiedHeight = null; m_levelDelta = null; m_smoothDelta = null; m_modifiedPaint = null; m_paintMask = null; } public static bool DecultivateGround(ZDO zdo) { bool changed; return TryDecultivateGround(zdo, out changed) && changed; } internal static bool IsDecultivationDue(ZDO zdo, int worldDay, int yearLength) { int num = default(int); return !zdo.GetInt(SeasonsVars.s_terrainDecultivated, ref num) || Math.Abs((long)worldDay - (long)num) >= yearLength; } internal static bool TryDecultivateGround(ZDO zdo, out bool changed) { changed = false; try { return DecultivateGroundCore(zdo, out changed); } catch (Exception arg) { changed = false; Seasons.LogWarning($"Seasons could not process terrain decultivation; the processed day was not advanced:\n{arg}"); return false; } } private static bool DecultivateGroundCore(ZDO zdo, out bool changed) { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Expected I4, but got Unknown //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Expected I4, but got Unknown //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Expected I4, but got Unknown //IL_04f8: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Expected I4, but got Unknown //IL_0540: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Expected O, but got Unknown //IL_06bf: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_05bf: Unknown result type (might be due to invalid IL or missing references) //IL_05c6: Invalid comparison between Unknown and I4 //IL_063e: Unknown result type (might be due to invalid IL or missing references) //IL_0645: Unknown result type (might be due to invalid IL or missing references) //IL_0666: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) //IL_05cc: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_0611: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0625: Unknown result type (might be due to invalid IL or missing references) //IL_062c: Invalid comparison between Unknown and I4 changed = false; if (zdo != null && zdo.IsValid() && (!zdo.HasOwner() || zdo.IsOwner())) { WorldGenerator instance = WorldGenerator.instance; if (instance != null) { World world = instance.m_world; bool? obj; if (world == null) { obj = null; } else { AltBiomeWorldData biomeData = world.m_biomeData; obj = ((biomeData != null) ? new bool?(biomeData.IsReady) : ((bool?)null)); } bool? flag = obj; if (flag == true) { byte[] byteArray = zdo.GetByteArray(ZDOVars.s_TCData, (byte[])null); if (byteArray == null) { return false; } ZPackage val = new ZPackage(Utils.Decompress(byteArray)); terrainCompVersion = val.ReadInt(); if (terrainCompVersion != 1) { Seasons.LogWarning("Seasons cannot decultivate ground: unsupported terrain compiler data version."); return false; } bool flag2 = false; m_operations = val.ReadInt(); m_lastOpPoint = val.ReadVector3(); m_lastOpRadius = val.ReadSingle(); int num = val.ReadInt(); TerrainComp val2 = TerrainComp.s_instances.Find((TerrainComp compiler) => (Object)(object)compiler != (Object)null && (Object)(object)compiler.m_nview != (Object)null && compiler.m_nview.GetZDO() == zdo); object obj2; if (!((Object)(object)val2 != (Object)null)) { ZoneSystem instance2 = ZoneSystem.instance; if (instance2 == null) { obj2 = null; } else { GameObject zonePrefab = instance2.m_zonePrefab; obj2 = ((zonePrefab != null) ? zonePrefab.GetComponentInChildren<Heightmap>(true) : null); } } else { obj2 = val2.m_hmap; } Heightmap val3 = (Heightmap)obj2; if ((Object)(object)val3 == (Object)null || num != (val3.m_width + 1) * (val3.m_width + 1)) { Seasons.LogWarning("Seasons cannot decultivate ground: the terrain dimensions could not be resolved safely."); return false; } m_modifiedHeight = new bool[num]; m_levelDelta = new float[num]; m_smoothDelta = new float[num]; for (int num2 = 0; num2 < m_modifiedHeight.Length; num2++) { m_modifiedHeight[num2] = val.ReadBool(); if (m_modifiedHeight[num2]) { m_levelDelta[num2] = val.ReadSingle(); m_smoothDelta[num2] = val.ReadSingle(); } else { m_levelDelta[num2] = 0f; m_smoothDelta[num2] = 0f; } } int num3 = val.ReadInt(); if (num3 != num && num3 != val3.m_width * val3.m_width) { Seasons.LogWarning("Seasons cannot decultivate ground: unsupported terrain paint grid dimensions."); return false; } m_modifiedPaint = new bool[num3]; m_paintMask = (Color[])(object)new Color[num3]; for (int num4 = 0; num4 < m_modifiedPaint.Length; num4++) { m_modifiedPaint[num4] = val.ReadBool(); if (m_modifiedPaint[num4]) { Color val4 = new Color { r = val.ReadSingle(), g = val.ReadSingle(), b = val.ReadSingle(), a = val.ReadSingle() }; m_paintMask[num4] = val4; } else { m_paintMask[num4] = Color.black; } } if (val.GetPos() != val.Size()) { Seasons.LogWarning("Seasons cannot decultivate ground: unexpected trailing terrain data."); return false; } int num5 = val3.m_width + 1; if (num3 != num) { bool[] modifiedPaint = m_modifiedPaint; Color[] paintMask = m_paintMask; m_modifiedPaint = new bool[num]; m_paintMask = (Color[])(object)new Color[num]; for (int num6 = 0; num6 < num5; num6++) { for (int num7 = 0; num7 < num5; num7++) { int num8 = num6 * num5 + num7; int num9 = Math.Min(num6, val3.m_width - 1) * val3.m_width + Math.Min(num7, val3.m_width - 1); m_modifiedPaint[num8] = modifiedPaint[num9]; m_paintMask[num8] = paintMask[num9]; } } } Vector3 position = zdo.GetPosition(); int num10 = val3.m_width / 2; float scale = val3.m_scale; float num11 = (float)val3.m_width * scale * 0.5f; Biome[] corners = (Biome[])(object)new Biome[4] { (Biome)(int)WorldGenerator.instance.GetBiomeSector(position.x - num11, position.z - num11, false).Biome, (Biome)(int)WorldGenerator.instance.GetBiomeSector(position.x + num11, position.z - num11, false).Biome, (Biome)(int)WorldGenerator.instance.GetBiomeSector(position.x - num11, position.z + num11, false).Biome, (Biome)(int)WorldGenerator.instance.GetBiomeSector(position.x + num11, position.z + num11, false).Biome }; for (int num12 = 0; num12 < m_modifiedPaint.Length; num12++) { if (m_modifiedPaint[num12]) { Color val5 = m_paintMask[num12]; float num13 = position.x + ((float)(num12 % num5 - num10) - 0.5f) * scale; float num14 = position.z + ((float)(num12 / num5 - num10) - 0.5f) * scale; float num15 = Mathf.Min(val5.r, val5.b); if (!(val5.g <= num15) && !WorldGenerator.IsDeepnorth(num13, num14) && (int)WorldGenerator.instance.GetBiomeSector(num13, num14, false).Biome != 64 && !IsNorthernTerrain(corners, (num13 - position.x) / (num11 * 2f) + 0.5f, (num14 - position.z) / (num11 * 2f) + 0.5f) && (!((Object)(object)val2 != (Object)null) || (int)val3.GetBiome(new Vector3(num13, position.y, num14), 0.02f, false) != 64)) { val5.r = Mathf.Max(val5.r, val5.g); val5.g = num15; m_paintMask[num12] = val5; flag2 = true; } } } if (!flag2) { return true; } ZPackage val6 = new ZPackage(); val6.Write(terrainCompVersion); val6.Write(m_operations); val6.Write(m_lastOpPoint); val6.Write(m_lastOpRadius); val6.Write(m_modifiedHeight.Length); for (int num16 = 0; num16 < m_modifiedHeight.Length; num16++) { val6.Write(m_modifiedHeight[num16]); if (m_modifiedHeight[num16]) { val6.Write(m_levelDelta[num16]); val6.Write(m_smoothDelta[num16]); } } val6.Write(m_modifiedPaint.Length); for (int num17 = 0; num17 < m_modifiedPaint.Length; num17++) { val6.Write(m_modifiedPaint[num17]); if (m_modifiedPaint[num17]) { val6.Write(m_paintMask[num17].r); val6.Write(m_paintMask[num17].g); val6.Write(m_paintMask[num17].b); val6.Write(m_paintMask[num17].a); } } byte[] array = Utils.Compress(val6.GetArray()); zdo.Set(ZDOVars.s_TCData, array); if ((Object)(object)val2 != (Object)null) { val2.CheckLoad(); val2.m_lastHash = val2.ComputePaintMaskHash(); } changed = true; return true; } } } return false; } private static bool IsNorthernTerrain(Biome[] corners, float x, float y) { Vector4 val = default(Vector4); ((Vector4)(ref val))..ctor(Heightmap.Distance(x, y, 0f, 0f), Heightmap.Distance(x, y, 1f, 0f), Heightmap.Distance(x, y, 0f, 1f), Heightmap.Distance(x, y, 1f, 1f)); float num = 0f; for (int i = 0; i < corners.Length; i++) { if ((int)corners[i] == 64) { num += ((Vector4)(ref val))[i]; } } if (num == 0f) { return false; } for (int j = 0; j < corners.Length; j++) { if ((int)corners[j] == 64) { continue; } float num2 = 0f; for (int k = 0; k < corners.Length; k++) { if ((int)corners[k] == (int)corners[j]) { num2 += ((Vector4)(ref val))[k]; } } if (num2 > num) { return false; } } return true; } } [Serializable] public class CachedData { [Serializable] public class TextureData { public string name; public byte[] originalPNG; public TextureProperties properties; public Dictionary<Seasons.Season, Dictionary<int, byte[]>> variants = new Dictionary<Seasons.Season, Dictionary<int, byte[]>>(); public bool Initialized() { Dictionary<int, byte[]> values; byte[] value; return properties != null && Enum.GetValues(typeof(Seasons.Season)).Cast<Seasons.Season>().All((Seasons.Season season) => variants.TryGetValue(season, out values) && Enumerable.Range(0, 4).All((int variant) => values.TryGetValue(variant, out value) && value != null && value.Length != 0)); } public TextureData(TextureVariants textureVariants) { if (textureVariants == null) { return; } originalPNG = textureVariants.originalPNG; name = textureVariants.originalName; properties = textureVariants.properties; foreach (KeyValuePair<Seasons.Season, Dictionary<int, Texture2D>> season in textureVariants.seasons) { variants.Add(season.Key, new Dictionary<int, byte[]>()); foreach (KeyValuePair<int, Texture2D> item in season.Value) { variants[season.Key].Add(item.Key, ImageConversion.EncodeToPNG(item.Value)); } } } public TextureData(DirectoryInfo texDirectory) { FileInfo[] files = texDirectory.GetFiles("properties.json"); if (files.Length != 0) { properties = JsonUtility.FromJson<TextureProperties>(File.ReadAllText(files[0].FullName)); } foreach (Seasons.Season value in Enum.GetValues(typeof(Seasons.Season))) { variants.Add(value, new Dictionary<int, byte[]>()); for (int i = 0; i < 4; i++) { FileInfo[] files2 = texDirectory.GetFiles(SeasonFileName(value, i)); if (files2.Length != 0) { variants[value].Add(i, File.ReadAllBytes(files2[0].FullName)); } } } } } internal const string cacheSubdirectory = "Cache"; internal const string prefabCacheCommonFile = "cache.bin"; internal const string prefabCacheFileName = "cache.json"; internal const string texturesDirectory = "textures"; internal const string originalPostfix = ".orig.png"; internal const string texturePropertiesFileName = "properties.json"; public Dictionary<string, PrefabController> controllers = new Dictionary<string, PrefabController>(); public Dictionary<int, TextureData> textures = new Dictionary<int, TextureData>(); public uint revision = 0u; public CachedData(uint revision) { this.revision = revision; } public bool Initialized() { Dictionary<string, PrefabController> dictionary = controllers; int result; if (dictionary != null && dictionary.Count > 0) { Dictionary<int, TextureData> dictionary2 = textures; if (dictionary2 != null && dictionary2.Count > 0) { result = (textures.Values.All((TextureData texture) => texture?.Initialized() ?? false) ? 1 : 0); goto IL_0061; } } result = 0; goto IL_0061; IL_0061: return (byte)result != 0; } public void SaveOnDisk() { if (Initialized()) { if (Seasons.cacheStorageFormat.Value == Seasons.CacheFormat.Binary) { SaveToBinary(); return; } if (Seasons.cacheStorageFormat.Value == Seasons.CacheFormat.Json) { SaveToJSON(); return; } SaveToJSON(); SaveToBinary(); } } public void LoadFromDisk() { try { if (Seasons.cacheStorageFormat.Value == Seasons.CacheFormat.Json) { LoadFromJSON(); } else { LoadFromBinary(); } } catch (Exception arg) { controllers = new Dictionary<string, PrefabController>(); textures = new Dictionary<int, TextureData>(); Seasons.LogWarning($"Unable to load seasonal texture cache:\n{arg}"); } } private void SaveToJSON() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown string text = CacheDirectory(); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "cache.json"); File.WriteAllText(text2, JsonConvert.SerializeObject((object)controllers, (Formatting)1, new JsonSerializerSettings { NullValueHandling = (NullValueHandling)1, DefaultValueHandling = (DefaultValueHandling)1 })); string text3 = Path.Combine(text, "textures"); Seasons.LogInfo("Saved cache file " + text2); foreach (KeyValuePair<int, TextureData> texture in textures) { string text4 = Path.Combine(text3, texture.Key.ToString()); Directory.CreateDirectory(text4); File.WriteAllBytes(Path.Combine(text4, texture.Value.name + ".orig.png"), texture.Value.originalPNG); File.WriteAllText(Path.Combine(text4, "properties.json"), JsonUtility.ToJson((object)texture.Value.properties, true)); foreach (KeyValuePair<Seasons.Season, Dictionary<int, byte[]>> variant in texture.Value.variants) { foreach (KeyValuePair<int, byte[]> item in variant.Value) { File.WriteAllBytes(Path.Combine(text4, SeasonFileName(variant.Key, item.Key)), item.Value); } } } Seasons.LogInfo($"Saved {textures.Count} textures at {text3}"); } private void LoadFromJSON() { string text = CacheDirectory(); DirectoryInfo directoryInfo = new DirectoryInfo(text); if (!directoryInfo.Exists) { return; } FileInfo[] files = directoryInfo.GetFiles("cache.json"); if (files.Length == 0) { Seasons.LogInfo("File not found: " + Path.Combine(text, "cache.json")); return; } try { controllers = JsonConvert.DeserializeObject<Dictionary<string, PrefabController>>(File.ReadAllText(files[0].FullName)); } catch (Exception arg) { Seasons.LogWarning($"Error loading JSON cache data from {files[0].FullName}\n{arg}"); return; } DirectoryInfo[] directories = directoryInfo.GetDirectories("textures"); if (directories.Length == 0) { return; } DirectoryInfo[] directories2 = directories[0].GetDirectories(); foreach (DirectoryInfo directoryInfo2 in directories2) { if (int.TryParse(directoryInfo2.Name, out var result) && !textures.ContainsKey(result)) { TextureData textureData = new TextureData(directoryInfo2); if (textureData.Initialized()) { textures.Add(result, textureData); } } } } private void SaveToBinary() { string text = CacheDirectory(); Directory.CreateDirectory(text); using (FileStream fileStream = new FileStream(Path.Combine(text, "cache.bin"), FileMode.Create)) { BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(fileStream, this); fileStream.Dispose(); } Seasons.LogInfo("Saved cache file " + Path.Combine(text, "cache.bin")); } private void LoadFromBinary() { string path = CacheDirectory(); string text = Path.Combine(path, "cache.bin"); if (!File.Exists(text)) { Seasons.LogInfo("File not found: " + text); return; } try { using FileStream fileStream = new FileStream(text, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryFormatter binaryFormatter = new BinaryFormatter(); CachedData cachedData = (CachedData)binaryFormatter.Deserialize(fileStream); fileStream.Dispose(); DictionaryExt.Copy<string, PrefabController>(controllers, cachedData.controllers); DictionaryExt.Copy<int, TextureData>(textures, cachedData.textures); cachedData = null; } catch (Exception arg) { Seasons.LogWarning($"Error loading binary cache data from {text}:\n {arg}"); } } public string CacheDirectory() { return Path.Combine(Seasons.cacheDirectory, revision.ToString()); } public static string SeasonFileName(Seasons.Season season, int variant) { return $"{season}_{variant + 1}.png"; } } [Serializable] public class PrefabController { [Serializable] public class CachedMaterial { public string name = string.Empty; public string shaderName = string.Empty; public Dictionary<string, int> textureProperties = new Dictionary<string, int>(); public Dictionary<string, string[]> colorVariants = new Dictionary<string, string[]>(); public CachedMaterial() { } public CachedMaterial(string materialName, string shader, string propertyName, int textureID) { name = materialName; shaderName = shader; AddTexture(propertyName, textureID); } public CachedMaterial(string materialName, string shader, string propertyName, Color[] colors) { name = materialName; shaderName = shader; AddColors(propertyName, colors); } public void AddTexture(string propertyName, int textureID) { if (!textureProperties.ContainsKey(propertyName)) { textureProperties.Add(propertyName, textureID); } } public void AddColors(string propertyName, Color[] colors) { List<string> vec = new List<string>(); CollectionExtensions.Do<Color>((IEnumerable<Color>)colors, (Action<Color>)delegate(Color x) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) vec.Add("#" + ColorUtility.ToHtmlStringRGBA(x)); }); if (!colorVariants.ContainsKey(propertyName)) { colorVariants.Add(propertyName, vec.ToArray()); } } } [Serializable] public class CachedRenderer { public string name = string.Empty; public string type = string.Empty; public Dictionary<string, CachedMaterial> materials = new Dictionary<string, CachedMaterial>(); public CachedRenderer() { } public CachedRenderer(string rendererName, string rendererType) { name = rendererName; type = rendererType; } public bool Initialized() { return materials.Any((KeyValuePair<string, CachedMaterial> m) => m.Value.textureProperties.Count > 0 || m.Value.colorVariants.Count > 0); } public void AddMaterialTexture(Material material, string propertyName, int textureID) { if (!materials.TryGetValue(((Object)material).name, out var value)) { materials.Add(((Object)material).name, new CachedMaterial(((Object)material).name, ((Object)material.shader).name, propertyName, textureID)); } else { value.AddTexture(propertyName, textureID); } } public void AddMaterialColors(Material material, string propertyName, Color[] colors) { if (!materials.TryGetValue(((Object)material).name, out var value)) { materials.Add(((Object)material).name, new CachedMaterial(((Object)material).name, ((Object)material.shader).name, propertyName, colors)); } else { value.AddColors(propertyName, colors); } } } public Dictionary<string, Dictionary<int, List<CachedRenderer>>> lodsInHierarchy = new Dictionary<string, Dictionary<int, List<CachedRenderer>>>(); public Dictionary<int, List<CachedRenderer>> lodLevelMaterials = new Dictionary<int, List<CachedRenderer>>(); public Dictionary<string, CachedRenderer> renderersInHierarchy = new Dictionary<string, CachedRenderer>(); public CachedRenderer cachedRenderer; public Dictionary<string, string[]> particleSystemStartColors; [NonSerialized] public long elapsedTicks = 0L; public bool Initialized() { return lodsInHierarchy.Count > 0 || lodLevelMaterials.Count > 0 || renderersInHierarchy.Count > 0 || cachedRenderer != null || particleSystemStartColors != null; } public override string ToString() { return ((cachedRenderer == null) ? "" : " 1 main renderer") + ((particleSystemStartColors == null) ? "" : " 1 particles start color") + " " + ((lodsInHierarchy.Count > 0) ? $" {lodsInHierarchy.Count} LOD groups" : "") + ((lodLevelMaterials.Count > 0) ? $" {lodLevelMaterials.Count} LODs" : "") + ((renderersInHierarchy.Count > 0) ? $" {renderersInHierarchy.Count} renderersInHierarchy" : "") + ((elapsedTicks > 0) ? $" in {(double)elapsedTicks / (double)Stopwatch.Frequency * 1000.0:F2} ms" : ""); } } public class SeasonalTextureVariants { public Dictionary<string, PrefabController> controllers = new Dictionary<string, PrefabController>(); public Dictionary<int, TextureVariants> textures = new Dictionary<int, TextureVariants>(); public uint revision = 0u; private bool m_reloading; private static readonly object s_diskLock = new object(); public bool IsUpdating => m_reloading || TextureCachingController.InProcess; public void Dispose() { foreach (TextureVariants value in textures.Values) { value.Dispose(); } textures.Clear(); controllers.Clear(); } public bool Initialize(bool force = false) { if (!force && Initialized()) { return true; } if (m_reloading || TextureCachingController.InProcess) { return false; } PrefabVariantController.instance?.RevertPrefabsState(); ClutterVariantController.Instance?.RevertColors(); Dispose(); revision = SeasonalTexturePrefabCache.GetRevision(); CachedData cachedData = new CachedData(revision); if (force) { lock (s_diskLock) { if (Directory.Exists(cachedData.CacheDirectory())) { Directory.Delete(cachedData.CacheDirectory(), recursive: true); } } } else { lock (s_diskLock) { cachedData.LoadFromDisk(); } } if (cachedData.Initialized()) { DictionaryExt.Copy<string, PrefabController>(controllers, cachedData.controllers); foreach (KeyValuePair<int, CachedData.TextureData> texture in cachedData.textures) { TextureVariants textureVariants = new TextureVariants(texture.Value); if (!textureVariants.Initialized()) { textureVariants.Dispose(); } else { textures.Add(texture.Key, textureVariants); } } Seasons.LogInfo($"Loaded from cache revision:{revision} controllers:{controllers.Count} textures:{textures.Count}"); return Initialized(); } if (!Seasons.runTextureCachingSync.Value) { TextureCachingController.StartCaching(this); } else { SeasonalTexturePrefabCache.SetCurrentTextureVariants(this); Seasons.StartCoroutineSync(SeasonalTexturePrefabCache.FillWithGameData()); Seasons.StartCoroutineSync(SaveCacheOnDisk()); } return Initialized(); } public IEnumerator SaveCacheOnDisk() { if (!Initialized()) { yield break; } CachedData cachedData = new CachedData(revision); foreach (KeyValuePair<int, TextureVariants> texVariants in textures) { CachedData.TextureData texData = new CachedData.TextureData(texVariants.Value); if (texData.Initialized()) { cachedData.textures.Add(texVariants.Key, texData); } } DictionaryExt.Copy<string, PrefabController>(cachedData.controllers, controllers); Exception saveError = null; Thread internalThread = new Thread((ThreadStart)delegate { try { lock (s_diskLock) { if (Directory.Exists(cachedData.CacheDirectory())) { Directory.Delete(cachedData.CacheDirectory(), recursive: true); } cachedData.SaveOnDisk(); } } catch (Exception ex) { saveError = ex; } }) { IsBackground = true }; internalThread.Start(); while (internalThread.IsAlive) { yield return Seasons.waitForFixedUpdate; } if (saveError != null) { Seasons.LogWarning($"Unable to save seasonal texture cache:\n{saveError}"); } ApplyTexturesToGPU(); } public bool Initialized() { return controllers.Count > 0 && textures.Count > 0; } public void ApplyTexturesToGPU() { foreach (KeyValuePair<int, TextureVariants> texture in textures) { texture.Value.ApplyTextures(); } } public IEnumerator ReloadCache() { if (m_reloading || TextureCachingController.InProcess) { yield break; } m_reloading = true; ZoneSystem sourceZone = ZoneSystem.instance; try { CachedData cachedData = new CachedData(SeasonalTexturePrefabCache.GetRevision()); Thread reader = new Thread((ThreadStart)delegate { lock (s_diskLock) { cachedData.LoadFromDisk(); } }) { IsBackground = true }; reader.Start(); while (reader.IsAlive) { yield return Seasons.waitForFixedUpdate; } if (!Object.op_Implicit((Object)(object)sourceZone) || (Object)(object)sourceZone != (Object)(object)ZoneSystem.instance) { yield break; } if (!cachedData.Initialized()) { m_reloading = false; yield return RebuildCache(); yield break; } Stopwatch stopwatch = Stopwatch.StartNew(); List<TextureVariants> oldTextures = new List<TextureVariants>(textures.Values); Dictionary<int, TextureVariants> loadedTextures = new Dictionary<int, TextureVariants>(); foreach (KeyValuePair<int, CachedData.TextureData> texData in cachedData.textures) { TextureVariants variants = new TextureVariants(texData.Value); if (variants.Initialized()) { loadedTextures.Add(texData.Key, variants); } else { variants.Dispose(); } } if (loadedTextures.Count == 0) { m_reloading = false; yield return RebuildCache(); yield break; } PrefabVariantController.instance?.RevertPrefabsState(); ClutterVariantController.Instance?.RevertColors(); controllers.Clear(); textures.Clear(); revision = cachedData.revision; DictionaryExt.Copy<string, PrefabController>(controllers, cachedData.controllers); DictionaryExt.Copy<int, TextureVariants>(textures, loadedTextures); try { ClutterVariantController.Reinitialize(); PrefabVariantController.ReinitializePrefabVariants(); } finally { foreach (TextureVariants oldTexture in oldTextures) { oldTexture.Dispose(); } } m_reloading = false; yield return Seasons.waitForFixedUpdate; PrefabVariantController.UpdatePrefabColors(); ClutterVariantController.Instance?.UpdateColors(); Seasons.LogInfo($"Loaded from cache revision:{revision} controllers:{controllers.Count} textures:{textures.Count} in {stopwatch.Elapsed.TotalSeconds,-4:F2} seconds"); } finally { m_reloading = false; if (Object.op_Implicit((Object)(object)sourceZone) && (Object)(object)sourceZone == (Object)(object)ZoneSystem.instance) { SeasonalTexturePrefabCache.SetCurrentTextureVariants(this); } } } public IEnumerator RebuildCache() { if (m_reloading || TextureCachingController.InProcess) { yield break; } m_reloading = true; ZoneSystem sourceZone = ZoneSystem.instance; SeasonalTextureVariants newTexturesVariants = new SeasonalTextureVariants(); try { SeasonalTexturePrefabCache.SetCurrentTextureVariants(newTexturesVariants); PrefabVariantController.instance?.RevertPrefabsState(); ClutterVariantController.Instance?.RevertColors(); yield return Seasons.waitForFixedUpdate; if (!Object.op_Implicit((Object)(object)sourceZone) || (Object)(object)sourceZone != (Object)(object)ZoneSystem.instance) { yield break; } yield return SeasonalTexturePrefabCache.FillWithGameData(); if (!Object.op_Implicit((Object)(object)sourceZone) || (Object)(object)sourceZone != (Object)(object)ZoneSystem.instance || !newTexturesVariants.Initialized()) { yield break; } Stopwatch stopwatch = Stopwatch.StartNew(); List<TextureVariants> oldTextures = new List<TextureVariants>(textures.Values); controllers.Clear(); textures.Clear(); revision = newTexturesVariants.revision; DictionaryExt.Copy<string, PrefabController>(controllers, newTexturesVariants.controllers); DictionaryExt.Copy<int, TextureVariants>(textures, newTexturesVariants.textures); newTexturesVariants.controllers.Clear(); newTexturesVariants.textures.Clear(); SeasonalTexturePrefabCache.SetCurrentTextureVariants(this); try { ClutterVariantController.Reinitialize(); PrefabVariantController.ReinitializePrefabVariants(); } finally { foreach (TextureVariants oldTexture in oldTextures) { oldTexture.Dispose(); } } yield return SaveCacheOnDisk(); yield return Seasons.waitForFixedUpdate; if (Object.op_Implicit((Object)(object)sourceZone) && !((Object)(object)sourceZone != (Object)(object)ZoneSystem.instance)) { m_reloading = false; PrefabVariantController.UpdatePrefabColors(); ClutterVariantController.Instance?.UpdateColors(); Seasons.LogInfo($"Colors reinitialized in {stopwatch.Elapsed.TotalSeconds,-4:F2} seconds"); Seasons.LogInfo("Cache rebuild ended"); } } finally { newTexturesVariants.Dispose(); m_reloading = false; if (Object.op_Implicit((Object)(object)sourceZone) && (Object)(object)sourceZone == (Object)(object)ZoneSystem.instance) { SeasonalTexturePrefabCache.SetCurrentTextureVariants(this); } } } } public class TextureVariants { public Texture2D original; public string originalName; public byte[] originalPNG; public TextureProperties properties; public Dictionary<Seasons.Season, Dictionary<int, Texture2D>> seasons = new Dictionary<Seasons.Season, Dictionary<int, Texture2D>>(); public TextureVariants(CachedData.TextureData texData) { if (texData == null) { return; } properties = texData.properties; if (properties == null) { return; } foreach (Seasons.Season value3 in Enum.GetValues(typeof(Seasons.Season))) { if (!texData.variants.TryGetValue(value3, out var value)) { continue; } for (int i = 0; i < 4; i++) { if (value.TryGetValue(i, out var value2)) { Texture2D val = properties.CreateTexture(); if (ImageConversion.LoadImage(val, value2, true)) { AddVariant(value3, i, val); } else { Object.Destroy((Object)(object)val); } } } } } public TextureVariants(Texture texture) { SetOriginalTexture(texture); } public void SetOriginalTexture(Texture texture) { if (texture is Texture2D) { original = (Texture2D)(object)((texture is Texture2D) ? texture : null); properties = new TextureProperties((Texture2D)(object)((texture is Texture2D) ? texture : null)); originalName = ((Object)original).name; } } public void Dispose() { foreach (Dictionary<int, Texture2D> value in seasons.Values) { foreach (Texture2D value2 in value.Values) { if (Object.op_Implicit((Object)(object)value2)) { Object.Destroy((Object)(object)value2); } } } seasons.Clear(); } public bool Initialized() { Dictionary<int, Texture2D> variants; Texture2D value; return properties != null && Enum.GetValues(typeof(Seasons.Season)).Cast<Seasons.Season>().All((Seasons.Season season) => seasons.TryGetValue(season, out variants) && Enumerable.Range(0, 4).All((int variant) => variants.TryGetValue(variant, out value) && Object.op_Implicit((Object)(object)value))); } public bool HaveOriginalTexture() { return Object.op_Implicit((Object)(object)original); } public void ApplyTextures() { foreach (KeyValuePair<Seasons.Season, Dictionary<int, Texture2D>> season in seasons) { foreach (KeyValuePair<int, Texture2D> item in season.Value) { item.Value.Apply(true, true); } } } public void AddVariant(Seasons.Season season, int variant, Texture2D tex) { if (!seasons.TryGetValue(season, out var value)) { value = new Dictionary<int, Texture2D>(); seasons.Add(season, value); } if (!value.ContainsKey(variant)) { value.Add(variant, tex); } } public Texture2D GetSeasonalVariant(Seasons.Season season, int variant) { if (CustomTextures.HaveCustomTexture(originalName, season, variant, properties, out var texture)) { return texture; } if (seasons.TryGetValue(season, out var value) && value.TryGetValue(variant, out var value2)) { return value2; } return original; } } [Serializable] public class TextureProperties { public TextureFormat format = (TextureFormat)5; public int mipmapCount = 1; public TextureWrapMode wrapMode = (TextureWrapMode)0; public FilterMode filterMode = (FilterMode)0; public int anisoLevel = 1; public float mipMapBias = 0f; public int width = 2; public int height = 2; public TextureProperties(Texture2D tex) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) mipmapCount = ((Texture)tex).mipmapCount; wrapMode = ((Texture)tex).wrapMode; filterMode = ((Texture)tex).filterMode; anisoLevel = ((Texture)tex).anisoLevel; mipMapBias = ((Texture)tex).mipMapBias; width = ((Texture)tex).width; height = ((Texture)tex).height; } public Texture2D CreateTexture() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown return new Texture2D(width, height, format, mipmapCount, false) { filterMode = filterMode, anisoLevel = anisoLevel, mipMapBias = mipMapBias, wrapMode = wrapMode }; } } public class SE_SummerHeat : SE_Stats { private const char DefaultBarSymbol = '▄'; private const float PartialSegmentEpsilon = 0.0001f; private static readonly StringBuilder TooltipBuilder = new StringBuilder(256); private float _damageTimer; public override void Setup(Character character) { StatusEffectHud.EnsureTimeTextRichText(); ((StatusEffect)this).m_name = "$seasons_status_summer_heat_name"; ((StatusEffect)this).m_tooltip = "$seasons_status_summer_heat_description"; if (((StatusEffect)this).m_icon == null) { ((StatusEffect)this).m_icon = Seasons.iconWarm ?? Seasons.iconSummer; } ((StatusEffect)this).m_ttl = 0f; ((StatusEffect)this).m_cooldownIcon = false; ((StatusEffect)this).m_flashIcon = false; ((SE_Stats)this).Setup(character); } public override void UpdateStatusEffect(float dt) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) ((SE_Stats)this).UpdateStatusEffect(dt); if (SummerHeat.IsReady && SummerHeat.IsMechanicActive) { Character character = ((StatusEffect)this).m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { float maxEffectFactor = SummerHeat.MaxEffectFactor; if (maxEffectFactor <= 0f) { _damageTimer = 0f; return; } _damageTimer += dt; if (_damageTimer < Mathf.Max(0.1f, Seasons.summerHeatDamageTickInterval.Value)) { return; } _damageTimer = 0f; float minSoftHpCap = SummerHeatUtils.GetMinSoftHpCap(); float num = Mathf.Lerp(1f, minSoftHpCap, maxEffectFactor); if (!(((Character)val).GetHealthPercentage() <= num) && (!Seasons.summerHeatDamageMaxOnly.Value || SummerHeat.CurrentZone == HeatZone.Max)) { float num2 = Mathf.Abs(Seasons.summerHeatDamageHealthPerTick.Value); if (!(num2 <= 0f)) { HitData val2 = new HitData(); val2.m_damage.m_damage = num2; val2.m_hitType = Seasons.summerHeatDamageHitType.Value; val2.m_point = ((Character)val).GetTopPoint(); ((Character)val).Damage(val2); } } return; } } _damageTimer = 0f; } public override string GetIconText() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!SummerHeat.IsReady || !SummerHeat.IsMechanicActive) { return string.Empty; } Seasons.SummerHeatDisplayMode value = Seasons.summerHeatDisplayMode.Value; if (1 == 0) { } string result = value switch { Seasons.SummerHeatDisplayMode.None => string.Empty, Seasons.SummerHeatDisplayMode.Bar => BuildBarText(), Seasons.SummerHeatDisplayMode.Percent => ColorizeText($"{SummerHeat.HeatPercent:0}%", GetHeatDisplayColor()), _ => BuildBarText(), }; if (1 == 0) { } return result; } public override string GetTooltipString() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) TooltipBuilder.Clear(); TooltipBuilder.Append("$seasons_status_summer_heat_description".Localize()).Append('\n').Append('\n'); TooltipBuilder.AppendFormat("{0}: {1}\n", "$seasons_status_summer_heat_current".Localize(), ColorizeText($"{SummerHeat.HeatPercent:0}%", GetHeatDisplayColor())); TooltipBuilder.AppendFormat("{0}: <color=orange>{1}</color>\n", "$seasons_status_summer_heat_zone".Localize(), GetZoneText(SummerHeat.CurrentZone).Localize()); TooltipBuilder.AppendFormat("{0}: <color=orange>{1}</color>\n", "$seasons_status_summer_heat_weather".Localize(), (SummerHeat.IsSunny ? "$seasons_status_summer_heat_sunny" : "$seasons_status_summer_heat_not_sunny").Localize()); TooltipBuilder.AppendFormat("{0}: <color=orange>{1}</color>\n", "$seasons_status_summer_heat_exposure".Localize(), GetExposureText().Localize()); string modifierSummary = GetModifierSummary(); if (!string.IsNullOrEmpty(modifierSummary)) { TooltipBuilder.Append(modifierSummary); } AppendActiveFactors(TooltipBuilder); if (SummerHeat.MaxEffectFactor > 0f) { float minSoftHpCap = SummerHeatUtils.GetMinSoftHpCap(); float num = Mathf.Lerp(1f, minSoftHpCap, SummerHeat.MaxEffectFactor) * 100f; TooltipBuilder.AppendFormat("<color=red>{0}</color>\n", string.Format("$seasons_status_summer_heat_cap_warning".Localize(), num.ToString("0"))); } AppendTechnicalInfo(TooltipBuilder); return TooltipBuilder.ToString(); } public override void ModifyHealthRegen(ref float regenMultiplier) { if (SummerHeat.IsMechanicActive) { ApplyMultiplier(ref regenMultiplier, GetHeatMultiplier(Seasons.summerHeatHealthRegenMultiplier.Value), regenStyle: true); } } public override void ModifyStaminaRegen(ref float staminaRegen) { if (SummerHeat.IsMechanicActive) { ApplyMultiplier(ref staminaRegen, GetHeatMultiplier(Seasons.summerHeatStaminaRegenMultiplier.Value), regenStyle: true); } } public override void ModifyEitrRegen(ref float eitrRegen) { if (SummerHeat.IsMechanicActive) { ApplyMultiplier(ref eitrRegen, GetHeatMultiplier(Seasons.summerHeatEitrRegenMultiplier.Value), regenStyle: true); } } public override void ModifyRunStaminaDrain(float baseDrain, ref float drain, Vector3 dir) { if (SummerHeat.IsMechanicActive) { drain += baseDrain * GetSignedModifier(Seasons.summerHeatStaminaUseMultiplier.Value); } } public override void ModifyAdrenaline(float baseValue, ref float use) { if (SummerHeat.IsMechanicActive) { use += baseValue * GetSignedModifier(Seasons.summerHeatAdrenalineMultiplier.Value); } } private static void ApplyMultiplier(ref float value, float multiplier, bool regenStyle) { if (!Mathf.Approximately(multiplier, 1f)) { if (regenStyle && multiplier > 1f) { value += multiplier - 1f; } else { value *= multiplier; } } } private string BuildBarText() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(Seasons.summerHeatBarSegments.Value, 1, 32); char barSymbol = GetBarSymbol(); GetBarBrightness(out var emptyAlpha, out var fullAlpha); float num2 = Mathf.Clamp01(SummerHeat.HeatFactor) * (float)num; int num3 = Mathf.Clamp(Mathf.FloorToInt(num2), 0, num); float num4 = num2 - (float)num3; bool flag = num4 > 0.0001f && num3 < num; int num5 = Mathf.Max(0, num - num3 - (flag ? 1 : 0)); float alpha = Mathf.Lerp(emptyAlpha, fullAlpha, Mathf.Clamp01(num4)); Color heatDisplayColor = GetHeatDisplayColor(); string value = ((num3 > 0) ? new string(barSymbol, num3) : string.Empty); string value2 = (flag ? barSymbol.ToString() : string.Empty); string value3 = ((num5 > 0) ? new string(barSymbol, num5) : string.Empty); return WrapBarText(ColorizeText(value, heatDisplayColor, fullAlpha) + ColorizeText(value2, heatDisplayColor, alpha) + ColorizeText(value3, heatDisplayColor, emptyAlpha)); } private static string WrapBarText(string barText) { Seasons.SummerHeatBarTagMode value = Seasons.summerHeatBarTagMode.Value; if (1 == 0) { } string result = value switch { Seasons.SummerHeatBarTagMode.None => barText, Seasons.SummerHeatBarTagMode.Sub => "<sub>" + barText + "</sub>", _ => "<sup>" + barText + "</sup>", }; if (1 == 0) { } return result; } private static char GetBarSymbol() { string value = Seasons.summerHeatBarSymbol.Value; if (string.IsNullOrWhiteSpace(value)) { return '▄'; } value = value.Trim(); return (value.Length > 0) ? value[0] : '▄'; } private static void GetBarBrightness(out float emptyAlpha, out float fullAlpha) { float num = Mathf.Clamp01(Seasons.summerHeatBarMinBrightness.Value); float num2 = Mathf.Clamp01(Seasons.summerHeatBarMaxBrightness.Value); emptyAlpha = Mathf.Min(num, num2); fullAlpha = Mathf.Max(num, num2); } private static Color GetHeatDisplayColor() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Color value = Seasons.summerHeatBarBonusColor.Value; Color value2 = Seasons.summerHeatBarNeutralColor.Value; Color value3 = Seasons.summerHeatBarPenaltyColor.Value; Color value4 = Seasons.summerHeatBarMaxColor.Value; if (SummerHeat.MaxEffectFactor > 0f) { return Color.Lerp(value3, value4, SummerHeat.MaxEffectFactor); } if (SummerHeat.RedFactor > 0f) { return Color.Lerp(value2, value3, SummerHeat.RedFactor); } if (SummerHeat.GreenFactor > 0f) { return Color.Lerp(value2, value, SummerHeat.GreenFactor); } return value2; } private static string ColorizeText(string value, Color color, float alpha = 1f) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(value)) { return string.Empty; } return "<color=#" + ColorHex(color, alpha) + ">" + value + "</color>"; } private static string ColorHex(Color color, float alpha) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(color.r) * 255f), 0, 255); int num2 = Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(color.g) * 255f), 0, 255); int num3 = Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(color.b) * 255f), 0, 255); int num4 = Mathf.Clamp(Mathf.RoundToInt(Mathf.Clamp01(alpha) * Mathf.Clamp01(color.a) * 255f), 0, 255); return $"{num:x2}{num2:x2}{num3:x2}{num4:x2}"; } private static float GetHeatMultiplier(float configuredEffect) { configuredEffect = Mathf.Clamp01(configuredEffect); if (Mathf.Approximately(configuredEffect, 0f)) { return 1f; } float num = Mathf.Lerp(1f, 1f + configuredEffect, SummerHeat.GreenFactor); float num2 = Mathf.Max(SummerHeat.RedFactor, SummerHeat.MaxEffectFactor); float num3 = Mathf.Lerp(1f, 1f - configuredEffect, num2); return (num2 > 0f) ? num3 : num; } private static float GetSignedModifier(float configuredValue) { configuredValue = Mathf.Clamp01(configuredValue); float num = Mathf.Max(SummerHeat.RedFactor, SummerHeat.MaxEffectFactor); if (num > 0f) { return configuredValue * num; } return 0f - configuredValue * SummerHeat.GreenFactor; } private static void AppendTechnicalInfo(StringBuilder builder) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) if (Seasons.summerHeatRavenTechnicalInfo.Value && TextsDialog_AddActiveEffects_SeasonTooltipWhenBuffDisabled.isActiveEffectsListCall && SummerHeat.IsReady) { bool flag = (Object)(object)SummerHeat.Instance == (Object)null || SummerHeat.Instance.IsDaytime(); float nightFactor = SummerHeatUtils.GetNightFactor(); GetThresholds(flag, nightFactor, out var greenThreshold, out var neutralThreshold, out var maxThreshold); float num = Mathf.Max(0.1f, SummerHeatUtils.ScaleHeatPercentForTime(SummerHeatUtils.ClampPercent(Seasons.summerHeatGreenFadeWidth.Value), flag, nightFactor)); float num2 = Mathf.Max(0.1f, SummerHeatUtils.ScaleHeatPercentForTime(SummerHeatUtils.ClampPercent(Seasons.summerHeatRedRampWidth.Value), flag, nightFactor)); float value = Mathf.Max(0f, greenThreshold - num); float value2 = greenThreshold + num; float value3 = Mathf.Min(maxThreshold, neutralThreshold + num2); float value4 = (flag ? 100f : (100f * nightFactor)); float value5 = SummerHeatUtils.ClampPercent(Seasons.summerHeatMaxOverflow.Value); Color heatDisplayColor = GetHeatDisplayColor(); Color value6 = Seasons.summerHeatBarBonusColor.Value; Color value7 = Seasons.summerHeatBarPenaltyColor.Value; Color value8 = Seasons.summerHeatBarMaxColor.Value; builder.Append('\n'); builder.AppendFormat("<color=orange>{0}</color>\n", "$seasons_status_summer_heat_technical".Localize()); builder.AppendFormat("{0}: {1} / {2}\n", "$seasons_status_summer_heat_technical_heat_values".Localize(), FormatPercent(SummerHeat.HeatPercent, heatDisplayColor), FormatPercent(SummerHeat.OverflowHeatPercent, value8)); builder.AppendFormat("{0}: {1} / {2} / {3}\n", "$seasons_status_summer_heat_technical_factors".Localize(), FormatFactorPercent(SummerHeat.GreenFactor, value6), FormatFactorPercent(SummerHeat.RedFactor, value7), FormatBoolColored(SummerHeat.MaxEffectFactor > 0f, value8)); builder.AppendFormat("{0}: <color=orange>{1}</color>\n", "$seasons_status_summer_heat_technical_direction".Localize(), GetTrendText().Localize()); builder.AppendFormat("{0}: <color=orange>{1}</color> / <color=orange>{2}</color> / <color=orange>{3}</color> / <color=orange>{4}</color>\n", "$seasons_status_summer_heat_technical_conditions".Localize(), FormatBool(flag), FormatBool(SummerHeat.IsSunny), FormatBool(SummerHeat.IsInShade), FormatBool(SummerHeatVisuals.IsWorldHazeActive())); AppendArmorTechnicalInfo(builder); builder.AppendFormat("{0}: {1}\n", "$seasons_status_summer_heat_technical_heat_scale".Localize(), BuildTechnicalHeatScale(flag)); builder.AppendFormat("{0}: {1} / {2} / {3}\n", "$seasons_status_summer_heat_technical_comfort_range".Localize(), FormatPercent(value, value6), FormatPercent(greenThreshold, value6), FormatPercent(value2, value6)); builder.AppendFormat("{0}: {1} / {2}\n", "$seasons_status_summer_heat_technical_penalty_ramp".Localize(), FormatPercent(neutralThreshold, value7), FormatPercent(value3, value7)); builder.AppendFormat("{0}: {1} / {2} / {3}\n", "$seasons_status_summer_heat_technical_overheated".Localize(), FormatPercent(maxThreshold, value8), FormatPercent(value4, value8), FormatPercent(value5, value8)); } } private static void GetThresholds(bool isDaytime, float nightFactor, out float greenThreshold, out float neutralThreshold, out float maxThreshold) { float num = SummerHeatUtils.ClampPercent(Seasons.summerHeatGreenThreshold.Value); float num2 = SummerHeatUtils.ClampPercent(Mathf.Max(num + 1f, Seasons.summerHeatNeutralThreshold.Value)); float value = SummerHeatUtils.ClampPercent(Mathf.Max(num2 + 1f, Seasons.summerHeatMaxThreshold.Value)); greenThreshold = SummerHeatUtils.ScaleHeatPercentForTime(num, isDaytime, nightFactor); neutralThreshold = SummerHeatUtils.ScaleHeatPercentForTime(num2, isDaytime, nightFactor); maxThreshold = SummerHeatUtils.ScaleHeatPercentForTime(value, isDaytime, nightFactor); } private static string FormatPercent(float value, Color color) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return ColorizeText($"{value:0.#}%", color); } private static string FormatFactorPercent(float value, Color color) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) return ColorizeText($"{Mathf.Clamp01(value) * 100f:0}%", color); } private static string FormatBool(bool value) { return (value ? "$seasons_status_summer_heat_yes" : "$seasons_status_summer_heat_no").Localize(); } private static string FormatBoolColored(bool value, Color yesColor) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) string text = FormatBool(value); return value ? ColorizeText(text, yesColor) : text; } private static void AppendArmorTechnicalInfo(StringBuilder builder) { if (Seasons.summerHeatArmorHeatEnabled.Value && !((Object)(object)SummerHeat.Instance == (Object)null)) { SummerHeatArmorState armorState = SummerHeat.Instance.ArmorState; builder.AppendFormat("{0}: {1} / {2}\n", "$seasons_status_summer_heat_technical_armor".Localize(), FormatArmorModifier(armorState.HeatingModifier, positiveIsGood: false), FormatArmorModifier(armorState.CoolingModifier, positiveIsGood: true)); builder.AppendFormat("{0}: <color=orange>{1}</color> / <color=orange>{2}</color> / <color=orange>{3}</color> / <color=orange>{4}</color>\n", "$seasons_status_summer_heat_technical_armor_slots".Localize(), LocalizeState(armorState.HeadState), LocalizeState(armorState.CloakState), LocalizeState(armorState.ChestState), LocalizeState(armorState.LegsState)); } } private static string FormatArmorModifier(float value, bool positiveIsGood) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Color value2 = Seasons.summerHeatBarBonusColor.Value; Color value3 = Seasons.summerHeatBarNeutralColor.Value; Color value4 = Seasons.summerHeatBarPenaltyColor.Value; Color color = (Mathf.Approximately(value, 0f) ? value3 : ((value > 0f == positiveIsGood) ? value2 : value4)); return ColorizeText($"{value * 100f:+0;-0;0}%", color); } private static string LocalizeState(string token) { return string.IsNullOrEmpty(token) ? string.Empty : token.Localize(); } private static string BuildTechnicalHeatScale(bool isDaytime) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(2400); for (int i = 0; i < 100; i++) { float heatPercent = (float)i * 100f / 99f; stringBuilder.Append(ColorizeText('|'.ToString(), GetHeatDisplayColorForValue(heatPercent, isDaytime))); } return $"<cspace=-0.08em>{stringBuilder}</cspace>"; } private static Color GetHeatDisplayColorForValue(float heatPercent, bool isDaytime) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) float nightFactor = SummerHeatUtils.GetNightFactor(); GetThresholds(isDaytime, nightFactor, out var greenThreshold, out var neutralThreshold, out var maxThreshold); float num = Mathf.Max(0.1f, SummerHeatUtils.ScaleHeatPercentForTime(SummerHeatUtils.ClampPercent(Seasons.summerHeatGreenFadeWidth.Value), isDaytime, nightFactor)); float num2 = Mathf.Max(0.1f, SummerHeatUtils.ScaleHeatPercentForTime(SummerHeatUtils.ClampPercent(Seasons.summerHeatRedRampWidth.Value), isDaytime, nightFactor)); Color value = Seasons.summerHeatBarBonusColor.Value; Color value2 = Seasons.summerHeatBarNeutralColor.Value; Color value3 = Seasons.summerHeatBarPenaltyColor.Value; Color value4 = Seasons.summerHeatBarMaxColor.Value; if (!isDaytime && nightFactor <= 0f) { return value2; } if (heatPercent >= maxThreshold) { return value4; } if (heatPercent > neutralThreshold) { float num3 = Mathf.Min(maxThreshold, neutralThreshold + num2); float num4 = ((heatPercent < num3) ? Mathf.InverseLerp(neutralThreshold, num3, heatPercent) : 1f); return Color.Lerp(value2, value3, num4); } float num5 = Mathf.Max(0f, greenThreshold - num); float num6 = greenThreshold + num; if (heatPercent >= num5 && heatPercent <= num6) { float num7 = ((heatPercent <= greenThreshold) ? Mathf.InverseLerp(num5, greenThreshold, heatPercent) : (1f - Mathf.InverseLerp(greenThreshold, num6, heatPercent))); float num8 = Mathf.Lerp(0.25f, 1f, num7); return Color.Lerp(value2, value, num8); } return value2; } private static string GetZoneText(HeatZone zone) { if (1 == 0) { } string result = zone switch { HeatZone.Green => "$seasons_status_summer_heat_zone_green", HeatZone.Neutral => "$seasons_status_summer_heat_zone_neutral", HeatZone.Red => "$seasons_status_summer_heat_zone_red", HeatZone.Max => "$seasons_status_summer_heat_zone_max", _ => "$seasons_status_summer_heat_zone_neutral", }; if (1 == 0) { } return result; } private static string GetExposureText() { if (SummerHeat.IsInSun) { return "$seasons_status_summer_heat_exposure_sun"; } if (SummerHeat.IsInShade) { return "$seasons_status_summer_heat_exposure_shade"; } return "$seasons_status_summer_heat_exposure_none"; } private static string GetTrendText() { if (SummerHeat.Direction > 0) { return "$seasons_status_summer_heat_trend_heating"; } if (SummerHeat.Direction < 0) { return "$seasons_status_summer_heat_trend_cooling"; } return "$seasons_status_summer_heat_trend_stable"; } private static string GetModifierSummary() { StringBuilder stringBuilder = new StringBuilder(128); AppendModifierLine(stringBuilder, "$seasons_status_summer_heat_modifier_health_regen", GetHeatMultiplier(Seasons.summerHeatHealthRegenMultiplier.Value)); AppendModifierLine(stringBuilder, "$seasons_status_summer_heat_modifier_stamina_regen", GetHeatMultiplier(Seasons.summerHeatStaminaRegenMultiplier.Value)); AppendModifierLine(stringBuilder, "$seasons_status_summer_heat_modifier_eitr_regen", GetHeatMultiplier(Seasons.summerHeatEitrRegenMultiplier.Value)); AppendModifierLine(stringBuilder, "$seasons_status_summer_heat_modifier_stamina_use", 1f + GetSignedModifier(Seasons.summerHeatStaminaUseMultiplier.Value)); AppendModifierLine(stringBuilder, "$seasons_status_summer_heat_modifier_adrenaline", 1f + GetSignedModifier(Seasons.summerHeatAdrenalineMultiplier.Value)); if (stringBuilder.Length == 0) { return string.Empty; } return "\n" + stringBuilder; } private static void AppendActiveFactors(StringBuilder builder) { bool flag = false; if ((Object)(object)SummerHeat.Instance != (Object)null && SummerHeat.Instance.HasCoolingFood()) { builder.AppendFormat("<color=orange>{0}</color>\n", "$seasons_status_summer_heat_factor_cooling_food".Localize()); flag = true; } if ((Object)(object)SummerHeat.Instance != (Object)null && SummerHeat.Instance.HasCampFireHeat()) { builder.AppendFormat("<color=orange>{0}</color>\n", "$seasons_status_summer_heat_factor_campfire".Localize()); flag = true; } if ((Object)(object)SummerHeat.Instance != (Object)null && SummerHeat.Instance.HasEncumberedHeat()) { builder.AppendFormat("<color=orange>{0}</color>\n", "$seasons_status_summer_heat_factor_encumbered".Localize()); flag = true; } if (flag) { builder.Append('\n'); } } private static void AppendModifierLine(StringBuilder builder, string label, float multiplier) { if (!Mathf.Approximately(multiplier, 1f)) { builder.AppendFormat("{0}: <color=orange>{1}%</color>\n", label.Localize(), ((multiplier - 1f) * 100f).ToString("+0;-0")); } } } internal struct SummerHeatArmorState { public static readonly SummerHeatArmorState Empty = new SummerHeatArmorState { HeadState = "$seasons_status_summer_heat_armor_disabled", CloakState = "$seasons_status_summer_heat_armor_disabled", ChestState = "$seasons_status_summer_heat_armor_disabled", LegsState = "$seasons_status_summer_heat_armor_disabled" }; public float HeatingModifier; public float CoolingModifier; public string HeadState; public string CloakState; public string ChestState; public string LegsState; } internal class SummerHeatController : MonoBehaviour { internal const float EvaluationInterval = 1f; internal const float DaytimeHeatCap = 100f; internal const float ShadowRayDistance = 100f; internal const float StableEpsilon = 0.01f; internal const float WetCoolingPerSecond = 5f; internal const float ShelterCoolingPerSecond = 2f; internal const float BurningHeatPerSecond = 5f; internal const float RunningHeatPerSecond = 0.5f; internal const float WalkingCoolingPerSecond = 0.5f; internal const float StandingCoolingPerSecond = 1f; internal const float CoolingFoodHeatPerSecond = 5f; internal const float CampFireHeatPerSecond = 0.5f; internal const float EncumberedHeatPerSecond = 0.5f; internal const float MovementThreshold = 0.1f; internal const float NoonPeak = 0.5f; internal const float NoonStart = 0.42f; internal const float NoonEnd = 0.58f; internal const float SecondaryAttackHeat = 1f; internal const float PrimaryAttackHeat = 0.5f; internal const float DodgeHeat = 0.5f; internal const float JumpHeat = 0.25f; internal const float BlockHeat = 1f; internal const float PerfectBlockHeat = 0.5f; internal const float FireDamageHeat = 10f; internal const float FrostDamageHeat = -10f; private const float BareHeadHairHeatRateBonus = 0.2f; private static readonly HashSet<string> s_configuredNonSunnySystems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> s_openHelmetItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> s_bareHeadHairItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> s_lightCloakItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> s_openChestItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> s_openLegItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static string s_configuredNonSunnySystemsValue = string.Empty; private static string s_openHelmetItemsValue = string.Empty; private static string s_bareHeadHairItemsValue = string.Empty; private static string s_lightCloakItemsValue = string.Empty; private static string s_openChestItemsValue = string.Empty; private static string s_openLegItemsValue = string.Empty; private float _evaluationTimer; private float _overflowHeat; private SummerHeatMode _mode = SummerHeatMode.Stable; private SummerHeatState _state; private string _currentEnvironmentName = string.Empty; private bool _isDaytime = true; private bool _hasWetStatus; private bool _hasShelterStatus; private bool _hasBurningStatus; private bool _hasColdStatus; private bool _hasCoolingFood; private bool _hasCampFireStatus; private bool _biomeAllowsSummerHeat = true; private Biome _currentBiome = (Biome)0; private SummerHeatArmorState _armorState = SummerHeatArmorState.Empty; internal static SummerHeatController Instance { get; private set; } internal Player Player { get; private set; } internal SummerHeatState State => _state; internal SummerHeatArmorState ArmorState