Decompiled source of BalancedDiet v1.0.0

plugins/BalancedDiet.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BalancedDiet")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BalancedDiet")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a22c48c8-afd6-481e-9e94-2817d45a4cff")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BalancedDiet;

internal static class BalancedDietFoodValues
{
	private static readonly Dictionary<string, FoodNutrients> Values;

	static BalancedDietFoodValues()
	{
		Values = new Dictionary<string, FoodNutrients>(StringComparer.OrdinalIgnoreCase);
		Add("CookedDeerMeat", "$item_deer_meat_cooked", 3, 2, 0, 0);
		Add("CookedMeat", "$item_boar_meat_cooked", 3, 3, 0, 0);
		Add("Honey", "$item_honey", 0, 0, 3, 1);
		Add("NeckTailGrilled", "$item_necktailgrilled", 2, 2, 0, 2);
		Add("Mushroom", "$item_mushroomcommon", 0, 0, 1, 1);
		Add("Raspberry", "$item_raspberries", 0, 0, 1, 4);
		Add("BoarJerky", 1, 1, 1, 0);
		Add("CarrotSoup", 0, 0, 2, 3);
		Add("QueensJam", 0, 0, 3, 2);
		Add("MushroomYellow", 0, 0, 1, 2);
		Add("Carrot", 0, 0, 1, 2);
		Add("Blueberries", 0, 0, 2, 2);
		Add("FishCooked", 3, 1, 0, 1);
		Add("MinceMeatSauce", 3, 2, 1, 0);
		Add("DeerStew", 2, 2, 2, 2);
		Add("CookedBjornMeat", 3, 3, 0, 0);
		Add("Sausages", 4, 3, 0, 0);
		Add("BlackSoup", 2, 1, 2, 2);
		Add("SerpentMeatCooked", 5, 4, 0, 0);
		Add("SerpentStew", 5, 4, 2, 2);
		Add("ShocklateSmoothie", 0, 0, 3, 4);
		Add("TurnipStew", 1, 2, 3, 3);
		Add("CookedWolfMeat", 4, 3, 0, 0);
		Add("WolfMeatSkewer", 4, 3, 2, 1);
		Add("Onion", 0, 0, 2, 3);
		Add("OnionSoup", 0, 0, 3, 4);
		Add("Eyescream", 0, 1, 4, 2);
		Add("WolfJerky", 2, 2, 2, 0);
		Add("LoxMeat", 5, 4, 0, 0);
		Add("FishWraps", 4, 3, 3, 2);
		Add("LoxPie", 5, 4, 4, 2);
		Add("Cloudberry", 0, 0, 1, 1);
		Add("BloodPudding", 2, 2, 5, 0);
		Add("Bread", 0, 0, 7, 0);
		Add("CookedEgg", 4, 0, 0, 0);
		Add("CookedBugMeat", 5, 3, 0, 0);
		Add("CookedHareMeat", 5, 2, 0, 0);
		Add("CookedChickenMeat", 5, 3, 0, 0);
		Add("MeatPlatter", 6, 6, 0, 0);
		Add("HoneyGlazedChicken", 5, 4, 3, 2);
		Add("MisthareSupreme", 5, 4, 3, 4);
		Add("Salad", 0, 0, 4, 5);
		Add("MushroomOmelette", 3, 3, 3, 3);
		Add("FishAndBread", 6, 4, 6, 0);
		Add("MagicallyStuffedShroom", 0, 0, 4, 4);
		Add("YggdrasilPorridge", 2, 2, 6, 6);
		Add("SeekerAspic", 3, 3, 3, 3);
		Add("RoyalJelly", 0, 0, 2, 2);
		Add("MushroomMagecap", 0, 0, 2, 2);
		Add("MushroomJotunPuffs", 0, 0, 2, 2);
		Add("VikingCupcake", 2, 2, 4, 2);
		Add("CookedVoltureMeat", 6, 4, 0, 0);
		Add("CookedAsksvinMeat", 6, 5, 0, 0);
		Add("CookedBoneMawSerpentMeat", 8, 6, 0, 0);
		Add("FierySvinstew", 5, 5, 4, 3);
		Add("MashedMeat", 7, 7, 0, 0);
		Add("PiquantPie", 5, 5, 5, 5);
		Add("SpicyMarmalade", 0, 0, 6, 5);
		Add("ScorchingMedley", 0, 0, 5, 5);
		Add("RoastedCrustPie", 0, 0, 9, 0);
		Add("SizzlingBerryBroth", 0, 0, 5, 6);
		Add("SparklingShroomshake", 0, 0, 6, 6);
		Add("MarinatedGreens", 0, 0, 5, 7);
		Add("FiddleheadFern", 0, 0, 2, 3);
		Add("MushroomSmokePuff", 0, 0, 2, 3);
		Add("Vineberry", 0, 0, 3, 3);
	}

