Decompiled source of BugreenBindingsSelected v11.14.0

BepInEx/plugins/BugreenBindingsSelected/BugreenBindingsSelected.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using TrinketAndBindingFramework;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace BugreenBindings;

internal static class AssetService
{
	private static MethodInfo _getPerk;

	private static MethodInfo _getItem;

	private static MethodInfo _getPrefab;

	private static MethodInfo _getTrinket;

	private static MethodInfo _getSprite;

	internal static bool Resolve()
	{
		if (_getPerk != null || _getItem != null || _getPrefab != null)
		{
			return true;
		}
		Type type = AccessTools.TypeByName("CL_AssetManager");
		if (type == null)
		{
			WKLog.Warn("AssetService: CL_AssetManager not found.");
			return false;
		}
		_getPerk = type.GetMethod("GetPerkAsset", BindingFlags.Static | BindingFlags.Public);
		_getItem = type.GetMethod("GetItemObjectPrefab", BindingFlags.Static | BindingFlags.Public);
		_getPrefab = type.GetMethod("GetAssetGameObject", BindingFlags.Static | BindingFlags.Public);
		_getTrinket = type.GetMethod("GetTrinketAsset", BindingFlags.Static | BindingFlags.Public);
		_getSprite = type.GetMethod("GetSpriteAsset", BindingFlags.Static | BindingFlags.Public);
		WKLog.Info("AssetService: perk=" + (_getPerk != null) + " item=" + (_getItem != null) + " prefab=" + (_getPrefab != null) + " trinket=" + (_getTrinket != null));
		if (!(_getPerk != null) && !(_getItem != null))
		{
			return _getPrefab != null;
		}
		return true;
	}

	internal static GameObject GetPrefab(string name)
	{
		object obj = Invoke(_getPrefab, name);
		return (GameObject)((obj is GameObject) ? obj : null);
	}

	internal static Object GetItem(string name)
	{
		object obj = Invoke(_getItem, name);
		return (Object)((obj is Object) ? obj : null);
	}

	internal static Object GetPerk(string name)
	{
		object obj = Invoke(_getPerk, name);
		return (Object)((obj is Object) ? obj : null);
	}

	internal static Sprite GetSprite(string name)
	{
		object obj = Invoke(_getSprite, name);
		return (Sprite)((obj is Sprite) ? obj : null);
	}

	private static object Invoke(MethodInfo method, string name)
	{
		if (method == null || !Resolve())
		{
			return null;
		}
		try
		{
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i].ParameterType == typeof(string))
				{
					array[i] = ((i == parameters.Length - 1) ? name : string.Empty);
				}
				else
				{
					array[i] = (parameters[i].ParameterType.IsValueType ? Activator.CreateInstance(parameters[i].ParameterType) : null);
				}
			}
			return method.Invoke(null, array);
		}
		catch (Exception ex)
		{
			WKLog.Warn("AssetService: " + method.Name + "(" + name + ") failed: " + ex.Message);
			return null;
		}
	}
}
internal class BackflipEffect : MonoBehaviour
{
	private const float Duration = 0.55f;

	internal static BackflipEffect Instance;

	private ENT_Player _player;

	private Transform _cam;

	private bool _running;

	private float _start;

	private float _applied;

	private void Awake()
	{
		Instance = this;
	}

	internal void Begin(ENT_Player player)
	{
		_player = player;
		_cam = null;
		_running = false;
		_applied = 0f;
		if (!((Object)(object)player == (Object)null))
		{
			FieldInfo field = typeof(ENT_Player).GetField("camTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				ref Transform cam = ref _cam;
				object? value = field.GetValue(player);
				cam = (Transform)((value is Transform) ? value : null);
			}
			WKLog.Info("Backflip: camera = " + (((Object)(object)_cam == (Object)null) ? "<none>" : ((Object)_cam).name));
		}
	}

	internal void End()
	{
		Finish();
		_player = null;
	}

	internal void TryStart()
	{
		if (!_running && !((Object)(object)_cam == (Object)null) && BindingState.IsActive("bugreen_backflip"))
		{
			_running = true;
			_start = Time.unscaledTime;
			_applied = 0f;
		}
	}

	private void Finish()
	{
		_running = false;
		_applied = 0f;
	}

	internal void ApplyFlip()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		if (_running && !((Object)(object)_cam == (Object)null))
		{
			float num = (Time.unscaledTime - _start) / 0.55f;
			if (num >= 1f)
			{
				_running = false;
				_applied = 0f;
				return;
			}
			float num2 = num * num * (3f - 2f * num);
			float num3 = -360f * num2;
			_cam.rotation *= Quaternion.Euler(num3, 0f, 0f);
			_applied = num3;
		}
	}

	internal static void Apply(Harmony harmony)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("ENT_Player:Jump", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				MethodInfo method = typeof(BackflipEffect).GetMethod("AfterJump", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Backflip: patched ENT_Player.Jump.");
			}
			else
			{
				WKLog.Warn("Backflip: ENT_Player.Jump not found.");
			}
			MethodInfo methodInfo2 = AccessTools.Method("CL_CameraControl:LateUpdate", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				MethodInfo method2 = typeof(BackflipEffect).GetMethod("AfterCameraUpdate", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Backflip: patched CL_CameraControl.LateUpdate.");
			}
			else
			{
				WKLog.Warn("Backflip: CL_CameraControl.LateUpdate not found.");
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Backflip patch failed: " + ex.Message);
		}
	}

	private static void AfterJump()
	{
		if ((Object)(object)Instance != (Object)null)
		{
			Instance.TryStart();
		}
	}

	private static void AfterCameraUpdate()
	{
		if ((Object)(object)Instance != (Object)null)
		{
			Instance.ApplyFlip();
		}
	}
}
internal static class BadSupplyPatch
{
	private class Saved
	{
		internal object Buff;

		internal bool HasBuff;

		internal List<object> Secondary = new List<object>();

		internal object SecondaryList;

		internal float HealOriginal;

		internal bool HasHeal;
	}

	private static readonly Random Rng = new Random();

	private static readonly Dictionary<object, Saved> Pending = new Dictionary<object, Saved>();

	internal static void Apply(Harmony harmony)
	{
		//IL_0053: 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_0066: Expected O, but got Unknown
		//IL_0066: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("HandItem_Buff:Use", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("BadSupply: HandItem_Buff.Use not found.");
				return;
			}
			MethodInfo method = typeof(BadSupplyPatch).GetMethod("BeforeUse", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(BadSupplyPatch).GetMethod("AfterUse", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			WKLog.Info("BadSupply: patched HandItem_Buff.Use.");
		}
		catch (Exception ex)
		{
			WKLog.Warn("BadSupply patch failed: " + ex.Message);
		}
	}

	private static void BeforeUse(object __instance)
	{
		if (!BindingState.IsActive("bugreen_bad_supply") || __instance == null)
		{
			return;
		}
		try
		{
			float num = (float)Rng.NextDouble();
			bool flag = num < 0.2f;
			float num2 = (flag ? 0f : ((float)(0.3 + Rng.NextDouble() * 1.2)));
			float timeFactor = (flag ? 0.05f : ((float)(0.3 + Rng.NextDouble() * 1.5)));
			Saved saved = new Saved();
			FieldInfo fieldInfo = Field(__instance, "healAmount", typeof(float));
			if (fieldInfo != null)
			{
				float num3 = (float)fieldInfo.GetValue(__instance);
				if (num3 > 0f)
				{
					saved.HasHeal = true;
					saved.HealOriginal = num3;
					fieldInfo.SetValue(__instance, num3 * num2);
				}
			}
			FieldInfo fieldInfo2 = Field(__instance, "buff", null);
			if (fieldInfo2 != null)
			{
				object value = fieldInfo2.GetValue(__instance);
				if (value != null)
				{
					object obj = CopyContainer(value, num2, timeFactor);
					if (obj != null)
					{
						saved.HasBuff = true;
						saved.Buff = value;
						fieldInfo2.SetValue(__instance, obj);
					}
				}
			}
			FieldInfo fieldInfo3 = Field(__instance, "secondaryBuffs", null);
			if (fieldInfo3 != null && fieldInfo3.GetValue(__instance) is IList { Count: >0 } list && Activator.CreateInstance(fieldInfo3.FieldType) is IList list2)
			{
				for (int i = 0; i < list.Count; i++)
				{
					object obj2 = CopyContainer(list[i], num2, timeFactor);
					list2.Add(obj2 ?? list[i]);
					saved.Secondary.Add(list[i]);
				}
				saved.SecondaryList = list;
				fieldInfo3.SetValue(__instance, list2);
			}
			Pending[__instance] = saved;
			WKLog.Info("Bad Supply: effect x" + num2.ToString("0.00") + ", duration x" + timeFactor.ToString("0.00") + (flag ? " (no effect)" : "") + ".");
		}
		catch (Exception ex)
		{
			WKLog.Warn("BadSupply prefix failed: " + ex.Message);
		}
	}

	private static void AfterUse(object __instance)
	{
		if (__instance == null || !Pending.TryGetValue(__instance, out var value))
		{
			return;
		}
		Pending.Remove(__instance);
		try
		{
			if (value.HasHeal)
			{
				FieldInfo fieldInfo = Field(__instance, "healAmount", typeof(float));
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(__instance, value.HealOriginal);
				}
			}
			if (value.HasBuff)
			{
				FieldInfo fieldInfo2 = Field(__instance, "buff", null);
				if (fieldInfo2 != null)
				{
					fieldInfo2.SetValue(__instance, value.Buff);
				}
			}
			if (value.SecondaryList != null)
			{
				FieldInfo fieldInfo3 = Field(__instance, "secondaryBuffs", null);
				if (fieldInfo3 != null)
				{
					fieldInfo3.SetValue(__instance, value.SecondaryList);
				}
			}
		}
		catch
		{
		}
	}

	private static object CopyContainer(object container, float factor, float timeFactor)
	{
		try
		{
			MethodInfo method = container.GetType().GetMethod("CopyBuffContainer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				return null;
			}
			object obj = method.Invoke(container, null);
			if (obj == null)
			{
				return null;
			}
			FieldInfo fieldInfo = Field(obj, "buffTime", typeof(float));
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(obj, (float)fieldInfo.GetValue(obj) * timeFactor);
			}
			FieldInfo fieldInfo2 = Field(obj, "buffs", null);
			IList list = ((fieldInfo2 == null) ? null : (fieldInfo2.GetValue(obj) as IList));
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					object obj2 = list[i];
					if (obj2 != null)
					{
						Scale(obj2, "maxAmount", factor);
						Scale(obj2, "amount", factor);
					}
				}
			}
			return obj;
		}
		catch (Exception ex)
		{
			WKLog.Warn("BadSupply: container copy failed: " + ex.Message);
			return null;
		}
	}

	private static void Scale(object target, string fieldName, float factor)
	{
		FieldInfo fieldInfo = Field(target, fieldName, typeof(float));
		if (fieldInfo != null)
		{
			fieldInfo.SetValue(target, (float)fieldInfo.GetValue(target) * factor);
		}
	}

	private static FieldInfo Field(object instance, string name, Type expected)
	{
		if (instance == null)
		{
			return null;
		}
		FieldInfo field = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			return null;
		}
		if (!(expected == null) && !(field.FieldType == expected))
		{
			return null;
		}
		return field;
	}
}
internal static class BalancedDietEffect
{
	internal static void Apply(Harmony harmony)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("PerkModule_HungerMeter:Initialize", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				MethodInfo method = typeof(BalancedDietEffect).GetMethod("AfterInitialize", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				WKLog.Warn("Balanced Diet: PerkModule_HungerMeter.Initialize not found.");
			}
			MethodInfo methodInfo2 = AccessTools.Method("PerkModule_HungerMeter:OnConsume", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				MethodInfo method2 = typeof(BalancedDietEffect).GetMethod("BeforeConsume", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				WKLog.Warn("Balanced Diet: PerkModule_HungerMeter.OnConsume not found.");
			}
			WKLog.Info("Balanced Diet: hunger accepts only food bar, milk and fruit.");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Balanced Diet patch failed: " + ex.Message);
		}
	}

