Decompiled source of SnowLeopardEngineer v2.0.1

SnowLeopardEngineer.dll

Decompiled 4 days 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.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Engi.EngiBubbleShield;
using EntityStates.Engi.Mine;
using EntityStates.Engi.SpiderMine;
using EntityStates.EngiTurret.EngiTurretWeapon;
using MonoMod.RuntimeDetour;
using MonoMod.RuntimeDetour.HookGen;
using RoR2;
using RoR2.ContentManagement;
using RuneFoxMods.DynamicSkins;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace SnowLeopardEngineer
{
	[BepInPlugin("com.AvaCat.SnowLeopardEngineer", "SnowLeopardEngineer", "1.0.0")]
	public class SnowLeopardEngineerPlugin : BaseUnityPlugin
	{
		private class BlueEffectsProvider : IContentPackProvider
		{
			private readonly ContentPack contentPack = new ContentPack();

			public string identifier => "com.AvaCat.SnowLeopardEngineer.Effects";

			public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args)
			{
				try
				{
					contentPack.identifier = identifier;
					blueMuzzleflash = CreateBlueEffect("MuzzleflashEngiTurret");
					blueTracer = CreateBlueEffect("TracerEngiTurret");
					blueImpact = CreateBlueEffect("ImpactEngiTurret");
					blueLaser = CreateBlueEffect("LaserEngiTurret");
					List<GameObject> projectileEffects = new List<GameObject>();
					string[] array = new string[10] { "EngiGrenadeExplosion", "EngiMineExplosion", "BubbleShieldEndEffect", "EngiHarpoonExplosion", "ChargeLaserCutter", "LaserCutterBeamLarge", "LaserCutterBeamMedium", "LaserCutterBeamSmall", "LaserCutterHitVFX", "LaserCutterLightningVFX" };
					foreach (string vanillaName in array)
					{
						tintWhites = vanillaName == "BubbleShieldEndEffect" || vanillaName.Contains("LaserCutter");
						GameObject blue;
						try
						{
							blue = CreateBlueEffect(vanillaName);
						}
						finally
						{
							tintWhites = false;
						}
						if (Object.op_Implicit((Object)(object)blue))
						{
							blueEffectsByName[vanillaName] = blue;
							projectileEffects.Add(blue);
							blue = null;
						}
					}
					blueMineExplosion = (blueEffectsByName.ContainsKey("EngiMineExplosion") ? blueEffectsByName["EngiMineExplosion"] : null);
					List<EffectDef> defs = new List<EffectDef>();
					List<GameObject> allEffects = new List<GameObject> { blueMuzzleflash, blueTracer, blueImpact, blueLaser };
					allEffects.AddRange(projectileEffects);
					foreach (GameObject prefab in allEffects)
					{
						if (Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponent("EffectComponent")))
						{
							defs.Add(new EffectDef(prefab));
						}
					}
					contentPack.effectDefs.Add(defs.ToArray());
					ManualLogSource instanceLogger = InstanceLogger;
					if (instanceLogger != null)
					{
						instanceLogger.LogInfo((object)$"[BlueFx] registered {defs.Count} blue turret effects");
					}
				}
				catch (Exception ex)
				{
					Exception e = ex;
					ManualLogSource instanceLogger2 = InstanceLogger;
					if (instanceLogger2 != null)
					{
						instanceLogger2.LogWarning((object)"[BlueFx] failed to create blue turret effects, turrets will keep default effects");
					}
					ManualLogSource instanceLogger3 = InstanceLogger;
					if (instanceLogger3 != null)
					{
						instanceLogger3.LogError((object)e);
					}
					blueMuzzleflash = (blueTracer = (blueImpact = null));
				}
				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;
			}
		}

		public class DynamicSkinExtension
		{
			private Modification SnepHairrootModification;

			private Modification SnepTailBaseModification;

			private Modification SnepArm1_LModification;

			private Modification SnepArm1_RModification;

			internal void BeforeStart()
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				_DynamicSkinManager.InstanceLogger = ((BaseUnityPlugin)Instance).Logger;
				new Hook((MethodBase)typeof(SkinDef).GetMethod("Apply"), (Delegate)new Action<Action<SkinDef, GameObject>, SkinDef, GameObject>(_DynamicSkinManager.SkinDefApply)).Apply();
			}

			internal void AfterStart()
			{
				InitializeModifications();
				InitializeDynamicBones();
				AddModificationsToList();
			}

			internal void BeforeBodyCatalogInit()
			{
				EngiBodySnepSkinAddedEvent += onSkinAdded;
			}

			internal void AfterBodyCatalogInit()
			{
			}

			private void InitializeModifications()
			{
				SnepHairrootModification = new Modification("Hairroot.prefab", "chest", "EngiBody", "AVACAT_SKIN_SNEP_NAME", 64, AffectsBaseModel: true, assetBundle);
				SnepTailBaseModification = new Modification("TailBase.prefab", "stomach", "EngiBody", "AVACAT_SKIN_SNEP_NAME", 186, AffectsBaseModel: true, assetBundle);
				SnepArm1_LModification = new Modification("Arm1_L.prefab", "chest", "EngiBody", "AVACAT_SKIN_SNEP_NAME", 182, AffectsBaseModel: true, assetBundle);
				SnepArm1_RModification = new Modification("Arm1_R.prefab", "chest", "EngiBody", "AVACAT_SKIN_SNEP_NAME", 184, AffectsBaseModel: true, assetBundle);
			}

			private void InitializeDynamicBones()
			{
				//IL_003e: 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_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: 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_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_016d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Unknown result type (might be due to invalid IL or missing references)
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_021d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0231: Unknown result type (might be due to invalid IL or missing references)
				//IL_0245: Unknown result type (might be due to invalid IL or missing references)
				//IL_0265: Unknown result type (might be due to invalid IL or missing references)
				SnepHairrootModification.dynamicBoneData = new DynamicBoneData("Hairroot", 0.39f, null, 0.1f, null, 0.39f, null, 0f, null, 0.03f, null, 0f, new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new List<DynamicBoneColliderData>
				{
					new DynamicBoneColliderData("chest", (Direction)1, new Vector3(0f, 0f, 0f), (Bound)0, 0.2f, 1.2f)
				}, new List<string>(), (FreezeAxis)0);
				SnepTailBaseModification.dynamicBoneData = new DynamicBoneData("TailSegment1", 0.1f, null, 0.1f, null, 0.1f, null, 0f, null, 0f, null, 0f, new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new List<DynamicBoneColliderData>(), new List<string>(), (FreezeAxis)0);
				SnepArm1_LModification.dynamicBoneData = new DynamicBoneData("Arm1_L", 0.8f, null, 0.1f, null, 0.75f, null, 0f, null, 0.08f, null, 0f, new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new List<DynamicBoneColliderData>
				{
					new DynamicBoneColliderData("chest", (Direction)1, new Vector3(0f, 0f, 0f), (Bound)0, 0.2f, 1.2f)
				}, new List<string>(), (FreezeAxis)0);
				SnepArm1_RModification.dynamicBoneData = new DynamicBoneData("Arm1_R", 0.8f, null, 0.1f, null, 0.75f, null, 0f, null, 0.08f, null, 0f, new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new Vector3(0f, 0f, 0f), new List<DynamicBoneColliderData>
				{
					new DynamicBoneColliderData("chest", (Direction)1, new Vector3(0f, 0f, 0f), (Bound)0, 0.2f, 1.2f)
				}, new List<string>(), (FreezeAxis)0);
			}

			private void AddModificationsToList()
			{
				_DynamicSkinManager.AddModification("AVACAT_SKIN_SNEP_NAME", 64, SnepHairrootModification);
				_DynamicSkinManager.AddModification("AVACAT_SKIN_SNEP_NAME", 186, SnepTailBaseModification);
				_DynamicSkinManager.AddModification("AVACAT_SKIN_SNEP_NAME", 182, SnepArm1_LModification);
				_DynamicSkinManager.AddModification("AVACAT_SKIN_SNEP_NAME", 184, SnepArm1_RModification);
			}

			private static void onSkinAdded(object sender, SkinAddedArgs e)
			{
				_DynamicSkinManager.AddSkinDef(e.skinDef);
			}
		}

		public delegate void VoidDelegate();

		public class SkinAddedArgs : EventArgs
		{
			public SkinDef skinDef { get; }

			public GameObject bodyPrefab { get; }

			public SkinAddedArgs(SkinDef newSkinDef, GameObject newGameObject)
			{
				skinDef = newSkinDef;
				bodyPrefab = newGameObject;
			}
		}

		private class FieldException : Exception
		{
			public FieldException(string message, Exception innerException)
				: base(message, innerException)
			{
			}
		}

		private class SnowLeopardProjectile : MonoBehaviour
		{
			private int framesLeft = 120;

			private void Update()
			{
				GameObject projectileOwner = GetProjectileOwner(((Component)this).gameObject);
				if (!Object.op_Implicit((Object)(object)projectileOwner))
				{
					if (--framesLeft <= 0)
					{
						((Behaviour)this).enabled = false;
					}
					return;
				}
				((Behaviour)this).enabled = false;
				if (IsSnepOwner(projectileOwner))
				{
					ApplyProjectileLook(((Component)this).gameObject);
				}
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static CollectContentPackProvidersDelegate <>9__12_0;

			public static Func<SkinDef, bool> <>9__47_0;

			public static Func<SkinDef, bool> <>9__77_8;

			public static Func<SkinDef, bool> <>9__90_0;

			public static Func<MeshFilter, bool> <>9__97_0;

			public static Func<MeshFilter, float> <>9__97_1;

			public static Func<NameTransformPair, bool> <>9__115_0;

			public static Func<SkinDef, bool> <>9__119_0;

			internal void <Awake>b__12_0(AddContentPackProviderDelegate addProvider)
			{
				addProvider.Invoke((IContentPackProvider)(object)blueEffectsProvider);
			}

			internal bool <AddBlueJets>b__47_0(SkinDef s)
			{
				return ((Object)s).name == "Snep";
			}

			internal bool <AddEngiBodySnepSkin>b__77_8(SkinDef s)
			{
				return ((Object)s).name == "CrystalTurret";
			}

			internal bool <AddEngiProjectileGhosts>b__90_0(SkinDef s)
			{
				return ((Object)s).name == "Snep";
			}

			internal bool <ReplaceMeshesWithStars>b__97_0(MeshFilter f)
			{
				return Object.op_Implicit((Object)(object)f.sharedMesh);
			}

			internal float <ReplaceMeshesWithStars>b__97_1(MeshFilter f)
			{
				//IL_0006: 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_000e: 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)
				Bounds bounds = f.sharedMesh.bounds;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				return ((Vector3)(ref extents)).magnitude;
			}

			internal bool <CacheCrystalMuzzle>b__115_0(NameTransformPair p)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return p.name.IndexOf("Muzzle", StringComparison.OrdinalIgnoreCase) >= 0;
			}

			internal bool <LinkSnepToWalkerSkin>b__119_0(SkinDef s)
			{
				return ((Object)s).name == "Snep";
			}
		}

		private const string EffectsFolder = "RoR2/Base/Characters/Engi/EngiTurret/Skills/";

		private const float BlueHue = 0.58f;

		private static readonly BlueEffectsProvider blueEffectsProvider = new BlueEffectsProvider();

		private static readonly ConditionalWeakTable<FireGauss, object> snepGaussStates = new ConditionalWeakTable<FireGauss, object>();

		private static readonly MethodInfo findCurrentSkinDef = typeof(SkinCatalog).GetMethod("FindCurrentSkinDefForBodyInstance", BindingFlags.Static | BindingFlags.Public);

		private static GameObject blueMuzzleflash;

		private static GameObject blueTracer;

		private static GameObject blueImpact;

		private static GameObject blueLaser;

		private static GameObject blueMineExplosion;

		private static GameObject effectRoot;

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

		private static bool tintWhites;

		private static readonly Dictionary<Texture, Texture2D> shiftedTextures = new Dictionary<Texture, Texture2D>();

		private static readonly Dictionary<Texture, Texture2D> shiftedTexturesTintedWhites = new Dictionary<Texture, Texture2D>();

		private static DynamicSkinExtension _DynamicSkinExtension = new DynamicSkinExtension();

		private static DynamicSkinManager _DynamicSkinManager = new DynamicSkinManager();

		private static VoidDelegate BeforeStartDelegate;

		private static VoidDelegate AfterStartDelegate;

		private static VoidDelegate BeforeBodyCatalogDelegate;

		private static VoidDelegate AfterBodyCatalogDelegate;

		private static readonly ConditionalWeakTable<object, object> laserStateOwners = new ConditionalWeakTable<object, object>();

		private static readonly HashSet<string> loggedLaserEffects = new HashSet<string>();

		private static AssetBundle assetBundle;

		private static readonly List<Material> materialsWithRoRShader = new List<Material>();

		private static readonly Color crystalMainAverage = new Color(0.308f, 0.39f, 0.485f, 1f);

		private static readonly Color crystalEmissionAverage = new Color(0f, 0.082f, 0.177f, 1f);

		private static readonly Color crystalGlowColor = new Color(0f, 0.42f, 0.91f, 1f);

		private const float CrystalGlowPower = 2.6f;

		private static Texture2D crystalMainFlat;

		private static Texture2D crystalEmissionFlat;

		private const int StarPoints = 5;

		private const float StarInnerRatio = 0.55f;

		private const float StarPointiness = 1.6f;

		private const float StarThickness = 0.55f;

		private static readonly Dictionary<Material, Material> projectileMaterialCache = new Dictionary<Material, Material>();

		private static readonly ConditionalWeakTable<Deployed, object> snepShieldStates = new ConditionalWeakTable<Deployed, object>();

		private const string CrystalMuzzleName = "MuzzleCrystal";

		private static readonly Vector3 walkerMuzzleOffset = Vector3.zero;

		private static Transform crystalMuzzleReference;

		internal static SnowLeopardEngineerPlugin Instance { get; private set; }

		internal static ManualLogSource InstanceLogger
		{
			get
			{
				SnowLeopardEngineerPlugin instance = Instance;
				return (instance != null) ? ((BaseUnityPlugin)instance).Logger : null;
			}
		}

		private static event EventHandler<SkinAddedArgs> EngiBodySnepSkinAddedEvent;

		private static event EventHandler<SkinAddedArgs> EngiTurretBodyCrystalTurretSkinAddedEvent;

		private void Awake()
		{
			//IL_001c: 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_0027: Expected O, but got Unknown
			Instance = this;
			object obj = <>c.<>9__12_0;
			if (obj == null)
			{
				CollectContentPackProvidersDelegate val = delegate(AddContentPackProviderDelegate addProvider)
				{
					addProvider.Invoke((IContentPackProvider)(object)blueEffectsProvider);
				};
				<>c.<>9__12_0 = val;
				obj = (object)val;
			}
			ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj;
			HookEndpointManager.Add((MethodBase)typeof(FireGauss).GetMethod("OnEnter", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<FireGauss>, FireGauss>(FireGaussOnEnter));
			HookEndpointManager.Add((MethodBase)typeof(FireGauss).GetMethod("FixedUpdate", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<FireGauss>, FireGauss>(FireGaussFixedUpdate));
			HookEndpointManager.Add((MethodBase)typeof(FireBeam).GetMethod("OnEnter", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<FireBeam>, FireBeam>(FireBeamOnEnter));
			HookEndpointManager.Add((MethodBase)typeof(Detonate).GetMethod("OnEnter", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<Detonate>, Detonate>(MineDetonateOnEnter));
			HookEndpointManager.Add((MethodBase)typeof(Detonate).GetMethod("OnEnter", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<Detonate>, Detonate>(SpiderMineDetonateOnEnter));
			Type typeFromHandle = typeof(Deployed);
			HookEndpointManager.Add((MethodBase)typeFromHandle.GetMethod("OnEnter", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<Deployed>, Deployed>(ShieldDeployedOnEnter));
			HookEndpointManager.Add((MethodBase)typeFromHandle.GetMethod("FixedUpdate", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<Deployed>, Deployed>(ShieldDeployedUpdate));
			HookEndpointManager.Add((MethodBase)typeFromHandle.GetMethod("OnExit", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<Action<Deployed>, Deployed>(ShieldDeployedUpdate));
			HookLaserCutterStates();
			AfterBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(AfterBodyCatalogDelegate, new VoidDelegate(AddWalkerTurretSkin));
			AfterBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(AfterBodyCatalogDelegate, new VoidDelegate(AddEngiProjectileGhosts));
			AfterBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(AfterBodyCatalogDelegate, new VoidDelegate(AddBlueJets));
			AfterBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(AfterBodyCatalogDelegate, new VoidDelegate(CacheCrystalMuzzle));
		}

		private static void FireGaussOnEnter(Action<FireGauss> orig, FireGauss self)
		{
			if (IsSnepTurret(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null))
			{
				snepGaussStates.Remove(self);
				snepGaussStates.Add(self, new object());
			}
			RunWithBlueEffects(orig, self);
		}

		private static void FireGaussFixedUpdate(Action<FireGauss> orig, FireGauss self)
		{
			RunWithBlueEffects(orig, self);
		}

		private static void RunWithBlueEffects(Action<FireGauss> orig, FireGauss self)
		{
			if (!Object.op_Implicit((Object)(object)blueTracer) || !snepGaussStates.TryGetValue(self, out var _))
			{
				orig(self);
				return;
			}
			GameObject effectPrefab = FireGauss.effectPrefab;
			GameObject hitEffectPrefab = FireGauss.hitEffectPrefab;
			GameObject tracerEffectPrefab = FireGauss.tracerEffectPrefab;
			try
			{
				if (Object.op_Implicit((Object)(object)blueMuzzleflash))
				{
					FireGauss.effectPrefab = blueMuzzleflash;
				}
				if (Object.op_Implicit((Object)(object)blueImpact))
				{
					FireGauss.hitEffectPrefab = blueImpact;
				}
				FireGauss.tracerEffectPrefab = blueTracer;
				orig(self);
			}
			finally
			{
				FireGauss.effectPrefab = effectPrefab;
				FireGauss.hitEffectPrefab = hitEffectPrefab;
				FireGauss.tracerEffectPrefab = tracerEffectPrefab;
			}
		}

		private static void FireBeamOnEnter(Action<FireBeam> orig, FireBeam self)
		{
			try
			{
				if (IsSnepTurret(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null))
				{
					ApplyCrystalMuzzle(self);
				}
				if (Object.op_Implicit((Object)(object)blueLaser) && IsSnepTurret(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null))
				{
					FieldInfo field = typeof(FireBeam).GetField("effectPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo field2 = typeof(FireBeam).GetField("hitEffectPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo field3 = typeof(FireBeam).GetField("laserPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (Object.op_Implicit((Object)(object)blueMuzzleflash) && NameStartsWith(field.GetValue(self), "MuzzleflashEngiTurret"))
					{
						field.SetValue(self, blueMuzzleflash);
					}
					if (Object.op_Implicit((Object)(object)blueImpact) && NameStartsWith(field2.GetValue(self), "ImpactEngiTurret"))
					{
						field2.SetValue(self, blueImpact);
					}
					field3.SetValue(self, blueLaser);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource instanceLogger = InstanceLogger;
				if (instanceLogger != null)
				{
					instanceLogger.LogWarning((object)("[BlueFx] couldn't swap beam effects: " + ex.Message));
				}
			}
			orig(self);
		}

		private static bool NameStartsWith(object prefab, string name)
		{
			GameObject val = (GameObject)((prefab is GameObject) ? prefab : null);
			return Object.op_Implicit((Object)(object)val) && ((Object)val).name.StartsWith(name, StringComparison.OrdinalIgnoreCase);
		}

		private static bool IsSnepTurret(GameObject bodyObject)
		{
			if (!Object.op_Implicit((Object)(object)bodyObject) || findCurrentSkinDef == null)
			{
				return false;
			}
			try
			{
				object? obj = findCurrentSkinDef.Invoke(null, new object[1] { bodyObject });
				SkinDef val = (SkinDef)((obj is SkinDef) ? obj : null);
				return Object.op_Implicit((Object)(object)val) && (((Object)val).name == "CrystalTurret" || ((Object)val).name == "CrystalWalkerTurret");
			}
			catch (Exception ex)
			{
				ManualLogSource instanceLogger = InstanceLogger;
				if (instanceLogger != null)
				{
					instanceLogger.LogWarning((object)("Couldn't read turret skin: " + ex.Message));
				}
				return false;
			}
		}

		private static GameObject LoadEffectPrefab(string effectName)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string> { "RoR2/Base/Characters/Engi/EngiTurret/Skills/" + effectName + ".prefab" };
			string value = "/" + effectName + ".prefab";
			List<string> list2 = new List<string>();
			foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
			{
				foreach (object key in resourceLocator.Keys)
				{
					if (key is string text)
					{
						if (text.EndsWith(value, StringComparison.OrdinalIgnoreCase) && !list.Contains(text))
						{
							list.Add(text);
						}
						else if (list2.Count < 25 && text.IndexOf("EngiTurret", StringComparison.OrdinalIgnoreCase) >= 0 && text.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
						{
							list2.Add(text);
						}
					}
				}
			}
			foreach (string item in list)
			{
				try
				{
					GameObject val = Addressables.LoadAssetAsync<GameObject>((object)item).WaitForCompletion();
					if (Object.op_Implicit((Object)(object)val))
					{
						return val;
					}
				}
				catch (Exception)
				{
				}
			}
			ManualLogSource instanceLogger = InstanceLogger;
			if (instanceLogger != null)
			{
				instanceLogger.LogWarning((object)("[BlueFx] tried " + string.Join(", ", list.ToArray()) + "; other EngiTurret prefab keys: " + string.Join(", ", list2.ToArray())));
			}
			return null;
		}

		private static GameObject CreateBlueEffect(string effectName)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			GameObject val = LoadEffectPrefab(effectName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				ManualLogSource instanceLogger = InstanceLogger;
				if (instanceLogger != null)
				{
					instanceLogger.LogWarning((object)("[BlueFx] couldn't load " + effectName));
				}
				return null;
			}
			if (!Object.op_Implicit((Object)(object)effectRoot))
			{
				effectRoot = new GameObject("SnowLeopardEngineerEffects");
				effectRoot.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)effectRoot);
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, effectRoot.transform);
			((Object)val2).name = effectName + "SnowLeopard";
			RecolorBlue(val2);
			return val2;
		}

		private static void RecolorBlue(GameObject root)
		{
			RecolorBlue(root, new Dictionary<Material, Material>());
		}

		private static void RecolorBlue(GameObject root, Dictionary<Material, Material> materialCache)
		{
			//IL_00d8: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)sharedMaterials[j]))
					{
						sharedMaterials[j] = BlueMaterial(sharedMaterials[j], materialCache);
					}
				}
				val.sharedMaterials = sharedMaterials;
				LineRenderer val2;
				TrailRenderer val3;
				if ((val2 = (LineRenderer)(object)((val is LineRenderer) ? val : null)) != null)
				{
					val2.colorGradient = ShiftGradient(val2.colorGradient);
				}
				else if ((val3 = (TrailRenderer)(object)((val is TrailRenderer) ? val : null)) != null)
				{
					val3.colorGradient = ShiftGradient(val3.colorGradient);
				}
			}
			ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val4 in componentsInChildren2)
			{
				MainModule main = val4.main;
				((MainModule)(ref main)).startColor = ShiftMinMax(((MainModule)(ref main)).startColor);
				ColorOverLifetimeModule colorOverLifetime = val4.colorOverLifetime;
				if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled)
				{
					((ColorOverLifetimeModule)(ref colorOverLifetime)).color = ShiftMinMax(((ColorOverLifetimeModule)(ref colorOverLifetime)).color);
				}
				TrailModule trails = val4.trails;
				if (((TrailModule)(ref trails)).enabled)
				{
					((TrailModule)(ref trails)).colorOverLifetime = ShiftMinMax(((TrailModule)(ref trails)).colorOverLifetime);
					((TrailModule)(ref trails)).colorOverTrail = ShiftMinMax(((TrailModule)(ref trails)).colorOverTrail);
				}
			}
			Light[] componentsInChildren3 = root.GetComponentsInChildren<Light>(true);
			foreach (Light val5 in componentsInChildren3)
			{
				val5.color = ShiftHue(val5.color);
			}
		}

		private static Material BlueMaterial(Material source, Dictionary<Material, Material> cache)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0064: Invalid comparison between Unknown and I4
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Invalid comparison between Unknown and I4
			//IL_0070: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			if (cache.TryGetValue(source, out var value))
			{
				return value;
			}
			Material val = (cache[source] = new Material(source)
			{
				name = ((Object)source).name + "_SnowLeopard"
			});
			Shader shader = val.shader;
			for (int i = 0; i < shader.GetPropertyCount(); i++)
			{
				string propertyName = shader.GetPropertyName(i);
				ShaderPropertyType propertyType = shader.GetPropertyType(i);
				if ((int)propertyType == 0)
				{
					Color color = val.GetColor(propertyName);
					val.SetColor(propertyName, ShiftHue(color));
				}
				else if ((int)propertyType == 4)
				{
					Texture texture = val.GetTexture(propertyName);
					if (Object.op_Implicit((Object)(object)texture) && propertyName == "_RemapTex")
					{
						val.SetTexture(propertyName, ShiftTextureHue(texture));
					}
				}
			}
			return val;
		}

		private static Color ShiftHue(Color color)
		{
			//IL_0001: 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_0070: 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_007c: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(color, ref num, ref num2, ref num3);
			if (num2 < 0.08f)
			{
				if (!tintWhites || num3 < 0.15f)
				{
					return color;
				}
				Color result = Color.HSVToRGB(0.58f, 0.6f, num3, true);
				result.a = color.a;
				return result;
			}
			Color result2 = Color.HSVToRGB(0.58f, num2, num3, true);
			result2.a = color.a;
			return result2;
		}

		private static Gradient ShiftGradient(Gradient gradient)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Gradient val = new Gradient();
			GradientColorKey[] colorKeys = gradient.colorKeys;
			for (int i = 0; i < colorKeys.Length; i++)
			{
				colorKeys[i].color = ShiftHue(colorKeys[i].color);
			}
			val.SetKeys(colorKeys, gradient.alphaKeys);
			val.mode = gradient.mode;
			return val;
		}

		private static MinMaxGradient ShiftMinMax(MinMaxGradient value)
		{
			//IL_0003: 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_0023: Expected I4, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_003e: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystemGradientMode mode = ((MinMaxGradient)(ref value)).mode;
			switch ((int)mode)
			{
			case 0:
				return new MinMaxGradient(ShiftHue(((MinMaxGradient)(ref value)).color));
			case 2:
				return new MinMaxGradient(ShiftHue(((MinMaxGradient)(ref value)).colorMin), ShiftHue(((MinMaxGradient)(ref value)).colorMax));
			case 1:
				return new MinMaxGradient(ShiftGradient(((MinMaxGradient)(ref value)).gradient));
			case 3:
				return new MinMaxGradient(ShiftGradient(((MinMaxGradient)(ref value)).gradientMin), ShiftGradient(((MinMaxGradient)(ref value)).gradientMax));
			case 4:
			{
				MinMaxGradient result = default(MinMaxGradient);
				((MinMaxGradient)(ref result))..ctor(ShiftGradient(((MinMaxGradient)(ref value)).gradient));
				((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4;
				return result;
			}
			default:
				return value;
			}
		}

		private static Texture ShiftTextureHue(Texture source)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Texture, Texture2D> dictionary = (tintWhites ? shiftedTexturesTintedWhites : shiftedTextures);
			if (dictionary.TryGetValue(source, out var value))
			{
				return (Texture)(object)value;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit(source, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, false);
			val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0);
			Color[] pixels = val.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i] = ShiftHue(pixels[i]);
			}
			val.SetPixels(pixels);
			val.Apply();
			((Texture)val).wrapMode = source.wrapMode;
			((Texture)val).filterMode = source.filterMode;
			((Object)val).name = ((Object)source).name + "_SnowLeopard";
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			dictionary[source] = val;
			return (Texture)(object)val;
		}

		private static void AddBlueJets()
		{
			//IL_0007: 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_0080: 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_00b4: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SkinDef[] bodySkins = BodyCatalog.GetBodySkins(BodyCatalog.FindBodyIndex("EngiBody"));
				SkinDef val = ((IEnumerable<SkinDef>)bodySkins).FirstOrDefault((Func<SkinDef, bool>)((SkinDef s) => ((Object)s).name == "Snep"));
				if (!Object.op_Implicit((Object)(object)val))
				{
					InstanceLogger.LogWarning((object)"[Jets] couldn't find the Snep skin to recolor the jets on");
					return;
				}
				RendererInfo[] rendererInfos = val.rendererInfos;
				Dictionary<Material, Material> cache = new Dictionary<Material, Material>();
				int num = 0;
				for (int num2 = 0; num2 < rendererInfos.Length; num2++)
				{
					RendererInfo val2 = rendererInfos[num2];
					if (val2.renderer is ParticleSystemRenderer)
					{
						Material val3 = (Object.op_Implicit((Object)(object)val2.defaultMaterial) ? val2.defaultMaterial : LoadDefaultMaterial(val2));
						if (!Object.op_Implicit((Object)(object)val3))
						{
							InstanceLogger.LogWarning((object)("[Jets] no material found for \"" + ((Object)val2.renderer).name + "\""));
							continue;
						}
						val2.defaultMaterial = BlueMaterial(val3, cache);
						object obj = val2;
						typeof(RendererInfo).GetField("defaultMaterialAddress", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, null);
						rendererInfos[num2] = (RendererInfo)obj;
						num++;
					}
				}
				val.rendererInfos = rendererInfos;
				InstanceLogger.LogInfo((object)$"[Jets] {num} jet materials made blue");
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)"[Jets] failed to recolor the jets");
				InstanceLogger.LogError((object)ex);
			}
		}

		private static Material LoadDefaultMaterial(RendererInfo info)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			object obj = info;
			object? obj2 = typeof(RendererInfo).GetField("defaultMaterialAddress", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj);
			AssetReference val = (AssetReference)((obj2 is AssetReference) ? obj2 : null);
			if (val == null || !val.RuntimeKeyIsValid())
			{
				return null;
			}
			return Addressables.LoadAssetAsync<Material>(val.RuntimeKey).WaitForCompletion();
		}

		private static void HookLaserCutterStates()
		{
			HookLaserState("EntityStates.Engi.EngiWeapon.EnterEngiLaserCutter", "OnEnter");
			string[] array = new string[3] { "EngiLaserCutter", "EngiLaserCutter2", "EngiLaserCutter3" };
			foreach (string text in array)
			{
				HookLaserState("EntityStates.Engi.EngiWeapon." + text, "OnEnter", "FixedUpdate", "Update", "OnExit");
			}
		}

		private static void HookLaserState(string typeName, params string[] methodNames)
		{
			try
			{
				Type type = typeof(FireGauss).Assembly.GetType(typeName);
				if (type == null)
				{
					ManualLogSource instanceLogger = InstanceLogger;
					if (instanceLogger != null)
					{
						instanceLogger.LogWarning((object)("[Laser] state " + typeName + " not found"));
					}
					return;
				}
				MethodInfo method = typeof(SnowLeopardEngineerPlugin).GetMethod("LaserCutterHook", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type);
				Type type2 = typeof(Action<, >).MakeGenericType(typeof(Action<>).MakeGenericType(type), type);
				foreach (string name in methodNames)
				{
					MethodInfo method2 = type.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method2 == null))
					{
						HookEndpointManager.Add((MethodBase)method2, Delegate.CreateDelegate(type2, method));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource instanceLogger2 = InstanceLogger;
				if (instanceLogger2 != null)
				{
					instanceLogger2.LogWarning((object)("[Laser] couldn't hook " + typeName));
				}
				ManualLogSource instanceLogger3 = InstanceLogger;
				if (instanceLogger3 != null)
				{
					instanceLogger3.LogError((object)ex);
				}
			}
		}

		private static void LaserCutterHook<T>(Action<T> orig, T self) where T : EntityState
		{
			if (!laserStateOwners.TryGetValue(self, out var value))
			{
				value = IsSnepOwner(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null);
				laserStateOwners.Add(self, value);
			}
			if (!(bool)value)
			{
				orig(self);
				return;
			}
			Action action = SwapEffectFields(typeof(T), self);
			try
			{
				orig(self);
			}
			finally
			{
				action();
			}
		}

		private static Action SwapEffectFields(Type stateType, object state)
		{
			List<Action> undo = new List<Action>();
			FieldInfo[] fields = stateType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			GameObject prefab = default(GameObject);
			foreach (FieldInfo field in fields)
			{
				object target = (field.IsStatic ? null : state);
				if (field.FieldType == typeof(GameObject))
				{
					ref GameObject reference = ref prefab;
					object? value = field.GetValue(target);
					reference = (GameObject)((value is GameObject) ? value : null);
					if (!Object.op_Implicit((Object)(object)prefab))
					{
						continue;
					}
					blueEffectsByName.TryGetValue(((Object)prefab).name, out var value2);
					LogLaserEffect(stateType, field, ((Object)prefab).name, value2);
					if (Object.op_Implicit((Object)(object)value2))
					{
						field.SetValue(target, value2);
						undo.Add(delegate
						{
							field.SetValue(target, prefab);
						});
					}
				}
				else
				{
					if (field.FieldType.Name != "EntityStateGameObject")
					{
						continue;
					}
					object holder = field.GetValue(target);
					if (holder == null)
					{
						continue;
					}
					object? obj = holder.GetType().GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(holder, null);
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					if (!Object.op_Implicit((Object)(object)val))
					{
						continue;
					}
					blueEffectsByName.TryGetValue(((Object)val).name, out var value3);
					LogLaserEffect(stateType, field, ((Object)val).name, value3);
					if (!Object.op_Implicit((Object)(object)value3))
					{
						continue;
					}
					MethodInfo method = holder.GetType().GetMethod("SetDirectRef", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo directField = holder.GetType().GetField("<directReference>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo addressField = holder.GetType().GetField("addressableReference", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(method == null))
					{
						object originalDirect = directField?.GetValue(holder);
						object originalAddress = addressField?.GetValue(holder);
						method.Invoke(holder, new object[2] { value3, true });
						undo.Add(delegate
						{
							directField?.SetValue(holder, originalDirect);
							addressField?.SetValue(holder, originalAddress);
						});
					}
				}
			}
			return delegate
			{
				foreach (Action item in undo)
				{
					item();
				}
			};
		}

		private static void LogLaserEffect(Type stateType, FieldInfo field, string effectName, GameObject blue)
		{
			string item = stateType.Name + "." + field.Name + "=" + effectName;
			if (loggedLaserEffects.Add(item))
			{
				ManualLogSource instanceLogger = InstanceLogger;
				if (instanceLogger != null)
				{
					instanceLogger.LogInfo((object)("[Laser] " + stateType.Name + "." + field.Name + " (" + (field.IsStatic ? "static" : "instance") + ") holds \"" + effectName + "\" -> " + (Object.op_Implicit((Object)(object)blue) ? "blue copy" : "no blue copy available")));
				}
			}
		}

		private void Start()
		{
			Instance = this;
			BeforeStart();
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SnowLeopardEngineer.avacatsnowleopardengineer"))
			{
				assetBundle = AssetBundle.LoadFromStream(stream);
			}
			((ResourceAvailability)(ref BodyCatalog.availability)).CallWhenAvailable((Action)BodyCatalogInit);
			HookEndpointManager.Add((MethodBase)typeof(Language).GetMethod("LoadStrings"), (Delegate)new Action<Action<Language>, Language>(LanguageLoadStrings));
			ReplaceShaders();
			AfterStart();
		}

		private void BeforeStart()
		{
			BeforeStartDelegate = (VoidDelegate)Delegate.Combine(BeforeStartDelegate, new VoidDelegate(_DynamicSkinExtension.BeforeStart));
			BeforeStartDelegate?.Invoke();
		}

		private void AfterStart()
		{
			AfterStartDelegate = (VoidDelegate)Delegate.Combine(AfterStartDelegate, new VoidDelegate(_DynamicSkinExtension.AfterStart));
			AfterStartDelegate?.Invoke();
		}

		private static void BeforeBodyCatalogInit()
		{
			BeforeBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(BeforeBodyCatalogDelegate, new VoidDelegate(_DynamicSkinExtension.BeforeBodyCatalogInit));
			BeforeBodyCatalogDelegate?.Invoke();
		}

		private static void AfterBodyCatalogInit()
		{
			AfterBodyCatalogDelegate = (VoidDelegate)Delegate.Combine(AfterBodyCatalogDelegate, new VoidDelegate(_DynamicSkinExtension.AfterBodyCatalogInit));
			AfterBodyCatalogDelegate?.Invoke();
		}

		private static void ReplaceShaders()
		{
			LoadMaterialsWithReplacedShader("RoR2/Base/Shaders/HGStandard.shader", "Assets/Resources/snepv2.mat", "Assets/Resources/CrystalTurret.mat");
		}

		private static void LoadMaterialsWithReplacedShader(string shaderPath, params string[] materialPaths)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Shader shader = Addressables.LoadAssetAsync<Shader>((object)shaderPath).WaitForCompletion();
			foreach (string text in materialPaths)
			{
				Material val = assetBundle.LoadAsset<Material>(text);
				val.shader = shader;
				materialsWithRoRShader.Add(val);
			}
		}

		private static void LanguageLoadStrings(Action<Language> orig, Language self)
		{
			orig(self);
			self.SetStringByToken("AVACAT_SKIN_SNEP_NAME", "Snow Leopard");
		}

		private static void Nothing(Action<SkinDef> orig, SkinDef self)
		{
		}

		private static void BodyCatalogInit()
		{
			BeforeBodyCatalogInit();
			MethodInfo method = typeof(SkinDef).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic);
			HookEndpointManager.Add((MethodBase)method, (Delegate)new Action<Action<SkinDef>, SkinDef>(Nothing));
			AddEngiTurretBodyCrystalTurretSkin();
			AddEngiBodySnepSkin();
			HookEndpointManager.Remove((MethodBase)method, (Delegate)new Action<Action<SkinDef>, SkinDef>(Nothing));
			AfterBodyCatalogInit();
		}

		private static void EngiTurretBodyCrystalTurretSkinAdded(SkinDef skinDef, GameObject bodyPrefab)
		{
			SnowLeopardEngineerPlugin.EngiTurretBodyCrystalTurretSkinAddedEvent?.Invoke(Instance, new SkinAddedArgs(skinDef, bodyPrefab));
		}

		private static void AddEngiTurretBodyCrystalTurretSkin()
		{
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			string text = "EngiTurretBody";
			string text2 = "CrystalTurret";
			try
			{
				GameObject val = BodyCatalog.FindBodyPrefab(text);
				if (!Object.op_Implicit((Object)(object)val))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin because \"" + text + "\" doesn't exist"));
					return;
				}
				ModelLocator component = val.GetComponent<ModelLocator>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it doesn't have \"ModelLocator\" component"));
					return;
				}
				GameObject gameObject = ((Component)component.modelTransform).gameObject;
				ModelSkinController skinController = (Object.op_Implicit((Object)(object)gameObject) ? gameObject.GetComponent<ModelSkinController>() : null);
				if (!Object.op_Implicit((Object)(object)skinController))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it doesn't have \"ModelSkinController\" component"));
					return;
				}
				Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>(true);
				SkinDef skin = ScriptableObject.CreateInstance<SkinDef>();
				TryCatchThrow("Icon", delegate
				{
					skin.icon = null;
				});
				((Object)skin).name = text2;
				skin.nameToken = "AVACAT_SKIN_CRYSTALTURRET_NAME";
				skin.rootObject = gameObject;
				TryCatchThrow("Base Skins", delegate
				{
					skin.baseSkins = Array.Empty<SkinDef>();
				});
				TryCatchThrow("Unlockable Name", delegate
				{
					skin.unlockableDef = null;
				});
				TryCatchThrow("Game Object Activations", delegate
				{
					skin.gameObjectActivations = Array.Empty<GameObjectActivation>();
				});
				TryCatchThrow("Renderer Infos", delegate
				{
					skin.rendererInfos = BuildRendererInfos(skinController, renderers[0], assetBundle.LoadAsset<Material>("Assets/Resources/CrystalTurret.mat"));
				});
				TryCatchThrow("Mesh Replacements", delegate
				{
					//IL_0011: 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_003d: Unknown result type (might be due to invalid IL or missing references)
					skin.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
					{
						new MeshReplacement
						{
							mesh = assetBundle.LoadAsset<Mesh>("Assets\\SkinMods\\SnowLeopardEngineer\\Meshes\\Crystal Turret.mesh"),
							renderer = renderers[0]
						}
					};
				});
				TryCatchThrow("Minion Skin Replacements", delegate
				{
					skin.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
				});
				TryCatchThrow("Projectile Ghost Replacements", delegate
				{
					skin.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
				});
				Array.Resize(ref skinController.skins, skinController.skins.Length + 1);
				skinController.skins[skinController.skins.Length - 1] = skin;
				BodyCatalog.skins[BodyCatalog.FindBodyIndex(val)] = skinController.skins;
				EngiTurretBodyCrystalTurretSkinAdded(skin, val);
			}
			catch (FieldException ex)
			{
				InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\""));
				InstanceLogger.LogWarning((object)("Field causing issue: " + ex.Message));
				InstanceLogger.LogError((object)ex.InnerException);
			}
			catch (Exception ex2)
			{
				InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\""));
				InstanceLogger.LogError((object)ex2);
			}
		}

		private static void EngiBodySnepSkinAdded(SkinDef skinDef, GameObject bodyPrefab)
		{
			SnowLeopardEngineerPlugin.EngiBodySnepSkinAddedEvent(Instance, new SkinAddedArgs(skinDef, bodyPrefab));
		}

		private static void AddEngiBodySnepSkin()
		{
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			string text = "EngiBody";
			string text2 = "Snep";
			try
			{
				GameObject val = BodyCatalog.FindBodyPrefab(text);
				if (!Object.op_Implicit((Object)(object)val))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin because \"" + text + "\" doesn't exist"));
					return;
				}
				ModelLocator component = val.GetComponent<ModelLocator>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it doesn't have \"ModelLocator\" component"));
					return;
				}
				GameObject gameObject = ((Component)component.modelTransform).gameObject;
				ModelSkinController skinController = (Object.op_Implicit((Object)(object)gameObject) ? gameObject.GetComponent<ModelSkinController>() : null);
				if (!Object.op_Implicit((Object)(object)skinController))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it doesn't have \"ModelSkinController\" component"));
					return;
				}
				Renderer[] renderers = gameObject.GetComponentsInChildren<Renderer>(true);
				SkinDef skin = ScriptableObject.CreateInstance<SkinDef>();
				TryCatchThrow("Icon", delegate
				{
					skin.icon = assetBundle.LoadAsset<Sprite>("Assets\\SkinMods\\SnowLeopardEngineer\\Icons\\SnepIcon.png");
				});
				((Object)skin).name = text2;
				skin.nameToken = "AVACAT_SKIN_SNEP_NAME";
				skin.rootObject = gameObject;
				TryCatchThrow("Base Skins", delegate
				{
					skin.baseSkins = Array.Empty<SkinDef>();
				});
				TryCatchThrow("Unlockable Name", delegate
				{
					skin.unlockableDef = null;
				});
				TryCatchThrow("Game Object Activations", delegate
				{
					skin.gameObjectActivations = Array.Empty<GameObjectActivation>();
				});
				TryCatchThrow("Renderer Infos", delegate
				{
					skin.rendererInfos = BuildRendererInfos(skinController, renderers[4], assetBundle.LoadAsset<Material>("Assets/Resources/snepv2.mat"));
				});
				TryCatchThrow("Mesh Replacements", delegate
				{
					//IL_0011: 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_003d: Unknown result type (might be due to invalid IL or missing references)
					skin.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
					{
						new MeshReplacement
						{
							mesh = assetBundle.LoadAsset<Mesh>("Assets\\SkinMods\\SnowLeopardEngineer\\Meshes\\SnepBody.mesh"),
							renderer = renderers[4]
						}
					};
				});
				TryCatchThrow("Minion Skin Replacements", delegate
				{
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: 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_0063: Unknown result type (might be due to invalid IL or missing references)
					skin.minionSkinReplacements = (MinionSkinReplacement[])(object)new MinionSkinReplacement[1]
					{
						new MinionSkinReplacement
						{
							minionBodyPrefab = BodyCatalog.FindBodyPrefab("EngiTurretBody"),
							minionSkin = BodyCatalog.GetBodySkins(BodyCatalog.FindBodyIndex("EngiTurretBody")).First((SkinDef s) => ((Object)s).name == "CrystalTurret")
						}
					};
				});
				TryCatchThrow("Projectile Ghost Replacements", delegate
				{
					skin.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
				});
				Array.Resize(ref skinController.skins, skinController.skins.Length + 1);
				skinController.skins[skinController.skins.Length - 1] = skin;
				BodyCatalog.skins[BodyCatalog.FindBodyIndex(val)] = skinController.skins;
				EngiBodySnepSkinAdded(skin, val);
			}
			catch (FieldException ex)
			{
				InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\""));
				InstanceLogger.LogWarning((object)("Field causing issue: " + ex.Message));
				InstanceLogger.LogError((object)ex.InnerException);
			}
			catch (Exception ex2)
			{
				InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\""));
				InstanceLogger.LogError((object)ex2);
			}
		}

		private static RendererInfo[] BuildRendererInfos(ModelSkinController skinController, Renderer target, Material material)
		{
			//IL_0022: 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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00e9: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			RendererInfo[] defaultRendererInfos = GetDefaultRendererInfos(skinController.skins[0]);
			List<RendererInfo> list = new List<RendererInfo>(defaultRendererInfos);
			bool flag = false;
			for (int i = 0; i < list.Count; i++)
			{
				if (!((Object)(object)list[i].renderer != (Object)(object)target))
				{
					RendererInfo val = list[i];
					val.defaultMaterial = material;
					val.defaultShadowCastingMode = (ShadowCastingMode)0;
					val.ignoreOverlays = false;
					object obj = val;
					typeof(RendererInfo).GetField("defaultMaterialAddress", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj, null);
					val = (RendererInfo)obj;
					list[i] = val;
					flag = true;
				}
			}
			if (!flag)
			{
				list.Add(new RendererInfo
				{
					defaultMaterial = material,
					defaultShadowCastingMode = (ShadowCastingMode)0,
					ignoreOverlays = false,
					renderer = target
				});
			}
			return list.ToArray();
		}

		private static object GetDefaultSkinParams(SkinDef defaultSkin)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[2] { "skinDefParams", "optimizedSkinDefParams" };
			foreach (string name in array)
			{
				object? obj = typeof(SkinDef).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(defaultSkin);
				Object val = (Object)((obj is Object) ? obj : null);
				if (Object.op_Implicit(val))
				{
					return val;
				}
			}
			string[] array2 = new string[2] { "skinDefParamsAddress", "optimizedSkinDefParamsAddress" };
			foreach (string name2 in array2)
			{
				object? obj2 = typeof(SkinDef).GetField(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(defaultSkin);
				AssetReference val2 = (AssetReference)((obj2 is AssetReference) ? obj2 : null);
				if (val2 != null && val2.RuntimeKeyIsValid())
				{
					Object val3 = Addressables.LoadAssetAsync<Object>(val2.RuntimeKey).WaitForCompletion();
					if (Object.op_Implicit(val3))
					{
						return val3;
					}
				}
			}
			return null;
		}

		private static RendererInfo[] GetDefaultRendererInfos(SkinDef defaultSkin)
		{
			try
			{
				object obj = GetDefaultSkinParams(defaultSkin);
				if (obj == null)
				{
					obj = typeof(SkinDef).GetMethod("GetSkinParams", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(defaultSkin, null);
				}
				if (obj?.GetType().GetField("rendererInfos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) is RendererInfo[] array && array.Length != 0)
				{
					return array;
				}
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)("Couldn't read default skin params: " + ex.Message));
			}
			return defaultSkin.rendererInfos ?? Array.Empty<RendererInfo>();
		}

		private static void TryCatchThrow(string message, Action action)
		{
			try
			{
				action?.Invoke();
			}
			catch (Exception innerException)
			{
				throw new FieldException(message, innerException);
			}
		}

		private static Texture2D FlatTexture(Color color)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false, false);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private static void AddEngiProjectileGhosts()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SkinDef[] bodySkins = BodyCatalog.GetBodySkins(BodyCatalog.FindBodyIndex("EngiBody"));
				SkinDef val = ((IEnumerable<SkinDef>)bodySkins).FirstOrDefault((Func<SkinDef, bool>)((SkinDef s) => ((Object)s).name == "Snep"));
				if (!Object.op_Implicit((Object)(object)val))
				{
					InstanceLogger.LogWarning((object)"[Crystal] couldn't find the Snep skin to add projectile ghosts to");
					return;
				}
				List<ProjectileGhostReplacement> list = val.projectileGhostReplacements.ToList();
				AddCrystalGhost(list, "EngiGrenadeProjectile", "EngiGrenadeGhost");
				AddCrystalGhost(list, "EngiMine", "EngiMineGhost");
				AddCrystalGhost(list, "EngiBubbleShield", "EngiBubbleShieldGhost");
				AddCrystalGhost(list, "SpiderMine", "SpiderMineGhost");
				AddCrystalGhost(list, "EngiHarpoon", "EngiHarpoonGhost");
				val.projectileGhostReplacements = list.ToArray();
				InstanceLogger.LogInfo((object)$"[Crystal] Snep skin now has {list.Count} projectile ghost replacements");
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)"[Crystal] failed to add projectile ghosts");
				InstanceLogger.LogError((object)ex);
			}
		}

		private static void AddCrystalGhost(List<ProjectileGhostReplacement> replacements, string projectileName, string ghostName)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = LoadEffectPrefab(projectileName);
			if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val.GetComponent<SnowLeopardProjectile>()))
			{
				val.AddComponent<SnowLeopardProjectile>();
			}
			GameObject val2 = CreateCrystalGhost(ghostName);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				InstanceLogger.LogWarning((object)("[Crystal] skipping " + projectileName + ": projectile=" + (Object.op_Implicit((Object)(object)val) ? "ok" : "missing") + " ghost=" + (Object.op_Implicit((Object)(object)val2) ? "ok" : "missing")));
			}
			else
			{
				replacements.Add(new ProjectileGhostReplacement
				{
					projectilePrefab = val,
					projectileGhostReplacementPrefab = val2
				});
			}
		}

		private static GameObject CreateCrystalGhost(string ghostName)
		{
			GameObject val = LoadEffectPrefab(ghostName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, GetEffectRoot().transform);
			((Object)val2).name = ghostName + "SnowLeopard";
			bool flag = (tintWhites = ghostName == "EngiHarpoonGhost");
			try
			{
				RecolorBlue(val2);
			}
			finally
			{
				tintWhites = false;
			}
			MakeCrystalEmissive(val2);
			if (ghostName == "EngiGrenadeGhost")
			{
				ReplaceMeshesWithStars(val2, collapseToOne: false);
			}
			if (flag)
			{
				ReplaceMeshesWithStars(val2, collapseToOne: true);
			}
			return val2;
		}

		private static void ReplaceMeshesWithStars(GameObject root, bool collapseToOne)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			List<MeshFilter> list = (from f in root.GetComponentsInChildren<MeshFilter>(true)
				where Object.op_Implicit((Object)(object)f.sharedMesh)
				select f).ToList();
			MeshFilter val = ((collapseToOne && list.Count > 0) ? list.OrderByDescending(delegate(MeshFilter f)
			{
				//IL_0006: 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_000e: 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)
				Bounds bounds2 = f.sharedMesh.bounds;
				Vector3 extents2 = ((Bounds)(ref bounds2)).extents;
				return ((Vector3)(ref extents2)).magnitude;
			}).First() : null);
			foreach (MeshFilter item in list)
			{
				if (collapseToOne && (Object)(object)item != (Object)(object)val)
				{
					Renderer component = ((Component)item).GetComponent<Renderer>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.enabled = false;
					}
					continue;
				}
				Mesh sharedMesh = item.sharedMesh;
				Bounds bounds = sharedMesh.bounds;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				float radius = (collapseToOne ? ((extents.x + extents.y + extents.z) / 3f * 1.6f) : (Mathf.Max(new float[3] { extents.x, extents.y, extents.z }) * 1.2f));
				item.sharedMesh = CreateStarMesh(radius);
			}
			SkinnedMeshRenderer[] componentsInChildren = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren)
			{
				InstanceLogger.LogWarning((object)("[Crystal] \"" + ((Object)val2).name + "\" is a skinned mesh, leaving it as is"));
			}
		}

		private static Mesh CreateStarMesh(float radius)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: 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_020f: 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_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: 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_0227: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[2349];
			Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length];
			for (int i = 0; i <= 28; i++)
			{
				float num = (float)Math.PI * (float)i / 28f;
				for (int j = 0; j <= 80; j++)
				{
					float num2 = (float)Math.PI * 2f * (float)j / 80f;
					float num3 = Mathf.Lerp(0.55f, 1f, Mathf.Pow(0.5f + 0.5f * Mathf.Cos(5f * num2), 1.6f));
					float num4 = Mathf.Sin(num);
					int num5 = i * 81 + j;
					array[num5] = new Vector3(num4 * Mathf.Cos(num2) * num3, num4 * Mathf.Sin(num2) * num3, Mathf.Cos(num) * 0.55f) * radius;
					array2[num5] = new Vector2((float)j / 80f, (float)i / 28f);
				}
			}
			List<int> list = new List<int>();
			for (int k = 0; k < 28; k++)
			{
				for (int l = 0; l < 80; l++)
				{
					int num6 = k * 81 + l;
					int num7 = num6 + 80 + 1;
					list.Add(num6);
					list.Add(num7);
					list.Add(num6 + 1);
					list.Add(num6 + 1);
					list.Add(num7);
					list.Add(num7 + 1);
				}
			}
			Mesh val = new Mesh
			{
				name = "SnowLeopardStar"
			};
			val.vertices = array;
			val.uv = array2;
			val.triangles = list.ToArray();
			val.RecalculateNormals();
			Vector3[] normals = val.normals;
			for (int m = 0; m <= 28; m++)
			{
				int num8 = m * 81;
				int num9 = num8 + 80;
				Vector3 val2 = normals[num8] + normals[num9];
				normals[num9] = (normals[num8] = ((Vector3)(ref val2)).normalized);
			}
			val.normals = normals;
			val.RecalculateBounds();
			return val;
		}

		private static int MakeCrystalEmissive(GameObject root)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			Material val = assetBundle.LoadAsset<Material>("Assets/Resources/CrystalTurret.mat");
			if (!Object.op_Implicit((Object)(object)val))
			{
				InstanceLogger.LogWarning((object)"[Crystal] couldn't load CrystalTurret.mat to copy its settings from");
				return 0;
			}
			if (!Object.op_Implicit((Object)(object)crystalMainFlat))
			{
				crystalMainFlat = FlatTexture(crystalMainAverage);
			}
			if (!Object.op_Implicit((Object)(object)crystalEmissionFlat))
			{
				crystalEmissionFlat = FlatTexture(crystalEmissionAverage);
			}
			int num = 0;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer))
				{
					continue;
				}
				Material[] sharedMaterials = val2.sharedMaterials;
				foreach (Material val3 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val3) && val3.HasProperty("_EmColor"))
					{
						val3.CopyPropertiesFromMaterial(val);
						val3.shaderKeywords = val.shaderKeywords;
						val3.SetTexture("_MainTex", (Texture)(object)crystalMainFlat);
						val3.SetTexture("_EmTex", (Texture)(object)Texture2D.whiteTexture);
						val3.SetColor("_EmColor", crystalGlowColor);
						val3.SetFloat("_EmPower", 2.6f);
						num++;
					}
				}
			}
			return num;
		}

		private static void ApplyProjectileLook(GameObject projectile)
		{
			tintWhites = true;
			try
			{
				RecolorBlue(projectile, projectileMaterialCache);
			}
			finally
			{
				tintWhites = false;
			}
			Component[] components = projectile.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!(fieldInfo.FieldType != typeof(GameObject)))
					{
						object? value = fieldInfo.GetValue(val);
						GameObject val2 = (GameObject)((value is GameObject) ? value : null);
						if (Object.op_Implicit((Object)(object)val2) && blueEffectsByName.TryGetValue(((Object)val2).name, out var value2))
						{
							fieldInfo.SetValue(val, value2);
						}
					}
				}
			}
		}

		private static GameObject GetProjectileOwner(GameObject projectile)
		{
			if (!Object.op_Implicit((Object)(object)projectile))
			{
				return null;
			}
			Component component = projectile.GetComponent("ProjectileController");
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			Type type = ((object)component).GetType();
			object? obj = type.GetField("owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(component) ?? type.GetProperty("owner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(component, null);
			return (GameObject)((obj is GameObject) ? obj : null);
		}

		private static bool IsSnepOwner(GameObject ownerBody)
		{
			if (!Object.op_Implicit((Object)(object)ownerBody) || findCurrentSkinDef == null)
			{
				return false;
			}
			try
			{
				object? obj = findCurrentSkinDef.Invoke(null, new object[1] { ownerBody });
				SkinDef val = (SkinDef)((obj is SkinDef) ? obj : null);
				return Object.op_Implicit((Object)(object)val) && ((Object)val).name == "Snep";
			}
			catch (Exception ex)
			{
				ManualLogSource instanceLogger = InstanceLogger;
				if (instanceLogger != null)
				{
					instanceLogger.LogWarning((object)("Couldn't read owner skin: " + ex.Message));
				}
				return false;
			}
		}

		private static void ShieldDeployedOnEnter(Action<Deployed> orig, Deployed self)
		{
			if (IsSnepOwner(GetProjectileOwner(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null)))
			{
				snepShieldStates.Remove(self);
				snepShieldStates.Add(self, new object());
			}
			RunWithBlueShieldEnd(orig, self);
		}

		private static void ShieldDeployedUpdate(Action<Deployed> orig, Deployed self)
		{
			RunWithBlueShieldEnd(orig, self);
		}

		private static void RunWithBlueShieldEnd(Action<Deployed> orig, Deployed self)
		{
			if (!blueEffectsByName.TryGetValue("BubbleShieldEndEffect", out var value) || !Object.op_Implicit((Object)(object)value) || !snepShieldStates.TryGetValue(self, out var _))
			{
				orig(self);
				return;
			}
			object obj = typeof(Deployed).GetField("destroyEffectPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(self);
			MethodInfo methodInfo = obj?.GetType().GetMethod("SetDirectRef", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (obj == null || methodInfo == null)
			{
				orig(self);
				return;
			}
			FieldInfo field = obj.GetType().GetField("<directReference>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field2 = obj.GetType().GetField("addressableReference", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			object value3 = field?.GetValue(obj);
			object value4 = field2?.GetValue(obj);
			try
			{
				methodInfo.Invoke(obj, new object[2] { value, true });
				orig(self);
			}
			finally
			{
				field?.SetValue(obj, value3);
				field2?.SetValue(obj, value4);
			}
		}

		private static void SpiderMineDetonateOnEnter(Action<Detonate> orig, Detonate self)
		{
			GameObject blastEffectPrefab = Detonate.blastEffectPrefab;
			GameObject value = null;
			if (Object.op_Implicit((Object)(object)blastEffectPrefab) && IsSnepOwner(GetProjectileOwner(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null)))
			{
				blueEffectsByName.TryGetValue(((Object)blastEffectPrefab).name, out value);
			}
			try
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					Detonate.blastEffectPrefab = value;
				}
				orig(self);
			}
			finally
			{
				Detonate.blastEffectPrefab = blastEffectPrefab;
			}
		}

		private static void MineDetonateOnEnter(Action<Detonate> orig, Detonate self)
		{
			GameObject explosionEffectPrefab = Detonate.explosionEffectPrefab;
			bool flag = Object.op_Implicit((Object)(object)blueMineExplosion) && IsSnepOwner(GetProjectileOwner(Object.op_Implicit((Object)(object)((EntityState)self).outer) ? ((Component)((EntityState)self).outer).gameObject : null));
			try
			{
				if (flag)
				{
					Detonate.explosionEffectPrefab = blueMineExplosion;
				}
				orig(self);
			}
			finally
			{
				Detonate.explosionEffectPrefab = explosionEffectPrefab;
			}
		}

		private static GameObject GetEffectRoot()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)effectRoot))
			{
				effectRoot = new GameObject("SnowLeopardEngineerEffects");
				effectRoot.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)effectRoot);
			}
			return effectRoot;
		}

		private static void CacheCrystalMuzzle()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = BodyCatalog.FindBodyPrefab("EngiTurretBody");
				ModelLocator val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ModelLocator>() : null);
				Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.modelTransform : null);
				ChildLocator val4 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<ChildLocator>() : null);
				if (!Object.op_Implicit((Object)(object)val4))
				{
					InstanceLogger.LogWarning((object)"[Muzzle] couldn't find the regular turret's child locator");
					return;
				}
				NameTransformPair val5 = ((IEnumerable<NameTransformPair>)val4.transformPairs).FirstOrDefault((Func<NameTransformPair, bool>)((NameTransformPair p) => p.name.IndexOf("Muzzle", StringComparison.OrdinalIgnoreCase) >= 0));
				crystalMuzzleReference = val5.transform;
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)"[Muzzle] failed to read the regular turret's muzzle");
				InstanceLogger.LogError((object)ex);
			}
		}

		private static void ApplyCrystalMuzzle(FireBeam self)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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_01d1: 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_0209: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)crystalMuzzleReference) || !Object.op_Implicit((Object)(object)((EntityState)self).outer) || !((Object)((Component)((EntityState)self).outer).gameObject).name.StartsWith("EngiWalkerTurretBody"))
			{
				return;
			}
			try
			{
				FieldInfo field = typeof(FireBeam).GetField("muzzleString", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				string text = field.GetValue(self) as string;
				ModelLocator component = ((Component)((EntityState)self).outer).GetComponent<ModelLocator>();
				Transform val = (Object.op_Implicit((Object)(object)component) ? component.modelTransform : null);
				ChildLocator val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ChildLocator>() : null);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					return;
				}
				Transform val3 = val2.FindChild("MuzzleCrystal");
				if (!Object.op_Implicit((Object)(object)val3))
				{
					Transform val4 = val2.FindChild(text);
					string boneName = (Object.op_Implicit((Object)(object)crystalMuzzleReference.parent) ? ((Object)crystalMuzzleReference.parent).name : null);
					Transform val5 = ((IEnumerable<Transform>)((Component)val).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == boneName));
					Transform val6 = val5;
					if (!Object.op_Implicit((Object)(object)val5) && Object.op_Implicit((Object)(object)val4))
					{
						val5 = val4.parent;
					}
					if (!Object.op_Implicit((Object)(object)val5))
					{
						val5 = val;
					}
					Transform transform = new GameObject("MuzzleCrystal").transform;
					transform.SetParent(val5, false);
					transform.localPosition = (Object.op_Implicit((Object)(object)val6) ? crystalMuzzleReference.localPosition : Vector3.zero) + walkerMuzzleOffset;
					transform.localRotation = (Object.op_Implicit((Object)(object)val6) ? crystalMuzzleReference.localRotation : Quaternion.identity);
					transform.localScale = Vector3.one;
					List<NameTransformPair> list = val2.transformPairs.ToList();
					list.Add(new NameTransformPair
					{
						name = "MuzzleCrystal",
						transform = transform
					});
					val2.transformPairs = list.ToArray();
				}
				field.SetValue(self, "MuzzleCrystal");
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)("[Muzzle] couldn't move the walker's beam start: " + ex.Message));
			}
		}

		private static string PathFrom(Transform root, Transform target)
		{
			string text = ((Object)target).name;
			Transform parent = target.parent;
			while (Object.op_Implicit((Object)(object)parent) && (Object)(object)parent != (Object)(object)root)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static void AddWalkerTurretSkin()
		{
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			string text = "EngiWalkerTurretBody";
			string text2 = "CrystalWalkerTurret";
			MethodInfo method = typeof(SkinDef).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic);
			HookEndpointManager.Add((MethodBase)method, (Delegate)new Action<Action<SkinDef>, SkinDef>(Nothing));
			try
			{
				GameObject val = BodyCatalog.FindBodyPrefab(text);
				if (!Object.op_Implicit((Object)(object)val))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin because \"" + text + "\" doesn't exist"));
					return;
				}
				ModelLocator component = val.GetComponent<ModelLocator>();
				GameObject val2 = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.modelTransform)) ? ((Component)component.modelTransform).gameObject : null);
				ModelSkinController val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<ModelSkinController>() : null);
				if (!Object.op_Implicit((Object)(object)val3))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it has no model skin controller"));
					return;
				}
				SkinnedMeshRenderer val4 = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true).FirstOrDefault();
				if (!Object.op_Implicit((Object)(object)val4))
				{
					InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\" because it has no skinned mesh renderer"));
					return;
				}
				Mesh mesh = assetBundle.LoadAsset<Mesh>("Assets\\SkinMods\\SnowLeopardEngineer\\Meshes\\Crystal Turret.mesh");
				Material material = assetBundle.LoadAsset<Material>("Assets/Resources/CrystalTurret.mat");
				SkinDef val5 = ScriptableObject.CreateInstance<SkinDef>();
				((Object)val5).name = text2;
				val5.nameToken = "AVACAT_SKIN_CRYSTALWALKERTURRET_NAME";
				GameObject rootObject = val3.skins[0].rootObject;
				val5.rootObject = (Object.op_Implicit((Object)(object)rootObject) ? rootObject : val2);
				val5.icon = null;
				val5.baseSkins = Array.Empty<SkinDef>();
				val5.unlockableDef = null;
				val5.gameObjectActivations = Array.Empty<GameObjectActivation>();
				val5.rendererInfos = BuildRendererInfos(val3, (Renderer)(object)val4, material);
				val5.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
				{
					new MeshReplacement
					{
						renderer = (Renderer)(object)val4,
						mesh = mesh
					}
				};
				val5.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
				val5.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
				Array.Resize(ref val3.skins, val3.skins.Length + 1);
				val3.skins[val3.skins.Length - 1] = val5;
				BodyCatalog.skins[BodyCatalog.FindBodyIndex(val)] = val3.skins;
				LinkSnepToWalkerSkin(val, val5);
				InstanceLogger.LogInfo((object)("[Walker] added \"" + text2 + "\""));
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)("Failed to add \"" + text2 + "\" skin to \"" + text + "\""));
				InstanceLogger.LogError((object)ex);
			}
			finally
			{
				HookEndpointManager.Remove((MethodBase)method, (Delegate)new Action<Action<SkinDef>, SkinDef>(Nothing));
			}
		}

		private static void LinkSnepToWalkerSkin(GameObject walkerPrefab, SkinDef walkerSkin)
		{
			//IL_0006: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			SkinDef[] bodySkins = BodyCatalog.GetBodySkins(BodyCatalog.FindBodyIndex("EngiBody"));
			SkinDef val = ((IEnumerable<SkinDef>)bodySkins).FirstOrDefault((Func<SkinDef, bool>)((SkinDef s) => ((Object)s).name == "Snep"));
			if (!Object.op_Implicit((Object)(object)val))
			{
				InstanceLogger.LogWarning((object)"[Walker] couldn't find the Snep skin to link the walker turret skin to");
				return;
			}
			List<MinionSkinReplacement> list = val.minionSkinReplacements.ToList();
			list.Add(new MinionSkinReplacement
			{
				minionBodyPrefab = walkerPrefab,
				minionSkin = walkerSkin
			});
			val.minionSkinReplacements = list.ToArray();
		}
	}
}
namespace RuneFoxMods
{
	internal class Utils
	{
		public static void PrintBodyCatalog()
		{
			Debug.Log((object)"\nBodyCatalog");
			foreach (GameObject allBodyPrefab in BodyCatalog.allBodyPrefabs)
			{
				Debug.Log((object)((Object)allBodyPrefab).name);
			}
			Debug.Log((object)"\n");
		}