	internal static bool TryGet(ItemData item, out FoodNutrients nutrients, out string matchedId)
	{
		nutrients = default(FoodNutrients);
		matchedId = string.Empty;
		if (item == null)
		{
			return false;
		}
		try
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				string text = NormalizePrefabName(((Object)item.m_dropPrefab).name);
				if (!string.IsNullOrEmpty(text) && Values.TryGetValue(text, out nutrients))
				{
					matchedId = text;
					return true;
				}
			}
		}
		catch
		{
		}
		try
		{
			string text2 = ((item.m_shared != null) ? item.m_shared.m_name : string.Empty);
			if (!string.IsNullOrEmpty(text2) && Values.TryGetValue(text2, out nutrients))
			{
				matchedId = text2;
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static void Add(string prefabName, int protein, int fat, int carbohydrate, int vitamin)
	{
		Add(prefabName, string.Empty, protein, fat, carbohydrate, vitamin);
	}

	private static void Add(string prefabName, string localizationToken, int protein, int fat, int carbohydrate, int vitamin)
	{
		FoodNutrients value = new FoodNutrients(protein, fat, carbohydrate, vitamin);
		if (!string.IsNullOrEmpty(prefabName))
		{
			Values[prefabName] = value;
		}
		if (!string.IsNullOrEmpty(localizationToken))
		{
			Values[localizationToken] = value;
		}
	}

	private static string NormalizePrefabName(string prefabName)
	{
		if (string.IsNullOrEmpty(prefabName))
		{
			return string.Empty;
		}
		if (prefabName.EndsWith("(Clone)", StringComparison.Ordinal))
		{
			prefabName = prefabName.Substring(0, prefabName.Length - "(Clone)".Length);
		}
		return prefabName.Trim();
	}
}
internal struct FoodNutrients
{
	internal readonly int Protein;

	internal readonly int Fat;

	internal readonly int Carbohydrate;

	internal readonly int Vitamin;

	internal FoodNutrients(int protein, int fat, int carbohydrate, int vitamin)
	{
		Protein = protein;
		Fat = fat;
		Carbohydrate = carbohydrate;
		Vitamin = vitamin;
	}
}
[BepInPlugin("mint.balanceddiet", "BalancedDiet", "1.7.1")]
public sealed class BalancedDietPlugin : BaseUnityPlugin
{
	private struct DietState
	{
		internal int Protein;

		internal int Fat;

		internal int Carbohydrate;

		internal int Vitamin;
	}

	private enum DietStatus
	{
		Exhaustion,
		Unbalanced,
		Satisfactory,
		Balanced,
		Ideal
	}

	public const string ModGuid = "mint.balanceddiet";

	public const string ModName = "BalancedDiet";

	public const string ModVersion = "1.7.1";

	private const KeyCode MenuKey = (KeyCode)98;

	private const int WindowId = 18402731;

	private const double DecayIntervalSeconds = 1200.0;

	private const double DecayPersistIntervalSeconds = 5.0;

	private const int DecayAmount = 1;

	private const int DeathPenaltyAmount = 10;

	private const int MinimumBalancedNutrient = 30;

	private const int MaximumBalancedSpread = 10;

	private const int ExhaustionStatModifier = -10;

	private const int UnbalancedStatModifier = -5;

	private const int SatisfactoryStatModifier = 5;

	private const int BalancedStatModifier = 10;

	private const int IdealStatModifier = 15;

	private const float IdealStaminaRegenMultiplier = 1.1f;

	private const float IdealMovementSpeedMultiplier = 1.1f;

	private const string ProteinKey = "balanced_diet_protein";

	private const string FatKey = "balanced_diet_fat";

	private const string CarbohydrateKey = "balanced_diet_carbohydrate";

	private const string VitaminKey = "balanced_diet_vitamin";

	private const string DecayElapsedKey = "balanced_diet_decay_elapsed";

	internal static BalancedDietPlugin Instance;

	internal static ManualLogSource Log;

	private Harmony _harmony;

	private bool _menuVisible;

	private Player _lastLocalPlayer;

	private double _decayElapsedSeconds;

	private double _decayPersistElapsedSeconds;

	private static ConfigEntry<float> UiScale;

	private static ConfigEntry<bool> CloseOnEscape;

	private static ConfigEntry<bool> DebugLogs;

	private static MethodInfo _zInputGetKeyDown;

	private static MethodInfo _unityInputGetKeyDown;

	private static bool _languageReflectionCached;

	private static FieldInfo _localizationInstanceField;

	private static PropertyInfo _localizationInstanceProperty;

	private static MethodInfo _getSelectedLanguageMethod;

	private static FieldInfo _selectedLanguageField;

	private static PropertyInfo _selectedLanguageProperty;

	private static FieldInfo _terminalInstance;

	private static FieldInfo _terminalInput;

	private static FieldInfo _chatInstance;

	private static FieldInfo _chatInput;

	private static FieldInfo _characterSEMan;

	private bool _uiReady;

	private Rect _windowRect;

	private Texture2D _dimTexture;

	private Texture2D _windowTexture;

	private Texture2D _panelTexture;

	private Texture2D _rowTexture;

	private Texture2D _summaryTexture;

	private Texture2D _effectTexture;

	private Texture2D _footerTexture;

	private Texture2D _barTexture;

	private Texture2D _solidTexture;

	private Texture2D _buttonTexture;

	private Texture2D _buttonHoverTexture;

	private Texture2D _buttonActiveTexture;

	private GUIStyle _windowStyle;

	private GUIStyle _panelStyle;

	private GUIStyle _titleStyle;

	private GUIStyle _subtitleStyle;

	private GUIStyle _rowStyle;

	private GUIStyle _rowLabelStyle;

	private GUIStyle _percentStyle;

	private GUIStyle _targetStyle;

	private GUIStyle _rowHintStyle;

	private GUIStyle _summaryStyle;

	private GUIStyle _balanceValueStyle;

	private GUIStyle _dietStatusStyle;

	private GUIStyle _balanceMetaStyle;

	private GUIStyle _effectCardStyle;

	private GUIStyle _effectTitleStyle;

	private GUIStyle _effectStyle;

	private GUIStyle _footerBarStyle;

	private GUIStyle _footerStyle;

	private GUIStyle _buttonStyle;

	private void Awake()
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "UiScale", 1f, Localize("Diet window scale.", "Масштаб окна системы питания."));
		CloseOnEscape = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "CloseOnEscape", true, Localize("Close the diet window with Escape.", "Закрывать окно клавишей Escape."));
		DebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogs", false, Localize("Write nutrient changes to the log.", "Писать в лог информацию об изменении питательных веществ."));
		CacheInputMethods();
		CacheFocusedInputFields();
		_harmony = new Harmony("mint.balanceddiet");
		BalancedDietPatches.ApplyAll(_harmony);
		Log.LogInfo((object)("BalancedDiet v1.7.1 loaded. Menu key: " + ((object)(KeyCode)98/*cast due to .constrained prefix*/).ToString()));
	}

	internal static string Localize(string english, string russian)
	{
		return IsRussianLanguage() ? russian : english;
	}

	private static bool IsRussianLanguage()
	{
		try
		{
			string text = ReadSelectedGameLanguage();
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string text2 = text.Trim();
			return text2.Equals("Russian", StringComparison.OrdinalIgnoreCase) || text2.Equals("Русский", StringComparison.OrdinalIgnoreCase) || text2.Equals("ru", StringComparison.OrdinalIgnoreCase) || text2.StartsWith("ru-", StringComparison.OrdinalIgnoreCase) || text2.StartsWith("ru_", StringComparison.OrdinalIgnoreCase) || text2.IndexOf("russian", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("рус", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		catch
		{
			return false;
		}
	}

	private static string ReadSelectedGameLanguage()
	{
		CacheLanguageReflection();
		object localizationInstance = GetLocalizationInstance();
		object obj = null;
		if (_getSelectedLanguageMethod != null && (_getSelectedLanguageMethod.IsStatic || localizationInstance != null))
		{
			object obj2 = (_getSelectedLanguageMethod.IsStatic ? null : localizationInstance);
			obj = _getSelectedLanguageMethod.Invoke(obj2, null);
		}
		if (obj == null)
		{
			obj = ReadFieldValue(_selectedLanguageField, localizationInstance);
		}
		if (obj == null)
		{
			obj = ReadPropertyValue(_selectedLanguageProperty, localizationInstance);
		}
		return (obj == null) ? null : Convert.ToString(obj, CultureInfo.InvariantCulture);
	}

	private static void CacheLanguageReflection()
	{
		if (_languageReflectionCached)
		{
			return;
		}
		_languageReflectionCached = true;
		Type type = FindRuntimeType("Localization", "LocalizationManager");
		if (!(type == null))
		{
			_localizationInstanceField = FindField(type, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, "instance", "m_instance", "Instance");
			_localizationInstanceProperty = FindProperty(type, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, "instance", "Instance");
			_getSelectedLanguageMethod = type.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (_getSelectedLanguageMethod == null)
			{
				_getSelectedLanguageMethod = type.GetMethod("GetLanguage", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			}
			_selectedLanguageField = FindField(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, "m_language", "m_selectedLanguage", "selectedLanguage");
			_selectedLanguageProperty = FindProperty(type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, "SelectedLanguage", "Language");
		}
	}

	private static Type FindRuntimeType(params string[] typeNames)
	{
		if (typeNames == null)
		{
			return null;
		}
		for (int i = 0; i < typeNames.Length; i++)
		{
			Type type = AccessTools.TypeByName(typeNames[i]);
			if (type != null)
			{
				return type;
			}
		}
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		for (int j = 0; j < assemblies.Length; j++)
		{
			Type[] types;
			try
			{
				types = assemblies[j].GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				types = ex.Types;
			}
			catch
			{
				continue;
			}
			if (types == null)
			{
				continue;
			}
			foreach (Type type2 in types)
			{
				if (type2 == null)
				{
					continue;
				}
				for (int l = 0; l < typeNames.Length; l++)
				{
					if (type2.Name.Equals(typeNames[l], StringComparison.Ordinal))
					{
						return type2;
					}
				}
			}
		}
		return null;
	}

	private static object GetLocalizationInstance()
	{
		object obj = ReadFieldValue(_localizationInstanceField, null);
		return obj ?? ReadPropertyValue(_localizationInstanceProperty, null);
	}

	private static FieldInfo FindField(Type type, BindingFlags flags, params string[] names)
	{
		if (type == null || names == null)
		{
			return null;
		}
		for (int i = 0; i < names.Length; i++)
		{
			FieldInfo field = type.GetField(names[i], flags);
			if (field != null)
			{
				return field;
			}
		}
		return null;
	}

	private static PropertyInfo FindProperty(Type type, BindingFlags flags, params string[] names)
	{
		if (type == null || names == null)
		{
			return null;
		}
		for (int i = 0; i < names.Length; i++)
		{
			PropertyInfo property = type.GetProperty(names[i], flags);
			if (property != null && property.GetIndexParameters().Length == 0)
			{
				return property;
			}
		}
		return null;
	}

	private static object ReadFieldValue(FieldInfo field, object instance)
	{
		if (field == null || (!field.IsStatic && instance == null))
		{
			return null;
		}
		object obj = (field.IsStatic ? null : instance);
		return field.GetValue(obj);
	}

	private static object ReadPropertyValue(PropertyInfo property, object instance)
	{
		if (property == null)
		{
			return null;
		}
		MethodInfo getMethod = property.GetGetMethod(nonPublic: true);
		if (getMethod == null || (!getMethod.IsStatic && instance == null))
		{
			return null;
		}
		object obj = (getMethod.IsStatic ? null : instance);
		return property.GetValue(obj, null);
	}

	private void OnDestroy()
	{
		PersistDecayProgress(_lastLocalPlayer);
		DietMaximumStatsRuntime.RestoreTrackedMaximums(_lastLocalPlayer);
		if (_harmony != null)
		{
			try
			{
				_harmony.UnpatchSelf();
			}
			catch
			{
			}
		}
		DestroyTexture(_dimTexture);
		DestroyTexture(_windowTexture);
		DestroyTexture(_panelTexture);
		DestroyTexture(_rowTexture);
		DestroyTexture(_summaryTexture);
		DestroyTexture(_effectTexture);
		DestroyTexture(_footerTexture);
		DestroyTexture(_barTexture);
		DestroyTexture(_solidTexture);
		DestroyTexture(_buttonTexture);
		DestroyTexture(_buttonHoverTexture);
		DestroyTexture(_buttonActiveTexture);
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			PersistDecayProgress(_lastLocalPlayer);
			DietMaximumStatsRuntime.ForgetPlayer();
			_lastLocalPlayer = null;
			_decayElapsedSeconds = 0.0;
			_decayPersistElapsedSeconds = 0.0;
			_menuVisible = false;
			return;
		}
		if ((Object)(object)_lastLocalPlayer != (Object)(object)localPlayer)
		{
			PersistDecayProgress(_lastLocalPlayer);
			DietMaximumStatsRuntime.ForgetPlayer();
			_lastLocalPlayer = localPlayer;
			_menuVisible = false;
			EnsureDietDataExists(localPlayer);
			_decayElapsedSeconds = ReadDoubleValue(localPlayer, "balanced_diet_decay_elapsed");
			_decayPersistElapsedSeconds = 0.0;
		}
		UpdateDietDecay(localPlayer);
		DietMaximumStatsRuntime.Sync(localPlayer);
		if (!IsUserTypingOrInventoryOpen())
		{
			if (IsKeyDown((KeyCode)98))
			{
				_menuVisible = !_menuVisible;
			}
			if (_menuVisible && CloseOnEscape.Value && IsKeyDown((KeyCode)27))
			{
				_menuVisible = false;
			}
		}
	}

	private void OnGUI()
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_011c: 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_013d: Expected O, but got Unknown
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		if (_menuVisible)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				EnsureUi();
				float num = Mathf.Clamp(UiScale.Value, 0.75f, 1.5f);
				Matrix4x4 matrix = GUI.matrix;
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f);
				GUIUtility.ScaleAroundPivot(new Vector2(num, num), val);
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_dimTexture, (ScaleMode)0);
				((Rect)(ref _windowRect)).width = 590f;
				((Rect)(ref _windowRect)).height = 575f;
				((Rect)(ref _windowRect)).x = ((float)Screen.width - ((Rect)(ref _windowRect)).width) * 0.5f;
				((Rect)(ref _windowRect)).y = ((float)Screen.height - ((Rect)(ref _windowRect)).height) * 0.5f;
				_windowRect = GUI.Window(18402731, _windowRect, new WindowFunction(DrawDietWindow), string.Empty, _windowStyle);
				GUI.matrix = matrix;
			}
		}
	}

	private void DrawDietWindow(int id)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			_menuVisible = false;
			return;
		}
		DietState state = ReadDietState(localPlayer);
		int averageValue = GetAverageValue(state);
		int nutrientSpread = GetNutrientSpread(state);
		DietStatus dietStatus = GetDietStatus(state);
		DrawWindowFrame();
		GUILayout.BeginVertical(_panelStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label(Localize("VIKING NUTRITION", "ПИТАНИЕ ВИКИНГА"), _titleStyle, Array.Empty<GUILayoutOption>());
		GUILayout.Label(Localize("NUTRIENT BALANCE", "БАЛАНС НУТРИЕНТОВ"), _subtitleStyle, Array.Empty<GUILayoutOption>());
		DrawHorizontalAccent(new Color(0.78f, 0.57f, 0.29f, 0.9f), 2f);
		GUILayout.Space(8f);
		DrawBalanceRow(averageValue, nutrientSpread, dietStatus, state);
		GUILayout.Space(10f);
		DrawNutrientRow(Localize("Protein", "Белки"), state.Protein, new Color(0.8f, 0.31f, 0.25f, 1f));
		GUILayout.Space(6f);
		DrawNutrientRow(Localize("Fats", "Жиры"), state.Fat, new Color(0.88f, 0.64f, 0.22f, 1f));
		GUILayout.Space(6f);
		DrawNutrientRow(Localize("Carbohydrates", "Углеводы"), state.Carbohydrate, new Color(0.77f, 0.48f, 0.24f, 1f));
		GUILayout.Space(6f);
		DrawNutrientRow(Localize("Vitamins", "Витамины"), state.Vitamin, new Color(0.38f, 0.68f, 0.38f, 1f));
		GUILayout.Space(10f);
		DrawActiveEffectRow(dietStatus);
		GUILayout.FlexibleSpace();
		GUILayout.BeginHorizontal(_footerBarStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
		GUILayout.Label(Localize("<b>B</b>   open / close", "<b>B</b>   открыть / закрыть"), _footerStyle, Array.Empty<GUILayoutOption>());
		GUILayout.FlexibleSpace();
		if (CloseOnEscape.Value)
		{
			GUILayout.Label(Localize("<b>ESC</b>   close", "<b>ESC</b>   закрыть"), _footerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(14f);
		}
		if (GUILayout.Button(Localize("CLOSE", "ЗАКРЫТЬ"), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(102f),
			GUILayout.Height(25f)
		}))
		{
			_menuVisible = false;
		}
		GUILayout.EndHorizontal();
		GUILayout.EndVertical();
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 38f));
	}

	private void DrawWindowFrame()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		float width = ((Rect)(ref _windowRect)).width;
		float height = ((Rect)(ref _windowRect)).height;
		Color color = default(Color);
		((Color)(ref color))..ctor(0.16f, 0.17f, 0.15f, 1f);
		Color color2 = default(Color);
		((Color)(ref color2))..ctor(0.52f, 0.44f, 0.29f, 0.72f);
		Color color3 = default(Color);
		((Color)(ref color3))..ctor(0.82f, 0.59f, 0.27f, 0.95f);
		DrawOutline(new Rect(1f, 1f, width - 2f, height - 2f), color, 3f);
		DrawOutline(new Rect(5f, 5f, width - 10f, height - 10f), color2, 1f);
		DrawColoredRect(new Rect(8f, 5f, 58f, 2f), color3);
		DrawColoredRect(new Rect(width - 8f - 58f, 5f, 58f, 2f), color3);
		DrawColoredRect(new Rect(8f, height - 7f, 58f, 2f), color3);
		DrawColoredRect(new Rect(width - 8f - 58f, height - 7f, 58f, 2f), color3);
	}

	private void DrawNutrientRow(string label, int value, Color nutrientColor)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		value = Mathf.Clamp(value, 0, 100);
		bool flag = value >= 30;
		int num = Mathf.Max(0, 30 - value);
		GUILayout.BeginVertical(_rowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(61f) });
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) });
		Rect rect = GUILayoutUtility.GetRect(5f, 18f, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Width(5f),
			GUILayout.Height(18f)
		});
		DrawColoredRect(rect, nutrientColor);
		GUILayout.Space(8f);
		GUILayout.Label(label, _rowLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
		GUILayout.FlexibleSpace();
		GUILayout.Label(value.ToString(CultureInfo.InvariantCulture) + "%", _percentStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(58f) });
		GUILayout.Label(Localize("minimum ", "минимум ") + 30.ToString(CultureInfo.InvariantCulture) + "%", _targetStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(88f) });
		GUILayout.EndHorizontal();
		Rect rect2 = GUILayoutUtility.GetRect(10f, 10f, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.ExpandWidth(true),
			GUILayout.Height(10f)
		});
		GUI.DrawTexture(rect2, (Texture)(object)_barTexture, (ScaleMode)0);
		DrawOutline(rect2, new Color(0.43f, 0.4f, 0.32f, 0.52f), 1f);
		float num2 = Mathf.Max(0f, ((Rect)(ref rect2)).width - 2f);
		float num3 = num2 * (float)value / 100f;
		if (num3 > 0f)
		{
			DrawColoredRect(new Rect(((Rect)(ref rect2)).x + 1f, ((Rect)(ref rect2)).y + 1f, num3, ((Rect)(ref rect2)).height - 2f), nutrientColor);
		}
		float num4 = ((Rect)(ref rect2)).x + num2 * 30f / 100f;
		DrawColoredRect(new Rect(num4, ((Rect)(ref rect2)).y - 1f, 2f, ((Rect)(ref rect2)).height + 2f), new Color(0.9f, 0.84f, 0.68f, 0.95f));
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(15f) });
		GUILayout.Label(flag ? Localize("<color=#83C97A>TARGET REACHED</color>", "<color=#83C97A>НОРМА ДОСТИГНУТА</color>") : (Localize("<color=#E7836E>MISSING ", "<color=#E7836E>НЕ ХВАТАЕТ ") + num.ToString(CultureInfo.InvariantCulture) + "%</color>"), _rowHintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.FlexibleSpace();
		GUILayout.Label(Localize("threshold 30%", "порог 30%"), _rowHintStyle, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
		GUILayout.EndVertical();
	}

	private void DrawBalanceRow(int average, int spread, DietStatus dietStatus, DietState state)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = GUILayoutUtility.GetRect(10f, 68f, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.ExpandWidth(true),
			GUILayout.Height(68f)
		});
		GUI.Box(rect, GUIContent.none, _summaryStyle);
		Color statusColor = GetStatusColor(dietStatus);
		DrawColoredRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 5f, ((Rect)(ref rect)).height), statusColor);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 16f, ((Rect)(ref rect)).y + 10f, ((Rect)(ref rect)).width - 128f, 25f);
		GUI.Label(val, GetStatusRichText(dietStatus), _dietStatusStyle);
		int num = Mathf.Min(Mathf.Min(state.Protein, state.Fat), Mathf.Min(state.Carbohydrate, state.Vitamin));
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + 16f, ((Rect)(ref rect)).y + 36f, ((Rect)(ref rect)).width - 128f, 20f);
		GUI.Label(val2, Localize("Spread: ", "Разброс: ") + spread.ToString(CultureInfo.InvariantCulture) + Localize("% of ", "% из ") + 10.ToString(CultureInfo.InvariantCulture) + Localize("%    Minimum: ", "%    Минимум: ") + num.ToString(CultureInfo.InvariantCulture) + "%", _balanceMetaStyle);
		Rect val3 = default(Rect);
		((Rect)(ref val3))..ctor(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - 104f, ((Rect)(ref rect)).y + 7f, 88f, 34f);
		GUI.Label(val3, average.ToString(CultureInfo.InvariantCulture) + "%", _balanceValueStyle);
		GUI.Label(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - 104f, ((Rect)(ref rect)).y + 39f, 88f, 17f), Localize("AVERAGE", "СРЕДНЕЕ"), _targetStyle);
	}

	private void DrawActiveEffectRow(DietStatus dietStatus)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: 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_0097: 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)
		Rect rect = GUILayoutUtility.GetRect(10f, 62f, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.ExpandWidth(true),
			GUILayout.Height(62f)
		});
		GUI.Box(rect, GUIContent.none, _effectCardStyle);
		DrawColoredRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 4f, ((Rect)(ref rect)).height), GetStatusColor(dietStatus));
		GUI.Label(new Rect(((Rect)(ref rect)).x + 15f, ((Rect)(ref rect)).y + 7f, ((Rect)(ref rect)).width - 28f, 18f), Localize("ACTIVE EFFECT", "АКТИВНЫЙ ЭФФЕКТ"), _effectTitleStyle);
		GUI.Label(new Rect(((Rect)(ref rect)).x + 15f, ((Rect)(ref rect)).y + 25f, ((Rect)(ref rect)).width - 28f, 29f), GetEffectRichText(dietStatus), _effectStyle);
	}

	private void DrawHorizontalAccent(Color color, float height)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = GUILayoutUtility.GetRect(10f, height, (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.ExpandWidth(true),
			GUILayout.Height(height)
		});
		DrawColoredRect(rect, color);
	}

	private void DrawColoredRect(Rect rect, Color color)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		Color color2 = GUI.color;
		GUI.color = color;
		GUI.DrawTexture(rect, (Texture)(object)_solidTexture, (ScaleMode)0);
		GUI.color = color2;
	}

	private void DrawOutline(Rect rect, Color color, float thickness)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		DrawColoredRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color);
		DrawColoredRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - thickness, ((Rect)(ref rect)).width, thickness), color);
		DrawColoredRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
		DrawColoredRect(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
	}

	private void EnsureUi()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Expected O, but got Unknown
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Expected O, but got Unknown
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Expected O, but got Unknown
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Expected O, but got Unknown
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Expected O, but got Unknown
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Expected O, but got Unknown
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Expected O, but got Unknown
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cf: Expected O, but got Unknown
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Expected O, but got Unknown
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f7: Expected O, but got Unknown
		//IL_0402: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0418: Unknown result type (might be due to invalid IL or missing references)
		//IL_0420: Unknown result type (might be due to invalid IL or missing references)
		//IL_0431: Expected O, but got Unknown
		//IL_0450: Unknown result type (might be due to invalid IL or missing references)
		//IL_0466: Unknown result type (might be due to invalid IL or missing references)
		//IL_046b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0473: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0484: Unknown result type (might be due to invalid IL or missing references)
		//IL_0495: Expected O, but got Unknown
		//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f9: Expected O, but got Unknown
		//IL_0518: Unknown result type (might be due to invalid IL or missing references)
		//IL_052e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0533: Unknown result type (might be due to invalid IL or missing references)
		//IL_053b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0544: Unknown result type (might be due to invalid IL or missing references)
		//IL_054c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		//IL_0565: Expected O, but got Unknown
		//IL_0584: Unknown result type (might be due to invalid IL or missing references)
		//IL_059a: Unknown result type (might be due to invalid IL or missing references)
		//IL_059f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ae: Expected O, but got Unknown
		//IL_05af: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05be: Expected O, but got Unknown
		//IL_05bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d6: Expected O, but got Unknown
		//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0610: Expected O, but got Unknown
		//IL_062f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0645: Unknown result type (might be due to invalid IL or missing references)
		//IL_064a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0652: Unknown result type (might be due to invalid IL or missing references)
		//IL_065b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0663: Unknown result type (might be due to invalid IL or missing references)
		//IL_066f: Unknown result type (might be due to invalid IL or missing references)
		//IL_067c: Expected O, but got Unknown
		//IL_0687: Unknown result type (might be due to invalid IL or missing references)
		//IL_068c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0694: Unknown result type (might be due to invalid IL or missing references)
		//IL_069d: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ae: Expected O, but got Unknown
		//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f7: Expected O, but got Unknown
		//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0707: Expected O, but got Unknown
		//IL_0708: Unknown result type (might be due to invalid IL or missing references)
		//IL_071f: Expected O, but got Unknown
		//IL_072a: Unknown result type (might be due to invalid IL or missing references)
		//IL_072f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0737: Unknown result type (might be due to invalid IL or missing references)
		//IL_0740: Unknown result type (might be due to invalid IL or missing references)
		//IL_0748: Unknown result type (might be due to invalid IL or missing references)
		//IL_0759: Expected O, but got Unknown
		//IL_0778: Unknown result type (might be due to invalid IL or missing references)
		//IL_078e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0793: Unknown result type (might be due to invalid IL or missing references)
		//IL_079b: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cd: Expected O, but got Unknown
		//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ed: Expected O, but got Unknown
		//IL_07ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fd: Expected O, but got Unknown
		//IL_07fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0815: Expected O, but got Unknown
		//IL_0820: Unknown result type (might be due to invalid IL or missing references)
		//IL_0825: Unknown result type (might be due to invalid IL or missing references)
		//IL_082d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0836: Unknown result type (might be due to invalid IL or missing references)
		//IL_0843: Expected O, but got Unknown
		//IL_0862: Unknown result type (might be due to invalid IL or missing references)
		//IL_0878: Unknown result type (might be due to invalid IL or missing references)
		//IL_087d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0885: Unknown result type (might be due to invalid IL or missing references)
		//IL_088e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0896: Unknown result type (might be due to invalid IL or missing references)
		//IL_089b: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a5: Expected O, but got Unknown
		//IL_08a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e1: Expected O, but got Unknown
		//IL_0900: Unknown result type (might be due to invalid IL or missing references)
		//IL_0916: Unknown result type (might be due to invalid IL or missing references)
		//IL_092c: Unknown result type (might be due to invalid IL or missing references)
		//IL_094c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0951: Unknown result type (might be due to invalid IL or missing references)
		if (!_uiReady)
		{
			_dimTexture = MakeTexture(new Color(0f, 0f, 0f, 0.6f));
			_windowTexture = MakeTexture(new Color(0.075f, 0.08f, 0.07f, 0.995f));
			_panelTexture = MakeTexture(new Color(0.095f, 0.105f, 0.095f, 0.985f));
			_rowTexture = MakeBorderedTexture(new Color(0.16f, 0.17f, 0.15f, 0.985f), new Color(0.4f, 0.37f, 0.29f, 0.34f));
			_summaryTexture = MakeBorderedTexture(new Color(0.19f, 0.19f, 0.16f, 0.99f), new Color(0.5f, 0.43f, 0.29f, 0.48f));
			_effectTexture = MakeBorderedTexture(new Color(0.135f, 0.145f, 0.13f, 0.99f), new Color(0.42f, 0.39f, 0.3f, 0.38f));
			_footerTexture = MakeBorderedTexture(new Color(0.12f, 0.125f, 0.11f, 0.99f), new Color(0.38f, 0.35f, 0.27f, 0.34f));
			_barTexture = MakeTexture(new Color(0.055f, 0.06f, 0.055f, 1f));
			_solidTexture = MakeTexture(Color.white);
			_buttonTexture = MakeBorderedTexture(new Color(0.22f, 0.21f, 0.17f, 1f), new Color(0.56f, 0.45f, 0.26f, 0.7f));
			_buttonHoverTexture = MakeBorderedTexture(new Color(0.35f, 0.29f, 0.18f, 1f), new Color(0.77f, 0.57f, 0.27f, 0.95f));
			_buttonActiveTexture = MakeBorderedTexture(new Color(0.46f, 0.34f, 0.17f, 1f), new Color(0.9f, 0.68f, 0.31f, 1f));
			GUIStyle val = new GUIStyle(GUI.skin.window)
			{
				padding = new RectOffset(8, 8, 8, 8),
				border = new RectOffset(0, 0, 0, 0)
			};
			val.normal.background = _windowTexture;
			_windowStyle = val;
			GUIStyle val2 = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(22, 22, 15, 14)
			};
			val2.normal.background = _panelTexture;
			_panelStyle = val2;
			_titleStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontSize = 23,
				fontStyle = (FontStyle)1,
				fixedHeight = 32f,
				richText = true
			};
			_titleStyle.normal.textColor = new Color(0.92f, 0.88f, 0.78f, 1f);
			_subtitleStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontSize = 10,
				fontStyle = (FontStyle)1,
				fixedHeight = 17f
			};
			_subtitleStyle.normal.textColor = new Color(0.7f, 0.67f, 0.58f, 1f);
			GUIStyle val3 = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(11, 11, 5, 4),
				border = new RectOffset(1, 1, 1, 1)
			};
			val3.normal.background = _rowTexture;
			_rowStyle = val3;
			_rowLabelStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 15,
				fontStyle = (FontStyle)1,
				fixedHeight = 22f
			};
			_rowLabelStyle.normal.textColor = new Color(0.88f, 0.86f, 0.8f, 1f);
			_percentStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)5,
				fontSize = 17,
				fontStyle = (FontStyle)1,
				fixedHeight = 22f
			};
			_percentStyle.normal.textColor = new Color(0.96f, 0.92f, 0.8f, 1f);
			_targetStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)5,
				fontSize = 10,
				fontStyle = (FontStyle)1,
				fixedHeight = 20f
			};
			_targetStyle.normal.textColor = new Color(0.7f, 0.68f, 0.61f, 1f);
			_rowHintStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 9,
				fontStyle = (FontStyle)1,
				fixedHeight = 14f,
				richText = true
			};
			_rowHintStyle.normal.textColor = new Color(0.67f, 0.65f, 0.58f, 1f);
			GUIStyle val4 = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(0, 0, 0, 0),
				border = new RectOffset(1, 1, 1, 1)
			};
			val4.normal.background = _summaryTexture;
			_summaryStyle = val4;
			_balanceValueStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontSize = 22,
				fontStyle = (FontStyle)1,
				fixedHeight = 34f
			};
			_balanceValueStyle.normal.textColor = new Color(0.93f, 0.85f, 0.65f, 1f);
			_dietStatusStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 15,
				fontStyle = (FontStyle)1,
				fixedHeight = 25f,
				richText = true
			};
			_balanceMetaStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 11,
				fixedHeight = 20f
			};
			_balanceMetaStyle.normal.textColor = new Color(0.72f, 0.7f, 0.63f, 1f);
			GUIStyle val5 = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(0, 0, 0, 0),
				border = new RectOffset(1, 1, 1, 1)
			};
			val5.normal.background = _effectTexture;
			_effectCardStyle = val5;
			_effectTitleStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 9,
				fontStyle = (FontStyle)1,
				fixedHeight = 18f
			};
			_effectTitleStyle.normal.textColor = new Color(0.72f, 0.7f, 0.63f, 1f);
			_effectStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 11,
				fontStyle = (FontStyle)1,
				fixedHeight = 29f,
				richText = true,
				wordWrap = true
			};
			GUIStyle val6 = new GUIStyle(GUI.skin.box)
			{
				padding = new RectOffset(9, 6, 4, 4),
				border = new RectOffset(1, 1, 1, 1)
			};
			val6.normal.background = _footerTexture;
			_footerBarStyle = val6;
			_footerStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = 10,
				richText = true
			};
			_footerStyle.normal.textColor = new Color(0.75f, 0.72f, 0.64f, 1f);
			GUIStyle val7 = new GUIStyle(GUI.skin.button)
			{
				alignment = (TextAnchor)4,
				fontSize = 10,
				fontStyle = (FontStyle)1,
				border = new RectOffset(1, 1, 1, 1)
			};
			val7.normal.background = _buttonTexture;
			val7.hover.background = _buttonHoverTexture;
			val7.active.background = _buttonActiveTexture;
			_buttonStyle = val7;
			_buttonStyle.normal.textColor = new Color(0.86f, 0.82f, 0.72f, 1f);
			_buttonStyle.hover.textColor = Color.white;
			_buttonStyle.active.textColor = Color.white;
			_windowRect = new Rect(0f, 0f, 590f, 575f);
			_uiReady = true;
		}
	}

	private static Texture2D MakeTexture(Color color)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		Color[] pixels = (Color[])(object)new Color[4] { color, color, color, color };
		val.SetPixels(pixels);
		val.Apply(false, true);
		return val;
	}

	private static Texture2D MakeBorderedTexture(Color fillColor, Color borderColor)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(6, 6, (TextureFormat)4, false);
		Color[] array = (Color[])(object)new Color[36];
		for (int i = 0; i < 6; i++)
		{
			for (int j = 0; j < 6; j++)
			{
				bool flag = j == 0 || i == 0 || j == 5 || i == 5;
				array[i * 6 + j] = (flag ? borderColor : fillColor);
			}
		}
		val.SetPixels(array);
		val.Apply(false, true);
		return val;
	}

	private static void DestroyTexture(Texture2D texture)
	{
		if ((Object)(object)texture != (Object)null)
		{
			Object.Destroy((Object)(object)texture);
		}
	}

	private static void CacheInputMethods()
	{
		try
		{
			Type type = AccessTools.TypeByName("ZInput");
			if (type != null)
			{
				_zInputGetKeyDown = type.GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(KeyCode) }, null);
			}
		}
		catch
		{
			_zInputGetKeyDown = null;
		}
		try
		{
			Type type2 = Type.GetType("UnityEngine.Input, UnityEngine.InputLegacyModule", throwOnError: false) ?? Type.GetType("UnityEngine.Input, UnityEngine", throwOnError: false) ?? Type.GetType("UnityEngine.Input", throwOnError: false);
			if (type2 != null)
			{
				_unityInputGetKeyDown = type2.GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(KeyCode) }, null);
			}
		}
		catch
		{
			_unityInputGetKeyDown = null;
		}
	}

	private static bool IsKeyDown(KeyCode key)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		if (_zInputGetKeyDown != null)
		{
			try
			{
				if (_zInputGetKeyDown.Invoke(null, new object[1] { key }) is int num && num != 0)
				{
					return true;
				}
			}
			catch
			{
			}
		}
		if (_unityInputGetKeyDown != null)
		{
			try
			{
				if (_unityInputGetKeyDown.Invoke(null, new object[1] { key }) is int num2 && num2 != 0)
				{
					return true;
				}
			}
			catch
			{
			}
		}
		return false;
	}

	private static void CacheFocusedInputFields()
	{
		try
		{
			Type typeFromHandle = typeof(Terminal);
			_terminalInstance = typeFromHandle.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_terminalInput = typeFromHandle.GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle.GetField("m_inputField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
			_terminalInstance = null;
			_terminalInput = null;
		}
		try
		{
			Type typeFromHandle2 = typeof(Chat);
			_chatInstance = typeFromHandle2.GetField("m_instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle2.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_chatInput = typeFromHandle2.GetField("m_input", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeFromHandle2.GetField("m_inputField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
			_chatInstance = null;
			_chatInput = null;
		}
	}

	private static bool IsUserTypingOrInventoryOpen()
	{
		try
		{
			if (InventoryGui.IsVisible())
			{
				return true;
			}
		}
		catch
		{
		}
		return IsInputFieldFocused(_terminalInstance, _terminalInput) || IsInputFieldFocused(_chatInstance, _chatInput);
	}

	private static bool IsInputFieldFocused(FieldInfo instanceField, FieldInfo inputField)
	{
		if (instanceField == null || inputField == null)
		{
			return false;
		}
		try
		{
			object value = instanceField.GetValue(null);
			if (value == null)
			{
				return false;
			}
			object value2 = inputField.GetValue(value);
			if (value2 == null)
			{
				return false;
			}
			PropertyInfo property = value2.GetType().GetProperty("isFocused", BindingFlags.Instance | BindingFlags.Public);
			if (property == null)
			{
				return false;
			}
			object value3 = property.GetValue(value2, null);
			return value3 is bool && (bool)value3;
		}
		catch
		{
			return false;
		}
	}

	private static void EnsureDietDataExists(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		try
		{
			if (player.m_customData == null)
			{
				player.m_customData = new Dictionary<string, string>();
			}
			EnsureValueExists(player, "balanced_diet_protein");
			EnsureValueExists(player, "balanced_diet_fat");
			EnsureValueExists(player, "balanced_diet_carbohydrate");
			EnsureValueExists(player, "balanced_diet_vitamin");
			EnsureValueExists(player, "balanced_diet_decay_elapsed");
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Could not initialize diet data: " + ex.Message));
		}
	}

	private static void EnsureValueExists(Player player, string key)
	{
		if (!player.m_customData.ContainsKey(key))
		{
			player.m_customData[key] = "0";
		}
	}

	private static DietState ReadDietState(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return default(DietState);
		}
		EnsureDietDataExists(player);
		return new DietState
		{
			Protein = ReadValue(player, "balanced_diet_protein"),
			Fat = ReadValue(player, "balanced_diet_fat"),
			Carbohydrate = ReadValue(player, "balanced_diet_carbohydrate"),
			Vitamin = ReadValue(player, "balanced_diet_vitamin")
		};
	}

	private static int ReadValue(Player player, string key)
	{
		try
		{
			if (player.m_customData != null && player.m_customData.TryGetValue(key, out var value) && int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				return Mathf.Clamp(result, 0, 100);
			}
		}
		catch
		{
		}
		return 0;
	}

	private static void WriteValue(Player player, string key, int value)
	{
		EnsureDietDataExists(player);
		player.m_customData[key] = Mathf.Clamp(value, 0, 100).ToString(CultureInfo.InvariantCulture);
	}

	private static double ReadDoubleValue(Player player, string key)
	{
		try
		{
			if ((Object)(object)player != (Object)null && player.m_customData != null && player.m_customData.TryGetValue(key, out var value) && double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return ClampDouble(result, 0.0, 1200.0);
			}
		}
		catch
		{
		}
		return 0.0;
	}

	private static void WriteDoubleValue(Player player, string key, double value)
	{
		if (!((Object)(object)player == (Object)null))
		{
			EnsureDietDataExists(player);
			player.m_customData[key] = ClampDouble(value, 0.0, 1200.0).ToString("R", CultureInfo.InvariantCulture);
		}
	}

	private static double ClampDouble(double value, double minimum, double maximum)
	{
		if (double.IsNaN(value) || double.IsInfinity(value))
		{
			return minimum;
		}
		if (value < minimum)
		{
			return minimum;
		}
		return (value > maximum) ? maximum : value;
	}

	private void UpdateDietDecay(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		float unscaledDeltaTime = Time.unscaledDeltaTime;
		if (!(unscaledDeltaTime <= 0f) && !float.IsNaN(unscaledDeltaTime) && !float.IsInfinity(unscaledDeltaTime))
		{
			double num = unscaledDeltaTime;
			_decayElapsedSeconds += num;
			_decayPersistElapsedSeconds += num;
			bool flag = false;
			while (_decayElapsedSeconds >= 1200.0)
			{
				_decayElapsedSeconds -= 1200.0;
				ChangeAllNutrients(player, -1, "1200-second decay");
				Log.LogInfo((object)"Diet decay applied: -1% to every nutrient after 1200 seconds.");
				flag = true;
			}
			if (flag || _decayPersistElapsedSeconds >= 5.0)
			{
				PersistDecayProgress(player);
				_decayPersistElapsedSeconds = 0.0;
			}
		}
	}

	private void PersistDecayProgress(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		try
		{
			WriteDoubleValue(player, "balanced_diet_decay_elapsed", _decayElapsedSeconds);
		}
		catch
		{
		}
	}

	private static void ChangeAllNutrients(Player player, int amount, string reason)
	{
		if (!((Object)(object)player == (Object)null))
		{
			DietState dietState = ReadDietState(player);
			WriteValue(player, "balanced_diet_protein", dietState.Protein + amount);
			WriteValue(player, "balanced_diet_fat", dietState.Fat + amount);
			WriteValue(player, "balanced_diet_carbohydrate", dietState.Carbohydrate + amount);
			WriteValue(player, "balanced_diet_vitamin", dietState.Vitamin + amount);
			if (DebugLogs != null && DebugLogs.Value)
			{
				Log.LogInfo((object)(reason + ": " + ((amount >= 0) ? "+" : string.Empty) + amount.ToString(CultureInfo.InvariantCulture) + "% to every nutrient."));
			}
		}
	}

	internal static void HandlePlayerDeath(Player player)
	{
		if (!((Object)(object)player == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
		{
			ChangeAllNutrients(player, -10, "death penalty");
		}
	}

	private static int GetAverageValue(DietState state)
	{
		float num = (float)(state.Protein + state.Fat + state.Carbohydrate + state.Vitamin) / 4f;
		return Mathf.Clamp(Mathf.RoundToInt(num), 0, 100);
	}

	private static int GetNutrientSpread(DietState state)
	{
		int num = Mathf.Min(Mathf.Min(state.Protein, state.Fat), Mathf.Min(state.Carbohydrate, state.Vitamin));
		int num2 = Mathf.Max(Mathf.Max(state.Protein, state.Fat), Mathf.Max(state.Carbohydrate, state.Vitamin));
		return num2 - num;
	}

	private static DietStatus GetDietStatus(DietState state)
	{
		int num = Mathf.Min(Mathf.Min(state.Protein, state.Fat), Mathf.Min(state.Carbohydrate, state.Vitamin));
		if (num < 30)
		{
			return DietStatus.Exhaustion;
		}
		if (GetNutrientSpread(state) > 10)
		{
			return DietStatus.Unbalanced;
		}
		int averageValue = GetAverageValue(state);
		if (averageValue >= 90)
		{
			return DietStatus.Ideal;
		}
		if (averageValue >= 70)
		{
			return DietStatus.Balanced;
		}
		return DietStatus.Satisfactory;
	}

	private static string GetStatusRichText(DietStatus status)
	{
		return status switch
		{
			DietStatus.Exhaustion => Localize("<color=#E7836E>DEPLETION</color>", "<color=#E7836E>ИСТОЩЕНИЕ</color>"), 
			DietStatus.Unbalanced => Localize("<color=#E5A653>UNBALANCED DIET</color>", "<color=#E5A653>НЕСБАЛАНСИРОВАННОЕ ПИТАНИЕ</color>"), 
			DietStatus.Satisfactory => Localize("<color=#D8C766>SATISFACTORY DIET</color>", "<color=#D8C766>УДОВЛЕТВОРИТЕЛЬНОЕ ПИТАНИЕ</color>"), 
			DietStatus.Balanced => Localize("<color=#83C97A>BALANCED DIET</color>", "<color=#83C97A>СБАЛАНСИРОВАННОЕ ПИТАНИЕ</color>"), 
			DietStatus.Ideal => Localize("<color=#74C9D6>IDEAL DIET</color>", "<color=#74C9D6>ИДЕАЛЬНОЕ ПИТАНИЕ</color>"), 
			_ => Localize("<color=#B8B8B8>UNKNOWN STATUS</color>", "<color=#B8B8B8>НЕИЗВЕСТНЫЙ СТАТУС</color>"), 
		};
	}

	private static Color GetStatusColor(DietStatus status)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		return (Color)(status switch
		{
			DietStatus.Exhaustion => new Color(0.91f, 0.4f, 0.32f, 1f), 
			DietStatus.Unbalanced => new Color(0.9f, 0.61f, 0.27f, 1f), 
			DietStatus.Satisfactory => new Color(0.84f, 0.75f, 0.32f, 1f), 
			DietStatus.Balanced => new Color(0.42f, 0.73f, 0.38f, 1f), 
			DietStatus.Ideal => new Color(0.34f, 0.72f, 0.8f, 1f), 
			_ => new Color(0.6f, 0.6f, 0.6f, 1f), 
		});
	}

	private static string GetEffectRichText(DietStatus status)
	{
		return status switch
		{
			DietStatus.Exhaustion => Localize("<color=#E7836E>-10 health, -10 stamina</color>", "<color=#E7836E>-10 здоровья, -10 выносливости</color>"), 
			DietStatus.Unbalanced => Localize("<color=#E5A653>-5 health, -5 stamina</color>", "<color=#E5A653>-5 здоровья, -5 выносливости</color>"), 
			DietStatus.Satisfactory => Localize("<color=#D8C766>+5 health, +5 stamina</color>", "<color=#D8C766>+5 здоровья, +5 выносливости</color>"), 
			DietStatus.Balanced => Localize("<color=#83C97A>+10 health, +10 stamina</color>", "<color=#83C97A>+10 здоровья, +10 выносливости</color>"), 
			DietStatus.Ideal => Localize("<color=#74C9D6>+15 health, +15 stamina, +10% stamina regeneration, +10% movement speed</color>", "<color=#74C9D6>+15 здоровья, +15 выносливости, +10% восстановления выносливости, +10% скорости</color>"), 
			_ => Localize("<color=#B8B8B8>No effect</color>", "<color=#B8B8B8>Нет эффекта</color>"), 
		};
	}

	internal static int GetHealthModifier(Player player)
	{
		return GetDietStatModifier(player);
	}

	internal static int GetStaminaModifier(Player player)
	{
		return GetDietStatModifier(player);
	}

	private static int GetDietStatModifier(Player player)
	{
		if (!IsLocalDietPlayer(player))
		{
			return 0;
		}
		return GetDietStatus(ReadDietState(player)) switch
		{
			DietStatus.Exhaustion => -10, 
			DietStatus.Unbalanced => -5, 
			DietStatus.Satisfactory => 5, 
			DietStatus.Balanced => 10, 
			DietStatus.Ideal => 15, 
			_ => 0, 
		};
	}

	internal static bool HasIdealDiet(Player player)
	{
		return IsLocalDietPlayer(player) && GetDietStatus(ReadDietState(player)) == DietStatus.Ideal;
	}

	internal static float GetIdealStaminaRegenMultiplier(Player player)
	{
		return HasIdealDiet(player) ? 1.1f : 1f;
	}

	internal static float GetIdealMovementSpeedMultiplier(Player player)
	{
		return HasIdealDiet(player) ? 1.1f : 1f;
	}

	internal static bool IsLocalPlayerSEMan(object seMan)
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || seMan == null)
		{
			return false;
		}
		try
		{
			if (_characterSEMan == null)
			{
				_characterSEMan = AccessTools.Field(typeof(Character), "m_seman");
			}
			return _characterSEMan != null && _characterSEMan.GetValue(localPlayer) == seMan;
		}
		catch
		{
			return false;
		}
	}

	private static bool IsLocalDietPlayer(Player player)
	{
		return (Object)(object)player != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && player == Player.m_localPlayer;
	}

	internal static bool TrySetAllNutrients(int value)
	{
		if (value < 0 || value > 100)
		{
			return false;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		WriteValue(localPlayer, "balanced_diet_protein", value);
		WriteValue(localPlayer, "balanced_diet_fat", value);
		WriteValue(localPlayer, "balanced_diet_carbohydrate", value);
		WriteValue(localPlayer, "balanced_diet_vitamin", value);
		if (DebugLogs != null && DebugLogs.Value)
		{
			Log.LogInfo((object)("Console command set every nutrient to " + value.ToString(CultureInfo.InvariantCulture) + "%."));
		}
		return true;
	}

	internal static void HandleConsumedItem(Player player, ItemData item)
	{
		if (!((Object)(object)player == (Object)null) && item != null && item.m_shared != null && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && BalancedDietFoodValues.TryGet(item, out var nutrients, out var matchedId))
		{
			DietState dietState = ReadDietState(player);
			WriteValue(player, "balanced_diet_protein", dietState.Protein + nutrients.Protein);
			WriteValue(player, "balanced_diet_fat", dietState.Fat + nutrients.Fat);
			WriteValue(player, "balanced_diet_carbohydrate", dietState.Carbohydrate + nutrients.Carbohydrate);
			WriteValue(player, "balanced_diet_vitamin", dietState.Vitamin + nutrients.Vitamin);
			if (DebugLogs != null && DebugLogs.Value)
			{
				ManualLogSource log = Log;
				string[] obj = new string[11]
				{
					"Consumed ", matchedId, ": protein +", null, null, null, null, null, null, null,
					null
				};
				int protein = nutrients.Protein;
				obj[3] = protein.ToString();
				obj[4] = "%, fat +";
				protein = nutrients.Fat;
				obj[5] = protein.ToString();
				obj[6] = "%, carbohydrates +";
				protein = nutrients.Carbohydrate;
				obj[7] = protein.ToString();
				obj[8] = "%, vitamins +";
				protein = nutrients.Vitamin;
				obj[9] = protein.ToString();
				obj[10] = "%.";
				log.LogInfo((object)string.Concat(obj));
			}
		}
	}
}
internal static class BalancedDietPatches
{
	internal static void ApplyAll(Harmony harmony)
	{
		FoodConsumptionPatch.Apply(harmony);
		PlayerDeathPatch.Apply(harmony);
		DietConsoleCommandPatch.Apply(harmony);
		DietMaximumStatsPatch.Apply(harmony);
		DietRuntimeMultipliersPatch.Apply(harmony);
	}
}
internal static class FoodConsumptionPatch
{
	private static bool _applied;