	private static void AfterInitialize(object __instance)
	{
		try
		{
			if (!BindingState.IsActive("bugreen_balanced_diet") || __instance == null)
			{
				return;
			}
			FieldInfo field = __instance.GetType().GetField("consumeBuffIDs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			IList list = ((field == null) ? null : (field.GetValue(__instance) as IList));
			if (list == null)
			{
				return;
			}
			int num = 0;
			for (int num2 = list.Count - 1; num2 >= 0; num2--)
			{
				string type = list[num2] as string;
				if (!Allowed(type))
				{
					list.RemoveAt(num2);
					num++;
				}
			}
			WKLog.Info("Balanced Diet: hunger consume list filtered, removed " + num + " type(s).");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Balanced Diet filter failed: " + ex.Message);
		}
	}

	private static bool BeforeConsume(string type)
	{
		if (!BindingState.IsActive("bugreen_balanced_diet"))
		{
			return true;
		}
		if (Allowed(type))
		{
			return true;
		}
		WKLog.Info("Balanced Diet: refused hunger restore from '" + type + "'.");
		return false;
	}

	private static bool Allowed(string type)
	{
		if (string.IsNullOrEmpty(type))
		{
			return false;
		}
		string text = type.ToLowerInvariant();
		if (!text.Contains("food") && !text.Contains("milk"))
		{
			return text.Contains("fruit");
		}
		return true;
	}
}
internal static class BindingDefs
{
	public static readonly BindingDef[] All = new BindingDef[11]
	{
		new BindingDef("bugreen_old_bones", "Old Bones", "You cannot move that fast than before.", "", "- reduces your walking/running speed when grounded by -25%\n- reduces your jump height by -15%\n+ increases your climbing speed by 10%", 1.5f, "Binding_Icon_Old_Bones.png"),
		new BindingDef("bugreen_one_hand", "One Hand", "You have only one hand now.", "Now I see which hand you always use for gooning.", "- Having only one hand now.\n+ Increases stamina by 30%\n+ Increases climbing speed by 20%", 3f, "Binding_Icon_Onehand.png"),
		new BindingDef("bugreen_timeflies", "Timeflies", "Timespeed go faster by 20%.", "The timepiece must be broken.", "- Timespeed go faster by 20%", 3f, "Binding_Icon_Timeflies.png"),
		new BindingDef("bugreen_take_a_slice", "Take A Slice", "You cannot choose sharing food with who.", "IT SMELLS TOO.", "- Reduces all abilities and buffs by -10%\n- Increases all Mass forms when consume a food item by 1%", 1.75f, "Binding_Icon_Take_A_Slice.png"),
		new BindingDef("bugreen_darkness", "Darkness", "Electricity in Superstructure went off.", "Hope you do not fear the dark.", "- Removes lights from electric devices\n+ Get a flashlight", 1.4f, "Binding_Icon_Darkness.png"),
		new BindingDef("bugreen_pacifism", "Pacifism", "No weapons and tools.", "", "No weapons and tools.", 1.25f, "Binding_Icon_Pacifism.png"),
		new BindingDef("bugreen_fragile", "Fragile", "-60% player health.", "Watch your steps.", "- Reduces player health by -60%\n- Treat the Grubs well", 2.5f, "Binding_Icon_Fragile.png"),
		new BindingDef("bugreen_gold_rush", "Gold Rush", "No valuable roaches.", "Having a million expects you.", "No valuable roaches.", 1.1f, "Binding_Icon_Gold_Rush.png"),
		new BindingDef("bugreen_echo", "Echo", "All denizens are invisible.", "Watch your steps.", "- All denizens are invisible\n+ sounds from denizens are louder\n+ Get a scanner", 4f, "Binding_Icon_Echo.png"),
		new BindingDef("bugreen_delusions", "Delusions", "You lost the ability to recognize things.", "FOR A RHOST CHICKEN.", "cannot recognize items.", 1.75f, "Binding_Icon_Delusions.png"),
		new BindingDef("bugreen_light_from_the_violet", "Light From The Violet", "Close your eyes when the lights on.", "You can cover your eyes. But always useless.", "Close your eyes when the lights on.\n- Light from above will burn your eyes\n- Reduces your walking/running speed by -70% when look up", 2.5f, "Binding_Icon_Light_From_The_Violet.png")
	};
}
internal static class BindingState
{
	private static readonly HashSet<string> ActiveIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static readonly HashSet<string> ActiveTitles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

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

	private static MethodInfo _isSelected;

	private static bool _registryQueryFailed;

	internal static int ActiveCount => ActiveIds.Count + ActiveTitles.Count;

	internal static void Init()
	{
		for (int i = 0; i < BindingDefs.All.Length; i++)
		{
			BindingDef bindingDef = BindingDefs.All[i];
			TitleById[bindingDef.Id] = bindingDef.Title;
		}
		ResolveRegistry();
	}

	private static void ResolveRegistry()
	{
		try
		{
			_isSelected = typeof(TrinketRegistry).GetMethod("IsSelected", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			WKLog.Info("BindingState: TrinketRegistry.IsSelected = " + (_isSelected != null));
		}
		catch (Exception ex)
		{
			WKLog.Warn("BindingState: registry lookup failed: " + ex.Message);
		}
	}

	internal static void RefreshFromPicker(object __instance)
	{
		if (__instance != null)
		{
			ActiveTitles.Clear();
			_registryQueryFailed = false;
			QueryById(__instance);
			QueryByTitle(__instance);
			WKLog.Info("Selected bindings: " + Describe());
		}
	}

	private static void QueryById(object picker)
	{
		if (_isSelected == null)
		{
			ResolveRegistry();
		}
		if (_isSelected == null)
		{
			return;
		}
		for (int i = 0; i < BindingDefs.All.Length; i++)
		{
			BindingDef bindingDef = BindingDefs.All[i];
			try
			{
				object obj = _isSelected.Invoke(null, new object[2] { picker, bindingDef.Id });
				if (obj is bool && (bool)obj)
				{
					ActiveIds.Add(bindingDef.Id);
				}
			}
			catch (Exception ex)
			{
				if (!_registryQueryFailed)
				{
					_registryQueryFailed = true;
					WKLog.Warn("BindingState: IsSelected(" + bindingDef.Id + ") failed: " + ex.Message);
				}
			}
		}
	}

	private static void QueryByTitle(object picker)
	{
		try
		{
			FieldInfo field = picker.GetType().GetField("selectedTrinkets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null || !(field.GetValue(picker) is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				string text = ReadTitle(item);
				if (!string.IsNullOrEmpty(text))
				{
					ActiveTitles.Add(text);
				}
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("BindingState: title fallback failed: " + ex.Message);
		}
	}

	private static string ReadTitle(object trinket)
	{
		if (trinket == null)
		{
			return null;
		}
		FieldInfo field = trinket.GetType().GetField("title", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null)
		{
			object value = field.GetValue(trinket);
			if (value is string)
			{
				return (string)value;
			}
		}
		Object val = (Object)((trinket is Object) ? trinket : null);
		if (!(val != (Object)null))
		{
			return null;
		}
		return val.name;
	}

	internal static void SetIds(IEnumerable<string> ids)
	{
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		if (ids != null)
		{
			foreach (string id in ids)
			{
				if (!string.IsNullOrEmpty(id))
				{
					hashSet.Add(id);
				}
			}
		}
		bool flag = hashSet.Count != ActiveIds.Count;
		if (!flag)
		{
			foreach (string item in hashSet)
			{
				if (!ActiveIds.Contains(item))
				{
					flag = true;
					break;
				}
			}
		}
		ActiveIds.Clear();
		foreach (string item2 in hashSet)
		{
			ActiveIds.Add(item2);
		}
		if (flag)
		{
			WKLog.Info("BindingState: selection now has " + ActiveIds.Count + " id(s): " + Describe() + ".");
		}
	}

	internal static bool IsActive(string id)
	{
		if (ActiveIds.Contains(id))
		{
			return true;
		}
		if (TitleById.TryGetValue(id, out var value))
		{
			return ActiveTitles.Contains(value);
		}
		return false;
	}

	internal static string Describe()
	{
		if (ActiveIds.Count > 0)
		{
			return "ids: " + string.Join(", ", new List<string>(ActiveIds).ToArray());
		}
		if (ActiveTitles.Count > 0)
		{
			return "titles: " + string.Join(", ", new List<string>(ActiveTitles).ToArray());
		}
		return "(none)";
	}
}
internal static class BuffAudit
{
	private static readonly string[] Ids = new string[14]
	{
		"addSpeed", "addGroundedSpeed", "addJump", "addClimb", "addStamina", "addStaminaRegen", "divideStamina", "addGripStrength", "damageResist", "addGravity",
		"addReach", "slowTime", "freezing", "massSpeedMult"
	};

	internal static void LogRunBuffs(ENT_Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		try
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < Ids.Length; i++)
			{
				float num = BuffService.Read((GameEntity)(object)player, Ids[i]);
				if (!float.IsNaN(num) && !(Math.Abs(num) < 0.0001f))
				{
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append(", ");
					}
					stringBuilder.Append(Ids[i]).Append("=").Append(num.ToString("0.###"));
				}
			}
			WKLog.Info("Buff audit: " + ((stringBuilder.Length == 0) ? "(no binding buffs)" : stringBuilder.ToString()) + ".");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Buff audit failed: " + ex.Message);
		}
	}
}
internal static class BuffIds
{
	public const string AddSpeed = "addSpeed";

	public const string AddGroundedSpeed = "addGroundedSpeed";

	public const string DivideSpeed = "divideSpeed";

	public const string AddSlow = "addSlow";

	public const string AddJump = "addJump";

	public const string AddJumpBoost = "addJumpBoost";

	public const string AddExtraJumps = "addExtraJumps";

	public const string AddClimb = "addClimb";

	public const string AddGravity = "addGravity";

	public const string AddReach = "addReach";

	public const string AddStamina = "addStamina";

	public const string AddStaminaRegen = "addStaminaRegen";

	public const string DivideStamina = "divideStamina";

	public const string AddGripStrength = "addGripStrength";

	public const string LimitGripStrength = "limitGripStrength";

	public const string GripResist = "gripResist";

	public const string DamageResist = "damageResist";

	public const string MassSpeedMult = "massSpeedMult";

	public const string SlowTime = "slowTime";

	public const string Freezing = "freezing";
}
internal static class BuffService
{
	private static Type _containerType;

	private static Type _buffType;

	private static FieldInfo _curBuffsField;

	private static FieldInfo _containerBuffs;

	private static FieldInfo _containerId;

	private static FieldInfo _containerDesc;

	private static FieldInfo _containerTime;

	private static FieldInfo _containerLoseOverTime;

	private static FieldInfo _containerMultiplier;

	private static FieldInfo _buffId;

	private static FieldInfo _buffAmount;

	private static FieldInfo _buffMax;

	private static MethodInfo _addBuff;

	private static MethodInfo _removeById;

