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 Hungry Viking v1.1.0
BepInEx/plugins/HungryViking.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("HungryViking")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b8af4abbc73174f01d114297ef8542d09d49fb04")] [assembly: AssemblyProduct("HungryViking")] [assembly: AssemblyTitle("HungryViking")] [assembly: AssemblyVersion("1.0.0.0")] namespace HungryViking; public class FoodMonitor { private class SlotState { public bool WarningFired; } private readonly HungryVikingMod _mod; public static readonly FieldRef<Player, List<Food>> FoodsRef = AccessTools.FieldRefAccess<Player, List<Food>>("m_foods"); private readonly Dictionary<string, SlotState> _states = new Dictionary<string, SlotState>(); private readonly HashSet<string> _prevNames = new HashSet<string>(); private int _prevFoodCount = -1; public int CurrentFoodCount { get; private set; } public float WorstSlotUrgency { get; private set; } public event Action OnWarning; public event Action OnStarving; public FoodMonitor(HungryVikingMod mod) { _mod = mod; } public static void ClearFoods(Player player) { FoodsRef.Invoke(player).Clear(); } public static string DrainFood(Player player, int zeroBasedIdx, float seconds) { List<Food> list = FoodsRef.Invoke(player); if (zeroBasedIdx >= list.Count) { return $"Slot {zeroBasedIdx + 1} is empty."; } Food val = list[zeroBasedIdx]; val.m_time = Mathf.Max(0f, val.m_time - seconds); return string.Format("Slot {0} ({1}): {2:F0}s remaining.", zeroBasedIdx + 1, val.m_item?.m_shared?.m_name ?? "?", val.m_time); } public static string DrainAllFoods(Player player, float seconds) { List<Food> list = FoodsRef.Invoke(player); foreach (Food item in list) { item.m_time = Mathf.Max(0f, item.m_time - seconds); } return $"Drained {seconds}s from {list.Count} slot(s)."; } public static string SetFoodTime(Player player, int zeroBasedIdx, float seconds) { List<Food> list = FoodsRef.Invoke(player); if (zeroBasedIdx >= list.Count) { return $"Slot {zeroBasedIdx + 1} is empty."; } Food val = list[zeroBasedIdx]; val.m_time = Mathf.Max(0f, seconds); return string.Format("Slot {0} ({1}): set to {2:F0}s.", zeroBasedIdx + 1, val.m_item?.m_shared?.m_name ?? "?", val.m_time); } public static string GetFoodStatus(Player player) { List<Food> list = FoodsRef.Invoke(player); if (list.Count == 0) { return "No active food buffs."; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < list.Count; i++) { Food val = list[i]; stringBuilder.AppendLine(string.Format(" Slot {0}: {1} {2:F0}s remaining", i + 1, val.m_item?.m_shared?.m_name ?? "unknown", val.m_time)); } return stringBuilder.ToString().TrimEnd(Array.Empty<char>()); } public void Tick(float dt) { List<Food> list = FoodsRef.Invoke(Player.m_localPlayer); if (CurrentFoodCount == 0 && list.Count > 0) { HungryVikingMod.Log.LogInfo((object)$"HungryViking: tracking {list.Count} food slot(s)"); } CurrentFoodCount = list.Count; HashSet<string> hashSet = new HashSet<string>(); foreach (Food item in list) { if (item?.m_item?.m_shared != null) { hashSet.Add(item.m_item.m_shared.m_name); } } foreach (string item2 in hashSet) { if (!_prevNames.Contains(item2)) { _states.Remove(item2); } } bool num = _prevFoodCount == -1; bool flag = CurrentFoodCount < _prevFoodCount; if ((num || flag) && CurrentFoodCount < 3) { this.OnStarving?.Invoke(); } float num2 = 0f; float value = _mod.HungerThreshold.Value; foreach (Food item3 in list) { if (item3?.m_item?.m_shared == null) { continue; } string name = item3.m_item.m_shared.m_name; if (!_states.TryGetValue(name, out var value2)) { value2 = new SlotState(); _states[name] = value2; } float time = item3.m_time; if (time < value) { num2 = Mathf.Max(num2, 1f - time / value); if (!value2.WarningFired) { value2.WarningFired = true; this.OnWarning?.Invoke(); } } else { value2.WarningFired = false; } } WorstSlotUrgency = num2; _prevFoodCount = CurrentFoodCount; _prevNames.Clear(); foreach (string item4 in hashSet) { _prevNames.Add(item4); } } } public class HungerStatusEffect : StatusEffect { public static HungerStatusEffect Create() { HungerStatusEffect hungerStatusEffect = ScriptableObject.CreateInstance<HungerStatusEffect>(); ((StatusEffect)hungerStatusEffect).m_name = "Hungry"; ((StatusEffect)hungerStatusEffect).m_icon = LoadIcon(); ((StatusEffect)hungerStatusEffect).m_ttl = 0f; return hungerStatusEffect; } private static Sprite LoadIcon() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0089: 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) Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = Array.Find(executingAssembly.GetManifestResourceNames(), (string n) => n.EndsWith("status_icon.png")); if (text != null) { using Stream stream = executingAssembly.GetManifestResourceStream(text); byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (LoadImage(val, array)) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width); } } HungryVikingMod.Log.LogWarning((object)"HungryViking: icon.png resource not found, using fallback icon."); return BuildFallbackIcon(); } private static bool LoadImage(Texture2D tex, byte[] bytes) { try { MethodInfo methodInfo = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); return methodInfo != null && (bool)methodInfo.Invoke(null, new object[2] { tex, bytes }); } catch { return false; } } private static Sprite BuildFallbackIcon() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false); float num = 32f; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.65f, 0.1f, 1f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.35f, 0.15f, 0f, 0.9f); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num2 = ((float)j + 0.5f - num) / (num * 0.88f); float num3 = ((float)i + 0.5f - num) / (num * 0.8f); if (num2 * num2 + num3 * num3 >= 1f) { val.SetPixel(j, i, Color.clear); continue; } float num4 = Mathf.Sin(num2 * (float)Math.PI * 2.5f) * 0.12f - 0.15f; float num5 = Mathf.Abs(num3 - num4); val.SetPixel(j, i, (num5 < 0.1f) ? val3 : val2); } } val.Apply(); return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f); } } [BepInPlugin("DeathMonger.HungryViking", "Hungry Viking", "1.1.0")] [BepInProcess("valheim.exe")] public class HungryVikingMod : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__37_0; public static ConsoleEvent <>9__37_1; public static ConsoleEvent <>9__37_2; public static ConsoleEvent <>9__37_3; public static ConsoleEvent <>9__37_4; public static ConsoleEvent <>9__37_5; internal void <InitCommands>b__37_0(ConsoleEventArgs _) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { FoodMonitor.ClearFoods(localPlayer); Log.LogInfo((object)"hv_clearfood: all food buffs removed."); } } internal void <InitCommands>b__37_1(ConsoleEventArgs args) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { if (args.Length < 2 || !TryParseSlot(args[1], out var zeroBasedIndex)) { Log.LogInfo((object)"Usage: hv_drainfood <1|2|3> [seconds]"); return; } float result; float seconds = ((args.Length >= 3 && float.TryParse(args[2], out result)) ? result : 60f); Log.LogInfo((object)FoodMonitor.DrainFood(localPlayer, zeroBasedIndex, seconds)); } } internal void <InitCommands>b__37_2(ConsoleEventArgs args) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { float result; float seconds = ((args.Length >= 2 && float.TryParse(args[1], out result)) ? result : 60f); Log.LogInfo((object)FoodMonitor.DrainAllFoods(localPlayer, seconds)); } } internal void <InitCommands>b__37_3(ConsoleEventArgs args) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { if (args.Length < 3 || !TryParseSlot(args[1], out var zeroBasedIndex) || !float.TryParse(args[2], out var result)) { Log.LogInfo((object)"Usage: hv_setfoodtime <1|2|3> <seconds>"); } else { Log.LogInfo((object)FoodMonitor.SetFoodTime(localPlayer, zeroBasedIndex, result)); } } } internal void <InitCommands>b__37_4(ConsoleEventArgs _) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Log.LogInfo((object)FoodMonitor.GetFoodStatus(localPlayer)); } } internal void <InitCommands>b__37_5(ConsoleEventArgs _) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } List<StatusEffect> statusEffects = ((Character)localPlayer).GetSEMan().GetStatusEffects(); if (statusEffects.Count == 0) { Log.LogInfo((object)"No active status effects."); return; } StringBuilder stringBuilder = new StringBuilder(); foreach (StatusEffect item in statusEffects) { stringBuilder.AppendLine($" \"{item.m_name}\" hash={item.NameHash()}"); } stringBuilder.AppendLine($" HaveStatusEffect(SmokedHash={-1612278721}) = {((Character)localPlayer).GetSEMan().HaveStatusEffect(-1612278721)}"); Log.LogInfo((object)stringBuilder.ToString().TrimEnd(Array.Empty<char>())); } } public const string ModGuid = "DeathMonger.HungryViking"; private readonly Harmony harmony = new Harmony("DeathMonger.HungryViking"); public ConfigEntry<bool> Enabled; public ConfigEntry<bool> ShowStatusIcon; public ConfigEntry<float> HungerThreshold; public ConfigEntry<float> VignetteIntensity; public ConfigEntry<float> VignetteExtent; public ConfigEntry<float> SmokedVignetteIntensity; public ConfigEntry<float> SmokedVignetteExtent; public ConfigEntry<float> PoisonedVignetteIntensity; public ConfigEntry<float> PoisonedVignetteExtent; private FoodMonitor _foodMonitor; private VignetteOverlay _vignette; private SmokedOverlay _smokedOverlay; private SmokedOverlay _poisonedOverlay; private HungerStatusEffect _statusEffect; private StatusEffect _activeStatusEffect; private Player _statusEffectPlayer; private const int SmokedHash = -1612278721; private const int PoisonedHash = 0; private bool _smokedTestActive; private bool _poisonedTestActive; private bool _hungerTestActive; private float _hungerPreviewTimer; private float _smokedPreviewTimer; private float _poisonedPreviewTimer; private Dictionary<string, string> _migrationCache; public static HungryVikingMod Instance { get; private set; } public static ManualLogSource Log => ((BaseUnityPlugin)Instance).Logger; public string HungerMessage { get; private set; } = ""; private void Awake() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) Instance = this; InitConfig(); harmony.PatchAll(); _vignette = ((Component)this).gameObject.AddComponent<VignetteOverlay>(); _smokedOverlay = ((Component)this).gameObject.AddComponent<SmokedOverlay>(); _poisonedOverlay = ((Component)this).gameObject.AddComponent<SmokedOverlay>(); _poisonedOverlay.SetLabelBaseColor(new Color(0.2f, 0.75f, 0.2f, 1f)); _foodMonitor = new FoodMonitor(this); _statusEffect = HungerStatusEffect.Create(); _foodMonitor.OnWarning += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)"HungryViking: entered hunger window"); }; _foodMonitor.OnStarving += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)"HungryViking: slot expired"); }; VignetteIntensity.SettingChanged += delegate { _hungerPreviewTimer = 2f; }; VignetteExtent.SettingChanged += delegate { _hungerPreviewTimer = 2f; }; SmokedVignetteIntensity.SettingChanged += delegate { _smokedPreviewTimer = 2f; }; SmokedVignetteExtent.SettingChanged += delegate { _smokedPreviewTimer = 2f; }; PoisonedVignetteIntensity.SettingChanged += delegate { _poisonedPreviewTimer = 2f; }; PoisonedVignetteExtent.SettingChanged += delegate { _poisonedPreviewTimer = 2f; }; InitCommands(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Hungry Viking loaded. HungerThreshold={HungerThreshold.Value}s Intensity={VignetteIntensity.Value}"); } private void InitCommands() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0029: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0099: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown object obj = <>c.<>9__37_0; if (obj == null) { ConsoleEvent val = delegate { Player localPlayer6 = Player.m_localPlayer; if (!((Object)(object)localPlayer6 == (Object)null)) { FoodMonitor.ClearFoods(localPlayer6); Log.LogInfo((object)"hv_clearfood: all food buffs removed."); } }; <>c.<>9__37_0 = val; obj = (object)val; } new ConsoleCommand("hv_clearfood", "[Hungry Viking] Instantly removes all food buffs.", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__37_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { Player localPlayer5 = Player.m_localPlayer; if (!((Object)(object)localPlayer5 == (Object)null)) { if (args.Length < 2 || !TryParseSlot(args[1], out var zeroBasedIndex2)) { Log.LogInfo((object)"Usage: hv_drainfood <1|2|3> [seconds]"); } else { float result3; float seconds2 = ((args.Length >= 3 && float.TryParse(args[2], out result3)) ? result3 : 60f); Log.LogInfo((object)FoodMonitor.DrainFood(localPlayer5, zeroBasedIndex2, seconds2)); } } }; <>c.<>9__37_1 = val2; obj2 = (object)val2; } new ConsoleCommand("hv_drainfood", "[Hungry Viking] hv_drainfood <slot 1-3> [seconds=60] — subtracts seconds from one food slot.", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>c.<>9__37_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { Player localPlayer4 = Player.m_localPlayer; if (!((Object)(object)localPlayer4 == (Object)null)) { float result2; float seconds = ((args.Length >= 2 && float.TryParse(args[1], out result2)) ? result2 : 60f); Log.LogInfo((object)FoodMonitor.DrainAllFoods(localPlayer4, seconds)); } }; <>c.<>9__37_2 = val3; obj3 = (object)val3; } new ConsoleCommand("hv_drainfoods", "[Hungry Viking] hv_drainfoods [seconds=60] — subtracts seconds from all food slots.", (ConsoleEvent)obj3, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__37_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { Player localPlayer3 = Player.m_localPlayer; if (!((Object)(object)localPlayer3 == (Object)null)) { if (args.Length < 3 || !TryParseSlot(args[1], out var zeroBasedIndex) || !float.TryParse(args[2], out var result)) { Log.LogInfo((object)"Usage: hv_setfoodtime <1|2|3> <seconds>"); } else { Log.LogInfo((object)FoodMonitor.SetFoodTime(localPlayer3, zeroBasedIndex, result)); } } }; <>c.<>9__37_3 = val4; obj4 = (object)val4; } new ConsoleCommand("hv_setfoodtime", "[Hungry Viking] hv_setfoodtime <slot 1-3> <seconds> — sets a slot to exactly X seconds remaining.", (ConsoleEvent)obj4, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj5 = <>c.<>9__37_4; if (obj5 == null) { ConsoleEvent val5 = delegate { Player localPlayer2 = Player.m_localPlayer; if (!((Object)(object)localPlayer2 == (Object)null)) { Log.LogInfo((object)FoodMonitor.GetFoodStatus(localPlayer2)); } }; <>c.<>9__37_4 = val5; obj5 = (object)val5; } new ConsoleCommand("hv_foodstatus", "[Hungry Viking] Prints the name and remaining time of each food slot.", (ConsoleEvent)obj5, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj6 = <>c.<>9__37_5; if (obj6 == null) { ConsoleEvent val6 = delegate { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { List<StatusEffect> statusEffects = ((Character)localPlayer).GetSEMan().GetStatusEffects(); if (statusEffects.Count == 0) { Log.LogInfo((object)"No active status effects."); } else { StringBuilder stringBuilder = new StringBuilder(); foreach (StatusEffect item in statusEffects) { stringBuilder.AppendLine($" \"{item.m_name}\" hash={item.NameHash()}"); } stringBuilder.AppendLine($" HaveStatusEffect(SmokedHash={-1612278721}) = {((Character)localPlayer).GetSEMan().HaveStatusEffect(-1612278721)}"); Log.LogInfo((object)stringBuilder.ToString().TrimEnd(Array.Empty<char>())); } } }; <>c.<>9__37_5 = val6; obj6 = (object)val6; } new ConsoleCommand("hv_selist", "[Hungry Viking] Lists all active status effects on the local player with their name hashes.", (ConsoleEvent)obj6, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("hv_testhunger", "[Hungry Viking] Toggles the hunger vignette on/off for visual testing. Also triggers automatically for 2 seconds when Intensity or Extent config values change.", (ConsoleEvent)delegate { _hungerTestActive = !_hungerTestActive; Log.LogInfo((object)("hv_testhunger: hunger overlay " + (_hungerTestActive ? "ON" : "OFF"))); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("hv_testsmoked", "[Hungry Viking] Toggles the smoked vignette overlay on/off for visual testing.", (ConsoleEvent)delegate { _smokedTestActive = !_smokedTestActive; Log.LogInfo((object)("hv_testsmoked: smoked overlay " + (_smokedTestActive ? "ON" : "OFF"))); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); new ConsoleCommand("hv_testpoisoned", "[Hungry Viking] Toggles the poisoned vignette overlay on/off for visual testing.", (ConsoleEvent)delegate { _poisonedTestActive = !_poisonedTestActive; Log.LogInfo((object)("hv_testpoisoned: poisoned overlay " + (_poisonedTestActive ? "ON" : "OFF"))); }, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool TryParseSlot(string s, out int zeroBasedIndex) { if (int.TryParse(s, out var result) && result >= 1 && result <= 3) { zeroBasedIndex = result - 1; return true; } zeroBasedIndex = -1; return false; } private void InitConfig() { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Expected O, but got Unknown //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable all Hungry Viking effects."); ShowStatusIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("Hunger", "Show Status Icon", MigrateBool("General", "Show Status Icon", fallback: true), "Show the Hunger status icon in the HUD alongside Rested, Shelter, etc."); HungerThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Hunger", "Hunger Threshold (seconds)", MigrateFloat("General", "Hunger Threshold (seconds)", 90f), "Seconds remaining on a food buff when the warning begins. Vignette and label fade in from here."); VignetteIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Hunger", "Vignette Intensity", MigrateFloat("General", "Vignette Intensity", 0.2f), new ConfigDescription("Maximum vignette edge opacity. 0 = off, 1 = fully opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); VignetteExtent = ((BaseUnityPlugin)this).Config.Bind<float>("Hunger", "Vignette Extent", MigrateFloat("General", "Vignette Extent", 0.5f), new ConfigDescription("How far the vignette extends from the screen edge toward the center. 0 = not visible, 1 = covers the full screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SmokedVignetteIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Smoked", "Vignette Intensity", 0.25f, new ConfigDescription("Maximum opacity of the center smoke vignette. 0 = off, 1 = fully opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); SmokedVignetteExtent = ((BaseUnityPlugin)this).Config.Bind<float>("Smoked", "Vignette Extent", 1f, new ConfigDescription("How far from the screen center the smoke vignette reaches. 0 = invisible, 1 = covers the full screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); PoisonedVignetteIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Poisoned", "Vignette Intensity", 0.25f, new ConfigDescription("Maximum opacity of the center poison vignette. 0 = off, 1 = fully opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); PoisonedVignetteExtent = ((BaseUnityPlugin)this).Config.Bind<float>("Poisoned", "Vignette Extent", 0.55f, new ConfigDescription("How far from the screen center the poison vignette reaches. 0 = invisible, 1 = covers the full screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ((BaseUnityPlugin)this).Config.Save(); } private string MigrateRaw(string section, string key) { if (_migrationCache == null) { _migrationCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); if (File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { string text = null; string[] array = File.ReadAllLines(((BaseUnityPlugin)this).Config.ConfigFilePath); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2).Trim(); } else if (text != null && !text2.StartsWith("#") && !text2.StartsWith("//")) { int num = text2.IndexOf('='); if (num >= 0) { _migrationCache[text + "/" + text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim(); } } } } } if (!_migrationCache.TryGetValue(section + "/" + key, out var value)) { return null; } return value; } private float MigrateFloat(string section, string key, float fallback) { string text = MigrateRaw(section, key); if (text == null || !float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return fallback; } return result; } private bool MigrateBool(string section, string key, bool fallback) { string text = MigrateRaw(section, key); if (text == null || !bool.TryParse(text, out var result)) { return fallback; } return result; } private void Update() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) if (!Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null) { if ((Object)(object)_activeStatusEffect != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).GetSEMan().RemoveStatusEffect(_activeStatusEffect.NameHash(), false); } _activeStatusEffect = null; _vignette.SetBase(0f, Color.black); _vignette.SetHungerLabel(null); _smokedOverlay.SetBase(0f, Color.white); _smokedOverlay.SetLabel(null); _poisonedOverlay.SetBase(0f, Color.white); _poisonedOverlay.SetLabel(null); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)(object)_statusEffectPlayer) { _activeStatusEffect = null; _statusEffectPlayer = localPlayer; } _vignette.SetInnerBoundary(1f - VignetteExtent.Value); _foodMonitor.Tick(Time.deltaTime); bool flag = _foodMonitor.CurrentFoodCount < 3; float num = (flag ? 1f : _foodMonitor.WorstSlotUrgency); if (_hungerPreviewTimer > 0f) { _hungerPreviewTimer -= Time.deltaTime; } int num2; float num3; if (!_hungerTestActive) { num2 = ((_hungerPreviewTimer > 0f) ? 1 : 0); if (num2 == 0) { num3 = num; goto IL_0183; } } else { num2 = 1; } num3 = 1f; goto IL_0183; IL_0183: float num4 = num3; if (num4 > 0f) { _vignette.SetBase(VignetteIntensity.Value * num4, new Color(1f, 0.8f, 0.15f)); } else { _vignette.SetBase(0f, Color.black); } string text = null; if (((uint)num2 | (flag ? 1u : 0u)) != 0) { text = "You are hungry."; } else if (num >= 0.5f) { text = "You are getting hungry."; } else if (num > 0f) { text = "You are starting to feel hungry."; } _vignette.SetHungerLabel(text, num4); UpdateSmokedOverlay(localPlayer); UpdatePoisonedOverlay(localPlayer); HungerMessage = (flag ? "Hungry" : "Getting Hungry"); bool flag2 = (num > 0f || flag) && ShowStatusIcon.Value; if (flag2 && (Object)(object)_activeStatusEffect == (Object)null) { _activeStatusEffect = ((Character)localPlayer).GetSEMan().AddStatusEffect((StatusEffect)(object)_statusEffect, false, 0, 0f); } else if (!flag2 && (Object)(object)_activeStatusEffect != (Object)null) { ((Character)localPlayer).GetSEMan().RemoveStatusEffect(_activeStatusEffect.NameHash(), false); _activeStatusEffect = null; } } private void UpdateSmokedOverlay(Player player) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (_smokedPreviewTimer > 0f) { _smokedPreviewTimer -= Time.deltaTime; } bool num = _smokedTestActive || _smokedPreviewTimer > 0f || ((Character)player).GetSEMan().HaveStatusEffect(-1612278721); _smokedOverlay.SetOuterBoundary(SmokedVignetteExtent.Value); if (num) { _smokedOverlay.SetBase(SmokedVignetteIntensity.Value, new Color(0.85f, 0.85f, 0.85f)); _smokedOverlay.SetLabel("You can't breathe in the smoke!", 1f); } else { _smokedOverlay.SetBase(0f, Color.white); _smokedOverlay.SetLabel(null); } } private void UpdatePoisonedOverlay(Player player) { //IL_009a: 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) if (_poisonedPreviewTimer > 0f) { _poisonedPreviewTimer -= Time.deltaTime; } bool num = _poisonedTestActive || _poisonedPreviewTimer > 0f; _poisonedOverlay.SetOuterBoundary(PoisonedVignetteExtent.Value); if (num) { _poisonedOverlay.SetBase(PoisonedVignetteIntensity.Value, new Color(0.2f, 0.8f, 0.2f)); _poisonedOverlay.SetLabel("You are poisoned.", 1f); } else { _poisonedOverlay.SetBase(0f, Color.white); _poisonedOverlay.SetLabel(null); } } private void OnDestroy() { harmony.UnpatchSelf(); } } public class SmokedOverlay : MonoBehaviour { private RawImage _image; private Text _label; private float _urgency; private static readonly Color LabelRedColor = new Color(1f, 0f, 0f, 1f); private Color _labelBaseColor = new Color(0.7f, 0.7f, 0.7f, 1f); private float _baseAlpha; private float _smoothedBase; private Color _baseColor; private float _labelPhase; private float _outerBoundary = 0.55f; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0078: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HungryViking_SmokedVignette"); Object.DontDestroyOnLoad((Object)(object)val); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 99; GameObject val2 = new GameObject("Image"); val2.transform.SetParent(val.transform, false); _image = val2.AddComponent<RawImage>(); _image.texture = (Texture)(object)BuildVignetteTexture(64, _outerBoundary); ((Graphic)_image).raycastTarget = false; ((Graphic)_image).color = Color.clear; RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; GameObject val4 = new GameObject("SmokedLabel"); val4.transform.SetParent(val.transform, false); _label = val4.AddComponent<Text>(); _label.text = ""; _label.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); _label.fontSize = 22; _label.fontStyle = (FontStyle)1; _label.alignment = (TextAnchor)1; ((Graphic)_label).color = _labelBaseColor; ((Graphic)_label).raycastTarget = false; ((Component)_label).gameObject.SetActive(false); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = new Vector2(0f, 1f); val5.anchorMax = new Vector2(1f, 1f); val5.pivot = new Vector2(0.5f, 1f); val5.offsetMin = new Vector2(0f, -100f); val5.offsetMax = new Vector2(0f, -70f); } public void SetLabelBaseColor(Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _labelBaseColor = color; } public void SetBase(float alpha, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _baseAlpha = alpha; _baseColor = color; } private void Update() { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) float num = ((_baseAlpha > _smoothedBase) ? Time.deltaTime : (Time.deltaTime * 0.5f)); _smoothedBase = Mathf.MoveTowards(_smoothedBase, _baseAlpha, num); float num2 = 0f; if (_urgency > 0f) { float num3 = Mathf.Lerp(0.2f, 1f, _urgency); _labelPhase = (_labelPhase + num3 * (float)Math.PI * 2f * Time.deltaTime) % ((float)Math.PI * 2f); num2 = (Mathf.Sin(_labelPhase) + 1f) * 0.5f; } float num4 = 1f - _urgency * 0.5f; float num5 = _smoothedBase * Mathf.Lerp(num4, 1f, num2); ((Graphic)_image).color = (Color)((num5 < 0.005f) ? Color.clear : new Color(_baseColor.r, _baseColor.g, _baseColor.b, num5)); if (((Component)_label).gameObject.activeSelf) { ((Graphic)_label).color = Color.Lerp(_labelBaseColor, LabelRedColor, num2 * _urgency); } } public void SetOuterBoundary(float value) { if (!Mathf.Approximately(_outerBoundary, value)) { _outerBoundary = value; Texture texture = _image.texture; _image.texture = (Texture)(object)BuildVignetteTexture(64, _outerBoundary); Object.Destroy((Object)(object)texture); } } public void SetLabel(string text, float urgency = 0f) { _urgency = urgency; if (string.IsNullOrEmpty(text)) { ((Component)_label).gameObject.SetActive(false); return; } _label.text = text; ((Component)_label).gameObject.SetActive(true); } private static Texture2D BuildVignetteTexture(int size, float extent) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false); float num = (float)size * 0.5f; float num2; float num3; if (extent >= 0.5f) { num2 = (extent - 0.5f) * 0.5f; num3 = 0f; } else { num2 = 0f; num3 = 1f - 2f * extent; } float num4 = Mathf.Max(1f - num3, 0.001f); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num5 = ((float)j + 0.5f - num) / num; float num6 = ((float)i + 0.5f - num) / num; float num7 = Mathf.Max(Mathf.Abs(num5), Mathf.Abs(num6)); float num8; if (num7 < num3) { num8 = 0f; } else { float num9 = Mathf.Clamp01((num7 - num3) / num4); float num10 = num9 * num9 * (3f - 2f * num9); num8 = Mathf.Lerp(num2, 1f, num10); } val.SetPixel(j, i, new Color(1f, 1f, 1f, num8)); } } val.Apply(); return val; } } public class VignetteOverlay : MonoBehaviour { private RawImage _image; private Text _hungerLabel; private float _hungerUrgency; private static readonly Color LabelBaseColor = new Color(1f, 0.35f, 0.1f, 1f); private static readonly Color LabelRedColor = new Color(1f, 0f, 0f, 1f); private float _baseAlpha; private Color _baseColor; private float _labelPhase; private float _innerBoundary = 0.82f; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0078: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HungryViking_Vignette"); Object.DontDestroyOnLoad((Object)(object)val); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 100; GameObject val2 = new GameObject("Image"); val2.transform.SetParent(val.transform, false); _image = val2.AddComponent<RawImage>(); _image.texture = (Texture)(object)BuildVignetteTexture(64, _innerBoundary); ((Graphic)_image).raycastTarget = false; ((Graphic)_image).color = Color.clear; RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; GameObject val4 = new GameObject("HungerLabel"); val4.transform.SetParent(val.transform, false); _hungerLabel = val4.AddComponent<Text>(); _hungerLabel.text = ""; _hungerLabel.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); _hungerLabel.fontSize = 22; _hungerLabel.fontStyle = (FontStyle)1; _hungerLabel.alignment = (TextAnchor)1; ((Graphic)_hungerLabel).color = new Color(1f, 0.35f, 0.1f, 1f); ((Graphic)_hungerLabel).raycastTarget = false; ((Component)_hungerLabel).gameObject.SetActive(false); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = new Vector2(0f, 1f); val5.anchorMax = new Vector2(1f, 1f); val5.pivot = new Vector2(0.5f, 1f); val5.offsetMin = new Vector2(0f, -70f); val5.offsetMax = new Vector2(0f, -40f); } public void SetBase(float alpha, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _baseAlpha = alpha; _baseColor = color; } private void Update() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) float num = 0f; if (_hungerUrgency > 0f) { float num2 = Mathf.Lerp(0.2f, 1f, _hungerUrgency); _labelPhase = (_labelPhase + num2 * (float)Math.PI * 2f * Time.deltaTime) % ((float)Math.PI * 2f); num = (Mathf.Sin(_labelPhase) + 1f) * 0.5f; } float num3 = 1f - _hungerUrgency * 0.5f; float num4 = _baseAlpha * Mathf.Lerp(num3, 1f, num); ((Graphic)_image).color = (Color)((num4 < 0.005f) ? Color.clear : new Color(_baseColor.r, _baseColor.g, _baseColor.b, num4)); if (((Component)_hungerLabel).gameObject.activeSelf) { ((Graphic)_hungerLabel).color = Color.Lerp(LabelBaseColor, LabelRedColor, num * _hungerUrgency); } } public void SetInnerBoundary(float value) { if (!Mathf.Approximately(_innerBoundary, value)) { _innerBoundary = value; Texture texture = _image.texture; _image.texture = (Texture)(object)BuildVignetteTexture(64, _innerBoundary); Object.Destroy((Object)(object)texture); } } public void SetHungerLabel(string text, float urgency = 0f) { _hungerUrgency = urgency; if (string.IsNullOrEmpty(text)) { ((Component)_hungerLabel).gameObject.SetActive(false); return; } _hungerLabel.text = text; ((Component)_hungerLabel).gameObject.SetActive(true); } private static Texture2D BuildVignetteTexture(int size, float innerBoundary) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false); float num = (float)size * 0.5f; float num2 = Mathf.Max(1f - innerBoundary, 0.001f); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num3 = ((float)j + 0.5f - num) / num; float num4 = ((float)i + 0.5f - num) / num; float num5 = Mathf.Clamp01((Mathf.Max(Mathf.Abs(num3), Mathf.Abs(num4)) - innerBoundary) / num2); float num6 = num5 * num5 * (3f - 2f * num5); val.SetPixel(j, i, new Color(1f, 1f, 1f, num6)); } } val.Apply(); return val; } }