	internal static void Apply(Harmony harmony)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		if (!_applied && harmony != null)
		{
			_applied = true;
			MethodInfo methodInfo = FindConsumptionMethod();
			if (methodInfo == null)
			{
				BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not find Player.ConsumeItem/EatFood/AddFood returning bool.");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(FoodConsumptionPatch), "Postfix", (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			BalancedDietPlugin.Log.LogInfo((object)("Food consumption patch bound to Player." + methodInfo.Name + "."));
		}
	}

	private static MethodInfo FindConsumptionMethod()
	{
		MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		string[] array = new string[3] { "ConsumeItem", "EatFood", "AddFood" };
		foreach (string value in array)
		{
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo == null || !methodInfo.Name.Equals(value, StringComparison.Ordinal) || methodInfo.ReturnType != typeof(bool))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				for (int k = 0; k < parameters.Length; k++)
				{
					if (parameters[k].ParameterType == typeof(ItemData))
					{
						return methodInfo;
					}
				}
			}
		}
		return null;
	}

	public static void Postfix(Player __instance, object[] __args, bool __result)
	{
		if (!__result || (Object)(object)__instance == (Object)null || __args == null)
		{
			return;
		}
		ItemData val = null;
		foreach (object obj in __args)
		{
			val = (ItemData)((obj is ItemData) ? obj : null);
			if (val != null)
			{
				break;
			}
		}
		if (val != null)
		{
			BalancedDietPlugin.HandleConsumedItem(__instance, val);
		}
	}
}
internal static class PlayerDeathPatch
{
	private static bool _applied;

