Decompiled source of HostGreatWizard v0.7.16

BepInEx/plugins/HostGreatWizard/HostGreatWizard.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HostRoleSeries;
using REPOLib.Modules;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("0.7.16.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1")]
[assembly: AssemblyVersion("0.7.16.0")]
namespace HostGreatWizard;

[BepInPlugin("local.bei.hostgreatwizard", "HostGreatWizard", "0.7.16")]
[BepInDependency("REPOLib", "4.2.0")]
[BepInDependency("local.bei.hostroleselector", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(PhysGrabObject), "GrabLink")]
	private static class StaffRealPhysicsGrab
	{
		private static void Prefix(int playerPhotonID)
		{
			Current?.BeforeRealGrab(playerPhotonID);
		}
	}

	[HarmonyPatch(typeof(StaticGrabObject), "GrabLink")]
	private static class StaffRealStaticGrab
	{
		private static void Prefix(int __0)
		{
			Current?.BeforeRealGrab(__0);
		}
	}

	[HarmonyPatch(typeof(PhysGrabber), "GrabLinkClimb")]
	private static class StaffRealClimbGrab
	{
		private static void Prefix(PhysGrabber __instance)
		{
			if (Object.op_Implicit((Object)(object)Current) && (Object)(object)__instance == (Object)(object)PhysGrabber.instance)
			{
				Current.BeforeRealGrab(Current.network.ViewId(((Component)__instance).gameObject));
			}
		}
	}

	[HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")]
	private static class StaffRejectCarrierGrab
	{
		private static bool Prefix(PhysGrabObject __instance)
		{
			if (Object.op_Implicit((Object)(object)Current) && Object.op_Implicit((Object)(object)Current.guestStaffCarrier))
			{
				return (Object)(object)((Component)__instance).gameObject != (Object)(object)Current.guestStaffCarrier;
			}
			return true;
		}
	}

	private enum ManaPalette
	{
		Normal,
		Charged,
		HolyCharging,
		HolyReady
	}

	private readonly ParticleSystem[] chargeSources = (ParticleSystem[])(object)new ParticleSystem[3];

	private readonly ParticleSystem[] loadedSources = (ParticleSystem[])(object)new ParticleSystem[3];

	private ParticleSystem voidActiveSource;

	private ParticleSystem chargeEffect;

	private ParticleSystem loadedEffect;

	private ParticleSystem activeEffect;

	private GameObject chargeEffectRoot;

	private Spell effectSpell;

	private bool effectReady;

	private float nextEffectAttempt;

	private float nextEffectWarning;

	private GameObject guestChargeCarrier;

	private ItemDrone guestChargeDrone;

	private readonly GuestChargePulse guestChargePulse = new GuestChargePulse();

	private float guestChargeReadyAt;

	private float guestChargeRetryAt;

	private float guestChargeWarningAt;

	private float guestChargeParkAt;

	private string guestChargeRoster;

	private static readonly Vector3 GuestCarrierParking = new Vector3(10000f, 3000f, 10000f);

	private GameObject guestStaffCarrier;

	private GameObject guestStaffHolder;

	private string guestStaffRoster;

	private int guestStaffKind = -1;

	private bool guestStaffLinked;

	private float guestStaffReadyAt;

	private float guestStaffRetryAt;

	private float guestStaffMoveAt;

	private static readonly FieldInfo staffKinematic = Field(typeof(PhysGrabObject), "isKinematic");

	private const float GuestStaffScale = 0.0001f;

	private int holyEffectPhase = -1;

	private Vector3 holyEffectCenter;

	private float holyEffectNext;

	private float holyEffectUntil;

	private static readonly FieldInfo holyEnemyHealth = Field(typeof(EnemyHealth), "healthCurrent");

	private static readonly FieldInfo holyEnemyDead = Field(typeof(EnemyHealth), "dead");

	private static readonly FieldInfo holyEnemyDying = Field(typeof(EnemyHealth), "deadImpulse");

	private static readonly FieldInfo holyEnemySpawned = Field(typeof(EnemyParent), "Spawned");

	private static readonly FieldInfo holyDeathHead = Field(typeof(PlayerAvatar), "playerDeathHead");

	private static readonly FieldInfo holyHeadSetup = Field(typeof(PlayerDeathHead), "setup");

	private static readonly FieldInfo holyHeadTriggered = Field(typeof(PlayerDeathHead), "triggered");

	private float holyFieldUntil = -1f;

	private PlayerAvatar holyFieldCaster;

	private readonly HashSet<EnemyHealth> holyAffectedEnemies = new HashSet<EnemyHealth>();

	private readonly Sound[][] chargeAudioSources = new Sound[3][];

	private HostChargeAudio hostChargeAudio;

	private Spell audioSpell;

	private float nextAudioAttempt;

	private float nextAudioWarning;

	private GameObject hud;

	private Canvas hudCanvas;

	private float nextHudAttempt;

	private float nextHudWarning;

	private readonly List<GameObject> manaBars = new List<GameObject>();

	private readonly List<Component> manaColorGraphics = new List<Component>();

	private ManaPalette? lastManaPalette;

	private readonly List<Component> holyBorder = new List<Component>();

	private Component holyGraphic;

	private GUIStyle spellStyle;

	private readonly Vector3[] hudCorners = (Vector3[])(object)new Vector3[4];

	private RectTransform holyFill;

	private static readonly Color ManaBlue = new Color(0.15f, 0.55f, 1f, 1f);

	private static readonly Color ManaCharged = new Color(0.6f, 0.82f, 1f, 1f);

	private static readonly Color ManaHoly = Color32.op_Implicit(new Color32((byte)236, byte.MaxValue, (byte)25, byte.MaxValue));

	private static readonly Color ManaHolyUnready = Color32.op_Implicit(new Color32((byte)230, (byte)233, (byte)136, byte.MaxValue));

	public const string Id = "local.bei.hostgreatwizard";

	internal static Plugin Current;

	private ConfigEntry<bool> modEnabled;

	private ConfigEntry<bool> nativeStaffCharge;

	private ConfigEntry<KeyboardShortcut> switchKey;

	private WizardRules rules = new WizardRules();

	private NativeNetwork network;

	private Harmony harmony;

	private object session;

	private object stage;

	private readonly InteractionFireGate interactionGate = new InteractionFireGate();

	private float nextWarning;

	private readonly WizardInput castInput = new WizardInput();

	private static readonly string[] SpellNames = new string[4] { "Roll", "Zero Gravity", "Void", "Holly Flush" };

	private static readonly FieldInfo dead = Field(typeof(PlayerAvatar), "deadSet");

	private static readonly FieldInfo disabled = Field(typeof(PlayerAvatar), "isDisabled");

	private static readonly FieldInfo spawned = Field(typeof(PlayerAvatar), "spawned");

	private static readonly FieldInfo tumbling = Field(typeof(PlayerAvatar), "isTumbling");

	private static readonly FieldInfo cameraField = Field(typeof(PhysGrabber), "playerCamera");

	private static readonly FieldInfo inputDisabled = Field(typeof(PlayerController), "InputDisableTimer");

	private static readonly FieldInfo chatActive = Field(typeof(ChatManager), "chatActive");

	private static readonly FieldInfo mapActive = Field(typeof(MapToolController), "Active");

	private static readonly FieldInfo menuState = Field(typeof(MenuManager), "currentMenuState");

	private readonly PrefabRef[] projectiles = (PrefabRef[])(object)new PrefabRef[3];

	private PrefabRef voidOnHit;

	private float nextCatalog;

	private static readonly FieldInfo projectilePlayer = Field(typeof(SlowProjectile), "playerCausingHurt");

	private static readonly FieldInfo hurtPlayer = Field(typeof(HurtCollider), "playerCausingHurtOverride");

	private static readonly FieldInfo muzzleCrouching = Field(typeof(PlayerAvatar), "isCrouching");

	private static readonly FieldInfo muzzleCrawling = Field(typeof(PlayerAvatar), "isCrawling");

	internal bool PhysicalStaffPowerEnabled
	{
		get
		{
			if (RoleEnabled)
			{
				return WorldReady();
			}
			return false;
		}
	}

	private bool RoleEnabled
	{
		get
		{
			if (((Behaviour)this).isActiveAndEnabled && modEnabled != null && modEnabled.Value)
			{
				return RoleMenu.IsSelected("local.bei.hostgreatwizard");
			}
			return false;
		}
	}

	private void DestroyChargeEffects()
	{
		StopHostChargeAudio();
		GameObject val = chargeEffectRoot;
		chargeEffectRoot = null;
		chargeEffect = (loadedEffect = (activeEffect = null));
		effectReady = false;
		if (Object.op_Implicit((Object)(object)val))
		{
			val.SetActive(false);
			Object.Destroy((Object)(object)val);
		}
	}

	private void UpdateChargeEffects(bool allowed, double duration)
	{
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Expected O, but got Unknown
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!allowed || rules.Charge <= 0.0 || !rules.CanChargeSelected)
			{
				DestroyChargeEffects();
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.PlayerVisionTarget) || !Object.op_Implicit((Object)(object)instance.PlayerVisionTarget.VisionTransform))
			{
				DestroyChargeEffects();
				return;
			}
			Vector3 position = instance.PlayerVisionTarget.VisionTransform.position - Vector3.up * 0.35f;
			if (Object.op_Implicit((Object)(object)chargeEffectRoot) && (effectSpell != rules.Selected || !Object.op_Implicit((Object)(object)chargeEffect) || !Object.op_Implicit((Object)(object)loadedEffect)))
			{
				DestroyChargeEffects();
			}
			if (!Object.op_Implicit((Object)(object)chargeEffectRoot))
			{
				if (Time.unscaledTime < nextEffectAttempt)
				{
					return;
				}
				int num = (int)(rules.HolySelected ? Spell.ZeroGravity : rules.Selected);
				if (!Object.op_Implicit((Object)(object)chargeSources[num]) || !Object.op_Implicit((Object)(object)loadedSources[num]))
				{
					return;
				}
				nextEffectAttempt = Time.unscaledTime + 0.1f;
				chargeEffectRoot = new GameObject("HostGreatWizard Body Charge Effects");
				chargeEffectRoot.SetActive(false);
				chargeEffectRoot.transform.position = position;
				effectSpell = rules.Selected;
				chargeEffect = CloneBodyParticles(chargeSources[num]);
				loadedEffect = CloneBodyParticles(loadedSources[num]);
				if (effectSpell == Spell.Void && Object.op_Implicit((Object)(object)voidActiveSource) && !((Component)voidActiveSource).transform.IsChildOf(((Component)loadedSources[num]).transform))
				{
					activeEffect = CloneBodyParticles(voidActiveSource);
				}
				ParticleSystem[] componentsInChildren = ((Component)chargeEffect).GetComponentsInChildren<ParticleSystem>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					EmissionModule emission = componentsInChildren[i].emission;
					((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(25f);
				}
				chargeEffectRoot.SetActive(true);
				chargeEffect.Play(true);
			}
			chargeEffectRoot.transform.position = position;
			if (rules.Charge < duration && effectReady)
			{
				effectReady = false;
				loadedEffect.Stop(true, (ParticleSystemStopBehavior)0);
				if (Object.op_Implicit((Object)(object)activeEffect))
				{
					activeEffect.Stop(true, (ParticleSystemStopBehavior)0);
				}
			}
			if (rules.Charge >= duration && !effectReady)
			{
				effectReady = true;
				loadedEffect.Play(true);
				if (Object.op_Implicit((Object)(object)activeEffect))
				{
					activeEffect.Play(true);
				}
			}
		}
		catch (Exception ex)
		{
			nextEffectAttempt = Time.unscaledTime + 1f;
			try
			{
				DestroyChargeEffects();
			}
			catch
			{
			}
			if (!(Time.unscaledTime < nextEffectWarning))
			{
				nextEffectWarning = Time.unscaledTime + 30f;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Wizard charge effect failed; magic input remains enabled: " + ex));
			}
		}
	}

	private ParticleSystem CloneBodyParticles(ParticleSystem source)
	{
		//IL_001e: 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_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, chargeEffectRoot.transform, false);
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = ((Component)source).transform.rotation;
		val.transform.localScale = ((Component)source).transform.lossyScale;
		val.SetActive(true);
		ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true);
		foreach (ParticleSystem obj in componentsInChildren)
		{
			MainModule main = obj.main;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).stopAction = (ParticleSystemStopAction)0;
			obj.Stop(false, (ParticleSystemStopBehavior)0);
		}
		return val.GetComponent<ParticleSystem>();
	}

	private void DestroyGuestChargeCarrier()
	{
		DestroyGuestStaffCarrier();
		holyEffectPhase = -1;
		guestChargePulse.Reset();
		if (!Object.op_Implicit((Object)(object)guestChargeCarrier))
		{
			guestChargeCarrier = null;
			guestChargeDrone = null;
			return;
		}
		try
		{
			network.Destroy(guestChargeCarrier);
			guestChargeCarrier = null;
			guestChargeDrone = null;
			guestChargeRoster = null;
		}
		catch (Exception ex)
		{
			GuestChargeWarning("Carrier cleanup failed: " + ex.Message);
		}
	}

	private void GuestChargeWarning(string message)
	{
		if (!(Time.unscaledTime < guestChargeWarningAt))
		{
			guestChargeWarningAt = Time.unscaledTime + 30f;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[WizardGuestCharge] " + message));
		}
	}

	private void UpdateGuestChargeEffects(bool allowed, double duration)
	{
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		//IL_0430: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: Unknown result type (might be due to invalid IL or missing references)
		//IL_043a: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0461: Unknown result type (might be due to invalid IL or missing references)
		//IL_046e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!WorldReady() || !RoleEnabled || (SemiFunc.IsMultiplayer() && !network.InRoom))
			{
				DestroyGuestChargeCarrier();
				return;
			}
			int i;
			if (!Object.op_Implicit((Object)(object)guestChargeCarrier) && Time.unscaledTime >= guestChargeRetryAt)
			{
				guestChargeRetryAt = Time.unscaledTime + 10f;
				PrefabRef val = null;
				foreach (Item allItem in Items.AllItems)
				{
					if (Object.op_Implicit((Object)(object)allItem) && allItem.prefab != null && ((PrefabRef<GameObject>)(object)allItem.prefab).IsValid() && (((PrefabRef<GameObject>)(object)allItem.prefab).PrefabName ?? "").IndexOf("drone", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						GameObject prefab = ((PrefabRef<GameObject>)(object)allItem.prefab).Prefab;
						ItemDrone val2 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrone>() : null);
						if (Object.op_Implicit((Object)(object)val2) && (Object.op_Implicit((Object)(object)val2.teleportParticles) || Object.op_Implicit((Object)(object)((Component)val2).transform.Find("Particles"))))
						{
							val = allItem.prefab;
							break;
						}
					}
				}
				if (val == null)
				{
					GuestChargeWarning("No native drone teleport-particle prefab available; guest charge skipped.");
					return;
				}
				guestChargeCarrier = NetworkPrefabs.SpawnNetworkPrefab(val, GuestCarrierParking, Quaternion.identity, (byte)0, (object[])null);
				if (!Object.op_Implicit((Object)(object)guestChargeCarrier))
				{
					throw new InvalidOperationException("Drone carrier spawn failed.");
				}
				guestChargeDrone = guestChargeCarrier.GetComponent<ItemDrone>();
				((Behaviour)guestChargeCarrier.GetComponent<ItemAttributes>()).enabled = false;
				((Behaviour)guestChargeCarrier.GetComponent<PhysGrabObject>()).enabled = false;
				ItemEquippable component = guestChargeCarrier.GetComponent<ItemEquippable>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Behaviour)component).enabled = false;
				}
				Rigidbody component2 = guestChargeCarrier.GetComponent<Rigidbody>();
				component2.isKinematic = true;
				component2.useGravity = false;
				component2.detectCollisions = false;
				Collider[] componentsInChildren = guestChargeCarrier.GetComponentsInChildren<Collider>(true);
				for (i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				MapCustom component3 = guestChargeCarrier.GetComponent<MapCustom>();
				if (Object.op_Implicit((Object)(object)component3))
				{
					component3.autoAdd = false;
					((Behaviour)component3).enabled = false;
				}
				guestChargeReadyAt = Time.unscaledTime + 0.75f;
				guestChargeParkAt = 0f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[WizardGuestCharge] Native carrier: " + ((PrefabRef<GameObject>)(object)val).ResourcePath));
			}
			string text = (SemiFunc.IsMultiplayer() ? network.Roster(out i) : "solo");
			if (text != guestChargeRoster)
			{
				guestChargeRoster = text;
				guestChargeReadyAt = Time.unscaledTime + 0.75f;
				guestChargePulse.Reset();
				guestChargeParkAt = 0f;
			}
			bool flag = Object.op_Implicit((Object)(object)guestChargeCarrier) && Object.op_Implicit((Object)(object)guestChargeDrone) && Object.op_Implicit((Object)(object)guestChargeDrone.teleportParticles) && Time.unscaledTime >= guestChargeReadyAt;
			if (flag)
			{
				((Behaviour)guestChargeDrone).enabled = false;
				if (Time.unscaledTime >= guestChargeParkAt)
				{
					guestChargeParkAt = Time.unscaledTime + 2f;
					network.Rpc(guestChargeCarrier, "SetPositionRPC", true, GuestCarrierParking, Quaternion.identity);
				}
			}
			bool charging = !nativeStaffCharge.Value && SemiFunc.IsMultiplayer() && allowed && rules.Charge > 0.0 && rules.CanChargeSelected;
			if (!guestChargePulse.Step(charging, rules.Charge >= duration, flag, Time.unscaledTime))
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.PlayerVisionTarget) && Object.op_Implicit((Object)(object)instance.PlayerVisionTarget.VisionTransform))
			{
				Vector3 val3 = instance.PlayerVisionTarget.VisionTransform.position - Vector3.up * 0.35f;
				if (Finite(val3))
				{
					network.Rpc(guestChargeCarrier, "TeleportEffectRPC", true, GuestCarrierParking, val3);
				}
			}
		}
		catch (Exception ex)
		{
			DestroyGuestChargeCarrier();
			guestChargeRetryAt = Time.unscaledTime + 10f;
			GuestChargeWarning("Guest charge effect failed; magic remains enabled: " + ex);
		}
	}

	private void StopGuestStaffLink()
	{
		if (!guestStaffLinked)
		{
			return;
		}
		guestStaffLinked = false;
		try
		{
			if (Object.op_Implicit((Object)(object)guestStaffHolder) && network.InRoom)
			{
				network.Rpc(guestStaffHolder, "GrabClimbEndedRPC", true);
			}
		}
		finally
		{
			if (Object.op_Implicit((Object)(object)guestStaffCarrier) && Object.op_Implicit((Object)(object)guestStaffHolder) && network.InRoom)
			{
				network.Rpc(guestStaffCarrier, "GrabPlayerRemoveRPC", true, network.ViewId(guestStaffHolder));
			}
			guestStaffHolder = null;
			guestStaffMoveAt = 0f;
		}
	}

	private void DestroyGuestStaffCarrier()
	{
		try
		{
			StopGuestStaffLink();
		}
		catch (Exception ex)
		{
			GuestChargeWarning("Native staff unlink failed: " + ex.Message);
		}
		if (Object.op_Implicit((Object)(object)guestStaffCarrier))
		{
			try
			{
				network.Destroy(guestStaffCarrier);
			}
			catch (Exception ex2)
			{
				GuestChargeWarning("Native staff cleanup failed: " + ex2.Message);
				return;
			}
		}
		guestStaffCarrier = null;
		guestStaffHolder = null;
		guestStaffKind = -1;
		guestStaffRoster = null;
	}

	internal void BeforeRealGrab(int playerViewId)
	{
		if (!guestStaffLinked || !Object.op_Implicit((Object)(object)guestStaffHolder) || network.ViewId(guestStaffHolder) != playerViewId)
		{
			return;
		}
		try
		{
			StopGuestStaffLink();
		}
		catch (Exception ex)
		{
			GuestChargeWarning("Native staff handover failed: " + ex.Message);
		}
	}

	private void UpdateGuestStaffEffects(bool allowed)
	{
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0510: Unknown result type (might be due to invalid IL or missing references)
		//IL_0512: Unknown result type (might be due to invalid IL or missing references)
		//IL_051d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0522: Unknown result type (might be due to invalid IL or missing references)
		//IL_056b: Unknown result type (might be due to invalid IL or missing references)
		//IL_056d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0591: Unknown result type (might be due to invalid IL or missing references)
		//IL_059b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_036e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e4: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!nativeStaffCharge.Value || !WorldReady() || !RoleEnabled || !SemiFunc.IsMultiplayer() || !network.InRoom)
			{
				DestroyGuestStaffCarrier();
				return;
			}
			int count;
			string text = network.Roster(out count);
			if (count < 2)
			{
				DestroyGuestStaffCarrier();
				return;
			}
			int num = (int)(rules.HolySelected ? Spell.ZeroGravity : rules.Selected);
			if (Object.op_Implicit((Object)(object)guestStaffCarrier) && (num != guestStaffKind || text != guestStaffRoster))
			{
				DestroyGuestStaffCarrier();
			}
			if (!Object.op_Implicit((Object)(object)guestStaffCarrier) && Time.unscaledTime >= guestStaffRetryAt)
			{
				guestStaffRetryAt = Time.unscaledTime + 10f;
				PrefabRef val = null;
				foreach (Item allItem in Items.AllItems)
				{
					if (Object.op_Implicit((Object)(object)allItem) && allItem.prefab != null && ((PrefabRef<GameObject>)(object)allItem.prefab).IsValid())
					{
						GameObject prefab = ((PrefabRef<GameObject>)(object)allItem.prefab).Prefab;
						if (Object.op_Implicit((Object)(object)prefab) && ((num == 0 && Object.op_Implicit((Object)(object)prefab.GetComponent<ItemStaffTorque>())) || (num == 1 && Object.op_Implicit((Object)(object)prefab.GetComponent<ItemStaffZeroGravity>())) || (num == 2 && Object.op_Implicit((Object)(object)prefab.GetComponent<ItemStaffVoid>()))))
						{
							val = allItem.prefab;
							break;
						}
					}
				}
				if (val == null)
				{
					GuestChargeWarning("Native staff prefab missing; local magic remains available.");
					return;
				}
				guestStaffCarrier = NetworkPrefabs.SpawnNetworkPrefab(val, GuestCarrierParking, Quaternion.identity, (byte)0, new object[3] { 0.0001f, 0.0001f, 0.0001f });
				if (!Object.op_Implicit((Object)(object)guestStaffCarrier))
				{
					throw new InvalidOperationException("Native staff spawn failed.");
				}
				guestStaffKind = num;
				guestStaffRoster = text;
				guestStaffReadyAt = Time.unscaledTime + 1f;
				guestStaffMoveAt = 0f;
				guestStaffRetryAt = 0f;
				MonoBehaviour[] components = guestStaffCarrier.GetComponents<MonoBehaviour>();
				foreach (MonoBehaviour val2 in components)
				{
					if (val2 is ItemStaffTorque || val2 is ItemStaffZeroGravity || val2 is ItemStaffVoid || val2 is ItemToggle || val2 is ItemMelee || val2 is ItemAttributes || val2 is ItemEquippable || val2 is ItemBattery || val2 is PhysGrabObject)
					{
						((Behaviour)val2).enabled = false;
					}
				}
				Rigidbody component = guestStaffCarrier.GetComponent<Rigidbody>();
				component.isKinematic = true;
				component.useGravity = false;
				component.detectCollisions = false;
				staffKinematic.SetValue(guestStaffCarrier.GetComponent<PhysGrabObject>(), true);
				Collider[] componentsInChildren = guestStaffCarrier.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				Renderer[] componentsInChildren2 = guestStaffCarrier.GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					componentsInChildren2[i].enabled = false;
				}
				ParticleSystem[] componentsInChildren3 = guestStaffCarrier.GetComponentsInChildren<ParticleSystem>(true);
				foreach (ParticleSystem val3 in componentsInChildren3)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					string name = ((Object)val3).name;
					MainModule main = val3.main;
					logger.LogInfo((object)("[WizardNativeStaff] " + name + " scaling=" + ((object)((MainModule)(ref main)).scalingMode/*cast due to .constrained prefix*/).ToString()));
					val3.Stop(true, (ParticleSystemStopBehavior)0);
				}
				Light[] componentsInChildren4 = guestStaffCarrier.GetComponentsInChildren<Light>(true);
				for (int i = 0; i < componentsInChildren4.Length; i++)
				{
					((Behaviour)componentsInChildren4[i]).enabled = false;
				}
				MapCustom component2 = guestStaffCarrier.GetComponent<MapCustom>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.autoAdd = false;
					((Behaviour)component2).enabled = false;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[WizardNativeStaff] Created " + ((PrefabRef<GameObject>)(object)val).ResourcePath + "; scale=0.0001. Guest native particles require upward gaze."));
			}
			if (Object.op_Implicit((Object)(object)guestStaffCarrier) && !(Time.unscaledTime < guestStaffReadyAt))
			{
				bool flag = allowed && rules.Charge > 0.0 && rules.CanChargeSelected && ((SpellModifierHeld() && LookingUp()) || rules.Charge >= ChargeDuration());
				PlayerAvatar instance = PlayerAvatar.instance;
				PhysGrabber instance2 = PhysGrabber.instance;
				Transform val4 = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.PlayerVisionTarget)) ? instance.PlayerVisionTarget.VisionTransform : null);
				if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)instance2) || network.ViewId(((Component)instance2).gameObject) <= 0)
				{
					flag = false;
				}
				Vector3 val5 = (flag ? (val4.position - Vector3.up * 0.35f) : GuestCarrierParking);
				if (!Finite(val5))
				{
					flag = false;
					val5 = GuestCarrierParking;
				}
				if (!flag)
				{
					StopGuestStaffLink();
				}
				if (Time.unscaledTime >= guestStaffMoveAt || (flag && !guestStaffLinked))
				{
					guestStaffMoveAt = Time.unscaledTime + (flag ? 0.05f : 2f);
					guestStaffCarrier.GetComponent<PhysGrabObject>().SetPositionLogic(val5, Quaternion.identity);
					network.Rpc(guestStaffCarrier, "SetPositionRPC", true, val5, Quaternion.identity);
				}
				if (flag && !guestStaffLinked)
				{
					guestStaffHolder = ((Component)instance2).gameObject;
					guestStaffLinked = true;
					network.Rpc(guestStaffHolder, "GrabLinkClimbRPC", true, val5);
					network.Rpc(guestStaffCarrier, "GrabPlayerAddRPC", true, network.ViewId(guestStaffHolder));
				}
			}
		}
		catch (Exception ex)
		{
			DestroyGuestStaffCarrier();
			guestStaffRetryAt = Time.unscaledTime + 10f;
			GuestChargeWarning("Native staff effect failed; magic remains enabled: " + ex);
		}
	}

	private bool EmptyHands()
	{
		PhysGrabber instance = PhysGrabber.instance;
		if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)PlayerController.instance))
		{
			return !instance.grabbed;
		}
		return false;
	}

	private void BeginHolyEffects(Vector3 center)
	{
		//IL_0001: 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)
		holyEffectCenter = center;
		holyEffectPhase = 0;
		holyEffectNext = Time.time;
		holyEffectUntil = Time.time + 3f;
	}

	private void UpdateHolyEffects()
	{
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		if (holyEffectPhase < 0)
		{
			return;
		}
		if (Time.time >= holyEffectUntil || !WorldReady() || !RoleEnabled || !Object.op_Implicit((Object)(object)holyFieldCaster))
		{
			holyEffectPhase = -1;
		}
		else
		{
			if (Time.time < holyEffectNext)
			{
				return;
			}
			holyEffectNext = Time.time + 0.15f;
			int phase = holyEffectPhase++;
			if (!Object.op_Implicit((Object)(object)guestChargeCarrier) || !Object.op_Implicit((Object)(object)guestChargeDrone) || !Object.op_Implicit((Object)(object)guestChargeDrone.teleportParticles) || Time.unscaledTime < guestChargeReadyAt)
			{
				return;
			}
			holyEffectCenter = ((Component)holyFieldCaster).transform.position;
			if (!Finite(holyEffectCenter))
			{
				return;
			}
			for (int i = 0; i < 12; i += 2)
			{
				try
				{
					network.Rpc(guestChargeCarrier, "TeleportEffectRPC", false, HolyFlashPoint(phase, i), HolyFlashPoint(phase, i + 1));
				}
				catch (Exception ex)
				{
					GuestChargeWarning("Holy light effect failed: " + ex.Message);
				}
			}
		}
	}

	private Vector3 HolyFlashPoint(int phase, int index)
	{
		//IL_0041: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		float num = MathF.PI * 2f * (float)index / 12f + (float)phase * 0.73f;
		float num2 = 2f + (float)((phase + index) % 4) * 2f;
		float num3 = 0.4f + (float)((phase * 2 + index) % 5) * 0.45f;
		return holyEffectCenter + new Vector3(Mathf.Cos(num) * num2, num3, Mathf.Sin(num) * num2);
	}

	private void CastHoly()
	{
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!rules.Busy || !rules.HolySelected || !rules.HolyAvailable || !rules.CanChargeSelected || !ControlsReady() || !EmptyHands() || !SemiFunc.RunIsLevel())
			{
				return;
			}
			Vector3 center = ((Component)instance).transform.position;
			if (!Finite(center))
			{
				return;
			}
			PlayerAvatar[] source = (from p in SemiFunc.PlayerGetList()
				where Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)p.playerHealth) && (bool)spawned.GetValue(p)
				select p).ToArray();
			PlayerAvatar[] array = source.Where((PlayerAvatar p) => HolyDeadInRange(p, center)).ToArray();
			PlayerAvatar[] array2 = source.Where((PlayerAvatar p) => !(bool)dead.GetValue(p) && !(bool)disabled.GetValue(p) && HolyWithin(center, ((Component)p).transform.position)).ToArray();
			CommitCast();
			ResetHolyField();
			holyFieldCaster = instance;
			holyFieldUntil = Time.time + 3f;
			int num = ApplyHolyEnemies(center);
			int num2 = 0;
			int num3 = 0;
			PlayerAvatar[] array3 = array;
			foreach (PlayerAvatar val in array3)
			{
				try
				{
					if (Object.op_Implicit((Object)(object)val) && (bool)dead.GetValue(val))
					{
						val.Revive(false);
						if (!(bool)dead.GetValue(val))
						{
							val.playerHealth.HealOther(24, false);
							num2++;
						}
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Holy] Revival failed; no retry: " + ex));
				}
			}
			array3 = array2;
			foreach (PlayerAvatar val2 in array3)
			{
				try
				{
					if (Object.op_Implicit((Object)(object)val2) && !(bool)dead.GetValue(val2) && !(bool)disabled.GetValue(val2))
					{
						val2.playerHealth.HealOther(25, true);
						num3++;
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Holy] Healing failed; no retry: " + ex2));
				}
			}
			BeginHolyEffects(center);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[Holly Flush] Cast complete; enemies=" + num + "; revives=" + num2 + "; healing requests=" + num3));
		}
		finally
		{
			rules.EndCast();
		}
	}

	private void ResetHolyField()
	{
		holyFieldUntil = -1f;
		holyFieldCaster = null;
		holyAffectedEnemies.Clear();
	}

	private void UpdateHolyField()
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (!(holyFieldUntil < 0f))
		{
			if (Time.time >= holyFieldUntil || !WorldReady() || !RoleEnabled || !SemiFunc.RunIsLevel() || !Object.op_Implicit((Object)(object)holyFieldCaster) || (bool)dead.GetValue(holyFieldCaster))
			{
				ResetHolyField();
			}
			else
			{
				ApplyHolyEnemies(((Component)holyFieldCaster).transform.position);
			}
		}
	}

	private int ApplyHolyEnemies(Vector3 center)
	{
		//IL_0000: 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)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if (!Finite(center))
		{
			return 0;
		}
		int num = 0;
		EnemyHealth[] array = Object.FindObjectsOfType<EnemyHealth>();
		foreach (EnemyHealth val in array)
		{
			try
			{
				if (!holyAffectedEnemies.Contains(val) && HolyEnemyInRange(val, center))
				{
					holyAffectedEnemies.Add(val);
					holyEnemyHealth.SetValue(val, 0);
					val.Hurt(0, Vector3.up);
					num++;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Holy] Enemy death failed; no retry: " + ex));
			}
		}
		return num;
	}

	private static bool HolyWithin(Vector3 center, Vector3 point)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if (Finite(center) && Finite(point))
		{
			Vector3 val = point - center;
			return HolyRules.Within(((Vector3)(ref val)).sqrMagnitude);
		}
		return false;
	}

	private static bool HolyEnemyInRange(EnemyHealth health, Vector3 center)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)health) || !((Component)health).gameObject.activeInHierarchy || (bool)holyEnemyDead.GetValue(health) || (bool)holyEnemyDying.GetValue(health))
		{
			return false;
		}
		EnemyParent componentInParent = ((Component)health).GetComponentInParent<EnemyParent>();
		if (Object.op_Implicit((Object)(object)componentInParent) && !(bool)holyEnemySpawned.GetValue(componentInParent))
		{
			return false;
		}
		Enemy component = ((Component)health).GetComponent<Enemy>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return HolyWithin(center, Object.op_Implicit((Object)(object)component.CenterTransform) ? component.CenterTransform.position : ((Component)component).transform.position);
		}
		return false;
	}

	private static bool HolyDeadInRange(PlayerAvatar target, Vector3 center)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		if (!(bool)dead.GetValue(target) || !(bool)disabled.GetValue(target))
		{
			return false;
		}
		object? value = holyDeathHead.GetValue(target);
		PlayerDeathHead val = (PlayerDeathHead)((value is PlayerDeathHead) ? value : null);
		if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val.playerAvatar != (Object)(object)target || !((Component)val).gameObject.activeInHierarchy || !(bool)holyHeadSetup.GetValue(val) || !(bool)holyHeadTriggered.GetValue(val))
		{
			return false;
		}
		PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return HolyWithin(center, component.centerPoint);
		}
		return false;
	}

	private void StopHostChargeAudio()
	{
		HostChargeAudio obj = hostChargeAudio;
		hostChargeAudio = null;
		obj?.Dispose();
	}

	private void UpdateHostChargeAudio(bool allowed, double duration)
	{
		try
		{
			if (!allowed || rules.Charge <= 0.0 || !rules.CanChargeSelected)
			{
				StopHostChargeAudio();
				return;
			}
			if (hostChargeAudio != null && audioSpell != rules.Selected)
			{
				StopHostChargeAudio();
			}
			if (hostChargeAudio == null)
			{
				if (Time.unscaledTime < nextAudioAttempt)
				{
					return;
				}
				int num = (int)(rules.HolySelected ? Spell.ZeroGravity : rules.Selected);
				Sound[] array = chargeAudioSources[num];
				if (array == null)
				{
					return;
				}
				hostChargeAudio = new HostChargeAudio(array);
				audioSpell = rules.Selected;
			}
			hostChargeAudio.Tick(rules.Charge >= duration, LookingUp());
		}
		catch (Exception ex)
		{
			nextAudioAttempt = Time.unscaledTime + 1f;
			StopHostChargeAudio();
			if (!(Time.unscaledTime < nextAudioWarning))
			{
				nextAudioWarning = Time.unscaledTime + 30f;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Wizard local charge sound failed; magic remains enabled: " + ex));
			}
		}
	}

	private void HideHud()
	{
		if (Object.op_Implicit((Object)(object)hud))
		{
			hud.SetActive(false);
		}
	}

	private void DestroyHud()
	{
		Canvas val = hudCanvas;
		GameObject val2 = hud;
		hud = null;
		hudCanvas = null;
		holyGraphic = null;
		holyFill = null;
		manaBars.Clear();
		manaColorGraphics.Clear();
		lastManaPalette = null;
		holyBorder.Clear();
		if (Object.op_Implicit((Object)(object)val))
		{
			Object.Destroy((Object)(object)((Component)val).gameObject);
		}
		else if (Object.op_Implicit((Object)(object)val2))
		{
			Object.Destroy((Object)(object)val2);
		}
	}

	private bool HudIsValid()
	{
		if (!Object.op_Implicit((Object)(object)hud) || !Object.op_Implicit((Object)(object)hudCanvas) || !Object.op_Implicit((Object)(object)holyFill) || !Object.op_Implicit((Object)(object)holyGraphic) || manaBars.Count != 10 || manaColorGraphics.Count != 14 || holyBorder.Count != 4)
		{
			return false;
		}
		foreach (GameObject manaBar in manaBars)
		{
			if (!Object.op_Implicit((Object)(object)manaBar))
			{
				return false;
			}
		}
		foreach (Component manaColorGraphic in manaColorGraphics)
		{
			if (!Object.op_Implicit((Object)(object)manaColorGraphic))
			{
				return false;
			}
		}
		foreach (Component item in holyBorder)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return false;
			}
		}
		return true;
	}

	private void UpdateHud(bool show)
	{
		try
		{
			RefreshHud(show);
		}
		catch (Exception error)
		{
			HudFailed(error);
		}
	}

	private void HudFailed(Exception error)
	{
		nextHudAttempt = Time.unscaledTime + 1f;
		try
		{
			DestroyHud();
		}
		catch
		{
		}
		if (!(Time.unscaledTime < nextHudWarning))
		{
			nextHudWarning = Time.unscaledTime + 30f;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Wizard HUD rebuilt after a rendering failure; magic input remains enabled: " + error));
		}
	}

	private void RefreshHud(bool show)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//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)
		//IL_00a1: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		if (!show)
		{
			HideHud();
			return;
		}
		if (!HudIsValid())
		{
			if (Time.unscaledTime < nextHudAttempt)
			{
				return;
			}
			nextHudAttempt = Time.unscaledTime + 1f;
			BuildHud();
		}
		hud.SetActive(true);
		Transform transform = ((Component)hudCanvas).transform;
		RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		float num;
		if (Object.op_Implicit((Object)(object)val))
		{
			Rect rect = val.rect;
			if (((Rect)(ref rect)).width > 0f)
			{
				rect = val.rect;
				num = ((Rect)(ref rect)).width / 1920f;
				goto IL_008f;
			}
		}
		num = 1f;
		goto IL_008f;
		IL_008f:
		float num2 = num;
		RectTransform val2 = (RectTransform)hud.transform;
		((Transform)val2).localScale = Vector3.one * (num2 * 0.7f);
		val2.anchoredPosition = new Vector2(-110f * num2, 28f * num2);
		bool flag = !rules.Busy && rules.CanChargeSelected && rules.Charge >= ChargeDuration();
		ManaPalette manaPalette = ((!rules.HolySelected) ? (flag ? ManaPalette.Charged : ManaPalette.Normal) : (flag ? ManaPalette.HolyReady : ManaPalette.HolyCharging));
		if (lastManaPalette != manaPalette)
		{
			Color val3 = (Color)(manaPalette switch
			{
				ManaPalette.Charged => ManaCharged, 
				ManaPalette.HolyCharging => ManaHolyUnready, 
				ManaPalette.HolyReady => ManaHoly, 
				_ => ManaBlue, 
			});
			foreach (Component manaColorGraphic in manaColorGraphics)
			{
				SetHudProperty(manaColorGraphic, "color", val3);
			}
			lastManaPalette = manaPalette;
		}
		for (int i = 0; i < manaBars.Count; i++)
		{
			manaBars[i].SetActive(i < rules.Mana);
		}
		float num3 = Mathf.Clamp01((float)rules.HolyProgress);
		if (Object.op_Implicit((Object)(object)holyFill))
		{
			holyFill.sizeDelta = new Vector2(91f * num3, 16f);
		}
		Color val4 = (rules.HolyAvailable ? ManaHoly : ManaHolyUnready);
		if (Object.op_Implicit((Object)(object)holyGraphic))
		{
			SetHudProperty(holyGraphic, "color", val4);
		}
		foreach (Component item in holyBorder)
		{
			SetHudProperty(item, "color", val4);
		}
	}

	private static void SetHudProperty(Component target, string name, object value)
	{
		((object)target).GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public)?.SetValue(target, value);
	}

	private bool BuildHud()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Expected O, but got Unknown
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_039c: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bd: Expected O, but got Unknown
		DestroyHud();
		Type type = Type.GetType("UnityEngine.UI.RawImage, UnityEngine.UI", throwOnError: true);
		GameObject val = new GameObject("HostGreatWizard Mana Canvas", new Type[2]
		{
			typeof(RectTransform),
			typeof(Canvas)
		});
		hudCanvas = val.GetComponent<Canvas>();
		hudCanvas.renderMode = (RenderMode)0;
		hudCanvas.sortingOrder = 100;
		hud = new GameObject("HostGreatWizard Mana", new Type[1] { typeof(RectTransform) });
		hud.SetActive(false);
		RectTransform val2 = (RectTransform)hud.transform;
		((Transform)val2).SetParent(val.transform, false);
		Vector2 val3 = default(Vector2);
		((Vector2)(ref val3))..ctor(1f, 0f);
		val2.anchorMax = val3;
		val2.anchorMin = val3;
		val2.pivot = new Vector2(1f, 0f);
		val2.sizeDelta = new Vector2(210f, 198f);
		CreateGraphic(type, "Mana background", Vector2.zero, new Vector2(210f, 62f), new Color(0.06f, 0.06f, 0.06f, 0.9f));
		CreateManaGraphic(type, "Mana bottom border", Vector2.zero, new Vector2(210f, 4f));
		CreateManaGraphic(type, "Mana top border", new Vector2(0f, 58f), new Vector2(210f, 4f));
		CreateManaGraphic(type, "Mana left border", new Vector2(0f, 4f), new Vector2(4f, 54f));
		CreateManaGraphic(type, "Mana right border", new Vector2(206f, 4f), new Vector2(4f, 54f));
		for (int i = 0; i < 10; i++)
		{
			manaBars.Add(CreateManaGraphic(type, "Mana " + (i + 1), new Vector2(14f + (float)i * 18.3f, 15f), new Vector2(16f, 32f)));
		}
		CreateGraphic(type, "Holly Flush background", new Vector2(-123f, 0f), new Vector2(105f, 31f), new Color(0.06f, 0.06f, 0.06f, 0.9f));
		holyBorder.Add(CreateGraphic(type, "Holly Flush bottom border", new Vector2(-123f, 0f), new Vector2(105f, 2f), ManaHolyUnready).GetComponent(type));
		holyBorder.Add(CreateGraphic(type, "Holly Flush top border", new Vector2(-123f, 29f), new Vector2(105f, 2f), ManaHolyUnready).GetComponent(type));
		holyBorder.Add(CreateGraphic(type, "Holly Flush left border", new Vector2(-123f, 2f), new Vector2(2f, 27f), ManaHolyUnready).GetComponent(type));
		holyBorder.Add(CreateGraphic(type, "Holly Flush right border", new Vector2(-20f, 2f), new Vector2(2f, 27f), ManaHolyUnready).GetComponent(type));
		GameObject val4 = CreateGraphic(type, "Holly Flush fill", new Vector2(-116f, 7.5f), new Vector2(0f, 16f), ManaHolyUnready);
		holyFill = (RectTransform)val4.transform;
		holyGraphic = val4.GetComponent(type);
		((Transform)val2).SetAsLastSibling();
		return true;
	}

	private void OnGUI()
	{
		try
		{
			DrawSpellLabel();
		}
		catch (Exception error)
		{
			HudFailed(error);
		}
	}

	private void DrawSpellLabel()
	{
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Expected O, but got Unknown
		//IL_0072: Expected O, but got Unknown
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)hud) || !hud.activeInHierarchy || !RoleEnabled)
		{
			return;
		}
		if (spellStyle == null)
		{
			spellStyle = new GUIStyle(GUI.skin.label)
			{
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)0,
				clipping = (TextClipping)0,
				wordWrap = false,
				richText = false,
				padding = new RectOffset(0, 0, 0, 0)
			};
		}
		((RectTransform)hud.transform).GetWorldCorners(hudCorners);
		float num = (hudCorners[3].x - hudCorners[0].x) / 210f;
		if (num <= 0f)
		{
			return;
		}
		spellStyle.fontSize = Mathf.Max(12, Mathf.RoundToInt(32f * num));
		spellStyle.normal.textColor = Color.white;
		Matrix4x4 matrix = GUI.matrix;
		Color color = GUI.color;
		Color contentColor = GUI.contentColor;
		bool enabled = GUI.enabled;
		int depth = GUI.depth;
		try
		{
			GUI.matrix = Matrix4x4.identity;
			GUI.color = (GUI.contentColor = Color.white);
			GUI.enabled = true;
			GUI.depth = -101;
			GUI.Label(new Rect(hudCorners[0].x + 4f * num, (float)Screen.height - hudCorners[0].y - 108f * num, 240f * num, 42f * num), SpellNames[(int)rules.Selected], spellStyle);
		}
		finally
		{
			GUI.matrix = matrix;
			GUI.color = color;
			GUI.contentColor = contentColor;
			GUI.enabled = enabled;
			GUI.depth = depth;
		}
	}

	private GameObject CreateGraphic(Type rawType, string name, Vector2 position, Vector2 size, Color color)
	{
		//IL_0014: 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_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_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_0054: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Expected O, but got Unknown
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		RectTransform val2 = (RectTransform)val.transform;
		((Transform)val2).SetParent(hud.transform, false);
		Vector2 val3 = (val2.pivot = Vector2.zero);
		Vector2 anchorMin = (val2.anchorMax = val3);
		val2.anchorMin = anchorMin;
		((Transform)val2).localScale = Vector3.one;
		((Transform)val2).localRotation = Quaternion.identity;
		val2.anchoredPosition3D = new Vector3(position.x, position.y, 0f);
		val2.sizeDelta = size;
		Component target = val.AddComponent(rawType);
		SetHudProperty(target, "texture", Texture2D.whiteTexture);
		SetHudProperty(target, "uvRect", (object)new Rect(0f, 0f, 1f, 1f));
		SetHudProperty(target, "material", null);
		SetHudProperty(target, "color", color);
		SetHudProperty(target, "raycastTarget", false);
		return val;
	}

	private GameObject CreateManaGraphic(Type rawType, string name, Vector2 position, Vector2 size)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: 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)
		GameObject val = CreateGraphic(rawType, name, position, size, ManaBlue);
		manaColorGraphics.Add(val.GetComponent(rawType));
		return val;
	}

	private static FieldInfo Field(Type type, string name)
	{
		return AccessTools.Field(type, name) ?? throw new MissingFieldException(type.Name, name);
	}

	private void Awake()
	{
		//IL_005a: 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_0089: Expected O, but got Unknown
		try
		{
			modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the wizard for the local host or single player only.");
			nativeStaffCharge = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "UseNativeStaffCharge", true, "Tiny stock staff charge effects for unmodded guests. Hold the spell key and look up to charge; retain native effects while full charge is held. False restores drone charge flashes.");
			switchKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "SwitchSpellKey", new KeyboardShortcut((KeyCode)114, Array.Empty<KeyCode>()), "Short tap and release to switch spell while empty-handed. Hold this key while looking upward more than 50 degrees for 0.3 seconds to charge. Full charge stays ready when looking away; press Interact to fire.");
			network = new NativeNetwork();
			harmony = new Harmony("local.bei.hostgreatwizard");
			Current = this;
			harmony.PatchAll(typeof(Plugin).Assembly);
			RegisterRole();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"HostGreatWizard 0.7.16 loaded: hold spell key and look up to charge in 0.3 seconds, retain full charge. Holly Flush: 13-minute rechargeable gauge, cost 1 mana.");
		}
		catch (Exception ex)
		{
			((Behaviour)this).enabled = false;
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
	}

	private bool WorldReady()
	{
		if (Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.MenuLevel() && (Object)(object)LevelGenerator.Instance != (Object)null)
		{
			return LevelGenerator.Instance.Generated;
		}
		return false;
	}

	private bool ControlsReady()
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Invalid comparison between Unknown and I4
		PlayerAvatar instance = PlayerAvatar.instance;
		if (WorldReady() && RoleEnabled && !RoleMenu.InputBlocked && Object.op_Implicit((Object)(object)GameDirector.instance) && !GameDirector.instance.DisableInput && (int)GameDirector.instance.currentState == 2 && Time.timeScale > 0f && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)PlayerController.instance) && Object.op_Implicit((Object)(object)PhysGrabber.instance) && Object.op_Implicit((Object)(object)InputManager.instance) && !(bool)dead.GetValue(instance) && !(bool)disabled.GetValue(instance) && !(bool)tumbling.GetValue(instance) && (bool)spawned.GetValue(instance) && (float)inputDisabled.GetValue(PlayerController.instance) <= 0f && (!Object.op_Implicit((Object)(object)MenuManager.instance) || (int)menuState.GetValue(MenuManager.instance) != 0) && (!Object.op_Implicit((Object)(object)ChatManager.instance) || !(bool)chatActive.GetValue(ChatManager.instance)) && (!Object.op_Implicit((Object)(object)instance.mapToolController) || !(bool)mapActive.GetValue(instance.mapToolController)))
		{
			return GUIUtility.keyboardControl == 0;
		}
		return false;
	}

	private void LateUpdate()
	{
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Invalid comparison between Unknown and I4
		try
		{
			if (!Object.op_Implicit((Object)(object)GameManager.instance) || !Object.op_Implicit((Object)(object)RunManager.instance) || SemiFunc.MenuLevel() || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				DestroyChargeEffects();
				DestroyGuestChargeCarrier();
				ResetHolyField();
				DestroyHud();
				castInput.Cancel(rules);
				session = null;
				stage = null;
				return;
			}
			object obj = (SemiFunc.IsMultiplayer() ? network.Room : RunManager.instance);
			if (session != obj)
			{
				session = obj;
				rules = new WizardRules();
				castInput.Cancel(rules);
				DestroyChargeEffects();
				DestroyGuestChargeCarrier();
				ResetHolyField();
			}
			if (stage != LevelGenerator.Instance)
			{
				stage = LevelGenerator.Instance;
				rules.BeginLevel();
				DestroyHud();
				castInput.Cancel(rules);
				DestroyChargeEffects();
				DestroyGuestChargeCarrier();
				ResetHolyField();
			}
			bool flag = WorldReady();
			if (flag && SemiFunc.RunIsLevel() && Object.op_Implicit((Object)(object)GameDirector.instance) && (int)GameDirector.instance.currentState == 2)
			{
				rules.TickLevel(Time.deltaTime);
			}
			if (flag && RoleEnabled)
			{
				rules.Recover(Time.deltaTime);
			}
			bool flag2 = ControlsReady();
			bool flag3 = flag2 && EmptyHands();
			if (!RoleEnabled || !flag)
			{
				DestroyChargeEffects();
			}
			if (flag && RoleEnabled)
			{
				FindSpellSources();
			}
			double duration = ChargeDuration();
			bool interact = Object.op_Implicit((Object)(object)InputManager.instance) && InputManager.instance.KeyHold((InputKey)2);
			if (castInput.Step(rules, flag2, SpellModifierHeld(), LookingUp(), interact, Time.deltaTime, duration, !flag3, interactionGate.IsBlocked(Time.frameCount, Time.time)))
			{
				if (rules.HolySelected)
				{
					CastHoly();
				}
				else
				{
					CastProjectile();
				}
			}
			UpdateHolyField();
			UpdateChargeEffects(flag2, duration);
			UpdateHostChargeAudio(flag2, duration);
			UpdateGuestChargeEffects(flag3, duration);
			UpdateGuestStaffEffects(flag3);
			UpdateHolyEffects();
			UpdateHud(flag2);
		}
		catch (Exception ex)
		{
			rules.EndCast();
			castInput.Cancel(rules);
			DestroyChargeEffects();
			DestroyGuestChargeCarrier();
			ResetHolyField();
			if (Time.unscaledTime >= nextWarning)
			{
				nextWarning = Time.unscaledTime + 10f;
				((BaseUnityPlugin)this).Logger.LogError((object)("Wizard operation failed: " + ex));
			}
		}
	}

	private bool SpellModifierHeld()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = switchKey.Value;
		if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !UnityInput.Current.GetKey(((KeyboardShortcut)(ref value)).MainKey))
		{
			return false;
		}
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
		{
			if (!UnityInput.Current.GetKey(modifier))
			{
				return false;
			}
		}
		return true;
	}

	private bool LookingUp()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		PlayerAvatar instance = PlayerAvatar.instance;
		PlayerLocalCamera val = (Object.op_Implicit((Object)(object)instance) ? instance.localCamera : null);
		Transform val2 = (Object.op_Implicit((Object)(object)val) ? val.GetOverrideTransform() : null);
		if (Object.op_Implicit((Object)(object)val2))
		{
			return WizardRules.IsLookingUp(val2.eulerAngles.x);
		}
		return false;
	}

	private void CommitCast()
	{
		rules.Commit();
	}

	internal void ObserveInteractionPrompt(string raw, string localized)
	{
		if (InteractionFireGate.IsInteractionPrompt(raw, localized))
		{
			ObserveLocalInteraction();
		}
	}

	internal void ObserveLocalInteraction()
	{
		interactionGate.Observe(Time.frameCount, Time.time);
	}

	private void OnDestroy()
	{
		RoleMenu.Unregister("local.bei.hostgreatwizard");
		try
		{
			DestroyChargeEffects();
			DestroyGuestChargeCarrier();
			ResetHolyField();
		}
		finally
		{
			DestroyHud();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)Current == (Object)(object)this)
			{
				Current = null;
			}
		}
	}

	private void OnDisable()
	{
		try
		{
			DestroyChargeEffects();
			DestroyGuestChargeCarrier();
			ResetHolyField();
		}
		finally
		{
			HideHud();
			castInput.Cancel(rules);
		}
	}

	private void RegisterRole()
	{
		RoleMenu.Register("local.bei.hostgreatwizard", "Great Wizard", "Hold spell key (default R) + look up: charge 0.3s. E: fire. Tap spell key: switch. Holly Flush: 13-minute gauge, costs 1 mana, reusable after refill.", 1, (Func<bool>)(() => ((Behaviour)this).isActiveAndEnabled && modEnabled.Value), (Action<bool>)ApplyRole);
	}

	private void ApplyRole(bool active)
	{
		if (!active)
		{
			ResetHolyField();
			rules.CancelCharge();
			DestroyChargeEffects();
			DestroyGuestChargeCarrier();
			HideHud();
			castInput.Cancel(rules);
		}
	}

	private double ChargeDuration()
	{
		return WizardRules.ChargeSeconds(rules.Selected);
	}

	private void FindSpellSources()
	{
		if ((projectiles.All((PrefabRef p) => ((PrefabRef<GameObject>)(object)p)?.IsValid() ?? false) && chargeSources.All((ParticleSystem p) => Object.op_Implicit((Object)(object)p)) && loadedSources.All((ParticleSystem p) => Object.op_Implicit((Object)(object)p)) && chargeAudioSources.All((Sound[] p) => p != null)) || !Object.op_Implicit((Object)(object)StatsManager.instance) || Time.unscaledTime < nextCatalog)
		{
			return;
		}
		nextCatalog = Time.unscaledTime + 2f;
		foreach (Item allItem in Items.AllItems)
		{
			if (!Object.op_Implicit((Object)(object)allItem) || allItem.prefab == null || !((PrefabRef<GameObject>)(object)allItem.prefab).IsValid())
			{
				continue;
			}
			string text = new string((((PrefabRef<GameObject>)(object)allItem.prefab).PrefabName ?? "").Where(char.IsLetterOrDigit).ToArray()).ToLowerInvariant();
			if (text != "itemstafftorque" && text != "itemstaffzerogravity" && text != "itemstaffvoid")
			{
				continue;
			}
			GameObject prefab = ((PrefabRef<GameObject>)(object)allItem.prefab).Prefab;
			if (Object.op_Implicit((Object)(object)prefab))
			{
				ItemStaffTorque component = prefab.GetComponent<ItemStaffTorque>();
				ItemStaffZeroGravity component2 = prefab.GetComponent<ItemStaffZeroGravity>();
				ItemStaffVoid component3 = prefab.GetComponent<ItemStaffVoid>();
				if (Object.op_Implicit((Object)(object)component))
				{
					chargeAudioSources[0] = (Sound[])(object)new Sound[5] { component.chargeUpSound, component.lightning01Sound, component.choir02Sound, component.loadedHighSoundLoop, component.loadedLowSoundLoop };
					projectiles[0] = component.projectilePrefab;
					chargeSources[0] = component.chargeUpParticles;
					loadedSources[0] = component.loadedParticles;
				}
				if (Object.op_Implicit((Object)(object)component2))
				{
					chargeAudioSources[1] = (Sound[])(object)new Sound[5] { component2.chargeUpSound, component2.lightning01Sound, component2.choir02Sound, component2.loadedHighSoundLoop, component2.loadedLowSoundLoop };
					projectiles[1] = component2.projectilePrefab;
					chargeSources[1] = component2.chargeUpParticles;
					loadedSources[1] = component2.loadedParticles;
				}
				if (Object.op_Implicit((Object)(object)component3))
				{
					chargeAudioSources[2] = (Sound[])(object)new Sound[5] { component3.chargeUpSound, component3.lightning01Sound, component3.choir02Sound, component3.loadedHighSoundLoop, component3.loadedLowSoundLoop };
					projectiles[2] = component3.projectilePrefab;
					voidOnHit = component3.prefabToInstantiateOnHit;
					chargeSources[2] = component3.chargeUpParticles;
					loadedSources[2] = component3.loadedParticles;
					voidActiveSource = component3.loadedActiveParticles;
				}
			}
		}
	}

	private bool Aim(out Vector3 origin, out Quaternion rotation)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: 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)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		origin = default(Vector3);
		rotation = Quaternion.identity;
		PlayerAvatar instance = PlayerAvatar.instance;
		PhysGrabber instance2 = PhysGrabber.instance;
		Camera val = (Camera)(Object.op_Implicit((Object)(object)instance2) ? /*isinst with value type is only supported in some contexts*/: null);
		if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		FlashlightController flashlightController = instance.flashlightController;
		Transform hand = (Object.op_Implicit((Object)(object)flashlightController) ? flashlightController.FollowTransformClient : null);
		if (!Object.op_Implicit((Object)(object)instance.PlayerVisionTarget) || !Object.op_Implicit((Object)(object)instance.PlayerVisionTarget.VisionTransform))
		{
			return false;
		}
		Vector3 position = instance.PlayerVisionTarget.VisionTransform.position;
		bool crouched = (bool)muzzleCrouching.GetValue(instance) || (bool)muzzleCrawling.GetValue(instance);
		if (!SpellMuzzle.TryPosition(crouched, position, hand, out origin))
		{
			return false;
		}
		origin = SpellMuzzle.ForwardOffset(crouched, origin, ((Component)val).transform.forward);
		Ray val2 = val.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
		Vector3 val3 = ((Ray)(ref val2)).origin + ((Ray)(ref val2)).direction * 50f;
		int num = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct());
		foreach (RaycastHit item in from h in Physics.RaycastAll(val2, 50f, num | LayerMask.GetMask(new string[1] { "Enemy" }), (QueryTriggerInteraction)1)
			orderby ((RaycastHit)(ref h)).distance
			select h)
		{
			RaycastHit current = item;
			if (!((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<PlayerAvatar>() == (Object)(object)instance) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<PlayerController>()))
			{
				val3 = ((RaycastHit)(ref current)).point;
				break;
			}
		}
		Vector3 val4 = origin - position;
		if (((Vector3)(ref val4)).sqrMagnitude > 0.001f)
		{
			foreach (RaycastHit item2 in from hit in Physics.RaycastAll(position, ((Vector3)(ref val4)).normalized, ((Vector3)(ref val4)).magnitude, num, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref hit)).distance
				select hit)
			{
				RaycastHit current2 = item2;
				if (!((Object)(object)((Component)((RaycastHit)(ref current2)).collider).GetComponentInParent<PlayerAvatar>() == (Object)(object)instance) && !((Object)(object)((Component)((RaycastHit)(ref current2)).collider).GetComponentInParent<PlayerController>() == (Object)(object)PlayerController.instance))
				{
					origin = ((RaycastHit)(ref current2)).point - ((Vector3)(ref val4)).normalized * 0.06f;
					break;
				}
			}
		}
		Vector3 val5 = val3 - origin;
		if (Vector3.Dot(val5, ((Component)val).transform.forward) < 0.05f)
		{
			val5 = ((Component)val).transform.forward;
		}
		if (!Finite(origin) || !Finite(val5))
		{
			return false;
		}
		rotation = Quaternion.LookRotation(val5, ((Component)val).transform.up);
		return true;
	}

	private static bool Finite(Vector3 v)
	{
		//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if (!float.IsNaN(v.x) && !float.IsInfinity(v.x) && !float.IsNaN(v.y) && !float.IsInfinity(v.y) && !float.IsNaN(v.z))
		{
			return !float.IsInfinity(v.z);
		}
		return false;
	}

	private void CastProjectile()
	{
		//IL_0046: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = null;
		bool flag = false;
		try
		{
			PrefabRef val2 = projectiles[(int)rules.Selected];
			if (val2 == null || !((PrefabRef<GameObject>)(object)val2).IsValid() || !Object.op_Implicit((Object)(object)((PrefabRef<GameObject>)(object)val2).Prefab.GetComponent<SlowProjectile>()) || !Aim(out var origin, out var rotation))
			{
				return;
			}
			val = NetworkPrefabs.SpawnNetworkPrefab(val2, origin, rotation, (byte)0, (object[])null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Native projectile did not spawn.");
			}
			SlowProjectile component = val.GetComponent<SlowProjectile>();
			PlayerAvatar instance = PlayerAvatar.instance;
			projectilePlayer.SetValue(component, instance);
			component.investigateRadiusOnHit = 24f;
			if (rules.Selected == Spell.Void)
			{
				component.prefabToInstantiateOnHit = voidOnHit;
				val.AddComponent<WizardVoidOwner>().Caster = instance;
			}
			component.SetSpawner(((Component)instance).gameObject);
			HurtCollider[] componentsInChildren = val.GetComponentsInChildren<HurtCollider>(true);
			foreach (HurtCollider val3 in componentsInChildren)
			{
				hurtPlayer.SetValue(val3, instance);
				bool impactArea = (Object)(object)val3 == (Object)(object)component.areaOfEffectHurtCollider || Object.op_Implicit((Object)(object)((Component)val3).GetComponentInParent<SemiAreaOfEffect>());
				if (WizardRules.IgnoreCaster(rules.Selected, impactArea))
				{
					val3.ignorePlayers.Add(instance);
				}
			}
			CommitCast();
			flag = true;
			component.Launch(rotation * Vector3.forward);
			SemiFunc.PlayerShopKeeperShotGunHost(instance);
		}
		finally
		{
			if (!flag && Object.op_Implicit((Object)(object)val))
			{
				network.Destroy(val);
			}
			rules.EndCast();
		}
	}
}
internal sealed class GuestChargePulse
{
	private bool active;

