Decompiled source of EatMoreWorkMore v1.0.0

BepInEx/plugins/EatMoreWorkMore/EatMoreWorkMore.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Eremite.Characters.Villagers;
using Eremite.Model;
using Eremite.Services;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("EatMoreWorkMore")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+055f62ae4651939356b97df61e718dba47ac37f9")]
[assembly: AssemblyProduct("EatMoreWorkMore")]
[assembly: AssemblyTitle("EatMoreWorkMore")]
[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 EatMoreWorkMore
{
	internal static class Descriptions
	{
		internal static readonly Dictionary<string, string> FullBellyClause = new Dictionary<string, string>
		{
			["en"] = "Additional stacks beyond the first extend the time before the next break by {BREAK_BONUS}.",
			["cs"] = "Každý další stack nad rámec prvního prodlouží čas do další přestávky o {BREAK_BONUS}.",
			["de"] = "Jeder weitere Stapel über den ersten hinaus verlängert die Zeit bis zur nächsten Pause um {BREAK_BONUS}.",
			["es"] = "Cada acumulación adicional más allá de la primera prolonga el tiempo hasta el siguiente descanso en {BREAK_BONUS}.",
			["es-LATAM"] = "Cada acumulación adicional más allá de la primera prolonga el tiempo hasta el siguiente descanso en {BREAK_BONUS}.",
			["fr"] = "Chaque cumul supplémentaire au-delà du premier prolonge le temps avant la prochaine pause de {BREAK_BONUS}.",
			["hu"] = "Az elsőn túli minden további halmozódás {BREAK_BONUS}-kal meghosszabbítja a következő pihenőig hátralévő időt.",
			["it"] = "Ogni accumulo oltre il primo prolunga il tempo prima della pausa successiva di {BREAK_BONUS}.",
			["ja"] = "最初の1つを超えるスタックごとに、次の休憩までの時間が{BREAK_BONUS}延びます。",
			["ko"] = "첫 번째를 초과하는 중첩마다 다음 휴식까지의 시간이 {BREAK_BONUS}만큼 늘어납니다.",
			["pl"] = "Każde dodatkowe naliczenie powyżej pierwszego wydłuża czas do następnej przerwy o {BREAK_BONUS}.",
			["pt"] = "Cada acúmulo além do primeiro prolonga o tempo até a próxima pausa em {BREAK_BONUS}.",
			["ru"] = "Каждое дополнительное наложение сверх первого увеличивает время до следующего отдыха на {BREAK_BONUS}.",
			["th"] = "การซ\u0e49อนแต\u0e48ละคร\u0e31\u0e49งท\u0e35\u0e48เก\u0e34นคร\u0e31\u0e49งแรกจะย\u0e37ดเวลาก\u0e48อนการพ\u0e31กคร\u0e31\u0e49งถ\u0e31ดไปออกไป {BREAK_BONUS}",
			["tr"] = "İlkin ötesindeki her ek yığın, sonraki molaya kadar olan süreyi {BREAK_BONUS} uzatır.",
			["ua"] = "Кожне додаткове накопичення понад перше збільшує час до наступного відпочинку на {BREAK_BONUS}.",
			["zh-CN"] = "超过第一层的每一层堆叠都会使距离下一次休息的时间延长{BREAK_BONUS}。",
			["zh-CT"] = "超過第一層的每一層堆疊都會使距離下一次休息的時間延長{BREAK_BONUS}。"
		};

		internal static readonly Dictionary<string, string> HungerClause = new Dictionary<string, string>
		{
			["en"] = "Each stack also makes the next break come {BREAK_PENALTY} sooner.",
			["cs"] = "Každý stack navíc také uspíší další přestávku o {BREAK_PENALTY}.",
			["de"] = "Jeder Stapel lässt die nächste Pause außerdem um {BREAK_PENALTY} früher eintreten.",
			["es"] = "Cada acumulación también adelanta el siguiente descanso un {BREAK_PENALTY}.",
			["es-LATAM"] = "Cada acumulación también adelanta el siguiente descanso un {BREAK_PENALTY}.",
			["fr"] = "Chaque cumul avance également la prochaine pause de {BREAK_PENALTY}.",
			["hu"] = "Minden halmozódás {BREAK_PENALTY}-kal korábbra is hozza a következő pihenőt.",
			["it"] = "Ogni accumulo anticipa inoltre la pausa successiva del {BREAK_PENALTY}.",
			["ja"] = "スタックごとに、次の休憩も{BREAK_PENALTY}早まります。",
			["ko"] = "중첩마다 다음 휴식이 {BREAK_PENALTY}만큼 빨라집니다.",
			["pl"] = "Każde naliczenie przyspiesza również następną przerwę o {BREAK_PENALTY}.",
			["pt"] = "Cada acúmulo também adianta a próxima pausa em {BREAK_PENALTY}.",
			["ru"] = "Каждое наложение также приближает следующий отдых на {BREAK_PENALTY}.",
			["th"] = "การซ\u0e49อนแต\u0e48ละคร\u0e31\u0e49งย\u0e31งทำให\u0e49การพ\u0e31กคร\u0e31\u0e49งถ\u0e31ดไปมาเร\u0e47วข\u0e36\u0e49น {BREAK_PENALTY}",
			["tr"] = "Her yığın ayrıca sonraki molayı {BREAK_PENALTY} öne çeker.",
			["ua"] = "Кожне накопичення також наближає наступний відпочинок на {BREAK_PENALTY}.",
			["zh-CN"] = "每层堆叠还会使下一次休息提前{BREAK_PENALTY}。",
			["zh-CT"] = "每層堆疊還會使下一次休息提前{BREAK_PENALTY}。"
		};

		internal static string Separator(string code)
		{
			if (code == null || (!code.StartsWith("ja") && !code.StartsWith("zh")))
			{
				return " ";
			}
			return "";
		}
	}
	[BepInPlugin("com.sneakertack.eatmoreworkmore", "Eat More, Work More", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<float> MoreThanOneComplexFoodStackBonus;

		internal static ConfigEntry<float> ZeroComplexFoodPenalty;

		internal static ConfigEntry<float> HungerPenaltyPerStack;

		internal static ConfigEntry<float> BreakIntervalFloor;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> DebugLogging;

		private void Awake()
		{
			//IL_005b: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_0098: 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_00cb: Expected O, but got Unknown
			//IL_00d0: 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_0103: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables/disables the mod.");
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Log a debug line to the BepInEx console/log each time a villager takes a break, showing needs met plus the resulting break-time multiplier.");
			ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "com.sneakertack.eatmoreworkmore.Balance.cfg"), true);
			MoreThanOneComplexFoodStackBonus = val.Bind<float>("Balance", "MoreThanOneComplexFoodStackBonus", 0.5f, new ConfigDescription("Break-time increase per complex food need met beyond the first. E.g. 0.5 => when 2 needs met, next break comes 50% later. When 3, 100% later.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			ZeroComplexFoodPenalty = val.Bind<float>("Balance", "ZeroComplexFoodPenalty", 0.15f, new ConfigDescription("Break-time reduction when no complex food need was met this break (villager ate basic food, non-preferred complex food, or went hungry). E.g. 0.15 => next break comes 15% sooner (before any Hunger stacks).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			HungerPenaltyPerStack = val.Bind<float>("Balance", "HungerPenaltyPerStack", 0.15f, new ConfigDescription("Additional break-time reduction per Hunger stack (on top of ZeroComplexFoodPenalty).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			BreakIntervalFloor = val.Bind<float>("Balance", "BreakIntervalFloor", 0.4f, new ConfigDescription("Lower bound on the break-time multiplier. ZeroComplexFood and Hunger penalties can't cause break-time to go lower than this. E.g. 0.4 => 40% is the shortest a break can be reduced to.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			new Harmony("com.sneakertack.eatmoreworkmore").PatchAll();
			Log.LogInfo((object)"Eat More, Work More loaded.");
		}
	}
	[HarmonyPatch(typeof(Villager), "GetNeedsInterval")]
	internal static class NeedsIntervalPatch
	{
		private static void Postfix(Villager __instance, ref float __result)
		{
			if (Plugin.Enabled.Value)
			{
				__result *= ComputeFactor(__instance);
				float needsInterval = __instance.raceModel.needsInterval;
				__result = Mathf.Clamp(__result, needsInterval * 0.1f, needsInterval * 10f);
			}
		}

		internal static float ComputeFactor(Villager villager)
		{
			if (villager.effectsManager == null || villager.state.lastNeedsFulfillment == 0f)
			{
				return 1f;
			}
			float num = 1f;
			int num2 = CountComplexFoodNeedsMet(villager);
			if (num2 >= 1)
			{
				return 1f + Plugin.MoreThanOneComplexFoodStackBonus.Value * (float)(num2 - 1);
			}
			int stacksOf = villager.effectsManager.GetStacksOf(villager.raceModel.hungerEffect);
			num -= Plugin.ZeroComplexFoodPenalty.Value + Plugin.HungerPenaltyPerStack.Value * (float)stacksOf;
			return Math.Max(num, Plugin.BreakIntervalFloor.Value);
		}

		internal static int CountComplexFoodNeedsMet(Villager villager)
		{
			int num = 0;
			NeedModel[] needs = villager.raceModel.needs;
			foreach (NeedModel val in needs)
			{
				if (val.category.solveHunger && villager.IsNeedFulfilled(val))
				{
					num++;
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(TextsService), "GetLocaText")]
	internal static class PerkDescriptionPatch
	{
		private const string FullBellyDescKey = "VillagerPerk_ComplexFoodBonus_Desc";

		private const string HungerDescKey = "ResolveEffect_HungerPenalty_Description";

		private static void Postfix(TextsService __instance, string key, ref string __result)
		{
			if (!Plugin.Enabled.Value)
			{
				return;
			}
			Dictionary<string, string> dictionary = ((key == "VillagerPerk_ComplexFoodBonus_Desc") ? Descriptions.FullBellyClause : ((key == "ResolveEffect_HungerPenalty_Description") ? Descriptions.HungerClause : null));
			if (dictionary != null)
			{
				string langCode = GetLangCode(__instance);
				if (!dictionary.TryGetValue(langCode, out var value))
				{
					value = dictionary["en"];
				}
				value = value.Replace("{BREAK_BONUS}", __instance.GetPercentage(Plugin.MoreThanOneComplexFoodStackBonus.Value, false, false)).Replace("{BREAK_PENALTY}", __instance.GetPercentage(Plugin.HungerPenaltyPerStack.Value, false, false));
				__result = __result + Descriptions.Separator(langCode) + value;
			}
		}

		private static string GetLangCode(TextsService svc)
		{
			try
			{
				return svc.CurrentLocaCode ?? "en";
			}
			catch
			{
				return "en";
			}
		}
	}
	[HarmonyPatch(typeof(VillagerNeedsConsumptionManager), "FulfillNeeds")]
	internal static class BreakDebugLogPatch
	{
		private static void Postfix(Villager ___villager)
		{
			if (Plugin.DebugLogging.Value && ___villager?.effectsManager != null)
			{
				int num = NeedsIntervalPatch.CountComplexFoodNeedsMet(___villager);
				int stacksOf = ___villager.effectsManager.GetStacksOf(___villager.raceModel.hungerEffect);
				float num2 = NeedsIntervalPatch.ComputeFactor(___villager);
				Plugin.Log.LogInfo((object)$"[EMWM] {Describe(___villager)}: {num} Complex Food needs met, {stacksOf} hunger => interval x{num2:0.##}");
			}
		}

		private static string Describe(Villager villager)
		{
			string text = villager.state?.name;
			string text2 = null;
			try
			{
				RaceModel raceModel = villager.raceModel;
				object obj;
				if (raceModel == null)
				{
					obj = null;
				}
				else
				{
					LocaText displayName = raceModel.displayName;
					obj = ((displayName != null) ? displayName.Text : null);
				}
				text2 = (string)obj;
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text))
			{
				return text2 ?? "villager";
			}
			if (text2 != null)
			{
				return text + " (" + text2 + ")";
			}
			return text;
		}
	}
}