		public static void ReadChildren(GameObject parent, int tabs, bool includecomponents = true)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			for (int i = 0; i < tabs; i++)
			{
				text += "  ";
			}
			for (int j = 0; j < parent.transform.childCount; j++)
			{
				Transform child = parent.transform.GetChild(j);
				if ((Object)(object)child == (Object)null)
				{
					break;
				}
				string text2 = ((Component)child).gameObject.activeInHierarchy.ToString();
				Debug.Log((object)(text + ((Object)child).name + " " + text2 + " " + ((Component)child).transform.position));
				if (includecomponents)
				{
					ReadComponents(((Component)child).gameObject, tabs + 1);
					Debug.Log((object)"");
				}
				ReadChildren(((Component)child).gameObject, tabs + 1, includecomponents);
			}
		}

		public static void readheiarchy(GameObject parent, bool includeComponents = true)
		{
			Debug.Log((object)((Object)parent).name);
			if (includeComponents)
			{
				ReadComponents(parent, 1);
				Debug.Log((object)"");
			}
			ReadChildren(parent, 1, includeComponents);
		}

		public static void ReadComponents(GameObject obj, int tabs)
		{
			string text = "";
			for (int i = 0; i < tabs; i++)
			{
				text += "  ";
			}
			Component[] components = obj.GetComponents(typeof(Component));
			Component[] array = components;
			foreach (Component val in array)
			{
				string text2 = "";
				Debug.Log((object)(text + "Comp: " + ((object)val).GetType().ToString() + "  " + text2));
			}
		}