	private bool ready;

	private double next;

	internal void Reset()
	{
		active = (ready = false);
		next = 0.0;
	}

	internal bool Step(bool charging, bool full, bool carrierReady, double now)
	{
		if (!charging)
		{
			Reset();
			return false;
		}
		if (!carrierReady)
		{
			return false;
		}
		if (!full)
		{
			ready = false;
		}
		if (!active || (full && !ready) || now >= next)
		{
			active = true;
			ready = full;
			next = now + 1.0;
			return true;
		}
		return false;
	}
}
internal static class HolyRules
{
	internal const double Radius = 10.0;

	internal const float Duration = 3f;

	internal const float FlashInterval = 0.15f;

	internal const int FlashesPerPulse = 12;

	internal static bool Within(double squaredDistance)
	{
		if (!double.IsNaN(squaredDistance) && squaredDistance >= 0.0)
		{
			return squaredDistance <= 100.0;
		}
		return false;
	}
}
internal sealed class HostChargeAudio : IDisposable
{
	private readonly GameObject root;

	private readonly Sound[] sounds;

	private bool ready;

	private bool lowLoaded;

	private bool disposed;

	internal HostChargeAudio(Sound[] templates)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Expected O, but got Unknown
		root = new GameObject("HostGreatWizard Local Staff Audio");
		sounds = (Sound[])(object)new Sound[templates.Length];
		try
		{
			for (int i = 0; i < templates.Length; i++)
			{
				Sound val = templates[i];
				if (val != null && val.Sounds != null && val.Sounds.Length != 0)
				{
					GameObject val2 = new GameObject("Staff Sound " + i);
					val2.transform.SetParent(root.transform, false);
					AudioSource val3 = val2.AddComponent<AudioSource>();
					val3.playOnAwake = false;
					AudioSource val4 = val.Source;
					if (!Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)AudioManager.instance) && Object.op_Implicit((Object)(object)AudioManager.instance.AudioDefault))
					{
						val4 = AudioManager.instance.AudioDefault.GetComponent<AudioSource>();
					}
					if (Object.op_Implicit((Object)(object)val4))
					{
						val3.outputAudioMixerGroup = val4.outputAudioMixerGroup;
					}
					Sound val5 = new Sound();
					Sound.CopySound(val, val5);
					val5.Source = val3;
					val5.SpatialBlend = 0f;
					val5.Doppler = 0f;
					val5.OffscreenVolume = (val5.OffscreenFalloff = 1f);
					sounds[i] = val5;
				}
			}
			Sound obj = sounds[0];
			if (obj != null)
			{
				obj.Play(Vector3.zero, 1f, 1f, 1f, 1f);
			}
		}
		catch
		{
			Dispose();
			throw;
		}
	}

	internal void Tick(bool full, bool lookingUp)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (disposed)
		{
			return;
		}
		if (full && !ready)
		{
			Sound obj = sounds[1];
			if (obj != null)
			{
				obj.Play(Vector3.zero, 1f, 1f, 1f, 1f);
			}
		}
		if (!full)
		{
			lowLoaded = false;
		}
		else if (!lookingUp)
		{
			lowLoaded = true;
		}
		ready = full;
		bool flag = lookingUp && !lowLoaded;
		Sound obj2 = sounds[2];
		if (obj2 != null)
		{
			obj2.PlayLoop(flag, 2f, 1f, 1f, 1f);
		}
		Sound obj3 = sounds[3];
		if (obj3 != null)
		{
			obj3.PlayLoop(full && !lowLoaded, 2f, 1f, 1f, 1f);
		}
		Sound obj4 = sounds[4];
		if (obj4 != null)
		{
			obj4.PlayLoop(full && lowLoaded, 2f, 1f, 1f, 1f);
		}
	}

	public void Dispose()
	{
		if (disposed)
		{
			return;
		}
		disposed = true;
		Sound[] array = sounds;
		foreach (Sound val in array)
		{
			if (val != null && Object.op_Implicit((Object)(object)val.Source))
			{
				val.Source.Stop();
			}
		}
		if (Object.op_Implicit((Object)(object)root))
		{
			root.SetActive(false);
			Object.Destroy((Object)(object)root);
		}
	}
}
internal sealed class InteractionFireGate
{
	internal const float PromptGraceSeconds = 0.15f;

