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 Hunger Pangs v1.2.2
plugins/HungerPangs.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("HungerPangs")] [assembly: AssemblyDescription("Valheim HungerPangs Mod by DrummerCraig")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HungerPangs")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ea00b146-e2c4-41cd-8e70-7bbada299b8e")] [assembly: AssemblyFileVersion("1.2.2.0")] [assembly: AssemblyVersion("1.2.2.0")] namespace DrummerCraig.HungerPangs; [BepInPlugin("drummercraig.hungerpangs", "Hunger Pangs", "1.2.2")] public class HungerPangs : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "UpdateFood")] private static class Player_UpdateFood_Patch { private static void Postfix(Player __instance) { if ((!_nearWorkbench && !_onBoat) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } float deltaTime = Time.deltaTime; foreach (Food food in __instance.GetFoods()) { if (food?.m_item != null) { food.m_time = Mathf.Min(food.m_time + deltaTime, food.m_item.m_shared.m_foodBurnTime); } } } } [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class Character_RPC_Damage_Patch { private static void Prefix(Character __instance, HitData hit) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Character attacker = hit.GetAttacker(); if ((Object)(object)attacker != (Object)null && !attacker.IsPlayer()) { _lastEnemyHitTime = Time.time; } if (hit.m_damage.m_frost > 0f) { _frostHitTimes.Enqueue(Time.time); } } } } private ConfigEntry<bool> modStatus; private ConfigEntry<bool> autoEat; private ConfigEntry<bool> foodExpiryNotify; private ConfigEntry<int> autoEatPercent; private ConfigEntry<int> foodExpiryPercent; private ConfigEntry<bool> autoEatNotify; private ConfigEntry<bool> lowSupplyNotify; private ConfigEntry<int> lowSupplyCount; private ConfigEntry<bool> autoMead; private ConfigEntry<int> autoMeadHealthPercent; private ConfigEntry<bool> autoMeadOnlyOnEnemyHit; private ConfigEntry<float> autoMeadEnemyHitWindow; private ConfigEntry<bool> autoMeadRequireMaxHealth; private ConfigEntry<bool> autoMeadNotify; private ConfigEntry<bool> autoPoisonMead; private ConfigEntry<float> autoPoisonMeadRange; private ConfigEntry<bool> autoPoisonMeadNotify; private ConfigEntry<bool> autoFireMead; private ConfigEntry<float> autoFireMeadRange; private ConfigEntry<bool> autoFireMeadNotify; private ConfigEntry<bool> autoFrostMead; private ConfigEntry<int> autoFrostMeadTickCount; private ConfigEntry<float> autoFrostMeadTickWindow; private ConfigEntry<bool> autoFrostMeadNotify; private ConfigEntry<bool> pauseFoodNearWorkbench; private ConfigEntry<bool> pauseFoodOnBoat; private static float _lastEnemyHitTime = float.MinValue; private static bool _nearWorkbench; private static bool _onBoat; private static readonly List<Character> _nearbyCharacterBuffer = new List<Character>(); private static readonly Queue<float> _frostHitTimes = new Queue<float>(); private static readonly HashSet<string> _poisonEnemyPrefabs = new HashSet<string>(); private static readonly HashSet<string> _fireEnemyPrefabs = new HashSet<string>(); private static readonly HashSet<string> _checkedPrefabs = new HashSet<string>(); private const float MeleeRange = 3f; private const float MeleeRangeSq = 9f; private readonly HashSet<string> hasShown = new HashSet<string>(); private readonly HashSet<string> seenThisTick = new HashSet<string>(); private readonly HashSet<string> lowSupplyShown = new HashSet<string>(); private Predicate<string> _notSeenThisTick; private void Awake() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Expected O, but got Unknown //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Expected O, but got Unknown //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Expected O, but got Unknown //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Expected O, but got Unknown //IL_043a: Unknown result type (might be due to invalid IL or missing references) modStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "01. Mod Status", true, "Master toggle for the entire mod. When disabled, no auto-eating or notifications occur."); autoEat = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "02. Auto-Eat", true, "Automatically re-eat food before it expires. When disabled, the mod will only show notifications if NotificationsEnabled is on, allowing you to eat manually on cue."); autoEatPercent = ((BaseUnityPlugin)this).Config.Bind<int>("General", "03. Auto-Eat Percent", 5, new ConfigDescription("Percentage of a food's total duration remaining when it is automatically re-eaten. Food becomes eligible to re-eat at 50% remaining (when it starts blinking), so this is your window. Lower values eat later and waste less food; higher values re-eat sooner after becoming eligible. Example: 5 = eat when 5% remains (e.g. ~1.5 min of a 30-min food). Requires Auto-Eat Enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 49), Array.Empty<object>())); autoEatNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "04. Auto-Eat Notify", true, "Show a HUD notification when a food item is automatically eaten. Requires AutomaticallyEat."); foodExpiryNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "05. Food Expiry Notify", true, "Show a HUD notification when a food item nears its expiry threshold. Useful on its own when Auto-Eat is Disabled,as a manual reminder to eat."); foodExpiryPercent = ((BaseUnityPlugin)this).Config.Bind<int>("General", "06. Food Expiry Percent", 30, new ConfigDescription("Percentage of a food's total duration remaining when the HUD notification appears. Food becomes eligible to re-eat at 50% remaining (when it starts blinking). Set this higher than Auto-Eat Percent so the notification fires before auto-eat. Example: 30 = notify when 30% remains (e.g. ~9 min of a 30-min food). Requires Notifications.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); lowSupplyNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "07. Low Supply Notify", true, "Show a HUD notification when AutomaticallyEat is enabled, a food item is consumed and the remaining count in your inventory is at or below the LowSupplyThreshold."); lowSupplyCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "08. Low Supply Count", 1, "The number of food items in your inventory for the LowSupplyNotification to appear."); pauseFoodNearWorkbench = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "09. Pause Near Workbench", true, "Pause food expiry timers when within range of a workbench. Food effects (health and stamina regen) continue normally — only the countdown is paused."); pauseFoodOnBoat = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "10. Pause On Boat", true, "Pause food expiry timers while sailing on a boat. Food effects (health and stamina regen) continue normally — only the countdown is paused."); autoMead = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Mead", "01. Auto Health Mead", true, "Automatically drink a health mead when your health drops below the configured threshold."); autoMeadHealthPercent = ((BaseUnityPlugin)this).Config.Bind<int>("Health Mead", "02. Health Threshold", 30, new ConfigDescription("Health percentage below which a health mead will be automatically consumed. Example: 40 = drink when health drops below 40% of your maximum.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 99), Array.Empty<object>())); autoMeadOnlyOnEnemyHit = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Mead", "03. Only On Enemy Hit", true, "Only auto-drink when the health drop was caused by an enemy. Prevents wasting meads on fall damage, lava, or other environmental hazards when not in combat."); autoMeadEnemyHitWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Health Mead", "04. Enemy Hit Window", 5f, new ConfigDescription("Seconds after the last enemy hit during which the mead trigger remains active. Requires Only On Enemy Hit. Example: 5 = the mead can fire within 5 seconds of being struck.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); autoMeadRequireMaxHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Mead", "05. Require Sufficient Max Health", false, "Only drink a mead if your maximum health is at least equal to the mead's total healing value. Prevents drinking a mead that heals more than your health cap, which would waste the excess. Meads that exceed your max health are skipped; the next-strongest eligible mead is tried instead."); autoMeadNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("Health Mead", "06. Notify", true, "Show a HUD notification when a health mead is automatically consumed."); autoPoisonMead = ((BaseUnityPlugin)this).Config.Bind<bool>("Poison Resist Mead", "01. Auto Poison Mead", true, "Automatically drink a poison resist mead when a nearby enemy can deal poison damage."); autoPoisonMeadRange = ((BaseUnityPlugin)this).Config.Bind<float>("Poison Resist Mead", "02. Detection Range", 4f, new ConfigDescription("Radius in meters to scan for poison-capable enemies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); autoPoisonMeadNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("Poison Resist Mead", "03. Notify", true, "Show a HUD notification when a poison resist mead is automatically consumed."); autoFireMead = ((BaseUnityPlugin)this).Config.Bind<bool>("Fire Resist Mead", "01. Auto Fire Mead", true, "Automatically drink a fire resist mead when a nearby enemy can deal fire damage."); autoFireMeadRange = ((BaseUnityPlugin)this).Config.Bind<float>("Fire Resist Mead", "02. Detection Range", 15f, new ConfigDescription("Radius in meters to scan for fire-capable enemies.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>())); autoFireMeadNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("Fire Resist Mead", "03. Notify", true, "Show a HUD notification when a fire resist mead is automatically consumed."); autoFrostMead = ((BaseUnityPlugin)this).Config.Bind<bool>("Frost Resist Mead", "01. Auto Frost Mead", true, "Automatically drink a frost resist mead after receiving repeated frost damage hits."); autoFrostMeadTickCount = ((BaseUnityPlugin)this).Config.Bind<int>("Frost Resist Mead", "02. Frost Tick Count", 3, new ConfigDescription("Number of frost damage hits within the time window required to trigger auto-consume.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); autoFrostMeadTickWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Frost Resist Mead", "03. Frost Tick Window", 10f, new ConfigDescription("Seconds over which frost hits are counted toward the trigger threshold.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>())); autoFrostMeadNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("Frost Resist Mead", "04. Notify", true, "Show a HUD notification when a frost resist mead is automatically consumed."); _notSeenThisTick = (string key) => !seenThisTick.Contains(key); new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID).PatchAll(); ((MonoBehaviour)this).StartCoroutine(FoodCheckLoop()); ((MonoBehaviour)this).StartCoroutine(MeadCheckLoop()); } private IEnumerator FoodCheckLoop() { WaitForSeconds wait = new WaitForSeconds(1f); while (true) { yield return wait; CheckFoods(); } } private IEnumerator MeadCheckLoop() { WaitForSeconds wait = new WaitForSeconds(0.5f); while (true) { yield return wait; CheckMeads(); CheckProximityResistMeads(); CheckFrostResistMeads(); } } private void CheckFoods() { Player localPlayer = Player.m_localPlayer; _nearWorkbench = (Object)(object)localPlayer != (Object)null && pauseFoodNearWorkbench.Value && NearWorkbench(localPlayer); _onBoat = (Object)(object)localPlayer != (Object)null && pauseFoodOnBoat.Value && IsOnBoat(localPlayer); if (!modStatus.Value || (Object)(object)localPlayer == (Object)null) { return; } Humanoid val = (Humanoid)(object)localPlayer; Inventory inventory = val.GetInventory(); List<Food> foods = localPlayer.GetFoods(); seenThisTick.Clear(); for (int i = 0; i < foods.Count; i++) { Food val2 = foods[i]; string name = val2.m_item.m_shared.m_name; seenThisTick.Add(name); float time = val2.m_time; float foodBurnTime = val2.m_item.m_shared.m_foodBurnTime; float num = ((foodBurnTime > 0f) ? (time / foodBurnTime * 100f) : 0f); if (!val2.CanEatAgain()) { hasShown.Remove(name); lowSupplyShown.Remove(name); continue; } if (foodExpiryNotify.Value && !hasShown.Contains(name) && num <= (float)foodExpiryPercent.Value) { string arg = Localization.instance.Localize(val2.m_item.m_shared.m_name); int num2 = Mathf.CeilToInt(time / 60f); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, $"{arg} expires in {num2} min", 0, (Sprite)null, false); } hasShown.Add(name); } if (!autoEat.Value || !(num <= (float)autoEatPercent.Value)) { continue; } ItemData item = inventory.GetItem(name, -1, false); if (item == null || !val.ConsumeItem(inventory, item, false)) { continue; } hasShown.Remove(name); if (autoEatNotify.Value) { string text = Localization.instance.Localize(val2.m_item.m_shared.m_name); MessageHud instance2 = MessageHud.instance; if (instance2 != null) { instance2.ShowMessage((MessageType)2, text + " automatically re-eaten", 0, (Sprite)null, false); } } if (!lowSupplyNotify.Value || lowSupplyCount.Value <= 0 || lowSupplyShown.Contains(name)) { continue; } int num3 = inventory.CountItems(name, -1, true); if (num3 <= lowSupplyCount.Value) { string arg2 = Localization.instance.Localize(val2.m_item.m_shared.m_name); MessageHud instance3 = MessageHud.instance; if (instance3 != null) { instance3.ShowMessage((MessageType)2, $"Low supply: {num3} {arg2} remaining", 0, (Sprite)null, false); } lowSupplyShown.Add(name); } } hasShown.RemoveWhere(_notSeenThisTick); lowSupplyShown.RemoveWhere(_notSeenThisTick); } private void CheckMeads() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (!modStatus.Value || !autoMead.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).GetHealthPercentage() * 100f >= (float)autoMeadHealthPercent.Value || (autoMeadOnlyOnEnemyHit.Value && Time.time - _lastEnemyHitTime > autoMeadEnemyHitWindow.Value)) { return; } Humanoid val = (Humanoid)(object)localPlayer; Inventory inventory = val.GetInventory(); List<ItemData> healthMeads = GetHealthMeads(inventory); float maxHealth = ((Character)localPlayer).GetMaxHealth(); SEMan sEMan = ((Character)localPlayer).GetSEMan(); foreach (ItemData item in healthMeads) { StatusEffect consumeStatusEffect = item.m_shared.m_consumeStatusEffect; if ((Object)(object)consumeStatusEffect != (Object)null && sEMan.HaveStatusEffect(consumeStatusEffect.NameHash())) { continue; } if (autoMeadRequireMaxHealth.Value) { float healthOverTime = ((SE_Stats)item.m_shared.m_consumeStatusEffect).m_healthOverTime; if (maxHealth < healthOverTime) { continue; } } if (!val.ConsumeItem(inventory, item, false)) { continue; } if (autoMeadNotify.Value) { string text = Localization.instance.Localize(item.m_shared.m_name); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, text + " automatically consumed", 0, (Sprite)null, false); } } break; } } private static bool NearWorkbench(Player player) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return (Object)(object)CraftingStation.FindClosestStationInRange("$piece_workbench", ((Component)player).transform.position, 20f) != (Object)null; } private static bool IsOnBoat(Player player) { return ((Character)player).IsAttachedToShip(); } private void CheckProximityResistMeads() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_011d: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) bool flag = modStatus.Value && autoPoisonMead.Value; bool flag2 = modStatus.Value && autoFireMead.Value; if (!flag && !flag2) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float num = 0f; if (flag) { num = Mathf.Max(num, autoPoisonMeadRange.Value); } if (flag2) { num = Mathf.Max(num, autoFireMeadRange.Value); } bool flag3 = false; bool flag4 = false; _nearbyCharacterBuffer.Clear(); Character.GetCharactersInRange(((Component)localPlayer).transform.position, num, _nearbyCharacterBuffer); float num2 = autoPoisonMeadRange.Value * autoPoisonMeadRange.Value; float num3 = autoFireMeadRange.Value * autoFireMeadRange.Value; foreach (Character item in _nearbyCharacterBuffer) { if ((Object)(object)item == (Object)null || item.IsPlayer() || item.IsDead()) { continue; } Vector3 val = ((Component)item).transform.position - ((Component)localPlayer).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (IsThreateningPlayer(item, localPlayer, sqrMagnitude)) { string prefabName = GetPrefabName(item); EnsureCached(prefabName, item); if (flag && !flag3 && sqrMagnitude <= num2 && _poisonEnemyPrefabs.Contains(prefabName)) { flag3 = true; } if (flag2 && !flag4 && sqrMagnitude <= num3 && _fireEnemyPrefabs.Contains(prefabName)) { flag4 = true; } if (flag3 && flag4) { break; } } } if (flag3) { ConsumeResistMead(localPlayer, autoPoisonMeadNotify, (DamageType)256); } if (flag4) { ConsumeResistMead(localPlayer, autoFireMeadNotify, (DamageType)32); } } private static bool IsThreateningPlayer(Character c, Player localPlayer, float distSq) { if (distSq <= 9f) { return true; } MonsterAI component = ((Component)c).GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null) { return ((BaseAI)component).GetTargetCreature() == localPlayer; } return false; } private static string GetPrefabName(Character c) { return ((Object)((Component)c).gameObject).name.Replace("(Clone)", "").Trim(); } private static void EnsureCached(string prefab, Character c) { if (_checkedPrefabs.Contains(prefab)) { return; } Humanoid val = (Humanoid)(object)((c is Humanoid) ? c : null); if ((Object)(object)val == (Object)null) { _checkedPrefabs.Add(prefab); return; } foreach (ItemData allItem in val.GetInventory().GetAllItems()) { if (allItem.m_shared.m_damages.m_poison > 0f) { _poisonEnemyPrefabs.Add(prefab); } if (allItem.m_shared.m_damages.m_fire > 0f) { _fireEnemyPrefabs.Add(prefab); } } ItemData currentWeapon = val.GetCurrentWeapon(); if (currentWeapon != null) { if (currentWeapon.m_shared.m_damages.m_poison > 0f) { _poisonEnemyPrefabs.Add(prefab); } if (currentWeapon.m_shared.m_damages.m_fire > 0f) { _fireEnemyPrefabs.Add(prefab); } } _checkedPrefabs.Add(prefab); } private void ConsumeResistMead(Player localPlayer, ConfigEntry<bool> notify, DamageType type) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)localPlayer).GetInventory(); SEMan sEMan = ((Character)localPlayer).GetSEMan(); foreach (ItemData resistMead in GetResistMeads(inventory, type)) { StatusEffect consumeStatusEffect = resistMead.m_shared.m_consumeStatusEffect; if ((Object)(object)consumeStatusEffect != (Object)null && sEMan.HaveStatusEffect(consumeStatusEffect.NameHash())) { break; } if (!((Humanoid)localPlayer).ConsumeItem(inventory, resistMead, false)) { continue; } if (notify.Value) { string text = Localization.instance.Localize(resistMead.m_shared.m_name); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, text + " automatically consumed", 0, (Sprite)null, false); } } break; } } private void CheckFrostResistMeads() { if (!modStatus.Value || !autoFrostMead.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float num = Time.time - autoFrostMeadTickWindow.Value; while (_frostHitTimes.Count > 0 && _frostHitTimes.Peek() < num) { _frostHitTimes.Dequeue(); } SEMan sEMan = ((Character)localPlayer).GetSEMan(); bool num2 = sEMan.HaveStatusEffect(StringExtensionMethods.GetStableHashCode("Freezing")); bool flag = _frostHitTimes.Count >= autoFrostMeadTickCount.Value; if (!num2 && !flag) { return; } Humanoid val = (Humanoid)(object)localPlayer; Inventory inventory = val.GetInventory(); foreach (ItemData resistMead in GetResistMeads(inventory, (DamageType)64)) { StatusEffect consumeStatusEffect = resistMead.m_shared.m_consumeStatusEffect; if ((Object)(object)consumeStatusEffect != (Object)null && sEMan.HaveStatusEffect(consumeStatusEffect.NameHash())) { _frostHitTimes.Clear(); break; } if (!val.ConsumeItem(inventory, resistMead, false)) { continue; } _frostHitTimes.Clear(); if (autoFrostMeadNotify.Value) { string text = Localization.instance.Localize(resistMead.m_shared.m_name); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, text + " automatically consumed", 0, (Sprite)null, false); } } break; } } private static List<ItemData> GetResistMeads(Inventory inventory, DamageType type) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if ((int)allItem.m_shared.m_itemType != 2) { continue; } StatusEffect consumeStatusEffect = allItem.m_shared.m_consumeStatusEffect; SE_Stats val = (SE_Stats)(object)((consumeStatusEffect is SE_Stats) ? consumeStatusEffect : null); if (val == null) { continue; } foreach (DamageModPair mod in val.m_mods) { if (mod.m_type == type && (int)mod.m_modifier != 0) { list.Add(allItem); break; } } } return list; } private static List<ItemData> GetHealthMeads(Inventory inventory) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if ((int)allItem.m_shared.m_itemType == 2) { StatusEffect consumeStatusEffect = allItem.m_shared.m_consumeStatusEffect; SE_Stats val = (SE_Stats)(object)((consumeStatusEffect is SE_Stats) ? consumeStatusEffect : null); if (val != null && val.m_healthOverTime > 0f) { list.Add(allItem); } } } list.Sort(delegate(ItemData a, ItemData b) { //IL_000b: 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) float healthOverTime = ((SE_Stats)a.m_shared.m_consumeStatusEffect).m_healthOverTime; float healthOverTime2 = ((SE_Stats)b.m_shared.m_consumeStatusEffect).m_healthOverTime; return healthOverTime2.CompareTo(healthOverTime); }); return list; } }