Decompiled source of Watcher v1.0.0

plugins/WatcherMod.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EmotesAPI;
using EntityStates;
using EntityStates.AI.Walker;
using EntityStates.Huntress;
using EntityStates.TitanMonster;
using EntityStates.Treebot.Weapon;
using HG;
using HG.BlendableTypes;
using HarmonyLib;
using KinematicCharacterController;
using On.RoR2;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Achievements;
using RoR2.AsyncManagement;
using RoR2.Audio;
using RoR2.CharacterAI;
using RoR2.ContentManagement;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using WatcherMod.Modules;
using WatcherMod.Modules.Characters;
using WatcherMod.Survivors.Watcher;
using WatcherMod.Survivors.Watcher.Components;
using WatcherMod.Survivors.Watcher.SkillStates;

[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("WatcherMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ae04c6578c9c9b2f39d7c1264053e73a73122d14")]
[assembly: AssemblyProduct("WatcherMod")]
[assembly: AssemblyTitle("WatcherMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace WatcherMod
{
	internal static class Log
	{
		internal static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void ErrorAssetBundle(string assetName, string bundleName)
		{
			Error("failed to load asset, " + assetName + ", because it does not exist in asset bundle, " + bundleName);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.Def537.Watcher", "WatcherMod", "1.0.0")]
	public class WatcherPlugin : BaseUnityPlugin
	{
		public const string MODUID = "com.Def537.Watcher";

		public const string MODNAME = "WatcherMod";

		public const string MODVERSION = "1.0.0";

		public const string DEVELOPER_PREFIX = "DEF537";

		public static WatcherPlugin instance;

		private void Awake()
		{
			instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			Language.Init();
			new WatcherSurvivor().Initialize();
			if (Chainloader.PluginInfos.ContainsKey("com.weliveinasociety.CustomEmotesAPI"))
			{
				WatcherEmotes.Init();
			}
			new ContentPacks().Initialize();
		}
	}
}
namespace WatcherMod.Modules
{
	internal static class Asset
	{
		internal static Dictionary<string, AssetBundle> loadedBundles = new Dictionary<string, AssetBundle>();

		internal static AssetBundle LoadAssetBundle(string bundleName)
		{
			if (bundleName == "myassetbundle")
			{
				Log.Error("AssetBundle name hasn't been changed. not loading any assets to avoid conflicts.\nMake sure to rename your assetbundle filename and rename the AssetBundleName field in your character setup code ");
				return null;
			}
			if (loadedBundles.ContainsKey(bundleName))
			{
				return loadedBundles[bundleName];
			}
			AssetBundle val = null;
			try
			{
				val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)WatcherPlugin.instance).Info.Location), "AssetBundles", bundleName));
			}
			catch (Exception arg)
			{
				Log.Error($"Error loading asset bundle, {bundleName}. Your asset bundle must be in a folder next to your mod dll called 'AssetBundles'. Follow the guide to build and install your mod correctly!\n{arg}");
			}
			loadedBundles[bundleName] = val;
			return val;
		}

		internal static GameObject CloneTracer(string originalTracerName, string newTracerName)
		{
			if ((Object)(object)LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/Tracers/" + originalTracerName) == (Object)null)
			{
				return null;
			}
			GameObject val = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/Tracers/" + originalTracerName), newTracerName, true);
			if (!Object.op_Implicit((Object)(object)val.GetComponent<EffectComponent>()))
			{
				val.AddComponent<EffectComponent>();
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<VFXAttributes>()))
			{
				val.AddComponent<VFXAttributes>();
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<NetworkIdentity>()))
			{
				val.AddComponent<NetworkIdentity>();
			}
			val.GetComponent<Tracer>().speed = 250f;
			val.GetComponent<Tracer>().length = 50f;
			Content.CreateAndAddEffectDef(val);
			return val;
		}

		internal static void ConvertAllRenderersToHopooShader(GameObject objectToConvert)
		{
			if (!Object.op_Implicit((Object)(object)objectToConvert))
			{
				return;
			}
			MeshRenderer[] componentsInChildren = objectToConvert.GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Renderer)val).sharedMaterial))
				{
					((Renderer)val).sharedMaterial.ConvertDefaultShaderToHopoo();
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = objectToConvert.GetComponentsInChildren<SkinnedMeshRenderer>();
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)((Renderer)val2).sharedMaterial))
				{
					((Renderer)val2).sharedMaterial.ConvertDefaultShaderToHopoo();
				}
			}
		}

		internal static GameObject LoadCrosshair(string crosshairName)
		{
			GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/Crosshair/" + crosshairName + "Crosshair");
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("could not load crosshair with the name " + crosshairName + ". defaulting to Standard");
				return LegacyResourcesAPI.Load<GameObject>("Prefabs/Crosshair/StandardCrosshair");
			}
			return val;
		}

		internal static GameObject LoadEffect(this AssetBundle assetBundle, string resourceName, bool parentToTransform)
		{
			return assetBundle.LoadEffect(resourceName, "", parentToTransform);
		}

		internal static GameObject LoadEffect(this AssetBundle assetBundle, string resourceName, string soundName = "", bool parentToTransform = false)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = assetBundle.LoadAsset<GameObject>(resourceName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Log.ErrorAssetBundle(resourceName, ((Object)assetBundle).name);
				return null;
			}
			val.AddComponent<DestroyOnTimer>().duration = 12f;
			val.AddComponent<NetworkIdentity>();
			val.AddComponent<VFXAttributes>().vfxPriority = (VFXPriority)2;
			EffectComponent obj = val.AddComponent<EffectComponent>();
			obj.applyScale = false;
			obj.effectIndex = (EffectIndex)(-1);
			obj.parentToReferencedTransform = parentToTransform;
			obj.positionAtReferencedTransform = true;
			obj.soundName = soundName;
			Content.CreateAndAddEffectDef(val);
			return val;
		}

		internal static GameObject CreateProjectileGhostPrefab(this AssetBundle assetBundle, string ghostName)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(ghostName);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("Failed to load ghost prefab " + ghostName);
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<NetworkIdentity>()))
			{
				val.AddComponent<NetworkIdentity>();
			}
			if (!Object.op_Implicit((Object)(object)val.GetComponent<ProjectileGhostController>()))
			{
				val.AddComponent<ProjectileGhostController>();
			}
			ConvertAllRenderersToHopooShader(val);
			return val;
		}

		internal static GameObject CloneProjectilePrefab(string prefabName, string newPrefabName)
		{
			return PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("Prefabs/Projectiles/" + prefabName), newPrefabName);
		}

		internal static GameObject LoadAndAddProjectilePrefab(this AssetBundle assetBundle, string newPrefabName)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(newPrefabName);
			if ((Object)(object)val == (Object)null)
			{
				Log.ErrorAssetBundle(newPrefabName, ((Object)assetBundle).name);
				return null;
			}
			Content.AddProjectilePrefab(val);
			return val;
		}
	}
	public static class Config
	{
		public static ConfigFile MyConfig = ((BaseUnityPlugin)WatcherPlugin.instance).Config;

		public static ConfigEntry<bool> CharacterEnableConfig(string section, string characterName, string description = "", bool enabledByDefault = true)
		{
			if (string.IsNullOrEmpty(description))
			{
				description = "Set to false to disable this character and as much of its code and content as possible";
			}
			return BindAndOptions(section, "Enable " + characterName, enabledByDefault, description, restartRequired: true);
		}

		public static ConfigEntry<T> BindAndOptions<T>(string section, string name, T defaultValue, string description = "", bool restartRequired = false)
		{
			return BindAndOptions(section, name, defaultValue, 0f, 20f, description, restartRequired);
		}

		public static ConfigEntry<T> BindAndOptions<T>(string section, string name, T defaultValue, float min, float max, string description = "", bool restartRequired = false)
		{
			if (string.IsNullOrEmpty(description))
			{
				description = name;
			}
			if (restartRequired)
			{
				description += " (restart required)";
			}
			ConfigEntry<T> result = MyConfig.Bind<T>(section, name, defaultValue, description);
			Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");
			return result;
		}

		public static ConfigEntry<float> BindAndOptionsSlider(string section, string name, float defaultValue, string description, float min = 0f, float max = 20f, bool restartRequired = false)
		{
			return BindAndOptions(section, name, defaultValue, min, max, description, restartRequired);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static void TryRegisterOption<T>(ConfigEntry<T> entry, float min, float max, bool restartRequired)
		{
		}

		public static bool GetKeyPressed(KeyboardShortcut entry)
		{
			//IL_0010: 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)
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref entry)).Modifiers)
			{
				if (!Input.GetKey(modifier))
				{
					return false;
				}
			}
			return Input.GetKeyDown(((KeyboardShortcut)(ref entry)).MainKey);
		}
	}
	internal class Content
	{
		internal static void AddCharacterBodyPrefab(GameObject bprefab)
		{
			ContentPacks.bodyPrefabs.Add(bprefab);
		}

		internal static void AddMasterPrefab(GameObject prefab)
		{
			ContentPacks.masterPrefabs.Add(prefab);
		}

		internal static void AddProjectilePrefab(GameObject prefab)
		{
			ContentPacks.projectilePrefabs.Add(prefab);
		}

		internal static void AddSurvivorDef(SurvivorDef survivorDef)
		{
			ContentPacks.survivorDefs.Add(survivorDef);
		}

		internal static void CreateSurvivor(GameObject bodyPrefab, GameObject displayPrefab, Color charColor, string tokenPrefix)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			CreateSurvivor(bodyPrefab, displayPrefab, charColor, tokenPrefix, null, 100f);
		}

		internal static void CreateSurvivor(GameObject bodyPrefab, GameObject displayPrefab, Color charColor, string tokenPrefix, float sortPosition)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			CreateSurvivor(bodyPrefab, displayPrefab, charColor, tokenPrefix, null, sortPosition);
		}

		internal static void CreateSurvivor(GameObject bodyPrefab, GameObject displayPrefab, Color charColor, string tokenPrefix, UnlockableDef unlockableDef)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			CreateSurvivor(bodyPrefab, displayPrefab, charColor, tokenPrefix, unlockableDef, 100f);
		}

		internal static void CreateSurvivor(GameObject bodyPrefab, GameObject displayPrefab, Color charColor, string tokenPrefix, UnlockableDef unlockableDef, float sortPosition)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			SurvivorDef obj = ScriptableObject.CreateInstance<SurvivorDef>();
			obj.bodyPrefab = bodyPrefab;
			obj.displayPrefab = displayPrefab;
			obj.primaryColor = charColor;
			obj.cachedName = ((Object)bodyPrefab).name.Replace("Body", "");
			obj.displayNameToken = tokenPrefix + "NAME";
			obj.descriptionToken = tokenPrefix + "DESCRIPTION";
			obj.outroFlavorToken = tokenPrefix + "OUTRO_FLAVOR";
			obj.mainEndingEscapeFailureFlavorToken = tokenPrefix + "OUTRO_FAILURE";
			obj.desiredSortPosition = sortPosition;
			obj.unlockableDef = unlockableDef;
			AddSurvivorDef(obj);
		}

		internal static void AddUnlockableDef(UnlockableDef unlockableDef)
		{
			ContentPacks.unlockableDefs.Add(unlockableDef);
		}

		internal static UnlockableDef CreateAndAddUnlockbleDef(string identifier, string nameToken, Sprite achievementIcon)
		{
			UnlockableDef obj = ScriptableObject.CreateInstance<UnlockableDef>();
			obj.cachedName = identifier;
			obj.nameToken = nameToken;
			obj.achievementIcon = achievementIcon;
			AddUnlockableDef(obj);
			return obj;
		}

		internal static void AddSkillDef(SkillDef skillDef)
		{
			ContentPacks.skillDefs.Add(skillDef);
		}

		internal static void AddSkillFamily(SkillFamily skillFamily)
		{
			ContentPacks.skillFamilies.Add(skillFamily);
		}

		internal static void AddEntityState(Type entityState)
		{
			ContentPacks.entityStates.Add(entityState);
		}

		internal static void AddBuffDef(BuffDef buffDef)
		{
			ContentPacks.buffDefs.Add(buffDef);
		}

		internal static BuffDef CreateAndAddBuff(string buffName, Sprite buffIcon, Color buffColor, bool canStack, bool isDebuff)
		{
			//IL_000d: 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)
			BuffDef obj = ScriptableObject.CreateInstance<BuffDef>();
			((Object)obj).name = buffName;
			obj.buffColor = buffColor;
			obj.canStack = canStack;
			obj.isDebuff = isDebuff;
			obj.eliteDef = null;
			obj.iconSprite = buffIcon;
			AddBuffDef(obj);
			return obj;
		}

		internal static void AddEffectDef(EffectDef effectDef)
		{
			ContentPacks.effectDefs.Add(effectDef);
		}

		internal static EffectDef CreateAndAddEffectDef(GameObject effectPrefab)
		{
			//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_000c: Expected O, but got Unknown
			//IL_000d: Expected O, but got Unknown
			EffectDef val = new EffectDef(effectPrefab);
			AddEffectDef(val);
			return val;
		}

		internal static void AddNetworkSoundEventDef(NetworkSoundEventDef networkSoundEventDef)
		{
			ContentPacks.networkSoundEventDefs.Add(networkSoundEventDef);
		}

		internal static NetworkSoundEventDef CreateAndAddNetworkSoundEventDef(string eventName)
		{
			NetworkSoundEventDef obj = ScriptableObject.CreateInstance<NetworkSoundEventDef>();
			obj.akId = AkSoundEngine.GetIDFromString(eventName);
			obj.eventName = eventName;
			AddNetworkSoundEventDef(obj);
			return obj;
		}
	}
	internal class ContentPacks : IContentPackProvider
	{
		internal ContentPack contentPack = new ContentPack();

		public static List<GameObject> bodyPrefabs = new List<GameObject>();

		public static List<GameObject> masterPrefabs = new List<GameObject>();

		public static List<GameObject> projectilePrefabs = new List<GameObject>();

		public static List<SurvivorDef> survivorDefs = new List<SurvivorDef>();

		public static List<UnlockableDef> unlockableDefs = new List<UnlockableDef>();

		public static List<SkillFamily> skillFamilies = new List<SkillFamily>();

		public static List<SkillDef> skillDefs = new List<SkillDef>();

		public static List<Type> entityStates = new List<Type>();

		public static List<BuffDef> buffDefs = new List<BuffDef>();

		public static List<EffectDef> effectDefs = new List<EffectDef>();

		public static List<NetworkSoundEventDef> networkSoundEventDefs = new List<NetworkSoundEventDef>();

		public string identifier => "com.Def537.Watcher";

		public void Initialize()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			ContentManager.collectContentPackProviders += new CollectContentPackProvidersDelegate(ContentManager_collectContentPackProviders);
		}

		private void ContentManager_collectContentPackProviders(AddContentPackProviderDelegate addContentPackProvider)
		{
			addContentPackProvider.Invoke((IContentPackProvider)(object)this);
		}

		public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
		{
			contentPack.identifier = identifier;
			contentPack.bodyPrefabs.Add(bodyPrefabs.ToArray());
			contentPack.masterPrefabs.Add(masterPrefabs.ToArray());
			contentPack.projectilePrefabs.Add(projectilePrefabs.ToArray());
			contentPack.survivorDefs.Add(survivorDefs.ToArray());
			contentPack.unlockableDefs.Add(unlockableDefs.ToArray());
			contentPack.skillDefs.Add(skillDefs.ToArray());
			contentPack.skillFamilies.Add(skillFamilies.ToArray());
			contentPack.entityStateTypes.Add(entityStates.ToArray());
			contentPack.buffDefs.Add(buffDefs.ToArray());
			contentPack.effectDefs.Add(effectDefs.ToArray());
			contentPack.networkSoundEventDefs.Add(networkSoundEventDefs.ToArray());
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args)
		{
			ContentPack.Copy(contentPack, args.output);
			args.ReportProgress(1f);
			yield break;
		}

		public IEnumerator FinalizeAsync(FinalizeAsyncArgs args)
		{
			args.ReportProgress(1f);
			yield break;
		}
	}
	internal static class ItemDisplayCheck
	{
		public static List<Object> allDisplayedItems;

		public static void PrintUnused(ItemDisplayRuleSet itemDisplayRuleSet, string bodyName = "")
		{
			PrintUnused((IEnumerable<KeyAssetRuleGroup>)itemDisplayRuleSet.keyAssetRuleGroups.ToList(), bodyName);
		}

		public static void PrintUnused(IEnumerable<KeyAssetRuleGroup> ruleSet = null, string bodyName = "")
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_003f: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			string text = "generating item displays for " + bodyName;
			if (allDisplayedItems == null)
			{
				LazyGatherAllItems();
			}
			List<Object> list = new List<Object>(allDisplayedItems);
			string text2 = "";
			if (ruleSet != null)
			{
				foreach (KeyAssetRuleGroup item in ruleSet)
				{
					if (item.displayRuleGroup.rules.Length != 0)
					{
						list.Remove(item.keyAsset);
						if (string.IsNullOrEmpty(text2))
						{
							text2 = item.displayRuleGroup.rules[0].childName;
						}
					}
				}
			}
			if (string.IsNullOrEmpty(text2))
			{
				text2 = "Chest";
			}
			foreach (Object item2 in list)
			{
				string text3 = "";
				if (ItemDisplays.KeyAssetDisplayPrefabs.ContainsKey(item2))
				{
					text3 += SpitOutNewRule(item2, text2, ItemDisplays.KeyAssetDisplayPrefabs[item2]);
				}
				else
				{
					Log.Error($"COULD NOT FIND DISPLAY PREFABS FOR KEYASSET {item2}");
				}
				text += text3;
			}
			Log.Message(text);
		}

		private static void LazyGatherAllItems()
		{
			allDisplayedItems = new List<Object>(ItemDisplays.KeyAssetDisplayPrefabs.Keys);
			allDisplayedItems.Sort(delegate(Object item1, Object item2)
			{
				if (item1 is ItemDef && item2 is ItemDef)
				{
					return item1.name.CompareTo(item2.name);
				}
				if (item1 is EquipmentDef && item2 is EquipmentDef)
				{
					return item1.name.CompareTo(item2.name);
				}
				if (item1 is ItemDef && item2 is EquipmentDef)
				{
					return -1;
				}
				return (item1 is EquipmentDef && item2 is ItemDef) ? 1 : 0;
			});
		}

		private static string SpitOutNewRule(Object asset, string firstCompatibleChild, ItemDisplayRule[] displayRules)
		{
			//IL_0031: 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)
			if (displayRules.Length == 0)
			{
				return $"\n[NO DISPLAY RULES FOUND FOR THE KEYASSET {asset}";
			}
			string text = "\n            itemDisplayRules.Add(ItemDisplays.CreateDisplayRuleGroupWithRules(ItemDisplays.KeyAssets[\"" + asset.name + "\"]";
			for (int i = 0; i < displayRules.Length; i++)
			{
				text = (((int)displayRules[i].limbMask != 0) ? (text + ",\n" + $"                ItemDisplays.CreateLimbMaskDisplayRule(LimbFlags.{displayRules[i].limbMask})") : (text + ",\n                ItemDisplays.CreateDisplayRule(ItemDisplays.LoadDisplay(\"" + ((Object)displayRules[i].followerPrefab).name + "\"),\n                    \"" + firstCompatibleChild + "\",\n                    new Vector3(2, 2, 2),\n                    new Vector3(0, 0, 0),\n                    new Vector3(1, 1, 1)\n                    )"));
			}
			return text + "\n                ));";
		}
	}
	internal static class ItemDisplays
	{
		public delegate bool BodySurface(Vector3 point, float margin, out Vector3 onSurface);

		private static Dictionary<string, GameObject> itemDisplayPrefabs = new Dictionary<string, GameObject>();

		public static Dictionary<Object, ItemDisplayRule[]> KeyAssetDisplayPrefabs = new Dictionary<Object, ItemDisplayRule[]>();

		public static Dictionary<string, Object> KeyAssets = new Dictionary<string, Object>();

		public static int queuedDisplays;

		public static bool initialized = false;

		private static readonly Dictionary<string, string[]> limbAxes = new Dictionary<string, string[]>
		{
			{
				"UpperArmL",
				new string[2] { "UpperArmL", "LowerArmL" }
			},
			{
				"LowerArmL",
				new string[2] { "LowerArmL", "HandL" }
			},
			{
				"HandL",
				new string[2] { "LowerArmL", "HandL" }
			},
			{
				"UpperArmR",
				new string[2] { "UpperArmR", "LowerArmR" }
			},
			{
				"LowerArmR",
				new string[2] { "LowerArmR", "HandR" }
			},
			{
				"HandR",
				new string[2] { "LowerArmR", "HandR" }
			},
			{
				"ThighL",
				new string[2] { "ThighL", "CalfL" }
			},
			{
				"CalfL",
				new string[2] { "CalfL", "FootL" }
			},
			{
				"FootL",
				new string[2] { "CalfL", "FootL" }
			},
			{
				"ThighR",
				new string[2] { "ThighR", "CalfR" }
			},
			{
				"CalfR",
				new string[2] { "CalfR", "FootR" }
			},
			{
				"FootR",
				new string[2] { "CalfR", "FootR" }
			}
		};

		private static BodySurface bodySurface;

		private static float itemScale = 1f;

		private static float limbThickness = 1f;

		private const float maxWornDistance = 0.6f;

		private const float surfaceMargin = 0.04f;

		private static readonly HashSet<string> torsoBones = new HashSet<string> { "Chest", "Stomach", "Pelvis" };

		public static void LazyInit()
		{
			if (!initialized)
			{
				initialized = true;
				PopulateDisplays();
			}
		}

		internal static void DisposeWhenDone()
		{
			queuedDisplays--;
			if (queuedDisplays <= 0 && initialized)
			{
				initialized = false;
				itemDisplayPrefabs = null;
				KeyAssetDisplayPrefabs = null;
				KeyAssets = null;
			}
		}

		internal static void PopulateDisplays()
		{
			PopulateFromBody("LoaderBody");
		}

		private static void PopulateFromBody(string bodyName)
		{
			//IL_00d0: 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)
			KeyAssetRuleGroup[] keyAssetRuleGroups = ((Component)LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/" + bodyName).GetComponent<ModelLocator>().modelTransform).GetComponent<CharacterModel>().itemDisplayRuleSet.keyAssetRuleGroups;
			for (int i = 0; i < keyAssetRuleGroups.Length; i++)
			{
				ItemDisplayRule[] rules = keyAssetRuleGroups[i].displayRuleGroup.rules;
				if (rules == null)
				{
					continue;
				}
				Object keyAsset = keyAssetRuleGroups[i].keyAsset;
				if (Object.op_Implicit(keyAsset))
				{
					KeyAssetDisplayPrefabs[keyAsset] = rules;
					KeyAssets[keyAsset.name] = keyAsset;
				}
				for (int j = 0; j < rules.Length; j++)
				{
					GameObject val = rules[j].followerPrefab;
					if (!Object.op_Implicit((Object)(object)val) && rules[j].followerPrefabAddress != null && ((AssetReference)rules[j].followerPrefabAddress).RuntimeKeyIsValid())
					{
						val = Addressables.LoadAssetAsync<GameObject>(((AssetReference)rules[j].followerPrefabAddress).RuntimeKey).WaitForCompletion();
					}
					if (Object.op_Implicit((Object)(object)val))
					{
						string key = ((Object)val).name?.ToLowerInvariant();
						if (!itemDisplayPrefabs.ContainsKey(key))
						{
							itemDisplayPrefabs[key] = val;
						}
					}
				}
			}
		}

		private static void PopulateCustomLightningArm()
		{
			GameObject val = PrefabAPI.InstantiateClone(itemDisplayPrefabs["displaylightningarmright"], "DisplayLightningCustom", false);
			LimbMatcher component = val.GetComponent<LimbMatcher>();
			component.limbPairs[0].targetChildLimb = "LightningArm1";
			component.limbPairs[1].targetChildLimb = "LightningArm2";
			component.limbPairs[2].targetChildLimb = "LightningArmEnd";
			itemDisplayPrefabs["displaylightningarmcustom"] = val;
		}

		public static GameObject LoadDisplay(string name)
		{
			if (itemDisplayPrefabs.ContainsKey(name.ToLowerInvariant()) && Object.op_Implicit((Object)(object)itemDisplayPrefabs[name.ToLowerInvariant()]))
			{
				return itemDisplayPrefabs[name.ToLowerInvariant()];
			}
			Log.Error("item display " + name + " returned null");
			return null;
		}

		internal static void RetargetFromReference(List<KeyAssetRuleGroup> groups, string referenceBodyName, Transform ourModel, BodySurface bodySurface = null, float itemScale = 1f, float limbThickness = 1f)
		{
			//IL_00e9: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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)
			//IL_0119: 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_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: 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_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			ItemDisplays.bodySurface = bodySurface;
			ItemDisplays.itemScale = itemScale;
			ItemDisplays.limbThickness = limbThickness;
			GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/" + referenceBodyName);
			ModelLocator val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ModelLocator>() : null);
			Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.modelTransform : null);
			CharacterModel val4 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<CharacterModel>() : null);
			ChildLocator val5 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<ChildLocator>() : null);
			ChildLocator val6 = (Object.op_Implicit((Object)(object)ourModel) ? ((Component)ourModel).GetComponent<ChildLocator>() : null);
			if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.itemDisplayRuleSet) || !Object.op_Implicit((Object)(object)val5) || !Object.op_Implicit((Object)(object)val6))
			{
				Log.Warning("ItemDisplays: couldn't set up retargeting from " + referenceBodyName + " - item displays keep their written placements.");
				return;
			}
			float num = BodySizeRatio(val5, val6);
			Dictionary<Object, ItemDisplayRule[]> dictionary = new Dictionary<Object, ItemDisplayRule[]>();
			KeyAssetRuleGroup[] keyAssetRuleGroups = val4.itemDisplayRuleSet.keyAssetRuleGroups;
			foreach (KeyAssetRuleGroup val7 in keyAssetRuleGroups)
			{
				Object val8 = val7.keyAsset;
				if (!Object.op_Implicit(val8) && val7.keyAssetAddress != null && ((AssetReference)val7.keyAssetAddress).RuntimeKeyIsValid())
				{
					val8 = (Object)(object)Addressables.LoadAssetAsync<ScriptableObject>(((AssetReference)val7.keyAssetAddress).RuntimeKey).WaitForCompletion();
				}
				if (Object.op_Implicit(val8) && val7.displayRuleGroup.rules != null)
				{
					dictionary[val8] = val7.displayRuleGroup.rules;
				}
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"# retargeted from {referenceBodyName}, size ratio {num:F3}");
			stringBuilder.AppendLine("# item | prefab | refBone -> ourBone | fallback | localPos | localAngles | localScale | dist from bone ref/ours (m)");
			int num2 = 0;
			int num3 = 0;
			for (int j = 0; j < groups.Count; j++)
			{
				KeyAssetRuleGroup val9 = groups[j];
				if (!Object.op_Implicit(val9.keyAsset) || !dictionary.TryGetValue(val9.keyAsset, out var value))
				{
					continue;
				}
				List<ItemDisplayRule> list = new List<ItemDisplayRule>();
				ItemDisplayRule[] array = value;
				foreach (ItemDisplayRule val10 in array)
				{
					if ((int)val10.ruleType == 0 && TryRetargetRule(val10, val3, val5, ourModel, val6, num, out var result))
					{
						list.Add(result);
						bool flag = result.childName != val10.childName;
						if (flag)
						{
							num2++;
						}
						Transform val11 = val5.FindChild(val10.childName);
						Transform val12 = val6.FindChild(result.childName);
						float num4 = (Object.op_Implicit((Object)(object)val11) ? Vector3.Distance(val11.position, val11.TransformPoint(val10.localPos)) : (-1f));
						float num5 = (Object.op_Implicit((Object)(object)val12) ? Vector3.Distance(val12.position, val12.TransformPoint(result.localPos)) : (-1f));
						string text = (Object.op_Implicit((Object)(object)val10.followerPrefab) ? ((Object)val10.followerPrefab).name : ((val10.followerPrefabAddress != null) ? ((AssetReference)val10.followerPrefabAddress).AssetGUID : "?"));
						stringBuilder.AppendLine(val9.keyAsset.name + " | " + text + " | " + val10.childName + " -> " + result.childName + " | " + (flag ? "FALLBACK" : "-") + " | " + string.Format("{0} | {1} | {2} | {3:F2}/{4:F2}", ((Vector3)(ref result.localPos)).ToString("F3"), ((Vector3)(ref result.localAngles)).ToString("F1"), ((Vector3)(ref result.localScale)).ToString("F3"), num4, num5));
					}
				}
				if (list.Count != 0)
				{
					val9.displayRuleGroup = new DisplayRuleGroup
					{
						rules = list.ToArray()
					};
					groups[j] = val9;
					num3++;
				}
			}
			Log.Info($"ItemDisplays: retargeted {num3}/{groups.Count} item displays from {referenceBodyName} (size ratio {num:F2}, {num2} placements fell back to Chest).");
			try
			{
				File.WriteAllText(Path.Combine(Paths.BepInExRootPath, "WatcherItemDisplays.txt"), stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				Log.Warning("ItemDisplays: couldn't write the placement dump: " + ex.Message);
			}
		}

		private static float BodySizeRatio(ChildLocator reference, ChildLocator ours)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Transform val = reference.FindChild("Head");
			Transform val2 = reference.FindChild("Pelvis");
			Transform val3 = ours.FindChild("Head");
			Transform val4 = ours.FindChild("Pelvis");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val4))
			{
				return 1f;
			}
			float num = Vector3.Distance(val.position, val2.position);
			float num2 = Vector3.Distance(val3.position, val4.position);
			if (!(num > 0.01f))
			{
				return 1f;
			}
			return num2 / num;
		}

		private static bool TryRetargetRule(ItemDisplayRule source, Transform referenceModel, ChildLocator referenceChildLocator, Transform ourModel, ChildLocator ourChildLocator, float sizeRatio, out ItemDisplayRule result)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0085: 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_008d: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: 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_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: 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_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			result = source;
			Transform val = referenceChildLocator.FindChild(source.childName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			string text = (Object.op_Implicit((Object)(object)ourChildLocator.FindChild(source.childName)) ? source.childName : "Chest");
			Transform val2 = ourChildLocator.FindChild(text);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			Transform val3 = referenceChildLocator.FindChild(text);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				val3 = val;
			}
			Vector3 val4 = val.TransformPoint(source.localPos);
			Quaternion val5 = val.rotation * Quaternion.Euler(source.localAngles);
			Vector3 val6 = Vector3.Scale(val.lossyScale, source.localScale);
			Quaternion val7 = Quaternion.Inverse(referenceModel.rotation);
			Vector3 val8 = val7 * (val4 - val3.position);
			Quaternion val9 = val7 * val5;
			Quaternion val10 = LimbSwing(text, referenceModel, referenceChildLocator, ourModel, ourChildLocator);
			val8 = val10 * val8 * sizeRatio;
			val9 = val10 * val9;
			Vector3 val11 = val2.position + ourModel.rotation * val8;
			if (bodySurface != null && torsoBones.Contains(source.childName) && Vector3.Distance(val.position, val4) < 0.6f)
			{
				Vector3 point = ourModel.InverseTransformPoint(val11);
				if (bodySurface(point, 0.04f, out var onSurface))
				{
					val11 = ourModel.TransformPoint(onSurface);
				}
			}
			if (limbThickness != 1f && limbAxes.TryGetValue(text, out var value) && Vector3.Distance(val.position, val4) < 0.6f)
			{
				Transform val12 = ourChildLocator.FindChild(value[0]);
				Transform val13 = ourChildLocator.FindChild(value[1]);
				Vector3 val14 = ((Object.op_Implicit((Object)(object)val12) && Object.op_Implicit((Object)(object)val13)) ? (val13.position - val12.position) : Vector3.zero);
				if (((Vector3)(ref val14)).sqrMagnitude > 0.0001f)
				{
					Vector3 val15 = val11 - val2.position;
					Vector3 val16 = Vector3.Project(val15, val14);
					val11 = val2.position + val16 + (val15 - val16) * limbThickness;
				}
			}
			Quaternion val17 = ourModel.rotation * val9;
			Vector3 lossyScale = val2.lossyScale;
			result.childName = text;
			result.localPos = val2.InverseTransformPoint(val11);
			Quaternion val18 = Quaternion.Inverse(val2.rotation) * val17;
			result.localAngles = ((Quaternion)(ref val18)).eulerAngles;
			float num = sizeRatio * itemScale;
			result.localScale = new Vector3(val6.x * num / lossyScale.x, val6.y * num / lossyScale.y, val6.z * num / lossyScale.z);
			return true;
		}

		private static Quaternion LimbSwing(string boneName, Transform referenceModel, ChildLocator referenceChildLocator, Transform ourModel, ChildLocator ourChildLocator)
		{
			//IL_000f: 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_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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (!limbAxes.TryGetValue(boneName, out var value))
			{
				return Quaternion.identity;
			}
			Transform val = referenceChildLocator.FindChild(value[0]);
			Transform val2 = referenceChildLocator.FindChild(value[1]);
			Transform val3 = ourChildLocator.FindChild(value[0]);
			Transform val4 = ourChildLocator.FindChild(value[1]);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val4))
			{
				return Quaternion.identity;
			}
			Vector3 val5 = Quaternion.Inverse(referenceModel.rotation) * (val2.position - val.position);
			Vector3 val6 = Quaternion.Inverse(ourModel.rotation) * (val4.position - val3.position);
			if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f || ((Vector3)(ref val6)).sqrMagnitude < 0.0001f)
			{
				return Quaternion.identity;
			}
			return Quaternion.FromToRotation(val5, val6);
		}

		public static KeyAssetRuleGroup CreateDisplayRuleGroupWithRules(string itemName, params ItemDisplayRule[] rules)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return CreateDisplayRuleGroupWithRules(GetKeyAssetFromString(itemName), rules);
		}

		public static KeyAssetRuleGroup CreateDisplayRuleGroupWithRules(Object keyAsset_, params ItemDisplayRule[] rules)
		{
			//IL_0015: 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)
			//IL_0035: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			if (keyAsset_ == (Object)null)
			{
				Log.Error("could not find keyasset");
			}
			return new KeyAssetRuleGroup
			{
				keyAsset = keyAsset_,
				displayRuleGroup = new DisplayRuleGroup
				{
					rules = rules
				}
			};
		}

		public static ItemDisplayRule CreateDisplayRule(string prefabName, string childName, Vector3 position, Vector3 rotation, Vector3 scale)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return CreateDisplayRule(LoadDisplay(prefabName), childName, position, rotation, scale);
		}

		public static ItemDisplayRule CreateDisplayRule(GameObject itemPrefab, string childName, Vector3 position, Vector3 rotation, Vector3 scale)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_002a: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			return new ItemDisplayRule
			{
				ruleType = (ItemDisplayRuleType)0,
				childName = childName,
				followerPrefab = itemPrefab,
				limbMask = (LimbFlags)0,
				localPos = position,
				localAngles = rotation,
				localScale = scale
			};
		}

		public static ItemDisplayRule CreateLimbMaskDisplayRule(LimbFlags limb)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			return new ItemDisplayRule
			{
				ruleType = (ItemDisplayRuleType)1,
				limbMask = limb,
				childName = "",
				followerPrefab = null
			};
		}

		private static Object GetKeyAssetFromString(string itemName)
		{
			Object val = (Object)(object)LegacyResourcesAPI.Load<ItemDef>("ItemDefs/" + itemName);
			if (val == (Object)null)
			{
				val = (Object)(object)LegacyResourcesAPI.Load<EquipmentDef>("EquipmentDefs/" + itemName);
			}
			if (val == (Object)null)
			{
				Log.Error("Could not load keyasset for " + itemName);
			}
			return val;
		}
	}
	internal static class Language
	{
		public static string TokensOutput = "";

		public static bool usingLanguageFolder = false;

		public static bool printingEnabled = false;

		public static void Init()
		{
			if (usingLanguageFolder)
			{
				Language.collectLanguageRootFolders += Language_collectLanguageRootFolders;
			}
		}

		private static void Language_collectLanguageRootFolders(List<string> obj)
		{
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)WatcherPlugin.instance).Info.Location), "Language");
			if (Directory.Exists(text))
			{
				obj.Add(text);
			}
		}

		public static void Add(string token, string text)
		{
			if (!usingLanguageFolder)
			{
				LanguageAPI.Add(token, text);
			}
			if (printingEnabled)
			{
				TokensOutput = TokensOutput + "\n    \"" + token + "\" : \"" + text.Replace(Environment.NewLine, "\\n").Replace("\n", "\\n") + "\",";
			}
		}

		public static void PrintOutput(string fileName = "")
		{
			if (printingEnabled)
			{
				string text = "{\n    strings:\n    {" + TokensOutput + "\n    }\n}";
				Log.Message(fileName + ": \n" + text);
				if (!string.IsNullOrEmpty(fileName))
				{
					File.WriteAllText(Path.Combine(Directory.GetParent(((BaseUnityPlugin)WatcherPlugin.instance).Info.Location).FullName, "Language", "en", fileName), text);
				}
				TokensOutput = "";
			}
		}
	}
	internal static class Materials
	{
		private static List<Material> cachedMaterials = new List<Material>();

		internal static Shader hotpoo = LegacyResourcesAPI.Load<Shader>("Shaders/Deferred/HGStandard");

		public static Material LoadMaterial(this AssetBundle assetBundle, string materialName)
		{
			return assetBundle.CreateHopooMaterialFromBundle(materialName);
		}

		public static Material CreateHopooMaterialFromBundle(this AssetBundle assetBundle, string materialName)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			Material val = cachedMaterials.Find(delegate(Material mat)
			{
				materialName.Replace(" (Instance)", "");
				return ((Object)mat).name.Contains(materialName);
			});
			if (Object.op_Implicit((Object)(object)val))
			{
				Log.Debug(((Object)val).name + " has already been loaded. returning cached");
				return val;
			}
			val = assetBundle.LoadAsset<Material>(materialName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Log.ErrorAssetBundle(materialName, ((Object)assetBundle).name);
				return new Material(hotpoo);
			}
			return val.ConvertDefaultShaderToHopoo();
		}

		public static Material SetHopooMaterial(this Material tempMat)
		{
			return tempMat.ConvertDefaultShaderToHopoo();
		}

		public static Material ConvertDefaultShaderToHopoo(this Material tempMat)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			if (cachedMaterials.Contains(tempMat))
			{
				Log.Debug(((Object)tempMat).name + " has already been converted. returning cached");
				return tempMat;
			}
			string text = ((Object)tempMat.shader).name.ToLowerInvariant();
			if (!text.StartsWith("standard") && !text.StartsWith("autodesk"))
			{
				Log.Debug(((Object)tempMat).name + " is not unity standard shader. aborting material conversion");
				return tempMat;
			}
			float? num = null;
			Color? val = null;
			if (tempMat.IsKeywordEnabled("_NORMALMAP"))
			{
				num = tempMat.GetFloat("_BumpScale");
			}
			if (tempMat.IsKeywordEnabled("_EMISSION"))
			{
				val = tempMat.GetColor("_EmissionColor");
			}
			tempMat.shader = hotpoo;
			tempMat.SetTexture("_EmTex", tempMat.GetTexture("_EmissionMap"));
			tempMat.EnableKeyword("DITHER");
			if (num.HasValue)
			{
				tempMat.SetFloat("_NormalStrength", num.Value);
				tempMat.SetTexture("_NormalTex", tempMat.GetTexture("_BumpMap"));
			}
			if (val.HasValue)
			{
				tempMat.SetColor("_EmColor", val.Value);
				tempMat.SetFloat("_EmPower", 1f);
			}
			if (tempMat.IsKeywordEnabled("NOCULL"))
			{
				tempMat.SetInt("_Cull", 0);
			}
			if (tempMat.IsKeywordEnabled("LIMBREMOVAL"))
			{
				tempMat.SetInt("_LimbRemovalOn", 1);
			}
			cachedMaterials.Add(tempMat);
			return tempMat;
		}

		public static Material MakeUnique(this Material material)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			if (cachedMaterials.Contains(material))
			{
				return new Material(material);
			}
			return material;
		}

		public static Material SetColor(this Material material, Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			material.SetColor("_Color", color);
			return material;
		}

		public static Material SetNormal(this Material material, float normalStrength = 1f)
		{
			material.SetFloat("_NormalStrength", normalStrength);
			return material;
		}

		public static Material SetEmission(this Material material)
		{
			return material.SetEmission(1f);
		}

		public static Material SetEmission(this Material material, float emission)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return material.SetEmission(emission, Color.white);
		}

		public static Material SetEmission(this Material material, float emission, Color emissionColor)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			material.SetFloat("_EmPower", emission);
			material.SetColor("_EmColor", emissionColor);
			return material;
		}

		public static Material SetCull(this Material material, bool cull = false)
		{
			material.SetInt("_Cull", cull ? 1 : 0);
			return material;
		}

		public static Material SetSpecular(this Material material, float strength)
		{
			material.SetFloat("_SpecularStrength", strength);
			return material;
		}

		public static Material SetSpecular(this Material material, float strength, float exponent)
		{
			material.SetFloat("_SpecularStrength", strength);
			material.SetFloat("SpecularExponent", exponent);
			return material;
		}
	}
	internal static class Prefabs
	{
		private static PhysicMaterial ragdollMaterial;

		public static GameObject CreateDisplayPrefab(AssetBundle assetBundle, string displayPrefabName, GameObject prefab)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(displayPrefabName);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("could not load display prefab " + displayPrefabName + ". Make sure this prefab exists in assetbundle " + ((Object)assetBundle).name);
				return null;
			}
			CharacterModel val2 = val.GetComponent<CharacterModel>();
			if (!Object.op_Implicit((Object)(object)val2))
			{
				val2 = val.AddComponent<CharacterModel>();
			}
			val2.baseRendererInfos = prefab.GetComponentInChildren<CharacterModel>().baseRendererInfos;
			Asset.ConvertAllRenderersToHopooShader(val);
			return val;
		}

		public static GameObject LoadCharacterModel(AssetBundle assetBundle, string modelName)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(modelName);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("could not load model prefab " + modelName + ". Make sure this prefab exists in assetbundle " + ((Object)assetBundle).name);
				return null;
			}
			return val;
		}

		public static GameObject LoadCharacterBody(AssetBundle assetBundle, string bodyName)
		{
			GameObject val = assetBundle.LoadAsset<GameObject>(bodyName);
			if ((Object)(object)val == (Object)null)
			{
				Log.Error("could not load body prefab " + bodyName + ". Make sure this prefab exists in assetbundle " + ((Object)assetBundle).name);
				return null;
			}
			return val;
		}

		public static GameObject CloneCharacterBody(BodyInfo bodyInfo)
		{
			GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/" + bodyInfo.bodyNameToClone + "Body");
			if (!Object.op_Implicit((Object)(object)val))
			{
				Log.Error(bodyInfo.bodyNameToClone + " Body to clone is not a valid body, character creation failed");
				return null;
			}
			GameObject val2 = PrefabAPI.InstantiateClone(val, bodyInfo.bodyName);
			for (int num = val2.transform.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)val2.transform.GetChild(num)).gameObject);
			}
			return val2;
		}

		public static GameObject CreateBodyPrefab(AssetBundle assetBundle, string modelPrefabName, BodyInfo bodyInfo)
		{
			return CreateBodyPrefab(LoadCharacterModel(assetBundle, modelPrefabName), bodyInfo);
		}

		public static GameObject CreateBodyPrefab(GameObject model, BodyInfo bodyInfo)
		{
			return CreateBodyPrefab(CloneCharacterBody(bodyInfo), model, bodyInfo);
		}

		public static GameObject CreateBodyPrefab(GameObject newBodyPrefab, AssetBundle assetBundle, string modelName, BodyInfo bodyInfo)
		{
			return CreateBodyPrefab(newBodyPrefab, LoadCharacterModel(assetBundle, modelName), bodyInfo);
		}

		public static GameObject CreateBodyPrefab(AssetBundle assetBundle, string bodyPrefabName, string modelPrefabName, BodyInfo bodyInfo)
		{
			return CreateBodyPrefab(LoadCharacterBody(assetBundle, bodyPrefabName), LoadCharacterModel(assetBundle, modelPrefabName), bodyInfo);
		}

		public static GameObject CreateBodyPrefab(GameObject newBodyPrefab, GameObject model, BodyInfo bodyInfo)
		{
			if ((Object)(object)model == (Object)null || (Object)(object)newBodyPrefab == (Object)null)
			{
				Log.Error($"Character creation failed. Model: {model}, Body: {newBodyPrefab}");
				return null;
			}
			SetupCharacterBody(newBodyPrefab, bodyInfo);
			Transform modelBaseTransform = AddCharacterModelToSurvivorBody(newBodyPrefab, model.transform, bodyInfo);
			SetupModelLocator(newBodyPrefab, modelBaseTransform, model.transform);
			SetupCharacterDirection(newBodyPrefab, modelBaseTransform, model.transform);
			SetupCameraTargetParams(newBodyPrefab, bodyInfo);
			SetupCapsuleCollider(newBodyPrefab);
			Content.AddCharacterBodyPrefab(newBodyPrefab);
			return newBodyPrefab;
		}

		private static void SetupCharacterBody(GameObject newBodyPrefab, BodyInfo bodyInfo)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody component = newBodyPrefab.GetComponent<CharacterBody>();
			component.baseNameToken = bodyInfo.bodyNameToken;
			component.subtitleNameToken = bodyInfo.subtitleNameToken;
			component.portraitIcon = bodyInfo.characterPortrait;
			component.bodyColor = bodyInfo.bodyColor;
			component._defaultCrosshairPrefab = bodyInfo.crosshair;
			component.hideCrosshair = false;
			component.preferredPodPrefab = bodyInfo.podPrefab;
			component.baseMaxHealth = bodyInfo.maxHealth;
			component.baseRegen = bodyInfo.healthRegen;
			component.baseArmor = bodyInfo.armor;
			component.baseMaxShield = bodyInfo.shield;
			component.baseDamage = bodyInfo.damage;
			component.baseAttackSpeed = bodyInfo.attackSpeed;
			component.baseCrit = bodyInfo.crit;
			component.baseMoveSpeed = bodyInfo.moveSpeed;
			component.baseJumpPower = bodyInfo.jumpPower;
			component.autoCalculateLevelStats = bodyInfo.autoCalculateLevelStats;
			if (bodyInfo.autoCalculateLevelStats)
			{
				component.levelMaxHealth = Mathf.Round(component.baseMaxHealth * 0.3f);
				component.levelMaxShield = Mathf.Round(component.baseMaxShield * 0.3f);
				component.levelRegen = component.baseRegen * 0.2f;
				component.levelMoveSpeed = 0f;
				component.levelJumpPower = 0f;
				component.levelDamage = component.baseDamage * 0.2f;
				component.levelAttackSpeed = 0f;
				component.levelCrit = 0f;
				component.levelArmor = 0f;
			}
			else
			{
				component.levelMaxHealth = bodyInfo.healthGrowth;
				component.levelMaxShield = bodyInfo.shieldGrowth;
				component.levelRegen = bodyInfo.regenGrowth;
				component.levelMoveSpeed = bodyInfo.moveSpeedGrowth;
				component.levelJumpPower = bodyInfo.jumpPowerGrowth;
				component.levelDamage = bodyInfo.damageGrowth;
				component.levelAttackSpeed = bodyInfo.attackSpeedGrowth;
				component.levelCrit = bodyInfo.critGrowth;
				component.levelArmor = bodyInfo.armorGrowth;
			}
			component.baseAcceleration = bodyInfo.acceleration;
			component.baseJumpCount = bodyInfo.jumpCount;
			component.sprintingSpeedMultiplier = 1.45f;
			component.bodyFlags = (BodyFlags)16;
			component.rootMotionInMainState = false;
			component.hullClassification = (HullClassification)0;
			component.isChampion = false;
		}

		private static Transform AddCharacterModelToSurvivorBody(GameObject bodyPrefab, Transform modelTransform, BodyInfo bodyInfo)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			Transform val = bodyPrefab.transform.Find("ModelBase");
			if ((Object)(object)val == (Object)null)
			{
				val = new GameObject("ModelBase").transform;
				val.parent = bodyPrefab.transform;
				val.localPosition = bodyInfo.modelBasePosition;
				val.localRotation = Quaternion.identity;
			}
			modelTransform.parent = ((Component)val).transform;
			modelTransform.localPosition = Vector3.zero;
			modelTransform.localRotation = Quaternion.identity;
			if ((Object)(object)bodyPrefab.transform.Find("CameraPivot") == (Object)null)
			{
				Transform transform = new GameObject("CameraPivot").transform;
				transform.parent = bodyPrefab.transform;
				transform.localPosition = bodyInfo.cameraPivotPosition;
				transform.localRotation = Quaternion.identity;
			}
			Transform val2 = bodyPrefab.transform.Find("AimOrigin");
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = new GameObject("AimOrigin").transform;
				val2.parent = bodyPrefab.transform;
				val2.localPosition = bodyInfo.aimOriginPosition;
				val2.localRotation = Quaternion.identity;
			}
			bodyPrefab.GetComponent<CharacterBody>().aimOriginTransform = val2;
			return ((Component)val).transform;
		}

		private static void SetupCharacterDirection(GameObject prefab, Transform modelBaseTransform, Transform modelTransform)
		{
			if (Object.op_Implicit((Object)(object)prefab.GetComponent<CharacterDirection>()))
			{
				CharacterDirection component = prefab.GetComponent<CharacterDirection>();
				component.targetTransform = modelBaseTransform;
				component.overrideAnimatorForwardTransform = null;
				component.rootMotionAccumulator = null;
				component.modelAnimator = ((Component)modelTransform).GetComponent<Animator>();
				component.driveFromRootRotation = false;
				component.turnSpeed = 720f;
			}
		}

		private static void SetupCameraTargetParams(GameObject prefab, BodyInfo bodyInfo)
		{
			CameraTargetParams component = prefab.GetComponent<CameraTargetParams>();
			component.cameraParams = bodyInfo.cameraParams;
			component.cameraPivotTransform = prefab.transform.Find("CameraPivot");
		}

		private static void SetupModelLocator(GameObject prefab, Transform modelBaseTransform, Transform modelTransform)
		{
			ModelLocator component = prefab.GetComponent<ModelLocator>();
			component.modelTransform = modelTransform;
			component.modelBaseTransform = modelBaseTransform;
		}

		private static void SetupCapsuleCollider(GameObject prefab)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider component = prefab.GetComponent<CapsuleCollider>();
			component.center = new Vector3(0f, 0f, 0f);
			component.radius = 0.5f;
			component.height = 1.82f;
			component.direction = 1;
		}

		public static CharacterModel SetupCharacterModel(GameObject bodyPrefab, CustomRendererInfo[] customInfos = null)
		{
			CharacterModel val = ((Component)bodyPrefab.GetComponent<ModelLocator>().modelTransform).gameObject.GetComponent<CharacterModel>();
			bool num = (Object)(object)val != (Object)null;
			if (!num)
			{
				val = ((Component)bodyPrefab.GetComponent<ModelLocator>().modelTransform).gameObject.AddComponent<CharacterModel>();
			}
			val.body = bodyPrefab.GetComponent<CharacterBody>();
			val.autoPopulateLightInfos = true;
			val.invisibilityCount = 0;
			val.temporaryOverlays = new List<TemporaryOverlayInstance>();
			if (!num)
			{
				SetupCustomRendererInfos(val, customInfos);
			}
			else
			{
				SetupPreAttachedRendererInfos(val);
			}
			SetupHurtboxGroup(bodyPrefab, ((Component)val).gameObject);
			SetupAimAnimator(bodyPrefab, ((Component)val).gameObject);
			SetupFootstepController(((Component)val).gameObject);
			SetupRagdoll(((Component)val).gameObject);
			return val;
		}

		public static void SetupPreAttachedRendererInfos(CharacterModel characterModel)
		{
			for (int i = 0; i < characterModel.baseRendererInfos.Length; i++)
			{
				if ((Object)(object)characterModel.baseRendererInfos[i].defaultMaterial == (Object)null)
				{
					characterModel.baseRendererInfos[i].defaultMaterial = characterModel.baseRendererInfos[i].renderer.sharedMaterial;
				}
				if ((Object)(object)characterModel.baseRendererInfos[i].defaultMaterial == (Object)null)
				{
					Log.Error($"no material for rendererinfo of this renderer: {characterModel.baseRendererInfos[i].renderer}");
				}
				characterModel.baseRendererInfos[i].defaultMaterial.ConvertDefaultShaderToHopoo();
			}
		}

		public static void SetupCustomRendererInfos(CharacterModel characterModel, CustomRendererInfo[] customInfos)
		{
			//IL_00ac: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			ChildLocator component = ((Component)characterModel).GetComponent<ChildLocator>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				Log.Error("Failed CharacterModel setup: ChildLocator component does not exist on the model");
				return;
			}
			List<RendererInfo> list = new List<RendererInfo>();
			for (int i = 0; i < customInfos.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)component.FindChild(customInfos[i].childName)))
				{
					Log.Error("Trying to add a RendererInfo for a renderer that does not exist: " + customInfos[i].childName);
					continue;
				}
				Renderer component2 = ((Component)component.FindChild(customInfos[i].childName)).GetComponent<Renderer>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					Material val = customInfos[i].material;
					if ((Object)(object)val == (Object)null)
					{
						val = ((!customInfos[i].dontHotpoo) ? component2.sharedMaterial.ConvertDefaultShaderToHopoo() : component2.sharedMaterial);
					}
					list.Add(new RendererInfo
					{
						renderer = component2,
						defaultMaterial = val,
						ignoreOverlays = customInfos[i].ignoreOverlays,
						defaultShadowCastingMode = (ShadowCastingMode)1
					});
				}
			}
			characterModel.baseRendererInfos = list.ToArray();
		}

		private static void SetupHurtboxGroup(GameObject bodyPrefab, GameObject model)
		{
			SetupMainHurtboxesFromChildLocator(bodyPrefab, model);
			SetHurtboxesHealthComponents(bodyPrefab);
		}

		private static void SetupMainHurtboxesFromChildLocator(GameObject bodyPrefab, GameObject model)
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bodyPrefab.GetComponent<HurtBoxGroup>() != (Object)null)
			{
				Log.Debug("Hitboxgroup already exists on model prefab. aborting code setup");
				return;
			}
			ChildLocator component = model.GetComponent<ChildLocator>();
			if (string.IsNullOrEmpty(component.FindChildNameInsensitive("MainHurtbox")))
			{
				Log.Error("Could not set up main hurtbox: make sure you have a transform pair in your prefab's ChildLocator called 'MainHurtbox'");
				return;
			}
			HurtBoxGroup val = model.AddComponent<HurtBoxGroup>();
			HurtBox val2 = null;
			GameObject val3 = component.FindChildGameObjectInsensitive("HeadHurtbox");
			if (Object.op_Implicit((Object)(object)val3))
			{
				Log.Debug("HeadHurtboxFound. Setting up");
				val2 = val3.AddComponent<HurtBox>();
				((Component)val2).gameObject.layer = LayerIndex.entityPrecise.intVal;
				val2.healthComponent = bodyPrefab.GetComponent<HealthComponent>();
				val2.isBullseye = false;
				val2.isSniperTarget = true;
				val2.damageModifier = (DamageModifier)0;
				val2.hurtBoxGroup = val;
				val2.indexInGroup = 1;
			}
			HurtBox val4 = component.FindChildGameObjectInsensitive("MainHurtbox").AddComponent<HurtBox>();
			((Component)val4).gameObject.layer = LayerIndex.entityPrecise.intVal;
			val4.healthComponent = bodyPrefab.GetComponent<HealthComponent>();
			val4.isBullseye = true;
			val4.isSniperTarget = (Object)(object)val2 == (Object)null;
			val4.damageModifier = (DamageModifier)0;
			val4.hurtBoxGroup = val;
			val4.indexInGroup = 0;
			if (Object.op_Implicit((Object)(object)val2))
			{
				val.hurtBoxes = (HurtBox[])(object)new HurtBox[2] { val4, val2 };
			}
			else
			{
				val.hurtBoxes = (HurtBox[])(object)new HurtBox[1] { val4 };
			}
			val.mainHurtBox = val4;
			val.bullseyeCount = 1;
		}

		private static string FindChildNameInsensitive(this ChildLocator childLocator, string child)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			return childLocator.transformPairs.Where((NameTransformPair pair) => pair.name.ToLowerInvariant() == child.ToLowerInvariant()).FirstOrDefault().name;
		}

		private static Transform FindChildInsensitive(this ChildLocator childLocator, string child)
		{
			return childLocator.FindChild(childLocator.FindChildNameInsensitive(child));
		}

		private static GameObject FindChildGameObjectInsensitive(this ChildLocator childLocator, string child)
		{
			return childLocator.FindChildGameObject(childLocator.FindChildNameInsensitive(child));
		}

		public static void SetHurtboxesHealthComponents(GameObject bodyPrefab)
		{
			HealthComponent component = bodyPrefab.GetComponent<HealthComponent>();
			HurtBoxGroup[] componentsInChildren = bodyPrefab.GetComponentsInChildren<HurtBoxGroup>();
			foreach (HurtBoxGroup val in componentsInChildren)
			{
				val.mainHurtBox.healthComponent = component;
				for (int j = 0; j < val.hurtBoxes.Length; j++)
				{
					val.hurtBoxes[j].healthComponent = component;
				}
			}
		}

		private static void SetupFootstepController(GameObject model)
		{
			FootstepHandler obj = model.AddComponent<FootstepHandler>();
			obj.baseFootstepString = "Play_player_footstep";
			obj.sprintFootstepOverrideString = "";
			obj.enableFootstepDust = true;
			obj.footstepDustPrefab = LegacyResourcesAPI.Load<GameObject>("Prefabs/GenericFootstepDust");
		}

		private static void SetupRagdoll(GameObject model)
		{
			RagdollController component = model.GetComponent<RagdollController>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			if ((Object)(object)ragdollMaterial == (Object)null)
			{
				ragdollMaterial = ((Component)LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterBodies/CommandoBody").GetComponentInChildren<RagdollController>().bones[1]).GetComponent<Collider>().material;
			}
			Transform[] bones = component.bones;
			foreach (Transform val in bones)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					((Component)val).gameObject.layer = LayerIndex.ragdoll.intVal;
					Collider component2 = ((Component)val).GetComponent<Collider>();
					if (Object.op_Implicit((Object)(object)component2))
					{
						component2.sharedMaterial = ragdollMaterial;
					}
					else
					{
						Log.Error($"Ragdoll bone {((Component)val).gameObject} doesn't have a collider. Ragdoll will break.");
					}
				}
			}
		}

		private static void SetupAimAnimator(GameObject prefab, GameObject model)
		{
			AimAnimator obj = model.AddComponent<AimAnimator>();
			obj.directionComponent = prefab.GetComponent<CharacterDirection>();
			obj.pitchRangeMax = 60f;
			obj.pitchRangeMin = -60f;
			obj.yawRangeMin = -80f;
			obj.yawRangeMax = 80f;
			obj.pitchGiveupRange = 30f;
			obj.yawGiveupRange = 10f;
			obj.giveupDuration = 3f;
			obj.inputBank = prefab.GetComponent<InputBankTest>();
		}

		public static void CreateGenericDoppelganger(GameObject bodyPrefab, string masterName, string masterToCopy)
		{
			CloneDopplegangerMaster(bodyPrefab, masterName, masterToCopy);
		}

		public static GameObject CloneDopplegangerMaster(GameObject bodyPrefab, string masterName, string masterToCopy)
		{
			GameObject obj = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/" + masterToCopy + "MonsterMaster"), masterName, true);
			obj.GetComponent<CharacterMaster>().bodyPrefab = bodyPrefab;
			Content.AddMasterPrefab(obj);
			return obj;
		}

		public static GameObject CreateBlankMasterPrefab(GameObject bodyPrefab, string masterName)
		{
			GameObject val = PrefabAPI.InstantiateClone(LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/CommandoMonsterMaster"), masterName, true);
			ContentPacks.masterPrefabs.Add(val);
			val.GetComponent<CharacterMaster>().bodyPrefab = bodyPrefab;
			AISkillDriver[] components = val.GetComponents<AISkillDriver>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.Destroy((Object)(object)components[i]);
			}
			return val;
		}

		public static GameObject LoadMaster(this AssetBundle assetBundle, GameObject bodyPrefab, string assetName)
		{
			//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)
			GameObject val = assetBundle.LoadAsset<GameObject>(assetName);
			BaseAI val2 = val.GetComponent<BaseAI>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.AddComponent<BaseAI>();
				val2.aimVectorDampTime = 0.1f;
				val2.aimVectorMaxSpeed = 360f;
			}
			val2.scanState = new SerializableEntityStateType(typeof(Wander));
			EntityStateMachine component = val.GetComponent<EntityStateMachine>();
			if ((Object)(object)component == (Object)null)
			{
				AddEntityStateMachine(val, "AI", typeof(Wander), typeof(Wander));
			}
			val2.stateMachine = component;
			CharacterMaster val3 = val.GetComponent<CharacterMaster>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.AddComponent<CharacterMaster>();
			}
			val3.bodyPrefab = bodyPrefab;
			val3.teamIndex = (TeamIndex)2;
			Content.AddMasterPrefab(val);
			return val;
		}

		public static void ClearEntityStateMachines(GameObject bodyPrefab)
		{
			EntityStateMachine[] components = bodyPrefab.GetComponents<EntityStateMachine>();
			for (int num = components.Length - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)components[num]);
			}
			bodyPrefab.GetComponent<NetworkStateMachine>().stateMachines = Array.Empty<EntityStateMachine>();
			CharacterDeathBehavior component = bodyPrefab.GetComponent<CharacterDeathBehavior>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.idleStateMachine = Array.Empty<EntityStateMachine>();
			}
			SetStateOnHurt component2 = bodyPrefab.GetComponent<SetStateOnHurt>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				component2.idleStateMachine = Array.Empty<EntityStateMachine>();
			}
			CharacterBody component3 = bodyPrefab.GetComponent<CharacterBody>();
			if (Object.op_Implicit((Object)(object)component3))
			{
				component3.vehicleIdleStateMachine = Array.Empty<EntityStateMachine>();
			}
		}

		public static EntityStateMachine AddEntityStateMachine(GameObject prefab, string machineName, Type mainStateType = null, Type initalStateType = null, bool addToHurt = true, bool addToDeath = true)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			EntityStateMachine val = EntityStateMachine.FindByCustomName(prefab, machineName);
			if ((Object)(object)val == (Object)null)
			{
				val = prefab.AddComponent<EntityStateMachine>();
			}
			else
			{
				Log.Message("An Entity State Machine already exists with the name " + machineName + ". replacing.");
			}
			val.customName = machineName;
			if (mainStateType == null)
			{
				mainStateType = typeof(Idle);
			}
			val.mainStateType = new SerializableEntityStateType(mainStateType);
			if (initalStateType == null)
			{
				initalStateType = typeof(Idle);
			}
			val.initialStateType = new SerializableEntityStateType(initalStateType);
			NetworkStateMachine component = prefab.GetComponent<NetworkStateMachine>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.stateMachines = component.stateMachines.Append(val).ToArray();
			}
			CharacterDeathBehavior component2 = prefab.GetComponent<CharacterDeathBehavior>();
			if (Object.op_Implicit((Object)(object)component2) && addToDeath)
			{
				component2.idleStateMachine = component2.idleStateMachine.Append(val).ToArray();
			}
			SetStateOnHurt component3 = prefab.GetComponent<SetStateOnHurt>();
			if (Object.op_Implicit((Object)(object)component3) && addToHurt)
			{
				component3.idleStateMachine = component3.idleStateMachine.Append(val).ToArray();
			}
			CharacterBody component4 = prefab.GetComponent<CharacterBody>();
			if (Object.op_Implicit((Object)(object)component4))
			{
				component4.vehicleIdleStateMachine = component4.vehicleIdleStateMachine.Append(val).ToArray();
			}
			return val;
		}

		public static EntityStateMachine AddMainEntityStateMachine(GameObject bodyPrefab, string machineName = "Body", Type mainStateType = null, Type initalStateType = null)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			EntityStateMachine val = EntityStateMachine.FindByCustomName(bodyPrefab, machineName);
			if ((Object)(object)val == (Object)null)
			{
				val = bodyPrefab.AddComponent<EntityStateMachine>();
			}
			else
			{
				Log.Message("An Entity State Machine already exists with the name " + machineName + ". replacing.");
			}
			val.customName = machineName;
			if (mainStateType == null)
			{
				mainStateType = typeof(GenericCharacterMain);
			}
			val.mainStateType = new SerializableEntityStateType(mainStateType);
			if (initalStateType == null)
			{
				initalStateType = typeof(SpawnTeleporterState);
			}
			val.initialStateType = new SerializableEntityStateType(initalStateType);
			NetworkStateMachine component = bodyPrefab.GetComponent<NetworkStateMachine>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.stateMachines = component.stateMachines.Append(val).ToArray();
			}
			CharacterDeathBehavior component2 = bodyPrefab.GetComponent<CharacterDeathBehavior>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				component2.deathStateMachine = val;
			}
			SetStateOnHurt component3 = bodyPrefab.GetComponent<SetStateOnHurt>();
			if (Object.op_Implicit((Object)(object)component3))
			{
				component3.targetStateMachine = val;
			}
			return val;
		}

		public static void SetupHitBoxGroup(GameObject modelPrefab, string hitBoxGroupName, params string[] hitboxChildNames)
		{
			ChildLocator component = modelPrefab.GetComponent<ChildLocator>();
			Transform[] array = (Transform[])(object)new Transform[hitboxChildNames.Length];
			for (int i = 0; i < hitboxChildNames.Length; i++)
			{
				array[i] = component.FindChild(hitboxChildNames[i]);
				if ((Object)(object)array[i] == (Object)null)
				{
					Log.Error("missing hitbox for " + hitboxChildNames[i]);
				}
			}
			SetupHitBoxGroup(modelPrefab, hitBoxGroupName, array);
		}

		public static void SetupHitBoxGroup(GameObject prefab, string hitBoxGroupName, params Transform[] hitBoxTransforms)
		{
			List<HitBox> list = new List<HitBox>();
			foreach (Transform val in hitBoxTransforms)
			{
				if ((Object)(object)val == (Object)null)
				{
					Log.Error("Error setting up hitboxGroup for " + hitBoxGroupName + ": hitbox transform was null");
					continue;
				}
				HitBox item = ((Component)val).gameObject.AddComponent<HitBox>();
				((Component)val).gameObject.layer = LayerIndex.projectile.intVal;
				list.Add(item);
			}
			if (list.Count == 0)
			{
				Log.Error("No hitboxes were set up. aborting setting up hitboxGroup for " + hitBoxGroupName);
				return;
			}
			HitBoxGroup obj = prefab.AddComponent<HitBoxGroup>();
			obj.hitBoxes = list.ToArray();
			obj.groupName = hitBoxGroupName;
		}
	}
	public class CustomRendererInfo
	{
		public string childName;

		public Material material;

		public bool dontHotpoo;

		public bool ignoreOverlays;
	}
	internal static class Skills
	{
		public static void CreateSkillFamilies(GameObject targetPrefab)
		{
			SkillSlot[] array = new SkillSlot[4];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			CreateSkillFamilies(targetPrefab, (SkillSlot[])(object)array);
		}

		public static void CreateSkillFamilies(GameObject targetPrefab, params SkillSlot[] slots)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			SkillLocator component = targetPrefab.GetComponent<SkillLocator>();
			foreach (SkillSlot val in slots)
			{
				switch (val - -1)
				{
				case 1:
					component.primary = CreateGenericSkillWithSkillFamily(targetPrefab, "Primary");
					break;
				case 2:
					component.secondary = CreateGenericSkillWithSkillFamily(targetPrefab, "Secondary");
					break;
				case 3:
					component.utility = CreateGenericSkillWithSkillFamily(targetPrefab, "Utility");
					break;
				case 4:
					component.special = CreateGenericSkillWithSkillFamily(targetPrefab, "Special");
					break;
				}
			}
		}

		public static void ClearGenericSkills(GameObject targetPrefab)
		{
			GenericSkill[] componentsInChildren = targetPrefab.GetComponentsInChildren<GenericSkill>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		public static GenericSkill CreateGenericSkillWithSkillFamily(GameObject targetPrefab, SkillSlot skillSlot, bool hidden = false)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected I4, but got Unknown
			SkillLocator component = targetPrefab.GetComponent<SkillLocator>();
			switch (skillSlot - -1)
			{
			case 1:
				return component.primary = CreateGenericSkillWithSkillFamily(targetPrefab, "Primary", hidden);
			case 2:
				return component.secondary = CreateGenericSkillWithSkillFamily(targetPrefab, "Secondary", hidden);
			case 3:
				return component.utility = CreateGenericSkillWithSkillFamily(targetPrefab, "Utility", hidden);
			case 4:
				return component.special = CreateGenericSkillWithSkillFamily(targetPrefab, "Special", hidden);
			case 0:
				Log.Error("Failed to create GenericSkill with skillslot None. If making a GenericSkill outside of the main 4, specify a familyName, and optionally a genericSkillName");
				return null;
			default:
				return null;
			}
		}

		public static GenericSkill CreateGenericSkillWithSkillFamily(GameObject targetPrefab, string familyName, bool hidden = false)
		{
			return CreateGenericSkillWithSkillFamily(targetPrefab, familyName, familyName, hidden);
		}

		public static GenericSkill CreateGenericSkillWithSkillFamily(GameObject targetPrefab, string genericSkillName, string familyName, bool hidden = false)
		{
			GenericSkill obj = targetPrefab.AddComponent<GenericSkill>();
			obj.skillName = genericSkillName;
			obj.hideInCharacterSelect = hidden;
			SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>();
			((Object)val).name = ((Object)targetPrefab).name + familyName + "Family";
			val.variants = (Variant[])(object)new Variant[0];
			obj._skillFamily = val;
			Content.AddSkillFamily(val);
			return obj;
		}

		public static void AddSkillToFamily(SkillFamily skillFamily, SkillDef skillDef, UnlockableDef unlockableDef = null)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Array.Resize(ref skillFamily.variants, skillFamily.variants.Length + 1);
			Variant[] variants = skillFamily.variants;
			int num = skillFamily.variants.Length - 1;
			Variant val = new Variant
			{
				skillDef = skillDef,
				unlockableDef = unlockableDef
			};
			((Variant)(ref val)).viewableNode = new Node(skillDef.skillNameToken, false, (Node)null);
			variants[num] = val;
		}

		public static void AddSkillsToFamily(SkillFamily skillFamily, params SkillDef[] skillDefs)
		{
			foreach (SkillDef skillDef in skillDefs)
			{
				AddSkillToFamily(skillFamily, skillDef);
			}
		}

		public static void AddPrimarySkills(GameObject targetPrefab, params SkillDef[] skillDefs)
		{
			AddSkillsToFamily(targetPrefab.GetComponent<SkillLocator>().primary.skillFamily, skillDefs);
		}

		public static void AddSecondarySkills(GameObject targetPrefab, params SkillDef[] skillDefs)
		{
			AddSkillsToFamily(targetPrefab.GetComponent<SkillLocator>().secondary.skillFamily, skillDefs);
		}

		public static void AddUtilitySkills(GameObject targetPrefab, params SkillDef[] skillDefs)
		{
			AddSkillsToFamily(targetPrefab.GetComponent<SkillLocator>().utility.skillFamily, skillDefs);
		}

		public static void AddSpecialSkills(GameObject targetPrefab, params SkillDef[] skillDefs)
		{
			AddSkillsToFamily(targetPrefab.GetComponent<SkillLocator>().special.skillFamily, skillDefs);
		}

		public static void AddUnlockablesToFamily(SkillFamily skillFamily, params UnlockableDef[] unlockableDefs)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			for (int i = 0; i < unlockableDefs.Length; i++)
			{
				Variant val = skillFamily.variants[i];
				val.unlockableDef = unlockableDefs[i];
				skillFamily.variants[i] = val;
			}
		}

		public static SkillDef CreateSkillDef(SkillDefInfo skillDefInfo)
		{
			return Skills.CreateSkillDef<SkillDef>(skillDefInfo);
		}

		public static T CreateSkillDef<T>(SkillDefInfo skillDefInfo) where T : SkillDef
		{
			//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_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)
			T val = ScriptableObject.CreateInstance<T>();
			((SkillDef)val).skillName = skillDefInfo.skillName;
			((Object)(object)val).name = skillDefInfo.skillName;
			((SkillDef)val).skillNameToken = skillDefInfo.skillNameToken;
			((SkillDef)val).skillDescriptionToken = skillDefInfo.skillDescriptionToken;
			((SkillDef)val).icon = skillDefInfo.skillIcon;
			((SkillDef)val).activationState = skillDefInfo.activationState;
			((SkillDef)val).activationStateMachineName = skillDefInfo.activationStateMachineName;
			((SkillDef)val).interruptPriority = skillDefInfo.interruptPriority;
			((SkillDef)val).baseMaxStock = skillDefInfo.baseMaxStock;
			((SkillDef)val).baseRechargeInterval = skillDefInfo.baseRechargeInterval;
			((SkillDef)val).rechargeStock = skillDefInfo.rechargeStock;
			((SkillDef)val).requiredStock = skillDefInfo.requiredStock;
			((SkillDef)val).stockToConsume = skillDefInfo.stockToConsume;
			((SkillDef)val).dontAllowPastMaxStocks = skillDefInfo.dontAllowPastMaxStocks;
			((SkillDef)val).beginSkillCooldownOnSkillEnd = skillDefInfo.beginSkillCooldownOnSkillEnd;
			((SkillDef)val).canceledFromSprinting = skillDefInfo.canceledFromSprinting;
			((SkillDef)val).forceSprintDuringState = skillDefInfo.forceSprintDuringState;
			((SkillDef)val).fullRestockOnAssign = skillDefInfo.fullRestockOnAssign;
			((SkillDef)val).resetCooldownTimerOnUse = skillDefInfo.resetCooldownTimerOnUse;
			((SkillDef)val).isCombatSkill = skillDefInfo.isCombatSkill;
			((SkillDef)val).mustKeyPress = skillDefInfo.mustKeyPress;
			((SkillDef)val).cancelSprintingOnActivation = skillDefInfo.cancelSprintingOnActivation;
			((SkillDef)val).keywordTokens = skillDefInfo.keywordTokens;
			Content.AddSkillDef((SkillDef)(object)val);
			return val;
		}
	}
	internal class SkillDefInfo
	{
		public string skillName;

		public string skillNameToken;

		public string skillDescriptionToken;

		public string[] keywordTokens = Array.Empty<string>();

		public Sprite skillIcon;

		public SerializableEntityStateType activationState;

		public string activationStateMachineName;

		public InterruptPriority interruptPriority;

		public float baseRechargeInterval;

		public int baseMaxStock = 1;

		public int rechargeStock = 1;

		public int requiredStock = 1;

		public int stockToConsume = 1;

		public bool resetCooldownTimerOnUse;

		public bool fullRestockOnAssign = true;

		public bool dontAllowPastMaxStocks;

		public bool beginSkillCooldownOnSkillEnd;

		public bool mustKeyPress;

		public bool isCombatSkill = true;

		public bool canceledFromSprinting;

		public bool cancelSprintingOnActivation = true;

		public bool forceSprintDuringState;

		public SkillDefInfo()
		{
		}

		public SkillDefInfo(string skillName, string skillNameToken, string skillDescriptionToken, Sprite skillIcon, SerializableEntityStateType activationState, string activationStateMachineName = "Weapon", bool agile = false)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			this.skillName = skillName;
			this.skillNameToken = skillNameToken;
			this.skillDescriptionToken = skillDescriptionToken;
			this.skillIcon = skillIcon;
			this.activationState = activationState;
			this.activationStateMachineName = activationStateMachineName;
			cancelSprintingOnActivation = !agile;
			if (agile)
			{
				keywordTokens = new string[1] { "KEYWORD_AGILE" };
			}
			interruptPriority = (InterruptPriority)0;
			isCombatSkill = true;
			baseRechargeInterval = 0f;
			requiredStock = 0;
			stockToConsume = 0;
		}
	}
	internal static class Skins
	{
		internal struct SkinDefInfo
		{
			internal SkinDef[] BaseSkins;

			internal Sprite Icon;

			internal string NameToken;

			internal UnlockableDef UnlockableDef;

			internal GameObject RootObject;

			internal RendererInfo[] RendererInfos;

			internal MeshReplacement[] MeshReplacements;

			internal GameObjectActivation[] GameObjectActivations;

			internal ProjectileGhostReplacement[] ProjectileGhostReplacements;

			internal MinionSkinReplacement[] MinionSkinReplacements;

			internal string Name;
		}

		internal static SkinDef CreateSkinDef(string skinName, Sprite skinIcon, RendererInfo[] defaultRendererInfos, GameObject root, UnlockableDef unlockableDef = null)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			SkinDefInfo skinDefInfo = new SkinDefInfo
			{
				BaseSkins = Array.Empty<SkinDef>(),
				GameObjectActivations = (GameObjectActivation[])(object)new GameObjectActivation[0],
				Icon = skinIcon,
				MeshReplacements = (MeshReplacement[])(object)new MeshReplacement[0],
				MinionSkinReplacements = (MinionSkinReplacement[])(object)new MinionSkinReplacement[0],
				Name = skinName,
				NameToken = skinName,
				ProjectileGhostReplacements = (ProjectileGhostReplacement[])(object)new ProjectileGhostReplacement[0],
				RendererInfos = (RendererInfo[])(object)new RendererInfo[defaultRendererInfos.Length],
				RootObject = root,
				UnlockableDef = unlockableDef
			};
			SkinDef.Awake += new hook_Awake(DoNothing);
			SkinDef obj = ScriptableObject.CreateInstance<SkinDef>();
			obj.baseSkins = skinDefInfo.BaseSkins;
			obj.icon = skinDefInfo.Icon;
			obj.unlockableDef = skinDefInfo.UnlockableDef;
			obj.rootObject = skinDefInfo.RootObject;
			defaultRendererInfos.CopyTo(skinDefInfo.RendererInfos, 0);
			obj.rendererInfos = skinDefInfo.RendererInfos;
			obj.gameObjectActivations = skinDefInfo.GameObjectActivations;
			obj.meshReplacements = skinDefInfo.MeshReplacements;
			obj.projectileGhostReplacements = skinDefInfo.ProjectileGhostReplacements;
			obj.minionSkinReplacements = skinDefInfo.MinionSkinReplacements;
			obj.nameToken = skinDefInfo.NameToken;
			((Object)obj).name = skinDefInfo.Name;
			SkinDef.Awake -= new hook_Awake(DoNothing);
			return obj;
		}

		private static void DoNothing(orig_Awake orig, SkinDef self)
		{
		}

		private static Rend