	private int lastObservedFrame = int.MinValue;

	private float blockedUntil = float.NegativeInfinity;

	internal static bool IsInteractionPrompt(string rawText, string localizedText)
	{
		if (!HasInteractTag(rawText))
		{
			return HasInteractTag(localizedText);
		}
		return true;
	}

	private static bool HasInteractTag(string text)
	{
		if (text != null)
		{
			return text.IndexOf("[interact]", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	internal void Observe(int frame, float scaledTime)
	{
		lastObservedFrame = frame;
		blockedUntil = scaledTime + 0.15f;
	}

	internal bool IsBlocked(int frame, float scaledTime)
	{
		if ((long)frame - (long)lastObservedFrame > 1)
		{
			return scaledTime <= blockedUntil;
		}
		return true;
	}
}
[HarmonyPatch(typeof(InfoTextTrigger), "Activate")]
internal static class InteractionPromptActivatePatch
{
	[HarmonyPostfix]
	private static void Postfix(InfoTextTrigger __instance, bool ___active, string ___infoTextLocalized)
	{
		if (___active && Object.op_Implicit((Object)(object)Plugin.Current))
		{
			Plugin.Current.ObserveInteractionPrompt(__instance.infoText, ___infoTextLocalized);
		}
	}
}
[HarmonyPatch(typeof(InfoTextTrigger), "Update")]
internal static class InteractionPromptUpdatePatch
{
	[HarmonyPrefix]
	private static void Prefix(InfoTextTrigger __instance, bool ___active, string ___infoTextLocalized)
	{
		if (___active && Object.op_Implicit((Object)(object)Plugin.Current))
		{
			Plugin.Current.ObserveInteractionPrompt(__instance.infoText, ___infoTextLocalized);
		}
	}

	[HarmonyPostfix]
	private static void Postfix(InfoTextTrigger __instance, bool ___active, string ___infoTextLocalized)
	{
		if (___active && Object.op_Implicit((Object)(object)Plugin.Current))
		{
			Plugin.Current.ObserveInteractionPrompt(__instance.infoText, ___infoTextLocalized);
		}
	}
}
[HarmonyPatch(typeof(CosmeticShopMachine), "Interact")]
internal static class LocalGachaInteractionPatch
{
	[HarmonyPrefix]
	private static void Prefix()
	{
		if (Object.op_Implicit((Object)(object)Plugin.Current))
		{
			Plugin.Current.ObserveLocalInteraction();
		}
	}
}
internal sealed class NativeNetwork
{
	private readonly Type viewType;

	private readonly PropertyInfo viewId;

	private readonly PropertyInfo inRoom;

	private readonly PropertyInfo room;

	private readonly PropertyInfo playerList;

	private readonly PropertyInfo actorNumber;

	private readonly MethodInfo rpc;

	private readonly MethodInfo destroy;

	private readonly object all;

	private readonly object others;

	internal bool InRoom => (bool)inRoom.GetValue(null);

	internal object Room => room.GetValue(null);

	internal NativeNetwork()
	{
		viewType = Type.GetType("Photon.Pun.PhotonView, PhotonUnityNetworking", throwOnError: true);
		Type type = Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking", throwOnError: true);
		viewId = viewType.GetProperty("ViewID");
		inRoom = type.GetProperty("InRoom", BindingFlags.Static | BindingFlags.Public);
		room = type.GetProperty("CurrentRoom", BindingFlags.Static | BindingFlags.Public);
		playerList = type.GetProperty("PlayerList", BindingFlags.Static | BindingFlags.Public);
		actorNumber = playerList?.PropertyType.GetElementType()?.GetProperty("ActorNumber");
		rpc = viewType.GetMethods().Single((MethodInfo method) => method.Name == "RPC" && method.GetParameters().Length == 3 && method.GetParameters()[0].ParameterType == typeof(string) && method.GetParameters()[1].ParameterType.FullName == "Photon.Pun.RpcTarget" && method.GetParameters()[2].ParameterType == typeof(object[]));
		Type parameterType = rpc.GetParameters()[1].ParameterType;
		all = Enum.Parse(parameterType, "All");
		others = Enum.Parse(parameterType, "Others");
		destroy = type.GetMethod("Destroy", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(GameObject) }, null);
		if (viewId == null || inRoom == null || destroy == null || room == null || actorNumber == null)
		{
			throw new MissingMemberException("Photon RPC/destroy/roster API is unavailable.");
		}
	}

	internal string Roster(out int count)
	{
		Array array = (Array)playerList.GetValue(null);
		count = array.Length;
		return string.Join(",", from object p in array
			select (int)actorNumber.GetValue(p) into id
			orderby id
			select id);
	}

	internal int ViewId(GameObject target)
	{
		Component component = target.GetComponent(viewType);
		if (!Object.op_Implicit((Object)(object)component))
		{
			return 0;
		}
		return (int)viewId.GetValue(component);
	}

	internal void Rpc(GameObject target, string methodName, bool othersOnly, params object[] arguments)
	{
		if (!Object.op_Implicit((Object)(object)target))
		{
			throw new ArgumentNullException("target");
		}
		if (SemiFunc.IsMultiplayer())
		{
			Component component = target.GetComponent(viewType);
			if (!Object.op_Implicit((Object)(object)component) || ViewId(target) <= 0 || !InRoom)
			{
				throw new InvalidOperationException("RPC target is not network-ready: " + methodName);
			}
			rpc.Invoke(component, new object[3]
			{
				methodName,
				othersOnly ? others : all,
				arguments
			});
		}
		else
		{
			if (othersOnly)
			{
				return;
			}
			MonoBehaviour[] components = target.GetComponents<MonoBehaviour>();
			foreach (MonoBehaviour val in components)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					MethodInfo methodInfo = ((object)val).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault((MethodInfo candidate) => candidate.Name == methodName && candidate.GetParameters().Length == arguments.Length + 1 && candidate.GetParameters().Last().ParameterType.FullName == "Photon.Pun.PhotonMessageInfo");
					if (!(methodInfo == null))
					{
						object[] array = new object[arguments.Length + 1];
						Array.Copy(arguments, array, arguments.Length);
						array[arguments.Length] = Activator.CreateInstance(methodInfo.GetParameters().Last().ParameterType);
						methodInfo.Invoke(val, array);
						return;
					}
				}
			}
			throw new MissingMethodException("Vanilla single-player RPC method not found: " + methodName);
		}
	}