	internal static bool Resolve()
	{
		if (_addBuff != null)
		{
			return true;
		}
		_containerType = AccessTools.TypeByName("BuffContainer");
		if (_containerType != null)
		{
			_buffType = _containerType.GetNestedType("Buff", BindingFlags.Public | BindingFlags.NonPublic);
		}
		_curBuffsField = FindField(typeof(GameEntity), "curBuffs");
		if (_containerType == null || _buffType == null || _curBuffsField == null)
		{
			WKLog.Warn("BuffService: types not resolved (container=" + (_containerType != null) + ", buff=" + (_buffType != null) + ", curBuffs=" + (_curBuffsField != null) + ").");
			return false;
		}
		_containerBuffs = Field(_containerType, "buffs");
		_containerId = Field(_containerType, "id");
		_containerDesc = Field(_containerType, "desc");
		_containerTime = Field(_containerType, "buffTime");
		_containerLoseOverTime = Field(_containerType, "loseOverTime");
		_containerMultiplier = Field(_containerType, "multiplier");
		_buffId = Field(_buffType, "id");
		_buffAmount = Field(_buffType, "amount");
		_buffMax = Field(_buffType, "maxAmount");
		Type fieldType = _curBuffsField.FieldType;
		_addBuff = fieldType.GetMethod("AddOrResetBuff", new Type[1] { _containerType }) ?? fieldType.GetMethod("AddBuff", new Type[1] { _containerType });
		_removeById = fieldType.GetMethod("RemoveBuffContainer", new Type[1] { typeof(string) });
		WKLog.Info("BuffService: ready (add=" + (_addBuff != null) + ", remove=" + (_removeById != null) + ").");
		return _addBuff != null;
	}

	internal static void Apply(GameEntity entityTarget, string containerId, string[] ids, float[] amounts, float duration)
	{
		if ((Object)(object)entityTarget == (Object)null || !Resolve())
		{
			return;
		}
		try
		{
			object value = _curBuffsField.GetValue(entityTarget);
			if (value == null)
			{
				return;
			}
			object obj = Activator.CreateInstance(_containerType);
			Set(obj, _containerId, containerId);
			Set(obj, _containerDesc, "Bugreen binding");
			Set(obj, _containerTime, duration);
			Set(obj, _containerLoseOverTime, false);
			Set(obj, _containerMultiplier, 1f);
			IList list = _containerBuffs.GetValue(obj) as IList;
			if (list == null)
			{
				list = Activator.CreateInstance(_containerBuffs.FieldType) as IList;
				_containerBuffs.SetValue(obj, list);
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < ids.Length && i < amounts.Length; i++)
			{
				object obj2 = Activator.CreateInstance(_buffType);
				Set(obj2, _buffId, ids[i]);
				Set(obj2, _buffAmount, amounts[i]);
				Set(obj2, _buffMax, amounts[i]);
				list.Add(obj2);
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(ids[i]).Append('=').Append(amounts[i]);
			}
			if (_removeById != null)
			{
				_removeById.Invoke(value, new object[1] { containerId });
			}
			_addBuff.Invoke(value, new object[1] { obj });
			WKLog.Info(string.Concat("Buff: ", containerId, " [", stringBuilder, "] for ", duration, "s."));
			float num = ReadBack(value, (ids.Length > 0) ? ids[0] : null);
			WKLog.Info("Buff verify: " + containerId + " -> GetBuff(" + ((ids.Length > 0) ? ids[0] : "?") + ") = " + num + ".");
		}
		catch (Exception ex)
		{
			WKLog.Warn("BuffService apply failed: " + ex.Message);
		}
	}

	internal static float Read(GameEntity target, string id)
	{
		if ((Object)(object)target == (Object)null || !Resolve())
		{
			return float.NaN;
		}
		try
		{
			object value = _curBuffsField.GetValue(target);
			return ReadBack(value, id);
		}
		catch
		{
			return float.NaN;
		}
	}

	private static float ReadBack(object entityBuff, string id)
	{
		if (entityBuff == null || string.IsNullOrEmpty(id))
		{
			return float.NaN;
		}
		try
		{
			MethodInfo method = entityBuff.GetType().GetMethod("GetBuff", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			if (method == null)
			{
				return float.NaN;
			}
			return (float)method.Invoke(entityBuff, new object[1] { id });
		}
		catch
		{
			return float.NaN;
		}
	}

	internal static void Remove(GameEntity entityTarget, string containerId)
	{
		try
		{
			if (!((Object)(object)entityTarget == (Object)null) && Resolve() && !(_removeById == null))
			{
				object value = _curBuffsField.GetValue(entityTarget);
				if (value != null)
				{
					_removeById.Invoke(value, new object[1] { containerId });
					WKLog.Info("Buff: removed " + containerId);
				}
			}
		}
		catch
		{
		}
	}

	private static FieldInfo Field(Type type, string name)
	{
		return type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
	}

	private static FieldInfo FindField(Type type, string name)
	{
		Type type2 = type;
		while (type2 != null)
		{
			FieldInfo field = type2.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field;
			}
			type2 = type2.BaseType;
		}
		return null;
	}

	private static void Set(object target, FieldInfo field, object value)
	{
		if (target != null && field != null && value != null && field.FieldType.IsInstanceOfType(value))
		{
			field.SetValue(target, value);
		}
	}
}
internal static class ClimbSpeedPatch
{
	internal static void Apply(Harmony harmony)
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = null;
			int num = 0;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.IsDynamic)
				{
					continue;
				}
				Type[] types;
				try
				{
					types = assembly.GetTypes();
				}
				catch
				{
					continue;
				}
				for (int j = 0; j < types.Length; j++)
				{
					MethodInfo[] methods;
					try
					{
						methods = types[j].GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					}
					catch
					{
						continue;
					}
					foreach (MethodInfo methodInfo2 in methods)
					{
						if (!(methodInfo2.Name != "GetClimbMult") && !(methodInfo2.ReturnType != typeof(float)))
						{
							num++;
							if (!(methodInfo != null))
							{
								MethodInfo method = typeof(ClimbSpeedPatch).GetMethod("Postfix", BindingFlags.Static | BindingFlags.NonPublic);
								harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
								methodInfo = methodInfo2;
							}
						}
					}
				}
			}
			if (methodInfo == null)
			{
				WKLog.Warn("GetClimbMult not found; Old Bones climb bonus disabled.");
				return;
			}
			WKLog.Info("Patched climb multiplier: " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + " (candidates: " + num + ")");
		}
		catch (Exception ex)
		{
			WKLog.Warn("ClimbSpeedPatch failed: " + ex.Message);
		}
	}

	private static void Postfix(ref float __result)
	{
		if (VioletOrb.ClimbPenalty)
		{
			__result *= 0.3f;
		}
	}
}
internal class CounterDisplay : MonoBehaviour
{
	private Component _counter;

	private PropertyInfo _textProperty;

	private string _bindingId;

	internal void Setup(Component counter, string bindingId)
	{
		_counter = counter;
		_bindingId = bindingId;
		if ((Object)(object)counter != (Object)null)
		{
			_textProperty = ((object)counter).GetType().GetProperty("text");
		}
		UpdateText();
	}

	private void Update()
	{
		UpdateText();
	}