	internal static void Apply(Harmony harmony)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Expected O, but got Unknown
		if (!_applied && harmony != null)
		{
			_applied = true;
			MethodInfo methodInfo = FindPlayerDeathMethod();
			if (methodInfo == null)
			{
				BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not find Player.OnDeath.");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(PlayerDeathPatch), "Prefix", (Type[])null);
			harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			BalancedDietPlugin.Log.LogInfo((object)("Death penalty patch bound to Player." + methodInfo.Name + "."));
		}
	}

	private static MethodInfo FindPlayerDeathMethod()
	{
		MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo != null && methodInfo.Name.Equals("OnDeath", StringComparison.Ordinal) && methodInfo.GetParameters().Length == 0)
			{
				return methodInfo;
			}
		}
		return null;
	}

	public static void Prefix(Player __instance)
	{
		BalancedDietPlugin.HandlePlayerDeath(__instance);
	}
}
internal static class DietConsoleCommandPatch
{
	private const string LongCommand = "balanceddiet_set";

	private const string ShortCommand = "bd_set";

	private static bool _applied;

	private static MethodInfo _addStringMethod;

	private static bool _devCommandsReflectionCached;

	private static FieldInfo _terminalDevCommandsField;

	private static FieldInfo _consoleDevCommandsField;

	internal static void Apply(Harmony harmony)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		if (!_applied && harmony != null)
		{
			_applied = true;
			CacheDevCommandsReflection();
			MethodInfo methodInfo = FindTryRunCommandMethod();
			if (methodInfo == null)
			{
				BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not find Terminal.TryRunCommand.");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(DietConsoleCommandPatch), "Prefix", (Type[])null);
			harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			BalancedDietPlugin.Log.LogInfo((object)"Console commands registered: balanceddiet_set and bd_set (devcommands required).");
		}
	}