	internal void Destroy(GameObject target)
	{
		if (Object.op_Implicit((Object)(object)target))
		{
			if (InRoom && ViewId(target) > 0)
			{
				destroy.Invoke(null, new object[1] { target });
			}
			else
			{
				Object.Destroy((Object)(object)target);
			}
		}
	}
}
internal sealed class WizardStaffHitLedger
{
	internal readonly HashSet<Enemy> HitEnemies = new HashSet<Enemy>();
}
internal sealed class WizardStaffHitSource : MonoBehaviour
{
	internal WizardStaffHitLedger Ledger;
}
internal static class PhysicalStaffDamage
{
	internal struct DamageState
	{
		internal bool Active;

		internal bool Kill;

		internal int Damage;
	}

	[HarmonyPatch(typeof(SlowProjectile), "SetSpawner")]
	private static class StaffShot
	{
		private static void Postfix(SlowProjectile __instance, GameObject __0)
		{
			Track(__instance, __0, Object.op_Implicit((Object)(object)Plugin.Current) && Plugin.Current.PhysicalStaffPowerEnabled);
		}
	}

	[HarmonyPatch(typeof(HurtCollider), "EnemyHurt")]
	private static class EnemyImpact
	{
		private static void Prefix(HurtCollider __instance, Enemy __0, out DamageState __state)
		{
			__state = BeginEnemyHit(__instance, __0);
		}