	private void UpdateText()
	{
		if ((Object)(object)_counter == (Object)null || _textProperty == null || (Object)(object)RunTimers.Instance == (Object)null)
		{
			return;
		}
		float num = ((_bindingId == "bugreen_candle_queen") ? RunTimers.Instance.CandleTimer : RunTimers.Instance.DeathTimer);
		if (num < 0f)
		{
			return;
		}
		int num2 = Mathf.Max(0, Mathf.CeilToInt(num));
		string value = (num2 / 60).ToString("00") + ":" + (num2 % 60).ToString("00");
		try
		{
			_textProperty.SetValue(_counter, value, null);
		}
		catch
		{
		}
	}
}
internal static class CounterPatch
{
	internal static void Apply(Harmony harmony)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("Perk:GetPerkModuleCounterText", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("Counter: Perk.GetPerkModuleCounterText not found.");
				return;
			}
			MethodInfo method = typeof(CounterPatch).GetMethod("AfterGet", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			WKLog.Info("Counter: patched Perk.GetPerkModuleCounterText.");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Counter patch failed: " + ex.Message);
		}
	}

	private static void AfterGet(object __instance, ref string __result)
	{
		try
		{
			if (__instance == null || (Object)(object)RunTimers.Instance == (Object)null)
			{
				return;
			}
			string text = ReadId(__instance);
			float num;
			if (text == "bugreen_candle_queen")
			{
				num = RunTimers.Instance.CandleTimer;
			}
			else
			{
				if (!(text == "bugreen_the_day_we_died"))
				{
					return;
				}
				num = RunTimers.Instance.DeathTimer;
			}
			if (!(num < 0f))
			{
				int num2 = (int)Math.Ceiling(num);
				if (num2 < 0)
				{
					num2 = 0;
				}
				string text2 = (num2 / 60).ToString("00") + ":" + (num2 % 60).ToString("00");
				__result = "<color=#FF4040>" + text2 + "</color>";
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Counter value failed: " + ex.Message);
		}
	}

	private static string ReadId(object perk)
	{
		FieldInfo field = perk.GetType().GetField("id", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (!(field == null))
		{
			return field.GetValue(perk) as string;
		}
		return null;
	}
}
internal class DarknessEffect : MonoBehaviour
{
	internal static DarknessEffect Instance;

	private GameObject _flashlightObject;

	private bool _active;

	private Color _originalAmbient;

	private float _originalAmbientIntensity;

	private float _originalReflection;

	private AmbientMode _originalAmbientMode;

	private Light _originalSun;

	private LightmapData[] _originalLightmaps;

	private int _originalPixelLights = 4;

	private float _nextScan;

	private Light[] _lights;

	private Type _lampType;

	private float _nextRefresh;

	private bool _lampScanNeeded = true;

	internal bool Active => _active;

	private void Awake()
	{
		Instance = this;
	}

	internal void Begin(ENT_Player player)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0064: Unknown result type (might be due to invalid IL or missing references)
		if (_active || !BindingState.IsActive("bugreen_darkness"))
		{
			return;
		}
		try
		{
			_active = true;
			_originalAmbient = RenderSettings.ambientLight;
			_originalAmbientIntensity = RenderSettings.ambientIntensity;
			_originalReflection = RenderSettings.reflectionIntensity;
			_originalAmbientMode = RenderSettings.ambientMode;
			_originalSun = RenderSettings.sun;
			_originalLightmaps = LightmapSettings.lightmaps;
			RenderSettings.ambientMode = (AmbientMode)3;
			RenderSettings.ambientLight = Color.black;
			RenderSettings.ambientIntensity = 0f;
			RenderSettings.reflectionIntensity = 0f;
			RenderSettings.sun = null;
			LightmapSettings.lightmaps = (LightmapData[])(object)new LightmapData[0];
			try
			{
				_originalPixelLights = QualitySettings.pixelLightCount;
				QualitySettings.pixelLightCount = Mathf.Max(8, _originalPixelLights);
			}
			catch
			{
			}
			AttachFlashlight();
			_lights = null;
			_lampScanNeeded = true;
			EnforceLighting();
			WKLog.Info("Darkness: lightmaps cleared (" + ((_originalLightmaps != null) ? _originalLightmaps.Length : 0) + "), sun removed, scene lights disabled, custom flashlight attached.");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Darkness failed: " + ex.Message);
		}
	}

	private static bool IsPlayerOrCameraOwned(Transform transform)
	{
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: 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)
		if ((Object)(object)transform == (Object)null)
		{
			return false;
		}
		ENT_Player player = ENT_Player.GetPlayer();
		if ((Object)(object)player != (Object)null)
		{
			if (transform.IsChildOf(((Component)player).transform))
			{
				return true;
			}
			Transform[] array = (Transform[])(object)new Transform[4]
			{
				ReadTransform(player, "camTransform"),
				ReadTransform(player, "inventoryHandRoot"),
				ReadTransform(player, "camRoot"),
				ReadTransform(player, "effectsRoot")
			};
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null && transform.IsChildOf(array[i]))
				{
					return true;
				}
			}
		}
		Camera[] allCameras = Camera.allCameras;
		for (int j = 0; j < allCameras.Length; j++)
		{
			if ((Object)(object)allCameras[j] != (Object)null && transform.IsChildOf(((Component)allCameras[j]).transform))
			{
				return true;
			}
		}
		Vector3 val = PlayerPosition();
		if (val != Vector3.zero && Vector3.Distance(transform.position, val) < 3f)
		{
			return true;
		}
		Transform val2 = transform;
		while ((Object)(object)val2 != (Object)null)
		{
			string text = ((Object)((Component)val2).gameObject).name.ToLowerInvariant();
			if (text.Contains("flashlight") || text.Contains("headlamp") || text.Contains("lantern") || text.Contains("handitem") || text.Contains("hand_light") || text.Contains("bugreenflashlight"))
			{
				return true;
			}
			val2 = val2.parent;
		}
		return false;
	}

	private static Vector3 PlayerPosition()
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player player = ENT_Player.GetPlayer();
		if ((Object)(object)player == (Object)null)
		{
			return Vector3.zero;
		}
		Transform val = ReadTransform(player, "camTransform");
		if (!((Object)(object)val != (Object)null))
		{
			return ((Component)player).transform.position;
		}
		return val.position;
	}

	private static Transform ReadTransform(ENT_Player player, string fieldName)
	{
		FieldInfo field = typeof(ENT_Player).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			return null;
		}
		object value = field.GetValue(player);
		Component val = (Component)((value is Component) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			return val.transform;
		}
		return (Transform)((value is Transform) ? value : null);
	}

	private void AttachFlashlight()
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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_0172: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_flashlightObject != (Object)null)
		{
			return;
		}
		Transform val = null;
		ENT_Player player = ENT_Player.GetPlayer();
		if ((Object)(object)player != (Object)null)
		{
			FieldInfo field = typeof(ENT_Player).GetField("camTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				object? value = field.GetValue(player);
				val = (Transform)((value is Transform) ? value : null);
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			val = ((Component)main).transform;
		}
		_flashlightObject = new GameObject("BugreenFlashlight");
		_flashlightObject.transform.SetParent(val, false);
		_flashlightObject.transform.localPosition = new Vector3(0.08f, -0.08f, 0.15f);
		_flashlightObject.transform.localRotation = Quaternion.identity;
		Light val2 = _flashlightObject.AddComponent<Light>();
		val2.type = (LightType)0;
		val2.range = 100f;
		val2.spotAngle = 80f;
		val2.intensity = 8f;
		val2.color = new Color(1f, 0.97f, 0.9f);
		val2.shadows = (LightShadows)0;
		val2.renderMode = (LightRenderMode)1;
		((Behaviour)val2).enabled = true;
		Light val3 = _flashlightObject.AddComponent<Light>();
		val3.type = (LightType)2;
		val3.range = 8f;
		val3.intensity = 2f;
		val3.color = new Color(1f, 0.95f, 0.85f);
		val3.shadows = (LightShadows)0;
		val3.renderMode = (LightRenderMode)1;
		((Behaviour)val3).enabled = true;
		WKLog.Info("Darkness: custom flashlight attached to " + ((Object)val).name + ".");
	}

	private void DisableLights()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Invalid comparison between Unknown and I4
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Invalid comparison between Unknown and I4
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Invalid comparison between Unknown and I4
		if (_lights == null || Time.unscaledTime >= _nextRefresh)
		{
			_nextRefresh = Time.unscaledTime + 5f;
			_lights = Object.FindObjectsOfType<Light>();
		}
		int num = 0;
		for (int i = 0; i < _lights.Length; i++)
		{
			Light val = _lights[i];
			if (!((Object)(object)val == (Object)null) && ((Behaviour)val).enabled && !((Object)(object)((Component)val).gameObject == (Object)(object)_flashlightObject) && !IsPlayerOrCameraOwned(((Component)val).transform) && ((int)val.type == 1 || (int)val.type == 2 || (int)val.type == 0 || (int)val.type == 3))
			{
				((Behaviour)val).enabled = false;
				num++;
			}
		}
		if (_lampScanNeeded)
		{
			ScanLampsOnce();
		}
		if (num > 0)
		{
			WKLog.Info("Darkness: disabled " + num + " newly enabled light(s).");
		}
	}

	private void ScanLampsOnce()
	{
		_lampScanNeeded = false;
		try
		{
			_lampType = AccessTools.TypeByName("CL_Lamp");
			if (_lampType == null)
			{
				return;
			}
			Object[] array = Object.FindObjectsOfType(_lampType);
			int num = 0;
			foreach (Object obj in array)
			{
				Component val = (Component)(object)((obj is Component) ? obj : null);
				if (!((Object)(object)val == (Object)null) && !IsPlayerOrCameraOwned(val.transform))
				{
					SetField(val, _lampType, "lampActive", false);
					SetField(val, _lampType, "intensity", 0f);
					SetField(val, _lampType, "emissiveMult", 0f);
					num++;
				}
			}
			WKLog.Info("Darkness: switched off " + num + " active lamp(s).");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Darkness lamps failed: " + ex.Message);
		}
	}

	private static void SetField(object target, Type type, string name, object value)
	{
		FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field != null && value != null && field.FieldType.IsInstanceOfType(value))
		{
			field.SetValue(target, value);
		}
	}

	private void EnforceLighting()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			RenderSettings.ambientMode = (AmbientMode)3;
			RenderSettings.ambientLight = Color.black;
			RenderSettings.ambientIntensity = 0f;
			RenderSettings.reflectionIntensity = 0f;
			RenderSettings.sun = null;
			RenderSettings.fog = false;
			RenderSettings.fogDensity = 0f;
			RenderSettings.fogColor = Color.black;
			if (LightmapSettings.lightmaps.Length > 0)
			{
				LightmapSettings.lightmaps = (LightmapData[])(object)new LightmapData[0];
			}
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				main.clearFlags = (CameraClearFlags)2;
				main.backgroundColor = Color.black;
			}
			DisableLights();
		}
		catch (Exception ex)
		{
			WKLog.Warn("Darkness enforce failed: " + ex.Message);
		}
	}

	internal static void EnforceFromPatch()
	{
		if ((Object)(object)Instance != (Object)null && Instance.Active)
		{
			Instance._lights = null;
			Instance._lampScanNeeded = true;
			Instance.EnforceLighting();
		}
	}

	internal static void ZeroLampFromPatch(Component lamp)
	{
		if (!((Object)(object)Instance == (Object)null) && Instance.Active && !((Object)(object)lamp == (Object)null) && !IsPlayerOrCameraOwned(lamp.transform))
		{
			SetField(lamp, ((object)lamp).GetType(), "lampActive", false);
			SetField(lamp, ((object)lamp).GetType(), "intensity", 0f);
			SetField(lamp, ((object)lamp).GetType(), "emissiveMult", 0f);
		}
	}

	private void Update()
	{
		if (!_active)
		{
			return;
		}
		try
		{
			if (Time.unscaledTime >= _nextScan)
			{
				_nextScan = Time.unscaledTime + 0.5f;
				EnforceLighting();
			}
			if ((Object)(object)_flashlightObject == (Object)null)
			{
				AttachFlashlight();
				return;
			}
			Light component = _flashlightObject.GetComponent<Light>();
			if ((Object)(object)component != (Object)null && !((Behaviour)component).enabled)
			{
				((Behaviour)component).enabled = true;
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Darkness update failed: " + ex.Message);
			_active = false;
		}
	}

	internal void End()
	{
		//IL_0008: 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)
		_active = false;
		try
		{
			RenderSettings.ambientMode = _originalAmbientMode;
			RenderSettings.ambientLight = _originalAmbient;
			RenderSettings.ambientIntensity = _originalAmbientIntensity;
			RenderSettings.reflectionIntensity = _originalReflection;
			RenderSettings.sun = _originalSun;
			if (_originalLightmaps != null && _originalLightmaps.Length > 0)
			{
				LightmapSettings.lightmaps = _originalLightmaps;
			}
			try
			{
				QualitySettings.pixelLightCount = _originalPixelLights;
			}
			catch
			{
			}
		}
		catch
		{
		}
		if ((Object)(object)_flashlightObject != (Object)null)
		{
			Object.Destroy((Object)(object)_flashlightObject);
			_flashlightObject = null;
		}
	}
}
internal static class DarknessPatches
{
	internal static void Apply(Harmony harmony)
	{
		TryPatch("CL_Lamp:OnEnable", "AfterLampEnable");
		TryPatch("M_Level:OnSpawn", "AfterLevelSpawn");
	}

	private static void TryPatch(string target, string postfixName)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method(target, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("Darkness: " + target + " not found.");
				return;
			}
			MethodInfo method = typeof(DarknessPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic);
			if (!(method == null))
			{
				Harmony val = new Harmony("bugreen.bindings.selected.darkness");
				val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Darkness: patched " + target + ".");
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Darkness patch " + target + " failed: " + ex.Message);
		}
	}

	private static void AfterLampEnable(object __instance)
	{
		Component val = (Component)((__instance is Component) ? __instance : null);
		if ((Object)(object)val != (Object)null)
		{
			DarknessEffect.ZeroLampFromPatch(val);
		}
	}

	private static void AfterLevelSpawn()
	{
		DarknessEffect.EnforceFromPatch();
	}
}
internal class DelusionsEffect : MonoBehaviour
{
	private class ItemVisual
	{
		internal Sprite Sprite;

		internal Item_Object Asset;

		internal HandItem HandItem;

		internal Item_Object Drop;
	}

	private class Snap
	{
		internal readonly List<Sprite> Sprites = new List<Sprite>();

		internal readonly List<Texture> Textures = new List<Texture>();

		internal readonly List<Mesh> Meshes = new List<Mesh>();
	}

	private class Visual
	{
		internal string Key;

		internal GameObject Root;

		internal readonly List<Renderer> Renderers = new List<Renderer>();

		internal readonly List<SpriteRenderer> Sprites = new List<SpriteRenderer>();

		internal readonly List<Renderer> Meshes = new List<Renderer>();

		internal readonly List<MeshFilter> Filters = new List<MeshFilter>();

		internal readonly List<Collider> Colliders = new List<Collider>();
	}

	internal static DelusionsEffect Instance;

	private static readonly string[][] Groups = new string[15][]
	{
		new string[4] { "roach_gold", "roach_lemon", "roach_platinum", "roach_flying_ruby" },
		new string[2] { "roach_platinum_navmesh", "roach_gold_navmesh" },
		new string[7] { "rebarrope_holiday", "rebarrope", "rebar_holiday", "rebar_explosive", "rebar_bone", "rebar", "artifact_rebar_return" },
		new string[5] { "artifact_evaglove", "artifact_rapier", "artifact_remote", "artifact_translocator", "artifact_timepiece" },
		new string[2] { "blinkeye", "blinkeye_marionette" },
		new string[6] { "beans", "beans_periphery", "candycauldron", "cocoa_full", "milk", "wine" },
		new string[9] { "bandage", "rhostone", "food_cookie", "food_bar", "food_fruit", "food_meat", "injector", "inoculator", "pillbottle" },
		new string[4] { "handgun", "handgun_debug", "flaregun", "cryogun" },
		new string[3] { "sluggrub_christmas", "sluggrub_sam", "sluggrub" },
		new string[2] { "10mm_ammo", "flaregun_ammo" },
		new string[7] { "floppy_t1", "floppy_lost", "floppy_t1_notes", "floppy_t1_randomitem", "floppy_t2", "floppy_t3", "floppy_variant" },
		new string[14]
		{
			"trinket_base", "trinket_beta", "trinket_calmingbuddy", "trinket_chalk", "trinket_carabiner", "trinket_climbingshoes", "trinket_employeeid", "trinket_headlamp", "trinket_helmet", "trinket_massdamper",
			"trinket_moonrock", "trinket_nugget", "trinket_photoofhome", "temp"
		},
		new string[5] { "candycauldron_empty", "beans_eaten", "cocoa_empty", "milk_empty", "wine_empty" },
		new string[4] { "grapplepiton", "piton", "piton_holiday", "autopiton" },
		new string[2] { "flashlight", "entityscanner" }
	};