		public static void PrintAllPaths(GameObject parent)
		{
			Debug.Log((object)((Object)parent).name);
			PrintAllPathsInner(parent, ((Object)parent).name);
		}

		private static void PrintAllPathsInner(GameObject parent, string parent_string)
		{
			int childCount = parent.transform.childCount;
			for (int i = 0; i < childCount; i++)
			{
				Transform child = parent.transform.GetChild(i);
				if (((Object)child).name.EndsWith("_end"))
				{
					break;
				}
				string text = parent_string + "/" + ((Object)child).name;
				Debug.Log((object)("  " + ((Object)child).name + "\t\t" + text));
				PrintAllPathsInner(((Component)child).gameObject, text);
			}
		}

		public static void PrintDynamicBone(DynamicBone DB)
		{
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)("Root: " + DB.m_Root));
			Debug.Log((object)("Damping: " + DB.m_Damping));
			Debug.Log((object)("Damping Dist: " + DB.m_DampingDistrib));
			Debug.Log((object)("Elasticity: " + DB.m_Elasticity));
			Debug.Log((object)("Elasticity Dist: " + DB.m_ElasticityDistrib));
			Debug.Log((object)("Stiffness: " + DB.m_Stiffness));
			Debug.Log((object)("Stiffness Dist: " + DB.m_StiffnessDistrib));
			Debug.Log((object)("Inert: " + DB.m_Inert));
			Debug.Log((object)("Inert Dist: " + DB.m_InertDistrib));
			Debug.Log((object)("Radius: " + DB.m_Radius));
			Debug.Log((object)("Radius Dist: " + DB.m_RadiusDistrib));
			Debug.Log((object)("End Length: " + DB.m_EndLength));
			Debug.Log((object)("End Offset: " + DB.m_EndOffset));
			Debug.Log((object)("Gravity: " + DB.m_Gravity));
			Debug.Log((object)("Force: " + DB.m_Force));
			Debug.Log((object)("FreezeAxis: " + DB.m_FreezeAxis));
			Debug.Log((object)("Colliders: " + DB.m_Colliders.Count));
			foreach (DynamicBoneCollider collider in DB.m_Colliders)
			{
				Debug.Log((object)("\t Parent: " + ((Object)((Component)collider).transform).name));
				Debug.Log((object)("\t Direction: " + collider.m_Direction));
				Debug.Log((object)("\t Center " + collider.m_Center));
				Debug.Log((object)("\t Bound " + collider.m_Bound));
				Debug.Log((object)("\t Radius " + collider.m_Radius));
				Debug.Log((object)("\t Height " + collider.m_Height));
			}
			Debug.Log((object)("Exclusions: " + DB.m_Exclusions.Count));
			foreach (Transform exclusion in DB.m_Exclusions)
			{
				Debug.Log((object)("\t Transform: " + ((Object)exclusion).name));
			}
		}

		public static ChildLocator GetChildLocator(GameObject body)
		{
			ChildLocator val = null;
			Transform child = body.transform.GetChild(0);
			if (Object.op_Implicit((Object)(object)child))
			{
				Transform child2 = child.GetChild(0);
				if (Object.op_Implicit((Object)(object)child2))
				{
					val = ((Component)child2).GetComponent<ChildLocator>();
					if (Object.op_Implicit((Object)(object)val))
					{
						Debug.Log((object)"Locator Found");
					}
				}
			}
			return val;
		}

		public static Transform FindChildInTree(Transform Root, string name)
		{
			Queue<Transform> queue = new Queue<Transform>();
			queue.Enqueue(Root);
			while (queue.Count != 0)
			{
				Transform val = queue.Dequeue();
				if (((Object)val).name == name)
				{
					return val;
				}
				for (int i = 0; i < val.childCount; i++)
				{
					Transform child = val.GetChild(i);
					queue.Enqueue(child);
				}
			}
			return null;
		}

		public static string RemoveCloneNaming(string str)
		{
			return str.Remove(str.Length - 7);
		}
	}
}
namespace RuneFoxMods.DynamicSkins
{
	public static class DynamicSkinHelpers
	{
		public static SkinnedMeshRenderer[] GetBaseSkinRenderers(GameObject modelObject)
		{
			SkinnedMeshRenderer[] componentsInChildren = modelObject.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
			SkinnedMeshRenderer[] array = componentsInChildren;
			foreach (SkinnedMeshRenderer val in array)
			{
				if ((Object)(object)((Component)val).transform.parent == (Object)(object)modelObject.transform)
				{
					list.Add(val);
				}
			}
			return list.ToArray();
		}