		private static Exception Finalizer(HurtCollider __instance, DamageState __state, Exception __exception)
		{
			Restore(__instance, __state);
			return __exception;
		}
	}

	internal const int Damage = 80;

	private static readonly FieldInfo LastHolder = AccessTools.Field(typeof(PhysGrabObject), "lastPlayerGrabbing") ?? throw new MissingFieldException("PhysGrabObject.lastPlayerGrabbing");

	private static readonly FieldInfo HasHealth = AccessTools.Field(typeof(Enemy), "HasHealth") ?? throw new MissingFieldException("Enemy.HasHealth");

	internal static void Track(SlowProjectile projectile, GameObject spawner, bool empowered)
	{
		if (!empowered || !SemiFunc.IsMasterClientOrSingleplayer() || !Object.op_Implicit((Object)(object)projectile) || !Object.op_Implicit((Object)(object)spawner) || (!Object.op_Implicit((Object)(object)spawner.GetComponent<ItemStaffTorque>()) && !Object.op_Implicit((Object)(object)spawner.GetComponent<ItemStaffZeroGravity>()) && !Object.op_Implicit((Object)(object)spawner.GetComponent<ItemStaffVoid>())))
		{
			return;
		}
		PhysGrabObject component = spawner.GetComponent<PhysGrabObject>();
		if (Object.op_Implicit((Object)(object)component) && component.grabbedLocal && Object.op_Implicit((Object)(object)PlayerAvatar.instance) && !((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)PlayerAvatar.instance))
		{
			HurtCollider val = (Object.op_Implicit((Object)(object)projectile.hurtCollider) ? projectile.hurtCollider.GetComponent<HurtCollider>() : null);
			HurtCollider areaOfEffectHurtCollider = projectile.areaOfEffectHurtCollider;
			WizardStaffHitSource wizardStaffHitSource = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<WizardStaffHitSource>() : null);
			if (!Object.op_Implicit((Object)(object)wizardStaffHitSource) && Object.op_Implicit((Object)(object)areaOfEffectHurtCollider))
			{
				wizardStaffHitSource = ((Component)areaOfEffectHurtCollider).GetComponent<WizardStaffHitSource>();
			}
			WizardStaffHitLedger ledger = ((Object.op_Implicit((Object)(object)wizardStaffHitSource) && wizardStaffHitSource.Ledger != null) ? wizardStaffHitSource.Ledger : new WizardStaffHitLedger());
			Tag(val, ledger);
			Tag(areaOfEffectHurtCollider, ledger);
		}
	}

	private static void Tag(HurtCollider hurt, WizardStaffHitLedger ledger)
	{
		if (Object.op_Implicit((Object)(object)hurt))
		{
			WizardStaffHitSource wizardStaffHitSource = ((Component)hurt).GetComponent<WizardStaffHitSource>();
			if (!Object.op_Implicit((Object)(object)wizardStaffHitSource))
			{
				wizardStaffHitSource = ((Component)hurt).gameObject.AddComponent<WizardStaffHitSource>();
			}
			wizardStaffHitSource.Ledger = ledger;
		}
	}

	internal static DamageState BeginEnemyHit(HurtCollider hurt, Enemy enemy)
	{
		if (!SemiFunc.IsMasterClientOrSingleplayer() || !Object.op_Implicit((Object)(object)hurt) || !Object.op_Implicit((Object)(object)enemy) || !(bool)HasHealth.GetValue(enemy) || !hurt.enemyLogic || (Object)(object)enemy == (Object)(object)hurt.enemyHost || hurt.deathPit)
		{
			return default(DamageState);
		}
		WizardStaffHitSource component = ((Component)hurt).GetComponent<WizardStaffHitSource>();
		if (!Object.op_Implicit((Object)(object)component) || component.Ledger == null)
		{
			return default(DamageState);
		}
		DamageState result = new DamageState
		{
			Active = true,
			Damage = hurt.enemyDamage,
			Kill = hurt.enemyKill
		};
		hurt.enemyKill = false;
		hurt.enemyDamage = (component.Ledger.HitEnemies.Add(enemy) ? 80 : 0);
		return result;
	}

	internal static void Restore(HurtCollider hurt, DamageState state)
	{
		if (state.Active && Object.op_Implicit((Object)(object)hurt))
		{
			hurt.enemyDamage = state.Damage;
			hurt.enemyKill = state.Kill;
		}
	}
}
internal static class SpellMuzzle
{
	internal static Vector3 ForwardOffset(bool crouched, Vector3 origin, Vector3 aimForward)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		return origin + aimForward * (crouched ? 0.6f : 0.12f);
	}

	internal static bool TryPosition(bool crouched, Vector3 head, Transform hand, out Vector3 origin)
	{
		//IL_0001: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		origin = head;
		if (!Finite(head))
		{
			return false;
		}
		if (crouched)
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)hand))
		{
			return false;
		}
		origin = hand.position;
		if (Finite(origin))
		{
			Vector3 val = origin - head;
			return ((Vector3)(ref val)).sqrMagnitude <= 9f;
		}
		return false;
	}

	private static bool Finite(Vector3 v)
	{
		//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if (!float.IsNaN(v.x) && !float.IsInfinity(v.x) && !float.IsNaN(v.y) && !float.IsInfinity(v.y) && !float.IsNaN(v.z))
		{
			return !float.IsInfinity(v.z);
		}
		return false;
	}
}
internal sealed class WizardVoidOwner : MonoBehaviour
{
	internal PlayerAvatar Caster;
}
internal static class VoidCasterProtection
{
	[HarmonyPatch]
	private static class SpawnPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(SlowProjectile), "ExplosionRPC", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(SlowProjectile), "DestroyRPC", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int matches = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.operand is MethodInfo { Name: "Instantiate" } methodInfo && methodInfo.ReturnType == typeof(GameObject) && (methodInfo.DeclaringType == typeof(Object) || methodInfo.DeclaringType.FullName == "Photon.Pun.PhotonNetwork"))
				{
					matches++;
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(VoidCasterProtection), "TrackSpawn", (Type[])null, (Type[])null));
				}
			}
			if (matches < 2)
			{
				throw new InvalidOperationException("VOID native impact spawn hooks changed.");
			}
		}
	}

	[HarmonyPatch(typeof(SlowWalkerAttack), "SuckInListPlayerUpdate")]
	private static class VacuumPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int matches = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (instruction.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(SemiFunc) && methodInfo.Name == "PlayerGetAllPlayerAvatarWithinRange")
				{
					matches++;
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(VoidCasterProtection), "FilterPlayers", (Type[])null, (Type[])null));
				}
			}
			if (matches != 1)
			{
				throw new InvalidOperationException("VOID player collection hook changed.");
			}
		}
	}

	internal static GameObject TrackSpawn(GameObject spawned, SlowProjectile projectile)
	{
		WizardVoidOwner component = ((Component)projectile).GetComponent<WizardVoidOwner>();
		if (!Object.op_Implicit((Object)(object)spawned) || !Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.Caster))
		{
			return spawned;
		}
		SlowWalkerAttack[] componentsInChildren = spawned.GetComponentsInChildren<SlowWalkerAttack>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			((Component)componentsInChildren[i]).gameObject.AddComponent<WizardVoidOwner>().Caster = component.Caster;
		}
		HurtCollider[] componentsInChildren2 = spawned.GetComponentsInChildren<HurtCollider>(true);
		foreach (HurtCollider val in componentsInChildren2)
		{
			if (!val.ignorePlayers.Contains(component.Caster))
			{
				val.ignorePlayers.Add(component.Caster);
			}
		}