	private bool _active;

	private float _next;

	private int _passes;

	private static bool _runActive;

	private static readonly Dictionary<Item, ItemVisual> Originals = new Dictionary<Item, ItemVisual>();

	private static readonly FieldInfo AssetField = FieldOf("itemAsset");

	private static readonly FieldInfo HandField = FieldOf("handItemAsset");

	private static readonly FieldInfo DropField = FieldOf("dropObject");

	private static bool _loggedExample;

	private float _nextPass;

	private static readonly Dictionary<GameObject, Snap> Snapshots = new Dictionary<GameObject, Snap>();

	private static HashSet<string>[] _groupKeys;

	private static readonly Dictionary<int, List<Item_Object>> PrefabsByGroup = new Dictionary<int, List<Item_Object>>();

	private static bool _preloaded;

	private static readonly Dictionary<string, bool> LoggedNoChange = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

	private static bool _loggedDbType;

	internal static bool ActiveForHooks
	{
		get
		{
			if (!_runActive)
			{
				return BindingState.IsActive("bugreen_delusions");
			}
			return true;
		}
	}

	private void Awake()
	{
		Instance = this;
	}

	internal static void ForceActive()
	{
		_runActive = true;
	}

	internal static void ResetRun()
	{
		_runActive = false;
		RestoreItemData();
	}

	internal void Begin(ENT_Player player)
	{
		_active = BindingState.IsActive("bugreen_delusions") || _runActive;
		_next = 0f;
		_passes = 0;
		if (_active)
		{
			PreloadAllGroups();
			SwapItemData();
		}
	}

	internal void End()
	{
		_active = false;
		RestoreItemData();
	}

	private static FieldInfo FieldOf(string name)
	{
		return typeof(Item).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
	}

	private static ItemVisual Snapshot(Item item)
	{
		ItemVisual itemVisual = new ItemVisual();
		if (item == null)
		{
			return itemVisual;
		}
		itemVisual.Sprite = item.normalSprite;
		itemVisual.Asset = (Item_Object)((AssetField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		itemVisual.HandItem = (HandItem)((HandField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		itemVisual.Drop = (Item_Object)((DropField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		return itemVisual;
	}

	internal static void SwapItemData()
	{
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < Groups.Length; i++)
		{
			List<Item_Object> list = GroupPrefabs(i);
			if (list.Count < 2)
			{
				continue;
			}
			List<Item> list2 = new List<Item>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			for (int j = 0; j < list.Count; j++)
			{
				Item_Object val = list[j];
				if (!((Object)(object)val == (Object)null) && val.itemData != null)
				{
					string text = Key(ItemName(val));
					if (!string.IsNullOrEmpty(text) && hashSet.Add(text))
					{
						list2.Add(val.itemData);
					}
				}
			}
			if (list2.Count < 2)
			{
				continue;
			}
			num2++;
			int num3 = 0;
			List<Visual> list3 = new List<Visual>();
			for (int k = 0; k < list2.Count; k++)
			{
				Visual visual = new Visual();
				visual.Key = Key(ItemName(list2[k]));
				list3.Add(visual);
			}
			int[] array = Derange(list3);
			List<ItemVisual> list4 = new List<ItemVisual>();
			for (int l = 0; l < list2.Count; l++)
			{
				list4.Add(Snapshot(list2[l]));
			}
			for (int m = 0; m < list2.Count; m++)
			{
				Item val2 = list2[m];
				if (val2 == null)
				{
					continue;
				}
				ItemVisual itemVisual = list4[m];
				if (!Originals.ContainsKey(val2))
				{
					Originals[val2] = itemVisual;
				}
				bool flag = false;
				for (int n = 0; n < list2.Count; n++)
				{
					int num4 = (array[m] + n) % list2.Count;
					if (num4 != m && Assign(val2, list4[num4], itemVisual))
					{
						flag = true;
						if (!_loggedExample)
						{
							_loggedExample = true;
							WKLog.Info("Delusions: example '" + Key(ItemName(val2)) + "' now uses the visuals of '" + Key(ItemName(list2[num4])) + "'.");
						}
						break;
					}
				}
				if (flag)
				{
					num++;
					num3++;
				}
			}
			if (num3 != 0)
			{
				continue;
			}
			StringBuilder stringBuilder = new StringBuilder();
			for (int num5 = 0; num5 < list2.Count; num5++)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(Key(ItemName(list2[num5])));
			}
			WKLog.Warn(string.Concat("Delusions: group ", i, " has ", list2.Count, " item(s) but no visual difference [", stringBuilder, "] (they share the same model prefabs)."));
		}
		WKLog.Info("Delusions: item visuals swapped for " + num + " item type(s) in " + num2 + " group(s).");
		if (num != 0)
		{
			return;
		}
		StringBuilder stringBuilder2 = new StringBuilder();
		for (int num6 = 0; num6 < Groups.Length; num6++)
		{
			if (stringBuilder2.Length > 0)
			{
				stringBuilder2.Append(", ");
			}
			stringBuilder2.Append("g").Append(num6).Append(":")
				.Append(GroupPrefabs(num6).Count);
		}
		WKLog.Warn(string.Concat("Delusions: nothing swapped (prefab counts [", stringBuilder2, "], database=", (VanillaAssets.Items() == null) ? "null" : "ok", ")."));
	}

	private static bool Assign(Item target, ItemVisual donor, ItemVisual original)
	{
		if (target == null || donor == null)
		{
			return false;
		}
		bool result = false;
		if ((Object)(object)donor.Sprite != (Object)null)
		{
			target.normalSprite = donor.Sprite;
			if (original != null && (Object)(object)target.normalSprite != (Object)(object)original.Sprite)
			{
				result = true;
			}
		}
		if (AssetField != null && (Object)(object)donor.Asset != (Object)null)
		{
			AssetField.SetValue(target, donor.Asset);
			if (original != null && !object.ReferenceEquals(donor.Asset, original.Asset))
			{
				result = true;
			}
		}
		if (HandField != null && (Object)(object)donor.HandItem != (Object)null)
		{
			HandField.SetValue(target, donor.HandItem);
			if (original != null && !object.ReferenceEquals(donor.HandItem, original.HandItem))
			{
				result = true;
			}
		}
		if (DropField != null && (Object)(object)donor.Drop != (Object)null)
		{
			DropField.SetValue(target, donor.Drop);
			if (original != null && !object.ReferenceEquals(donor.Drop, original.Drop))
			{
				result = true;
			}
		}
		return result;
	}

	internal static void RestoreItemData()
	{
		foreach (KeyValuePair<Item, ItemVisual> original in Originals)
		{
			Item key = original.Key;
			ItemVisual value = original.Value;
			if (key != null && value != null)
			{
				if ((Object)(object)value.Sprite != (Object)null)
				{
					key.normalSprite = value.Sprite;
				}
				if (AssetField != null)
				{
					AssetField.SetValue(key, value.Asset);
				}
				if (HandField != null)
				{
					HandField.SetValue(key, value.HandItem);
				}
				if (DropField != null)
				{
					DropField.SetValue(key, value.Drop);
				}
			}
		}
		Originals.Clear();
	}

	internal static void RequestPass()
	{
		if (!((Object)(object)Instance == (Object)null) && Instance._active)
		{
			Instance._passes = 0;
			Instance._nextPass = 0f;
		}
	}

	private void Update()
	{
		if (!_active || _passes >= 3 || Time.unscaledTime < _nextPass)
		{
			return;
		}
		_nextPass = Time.unscaledTime + ((_passes == 0) ? 4f : 15f);
		_passes++;
		try
		{
			Shuffle();
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions failed: " + ex.Message);
			_active = false;
		}
	}

	private void Shuffle()
	{
		List<Visual> list = CollectScene();
		CaptureSnapshots(list);
		if (_passes == 1)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < list.Count && i < 60; i++)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(list[i].Key);
			}
			WKLog.Info(string.Concat("Delusions: scene keys (", list.Count, "): ", stringBuilder, "."));
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		StringBuilder stringBuilder2 = new StringBuilder();
		for (int j = 0; j < Groups.Length; j++)
		{
			HashSet<string> hashSet = GroupKeys()[j];
			List<Visual> list2 = new List<Visual>();
			for (int k = 0; k < list.Count; k++)
			{
				if (hashSet.Contains(list[k].Key))
				{
					list2.Add(list[k]);
				}
			}
			if (list2.Count >= 2 && DistinctKeys(list2) >= 2)
			{
				num2++;
				num3 += list2.Count;
				if (stringBuilder2.Length > 0)
				{
					stringBuilder2.Append(", ");
				}
				stringBuilder2.Append("g").Append(j).Append(":")
					.Append(list2.Count);
				int[] array = Derange(list2);
				for (int l = 0; l < list2.Count; l++)
				{
					Visual visual = list2[array[l]];
					Snap donor = Snapshots[visual.Root];
					num += ApplyModel(list2[l], donor, visual);
				}
			}
		}
		WKLog.Info(string.Concat("Delusions: ", num3, " item(s) in ", num2, " group(s) [", stringBuilder2, "], replaced ", num, " model part(s)."));
	}

	private static void CaptureSnapshots(List<Visual> scene)
	{
		for (int i = 0; i < scene.Count; i++)
		{
			Visual visual = scene[i];
			if ((Object)(object)visual.Root == (Object)null || Snapshots.ContainsKey(visual.Root))
			{
				continue;
			}
			Snap snap = new Snap();
			for (int j = 0; j < visual.Sprites.Count; j++)
			{
				if ((Object)(object)visual.Sprites[j] != (Object)null && (Object)(object)visual.Sprites[j].sprite != (Object)null)
				{
					snap.Sprites.Add(visual.Sprites[j].sprite);
				}
			}
			for (int k = 0; k < visual.Meshes.Count; k++)
			{
				Renderer val = visual.Meshes[k];
				if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMaterial != (Object)null && (Object)(object)val.sharedMaterial.mainTexture != (Object)null)
				{
					snap.Textures.Add(val.sharedMaterial.mainTexture);
				}
			}
			for (int l = 0; l < visual.Filters.Count; l++)
			{
				if ((Object)(object)visual.Filters[l] != (Object)null && (Object)(object)visual.Filters[l].sharedMesh != (Object)null)
				{
					snap.Meshes.Add(visual.Filters[l].sharedMesh);
				}
			}
			Snapshots[visual.Root] = snap;
		}
	}

	private static HashSet<string>[] GroupKeys()
	{
		if (_groupKeys != null)
		{
			return _groupKeys;
		}
		_groupKeys = new HashSet<string>[Groups.Length];
		for (int i = 0; i < Groups.Length; i++)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			for (int j = 0; j < Groups[i].Length; j++)
			{
				string text = Key(Groups[i][j]);
				if (!string.IsNullOrEmpty(text))
				{
					hashSet.Add(text);
				}
			}
			_groupKeys[i] = hashSet;
		}
		return _groupKeys;
	}