	private static void CacheDevCommandsReflection()
	{
		if (!_devCommandsReflectionCached)
		{
			_devCommandsReflectionCached = true;
			_terminalDevCommandsField = FindDevCommandsField(typeof(Terminal), allowInstanceField: true);
			Type type = AccessTools.TypeByName("Console");
			if (type != null)
			{
				_consoleDevCommandsField = FindDevCommandsField(type, allowInstanceField: false);
			}
			FieldInfo fieldInfo = _terminalDevCommandsField ?? _consoleDevCommandsField;
			if (fieldInfo == null)
			{
				BalancedDietPlugin.Log.LogWarning((object)"BalancedDiet could not resolve the Valheim devcommands flag. Diet console commands will remain locked.");
				return;
			}
			BalancedDietPlugin.Log.LogInfo((object)("Diet console command access bound to " + fieldInfo.DeclaringType.Name + "." + fieldInfo.Name + "."));
		}
	}

	private static FieldInfo FindDevCommandsField(Type type, bool allowInstanceField)
	{
		if (type == null)
		{
			return null;
		}
		string[] array = new string[4] { "m_cheat", "m_cheats", "m_devCommands", "m_devcommands" };
		for (int i = 0; i < array.Length; i++)
		{
			FieldInfo field = type.GetField(array[i], BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (IsUsableDevCommandsField(field, allowInstanceField))
			{
				return field;
			}
		}
		FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (FieldInfo fieldInfo in fields)
		{
			if (IsUsableDevCommandsField(fieldInfo, allowInstanceField))
			{
				string text = fieldInfo.Name.ToLowerInvariant();
				if (text.Contains("cheat") || text.Contains("devcommand"))
				{
					return fieldInfo;
				}
			}
		}
		return null;
	}

	private static bool IsUsableDevCommandsField(FieldInfo field, bool allowInstanceField)
	{
		return field != null && field.FieldType == typeof(bool) && (field.IsStatic || allowInstanceField);
	}

	private static bool AreDevCommandsEnabled(Terminal terminal)
	{
		CacheDevCommandsReflection();
		if (TryReadBooleanField(_terminalDevCommandsField, terminal, out var value))
		{
			return value;
		}
		if (TryReadBooleanField(_consoleDevCommandsField, null, out value))
		{
			return value;
		}
		return false;
	}

	private static bool TryReadBooleanField(FieldInfo field, object instance, out bool value)
	{
		value = false;
		if (field == null || (!field.IsStatic && instance == null))
		{
			return false;
		}
		try
		{
			object obj = (field.IsStatic ? null : instance);
			object value2 = field.GetValue(obj);
			if (value2 is bool)
			{
				value = (bool)value2;
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static MethodInfo FindTryRunCommandMethod()
	{
		MethodInfo[] methods = typeof(Terminal).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo == null) && methodInfo.Name.Equals("TryRunCommand", StringComparison.Ordinal))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 0 && parameters[0].ParameterType == typeof(string))
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	public static bool Prefix(Terminal __instance, string __0)
	{
		if (string.IsNullOrWhiteSpace(__0))
		{
			return true;
		}
		string[] array = __0.Trim().Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		if (array.Length == 0 || (!array[0].Equals("balanceddiet_set", StringComparison.OrdinalIgnoreCase) && !array[0].Equals("bd_set", StringComparison.OrdinalIgnoreCase)))
		{
			return true;
		}
		if (!AreDevCommandsEnabled(__instance))
		{
			Reply(__instance, BalancedDietPlugin.Localize("BalancedDiet: enable devcommands first.", "BalancedDiet: сначала включите devcommands."));
			return false;
		}
		if (array.Length != 2 || !int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0 || result > 100)
		{
			Reply(__instance, BalancedDietPlugin.Localize("BalancedDiet: use ", "BalancedDiet: используйте ") + "balanceddiet_set <0-100>.");
			return false;
		}
		if (!BalancedDietPlugin.TrySetAllNutrients(result))
		{
			Reply(__instance, BalancedDietPlugin.Localize("BalancedDiet: the local player is not loaded yet.", "BalancedDiet: локальный персонаж ещё не загружен."));
			return false;
		}
		Reply(__instance, BalancedDietPlugin.Localize("BalancedDiet: all nutrients have been set to ", "BalancedDiet: все показатели установлены на ") + result.ToString(CultureInfo.InvariantCulture) + "%.");
		return false;
	}

	private static void Reply(Terminal terminal, string message)
	{
		bool flag = false;
		try
		{
			if (_addStringMethod == null)
			{
				_addStringMethod = typeof(Terminal).GetMethod("AddString", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			}
			if ((Object)(object)terminal != (Object)null && _addStringMethod != null)
			{
				_addStringMethod.Invoke(terminal, new object[1] { message });
				flag = true;
			}
		}
		catch
		{
			flag = false;
		}
		if (!flag)
		{
			BalancedDietPlugin.Log.LogInfo((object)message);
		}
	}
}
internal static class DietMaximumStatsPatch
{
	public struct FoodUpdateState
	{
		public bool RestoreStamina;

		public float StaminaBefore;
	}

	private static bool _applied;

	internal static void Apply(Harmony harmony)
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Expected O, but got Unknown
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Expected O, but got Unknown
		if (!_applied && harmony != null)
		{
			_applied = true;
			DietMaximumStatsRuntime.Initialize();
			MethodInfo maxHealthSetter = DietMaximumStatsRuntime.MaxHealthSetter;
			if (maxHealthSetter == null)
			{
				BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not find Character.SetMaxHealth(float).");
			}
			else
			{
				HarmonyMethod val = new HarmonyMethod(typeof(DietMaximumStatsPatch), "SetMaxHealthPrefix", (Type[])null);
				harmony.Patch((MethodBase)maxHealthSetter, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				BalancedDietPlugin.Log.LogInfo((object)("Diet health maximum bound to " + maxHealthSetter.DeclaringType.Name + "." + maxHealthSetter.Name + "."));
			}
			MethodInfo methodInfo = FindUpdateFoodMethod();
			if (methodInfo == null)
			{
				BalancedDietPlugin.Log.LogWarning((object)"BalancedDiet could not find Player.UpdateFood. Maximum stats will still be synchronized by the plugin update loop.");
				return;
			}
			HarmonyMethod val2 = new HarmonyMethod(typeof(DietMaximumStatsPatch), "Prefix", (Type[])null);
			HarmonyMethod val3 = new HarmonyMethod(typeof(DietMaximumStatsPatch), "Postfix", (Type[])null);
			harmony.Patch((MethodBase)methodInfo, val2, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			BalancedDietPlugin.Log.LogInfo((object)("Diet maximum stat refresh bound to Player." + methodInfo.Name + "."));
		}
	}

	private static MethodInfo FindUpdateFoodMethod()
	{
		MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		MethodInfo methodInfo = null;
		foreach (MethodInfo methodInfo2 in methods)
		{
			if (!(methodInfo2 == null) && methodInfo2.Name.Equals("UpdateFood", StringComparison.Ordinal) && !(methodInfo2.ReturnType != typeof(void)))
			{
				ParameterInfo[] parameters = methodInfo2.GetParameters();
				if (parameters.Length == 2 && parameters[0].ParameterType == typeof(float) && parameters[1].ParameterType == typeof(bool))
				{
					return methodInfo2;
				}
				if (methodInfo == null)
				{
					methodInfo = methodInfo2;
				}
			}
		}
		return methodInfo;
	}

	public static void SetMaxHealthPrefix(object __instance, ref float __0)
	{
		DietMaximumStatsRuntime.ModifyHealthMaximum((Player)((__instance is Player) ? __instance : null), ref __0);
	}

	public static void Prefix(Player __instance, ref FoodUpdateState __state)
	{
		__state = default(FoodUpdateState);
		if ((Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || __instance != Player.m_localPlayer)
		{
			return;
		}
		try
		{
			__state.RestoreStamina = true;
			__state.StaminaBefore = __instance.GetStamina();
		}
		catch
		{
			__state.RestoreStamina = false;
			__state.StaminaBefore = 0f;
		}
	}

	public static void Postfix(Player __instance, FoodUpdateState __state)
	{
		DietMaximumStatsRuntime.AfterFoodUpdate(__instance, __state.RestoreStamina, __state.StaminaBefore);
	}
}
internal static class DietMaximumStatsRuntime
{
	private const float ComparisonTolerance = 0.001f;

	private static bool _initialized;

	private static FieldInfo _maxStaminaField;

	private static MethodInfo _getMaxHealthMethod;

	private static MethodInfo _setMaxHealthMethod;

	private static bool _suppressHealthModifier;

	private static Player _trackedPlayer;

	private static bool _healthBaseKnown;

	private static float _vanillaMaxHealth;

	private static int _appliedHealthModifier;

	private static float _lastWrittenMaxHealth;

	private static bool _staminaTracked;

	private static int _appliedStaminaModifier;

	private static float _lastWrittenMaxStamina;

	internal static MethodInfo MaxHealthSetter
	{
		get
		{
			Initialize();
			return _setMaxHealthMethod;
		}
	}

	internal static void Initialize()
	{
		if (!_initialized)
		{
			_initialized = true;
			_getMaxHealthMethod = FindFloatGetter(typeof(Character), "GetMaxHealth");
			_setMaxHealthMethod = FindFloatSetter(typeof(Character), "SetMaxHealth");
			_maxStaminaField = FindMaximumField(typeof(Player), "m_maxStamina", "stamina");
			LogResolvedHealthMethods();
			LogResolvedField("stamina", _maxStaminaField);
		}
	}

	internal static void Sync(Player player)
	{
		if (!((Object)(object)player == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && player == Player.m_localPlayer)
		{
			Initialize();
			if (_trackedPlayer != player)
			{
				ForgetPlayer();
				_trackedPlayer = player;
			}
			SyncHealthMaximum(player);
			SyncField(player, _maxStaminaField, BalancedDietPlugin.GetStaminaModifier(player), ref _staminaTracked, ref _appliedStaminaModifier, ref _lastWrittenMaxStamina);
		}
	}

	internal static void ModifyHealthMaximum(Player player, ref float vanillaMaximum)
	{
		if (!_suppressHealthModifier && !((Object)(object)player == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && player == Player.m_localPlayer)
		{
			EnsureTrackedPlayer(player);
			float num = vanillaMaximum;
			int healthModifier = BalancedDietPlugin.GetHealthModifier(player);
			float lastWrittenMaxHealth = (vanillaMaximum = Mathf.Max(1f, num + (float)healthModifier));
			_healthBaseKnown = true;
			_vanillaMaxHealth = num;
			_appliedHealthModifier = healthModifier;
			_lastWrittenMaxHealth = lastWrittenMaxHealth;
		}
	}

	internal static void AfterFoodUpdate(Player player, bool restoreStamina, float staminaBefore)
	{
		if ((Object)(object)player == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || player != Player.m_localPlayer)
		{
			return;
		}
		float num = 0f;
		bool flag = false;
		if (restoreStamina)
		{
			try
			{
				num = player.GetStamina();
				flag = num + 0.001f < staminaBefore;
			}
			catch
			{
				restoreStamina = false;
			}
		}
		if (flag)
		{
			_staminaTracked = false;
		}
		Sync(player);
		if (!restoreStamina || !flag)
		{
			return;
		}
		try
		{
			float num2 = ReadMaximum(player, _maxStaminaField, staminaBefore);
			float num3 = Mathf.Min(staminaBefore, num2);
			float stamina = player.GetStamina();
			if (stamina + 0.001f < num3)
			{
				((Character)player).AddStamina(num3 - stamina);
			}
		}
		catch
		{
		}
	}

	internal static void RestoreTrackedMaximums(Player player)
	{
		if ((Object)(object)player == (Object)null || player != _trackedPlayer)
		{
			ForgetPlayer();
			return;
		}
		RestoreHealthMaximum(player);
		RemoveAppliedModifier(player, _maxStaminaField, ref _staminaTracked, ref _appliedStaminaModifier, ref _lastWrittenMaxStamina);
		ForgetPlayer();
	}

	internal static void ForgetPlayer()
	{
		_trackedPlayer = null;
		_healthBaseKnown = false;
		_vanillaMaxHealth = 0f;
		_appliedHealthModifier = 0;
		_lastWrittenMaxHealth = 0f;
		_staminaTracked = false;
		_appliedStaminaModifier = 0;
		_lastWrittenMaxStamina = 0f;
	}

	private static void EnsureTrackedPlayer(Player player)
	{
		if (_trackedPlayer != player)
		{
			ForgetPlayer();
			_trackedPlayer = player;
		}
	}

	private static void SyncHealthMaximum(Player player)
	{
		if (_getMaxHealthMethod == null || _setMaxHealthMethod == null)
		{
			return;
		}
		int healthModifier = BalancedDietPlugin.GetHealthModifier(player);
		if (!_healthBaseKnown)
		{
			try
			{
				object obj = _getMaxHealthMethod.Invoke(player, new object[0]);
				if (obj is float)
				{
					_vanillaMaxHealth = (float)obj;
					_healthBaseKnown = true;
					WriteHealthMaximum(player, _vanillaMaxHealth, healthModifier);
				}
				return;
			}
			catch (Exception ex)
			{
				BalancedDietPlugin.Log.LogError((object)("BalancedDiet could not read maximum health: " + ex.Message));
				return;
			}
		}
		if (healthModifier != _appliedHealthModifier)
		{
			WriteHealthMaximum(player, _vanillaMaxHealth, healthModifier);
		}
	}

	private static void WriteHealthMaximum(Player player, float vanillaMaximum, int modifier)
	{
		if (_setMaxHealthMethod == null)
		{
			return;
		}
		float num = Mathf.Max(1f, vanillaMaximum + (float)modifier);
		try
		{
			_suppressHealthModifier = true;
			_setMaxHealthMethod.Invoke(player, new object[1] { num });
			_healthBaseKnown = true;
			_vanillaMaxHealth = vanillaMaximum;
			_appliedHealthModifier = modifier;
			_lastWrittenMaxHealth = num;
		}
		catch (Exception ex)
		{
			BalancedDietPlugin.Log.LogError((object)("BalancedDiet could not write maximum health: " + ex.Message));
		}
		finally
		{
			_suppressHealthModifier = false;
		}
	}

	private static void RestoreHealthMaximum(Player player)
	{
		if (!_healthBaseKnown || _setMaxHealthMethod == null)
		{
			return;
		}
		try
		{
			_suppressHealthModifier = true;
			_setMaxHealthMethod.Invoke(player, new object[1] { Mathf.Max(1f, _vanillaMaxHealth) });
		}
		catch
		{
		}
		finally
		{
			_suppressHealthModifier = false;
		}
	}

	private static void SyncField(Player player, FieldInfo field, int desiredModifier, ref bool tracked, ref int appliedModifier, ref float lastWrittenMaximum)
	{
		if (field == null)
		{
			return;
		}
		try
		{
			if (field.GetValue(player) is float num)
			{
				float num2 = ((!tracked || !(Mathf.Abs(num - lastWrittenMaximum) <= 0.001f)) ? num : (num - (float)appliedModifier));
				float num3 = Mathf.Max(1f, num2 + (float)desiredModifier);
				if (Mathf.Abs(num - num3) > 0.001f)
				{
					field.SetValue(player, num3);
				}
				tracked = true;
				appliedModifier = desiredModifier;
				lastWrittenMaximum = num3;
			}
		}
		catch (Exception ex)
		{
			tracked = false;
			BalancedDietPlugin.Log.LogError((object)("BalancedDiet could not synchronize " + field.Name + ": " + ex.Message));
		}
	}

	private static void RemoveAppliedModifier(Player player, FieldInfo field, ref bool tracked, ref int appliedModifier, ref float lastWrittenMaximum)
	{
		if (field == null || !tracked)
		{
			tracked = false;
			appliedModifier = 0;
			lastWrittenMaximum = 0f;
			return;
		}
		try
		{
			if (field.GetValue(player) is float num && Mathf.Abs(num - lastWrittenMaximum) <= 0.001f)
			{
				field.SetValue(player, Mathf.Max(1f, num - (float)appliedModifier));
			}
		}
		catch
		{
		}
		tracked = false;
		appliedModifier = 0;
		lastWrittenMaximum = 0f;
	}

	private static float ReadMaximum(Player player, FieldInfo field, float fallback)
	{
		if ((Object)(object)player == (Object)null || field == null)
		{
			return fallback;
		}
		object value = field.GetValue(player);
		return (value is float) ? ((float)value) : fallback;
	}

	private static MethodInfo FindFloatGetter(Type startingType, string methodName)
	{
		MethodInfo[] methods = startingType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo != null && methodInfo.Name.Equals(methodName, StringComparison.Ordinal) && methodInfo.ReturnType == typeof(float) && methodInfo.GetParameters().Length == 0)
			{
				return methodInfo;
			}
		}
		return null;
	}

	private static MethodInfo FindFloatSetter(Type startingType, string methodName)
	{
		MethodInfo[] methods = startingType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo == null) && methodInfo.Name.Equals(methodName, StringComparison.Ordinal) && !(methodInfo.ReturnType != typeof(void)))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float))
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	private static FieldInfo FindMaximumField(Type startingType, string preferredName, string requiredNamePart)
	{
		Type type = startingType;
		while (type != null)
		{
			FieldInfo field = type.GetField(preferredName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field.FieldType == typeof(float))
			{
				return field;
			}
			type = type.BaseType;
		}
		type = startingType;
		while (type != null)
		{
			FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo != null && fieldInfo.FieldType == typeof(float) && fieldInfo.Name.IndexOf("max", StringComparison.OrdinalIgnoreCase) >= 0 && fieldInfo.Name.IndexOf(requiredNamePart, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return fieldInfo;
				}
			}
			type = type.BaseType;
		}
		return null;
	}

	private static void LogResolvedHealthMethods()
	{
		if (_getMaxHealthMethod == null || _setMaxHealthMethod == null)
		{
			BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not resolve Character health maximum methods.");
			return;
		}
		BalancedDietPlugin.Log.LogInfo((object)("Diet health maximum synchronized through " + _setMaxHealthMethod.DeclaringType.Name + "." + _setMaxHealthMethod.Name + "."));
	}

	private static void LogResolvedField(string statName, FieldInfo field)
	{
		if (field == null)
		{
			BalancedDietPlugin.Log.LogError((object)("BalancedDiet could not find the internal maximum " + statName + " field."));
			return;
		}
		BalancedDietPlugin.Log.LogInfo((object)("Diet " + statName + " maximum synchronized through " + field.DeclaringType.Name + "." + field.Name + "."));
	}
}
internal static class DietRuntimeMultipliersPatch
{
	private static bool _applied;