BepInEx/plugins/HostRoleSeries/HostRoleSelector.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HostRoleSeries;

[BepInPlugin("local.bei.hostroleselector", "Host Role Selector", "1.0.0")]
public sealed class RoleMenu : BaseUnityPlugin
{
	public const string PluginId = "local.bei.hostroleselector";

	private static RoleMenu instance;

	private readonly RoleRegistry roles = new RoleRegistry();

	private ConfigEntry<KeyboardShortcut> menuKey;

	private ConfigEntry<string> preferred;

	private readonly List<InputKey> blockInputs = new List<InputKey>();

	private bool open;

	private bool initialized;

	private int highlighted;

	private string pending;

	private string notice = "";

	private float noticeUntil;

	private GUIStyle title;

	private GUIStyle text;

	private GUIStyle small;

	private GUIStyle button;

	private Texture2D pointer;

	private static readonly FieldInfo dead = typeof(PlayerAvatar).GetField("deadSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo spawned = typeof(PlayerAvatar).GetField("spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo chat = typeof(ChatManager).GetField("chatActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo menuState = typeof(MenuManager).GetField("currentMenuState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	public static bool InputBlocked
	{
		get
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				return instance.open;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		menuKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "RoleMenuKey", new KeyboardShortcut((KeyCode)286, Array.Empty<KeyCode>()), "Open the shared host-role menu. Arrows: select; Enter: apply; Escape: cancel.");
		preferred = ((BaseUnityPlugin)this).Config.Bind<string>("Selection", "SelectedRole", "", "Last selected role ID, or none. Empty selects the first installed enabled role on startup.");
		instance = this;
	}

	public static void Register(string id, string name, string description, int order, Func<bool> available, Action<bool> apply)
	{
		if (!Object.op_Implicit((Object)(object)instance))
		{
			throw new InvalidOperationException("Host Role Selector is not loaded.");
		}
		instance.roles.Register(new RoleEntry(id, name, description, order, available, apply));
	}

	public static void Unregister(string id)
	{
		if (Object.op_Implicit((Object)(object)instance))
		{
			instance.roles.Remove(id);
		}
	}

	public static bool IsSelected(string id)
	{
		if (Object.op_Implicit((Object)(object)instance) && ((Behaviour)instance).isActiveAndEnabled && WorldReady())
		{
			return instance.roles.ActiveId == id;
		}
		return false;
	}

	private static bool WorldReady()
	{
		if (Object.op_Implicit((Object)(object)GameManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance) && SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.MenuLevel() && (Object)(object)LevelGenerator.Instance != (Object)null)
		{
			return LevelGenerator.Instance.Generated;
		}
		return false;
	}

	private static bool MenuReady()
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Invalid comparison between Unknown and I4
		PlayerAvatar val = PlayerAvatar.instance;
		if (WorldReady() && Object.op_Implicit((Object)(object)val) && dead != null && spawned != null && (bool)spawned.GetValue(val) && !(bool)dead.GetValue(val) && Object.op_Implicit((Object)(object)GameDirector.instance) && (int)GameDirector.instance.currentState == 2 && (!Object.op_Implicit((Object)(object)ChatManager.instance) || chat == null || !(bool)chat.GetValue(ChatManager.instance)))
		{
			if (Object.op_Implicit((Object)(object)MenuManager.instance) && !(menuState == null))
			{
				return (int)menuState.GetValue(MenuManager.instance) != 0;
			}
			return true;
		}
		return false;
	}