	private static int DistinctKeys(List<Visual> members)
	{
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		for (int i = 0; i < members.Count; i++)
		{
			hashSet.Add(members[i].Key);
		}
		return hashSet.Count;
	}

	private static int[] Derange(List<Visual> members)
	{
		int count = members.Count;
		int[] array = new int[count];
		for (int i = 0; i < 32; i++)
		{
			for (int j = 0; j < count; j++)
			{
				array[j] = j;
			}
			for (int num = count - 1; num > 0; num--)
			{
				int num2 = Random.Range(0, num + 1);
				int num3 = array[num];
				array[num] = array[num2];
				array[num2] = num3;
			}
			bool flag = true;
			for (int k = 0; k < count; k++)
			{
				if (string.Equals(members[k].Key, members[array[k]].Key, StringComparison.OrdinalIgnoreCase))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				return array;
			}
		}
		for (int l = 0; l < count; l++)
		{
			int num4 = l;
			for (int m = 1; m <= count; m++)
			{
				int num5 = (l + m) % count;
				if (!string.Equals(members[l].Key, members[num5].Key, StringComparison.OrdinalIgnoreCase))
				{
					num4 = num5;
					break;
				}
			}
			array[l] = num4;
		}
		return array;
	}

	private static int ApplyModel(Visual target, Snap donor, Visual donorVisual)
	{
		int num = 0;
		for (int i = 0; i < target.Sprites.Count; i++)
		{
			SpriteRenderer val = target.Sprites[i];
			if (!((Object)(object)val == (Object)null) && donor.Sprites.Count != 0)
			{
				Sprite val2 = donor.Sprites[i % donor.Sprites.Count];
				if (!((Object)(object)val2 == (Object)null))
				{
					val.sprite = val2;
					num++;
				}
			}
		}
		for (int j = 0; j < target.Meshes.Count; j++)
		{
			Renderer val3 = target.Meshes[j];
			if ((Object)(object)val3 == (Object)null || donor.Textures.Count == 0)
			{
				continue;
			}
			Texture val4 = donor.Textures[j % donor.Textures.Count];
			if ((Object)(object)val4 == (Object)null)
			{
				continue;
			}
			Material material = val3.material;
			if ((Object)(object)material == (Object)null)
			{
				continue;
			}
			try
			{
				material.mainTexture = val4;
				if (material.HasProperty("_BaseMap"))
				{
					material.SetTexture("_BaseMap", val4);
				}
				if (material.HasProperty("_MainTex"))
				{
					material.SetTexture("_MainTex", val4);
				}
				num++;
			}
			catch
			{
			}
		}
		for (int k = 0; k < target.Filters.Count; k++)
		{
			MeshFilter val5 = target.Filters[k];
			if (!((Object)(object)val5 == (Object)null) && donor.Meshes.Count != 0)
			{
				Mesh val6 = donor.Meshes[k % donor.Meshes.Count];
				if ((Object)(object)val6 != (Object)null)
				{
					val5.sharedMesh = val6;
					num++;
				}
			}
		}
		return num + CopyColliders(target, donorVisual);
	}

	private static int CopyColliders(Visual target, Visual source)
	{
		int num = 0;
		for (int i = 0; i < target.Colliders.Count; i++)
		{
			Collider val = target.Colliders[i];
			if (!((Object)(object)val == (Object)null) && source.Colliders.Count != 0)
			{
				Collider val2 = source.Colliders[i % source.Colliders.Count];
				if (!((Object)(object)val2 == (Object)null) && CopyGeometry(val, val2))
				{
					num++;
				}
			}
		}
		for (int j = target.Colliders.Count; j < source.Colliders.Count; j++)
		{
			Collider val3 = source.Colliders[j];
			if ((Object)(object)val3 == (Object)null || (Object)(object)target.Root == (Object)null)
			{
				continue;
			}
			try
			{
				Component obj = target.Root.AddComponent(((object)val3).GetType());
				Collider val4 = (Collider)(object)((obj is Collider) ? obj : null);
				if ((Object)(object)val4 != (Object)null && CopyGeometry(val4, val3))
				{
					num++;
				}
			}
			catch
			{
			}
		}
		return num;
	}

