Decompiled source of On Last HP v1.0.5

plugins/On_Last_HP/OnLastHP.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OnLastHP")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("OnLastHP")]
[assembly: AssemblyTitle("OnLastHP")]
[assembly: AssemblyVersion("1.0.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OnLastHP
{
	[HarmonyPatch(typeof(HealthComponent), "get_alive")]
	internal static class AlivePatch
	{
		[HarmonyPostfix]
		private static void Postfix(HealthComponent __instance, ref bool __result)
		{
			int num = Plugin.Count(__instance);
			if (num > 0)
			{
				__result = HealthRules.IsAlive(__instance.health, num);
			}
		}
	}
	[HarmonyPatch]
	internal static class DeathFloorPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(HealthComponent), "TakeDamageProcess", new Type[1] { typeof(DamageInfo) }, (Type[])null);
			yield return AccessTools.Method(typeof(HealthComponent), "Suicide", new Type[3]
			{
				typeof(GameObject),
				typeof(GameObject),
				typeof(DamageTypeCombo)
			}, (Type[])null);
			yield return AccessTools.Method(typeof(HealthComponent), "Die", new Type[1] { typeof(bool) }, (Type[])null);
			yield return AccessTools.Method(typeof(HealthComponent), "ServerFixedUpdate", new Type[1] { typeof(float) }, (Type[])null);
		}

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
		{
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			FieldInfo fieldInfo = AccessTools.Field(typeof(HealthComponent), "health");
			MethodInfo methodInfo = AccessTools.PropertySetter(typeof(HealthComponent), "Networkhealth");
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "DeathFloor", (Type[])null, (Type[])null);
			int num = 0;
			int num2 = 0;
			for (int i = 1; i + 1 < list.Count; i++)
			{
				if (list[i].opcode != OpCodes.Ldc_R4 || !(list[i].operand is float num3) || num3 != 0f)
				{
					continue;
				}
				bool flag = CodeInstructionExtensions.Calls(list[i + 1], methodInfo);
				bool num4 = CodeInstructionExtensions.LoadsField(list[i - 1], fieldInfo, false) || (i >= 3 && list[i - 1].opcode == OpCodes.Add && CodeInstructionExtensions.LoadsField(list[i - 3], fieldInfo, false));
				bool flag2 = i + 4 < list.Count && CodeInstructionExtensions.Calls(list[i + 4], methodInfo);
				bool flag3 = num4 && list[i + 1].opcode.FlowControl == FlowControl.Cond_Branch && (__originalMethod.Name == "ServerFixedUpdate" || flag2);
				if (flag || flag3)
				{
					list[i].opcode = OpCodes.Ldarg_0;
					list[i].operand = null;
					list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo2));
					if (flag)
					{
						num++;
					}
					if (flag3)
					{
						num2++;
					}
					i++;
				}
			}
			int num5 = ((!(__originalMethod.Name == "ServerFixedUpdate")) ? 1 : 0);
			int num6 = ((!(__originalMethod.Name == "Suicide") && !(__originalMethod.Name == "Die")) ? 1 : 0);
			if (num != num5 || num2 != num6)
			{
				throw new InvalidOperationException($"Unsupported RoR2 IL in {__originalMethod.Name}: stores={num}, comparisons={num2}.");
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(GenericSkill), "CanExecute")]
	internal static class SpecialExecutionPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(GenericSkill __instance, ref bool __result)
		{
			if (!Plugin.SpecialBlocked(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(GenericSkill), "IsReady")]
	internal static class SpecialReadyPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GenericSkill __instance, ref bool __result)
		{
			if (Plugin.SpecialBlocked(__instance))
			{
				__result = false;
			}
		}
	}
	internal static class HealthRules
	{
		internal const float HealthPerStack = 75f;

		internal static float DeathFloor(int count)
		{
			if (count <= 0)
			{
				return 0f;
			}
			return -75f * (float)count;
		}

		internal static bool IsAlive(float health, int count)
		{
			return health > DeathFloor(count);
		}

		internal static bool BlocksSpecial(float health, int count)
		{
			if (count > 0)
			{
				return health < 0f;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemIcon), "SetItemIndex", new Type[] { typeof(SetItemIndexArgs) })]
	internal static class InventoryIconLayoutPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemIcon __instance)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Object.op_Implicit((Object)(object)Plugin.Item) && __instance.itemIndex == Plugin.Item.itemIndex;
			InventoryIconLayout inventoryIconLayout = ((Component)__instance).GetComponent<InventoryIconLayout>();
			if (flag && !Object.op_Implicit((Object)(object)inventoryIconLayout))
			{
				inventoryIconLayout = ((Component)__instance).gameObject.AddComponent<InventoryIconLayout>();
			}
			if (Object.op_Implicit((Object)(object)inventoryIconLayout))
			{
				inventoryIconLayout.Apply(__instance, flag);
			}
		}
	}
	internal sealed class InventoryIconLayout : MonoBehaviour
	{
		private RectTransform imageRect;

		private Vector2 anchorMin;

		private Vector2 anchorMax;

		private Vector2 offsetMin;

		private Vector2 offsetMax;

		private Vector3 scale;

		private Rect uv;

		private bool applied;

		internal void Apply(ItemIcon icon, bool ours)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)icon.image))
			{
				return;
			}
			if (ours && !applied)
			{
				imageRect = ((Graphic)icon.image).rectTransform;
				anchorMin = imageRect.anchorMin;
				anchorMax = imageRect.anchorMax;
				offsetMin = imageRect.offsetMin;
				offsetMax = imageRect.offsetMax;
				scale = ((Transform)imageRect).localScale;
				uv = icon.image.uvRect;
				applied = true;
				if ((Object)(object)imageRect != (Object)(object)icon.rectTransform)
				{
					imageRect.anchorMin = Vector2.zero;
					imageRect.anchorMax = Vector2.one;
					imageRect.offsetMin = new Vector2(2f, 2f);
					imageRect.offsetMax = new Vector2(-2f, -2f);
					((Transform)imageRect).localScale = Vector3.one;
				}
				icon.image.uvRect = new Rect(0f, 0f, 1f, 1f);
			}
			else if (!ours && applied)
			{
				imageRect.anchorMin = anchorMin;
				imageRect.anchorMax = anchorMax;
				imageRect.offsetMin = offsetMin;
				imageRect.offsetMax = offsetMax;
				((Transform)imageRect).localScale = scale;
				icon.image.uvRect = uv;
				applied = false;
			}
		}
	}
	internal sealed class ObjMeshData
	{
		internal readonly List<float[]> Positions = new List<float[]>();

		internal readonly List<float[]> UVs = new List<float[]>();

		internal readonly List<int> Triangles = new List<int>();

		internal static ObjMeshData Parse(TextReader reader)
		{
			List<float[]> list = new List<float[]>();
			List<float[]> list2 = new List<float[]>();
			ObjMeshData objMeshData = new ObjMeshData();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			string text;
			while ((text = reader.ReadLine()) != null)
			{
				string[] array = text.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
				if (array.Length == 0 || array[0].StartsWith("#"))
				{
					continue;
				}
				if (array[0] == "v")
				{
					list.Add(new float[3]
					{
						Number(array[1]),
						Number(array[2]),
						Number(array[3])
					});
				}
				else if (array[0] == "vt")
				{
					list2.Add(new float[2]
					{
						Number(array[1]),
						Number(array[2])
					});
				}
				else
				{
					if (!(array[0] == "f"))
					{
						continue;
					}
					List<int> list3 = new List<int>();
					for (int i = 1; i < array.Length && !array[i].StartsWith("#"); i++)
					{
						string key = array[i] + ":" + list.Count + ":" + list2.Count;
						if (!dictionary.TryGetValue(key, out var value))
						{
							string[] array2 = array[i].Split('/');
							value = objMeshData.Positions.Count;
							objMeshData.Positions.Add(list[Resolve(array2[0], list.Count)]);
							objMeshData.UVs.Add((array2.Length > 1 && array2[1].Length > 0) ? list2[Resolve(array2[1], list2.Count)] : new float[2]);
							dictionary.Add(key, value);
						}
						list3.Add(value);
					}
					if (list3.Count < 3)
					{
						throw new FormatException("OBJ face has fewer than 3 vertices.");
					}
					for (int j = 1; j + 1 < list3.Count; j++)
					{
						objMeshData.Triangles.Add(list3[0]);
						objMeshData.Triangles.Add(list3[j + 1]);
						objMeshData.Triangles.Add(list3[j]);
					}
				}
			}
			if (objMeshData.Triangles.Count == 0)
			{
				throw new FormatException("OBJ contains no faces.");
			}
			return objMeshData;
		}

		private static float Number(string value)
		{
			return float.Parse(value, CultureInfo.InvariantCulture);
		}

		private static int Resolve(string value, int count)
		{
			int num = int.Parse(value, CultureInfo.InvariantCulture);
			num = ((num > 0) ? (num - 1) : (count + num));
			if (num < 0 || num >= count)
			{
				throw new FormatException("OBJ index out of range.");
			}
			return num;
		}
	}
	[BepInPlugin("ua.onlasthp.item", "On Last HP", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		private sealed class Tokens
		{
			public string name = "";

			public string pickup = "";

			public string description = "";

			public string lore = "";
		}

		public const string Guid = "ua.onlasthp.item";

		public const string Version = "1.0.4";

		internal static ItemDef Item;

		internal static GameObject BeltDisplayPrefab;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Expected O, but got Unknown
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Expected O, but got Unknown
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Expected O, but got Unknown
			try
			{
				string[] array = new string[13]
				{
					"en", "uk", "de", "es-419", "es-ES", "FR", "IT", "ja", "ko", "pt-BR",
					"RU", "tr", "zh-CN"
				};
				foreach (string text in array)
				{
					RegisterLanguage(text, text);
					if (text.ToLowerInvariant() != text)
					{
						RegisterLanguage(text, text.ToLowerInvariant());
					}
				}
				RegisterLanguage("en", "generic");
				RegisterLanguage("uk", "ua");
				RegisterLanguage("uk", "uk-UA");
				ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "auto", "Item text: auto (game language), en, or uk. Does not change the game's language.");
				if (val.Value == "uk" || val.Value == "en")
				{
					using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("OnLastHP." + val.Value + ".json");
					using StreamReader streamReader = new StreamReader(stream);
					Tokens tokens = JsonUtility.FromJson<Tokens>(streamReader.ReadToEnd());
					LanguageAPI.AddOverlay("ONLASTHP_NAME", tokens.name);
					LanguageAPI.AddOverlay("ONLASTHP_PICKUP", tokens.pickup);
					LanguageAPI.AddOverlay("ONLASTHP_DESCRIPTION", tokens.description);
					LanguageAPI.AddOverlay("ONLASTHP_LORE", tokens.lore);
				}
				Item = ScriptableObject.CreateInstance<ItemDef>();
				((Object)Item).name = "OnLastHP";
				Item.nameToken = "ONLASTHP_NAME";
				Item.pickupToken = "ONLASTHP_PICKUP";
				Item.descriptionToken = "ONLASTHP_DESCRIPTION";
				Item.loreToken = "ONLASTHP_LORE";
				AccessTools.Field(typeof(ItemDef), "deprecatedTier").SetValue(Item, (object)(ItemTier)0);
				Item.tags = (ItemTag[])(object)new ItemTag[2]
				{
					(ItemTag)3,
					(ItemTag)16
				};
				Item.canRemove = true;
				Item.pickupIconSprite = RuntimeAssets.LoadIcon();
				Item.pickupModelPrefab = RuntimeAssets.CreateTractor();
				BeltDisplayPrefab = RuntimeAssets.CreateBeltDisplay(Item.pickupModelPrefab);
				harmony = new Harmony("ua.onlasthp.item");
				harmony.PatchAll(typeof(Plugin).Assembly);
				if (!ItemAPI.Add(new CustomItem(Item, new ItemDisplayRuleDict((ItemDisplayRule[])null))))
				{
					throw new InvalidOperationException("ItemAPI refused OnLastHP registration.");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"On Last HP 1.0.4 loaded: Tier1, -75 HP per stack; special locked below 0 HP.");
			}
			catch (Exception arg)
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogError((object)$"On Last HP could not initialize: {arg}");
				((Behaviour)this).enabled = false;
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		internal static int Count(HealthComponent health)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)health) || !Object.op_Implicit((Object)(object)health.body) || !Object.op_Implicit((Object)(object)health.body.inventory) || !Object.op_Implicit((Object)(object)Item) || (int)Item.itemIndex == -1)
			{
				return 0;
			}
			return health.body.inventory.GetItemCount(Item.itemIndex);
		}

		public static float DeathFloor(HealthComponent health)
		{
			return HealthRules.DeathFloor(Count(health));
		}

		internal static bool SpecialBlocked(GenericSkill skill)
		{
			CharacterBody characterBody = skill.characterBody;
			if (Object.op_Implicit((Object)(object)characterBody) && Object.op_Implicit((Object)(object)characterBody.healthComponent) && Object.op_Implicit((Object)(object)characterBody.skillLocator) && (Object)(object)characterBody.skillLocator.special == (Object)(object)skill)
			{
				return HealthRules.BlocksSpecial(characterBody.healthComponent.health, Count(characterBody.healthComponent));
			}
			return false;
		}

		private static void RegisterLanguage(string resource, string language)
		{
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("OnLastHP." + resource + ".json");
			using StreamReader streamReader = new StreamReader(stream ?? throw new FileNotFoundException(resource));
			Tokens tokens = JsonUtility.FromJson<Tokens>(streamReader.ReadToEnd());
			LanguageAPI.Add("ONLASTHP_NAME", tokens.name, language);
			LanguageAPI.Add("ONLASTHP_PICKUP", tokens.pickup, language);
			LanguageAPI.Add("ONLASTHP_DESCRIPTION", tokens.description, language);
			LanguageAPI.Add("ONLASTHP_LORE", tokens.lore, language);
		}
	}
	[HarmonyPatch(typeof(CharacterModel), "Awake")]
	internal static class RearBeltDisplayPatch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterModel __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<RearBeltDisplay>()))
			{
				((Component)__instance).gameObject.AddComponent<RearBeltDisplay>();
			}
		}
	}
	internal sealed class RearBeltDisplay : MonoBehaviour
	{
		private CharacterModel model;

		private CharacterBody body;

		private Transform beltBone;

		private string beltBoneName;

		private Vector3 beltLocalPosition;

		private Quaternion beltLocalRotation;

		private Vector3 beltLocalScale;

		private GameObject instance;

		private float nextInventoryCheck;

		private void Start()
		{
			model = ((Component)this).GetComponent<CharacterModel>();
			body = ((Component)this).GetComponentInParent<CharacterBody>();
			if (!Object.op_Implicit((Object)(object)body))
			{
				body = model.body;
			}
			ChildLocator component = ((Component)this).GetComponent<ChildLocator>();
			if (Object.op_Implicit((Object)(object)component))
			{
				string[] array = new string[9] { "Pelvis", "Hip", "Hips", "Stomach", "SpineStomach1", "MechBase", "PlatformBase", "Chest", "Center" };
				foreach (string text in array)
				{
					beltBone = component.FindChild(text);
					if (Object.op_Implicit((Object)(object)beltBone))
					{
						beltBoneName = text;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)beltBone))
			{
				beltBone = ((Component)this).transform;
			}
			if (Object.op_Implicit((Object)(object)body))
			{
				CacheBeltPose();
			}
		}

		private void CacheBeltPose()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)body).transform;
			Transform val = beltBone;
			GameObject bodyPrefab = BodyCatalog.GetBodyPrefab(body.bodyIndex);
			ModelLocator val2 = (Object.op_Implicit((Object)(object)bodyPrefab) ? bodyPrefab.GetComponent<ModelLocator>() : null);
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.modelTransform))
			{
				ChildLocator component = ((Component)val2.modelTransform).GetComponent<ChildLocator>();
				Transform val3 = ((Object.op_Implicit((Object)(object)component) && !string.IsNullOrEmpty(beltBoneName)) ? component.FindChild(beltBoneName) : val2.modelTransform);
				if (Object.op_Implicit((Object)(object)val3))
				{
					transform = bodyPrefab.transform;
					val = val3;
				}
			}
			float num = Mathf.Clamp(body.radius, 0.7f, 3.5f);
			Vector3 val4 = val.position - transform.forward * (0.27f * num) - transform.up * (0.09f * num);
			beltLocalPosition = val.InverseTransformPoint(val4);
			beltLocalRotation = Quaternion.Inverse(val.rotation) * transform.rotation * Quaternion.Euler(0f, 90f, 0f);
			Vector3 lossyScale = val.lossyScale;
			float num2 = 0.26f * num;
			beltLocalScale = new Vector3(num2 / Mathf.Max(Mathf.Abs(lossyScale.x), 0.001f), num2 / Mathf.Max(Mathf.Abs(lossyScale.y), 0.001f), num2 / Mathf.Max(Mathf.Abs(lossyScale.z), 0.001f));
		}

		private void LateUpdate()
		{
			//IL_00b6: 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)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)model) && Object.op_Implicit((Object)(object)Plugin.BeltDisplayPrefab) && Time.unscaledTime >= nextInventoryCheck)
			{
				nextInventoryCheck = Time.unscaledTime + 0.2f;
				bool flag = Object.op_Implicit((Object)(object)body.healthComponent) && Plugin.Count(body.healthComponent) > 0;
				if (flag && !Object.op_Implicit((Object)(object)instance))
				{
					instance = Object.Instantiate<GameObject>(Plugin.BeltDisplayPrefab, beltBone);
					((Object)instance).name = "OnLastHP_RearBelt";
					instance.transform.localPosition = beltLocalPosition;
					instance.transform.localRotation = beltLocalRotation;
					instance.transform.localScale = beltLocalScale;
					model.AddCustomDisplayPrefab(instance, Plugin.BeltDisplayPrefab);
				}
				else if (!flag && Object.op_Implicit((Object)(object)instance))
				{
					model.RemoveCustomDisplayPrefab(Plugin.BeltDisplayPrefab);
					instance = null;
				}
			}
		}
	}
	internal static class RuntimeAssets
	{
		private static Texture2D LoadTexture(string resource)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0055: 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_0064: Expected O, but got Unknown
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream(resource);
			using MemoryStream memoryStream = new MemoryStream();
			if (stream == null)
			{
				throw new FileNotFoundException(resource);
			}
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray()))
			{
				throw new InvalidDataException("Could not decode " + resource);
			}
			((Object)val).name = resource;
			((Texture)val).wrapMode = (TextureWrapMode)0;
			return val;
		}

		internal static Sprite LoadIcon()
		{
			//IL_004b: 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)
			Texture2D val = LoadTexture("OnLastHP.Icon.png");
			if (((Texture)val).width != ((Texture)val).height)
			{
				throw new InvalidDataException("Inventory icon must be square.");
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
		}

		internal static GameObject CreateTractor()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Expected O, but got Unknown
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			ObjMeshData objMeshData;
			using (Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("OnLastHP.Tractor.obj"))
			{
				using StreamReader reader = new StreamReader(stream ?? throw new FileNotFoundException("Tractor.obj"));
				objMeshData = ObjMeshData.Parse(reader);
			}
			Vector3[] array = ((IEnumerable<float[]>)objMeshData.Positions).Select((Func<float[], Vector3>)((float[] p) => new Vector3(0f - p[0], p[1], p[2]))).ToArray();
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(array[0], Vector3.zero);
			Vector3[] array2 = array;
			foreach (Vector3 val2 in array2)
			{
				((Bounds)(ref val)).Encapsulate(val2);
			}
			float num2 = 1.2f / Mathf.Max(((Bounds)(ref val)).size.x, Mathf.Max(((Bounds)(ref val)).size.y, ((Bounds)(ref val)).size.z));
			for (int num3 = 0; num3 < array.Length; num3++)
			{
				array[num3] = (array[num3] - ((Bounds)(ref val)).center) * num2;
			}
			Mesh val3 = new Mesh
			{
				name = "OnLastHP_Tractor",
				indexFormat = (IndexFormat)1
			};
			val3.vertices = array;
			val3.uv = ((IEnumerable<float[]>)objMeshData.UVs).Select((Func<float[], Vector2>)((float[] uv) => new Vector2(uv[0], uv[1]))).ToArray();
			val3.triangles = objMeshData.Triangles.ToArray();
			val3.RecalculateNormals();
			val3.RecalculateBounds();
			Shader obj = Shader.Find("Hopoo Games/Deferred/Standard") ?? Shader.Find("Standard");
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("No supported item shader was found.");
			}
			Material val4 = new Material(obj)
			{
				name = "OnLastHP_TractorMaterial"
			};
			val4.mainTexture = (Texture)(object)LoadTexture("OnLastHP.Tractor.jpg");
			if (val4.HasProperty("_Color"))
			{
				val4.SetColor("_Color", Color.white);
			}
			GameObject val5 = new GameObject("OnLastHP_PrefabStorage");
			val5.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)val5);
			GameObject val6 = new GameObject("OnLastHP_TractorPickup");
			val6.transform.SetParent(val5.transform, false);
			GameObject val7 = new GameObject("Tractor");
			val7.transform.SetParent(val6.transform, false);
			val7.AddComponent<MeshFilter>().sharedMesh = val3;
			((Renderer)val7.AddComponent<MeshRenderer>()).sharedMaterial = val4;
			return val6;
		}

		internal static GameObject CreateBeltDisplay(GameObject pickup)
		{
			GameObject val = Object.Instantiate<GameObject>(pickup, pickup.transform.parent);
			((Object)val).name = "OnLastHP_RearBeltDisplay";
			ItemDisplay obj = val.AddComponent<ItemDisplay>();
			obj.rendererInfos = ((IEnumerable<Renderer>)val.GetComponentsInChildren<Renderer>(true)).Select((Func<Renderer, RendererInfo>)((Renderer renderer) => new RendererInfo
			{
				renderer = renderer,
				defaultMaterial = renderer.sharedMaterial,
				defaultShadowCastingMode = (ShadowCastingMode)0,
				hideOnDeath = true
			})).ToArray();
			obj.hideOnDeathObjects = Array.Empty<GameObject>();
			return val;
		}
	}
}