	private bool MenuPressed()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = menuKey.Value;
		if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !UnityInput.Current.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
		{
			return false;
		}
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
		{
			if (!UnityInput.Current.GetKey(modifier))
			{
				return false;
			}
		}
		return true;
	}

	private void Update()
	{
		try
		{
			if (!WorldReady())
			{
				open = false;
				pending = null;
				roles.Select("none");
				initialized = false;
				return;
			}
			if (!initialized)
			{
				roles.Select(roles.Initial(preferred.Value));
				initialized = true;
			}
			roles.Validate();
			if (!MenuReady())
			{
				open = false;
				pending = null;
				return;
			}
			RoleEntry[] entries = roles.Entries;
			if (MenuPressed())
			{
				open = !open;
				pending = null;
				highlighted = Array.FindIndex(entries, (RoleEntry e) => e.Id == roles.ActiveId) + 1;
			}
			if (!open)
			{
				return;
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)27))
			{
				open = false;
				pending = null;
				return;
			}
			if (Object.op_Implicit((Object)(object)CursorManager.instance))
			{
				SemiFunc.CursorUnlock(0.1f);
			}
			if (Object.op_Implicit((Object)(object)CameraAim.Instance))
			{
				CameraAim.Instance.OverrideAimStop();
			}
			if (Object.op_Implicit((Object)(object)InputManager.instance))
			{
				InputManager.instance.DisableControlsExcept(0.1f, blockInputs);
			}
			int num = entries.Length + 1;
			highlighted = Mathf.Clamp(highlighted, 0, num - 1);
			if (UnityInput.Current.GetKeyDown((KeyCode)276) || UnityInput.Current.GetKeyDown((KeyCode)273))
			{
				highlighted = (highlighted + num - 1) % num;
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)275) || UnityInput.Current.GetKeyDown((KeyCode)274))
			{
				highlighted = (highlighted + 1) % num;
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)8))
			{
				pending = "none";
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)13))
			{
				pending = ((highlighted == 0) ? "none" : entries[highlighted - 1].Id);
			}
			if (pending == null)
			{
				return;
			}
			string requested = pending;
			pending = null;
			if (!roles.Select(requested))
			{
				notice = "This role is disabled in its config.";
				return;
			}
			preferred.Value = requested;
			if (!((BaseUnityPlugin)this).Config.SaveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			notice = "Role: " + ((requested == "none") ? "NONE" : Array.Find(entries, (RoleEntry e) => e.Id == requested).Name);
			noticeUntil = Time.unscaledTime + 4f;
			open = false;
		}
		catch (Exception ex)
		{
			open = false;
			pending = null;
			((BaseUnityPlugin)this).Logger.LogError((object)("Role selection failed: " + ex));
		}
	}

	private static void Fill(Rect rect, Color color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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)
		Color color2 = GUI.color;
		GUI.color = color;
		GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color2;
	}

	private void OnGUI()
	{
		//IL_0532: Unknown result type (might be due to invalid IL or missing references)
		//IL_0538: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		//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_008c: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Expected O, but got Unknown
		//IL_00c1: Expected O, but got Unknown
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: 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_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_044b: Unknown result type (might be due to invalid IL or missing references)
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0507: Unknown result type (might be due to invalid IL or missing references)
		//IL_050c: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_0558: Invalid comparison between Unknown and I4
		if (!MenuReady())
		{
			return;
		}
		if (this.text == null)
		{
			this.text = new GUIStyle(GUI.skin.label)
			{
				fontSize = 19,
				wordWrap = true,
				richText = false
			};
			this.text.normal.textColor = Color.white;
			title = new GUIStyle(this.text)
			{
				fontSize = 26,
				fontStyle = (FontStyle)1
			};
			small = new GUIStyle(this.text)
			{
				fontSize = 15
			};
			button = new GUIStyle(GUI.skin.button)
			{
				fontSize = 20,
				alignment = (TextAnchor)3,
				padding = new RectOffset(18, 12, 8, 8)
			};
		}
		if (!open)
		{
			if (Time.unscaledTime < noticeUntil)
			{
				Fill(new Rect(22f, 22f, 460f, 55f), new Color(0.08f, 0.1f, 0.14f, 0.95f));
				GUI.Label(new Rect(34f, 33f, 438f, 35f), notice, this.text);
			}
			return;
		}
		Matrix4x4 matrix = GUI.matrix;
		Color color = GUI.color;
		bool enabled = GUI.enabled;
		try
		{
			RoleEntry[] entries = roles.Entries;
			highlighted = Mathf.Clamp(highlighted, 0, entries.Length);
			float num = 230 + 62 * (entries.Length + 1);
			float num2 = Mathf.Min(1.1f, Mathf.Min((float)Screen.width / 820f, (float)Screen.height / (num + 60f)));
			GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * num2);
			float num3 = ((float)Screen.width / num2 - 760f) / 2f;
			float num4 = ((float)Screen.height / num2 - num) / 2f;
			Fill(new Rect(num3, num4, 760f, num), new Color(0.1f, 0.12f, 0.16f, 0.98f));
			Fill(new Rect(num3, num4, 760f, 58f), new Color(0.12f, 0.32f, 0.55f));
			GUI.Label(new Rect(num3 + 22f, num4 + 14f, 660f, 40f), "HOST ROLES / SELECT YOUR ROLE", title);
			if (GUI.Button(new Rect(num3 + 702f, num4 + 12f, 40f, 34f), "X"))
			{
				open = false;
				pending = null;
			}
			Rect val = default(Rect);
			for (int i = 0; i <= entries.Length; i++)
			{
				string text = ((i == 0) ? "none" : entries[i - 1].Id);
				string text2 = ((i == 0) ? "NONE" : entries[i - 1].Name);
				bool flag = i == 0 || entries[i - 1].IsAvailable;
				((Rect)(ref val))..ctor(num3 + 22f, num4 + 76f + (float)(i * 62), 716f, 52f);
				if (highlighted == i)
				{
					Fill(new Rect(((Rect)(ref val)).x - 4f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 8f, ((Rect)(ref val)).height + 6f), new Color(0.23f, 0.57f, 0.95f));
				}
				GUI.enabled = enabled && flag;
				if (GUI.Button(val, text2 + ((text == roles.ActiveId) ? "   [ACTIVE]" : "") + (flag ? "" : "   [CFG OFF]"), button))
				{
					highlighted = i;
				}
			}
			GUI.enabled = enabled;
			float num5 = num4 + 76f + (float)((entries.Length + 1) * 62);
			string text3 = ((highlighted == 0) ? "No host-role abilities. Stored resources are kept." : entries[Mathf.Clamp(highlighted - 1, 0, entries.Length - 1)].Description);
			GUI.Label(new Rect(num3 + 24f, num5 + 4f, 712f, 52f), text3, small);
			GUI.enabled = enabled && (highlighted == 0 || entries[highlighted - 1].IsAvailable);
			if (GUI.Button(new Rect(num3 + 22f, num5 + 62f, 716f, 43f), "APPLY SELECTED ROLE", button))
			{
				pending = ((highlighted == 0) ? "none" : entries[highlighted - 1].Id);
			}
			GUI.enabled = enabled;
			GUI.Label(new Rect(num3 + 24f, num5 + 117f, 714f, 25f), "Arrows: select   Enter: apply   Backspace: none   " + ((object)menuKey.Value/*cast due to .constrained prefix*/).ToString() + " / Esc: close", small);
		}
		finally
		{
			GUI.matrix = matrix;
			GUI.color = color;
			GUI.enabled = enabled;
		}
		if (open && (int)Event.current.type == 7)
		{
			DrawPointer();
		}
	}

	private void DrawPointer()
	{
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: 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_0021: Expected O, but got Unknown
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: 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)
		if (!Object.op_Implicit((Object)(object)pointer))
		{
			pointer = new Texture2D(20, 28, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[560];
			for (int i = 0; i < 28; i++)
			{
				for (int j = 0; j < 20; j++)
				{
					array[(27 - i) * 20 + j] = (((float)j <= (float)i * 0.6f) ? ((j > 1 && (float)j < (float)i * 0.6f - 2f) ? Color.white : Color.black) : Color.clear);
				}
			}
			pointer.SetPixels(array);
			pointer.Apply();
		}
		Vector3 mousePosition = Input.mousePosition;
		GUI.DrawTexture(new Rect(mousePosition.x, (float)Screen.height - mousePosition.y, 20f, 28f), (Texture)(object)pointer);
	}

	private void OnDisable()
	{
		open = false;
		pending = null;
		roles.Select("none");
		initialized = false;
	}

	private void OnDestroy()
	{
		try
		{
			roles.Select("none");
		}
		finally
		{
			if (Object.op_Implicit((Object)(object)pointer))
			{
				Object.Destroy((Object)(object)pointer);
			}
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
}
public sealed class RoleEntry
{
	public string Id { get; }

	public string Name { get; }

	public string Description { get; }

	internal int Order { get; }

	internal Func<bool> Available { get; }

	internal Action<bool> Apply { get; }

	public bool IsAvailable => Available();

	public RoleEntry(string id, string name, string description, int order, Func<bool> available, Action<bool> apply)
	{
		Id = id;
		Name = name;
		Description = description;
		Order = order;
		Available = available;
		Apply = apply;
	}
}
public sealed class RoleRegistry
{
	public const string None = "none";

	private readonly Dictionary<string, RoleEntry> entries = new Dictionary<string, RoleEntry>();

	public string ActiveId { get; private set; } = "none";

	public RoleEntry[] Entries => entries.Values.OrderBy((RoleEntry r) => r.Order).ThenBy<RoleEntry, string>((RoleEntry r) => r.Id, StringComparer.Ordinal).ToArray();

	public void Register(RoleEntry entry)
	{
		if (entry == null || string.IsNullOrWhiteSpace(entry.Id) || entry.Id == "none" || entries.ContainsKey(entry.Id))
		{
			throw new ArgumentException("Duplicate or invalid role registration.");
		}
		entries.Add(entry.Id, entry);
	}

	public bool Select(string id)
	{
		if (id == ActiveId)
		{
			return true;
		}
		RoleEntry value = null;
		if (id != "none" && (!entries.TryGetValue(id, out value) || !value.IsAvailable))
		{
			return false;
		}
		string activeId = ActiveId;
		ActiveId = "none";
		if (entries.TryGetValue(activeId, out var value2))
		{
			value2.Apply(obj: false);
		}
		if (value == null)
		{
			return true;
		}
		try
		{
			ActiveId = id;
			value.Apply(obj: true);
		}
		catch
		{
			ActiveId = "none";
			value.Apply(obj: false);
			throw;
		}
		return true;
	}

	public void Remove(string id)
	{
		if (ActiveId == id)
		{
			Select("none");
		}
		entries.Remove(id);
	}

	public string Initial(string preferred)
	{
		if (preferred == "none")
		{
			return "none";
		}
		if (preferred == null || !entries.TryGetValue(preferred, out var value))
		{
			return Entries.FirstOrDefault((RoleEntry e) => e.IsAvailable)?.Id ?? "none";
		}
		if (!value.IsAvailable)
		{
			return "none";
		}
		return preferred;
	}

	public void Validate()
	{
		if (entries.TryGetValue(ActiveId, out var value) && !value.IsAvailable)
		{
			Select("none");
		}
	}
}