	private static bool CopyGeometry(Collider target, Collider donor)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || (Object)(object)donor == (Object)null || ((object)target).GetType() != ((object)donor).GetType())
		{
			return false;
		}
		try
		{
			BoxCollider val = (BoxCollider)(object)((target is BoxCollider) ? target : null);
			BoxCollider val2 = (BoxCollider)(object)((donor is BoxCollider) ? donor : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
			{
				val.center = val2.center;
				val.size = val2.size;
				((Collider)val).isTrigger = ((Collider)val2).isTrigger;
				return true;
			}
			SphereCollider val3 = (SphereCollider)(object)((target is SphereCollider) ? target : null);
			SphereCollider val4 = (SphereCollider)(object)((donor is SphereCollider) ? donor : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null)
			{
				val3.center = val4.center;
				val3.radius = val4.radius;
				((Collider)val3).isTrigger = ((Collider)val4).isTrigger;
				return true;
			}
			CapsuleCollider val5 = (CapsuleCollider)(object)((target is CapsuleCollider) ? target : null);
			CapsuleCollider val6 = (CapsuleCollider)(object)((donor is CapsuleCollider) ? donor : null);
			if ((Object)(object)val5 != (Object)null && (Object)(object)val6 != (Object)null)
			{
				val5.center = val6.center;
				val5.radius = val6.radius;
				val5.height = val6.height;
				val5.direction = val6.direction;
				((Collider)val5).isTrigger = ((Collider)val6).isTrigger;
				return true;
			}
			MeshCollider val7 = (MeshCollider)(object)((target is MeshCollider) ? target : null);
			MeshCollider val8 = (MeshCollider)(object)((donor is MeshCollider) ? donor : null);
			if ((Object)(object)val7 != (Object)null && (Object)(object)val8 != (Object)null)
			{
				val7.sharedMesh = val8.sharedMesh;
				val7.convex = val8.convex;
				((Collider)val7).isTrigger = ((Collider)val8).isTrigger;
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	internal static void PreloadAllGroups()
	{
		int num = 0;
		int num2 = 0;
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < Groups.Length; i++)
		{
			List<Item_Object> list = GroupPrefabs(i);
			if (list.Count != 0)
			{
				num++;
				num2 += list.Count;
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append("g").Append(i).Append(":")
					.Append(list.Count);
				for (int j = 0; j < list.Count; j++)
				{
					TouchAssets(list[j]);
				}
			}
		}
		_preloaded = num2 > 0;
		if (num2 == 0)
		{
			IList list2 = null;
			try
			{
				list2 = VanillaAssets.Items();
			}
			catch
			{
			}
			WKLog.Warn("Delusions: preload found 0 prefabs (item database = " + ((list2 == null) ? "null" : list2.Count.ToString()) + ").");
		}
		else
		{
			WKLog.Info(string.Concat("Delusions: preloaded ", num2, " item prefab(s) in ", num, " group(s) [", stringBuilder, "]."));
		}
	}

	private static Item_Object AsItemObject(object entry)
	{
		if (entry == null)
		{
			return null;
		}
		Item_Object val = (Item_Object)((entry is Item_Object) ? entry : null);
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		GameObject val2 = (GameObject)((entry is GameObject) ? entry : null);
		if ((Object)(object)val2 == (Object)null)
		{
			Component val3 = (Component)((entry is Component) ? entry : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val2 = val3.gameObject;
			}
		}
		if ((Object)(object)val2 == (Object)null)
		{
			return null;
		}
		if (!_loggedDbType)
		{
			_loggedDbType = true;
			WKLog.Info("Delusions: item database entries are GameObjects (e.g. " + ((Object)val2).name + ").");
		}
		val = val2.GetComponent<Item_Object>();
		if ((Object)(object)val == (Object)null)
		{
			val = val2.GetComponentInChildren<Item_Object>(true);
		}
		return val;
	}

	private static List<Item_Object> GroupPrefabs(int group)
	{
		if (PrefabsByGroup.TryGetValue(group, out var value))
		{
			return value;
		}
		value = new List<Item_Object>();
		try
		{
			IList list = VanillaAssets.Items();
			int num = 0;
			while (list != null && num < list.Count)
			{
				Item_Object val = AsItemObject(list[num]);
				if (!((Object)(object)val == (Object)null))
				{
					string text = Key(ItemName(val));
					if (text != null && GroupKeys()[group].Contains(text))
					{
						value.Add(val);
					}
				}
				num++;
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions: prefab list failed: " + ex.Message);
		}
		PrefabsByGroup[group] = value;
		return value;
	}

	private static void TouchAssets(Item_Object prefab)
	{
		try
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			if (prefab.itemData != null)
			{
				Sprite normalSprite = prefab.itemData.normalSprite;
				if ((Object)(object)normalSprite != (Object)null && (Object)(object)normalSprite.texture != (Object)null)
				{
					_ = ((Texture)normalSprite.texture).width;
				}
			}
			Renderer[] componentsInChildren = ((Component)prefab).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					SpriteRenderer val2 = (SpriteRenderer)(object)((val is SpriteRenderer) ? val : null);
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2.sprite != (Object)null && (Object)(object)val2.sprite.texture != (Object)null)
					{
						_ = ((Texture)val2.sprite.texture).width;
					}
					if ((Object)(object)val.sharedMaterial != (Object)null && (Object)(object)val.sharedMaterial.mainTexture != (Object)null)
					{
						_ = val.sharedMaterial.mainTexture.width;
					}
				}
			}
		}
		catch
		{
		}
	}

	internal static Sprite RandomSpriteFor(string targetKey)
	{
		int num = GroupIndex(targetKey);
		if (num < 0)
		{
			return null;
		}
		List<Item_Object> list = GroupPrefabs(num);
		List<Item_Object> list2 = new List<Item_Object>();
		for (int i = 0; i < list.Count; i++)
		{
			Item_Object val = list[i];
			if (!((Object)(object)val == (Object)null) && val.itemData != null && !((Object)(object)val.itemData.normalSprite == (Object)null))
			{
				string text = Key(ItemName(val));
				if (!string.IsNullOrEmpty(text) && !string.Equals(text, targetKey, StringComparison.OrdinalIgnoreCase))
				{
					list2.Add(val);
				}
			}
		}
		if (list2.Count == 0)
		{
			return null;
		}
		return list2[Random.Range(0, list2.Count)].itemData.normalSprite;
	}

	internal static bool RandomizeInstance(Item_Object item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		string text = Key(ItemName(item));
		if (text == null)
		{
			return false;
		}
		int num = GroupIndex(text);
		if (num < 0)
		{
			return false;
		}
		List<Item_Object> list = PrefabsInGroup(num, text);
		if (list.Count == 0)
		{
			return false;
		}
		Visual visual = VisualFrom(((Component)item).gameObject);
		Sprite val = ((visual.Sprites.Count == 0 || (Object)(object)visual.Sprites[0] == (Object)null) ? null : visual.Sprites[0].sprite);
		Mesh val2 = ((visual.Filters.Count == 0 || (Object)(object)visual.Filters[0] == (Object)null) ? null : visual.Filters[0].sharedMesh);
		Texture val3 = ((visual.Meshes.Count == 0 || (Object)(object)visual.Meshes[0] == (Object)null || (Object)(object)visual.Meshes[0].sharedMaterial == (Object)null) ? null : visual.Meshes[0].sharedMaterial.mainTexture);
		for (int i = 0; i < list.Count && i < 5; i++)
		{
			int index = Random.Range(i, list.Count);
			Item_Object value = list[i];
			list[i] = list[index];
			list[index] = value;
			Item_Object val4 = list[i];
			if (!((Object)(object)val4 == (Object)null))
			{
				Visual donorVisual = VisualFrom(((Component)val4).gameObject);
				Snap donor = SnapFrom(((Component)val4).gameObject);
				ApplyModel(visual, donor, donorVisual);
				Sprite val5 = ((visual.Sprites.Count == 0 || (Object)(object)visual.Sprites[0] == (Object)null) ? null : visual.Sprites[0].sprite);
				Mesh val6 = ((visual.Filters.Count == 0 || (Object)(object)visual.Filters[0] == (Object)null) ? null : visual.Filters[0].sharedMesh);
				Texture val7 = ((visual.Meshes.Count == 0 || (Object)(object)visual.Meshes[0] == (Object)null || (Object)(object)visual.Meshes[0].sharedMaterial == (Object)null) ? null : visual.Meshes[0].sharedMaterial.mainTexture);
				if ((Object)(object)val5 != (Object)(object)val || (Object)(object)val6 != (Object)(object)val2 || (Object)(object)val7 != (Object)(object)val3)
				{
					WKLog.Info("Delusions: '" + text + "' now looks like '" + Key(ItemName(val4)) + "'.");
					return true;
				}
			}
		}
		if (!LoggedNoChange.ContainsKey(text))
		{
			LoggedNoChange[text] = true;
			WKLog.Warn("Delusions: no visible change for '" + text + "'.");
		}
		return false;
	}

	internal static bool RandomizeItem(Item item)
	{
		if (item == null)
		{
			return false;
		}
		string text = Key(ItemName(item));
		if (text == null)
		{
			return false;
		}
		int num = GroupIndex(text);
		if (num < 0)
		{
			return false;
		}
		List<Item_Object> list = PrefabsInGroup(num, text);
		if (list.Count == 0)
		{
			return false;
		}
		for (int i = 0; i < list.Count && i < 5; i++)
		{
			int index = Random.Range(i, list.Count);
			Item_Object value = list[i];
			list[i] = list[index];
			list[index] = value;
			Item_Object val = list[i];
			if (!((Object)(object)val == (Object)null) && val.itemData != null && !((Object)(object)val.itemData.normalSprite == (Object)null) && !((Object)(object)item.normalSprite == (Object)(object)val.itemData.normalSprite))
			{
				item.normalSprite = val.itemData.normalSprite;
				WKLog.Info("Delusions: item '" + text + "' sprite -> '" + Key(ItemName(val)) + "'.");
				return true;
			}
		}
		return false;
	}

	internal static HandItem RandomHandAssetFor(Item item)
	{
		if (item == null)
		{
			return null;
		}
		string text = Key(ItemName(item));
		if (text == null)
		{
			return null;
		}
		int num = GroupIndex(text);
		if (num < 0)
		{
			return null;
		}
		List<Item_Object> list = GroupPrefabs(num);
		List<HandItem> list2 = new List<HandItem>();
		for (int i = 0; i < list.Count; i++)
		{
			Item_Object val = list[i];
			if ((Object)(object)val == (Object)null || val.itemData == null)
			{
				continue;
			}
			string text2 = Key(ItemName(val));
			if (!string.IsNullOrEmpty(text2) && !string.Equals(text2, text, StringComparison.OrdinalIgnoreCase))
			{
				HandItem val2 = val.itemData.handItemAsset;
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = FindLoadedHandPrefab(text2);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					list2.Add(val2);
				}
			}
		}
		if (list2.Count == 0)
		{
			return null;
		}
		return list2[Random.Range(0, list2.Count)];
	}

	private static HandItem FindLoadedHandPrefab(string key)
	{
		try
		{
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(HandItem));
			foreach (Object obj in array)
			{
				HandItem val = (HandItem)(object)((obj is HandItem) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					string a = Key(((Object)((Component)val).gameObject).name);
					if (string.Equals(a, key, StringComparison.OrdinalIgnoreCase))
					{
						return val;
					}
				}
			}
		}
		catch
		{
		}
		return null;
	}

	private static string ItemName(Item item)
	{
		if (item == null)
		{
			return null;
		}
		if (!string.IsNullOrEmpty(item.prefabName))
		{
			return item.prefabName;
		}
		return item.itemName;
	}

	private static string ItemName(Item_Object item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return null;
		}
		if (item.itemData != null)
		{
			if (!string.IsNullOrEmpty(item.itemData.prefabName))
			{
				return item.itemData.prefabName;
			}
			if (!string.IsNullOrEmpty(item.itemData.itemName))
			{
				return item.itemData.itemName;
			}
		}
		return ((Object)item).name;
	}

	private static int GroupIndex(string key)
	{
		for (int i = 0; i < Groups.Length; i++)
		{
			if (GroupKeys()[i].Contains(key))
			{
				return i;
			}
		}
		return -1;
	}

	private static List<Item_Object> PrefabsInGroup(int group, string selfKey)
	{
		if (!PrefabsByGroup.TryGetValue(group, out var value))
		{
			value = new List<Item_Object>();
			try
			{
				IList list = VanillaAssets.Items();
				int num = 0;
				while (list != null && num < list.Count)
				{
					Item_Object val = AsItemObject(list[num]);
					if (!((Object)(object)val == (Object)null))
					{
						string text = Key(ItemName(val));
						if (text != null && GroupKeys()[group].Contains(text))
						{
							value.Add(val);
						}
					}
					num++;
				}
			}
			catch (Exception ex)
			{
				WKLog.Warn("Delusions: prefab list failed: " + ex.Message);
			}
			PrefabsByGroup[group] = value;
		}
		List<Item_Object> list2 = new List<Item_Object>();
		for (int i = 0; i < value.Count; i++)
		{
			string text2 = Key(ItemName(value[i]));
			if (text2 != null && !string.Equals(text2, selfKey, StringComparison.OrdinalIgnoreCase))
			{
				list2.Add(value[i]);
			}
		}
		return list2;
	}

	private static Visual VisualFrom(GameObject root)
	{
		Visual visual = new Visual();
		visual.Root = root;
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null))
			{
				visual.Renderers.Add(val);
				SpriteRenderer val2 = (SpriteRenderer)(object)((val is SpriteRenderer) ? val : null);
				if ((Object)(object)val2 != (Object)null)
				{
					visual.Sprites.Add(val2);
				}
				else
				{
					visual.Meshes.Add(val);
				}
			}
		}
		MeshFilter[] componentsInChildren2 = root.GetComponentsInChildren<MeshFilter>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			if ((Object)(object)componentsInChildren2[j] != (Object)null)
			{
				visual.Filters.Add(componentsInChildren2[j]);
			}
		}
		Collider[] componentsInChildren3 = root.GetComponentsInChildren<Collider>(true);
		for (int k = 0; k < componentsInChildren3.Length; k++)
		{
			if ((Object)(object)componentsInChildren3[k] != (Object)null)
			{
				visual.Colliders.Add(componentsInChildren3[k]);
			}
		}
		return visual;
	}

	private static Snap SnapFrom(GameObject root)
	{
		Snap snap = new Snap();
		Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			SpriteRenderer val2 = (SpriteRenderer)(object)((val is SpriteRenderer) ? val : null);
			if ((Object)(object)val2 != (Object)null)
			{
				if ((Object)(object)val2.sprite != (Object)null)
				{
					snap.Sprites.Add(val2.sprite);
				}
			}
			else if ((Object)(object)val.sharedMaterial != (Object)null && (Object)(object)val.sharedMaterial.mainTexture != (Object)null)
			{
				snap.Textures.Add(val.sharedMaterial.mainTexture);
			}
		}
		MeshFilter[] componentsInChildren2 = root.GetComponentsInChildren<MeshFilter>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			if ((Object)(object)componentsInChildren2[j] != (Object)null && (Object)(object)componentsInChildren2[j].sharedMesh != (Object)null)
			{
				snap.Meshes.Add(componentsInChildren2[j].sharedMesh);
			}
		}
		return snap;
	}

	private static List<Visual> CollectScene()
	{
		//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)
		List<Visual> list = new List<Visual>();
		HashSet<GameObject> hashSet = new HashSet<GameObject>();
		Object[] array = Object.FindObjectsOfType(typeof(Item_Object));
		foreach (Object obj in array)
		{
			Item_Object val = (Item_Object)(object)((obj is Item_Object) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Scene scene = ((Component)val).gameObject.scene;
			if (!((Scene)(ref scene)).IsValid())
			{
				continue;
			}
			string text = Key(ItemName(val));
			if (text != null && hashSet.Add(((Component)val).gameObject))
			{
				Visual visual = VisualFrom(((Component)val).gameObject);
				visual.Key = text;
				if (visual.Renderers.Count > 0 || visual.Filters.Count > 0)
				{
					list.Add(visual);
				}
			}
		}
		AddDenizens(list, hashSet, typeof(DEN_Roach));
		AddDenizens(list, hashSet, typeof(DEN_GiantRoach));
		AddDenizens(list, hashSet, typeof(DEN_Crawler));
		return list;
	}

	private static void AddDenizens(List<Visual> result, HashSet<GameObject> seen, Type type)
	{
		//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)
		Object[] array = Object.FindObjectsOfType(type);
		foreach (Object obj in array)
		{
			Component val = (Component)(object)((obj is Component) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Scene scene = val.gameObject.scene;
			if (!((Scene)(ref scene)).IsValid())
			{
				continue;
			}
			string text = Key(((Object)val.gameObject).name);
			if (text != null && seen.Add(val.gameObject))
			{
				Visual visual = VisualFrom(val.gameObject);
				visual.Key = text;
				if (visual.Renderers.Count > 0 || visual.Filters.Count > 0)
				{
					result.Add(visual);
				}
			}
		}
	}

	private static List<Visual> CollectSceneLegacy()
	{
		//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)
		List<Visual> list = new List<Visual>();
		HashSet<GameObject> hashSet = new HashSet<GameObject>();
		Object[] array = Resources.FindObjectsOfTypeAll(typeof(GameObject));
		foreach (Object obj in array)
		{
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Scene scene = val.scene;
			if (!((Scene)(ref scene)).IsValid())
			{
				continue;
			}
			Transform parent = val.transform.parent;
			if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponentInParent<Item_Object>() != (Object)null)
			{
				continue;
			}
			Item_Object val2 = val.GetComponent<Item_Object>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.GetComponentInChildren<Item_Object>(true);
			}
			string name = ((Object)val).name;
			if ((Object)(object)val2 != (Object)null && val2.itemData != null)
			{
				if (!string.IsNullOrEmpty(val2.itemData.prefabName))
				{
					name = val2.itemData.prefabName;
				}
				else if (!string.IsNullOrEmpty(val2.itemData.itemName))
				{
					name = val2.itemData.itemName;
				}
			}
			string text = Key(name);
			if (text == null)
			{
				continue;
			}
			GameObject val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : val);
			if (!hashSet.Add(val3))
			{
				continue;
			}
			Visual visual = new Visual();
			visual.Key = text;
			visual.Root = val3;
			Renderer[] componentsInChildren = val3.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren)
			{
				if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val4.sharedMaterial == (Object)null))
				{
					visual.Renderers.Add(val4);
					SpriteRenderer val5 = (SpriteRenderer)(object)((val4 is SpriteRenderer) ? val4 : null);
					if ((Object)(object)val5 != (Object)null)
					{
						visual.Sprites.Add(val5);
					}
					else
					{
						visual.Meshes.Add(val4);
					}
				}
			}
			MeshFilter[] componentsInChildren2 = val3.GetComponentsInChildren<MeshFilter>(true);
			for (int k = 0; k < componentsInChildren2.Length; k++)
			{
				if ((Object)(object)componentsInChildren2[k] != (Object)null && (Object)(object)componentsInChildren2[k].sharedMesh != (Object)null)
				{
					visual.Filters.Add(componentsInChildren2[k]);
				}
			}
			Collider[] componentsInChildren3 = val3.GetComponentsInChildren<Collider>(true);
			for (int l = 0; l < componentsInChildren3.Length; l++)
			{
				if ((Object)(object)componentsInChildren3[l] != (Object)null)
				{
					visual.Colliders.Add(componentsInChildren3[l]);
				}
			}
			if (visual.Renderers.Count > 0 || visual.Filters.Count > 0)
			{
				list.Add(visual);
			}
		}
		return list;
	}

	internal static string Key(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return null;
		}
		string text = name.ToLowerInvariant().Trim().Replace("(clone)", string.Empty)
			.Replace(" ", string.Empty);
		string[] array = new string[16]
		{
			"item_object_", "item_object", "world_item_", "item_hands_", "item_hand_", "handitem_", "hand_item_", "hands_", "hand_", "item_",
			"denizen_", "den_", "env_", "ut_", "cl_", "trinket_"
		};
		bool flag = true;
		while (flag)
		{
			flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				if (text.StartsWith(array[i]))
				{
					text = text.Substring(array[i].Length);
					flag = true;
					break;
				}
			}
		}
		if (!string.IsNullOrEmpty(text))
		{
			return text;
		}
		return null;
	}
}
internal static class DelusionsSpawnPatch
{
	private static readonly HashSet<int> Done = new HashSet<int>();

