Decompiled source of CampfireCards v0.9.6

plugins/CampfireCards/CampfireCards.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CampfireCards.Abilities;
using CampfireCards.Art;
using CampfireCards.Cards;
using CampfireCards.Core;
using CampfireCards.Generated;
using CampfireCards.Net;
using CampfireCards.Ui;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;
using Zorro.ControllerSupport;
using Zorro.Core;
using Zorro.Core.Serizalization;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CampfireCards
{
	public static class Controls
	{
		public enum Act
		{
			BloodBattery,
			SecondWind,
			EmergencyPurge,
			SafetyNet,
			BuildScreen,
			ScavengerFood,
			ScavengerLuggage,
			ScavengerMisc,
			BugReport
		}

		public const string Auto = "auto";

		public const string None = "none";

		private static readonly string[] Candidates = new string[7] { "<Gamepad>/dpad/up", "<Gamepad>/dpad/down", "<Gamepad>/dpad/left", "<Gamepad>/dpad/right", "<Gamepad>/select", "<Gamepad>/leftStickPress", "<Gamepad>/rightStickPress" };

		private static readonly string[] NotGamepad = new string[5] { "<keyboard>", "<mouse>", "<pointer>", "<touchscreen>", "<pen>" };

		private static InputAction[] _pad;

		private static bool _resolved;

		private static bool _watching;

		public static bool UsingGamepad
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				try
				{
					return (int)InputHandler.GetCurrentUsedInputScheme() == 1;
				}
				catch
				{
					return false;
				}
			}
		}

		public static Act? ActOf(string ability)
		{
			return ability switch
			{
				"BloodBattery" => Act.BloodBattery, 
				"SecondWind" => Act.SecondWind, 
				"EmergencyPurge" => Act.EmergencyPurge, 
				"SafetyNet" => Act.SafetyNet, 
				_ => null, 
			};
		}

		public static bool SharesButton(Act a, Act b)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (a == b)
			{
				return true;
			}
			ConfigEntry<Key> val = KeyOf(a);
			ConfigEntry<Key> val2 = KeyOf(b);
			if (val != null && val2 != null && (int)val.Value != 0 && val.Value == val2.Value)
			{
				return true;
			}
			InputAction val3 = PadAction(a);
			InputAction val4 = PadAction(b);
			if (val3 != null && val4 != null)
			{
				InputBinding val5 = val3.bindings[0];
				string text = Control(((InputBinding)(ref val5)).effectivePath);
				val5 = val4.bindings[0];
				return text == Control(((InputBinding)(ref val5)).effectivePath);
			}
			return false;
		}

		public static bool WasPressed(Act act)
		{
			if (KeyPressed(KeyOf(act)))
			{
				return true;
			}
			InputAction val = PadAction(act);
			if (val != null)
			{
				return val.WasPressedThisFrame();
			}
			return false;
		}

		public static bool ProducesText(Act act)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			ConfigEntry<Key> val = KeyOf(act);
			if (val == null || (int)val.Value == 0)
			{
				return false;
			}
			Key value = val.Value;
			if ((int)value < 1 || (int)value > 50)
			{
				if ((int)value >= 77)
				{
					return (int)value <= 93;
				}
				return false;
			}
			return true;
		}

		public static bool IsHeld(Act act)
		{
			if (KeyHeld(KeyOf(act)))
			{
				return true;
			}
			InputAction val = PadAction(act);
			if (val != null)
			{
				return val.IsPressed();
			}
			return false;
		}

		public static string Label(Act act)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (UsingGamepad)
			{
				InputAction val = PadAction(act);
				if (val != null)
				{
					try
					{
						InputBinding val2 = val.bindings[0];
						return InputControlPath.ToHumanReadableString(((InputBinding)(ref val2)).effectivePath, (HumanReadableStringOptions)2, (InputControl)null);
					}
					catch
					{
					}
				}
			}
			ConfigEntry<Key> val3 = KeyOf(act);
			if (val3 == null || (int)val3.Value == 0)
			{
				return "?";
			}
			return ((object)val3.Value/*cast due to .constrained prefix*/).ToString();
		}

		private static ConfigEntry<Key> KeyOf(Act act)
		{
			return (ConfigEntry<Key>)(act switch
			{
				Act.BloodBattery => Plugin.BloodBatteryKey, 
				Act.SecondWind => Plugin.SecondWindKey, 
				Act.EmergencyPurge => Plugin.EmergencyPurgeKey, 
				Act.SafetyNet => Plugin.SafetyNetKey, 
				Act.ScavengerFood => Plugin.ScavengerFoodKey, 
				Act.ScavengerLuggage => Plugin.ScavengerLuggageKey, 
				Act.ScavengerMisc => Plugin.ScavengerMiscKey, 
				Act.BugReport => Plugin.BugReportKey, 
				_ => Plugin.BuildScreenKey, 
			});
		}

		private static ConfigEntry<string> PadOf(Act act)
		{
			return (ConfigEntry<string>)(act switch
			{
				Act.BloodBattery => Plugin.BloodBatteryPad, 
				Act.SecondWind => Plugin.SecondWindPad, 
				Act.EmergencyPurge => Plugin.EmergencyPurgePad, 
				Act.SafetyNet => Plugin.SafetyNetPad, 
				Act.ScavengerFood => Plugin.ScavengerFoodPad, 
				Act.ScavengerLuggage => Plugin.ScavengerLuggagePad, 
				Act.ScavengerMisc => Plugin.ScavengerMiscPad, 
				Act.BugReport => Plugin.BugReportPad, 
				_ => Plugin.BuildScreenPad, 
			});
		}

		private static bool KeyPressed(ConfigEntry<Key> key)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || key == null || (int)key.Value == 0)
			{
				return false;
			}
			try
			{
				KeyControl val = current[key.Value];
				return val != null && ((ButtonControl)val).wasPressedThisFrame;
			}
			catch
			{
				return false;
			}
		}

		private static bool KeyHeld(ConfigEntry<Key> key)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || key == null || (int)key.Value == 0)
			{
				return false;
			}
			try
			{
				KeyControl val = current[key.Value];
				return val != null && ((ButtonControl)val).isPressed;
			}
			catch
			{
				return false;
			}
		}

		private static InputAction PadAction(Act act)
		{
			Resolve();
			if (_pad == null)
			{
				return null;
			}
			return _pad[(int)act];
		}

		private static void Resolve()
		{
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			if (_resolved)
			{
				return;
			}
			InputActionAsset val = null;
			try
			{
				val = InputSystem.actions;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			_resolved = true;
			WatchRebinds();
			Release();
			Act[] array = (Act[])Enum.GetValues(typeof(Act));
			string[] array2 = new string[array.Length];
			HashSet<string> hashSet = GameplayControls(val);
			HashSet<string> hashSet2 = new HashSet<string>(hashSet);
			Act[] array3 = array;
			foreach (Act act in array3)
			{
				ConfigEntry<string> val2 = PadOf(act);
				string text = (array2[(int)act] = ((val2 != null && val2.Value != null) ? val2.Value.Trim() : "auto"));
				if (!IsAuto(text) && !IsNone(text))
				{
					hashSet2.Add(Control(text));
				}
			}
			_pad = (InputAction[])(object)new InputAction[array.Length];
			array3 = array;
			for (int i = 0; i < array3.Length; i++)
			{
				Act act2 = array3[i];
				string text2 = array2[(int)act2];
				string text3 = null;
				if (IsNone(text2))
				{
					continue;
				}
				if (IsAuto(text2))
				{
					string[] candidates = Candidates;
					foreach (string text4 in candidates)
					{
						if (!IsUsed(hashSet2, text4))
						{
							text3 = text4;
							break;
						}
					}
					if (text3 == null)
					{
						Plugin.Log.LogWarning((object)$"No free controller button for {act2}: every candidate is used. Set Keys.{act2}Gamepad to a button path, for example <Gamepad>/dpad/left.");
						continue;
					}
					hashSet2.Add(Control(text3));
				}
				else
				{
					text3 = text2;
					if (IsUsed(hashSet, text3))
					{
						Plugin.Log.LogWarning((object)$"Keys.{act2}Gamepad ({text3}) is also bound to a PEAK action; both will fire.");
					}
				}
				try
				{
					InputAction val3 = new InputAction("CampfireCards_" + act2, (InputActionType)1, text3, (string)null, (string)null, (string)null);
					val3.Enable();
					if (val3.controls.Count == 0 && Gamepad.all.Count > 0)
					{
						Plugin.Log.LogWarning((object)$"Keys.{act2}Gamepad ({text3}) matches no button on the connected controller. Check the path, for example <Gamepad>/dpad/left.");
					}
					_pad[(int)act2] = val3;
					Plugin.Log.LogInfo((object)$"Controller button for {act2}: {text3}");
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)$"Keys.{act2}Gamepad ({text3}) is not a valid button path: {ex.Message}");
				}
			}
		}

		private static bool IsAuto(string w)
		{
			return w.Equals("auto", StringComparison.OrdinalIgnoreCase);
		}

		private static bool IsNone(string w)
		{
			if (w.Length != 0)
			{
				return w.Equals("none", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static void Release()
		{
			if (_pad == null)
			{
				return;
			}
			InputAction[] pad = _pad;
			foreach (InputAction val in pad)
			{
				if (val != null)
				{
					val.Disable();
					val.Dispose();
				}
			}
			_pad = null;
		}

		private static void WatchRebinds()
		{
			if (_watching)
			{
				return;
			}
			_watching = true;
			InputSystem.onActionChange += delegate(object obj, InputActionChange change)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Invalid comparison between Unknown and I4
				if ((int)change == 8)
				{
					InputActionAsset val = null;
					try
					{
						val = InputSystem.actions;
					}
					catch
					{
					}
					if (!((Object)(object)val == (Object)null))
					{
						if (obj != val)
						{
							InputActionMap val2 = (InputActionMap)((obj is InputActionMap) ? obj : null);
							if (val2 == null || !((Object)(object)val2.asset == (Object)(object)val))
							{
								InputAction val3 = (InputAction)((obj is InputAction) ? obj : null);
								if (val3 == null || val3.actionMap == null || !((Object)(object)val3.actionMap.asset == (Object)(object)val))
								{
									return;
								}
							}
						}
						_resolved = false;
					}
				}
			};
		}

		private static HashSet<string> GameplayControls(InputActionAsset asset)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0090: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> hashSet = new HashSet<string>();
			Enumerator<InputActionMap> enumerator = asset.actionMaps.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputActionMap current = enumerator.Current;
					if (string.Equals(current.name, "UI", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					Enumerator<InputAction> enumerator2 = current.actions.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							InputAction current2 = enumerator2.Current;
							if (current2.name.StartsWith("UI", StringComparison.Ordinal) || current2.name.StartsWith("Navigate", StringComparison.Ordinal))
							{
								continue;
							}
							Enumerator<InputBinding> enumerator3 = current2.bindings.GetEnumerator();
							try
							{
								while (enumerator3.MoveNext())
								{
									InputBinding current3 = enumerator3.Current;
									if (((InputBinding)(ref current3)).isComposite)
									{
										continue;
									}
									string effectivePath = ((InputBinding)(ref current3)).effectivePath;
									if (!string.IsNullOrEmpty(effectivePath) && effectivePath[0] == '<')
									{
										int num = effectivePath.IndexOf('>');
										if (num >= 0 && Array.IndexOf(NotGamepad, effectivePath.Substring(0, num + 1).ToLowerInvariant()) < 0)
										{
											hashSet.Add(Control(effectivePath));
										}
									}
								}
							}
							finally
							{
								((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
					}
				}
				return hashSet;
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static bool IsUsed(HashSet<string> used, string path)
		{
			string text = Control(path);
			for (int num = text.Length; num > 0; num = text.LastIndexOf('/', num - 1))
			{
				if (used.Contains(text.Substring(0, num)))
				{
					return true;
				}
			}
			return false;
		}

		private static string Control(string path)
		{
			int num = path.IndexOf('/');
			return ((num >= 0) ? path.Substring(num + 1) : path).ToLowerInvariant();
		}
	}
	public static class RunState
	{
		public static bool OnIsland;

		public static bool RunStarted;

		public static bool SentOpeningArrival;

		public static float GroundedSince = -1f;

		public static readonly HashSet<Campfire> ArrivedFires = new HashSet<Campfire>();

		public static void Reset()
		{
			RunStarted = false;
			SentOpeningArrival = false;
			GroundedSince = -1f;
			ArrivedFires.Clear();
			Effects.Reset();
			Hooks.ResetStatusCarries();
			Hooks.ResetEndGameHold();
			PickSession.Reset();
			Ability_EternalCampfire.Arbiter.Reset();
			NetHandlers.Reset();
			Hooks.ResetRunTracking();
			Hud.ClearMarkers();
			DeckScreen.HideIfOpen();
			BugReportScreen.HideIfOpen();
		}

		public static bool IsGameplayScene(string name)
		{
			if (name != null)
			{
				if (!name.Contains("Island"))
				{
					return name.Contains("Level_");
				}
				return true;
			}
			return false;
		}
	}
	public static class Hooks
	{
		private sealed class ItemUse
		{
			public Item Item;

			public int Frame;

			public bool Food;

			public bool Cooked;

			public bool Curative;

			public float Hunger;

			public float InjuryBefore;

			public readonly HashSet<STATUSTYPE> Cured = new HashSet<STATUSTYPE>();
		}

		private sealed class BarCapture
		{
			public RectTransform Segments;

			public float SegmentsRight;

			public RectTransform Overflow;

			public float OverflowX;

			public float FrameWidth;

			public bool Moved;
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static Action<Character> <0>__OnCharacterRegistered;

			public static UnityAction<Scene, LoadSceneMode> <1>__OnSceneLoaded;

			public static WillRenderCanvases <2>__ApplyPendingBarFrame;

			public static Action<EventData> <3>__OnPhotonEvent;
		}

		private static float _nextArrivalCheck;

		private static float _nextAbilityBar;

		private static bool _photonSubscribed;

		private static bool? _tfaPresent;

		private static readonly Dictionary<Campfire, byte> _fireKeys = new Dictionary<Campfire, byte>();

		private static int _chainKeysTaken;

		internal const byte ChainKeyFirst = 200;

		internal const int ChainKeyRange = 50;

		private static bool _overlayModsChecked;

		private static readonly HashSet<int> _unreadableFrom = new HashSet<int>();

		private static bool _wasHost;

		private static int _lastSegmentNumber = int.MinValue;

		private static readonly FieldRef<ItemActionBase, Item> ActionItem = AccessTools.FieldRefAccess<ItemActionBase, Item>("item");

		private static readonly List<ItemUse> _batches = new List<ItemUse>();

		private static readonly string[] MedicalItemNames = new string[10] { "Bandages", "FirstAidKit", "Antidote", "Cure-All", "MedicinalRoot", "Mandrake_Hidden", "AloeVera", "Heat Pack", "Amulet_Healing", "HealingDart Variant" };

		private static HashSet<ushort> _medicalIds;

		private static readonly ItemTransaction _lunch = new ItemTransaction();

		public const int LockedPocket = 2;

		private static readonly Dictionary<byte, Campfire> _litFires = new Dictionary<byte, Campfire>();

		private static readonly SpawnLedger _spawns = new SpawnLedger();

		private const float MaxSpawnDistance = 7f;

		private static readonly FieldRef<CharacterClimbing, Character> ClimbingCharacter = AccessTools.FieldRefAccess<CharacterClimbing, Character>("character");

		private static readonly FieldRef<CharacterRopeHandling, Character> RopeCharacter = AccessTools.FieldRefAccess<CharacterRopeHandling, Character>("character");

		private static readonly FieldRef<CharacterVineClimbing, Character> VineCharacter = AccessTools.FieldRefAccess<CharacterVineClimbing, Character>("character");

		private static readonly FieldRef<CharacterGrabbing, Character> GrabbingCharacter = AccessTools.FieldRefAccess<CharacterGrabbing, Character>("character");

		private static readonly FieldRef<CharacterMovement, Character> MovementCharacter = AccessTools.FieldRefAccess<CharacterMovement, Character>("character");

		[ThreadStatic]
		private static Character _climbCtx;

		[ThreadStatic]
		private static int _climbDepth;

		[ThreadStatic]
		private static float _slideBefore;

		[ThreadStatic]
		private static bool _slideTracked;

		private static Character _pullLatchHelper;

		private static float _pullLatchExpire;

		private static readonly Action<Character, Vector3, float> DragTowards = AccessTools.MethodDelegate<Action<Character, Vector3, float>>(AccessTools.Method(typeof(Character), "DragTowards", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Character> LimitFalling = AccessTools.MethodDelegate<Action<Character>>(AccessTools.Method(typeof(Character), "LimitFalling", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Character> UnStick = AccessTools.MethodDelegate<Action<Character>>(AccessTools.Method(typeof(Character), "UnStick", (Type[])null, (Type[])null), (object)null, true);

		[ThreadStatic]
		private static int _dynamiteSpawnDepth;

		[ThreadStatic]
		private static bool _dynamiteBlast;

		private static int _lastFeederActor = int.MinValue;

		private static float _lastFedTime;

		private static float _endGameHoldUntil;

		private static Character _endGameRecheck;

		private static readonly FieldRef<CharacterHeatEmission, Character> HeatEmissionCharacter = AccessTools.FieldRefAccess<CharacterHeatEmission, Character>("character");

		private static readonly FieldRef<CharacterHeatEmission, float> HeatEmissionCounter = AccessTools.FieldRefAccess<CharacterHeatEmission, float>("counter");

		private static readonly FieldRef<CharacterAfflictions, bool> AfflictionsInAirport = AccessTools.FieldRefAccess<CharacterAfflictions, bool>("m_inAirport");

		private static readonly FieldRef<CharacterData, bool> NativeInvincible = AccessTools.FieldRefAccess<CharacterData, bool>("isInvincible");

		private static readonly FieldRef<CharacterAfflictions, float[]> IncrementalStatuses = AccessTools.FieldRefAccess<CharacterAfflictions, float[]>("currentIncrementalStatuses");

		private static readonly FieldRef<CharacterAfflictions, float[]> DecrementalStatuses = AccessTools.FieldRefAccess<CharacterAfflictions, float[]>("currentDecrementalStatuses");

		private static readonly int StatusCount = Enum.GetValues(typeof(STATUSTYPE)).Length;

		private static readonly StatusCarry AddCarry = new StatusCarry(StatusCount);

		private static readonly StatusCarry SubCarry = new StatusCarry(StatusCount);

		private static float _petrifyCarry;

		[ThreadStatic]
		internal static int _itemActionDepth;

		[ThreadStatic]
		internal static bool _itemScaled;

		[ThreadStatic]
		private static int _fallDepth;

		[ThreadStatic]
		private static Character _heatEmitter;

		[ThreadStatic]
		private static Character _regenChar;

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

		private static float _injuryCommitted;

		private static readonly Action<Character, Vector3, Vector3, float> AddForceAt = AccessTools.MethodDelegate<Action<Character, Vector3, Vector3, float>>(AccessTools.Method(typeof(Character), "AddForceAtPosition", (Type[])null, (Type[])null), (object)null, true);

		private static readonly FieldRef<StatusFieldBase, float> FieldLastEntered = AccessTools.FieldRefAccess<StatusFieldBase, float>("lastEnteredTime");

		private static readonly FieldRef<StatusFieldBase, bool> FieldInflicting = AccessTools.FieldRefAccess<StatusFieldBase, bool>("inflicting");

		private static readonly FieldRef<StatusFieldBase, bool> FieldInField = AccessTools.FieldRefAccess<StatusFieldBase, bool>("characterInField");

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

		private static StaminaBar _barToStyle;

		private static readonly ThornsLedger _thorns = new ThornsLedger();

		internal static bool TfaPresent
		{
			get
			{
				if (!_tfaPresent.HasValue)
				{
					try
					{
						_tfaPresent = Chainloader.PluginInfos.ContainsKey("com.CptPICHU.peak.truefinalascent");
					}
					catch
					{
						_tfaPresent = false;
					}
				}
				return _tfaPresent.Value;
			}
		}

		public static float PendingInjuryCarry => AddCarry.Of(0);

		public static void Subscribe()
		{
			//IL_005f: 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)
			//IL_006a: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			PlayerHandler.CharacterRegistered = (Action<Character>)Delegate.Combine(PlayerHandler.CharacterRegistered, new Action<Character>(OnCharacterRegistered));
			SceneManager.sceneLoaded += OnSceneLoaded;
			object obj = <>O.<2>__ApplyPendingBarFrame;
			if (obj == null)
			{
				WillRenderCanvases val = ApplyPendingBarFrame;
				<>O.<2>__ApplyPendingBarFrame = val;
				obj = (object)val;
			}
			Canvas.willRenderCanvases -= (WillRenderCanvases)obj;
			object obj2 = <>O.<2>__ApplyPendingBarFrame;
			if (obj2 == null)
			{
				WillRenderCanvases val2 = ApplyPendingBarFrame;
				<>O.<2>__ApplyPendingBarFrame = val2;
				obj2 = (object)val2;
			}
			Canvas.willRenderCanvases += (WillRenderCanvases)obj2;
			SubscribePhoton();
		}

		private static void SubscribePhoton()
		{
			if (!_photonSubscribed)
			{
				LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient;
				if (networkingClient != null)
				{
					networkingClient.EventReceived += OnPhotonEvent;
					_photonSubscribed = true;
				}
			}
		}

		private static IEnumerator ResubscribeNextFrame()
		{
			yield return null;
			SubscribePhoton();
		}

		public static void ResetRunTracking()
		{
			_lastFeederActor = int.MinValue;
			_fallDepth = 0;
			_climbDepth = 0;
			_climbCtx = null;
			_batches.Clear();
			_thorns.Reset();
			_lunch.Reset();
			_dynamiteSpawnDepth = 0;
			_dynamiteBlast = false;
			_lastSegmentNumber = int.MinValue;
			_fireKeys.Clear();
			_chainKeysTaken = 0;
			ResetCampfireSpawns();
		}

		public static void OnRunStarted()
		{
			RunState.Reset();
			RunState.RunStarted = true;
			RunState.OnIsland = true;
			LocalCards.OnRunStarted(Environment.TickCount ^ (NetSend.LocalActor * 7919));
			RunMemoryFile.OnRunStarted(LocalCards.RunSeed);
			PickSession.OnRunStarted();
			Hud.Ensure();
			_wasHost = NetSend.IsHost;
			RecordRoster();
			if (!NetSend.IsHost)
			{
				NetSend.Raise(NetHandlers.MakeHello(), (ReceiverGroup)0);
			}
			Plugin.Log.LogInfo((object)$"Run started. Host={NetSend.IsHost} actor={NetSend.LocalActor} solo={NetSend.IsSolo} deck={Deck.Count} cards");
			WarnOverlayMods();
		}

		public static void OnRunEnded()
		{
			RunState.Reset();
			RunMemoryFile.OnRunEnded();
			Hud.CloseAll();
		}

		public static void OnCampfireLitPrefix(Campfire __instance, bool updateSegment, out FireState __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected I4, but got Unknown
			__state = (FireState)(int)__instance.state;
			if ((int)__state != 1 && RunState.RunStarted)
			{
				if (TfaPresent)
				{
					PickSession.CapturePreLitEligibility();
				}
				if (updateSegment)
				{
					PickSession.SnapshotCampfireEligibility(FireKey(__instance));
				}
			}
		}

		public static void OnCampfireLit(Campfire __instance, bool updateSegment, float burningFor, FireState __state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			if ((int)__state == 1 || !RunState.RunStarted)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			byte b = FireKey(__instance);
			byte b2 = b;
			bool flag = false;
			if (!updateSegment)
			{
				if (!TfaPresent)
				{
					return;
				}
				bool flag2 = burningFor <= 0.01f && PhotonNetwork.Time - PickSession.RunStartTime > 20.0;
				Plugin.Log.LogInfo((object)($"Campfire lit without a segment advance (burningFor {burningFor:0.##}): " + (flag2 ? "chained-run biome fire" : "sync relight, ignored")));
				if (!flag2)
				{
					return;
				}
				flag = true;
			}
			else if (TfaPresent && PickSession.SegmentUsed(b))
			{
				flag = true;
			}
			bool flag3 = true;
			if (flag)
			{
				if (!PollBiomeNow(localCharacter) && (Object)(object)localCharacter != (Object)null)
				{
					LocalCards.OnChainBoundary(localCharacter);
				}
				if (NetSend.IsHost)
				{
					int num = TakeFreeChainKey();
					if (num < 0)
					{
						flag3 = false;
						Plugin.Log.LogWarning((object)"Chain keys exhausted; this fire deals no cards");
					}
					else
					{
						b2 = (byte)num;
						PickSession.AdoptPreLitEligibility(b2);
						_fireKeys[__instance] = b2;
					}
				}
			}
			else
			{
				_fireKeys[__instance] = b2;
			}
			Plugin.Log.LogInfo((object)$"Campfire lit -> {__instance.advanceToSegment} (key {b2})");
			if (NetSend.IsHost)
			{
				HostCampfireLit(__instance, b);
			}
			if ((Object)(object)localCharacter != (Object)null)
			{
				LocalCards.OnCampfireLit(localCharacter, __instance);
			}
			if (flag3 && (!TfaPresent || NetSend.IsHost))
			{
				PickSession.RequestSession(1, b2);
			}
		}

		private static void WarnOverlayMods()
		{
			if (_overlayModsChecked)
			{
				return;
			}
			_overlayModsChecked = true;
			try
			{
				foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
				{
					string text = ((pluginInfo.Value != null && pluginInfo.Value.Metadata != null) ? pluginInfo.Value.Metadata.Name : null);
					if (text != null && text.IndexOf("EffectPreview", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						Plugin.Log.LogInfo((object)(text + " detected: its stamina-bar overlay may not line up with card-extended stamina bars"));
					}
				}
			}
			catch
			{
			}
		}

		internal static byte FireKey(Campfire fire)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)fire != (Object)null && _fireKeys.TryGetValue(fire, out var value))
			{
				return value;
			}
			int num = (((Object)(object)fire != (Object)null) ? ((int)fire.advanceToSegment) : 0);
			return (byte)((num >= 255) ? 254u : ((uint)num));
		}

		private static int TakeFreeChainKey()
		{
			for (int i = 0; i < 50; i++)
			{
				byte b = (byte)(200 + _chainKeysTaken++ % 50);
				if (!PickSession.SegmentUsed(b))
				{
					return b;
				}
			}
			return -1;
		}

		public static void OnLobbyCreated(SteamLobbyHandler __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CSteamID lobbySteamId = __instance.LobbySteamId;
				if (((CSteamID)(ref lobbySteamId)).IsValid())
				{
					HostLog.WriteHosting(lobbySteamId.m_SteamID);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("HostLog: " + ex.Message));
			}
		}

		public static void OnCharacterRegistered(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return;
			}
			try
			{
				int actor = NetSend.ActorOf(c);
				if (c.IsLocal)
				{
					if (!NetSend.IsHost && !Effects.HasAnyState)
					{
						NetSend.RaiseToMaster(NetHandlers.MakeHello());
						NetSend.RaiseToMaster(new StateRequest
						{
							modVersion = "0.9.6"
						});
					}
				}
				else if (NetSend.IsHost)
				{
					PickSession.HostNoteReady(actor, arrived: false);
					HostAdoptRejoiners();
					if (Effects.HasAnyState)
					{
						NetSend.RaiseTo(Effects.BuildStateSync(PickSession.SessionId), actor);
					}
					if (PickSession.HasMirror)
					{
						NetSend.RaiseTo(PickSession.BuildMirror(), actor);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("OnCharacterRegistered: " + ex));
			}
		}

		internal static void HostAdoptRejoiners()
		{
			if (!NetSend.IsHost || !RunState.RunStarted)
			{
				return;
			}
			Room currentRoom = PhotonNetwork.CurrentRoom;
			if (currentRoom == null)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (Player value2 in currentRoom.Players.Values)
			{
				list.Add(value2.ActorNumber);
			}
			bool flag = false;
			foreach (Player value3 in currentRoom.Players.Values)
			{
				foreach (int item in PickSession.Directory.DepartedTwins(value3.ActorNumber, value3.UserId, list))
				{
					if ((Effects.CardsByActor.TryGetValue(item, out var value) && value.Count > 0) || Effects.Flags(item) != 0 || Effects.Penalties.Count(item) != 0)
					{
						Effects.TransferActorState(item, value3.ActorNumber);
						PickSession.OnActorReplaced(item, value3.ActorNumber);
						Ability_EternalCampfire.Arbiter.Transfer(item, value3.ActorNumber);
						_spawns.Transfer(item, value3.ActorNumber);
						flag = true;
						Plugin.Log.LogInfo((object)$"Rejoin: moved {Effects.CardsOf(value3.ActorNumber).Count} card(s) back to {NetSend.NameOf(value3.ActorNumber)} (actor {item} -> {value3.ActorNumber})");
					}
				}
			}
			if (flag)
			{
				NetSend.Raise(Effects.BuildStateSync(PickSession.SessionId), (ReceiverGroup)1);
			}
		}

		private static void RecordRoster()
		{
			Room currentRoom = PhotonNetwork.CurrentRoom;
			if (currentRoom == null)
			{
				return;
			}
			List<int> list = new List<int>();
			foreach (Player value in currentRoom.Players.Values)
			{
				list.Add(value.ActorNumber);
			}
			foreach (Player value2 in currentRoom.Players.Values)
			{
				foreach (int item in PickSession.Directory.DepartedTwins(value2.ActorNumber, value2.UserId, list))
				{
					PickSession.OnActorReplaced(item, value2.ActorNumber);
				}
				PickSession.Directory.Record(value2.ActorNumber, value2.UserId);
			}
		}

		public static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ResetBarCaptures();
			if (!(RunState.OnIsland = RunState.IsGameplayScene(((Scene)(ref scene)).name)))
			{
				RunState.Reset();
				Hud.CloseAll();
			}
			Plugin.Run(ResubscribeNextFrame());
		}

		public static void OnPhotonEvent(EventData e)
		{
			try
			{
				if (e.Code == 254)
				{
					PickSession.OnPlayerLeft(e.Sender);
					if (NetSend.IsHost)
					{
						Ability_EternalCampfire.Arbiter.ForgetVictim(e.Sender);
					}
					_unreadableFrom.Remove(e.Sender);
				}
				else
				{
					if (e.Code < 90 || e.Code > 119 || !(e.CustomData is byte[] data))
					{
						return;
					}
					try
					{
						NetDispatcher.Dispatch(e.Code, data, e.Sender);
						return;
					}
					catch (Exception ex) when (ex is IOException || ex is InvalidDataException || ex is FormatException)
					{
						Plugin.Log.LogWarning((object)$"Net event {e.Code} from actor {e.Sender} could not be read: {ex.Message}");
						if (_unreadableFrom.Add(e.Sender))
						{
							Hud.Toast($"Can't read Campfire Cards data from {NetSend.NameOf(e.Sender)}. Everyone needs the same mod version.", warning: true);
						}
						return;
					}
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Net event {e.Code}: {arg}");
			}
		}

		public static void Tick()
		{
			_fallDepth = 0;
			_climbDepth = 0;
			_climbCtx = null;
			_itemActionDepth = 0;
			_itemScaled = false;
			CardSettings.Current.BenefitStrength = (RunState.OnIsland ? CardSettings.Current.StrengthFor(Ascents.currentAscent) : 1f);
			if (!RunState.OnIsland)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Hud.Ensure();
			if (!RunState.RunStarted)
			{
				return;
			}
			if (!_wasHost && NetSend.IsHost)
			{
				_wasHost = true;
				PickSession.HostPromotedSweep();
			}
			RestoreKey(localCharacter);
			PollBiome(localCharacter);
			Effects.Recompute(localCharacter);
			SampleInjuryCapFloor(localCharacter);
			LocalCards.Tick(localCharacter, Time.deltaTime);
			FlushItemUses(localCharacter);
			AbilityKeys(localCharacter);
			PickSession.HostTick();
			DeckScreen.Tick(localCharacter);
			BugReportScreen.Tick();
			TickEndGameHold();
			if (Time.unscaledTime >= _nextAbilityBar)
			{
				_nextAbilityBar = Time.unscaledTime + 0.2f;
				Hud.RefreshAbilityBar(localCharacter);
				PickSession.UpdateBanner();
			}
			if (!(Time.unscaledTime < _nextArrivalCheck))
			{
				_nextArrivalCheck = Time.unscaledTime + 0.25f;
				RecordRoster();
				if (NetSend.IsHost)
				{
					HostAdoptRejoiners();
				}
				CheckArrivals(localCharacter);
			}
		}

		private static void PollBiome(Character local)
		{
			PollBiomeNow(local);
		}

		private static bool PollBiomeNow(Character local)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			if ((Object)(object)local == (Object)null)
			{
				return false;
			}
			int num;
			try
			{
				num = (int)MapHandler.CurrentSegmentNumber;
			}
			catch
			{
				return false;
			}
			if (num == _lastSegmentNumber)
			{
				return false;
			}
			_lastSegmentNumber = num;
			LocalCards.OnSegmentNumber(local, num);
			return true;
		}

		private static void AbilityKeys(Character local)
		{
			bool flag = false;
			try
			{
				flag = (Object)(object)GUIManager.instance != (Object)null && (GUIManager.instance.windowBlockingInput || GUIManager.instance.wheelActive);
			}
			catch
			{
			}
			if (flag)
			{
				return;
			}
			if (!local.data.dead && !local.data.passedOut && !local.data.fullyPassedOut)
			{
				HashSet<Controls.Act> hashSet = new HashSet<Controls.Act>();
				foreach (Ability item in LocalCards.Manual)
				{
					Controls.Act? act = Controls.ActOf(item.Card.Ability);
					if (!act.HasValue || !hashSet.Add(act.Value) || !Controls.WasPressed(act.Value))
					{
						continue;
					}
					List<Ability> list = new List<Ability>();
					foreach (Ability item2 in LocalCards.Manual)
					{
						Controls.Act? act2 = Controls.ActOf(item2.Card.Ability);
						if (act2.HasValue && Controls.SharesButton(act.Value, act2.Value))
						{
							list.Add(item2);
						}
					}
					if (list.Count > 1)
					{
						Hud.Toast("These abilities share a key. Assign separate keys in the config.", warning: true);
						break;
					}
					try
					{
						item.Activate(local);
					}
					catch (Exception arg)
					{
						Plugin.Log.LogError((object)$"{item.Card.Name} Activate: {arg}");
					}
				}
			}
			if (Controls.WasPressed(Controls.Act.BuildScreen))
			{
				DeckScreen.Toggle(local);
			}
			if (Controls.WasPressed(Controls.Act.BugReport))
			{
				BugReportScreen.Toggle();
			}
		}

		public static bool OnUpdatePausedPrefix(GUIManager __instance)
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.input == (Object)null || !localCharacter.input.pauseWasPressed)
			{
				return true;
			}
			if ((Object)(object)DeckScreen.Instance != (Object)null && ((MenuWindow)DeckScreen.Instance).isOpen)
			{
				localCharacter.input.pauseWasPressed = false;
				DeckScreen.Instance.BackFromInput();
				return false;
			}
			if (ItemChooser.IsOpen)
			{
				localCharacter.input.pauseWasPressed = false;
				ItemChooser.Instance.HideNow();
				return false;
			}
			if ((Object)(object)BugReportScreen.Instance != (Object)null && ((MenuWindow)BugReportScreen.Instance).isOpen)
			{
				localCharacter.input.pauseWasPressed = false;
				BugReportScreen.Instance.CloseFromInput();
				return false;
			}
			return true;
		}

		private static void CheckArrivals(Character local)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if (!RunState.SentOpeningArrival)
			{
				if (local.data.passedOutOnTheBeach <= 0f && !local.warping && local.data.isGrounded && !local.data.passedOut)
				{
					if (RunState.GroundedSince < 0f)
					{
						RunState.GroundedSince = Time.unscaledTime;
					}
					if (Time.unscaledTime - RunState.GroundedSince >= 2f)
					{
						RunState.SentOpeningArrival = true;
						NetSend.Raise(new Arrival
						{
							segment = byte.MaxValue,
							time = PhotonNetwork.Time
						}, (ReceiverGroup)0);
						PickSession.RecordArrival(NetSend.LocalActor, byte.MaxValue, PhotonNetwork.Time);
					}
				}
				else
				{
					RunState.GroundedSince = -1f;
				}
			}
			Campfire val = null;
			try
			{
				val = MapHandler.CurrentCampfire;
			}
			catch
			{
			}
			if ((Object)(object)val != (Object)null && !val.Lit && !RunState.ArrivedFires.Contains(val))
			{
				float num = ((val.moraleBoostRadius > 0f) ? val.moraleBoostRadius : 15f);
				if (Vector3.Distance(local.Center, ((Component)val).transform.position) <= num)
				{
					byte segment = FireKey(val);
					RunState.ArrivedFires.Add(val);
					NetSend.Raise(new Arrival
					{
						segment = segment,
						time = PhotonNetwork.Time
					}, (ReceiverGroup)0);
					PickSession.RecordArrival(NetSend.LocalActor, segment, PhotonNetwork.Time);
				}
			}
		}

		private static void RestoreKey(Character local)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<Key> restoreRunKey = Plugin.RestoreRunKey;
			Keyboard current = Keyboard.current;
			if (current == null || restoreRunKey == null || (int)restoreRunKey.Value == 0)
			{
				return;
			}
			bool flag = false;
			try
			{
				flag = (Object)(object)GUIManager.instance != (Object)null && (GUIManager.instance.windowBlockingInput || GUIManager.instance.wheelActive);
			}
			catch
			{
			}
			if (flag)
			{
				return;
			}
			KeyControl val = null;
			try
			{
				val = current[restoreRunKey.Value];
			}
			catch
			{
			}
			if (val != null && ((ButtonControl)val).wasPressedThisFrame)
			{
				if (!NetSend.IsHost)
				{
					Hud.Toast("Card restore: only the host can restore the run");
				}
				else
				{
					RunMemoryFile.RestoreAll();
				}
			}
		}

		private static ItemUse Batch(Item item, Character user)
		{
			foreach (ItemUse batch in _batches)
			{
				if ((Object)(object)batch.Item == (Object)(object)item && batch.Frame == Time.frameCount)
				{
					return batch;
				}
			}
			ItemUse itemUse = new ItemUse
			{
				Item = item,
				Frame = Time.frameCount,
				InjuryBefore = user.refs.afflictions.GetCurrentStatus((STATUSTYPE)0)
			};
			_batches.Add(itemUse);
			return itemUse;
		}

		private static void FlushItemUses(Character local)
		{
			for (int num = _batches.Count - 1; num >= 0; num--)
			{
				ItemUse itemUse = _batches[num];
				if (itemUse.Frame < Time.frameCount)
				{
					_batches.RemoveAt(num);
					if (itemUse.Food)
					{
						Plugin.Verbose(string.Format("Ate {0}: cooked={1}, Hunger removed {2:0.#}", ((Object)(object)itemUse.Item != (Object)null) ? itemUse.Item.GetItemName((ItemInstanceData)null) : "?", itemUse.Cooked, itemUse.Hunger * 100f));
					}
					if (itemUse.Food)
					{
						LocalCards.OnFood(local, new FoodEvent
						{
							Item = itemUse.Item,
							Cooked = itemUse.Cooked,
							HungerRemoved = itemUse.Hunger,
							InjuryBefore = itemUse.InjuryBefore
						});
					}
					if (itemUse.Curative)
					{
						LocalCards.OnCurative(local, new CurativeEvent
						{
							Item = itemUse.Item,
							Cured = itemUse.Cured
						});
					}
				}
			}
		}

		public static bool IsCooked(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			try
			{
				IntItemData val = default(IntItemData);
				if (item.data != null && item.data.TryGetDataEntry<IntItemData>((DataEntryKey)1, ref val))
				{
					return val.Value > 0;
				}
				return (Object)(object)item.cooking != (Object)null && item.cooking.timesCookedLocal > 0;
			}
			catch
			{
				return false;
			}
		}

		public static bool IsFood(Item item)
		{
			if ((Object)(object)item != (Object)null)
			{
				return (Object)(object)((Component)item).GetComponent<Action_RestoreHunger>() != (Object)null;
			}
			return false;
		}

		public static bool IsCurativeItem(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			if (_medicalIds == null || _medicalIds.Count == 0)
			{
				HashSet<ushort> hashSet = new HashSet<ushort>();
				string[] medicalItemNames = MedicalItemNames;
				Item val = default(Item);
				for (int i = 0; i < medicalItemNames.Length; i++)
				{
					if (ItemDatabase.TryGetItem(medicalItemNames[i], ref val) && (Object)(object)val != (Object)null)
					{
						hashSet.Add(val.itemID);
					}
				}
				if (hashSet.Count == 0)
				{
					return false;
				}
				_medicalIds = hashSet;
			}
			return _medicalIds.Contains(item.itemID);
		}

		public static void OnRestoreHungerPrefix(Action_RestoreHunger __instance, out float __state)
		{
			__state = __instance.restorationAmount;
			_itemActionDepth++;
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (Mine(val2))
			{
				bool cooked = IsCooked(val);
				float num = StatComposites.FoodNutrition(Effects.Local, cooked);
				if (__state > 0f && Mathf.Abs(num - 1f) > 0.0001f)
				{
					__instance.restorationAmount = __state * num;
					_itemScaled = true;
				}
				ItemUse itemUse = Batch(val, val2);
				itemUse.Food = true;
				itemUse.Cooked = cooked;
				itemUse.Hunger += __instance.restorationAmount;
			}
		}

		public static void OnRestoreHunger(Action_RestoreHunger __instance, float __state)
		{
			__instance.restorationAmount = __state;
			if (_itemActionDepth > 0)
			{
				_itemActionDepth--;
			}
			_itemScaled = false;
		}

		public static void OnModifyStatusActionPrefix(Action_ModifyStatus __instance, out float __state)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			__state = __instance.changeAmount;
			_itemActionDepth++;
			if (__state >= 0f)
			{
				return;
			}
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (!Mine(val2))
			{
				return;
			}
			STATUSTYPE statusType = __instance.statusType;
			if ((int)statusType == 1)
			{
				return;
			}
			ItemUse itemUse = Batch(val, val2);
			if ((int)statusType == 0)
			{
				float num = Effects.Local[Channel.healReceived];
				Character val3 = default(Character);
				num = ((!val.TryGetFeeder(ref val3) || !((Object)(object)val3 != (Object)null) || !((Object)(object)val3 != (Object)(object)val2)) ? (num * Effects.Local[Channel.healSelfUse]) : (num * Effects.ActorChannel(NetSend.ActorOf(val3), Channel.healGiven)));
				if (Mathf.Abs(num - 1f) > 0.0001f)
				{
					__instance.changeAmount = __state * num;
					_itemScaled = true;
				}
			}
			if (CurativeSelection.RecordMedicalCure(itemUse.Cured, statusType, (STATUSTYPE)3, (STATUSTYPE)10, IsCurativeItem(val)))
			{
				itemUse.Curative = true;
			}
		}

		public static void OnModifyStatusAction(Action_ModifyStatus __instance, float __state)
		{
			__instance.changeAmount = __state;
			if (_itemActionDepth > 0)
			{
				_itemActionDepth--;
			}
			_itemScaled = false;
		}

		public static void OnApplyAfflictionActionPrefix(Action_ApplyAffliction __instance)
		{
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (!Mine(val2) || !IsCurativeItem(val))
			{
				return;
			}
			ItemUse itemUse = Batch(val, val2);
			itemUse.Curative = true;
			if (WarmsCold(__instance.affliction))
			{
				itemUse.Cured.Add((STATUSTYPE)2);
			}
			if (__instance.extraAfflictions == null)
			{
				return;
			}
			Affliction[] extraAfflictions = __instance.extraAfflictions;
			for (int i = 0; i < extraAfflictions.Length; i++)
			{
				if (WarmsCold(extraAfflictions[i]))
				{
					itemUse.Cured.Add((STATUSTYPE)2);
				}
			}
		}

		private static bool WarmsCold(Affliction a)
		{
			return a is Affliction_AdjustColdOverTime;
		}

		public static void OnHealingGemActionPrefix(Action_HealingGem __instance, out float[] __state)
		{
			__state = null;
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (Mine(val2) && IsCurativeItem(val))
			{
				CharacterAfflictions afflictions = val2.refs.afflictions;
				__state = new float[StatusCount];
				for (int i = 0; i < __state.Length; i++)
				{
					__state[i] = afflictions.GetCurrentStatus((STATUSTYPE)i);
				}
			}
		}

		public static void OnHealingGemAction(Action_HealingGem __instance, float[] __state)
		{
			if (__state == null)
			{
				return;
			}
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (!Mine(val2))
			{
				return;
			}
			CharacterAfflictions afflictions = val2.refs.afflictions;
			ItemUse itemUse = Batch(val, val2);
			itemUse.Curative = true;
			for (int i = 0; i < __state.Length; i++)
			{
				if (afflictions.GetCurrentStatus((STATUSTYPE)i) < __state[i] - 0.0001f)
				{
					itemUse.Cured.Add((STATUSTYPE)i);
				}
			}
		}

		public static void OnClearAllStatusActionPrefix(Action_ClearAllStatus __instance)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Item val = ActionItem.Invoke((ItemActionBase)(object)__instance);
			Character val2 = (((Object)(object)val != (Object)null) ? val.holderCharacter : null);
			if (!Mine(val2) || !IsCurativeItem(val))
			{
				return;
			}
			ItemUse itemUse = Batch(val, val2);
			itemUse.Curative = true;
			foreach (STATUSTYPE value in Enum.GetValues(typeof(STATUSTYPE)))
			{
				itemUse.Cured.Add(value);
			}
		}

		private static bool LuckyLunchSaves(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			return _lunch.Decide(((Object)item).GetInstanceID(), Time.frameCount, delegate
			{
				if (!Mine(item.holderCharacter) || !IsFood(item))
				{
					return false;
				}
				Ability_LuckyLunch ability_LuckyLunch = LocalCards.Get<Ability_LuckyLunch>();
				if (ability_LuckyLunch == null)
				{
					return false;
				}
				bool flag = IsCooked(item);
				bool flag2 = flag && ability_LuckyLunch.TryUse();
				if (!flag)
				{
					ability_LuckyLunch.HintUncooked();
				}
				Plugin.Verbose(string.Format("Lucky Lunch: {0} cooked={1} biome={2} -> {3}", item.GetItemName((ItemInstanceData)null), flag, LocalCards.Biome, flag2 ? "kept" : (flag ? "used up (already used this biome)" : "used up (not cooked)")));
				return flag2;
			});
		}

		private static void FireConsumedOnce(Item item)
		{
			if ((Object)(object)item != (Object)null && item.OnConsumed != null && _lunch.TryFireEffects(((Object)item).GetInstanceID(), Time.frameCount))
			{
				item.OnConsumed();
			}
		}

		public static bool OnConsumeDelayedPrefix(Item __instance, bool ignoreActions, ref IEnumerator __result)
		{
			if (!LuckyLunchSaves(__instance))
			{
				return true;
			}
			__result = KeepItem(__instance, ignoreActions);
			return false;
		}

		private static IEnumerator KeepItem(Item item, bool ignoreActions)
		{
			if (!ignoreActions)
			{
				FireConsumedOnce(item);
			}
			yield return null;
			if ((Object)(object)item != (Object)null && (Object)(object)item.overrideHolderCharacter != (Object)null && (Object)(object)item.trueHolderCharacter != (Object)(object)item.overrideHolderCharacter)
			{
				item.overrideHolderCharacter = null;
			}
		}

		public static bool OnReduceUsesPrefix(Action_ReduceUses __instance)
		{
			return !LuckyLunchSaves(ActionItem.Invoke((ItemActionBase)(object)__instance));
		}

		public static bool OnConsumeAndSpawnPrefix(Action_ConsumeAndSpawn __instance)
		{
			Item item = ActionItem.Invoke((ItemActionBase)(object)__instance);
			if (!LuckyLunchSaves(item))
			{
				return true;
			}
			FireConsumedOnce(item);
			return false;
		}

		private static bool PocketLocked(Player p)
		{
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)p).photonView;
				if ((Object)(object)photonView == (Object)null || photonView.Owner == null)
				{
					return false;
				}
				return RunState.RunStarted && CardSettings.Current.DrawbacksEnabled && Effects.HasAbility(photonView.Owner.ActorNumber, "PocketTradeoff");
			}
			catch
			{
				return false;
			}
		}

		public static bool OnAddItemPrefix(Player __instance, ushort itemID, ref ItemInstanceData instanceData, ref ItemSlot slot, ref bool __result)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || !PocketLocked(__instance))
			{
				return true;
			}
			Item val = default(Item);
			if (!ItemDatabase.TryGetItem(itemID, ref val) || val is Backpack)
			{
				return true;
			}
			ItemSlot[] itemSlots = __instance.itemSlots;
			if (itemSlots == null || itemSlots.Length <= 2 || !itemSlots[2].IsEmpty())
			{
				return true;
			}
			for (int i = 0; i < itemSlots.Length; i++)
			{
				if (i != 2 && itemSlots[i].IsEmpty())
				{
					return true;
				}
			}
			if (instanceData == null)
			{
				instanceData = new ItemInstanceData(Guid.NewGuid());
				ItemInstanceDataHandler.AddInstanceData(instanceData);
			}
			Character character = __instance.character;
			if (__instance.tempFullSlot.IsEmpty() && (Object)(object)character != (Object)null && !character.data.isClimbingAnything)
			{
				__instance.tempFullSlot.SetItem(val, instanceData);
				slot = __instance.tempFullSlot;
				byte[] array = IBinarySerializable.ToManagedArray<InventorySyncData>(new InventorySyncData(__instance.itemSlots, __instance.backpackSlot, __instance.tempFullSlot));
				((MonoBehaviourPun)__instance).photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, false });
				__result = true;
				return false;
			}
			slot = null;
			__result = false;
			return false;
		}

		public static bool OnHasEmptySlotPrefix(Player __instance, ushort itemID, ref bool __result)
		{
			if (!PocketLocked(__instance))
			{
				return true;
			}
			Item val = default(Item);
			if (!ItemDatabase.TryGetItem(itemID, ref val) || val is Backpack)
			{
				return true;
			}
			ItemSlot[] itemSlots = __instance.itemSlots;
			for (int i = 0; i < itemSlots.Length; i++)
			{
				if (i != 2 && itemSlots[i].IsEmpty())
				{
					__result = true;
					return false;
				}
			}
			__result = __instance.tempFullSlot.IsEmpty();
			return false;
		}

		private static void ResetCampfireSpawns()
		{
			_litFires.Clear();
			_spawns.Reset();
		}

		private static void HostCampfireLit(Campfire fire, byte raw)
		{
			byte b = FireKey(fire);
			_litFires[b] = fire;
			_spawns.FireLit(b);
			if (raw != b)
			{
				_litFires[raw] = fire;
				_spawns.ForgetFire(raw);
				_spawns.FireLit(raw);
			}
		}

		public static void HostSpawnItem(SpawnItem m, int sender)
		{
			if (!PhotonNetwork.IsMasterClient && !PhotonNetwork.OfflineMode)
			{
				return;
			}
			bool ownsCardForItem = false;
			bool flag = false;
			byte b = 0;
			foreach (byte item in Effects.CardsOf(sender))
			{
				CardDef cardDef = CardSettings.Current.Card(item);
				if (cardDef != null)
				{
					int num = Mathf.RoundToInt(CardSettings.Current.Param(cardDef, "item", -1f));
					if (cardDef.Ability == "CampfireSpawn" && num == m.item)
					{
						ownsCardForItem = true;
						flag = true;
						break;
					}
					if (cardDef.Ability == "BoneBook" && num == m.item)
					{
						b = 8;
						ownsCardForItem = (Effects.Flags(sender) & b) == 0;
						break;
					}
					if (cardDef.Ability == "MythicChoice" && m.item < CardTable.SpawnItems.Length && Array.IndexOf(CardTable.MythicItems, CardTable.SpawnItems[m.item]) >= 0)
					{
						b = 4;
						ownsCardForItem = (Effects.Flags(sender) & b) == 0;
						break;
					}
				}
			}
			if (m.item >= CardTable.SpawnItems.Length)
			{
				ownsCardForItem = false;
			}
			SpawnVerdict spawnVerdict = _spawns.TryClaim(sender, m.item, m.segment, ownsCardForItem);
			if (spawnVerdict != SpawnVerdict.Ok)
			{
				Plugin.Log.LogWarning((object)$"Refused item {m.item} for actor {sender} at fire {m.segment}: {spawnVerdict}");
				return;
			}
			if (!_litFires.TryGetValue(m.segment, out var value) || (Object)(object)value == (Object)null)
			{
				Plugin.Log.LogWarning((object)$"Item {m.item}: fire {m.segment} is gone");
				return;
			}
			Item obj = SpawnByFire(value, CardTable.SpawnItems[m.item], sender * 3 + m.item);
			if ((Object)(object)obj != (Object)null && b != 0)
			{
				Effects.SetFlag(sender, b, on: true);
				NetSend.Raise(new CardRewardUsed
				{
					actor = sender,
					flag = b
				}, (ReceiverGroup)1);
			}
			if ((Object)(object)obj != (Object)null && flag)
			{
				string text = CarePackageRolls.RandomItemName(foodOnly: true);
				if (text != null)
				{
					SpawnByFire(value, text, sender * 3 + m.item + 101);
				}
				string text2 = CarePackageRolls.RandomItemName(foodOnly: false);
				if (text2 != null)
				{
					SpawnByFire(value, text2, sender * 3 + m.item + 202);
				}
			}
		}

		private static Item SpawnByFire(Campfire fire, string name, int salt)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Item val = default(Item);
			if (!ItemDatabase.TryGetItem(name, ref val))
			{
				Plugin.Log.LogWarning((object)("Unknown item prefab " + name));
				return null;
			}
			if (!SpawnSpot(fire, salt, out var pos))
			{
				Plugin.Log.LogWarning((object)("Item " + name + ": no room next to the fire"));
				return null;
			}
			GameObject val2 = PhotonNetwork.InstantiateItemRoom(name, pos + Vector3.up * 0.25f, Quaternion.identity, true);
			Item val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Item>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.SetKinematicNetworked(true, pos + Vector3.up * 0.25f, Quaternion.identity);
			}
			Plugin.Verbose($"Spawned {name} at {pos}");
			return val3;
		}

		private static bool SpawnSpot(Campfire fire, int salt, out Vector3 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0048: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)fire).transform.position;
			if (!SafeSpot.NearCampfire(fire, salt, out pos, out var _))
			{
				if (!SafeSpot.Near(position, 2.5f, 6f, out pos))
				{
					return false;
				}
				pos -= Vector3.up * 1f;
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(pos.x - position.x, pos.z - position.z);
			if (((Vector2)(ref val)).magnitude <= 7f)
			{
				return Mathf.Abs(pos.y - position.y) <= 4f;
			}
			return false;
		}

		private static void EnterClimb(Character c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				_climbCtx = c;
				_climbDepth++;
			}
		}

		private static void ExitClimb()
		{
			if (--_climbDepth <= 0)
			{
				_climbDepth = 0;
				_climbCtx = null;
			}
		}

		public static void OnWallClimbContextPrefix(CharacterClimbing __instance)
		{
			EnterClimb(ClimbingCharacter.Invoke(__instance));
		}

		public static void OnWallClimbContext(CharacterClimbing __instance)
		{
			ExitClimb();
		}

		public static void OnRopeClimbContextPrefix(CharacterRopeHandling __instance)
		{
			EnterClimb(RopeCharacter.Invoke(__instance));
		}

		public static void OnRopeClimbContext(CharacterRopeHandling __instance)
		{
			ExitClimb();
		}

		public static void OnVineClimbContextPrefix(CharacterVineClimbing __instance)
		{
			EnterClimb(VineCharacter.Invoke(__instance));
		}

		public static void OnVineClimbContext(CharacterVineClimbing __instance)
		{
			ExitClimb();
		}

		public static void OnStartClimbPrefix(CharacterClimbing __instance)
		{
			EnterClimb(ClimbingCharacter.Invoke(__instance));
		}

		public static void OnStartClimb(CharacterClimbing __instance)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			ExitClimb();
			if (Mine(ClimbingCharacter.Invoke(__instance)))
			{
				float num = Effects.Local[Channel.slipForce];
				Vector2 playerSlide = __instance.playerSlide;
				if (Mathf.Abs(num - 1f) > 0.0001f && playerSlide.y < 0f)
				{
					__instance.playerSlide = new Vector2(playerSlide.x, playerSlide.y * num);
				}
			}
		}

		public static bool OnUseStaminaPrefix(Character __instance, ref float usage, ref bool __result)
		{
			if (usage <= 0f || !Mine(__instance))
			{
				return true;
			}
			bool flag = (Object)(object)_climbCtx == (Object)(object)__instance && _climbDepth > 0;
			usage *= StatComposites.StaminaCost(Effects.Local, flag);
			if (flag)
			{
				Ability_OverhangRegen.NoteClimbCost(usage);
				Ability_HoldRefund.NoteClimbCost(usage);
			}
			if (usage <= 0f)
			{
				__result = true;
				return false;
			}
			return true;
		}

		private static bool ExtendedPullSafe(Character helper, Character target, Vector3 dragPoint)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = dragPoint - target.Center;
			Vector2 val2 = new Vector2(val.x, val.z);
			float magnitude = ((Vector2)(ref val2)).magnitude;
			if (target.data.isClimbing)
			{
				if (val.y > 0f)
				{
					return val.y >= 0.55f * magnitude;
				}
				return false;
			}
			return target.Center.y < helper.Center.y + 1f;
		}

		public static void OnReachPrefix(CharacterGrabbing __instance)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			Character val = GrabbingCharacter.Invoke(__instance);
			if (!Mine(val) || !val.data.isReaching || val.data.dead || val.data.passedOut)
			{
				return;
			}
			Ability_HelpCost ability_HelpCost = LocalCards.Get<Ability_HelpCost>();
			if (ability_HelpCost == null)
			{
				return;
			}
			float num = 4f * Effects.Local[Channel.helpReach];
			Vector3 dragPoint = val.Center + Util.ZeroY(val.data.lookDirection * __instance.extendReachDistance);
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)val) && !allCharacter.isBot && !allCharacter.data.dead)
				{
					float num2 = Vector3.Distance(val.Center, allCharacter.Center);
					if (!(num2 > num) && !(Vector3.Angle(val.data.lookDirection, allCharacter.Center - val.Center) > 60f) && CharacterGrabbing.TargetCanBeHelped(allCharacter, val) && (!(num2 > 4f) || ExtendedPullSafe(val, allCharacter, dragPoint)))
					{
						ability_HelpCost.OnPull(val);
						break;
					}
				}
			}
		}

		public static void OnTryWallClimbPrefix(CharacterClimbing __instance, ref float raycastDistance)
		{
			if (Mine(ClimbingCharacter.Invoke(__instance)))
			{
				raycastDistance *= Effects.Local[Channel.grabReach];
			}
		}

		public static void OnReach(CharacterGrabbing __instance)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			Character val = GrabbingCharacter.Invoke(__instance);
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)val == (Object)null || !Mine(localCharacter) || (Object)(object)val == (Object)(object)localCharacter || localCharacter.data.dead)
			{
				return;
			}
			float num = Effects.ActorChannel(NetSend.ActorOf(val), Channel.helpReach);
			if (num <= 1.0001f)
			{
				return;
			}
			float num2 = Vector3.Distance(val.Center, localCharacter.Center);
			if (num2 <= 4f || num2 > 4f * num || Vector3.Angle(val.data.lookDirection, localCharacter.Center - val.Center) > 60f || !CharacterGrabbing.TargetCanBeHelped(localCharacter, val))
			{
				return;
			}
			Vector3 val2 = val.Center + Util.ZeroY(val.data.lookDirection * __instance.extendReachDistance);
			if ((!((Object)(object)_pullLatchHelper == (Object)(object)val) || !(Time.time <= _pullLatchExpire)) && !ExtendedPullSafe(val, localCharacter, val2))
			{
				return;
			}
			_pullLatchHelper = val;
			_pullLatchExpire = Time.time + 0.25f;
			if (localCharacter.IsStuck())
			{
				UnStick(localCharacter);
			}
			localCharacter.refs.afflictions.SubtractStatus((STATUSTYPE)11, 1f, false, false);
			localCharacter.refs.afflictions.SubtractStatus((STATUSTYPE)14, 1f, false, false);
			DragTowards(localCharacter, val2, Mathf.Lerp(70f, 45f, Mathf.InverseLerp(4f, 4f * num, num2)));
			LimitFalling(localCharacter);
			localCharacter.data.sinceGrabFriend = 0f;
			try
			{
				GUIManager.instance.Grasp();
			}
			catch
			{
			}
		}

		public static void OnClimbingSlidePrefix(CharacterClimbing __instance, out float __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			__state = __instance.playerSlide.y;
			_slideBefore = __state;
			_slideTracked = true;
		}

		public static void OnClimbingSlide(CharacterClimbing __instance, float __state)
		{
			_slideTracked = false;
		}

		public static void OnRequestedPositionPrefix(CharacterClimbing __instance, out float __state)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			Character val = ClimbingCharacter.Invoke(__instance);
			__state = (((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null) ? val.data.slippy : 0f);
			if (!Mine(val))
			{
				return;
			}
			float num = Effects.Local[Channel.slipForce];
			if (Mathf.Abs(num - 1f) < 0.0001f)
			{
				return;
			}
			if (_slideTracked)
			{
				Vector2 playerSlide = __instance.playerSlide;
				if (playerSlide.y < _slideBefore)
				{
					__instance.playerSlide = new Vector2(playerSlide.x, _slideBefore + (playerSlide.y - _slideBefore) * num);
				}
				_slideTracked = false;
			}
			val.data.slippy = __state * num;
		}

		public static void OnRequestedPosition(CharacterClimbing __instance, float __state)
		{
			Character val = ClimbingCharacter.Invoke(__instance);
			if (Mine(val))
			{
				val.data.slippy = __state;
			}
		}

		public static void OnJumpGravity(CharacterMovement __instance, ref Vector3 __result)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (__result.y >= 0f)
			{
				return;
			}
			Character val = MovementCharacter.Invoke(__instance);
			if (Mine(val) && val.data.isJumping && !(val.data.sinceJump > 0.75f))
			{
				float num = Effects.Local[Channel.jumpHeight];
				if (!(num <= 1.0001f))
				{
					__result /= 1f + 0.5f * (num - 1f);
				}
			}
		}

		public static void OnCharacterJumped(Character character, bool doubleJump)
		{
			if (doubleJump && Mine(character))
			{
				Ability_SecondSpring.Active?.OnExtraJumpUsed(character);
			}
		}

		public static void OnDynamiteSourcePrefix(out DynamiteSpawnState __state)
		{
			__state = null;
			if (RunState.RunStarted)
			{
				__state = new DynamiteSpawnState
				{
					PreviousDepth = _dynamiteSpawnDepth,
					Existing = new HashSet<int>()
				};
				AOE[] array = Object.FindObjectsOfType<AOE>(true);
				foreach (AOE val in array)
				{
					__state.Existing.Add(((Object)val).GetInstanceID());
				}
				_dynamiteSpawnDepth++;
			}
		}

		public static Exception OnDynamiteSourceFinalizer(Exception __exception, DynamiteSpawnState __state)
		{
			if (__state == null)
			{
				return __exception;
			}
			_dynamiteSpawnDepth = __state.PreviousDepth;
			AOE[] array = Object.FindObjectsOfType<AOE>(true);
			foreach (AOE val in array)
			{
				if (!__state.Existing.Contains(((Object)val).GetInstanceID()) && (Object)(object)((Component)val).GetComponent<DynamiteCardBlast>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<DynamiteCardBlast>();
				}
			}
			return __exception;
		}

		public static void OnDynamiteFusePrefix(out bool __state)
		{
			__state = _dynamiteBlast;
			_dynamiteBlast = true;
		}

		public static Exception OnDynamiteFuseFinalizer(Exception __exception, bool __state)
		{
			_dynamiteBlast = __state;
			return __exception;
		}

		public static void OnBlastContextPrefix(AOE __instance, out bool __state)
		{
			__state = _dynamiteBlast;
			_dynamiteBlast = _dynamiteSpawnDepth > 0 || (Object)(object)((Component)__instance).GetComponent<DynamiteCardBlast>() != (Object)null;
		}

		public static Exception OnBlastContextFinalizer(Exception __exception, bool __state)
		{
			_dynamiteBlast = __state;
			return __exception;
		}

		public static void OnThornInteractTime(ThornOnMe __instance, ref float __result)
		{
			ScaleThornTime(__instance, ref __result);
		}

		public static void OnThornPopOutTime(ThornOnMe __instance, ref float __result)
		{
			ScaleThornTime(__instance, ref __result);
		}

		private static void ScaleThornTime(ThornOnMe thorn, ref float time)
		{
			if (RunState.RunStarted && !((Object)(object)thorn == (Object)null) && thorn.isThorn && !((Object)(object)thorn.character == (Object)null) && !(time <= 0f))
			{
				time *= Effects.ActorChannel(NetSend.ActorOf(thorn.character), Channel.thornRemovalTime);
			}
		}

		public static void OnPostReviveStatusPrefix(CharacterAfflictions afflictions, out float __state)
		{
			__state = -1f;
			if ((Object)(object)afflictions != (Object)null && Mine(afflictions.character))
			{
				__state = afflictions.GetCurrentStatus((STATUSTYPE)5);
			}
		}

		public static void OnPostReviveStatus(CharacterAfflictions afflictions, float __state)
		{
			if (!(__state < 0f) && !((Object)(object)afflictions == (Object)null) && Mine(afflictions.character))
			{
				float multiplier = Effects.ActorChannel(NetSend.ActorOf(afflictions.character), Channel.reviveCurse);
				float currentStatus = afflictions.GetCurrentStatus((STATUSTYPE)5);
				float num = ReviewedEffectMath.RevivalCurse(__state, currentStatus, multiplier);
				if (Mathf.Abs(num - currentStatus) > 1E-05f)
				{
					afflictions.SetStatus((STATUSTYPE)5, num, true);
				}
			}
		}

		public static void OnCarriedDeathPrefix(Character __instance, out float __state)
		{
			__state = -1f;
			if (Mine(__instance) && !__instance.data.dead && __instance.data.fullyPassedOut)
			{
				__state = __instance.data.deathTimer;
			}
		}

		public static void OnCarriedDeath(Character __instance, float __state)
		{
			if (!(__state < 0f) && Mine(__instance) && !__instance.data.dead && __instance.data.fullyPassedOut)
			{
				Character carrier = __instance.data.carrier;
				if (!((Object)(object)carrier == (Object)null) && !carrier.data.dead)
				{
					float multiplier = Effects.ActorChannel(NetSend.ActorOf(carrier), Channel.carriedDeathRate);
					__instance.data.deathTimer = ReviewedEffectMath.CarriedDeathTimer(__state, __instance.data.deathTimer, multiplier, Time.fixedDeltaTime / 60f);
				}
			}
		}

		public static void OnPassedOut(Character __instance)
		{
			if (Mine(__instance) && !__instance.isBot)
			{
				LocalCards.OnDown(__instance);
			}
		}

		public static void OnDiedPrefix(Character __instance, out bool __state)
		{
			__state = (Object)(object)__instance.data != (Object)null && (__instance.data.passedOut || __instance.data.fullyPassedOut);
			if (NetSend.IsHost && EternalReviveLikely(__instance))
			{
				_endGameHoldUntil = Time.time + 8f;
				_endGameRecheck = __instance;
			}
		}

		public static void OnDied(Character __instance, bool __state)
		{
			if (Mine(__instance) && !__instance.isBot)
			{
				if (!__state)
				{
					LocalCards.OnDown(__instance);
				}
				LocalCards.OnDeath(__instance);
			}
		}

		internal static void ResetEndGameHold()
		{
			_endGameHoldUntil = 0f;
			_endGameRecheck = null;
		}

		public static bool OnCheckEndGamePrefix(Character __instance)
		{
			if (Time.time >= _endGameHoldUntil)
			{
				return true;
			}
			_endGameRecheck = __instance;
			return false;
		}

		internal static void TickEndGameHold()
		{
			if ((Object)(object)_endGameRecheck == (Object)null || Time.time < _endGameHoldUntil)
			{
				return;
			}
			Character endGameRecheck = _endGameRecheck;
			_endGameRecheck = null;
			try
			{
				endGameRecheck.CheckEndGame();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("End-game recheck: " + ex.Message));
			}
		}

		private static bool EternalReviveLikely(Character victim)
		{
			//IL_00e3: 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)
			try
			{
				if ((Object)(object)victim == (Object)null || victim.isBot)
				{
					return false;
				}
				int num = NetSend.ActorOf(victim);
				CardSettings current = CardSettings.Current;
				Character val = default(Character);
				foreach (KeyValuePair<int, List<byte>> item in Effects.CardsByActor)
				{
					foreach (byte item2 in item.Value)
					{
						CardDef cardDef = current.Card(item2);
						if (cardDef != null && !(cardDef.Ability != "EternalCampfire") && !Ability_EternalCampfire.Arbiter.UsedInBiome(item.Key, LocalCards.Biome))
						{
							if (item.Key == num)
							{
								return true;
							}
							if (PlayerHandler.TryGetCharacter(item.Key, ref val) && !((Object)(object)val == (Object)null) && !((Object)(object)val.data == (Object)null) && !val.data.dead && Vector3.Distance(val.Center, victim.Center) <= current.Param(cardDef, "radius", 15f) + 2f)
							{
								return true;
							}
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool OnFedItemPrefix(Character __instance, int itemPhotonID)
		{
			if (!RunState.RunStarted)
			{
				return true;
			}
			try
			{
				PhotonView val = PhotonView.Find(itemPhotonID);
				Item val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Item>() : null);
				if (!Mine(__instance) || (!__instance.data.passedOut && !__instance.data.fullyPassedOut))
				{
					return true;
				}
				Character val3 = (((Object)(object)val2 != (Object)null) ? val2.trueHolderCharacter : null);
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)__instance)
				{
					return true;
				}
				_lastFeederActor = NetSend.ActorOf(val3);
				_lastFedTime = Time.time;
			}
			catch
			{
			}
			return true;
		}

		public static void OnUnPassedOut(Character __instance)
		{
			if (Mine(__instance))
			{
				LocalCards.OnRecovered();
				if (_lastFeederActor != int.MinValue && Time.time - _lastFedTime < 20f)
				{
					NetSend.RaiseTo(new RevivedBy
					{
						victimActor = NetSend.LocalActor
					}, _lastFeederActor);
				}
				_lastFeederActor = int.MinValue;
			}
		}

		public static void OnRespawnChestUsedPrefix(Character interactor)
		{
			if (!Mine(interactor))
			{
				return;
			}
			bool flag = true;
			try
			{
				flag = Ascents.canReviveDead;
			}
			catch
			{
			}
			if (!flag)
			{
				return;
			}
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)interactor) && !allCharacter.isBot && !((Object)(object)allCharacter.data == (Object)null) && (allCharacter.data.dead || allCharacter.data.fullyPassedOut))
				{
					Ability_HerosArrival.OnRevivedTeammate(NetSend.ActorOf(allCharacter));
					break;
				}
			}
		}

		public static bool OnKillPlanePrefix(Collision other)
		{
			if (other == null || (Object)(object)other.collider == (Object)null)
			{
				return true;
			}
			Character val = default(Character);
			if (!CharacterRagdoll.TryGetCharacterFromCollider(other.collider, ref val) || !Mine(val))
			{
				return true;
			}
			Ability_PhoenixClause owned = Ability_PhoenixClause.Owned;
			if (owned != null)
			{
				return !owned.TryPreventKillPlane(val);
			}
			return true;
		}

		public static void ResetStatusCarries()
		{
			AddCarry.Reset();
			SubCarry.Reset();
			_petrifyCarry = 0f;
			_injuryCommitted = 0f;
			_shareOwed.Clear();
		}

		private static bool Mine(Character c)
		{
			if ((Object)(object)c != (Object)null && c.IsLocal)
			{
				return RunState.RunStarted;
			}
			return false;
		}

		public static void OnFallDamagePrefix(CharacterMovement __instance)
		{
			_fallDepth++;
		}

		public static void OnFallDamage(CharacterMovement __instance)
		{
			if (_fallDepth > 0)
			{
				_fallDepth--;
			}
		}

		public static void OnClimbFallDamagePrefix(CharacterClimbing __instance)
		{
			_fallDepth++;
		}

		public static void OnClimbFallDamage(CharacterClimbing __instance)
		{
			if (_fallDepth > 0)
			{
				_fallDepth--;
			}
		}

		public static bool OnAddStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount, bool fromRPC, bool ignoreInvincibility, bool ignoreSkeleton, ref bool __result, out bool __state)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected I4, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Invalid comparison between Unknown and I4
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			__state = false;
			if (amount <= 0f)
			{
				return true;
			}
			Character character = __instance.character;
			if (!Mine(character))
			{
				return true;
			}
			if ((int)statusType == 13)
			{
				return true;
			}
			bool raw = CardStatus.Raw;
			float num = amount;
			if (!raw)
			{
				if ((int)statusType == 0 && NativeInjuryRules.Blocks(character.isZombie, character.statusesLocked, character.isScoutmaster, AfflictionsInAirport.Invoke(__instance), NativeInvincible.Invoke(character.data), ignoreInvincibility))
				{
					return true;
				}
				bool flag = (int)statusType == 0 && _fallDepth > 0;
				amount *= Effects.StatusGainMultiplier(statusType, flag);
				if ((int)statusType == 3 && amount > 0f)
				{
					amount *= Ability_GasImmunity.PoisonFactor(num);
				}
				if (flag && amount > 0f)
				{
					amount *= Ability_BandageBrace.FallFactor(character);
				}
				if ((int)statusType == 0 && _dynamiteBlast)
				{
					amount *= Effects.Local[Channel.dynamiteInjury];
				}
				if ((int)statusType == 0 && amount > 0f)
				{
					amount = ResolveInjury(character, amount, flag, ignoreInvincibility, ignoreSkeleton, out var prevented);
					if (prevented)
					{
						__result = false;
						return false;
					}
				}
				if (StatComposites.CancelsStatus(amount))
				{
					__result = false;
					return false;
				}
			}
			int status = (int)statusType;
			if (raw || Mathf.Abs(amount - num) > 1E-06f || AddCarry.Of(status) > 0f)
			{
				amount = CarryAdd(__instance, character, statusType, amount, ignoreInvincibility, ignoreSkeleton);
			}
			__state = fromRPC && Mathf.Abs(amount - num) > 1E-05f;
			return true;
		}

		private static float CarryAdd(CharacterAfflictions aff, Character ch, STATUSTYPE t, float amount, bool ignoreInvincibility, bool ignoreSkeleton)
		{
			//IL_0002: 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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected I4, but got Unknown
			if (!NativeAccepts(aff, ch, t, ignoreInvincibility))
			{
				return amount;
			}
			float num = 1f;
			if (ch.data.isSkeleton && (int)t == 0 && !ignoreSkeleton)
			{
				num *= 8f;
			}
			if (NativeDifficultyScaled(t))
			{
				num *= Ascents.etcDamageMultiplier;
			}
			if (num <= 0f)
			{
				return amount;
			}
			float[] array = IncrementalStatuses.Invoke(aff);
			int num2 = (int)t;
			if (array == null || num2 >= array.Length)
			{
				return amount;
			}
			bool resetPending;
			float num3 = AddCarry.Route(num2, array[num2], amount * num, out resetPending);
			if (resetPending)
			{
				array[num2] = 0f;
			}
			return num3 / num;
		}

		private static bool NativeAccepts(CharacterAfflictions aff, Character ch, STATUSTYPE t, bool ignoreInvincibility)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			if (ch.isZombie && (int)t != 6 && (int)t != 11)
			{
				return false;
			}
			if (ch.statusesLocked || ch.isScoutmaster || AfflictionsInAirport.Invoke(aff))
			{
				return false;
			}
			if (ch.data.isSkeleton && (int)t != 0 && (int)t != 5 && (int)t != 14 && (int)t != 11)
			{
				return false;
			}
			if (!ignoreInvincibility && NativeInvincible.Invoke(ch.data) && (int)t != 5)
			{
				return false;
			}
			if ((int)t == 1 && !aff.canGetHungry)
			{
				return false;
			}
			return true;
		}

		private static bool NativeDifficultyScaled(STATUSTYPE t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if ((int)t != 0 && (int)t != 5 && (int)t != 3 && (int)t != 10 && (int)t != 2 && (int)t != 8)
			{
				return (int)t == 6;
			}
			return true;
		}

		public static void OnAddStatus(CharacterAfflictions __instance, bool __state)
		{
			if (__state)
			{
				__instance.PushStatuses((Player)null);
			}
		}

		private static float ResolveInjury(Character ch, float amount, bool fall, bool ignoreInvincibility, bool ignoreSkeleton, out bool prevented)
		{
			int owner = Effects.SharedBurdenOwner;
			float shareFactor = ((owner != int.MinValue && owner != NetSend.LocalActor) ? Effects.SharedBurdenFactor : 1f);
			CardDef cardDef = Array.Find(CardTable.Cards, (CardDef c) => c.Ability == "SharedBurden");
			float absorb = ((cardDef != null) ? CardSettings.Current.Param(cardDef, "absorb", 0.5f) : 0.5f);
			float cap = ((cardDef != null) ? CardSettings.Current.Param(cardDef, "cap", 0.1f) : 0.1f);
			if (!CardSettings.Current.DrawbacksEnabled)
			{
				absorb = 0f;
			}
			Ability_DelayedConsequences delayed = (fall ? Ability_DelayedConsequences.Owned : null);
			Ability_PhoenixClause phoenix = (fall ? Ability_PhoenixClause.Owned : null);
			Func<float, bool> preventFall = null;
			if (phoenix != null)
			{
				preventFall = delegate(float injury)
				{
					float immediate = injury;
					float deferred = 0f;
					if (delayed != null)
					{
						delayed.Preview(injury, out immediate, out deferred);
					}
					return phoenix.TryPreventFatalFall(ch, immediate, deferred, ignoreSkeleton);
				};
			}
			Func<float, float> deferFall = ((delayed != null) ? ((Func<float, float>)((float injury) => delayed.Defer(injury, ignoreInvincibility, ignoreSkeleton))) : null);
			return InjuryResolution.Resolve(amount, shareFactor, absorb, cap, fall, preventFall, deferFall, delegate(float share)
			{
				OweShare(owner, share);
			}, out prevented);
		}

		private static void OweShare(int owner, float share)
		{
			_shareOwed.TryGetValue(owner, out var value);
			value += share;
			if (value < 0.02499f)
			{
				_shareOwed[owner] = value;
				return;
			}
			_shareOwed[owner] = 0f;
			NetSend.RaiseTo(new InjuryShare
			{
				amount = value
			}, owner);
		}

		public static void OnSubtractStatusPrefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount, bool decreasedNaturally)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected I4, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Invalid comparison between Unknown and I4
			if (amount <= 0f || (int)statusType == 13)
			{
				return;
			}
			Character character = __instance.character;
			if (!Mine(character))
			{
				return;
			}
			bool raw = CardStatus.Raw;
			float num = amount;
			if (!raw)
			{
				if (decreasedNaturally)
				{
					amount *= Effects.NaturalDecayMultiplier(statusType);
				}
				else if ((int)statusType == 2 && _itemActionDepth == 0)
				{
					float num2 = Effects.Local[Channel.coldDecay];
					if ((Object)(object)_heatEmitter != (Object)null && (Object)(object)_heatEmitter != (Object)(object)character)
					{
						num2 *= Effects.Local[Channel.huddleStrength];
					}
					amount *= num2;
				}
				else if ((int)statusType == 0 && _itemActionDepth == 0)
				{
					amount *= Effects.Local[Channel.healReceived];
				}
			}
			int num3 = (int)statusType;
			bool flag = !decreasedNaturally && ((int)statusType == 3 || (int)statusType == 10);
			if ((!raw && !_itemScaled && Mathf.Abs(amount - num) <= 1E-06f && (flag || SubCarry.Of(num3) <= 0f)) || character.statusesLocked || (character.isZombie && (int)statusType != 6 && (int)statusType != 11))
			{
				return;
			}
			if (__instance.GetCurrentStatus(statusType) <= 0f)
			{
				SubCarry.Clear(num3);
				return;
			}
			float[] array = DecrementalStatuses.Invoke(__instance);
			if (array == null || num3 >= array.Length)
			{
				return;
			}
			if (raw)
			{
				SubCarry.Bank(num3, array[num3], amount);
				return;
			}
			amount = SubCarry.Route(num3, array[num3], amount, out var resetPending);
			if (resetPending)
			{
				array[num3] = 0f;
			}
		}

		public static void OnAddPetrifyPrefix(CharacterAfflictions __instance, ref int petrify)
		{
			if (petrify > 0 && !CardStatus.Raw && Mine(__instance.character))
			{
				float num = StatComposites.StatusGain(Effects.Local, Channel.petrifyRate);
				if (!(Mathf.Abs(num - 1f) <= 0.0001f) || !(_petrifyCarry <= 0f))
				{
					petrify = StatusCarry.Whole(ref _petrifyCarry, (float)petrify * num);
				}
			}
		}

		public static void OnHeatEmissionPrefix(CharacterHeatEmission __instance, out bool __state)
		{
			__state = false;
			Character val = (_heatEmitter = HeatEmissionCharacter.Invoke(__instance));
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.data == (Object)null) && !(val.data.sinceAddedCold < 3f))
			{
				__state = HeatEmissionCounter.Invoke(__instance) + Time.deltaTime >= __instance.rate;
			}
		}

		public static void OnHeatEmission(CharacterHeatEmission __instance, bool __state)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Character heatEmitter = _heatEmitter;
			_heatEmitter = null;
			if (!__state || (Object)(object)heatEmitter == (Object)null)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if (!Mine(localCharacter) || (Object)(object)heatEmitter == (Object)(object)localCharacter || localCharacter.data.dead)
			{
				return;
			}
			float num = Effects.Local[Channel.huddleStrength];
			if (num <= 1.0001f)
			{
				return;
			}
			float num2 = Vector3.Distance(((Component)__instance).transform.position, localCharacter.Center);
			if (num2 < __instance.radius || num2 >= __instance.radius * num)
			{
				return;
			}
			_heatEmitter = heatEmitter;
			try
			{
				localCharacter.refs.afflictions.SubtractStatus((STATUSTYPE)2, __instance.heatAmount, false, false);
			}
			finally
			{
				_heatEmitter = null;
			}
		}

		public static void OnRegenContextPrefix(Character __instance)
		{
			_regenChar = __instance;
		}

		public static void OnRegenContext(Character __instance)
		{
			_regenChar = null;
		}

		public static void OnAddStaminaPrefix(Character __instance, ref float add)
		{
			if (!(add <= 0f) && !((Object)(object)_regenChar != (Object)(object)__instance) && Mine(__instance))
			{
				add *= Effects.Local[Channel.regenRate];
			}
		}

		public static void OnCanRegenStamina(Character __instance, ref bool __result)
		{
			if (!Mine(__instance))
			{
				return;
			}
			float num = Effects.Local[Channel.regenDelay];
			if (Mathf.Abs(num) < 0.001f)
			{
				return;
			}
			CharacterData data = __instance.data;
			if ((Object)(object)data.currentClimbHandle != (Object)null)
			{
				return;
			}
			bool flag = data.sinceGrounded > 0.2f && !__instance.refs.afflictions.isWebbed;
			float num2 = Mathf.Max(0f, ((data.currentStamina > 0f) ? 1f : 2f) + num);
			if (!__result)
			{
				if (!flag && data.sinceUseStamina >= num2)
				{
					__result = true;
				}
			}
			else if (num > 0f && !__instance.IsStuck() && data.sinceUseStamina < num2)
			{
				__result = false;
			}
		}

		public static void OnGetMaxStamina(Character __instance, ref float __result)
		{
			if (Mine(__instance))
			{
				float num = Effects.Local[Channel.maxStamina];
				if (!(Mathf.Abs(num) < 0.0001f))
				{
					__result = Mathf.Max(Mathf.Min(1f + num, 1.9f) - __instance.refs.afflictions.statusSum, 0f);
				}
			}
		}

		internal static float PassOutThreshold()
		{
			return Mathf.Min(1f + Mathf.Max(0f, Effects.Local[Channel.maxStamina]), 1.9f);
		}

		public static void OnShouldPassOut(CharacterAfflictions __instance, ref bool __result)
		{
			if (__result && !((Object)(object)__instance.character == (Object)null) && Mine(__instance.character))
			{
				__result = __instance.statusSum > PassOutThreshold() - 0.01f;
			}
		}

		internal static void SampleInjuryCapFloor(Character local)
		{
			_injuryCommitted = (((Object)(object)local != (Object)null && local.refs != null && (Object)(object)local.refs.afflictions != (Object)null) ? local.refs.afflictions.GetCurrentStatus((STATUSTYPE)0) : 0f);
		}

		public static void OnGetStatusCap(CharacterAfflictions __instance, STATUSTYPE type, ref float __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)type == 0 && !((Object)(object)__instance.character == (Object)null) && RunState.RunStarted)
			{
				__result = Mathf.Max(__result, Mine(__instance.character) ? Mathf.Max(PassOutThreshold(), _injuryCommitted) : 1.9f);
			}
		}

		public static bool OnScorpionAttackPrefix(Scorpion __instance, Character character)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || !character.IsLocal || !Mine(character))
			{
				return true;
			}
			float num = PassOutThreshold();
			if (num <= 1.