	internal static void Apply(Harmony harmony)
	{
		if (!_applied && harmony != null)
		{
			_applied = true;
			PatchMovementSpeed(harmony, "GetJogSpeedFactor");
			PatchMovementSpeed(harmony, "GetRunSpeedFactor");
			PatchStaminaRegen(harmony);
		}
	}

	private static void PatchMovementSpeed(Harmony harmony, string methodName)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Expected O, but got Unknown
		MethodInfo methodInfo = FindPlayerFloatGetter(methodName);
		if (methodInfo == null)
		{
			BalancedDietPlugin.Log.LogError((object)("BalancedDiet could not find Player." + methodName + " returning float."));
			return;
		}
		HarmonyMethod val = new HarmonyMethod(typeof(DietRuntimeMultipliersPatch), "MovementSpeedPostfix", (Type[])null);
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		BalancedDietPlugin.Log.LogInfo((object)("Ideal diet movement bonus bound to Player." + methodInfo.Name + "."));
	}

	private static void PatchStaminaRegen(Harmony harmony)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		MethodInfo methodInfo = FindStaminaRegenMethod();
		if (methodInfo == null)
		{
			BalancedDietPlugin.Log.LogError((object)"BalancedDiet could not find SEMan.ModifyStaminaRegen.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(typeof(DietRuntimeMultipliersPatch), "StaminaRegenPostfix", (Type[])null);
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		BalancedDietPlugin.Log.LogInfo((object)"Ideal diet stamina regeneration bonus bound to SEMan.ModifyStaminaRegen.");
	}

	private static MethodInfo FindPlayerFloatGetter(string methodName)
	{
		MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo != null && methodInfo.Name.Equals(methodName, StringComparison.Ordinal) && methodInfo.ReturnType == typeof(float) && methodInfo.GetParameters().Length == 0)
			{
				return methodInfo;
			}
		}
		return null;
	}

	private static MethodInfo FindStaminaRegenMethod()
	{
		MethodInfo[] methods = typeof(SEMan).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo == null) && methodInfo.Name.Equals("ModifyStaminaRegen", StringComparison.Ordinal))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (FindRefFloatIndex(parameters) >= 0)
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	public static void MovementSpeedPostfix(Player __instance, ref float __result)
	{
		float idealMovementSpeedMultiplier = BalancedDietPlugin.GetIdealMovementSpeedMultiplier(__instance);
		if (idealMovementSpeedMultiplier > 1f)
		{
			__result *= idealMovementSpeedMultiplier;
		}
	}

	public static void StaminaRegenPostfix(object __instance, MethodBase __originalMethod, object[] __args)
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || !BalancedDietPlugin.IsLocalPlayerSEMan(__instance) || __originalMethod == null || __args == null)
		{
			return;
		}
		int num = FindRefFloatIndex(__originalMethod.GetParameters());
		if (num >= 0 && num < __args.Length && __args[num] is float)
		{
			float num2 = (float)__args[num];
			float idealStaminaRegenMultiplier = BalancedDietPlugin.GetIdealStaminaRegenMultiplier(localPlayer);
			if (idealStaminaRegenMultiplier > 1f)
			{
				__args[num] = num2 * idealStaminaRegenMultiplier;
			}
		}
	}

	private static int FindRefFloatIndex(ParameterInfo[] parameters)
	{
		if (parameters == null)
		{
			return -1;
		}
		Type type = typeof(float).MakeByRefType();
		for (int i = 0; i < parameters.Length; i++)
		{
			if (parameters[i] != null && parameters[i].ParameterType == type)
			{
				return i;
			}
		}
		return -1;
	}
}