		public static Transform[] BoneArrayBuilder(Transform NewBoneRoot)
		{
			List<Transform> list = new List<Transform>();
			BoneArrayBuilderHelper(NewBoneRoot, list);
			return list.ToArray();
		}

		public static void BoneArrayBuilderHelper(Transform parent, List<Transform> list)
		{
			if (!((Object)parent).name.EndsWith("_end"))
			{
				list.Add(parent);
			}
			for (int i = 0; i < parent.childCount; i++)
			{
				BoneArrayBuilderHelper(parent.GetChild(i), list);
			}
		}

		public static Transform GetArmature(GameObject obj)
		{
			return GetArmatureHelper(obj);
		}

		public static Transform GetArmatureHelper(GameObject obj)
		{
			if (((Object)obj).name.ToLower().Contains("armature"))
			{
				return obj.transform;
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform armatureHelper = GetArmatureHelper(((Component)obj.transform.GetChild(i)).gameObject);
				if (Object.op_Implicit((Object)(object)armatureHelper))
				{
					return armatureHelper;
				}
			}
			return null;
		}

		public static Transform GetTopParent(Transform obj)
		{
			Transform val = obj;
			while ((Object)(object)val.parent != (Object)null)
			{
				val = val.parent;
			}
			return val;
		}

		public static string GetPrevBoneInList(Transform targetBone, SkinnedMeshRenderer meshRenderer)
		{
			Transform[] bones = meshRenderer.bones;
			for (int i = 0; i <= bones.Length - 1; i++)
			{
				if (((Object)bones[i + 1]).name == ((Object)targetBone).name)
				{
					return ((Object)bones[i]).name;
				}
			}
			return null;
		}