	private static readonly HashSet<string> LoggedHand = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<string, Sprite> HandChoice = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<int, int> Attempts = new Dictionary<int, int>();

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

	private static readonly HashSet<string> LoggedHandSwap = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static Sprite HandSpriteFor(string key)
	{
		if (HandChoice.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		Sprite val = DelusionsEffect.RandomSpriteFor(key);
		if ((Object)(object)val != (Object)null)
		{
			HandChoice[key] = val;
		}
		return val;
	}

	internal static void Apply(Harmony harmony)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Expected O, but got Unknown
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Expected O, but got Unknown
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Expected O, but got Unknown
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Expected O, but got Unknown
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Expected O, but got Unknown
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("Item_Object:Start", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("Delusions: Item_Object.Start not found.");
				return;
			}
			MethodInfo method = typeof(DelusionsSpawnPatch).GetMethod("AfterStart", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			WKLog.Info("Delusions: patched Item_Object.Start.");
			MethodInfo methodInfo2 = AccessTools.Method("Item_Object:Update", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				MethodInfo method2 = typeof(DelusionsSpawnPatch).GetMethod("BeforeItemUpdate", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched Item_Object.Update.");
			}
			MethodInfo methodInfo3 = AccessTools.Method("M_Level:OnSpawn", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				MethodInfo method3 = typeof(DelusionsSpawnPatch).GetMethod("AfterLevelSpawn", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched M_Level.OnSpawn.");
			}
			MethodInfo methodInfo4 = AccessTools.Method("HandItem:Initialize", (Type[])null, (Type[])null);
			if (methodInfo4 != null)
			{
				MethodInfo method4 = typeof(DelusionsSpawnPatch).GetMethod("AfterHandInitialize", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched HandItem.Initialize.");
			}
			PatchItemLifecycle(harmony, "OnPickup");
			PatchItemLifecycle(harmony, "OnPlaceInInventory");
			PatchItemLifecycle(harmony, "OnPlaceInWorld");
			PatchItemLifecycle(harmony, "OnDrop");
			PatchItemDataProbe(harmony, "InitializeInHand");
			PatchItemDataProbe(harmony, "CreateDropObject");
			PatchHandAssetSwap(harmony);
			MethodInfo methodInfo5 = AccessTools.Method("Hand:SetSprite", (Type[])null, (Type[])null);
			if (methodInfo5 != null)
			{
				MethodInfo method5 = typeof(DelusionsSpawnPatch).GetMethod("AfterSetSprite", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(method5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched Hand.SetSprite.");
			}
			MethodInfo methodInfo6 = AccessTools.Method("M_Gamemode:StartFreshGamemode", (Type[])null, (Type[])null);
			if (methodInfo6 != null)
			{
				MethodInfo method6 = typeof(DelusionsSpawnPatch).GetMethod("BeforeStartFresh", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched M_Gamemode.StartFreshGamemode (preload).");
			}
			MethodInfo methodInfo7 = AccessTools.Method("ENT_Player:HandAnimation", (Type[])null, (Type[])null);
			if (methodInfo7 != null)
			{
				MethodInfo method7 = typeof(DelusionsSpawnPatch).GetMethod("AfterHandAnimation", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(method7), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched ENT_Player.HandAnimation.");
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions spawn patch failed: " + ex.Message);
		}
	}

	private static void PatchItemLifecycle(Harmony harmony, string methodName)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("Item_Object:" + methodName, (Type[])null, (Type[])null);
			if (!(methodInfo == null))
			{
				MethodInfo method = typeof(DelusionsSpawnPatch).GetMethod("AfterItemLifecycle", BindingFlags.Static | BindingFlags.NonPublic);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				WKLog.Info("Delusions: patched Item_Object." + methodName + ".");
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions: Item_Object." + methodName + " patch failed: " + ex.Message);
		}
	}

	private static void PatchItemDataProbe(Harmony harmony, string methodName)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("Item:" + methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("Delusions: Item." + methodName + " not found.");
				return;
			}
			MethodInfo method = typeof(DelusionsSpawnPatch).GetMethod("AfterItemDataProbe", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			WKLog.Info("Delusions: patched Item." + methodName + " (probe).");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions: Item." + methodName + " probe failed: " + ex.Message);
		}
	}

	private static void PatchHandAssetSwap(Harmony harmony)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		try
		{
			MethodInfo methodInfo = AccessTools.Method("Item:InitializeInHand", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				WKLog.Warn("Delusions: Item.InitializeInHand not found (hand swap).");
				return;
			}
			MethodInfo method = typeof(DelusionsSpawnPatch).GetMethod("BeforeInitializeInHand", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			WKLog.Info("Delusions: patched Item.InitializeInHand (hand animation swap).");
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions: hand swap patch failed: " + ex.Message);
		}
	}

	private static void BeforeInitializeInHand(object __instance)
	{
		try
		{
			Item val = (Item)((__instance is Item) ? __instance : null);
			if (val == null || !DelusionsEffect.ActiveForHooks)
			{
				return;
			}
			HandItem val2 = DelusionsEffect.RandomHandAssetFor(val);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			FieldInfo field = typeof(Item).GetField("handItemAsset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null) && !object.ReferenceEquals(field.GetValue(val), val2))
			{
				field.SetValue(val, val2);
				string text = DelusionsEffect.Key(string.IsNullOrEmpty(val.prefabName) ? val.itemName : val.prefabName);
				if (!string.IsNullOrEmpty(text) && LoggedHandSwap.Add(text))
				{
					WKLog.Info("Delusions: hand animation '" + text + "' -> '" + ((Object)val2).name + "'.");
				}
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions hand swap failed: " + ex.Message);
		}
	}

	private static void AfterItemDataProbe(object __instance)
	{
		try
		{
			Item val = (Item)((__instance is Item) ? __instance : null);
			if (val != null && DelusionsEffect.ActiveForHooks)
			{
				string text = DelusionsEffect.Key(string.IsNullOrEmpty(val.prefabName) ? val.itemName : val.prefabName);
				if (!string.IsNullOrEmpty(text) && Probed.Add(text))
				{
					FieldInfo field = typeof(Item).GetField("itemAsset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					FieldInfo field2 = typeof(Item).GetField("handItemAsset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					Object val2 = (Object)((field == null) ? null : /*isinst with value type is only supported in some contexts*/);
					Object val3 = (Object)((field2 == null) ? null : /*isinst with value type is only supported in some contexts*/);
					WKLog.Info("Delusions: probe " + text + " asset=" + ((val2 == (Object)null) ? "<null>" : val2.name) + " hand=" + ((val3 == (Object)null) ? "<null>" : val3.name) + ".");
				}
			}
		}
		catch
		{
		}
	}

	private static void AfterItemLifecycle(object __instance)
	{
		try
		{
			Item_Object val = (Item_Object)((__instance is Item_Object) ? __instance : null);
			if (!((Object)(object)val == (Object)null) && DelusionsEffect.ActiveForHooks && !Done.Contains(((Object)val).GetInstanceID()) && DelusionsEffect.RandomizeInstance(val))
			{
				Done.Add(((Object)val).GetInstanceID());
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions lifecycle failed: " + ex.Message);
		}
	}

	private static void BeforeItemUpdate(object __instance)
	{
		try
		{
			Item_Object val = (Item_Object)((__instance is Item_Object) ? __instance : null);
			if ((Object)(object)val == (Object)null || !DelusionsEffect.ActiveForHooks)
			{
				return;
			}
			int instanceID = ((Object)val).GetInstanceID();
			if (!Done.Contains(instanceID))
			{
				if (!Attempts.ContainsKey(instanceID))
				{
					Attempts[instanceID] = 0;
					WKLog.Info("Delusions: update hook " + ((Object)val).name + " (data=" + ((val.itemData == null) ? "?" : val.itemData.prefabName) + ").");
				}
				Attempts[instanceID] += 1;
				if (DelusionsEffect.RandomizeInstance(val) || Attempts[instanceID] >= 8)
				{
					Done.Add(instanceID);
				}
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions update hook failed: " + ex.Message);
		}
	}

	private static void AfterLevelSpawn(object __instance)
	{
		try
		{
			DelusionsEffect.RequestPass();
			string levelName = null;
			if (__instance != null)
			{
				FieldInfo field = __instance.GetType().GetField("levelName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				levelName = ((field == null) ? null : (field.GetValue(__instance) as string));
			}
			LambdaCatalog.ObserveLevel(levelName);
		}
		catch
		{
		}
	}

	private static void AfterHandAnimation(object __instance)
	{
		try
		{
			if (__instance == null || !DelusionsEffect.ActiveForHooks)
			{
				return;
			}
			FieldInfo field = __instance.GetType().GetField("hands", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Array array = ((field == null) ? null : (field.GetValue(__instance) as Array));
			if (array == null)
			{
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				object value = array.GetValue(i);
				if (value == null)
				{
					continue;
				}
				FieldInfo field2 = value.GetType().GetField("handSprite", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				SpriteRenderer val = (SpriteRenderer)((field2 == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if ((Object)(object)val == (Object)null || (Object)(object)val.sprite == (Object)null)
				{
					continue;
				}
				string text = DelusionsEffect.Key(((Object)val.sprite).name);
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				for (int j = 0; j < 3; j++)
				{
					Sprite val2 = HandSpriteFor(text);
					if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val.sprite)
					{
						val.sprite = val2;
						if (!LoggedHand.Contains(text))
						{
							LoggedHand.Add(text);
							WKLog.Info("Delusions: hand sprite '" + text + "' -> '" + ((Object)val2).name + "'.");
						}
						break;
					}
					HandChoice.Remove(text);
				}
			}
		}
		catch (Exception ex)
		{
			WKLog.Warn("Delusions hand animation failed: " + ex.Message);
		}
	}

	private static void BeforeStartFresh(object __instance)
	{
		try
		{
			DelusionsEffect.PreloadAllGroups();
			HashSet<string> hashSet = VanillaItemGrant.ReadSelectedFromSave(__instance);
			bool flag = false;
			if (hashSet != null)
			{
				foreach (string item in hashSet)
				{
					if (!string.IsNullOrEmpty(item) && item.ToLowerInvariant().Contains("delusions"))
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
			{