Decompiled source of BossProgressFoodDuration v1.1.0

BossProgressFoodDuration.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("BossProgressFoodDuration")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BossProgressFoodDuration")]
[assembly: AssemblyTitle("BossProgressFoodDuration")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BossProgressFoodDuration
{
	[BepInPlugin("com.bossprogressfoodduration", "BossProgressFoodDuration", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.bossprogressfoodduration";

		public const string PluginName = "BossProgressFoodDuration";

		public const string PluginVersion = "1.1.0";

		private static readonly string[] BossKeys = new string[7] { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader" };

		private static readonly string[] BossNames = new string[7] { "Eikthyr", "Elder", "Bonemass", "Moder", "Yagluth", "Queen", "Fader" };

		internal static ConfigEntry<bool> DisableFoodDecay;

		internal static ConfigEntry<bool> AffectPlatters;

		internal static ConfigEntry<bool> FillOnEat;

		private static readonly HashSet<string> PlatterPrefabs = new HashSet<string> { "FeastMeadows", "FeastBlackforest", "FeastSwamps", "FeastMountains", "FeastPlains", "FeastOceans", "FeastMistlands", "FeastAshlands", "FeastDeepNorth" };

		private static readonly Dictionary<SharedData, float> OriginalSeconds = new Dictionary<SharedData, float>();

		internal static readonly HashSet<string> PlatterNames = new HashSet<string>();

		private bool _appliedAffectPlatters;

		private ConfigEntry<float> _baseMinutes;

		private readonly List<ConfigEntry<float>> _bossMinutes = new List<ConfigEntry<float>>();

		internal static float CurrentSeconds;

		private ObjectDB _appliedDb;

		private float _appliedSeconds = -1f;

		private float _nextCheck;

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00bd: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00eb: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			_baseMinutes = Bind("BaseMinutes", 20f, "Food duration (minutes) before any Forsaken has been defeated.", 100);
			float num = 20f;
			for (int i = 0; i < BossNames.Length; i++)
			{
				num = Mathf.Min(num + 5f, 50f);
				_bossMinutes.Add(Bind("After" + BossNames[i], num, "Food duration (minutes) once " + BossNames[i] + " has been defeated. If several bosses are defeated, the furthest one in progression order decides.", 99 - i));
			}
			DisableFoodDecay = ((BaseUnityPlugin)this).Config.Bind<bool>("FoodDecay", "DisableFoodDecay", false, new ConfigDescription("Off = vanilla: eaten food loses potency (your max health/stamina shrink) as its time runs down.\nOn = no decay: food gives its full bonus until its time runs out, then disappears.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = 110
			} }));
			AffectPlatters = ((BaseUnityPlugin)this).Config.Bind<bool>("FoodDuration", "AffectPlatters", false, new ConfigDescription("Off = vanilla: platters (Whole Roasted Meadow Boar, Black Forest Buffet Platter, ...) keep their own long duration.\nOn = platters are set to the same duration as every other food.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = 92
			} }));
			FillOnEat = ((BaseUnityPlugin)this).Config.Bind<bool>("FoodEffects", "FillHealthAndStaminaOnEat", false, new ConfigDescription("Off = vanilla: eating raises your maximum health and stamina, but your current health and stamina stay where they were and slowly refill.\nOn = eating a food fills your health and stamina to the new maximum right away.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = 80
			} }));
			new Harmony("com.bossprogressfoodduration").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BossProgressFoodDuration 1.1.0 loaded");
		}

		private ConfigEntry<float> Bind(string key, float value, string description, int order)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>("FoodDuration", key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = order
			} }));
		}

		private void Update()
		{
			if (Time.unscaledTime < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.unscaledTime + 1f;
			ObjectDB instance = ObjectDB.instance;
			if (!((Object)(object)instance == (Object)null) && instance.m_items.Count != 0 && !((Object)(object)ZoneSystem.instance == (Object)null))
			{
				float num = (CurrentSeconds = CurrentMinutes() * 60f);
				if (!((Object)(object)instance == (Object)(object)_appliedDb) || !Mathf.Approximately(num, _appliedSeconds) || AffectPlatters.Value != _appliedAffectPlatters)
				{
					int num2 = Apply(instance, num);
					_appliedDb = instance;
					_appliedSeconds = num;
					_appliedAffectPlatters = AffectPlatters.Value;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Set {num2} food items to {num / 60f:0.#} minutes");
				}
			}
		}

		private float CurrentMinutes()
		{
			float value = _baseMinutes.Value;
			for (int i = 0; i < BossKeys.Length; i++)
			{
				if (ZoneSystem.instance.GetGlobalKey(BossKeys[i]))
				{
					value = _bossMinutes[i].Value;
				}
			}
			return value;
		}

		internal static bool IsFood(SharedData shared)
		{
			if (shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f)
			{
				return shared.m_foodBurnTime > 0f;
			}
			return false;
		}

		private int Apply(ObjectDB db, float seconds)
		{
			int num = 0;
			List<string> list = new List<string>();
			foreach (GameObject item in db.m_items)
			{
				ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				SharedData shared = val.m_itemData.m_shared;
				if (!IsFood(shared))
				{
					continue;
				}
				if (!OriginalSeconds.TryGetValue(shared, out var value))
				{
					value = shared.m_foodBurnTime;
					OriginalSeconds[shared] = value;
				}
				if (PlatterPrefabs.Contains(((Object)item).name))
				{
					PlatterNames.Add(shared.m_name);
					if (!AffectPlatters.Value)
					{
						shared.m_foodBurnTime = value;
						list.Add($"{((Object)item).name} ({value / 60f:0.#} min)");
						continue;
					}
				}
				shared.m_foodBurnTime = seconds;
				num++;
			}
			if (list.Count > 0)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Left platters at vanilla duration: " + string.Join(", ", list)));
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Player), "EatFood")]
	internal static class Player_EatFood_Patch
	{
		private static void Prefix(ItemData item)
		{
			if (Plugin.CurrentSeconds > 0f && item != null && item.m_shared != null && Plugin.IsFood(item.m_shared) && (Plugin.AffectPlatters.Value || !Plugin.PlatterNames.Contains(item.m_shared.m_name)))
			{
				item.m_shared.m_foodBurnTime = Plugin.CurrentSeconds;
			}
		}

		private static void Postfix(Player __instance, bool __result)
		{
			if (__result && Plugin.FillOnEat.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				((Character)__instance).SetHealth(((Character)__instance).GetMaxHealth());
				((Character)__instance).AddStamina(((Character)__instance).GetMaxStamina());
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateFood")]
	internal static class Player_UpdateFood_Patch
	{
		internal static float DecayExponent()
		{
			if (!Plugin.DisableFoodDecay.Value)
			{
				return 0.3f;
			}
			return 0f;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool replaced = false;
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Mathf.Approximately(num, 0.3f))
				{
					replaced = true;
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Player_UpdateFood_Patch), "DecayExponent", (Type[])null, (Type[])null));
				}
				else
				{
					yield return instruction;
				}
			}
			if (!replaced)
			{
				Debug.LogWarning((object)"[BossProgressFoodDuration] Could not find the food decay exponent; DisableFoodDecay will have no effect.");
			}
		}
	}
}