		public static int GetBoneIndexInList(Transform targetBone, SkinnedMeshRenderer meshRenderer)
		{
			Transform[] bones = meshRenderer.bones;
			for (int i = 0; i <= bones.Length; i++)
			{
				if (((Object)bones[i]).name == ((Object)targetBone).name)
				{
					return i;
				}
			}
			return -1;
		}

		public static int GetPrevBoneIndexInList(Transform targetBone, SkinnedMeshRenderer meshRenderer)
		{
			Transform[] bones = meshRenderer.bones;
			for (int i = 0; i <= bones.Length - 1; i++)
			{
				if (((Object)bones[i + 1]).name == ((Object)targetBone).name)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal class DynamicSkinManager
	{
		internal Dictionary<string, SkinDef> SkinDefs = new Dictionary<string, SkinDef>();

		private GameObject LastModelObject;

		internal Dictionary<string, SortedList<int, Modification>> ModificationList = new Dictionary<string, SortedList<int, Modification>>();

		private Dictionary<GameObject, AppliedModifications> ModifiedObjects = new Dictionary<GameObject, AppliedModifications>();

		internal ManualLogSource InstanceLogger;

		internal void AddModification(string skinNameToken, int boneIndex, Modification modification)
		{
			if (!ModificationList.TryGetValue(skinNameToken, out var value))
			{
				value = new SortedList<int, Modification>();
				ModificationList.Add(skinNameToken, value);
			}
			value.Add(boneIndex, modification);
		}

		internal void AddSkinDef(SkinDef skinDef)
		{
			SkinDefs.Add(skinDef.nameToken, skinDef);
		}

		internal void SkinDefApply(Action<SkinDef, GameObject> orig, SkinDef self, GameObject modelObject)
		{
			orig(self, modelObject);
			RemoveInvalidModelObjects();
			ModifiedObjects.TryGetValue(modelObject, out var value);
			try
			{
				if (!SkinDefs.TryGetValue(self.nameToken, out var _))
				{
					if (value != null)
					{
						ClearSkinModifications(LastModelObject, value);
					}
				}
				else if (value == null)
				{
					AppliedModifications appliedModifications = new AppliedModifications();
					ModifiedObjects.Add(modelObject, appliedModifications);
					ApplySkinModifications(self, modelObject, appliedModifications);
				}
			}
			catch (Exception ex)
			{
				InstanceLogger.LogWarning((object)"An error occured while adding accessories to a skin");
				InstanceLogger.LogError((object)ex);
			}
		}

		private void RemoveInvalidModelObjects()
		{
			foreach (GameObject item in ModifiedObjects.Keys.Where((GameObject el) => !Object.op_Implicit((Object)(object)el)).ToList())
			{
				ModifiedObjects.Remove(item);
			}
		}

		private void ClearSkinModifications(GameObject modelObject, AppliedModifications modifications)
		{
			while (modifications.BaseModelModifications.Count != 0)
			{
				Modification modification = modifications.BaseModelModifications.Pop();
				clearModification(modification, modelObject, modifications);
			}
			while (modifications.OtherModifications.Count != 0)
			{
				clearModification(modifications.OtherModifications[0], modelObject, modifications);
			}
			ModifiedObjects.Remove(modelObject);
		}

		private void ApplySkinModifications(SkinDef skindef, GameObject modelObject, AppliedModifications modifications)
		{
			CharacterModel component = modelObject.GetComponent<CharacterModel>();
			LastModelObject = modelObject;
			if (!ModificationList.TryGetValue(skindef.nameToken, out var value))
			{
				return;
			}
			foreach (KeyValuePair<int, Modification> item in value)
			{
				ApplyModification(modelObject, component, item.Value, modifications);
			}
		}

		private static void ApplyModification(GameObject modelObject, CharacterModel characterModel, Modification modification, AppliedModifications modifications)
		{
			string bodyname = modification.bodyname;
			string parentname = modification.parentname;
			Transform val = Utils.FindChildInTree(modelObject.transform, parentname);
			GameObject val2;
			if (modification.affectsbasemodel)
			{
				val2 = Object.Instantiate<GameObject>(modification.prefab, val, false);
				((Object)val2).name = Utils.RemoveCloneNaming(((Object)val2).name);
				modification.instance = val2;
				modification.inst_armature = val2;
				ModificationApplyBones(modelObject, modification, modifications);
			}
			else
			{
				val2 = Object.Instantiate<GameObject>(modification.prefab, modelObject.transform, false);
				((Object)val2).name = Utils.RemoveCloneNaming(((Object)val2).name);
				modification.instance = val2;
				Transform armature = DynamicSkinHelpers.GetArmature(val2);
				((Component)armature).transform.SetParent(val, false);
				modification.inst_armature = ((Component)armature).gameObject;
			}
			modification.instance = val2;
			if (modification.dynamicBoneData != null)
			{
				ModificationApplyDynamicBones(modelObject, modification);
			}
			ModificationAddRenderers(val2, characterModel);
			modifications.OtherModifications.Add(modification);
		}

		private static void ModificationApplyBones(GameObject modelObject, Modification modification, AppliedModifications modifications)
		{
			SkinnedMeshRenderer[] baseSkinRenderers = DynamicSkinHelpers.GetBaseSkinRenderers(modelObject);
			List<Transform> list = baseSkinRenderers[0].bones.ToList();
			Transform[] array = DynamicSkinHelpers.BoneArrayBuilder(modificat