Decompiled source of ScalerCore v1.0.1

ScalerCore.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using ScalerCore.AprilFools;
using ScalerCore.Compat;
using ScalerCore.Handlers;
using ScalerCore.Handlers.EnemyVisuals;
using ScalerCore.Utilities;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.Rendering.PostProcessing;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Vippy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Scaling library API for R.E.P.O. shrink and grow mods. Handles physics, mass, audio, NavMesh, animation, colliders, and multiplayer sync. Compile-time reference only: ship the runtime through the ScalerCore Thunderstore dependency.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+d35a3d825cc7f5af8afd129a74679ae52afd0bb7")]
[assembly: AssemblyProduct("ScalerCore")]
[assembly: AssemblyTitle("ScalerCore")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/VirtualPixel/ScalerCore.git")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ScalerCore
{
	internal static class BuildInfo
	{
		public const string Version = "1.0.1";
	}
	[HarmonyPatch(typeof(PhysGrabObject), "Start")]
	internal static class AttachToValuablePatch
	{
		private static void Postfix(PhysGrabObject __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				bool num = (Object)(object)((Component)__instance).GetComponent<ValuableObject>() != (Object)null;
				bool flag = (Object)(object)((Component)__instance).GetComponent<ItemAttributes>() != (Object)null;
				bool flag2 = (Object)(object)((Component)__instance).GetComponent<CosmeticWorldObject>() != (Object)null;
				bool flag3 = (Object)(object)((Component)__instance).GetComponent<PlayerDeathHead>() != (Object)null;
				bool flag4 = (Object)(object)((Component)__instance).GetComponent<ShopRadio>() != (Object)null;
				if (num || flag || flag2 || flag3 || flag4)
				{
					((Component)__instance).gameObject.AddComponent<ScaleController>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyRigidbody), "Awake")]
	internal static class AttachToEnemyPatch
	{
		private static void Postfix(EnemyRigidbody __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Start")]
	internal static class AttachToPlayerPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
				PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
				if (component != null)
				{
					component.RefreshRpcMonoBehaviourCache();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabHinge), "Awake")]
	internal static class AttachToDoorPatch
	{
		private static void Postfix(PhysGrabHinge __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<ScaleController>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<ScaleController>();
			}
		}
	}
	[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
	internal static class LevelChangePatch
	{
		private static void Postfix()
		{
			ScaleManager.CleanupAll();
			MapCollapse.OnLevelChange();
		}
	}
	[HarmonyPatch(typeof(RunManagerPUN), "UpdateLevelRPC")]
	internal static class LevelChangeNonHostPatch
	{
		private static void Postfix()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleManager.CleanupAll();
				MapCollapse.OnLevelChange();
			}
		}
	}
	[HarmonyPatch(typeof(ParticleScriptExplosion), "Spawn")]
	internal static class EnemyExplosionScalePatch
	{
		private static ScaleController? EnemyController(ParticleScriptExplosion spawner)
		{
			EnemyParent componentInParent = ((Component)spawner).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return null;
			}
			ScaleController componentInChildren = ((Component)componentInParent).GetComponentInChildren<ScaleController>();
			if (!((Object)(object)componentInChildren != (Object)null) || !componentInChildren.IsScaled)
			{
				return null;
			}
			return componentInChildren;
		}

		private static void Prefix(ParticleScriptExplosion __instance, ref float size, ref int damage, ref int enemyDamage, ref float forceMulti)
		{
			ScaleController scaleController = EnemyController(__instance);
			if (!((Object)(object)scaleController == (Object)null))
			{
				float factor = scaleController._options.Factor;
				size *= factor;
				damage = Mathf.RoundToInt((float)damage * factor);
				enemyDamage = Mathf.RoundToInt((float)enemyDamage * factor);
				forceMulti *= factor;
				Plugin.Log.LogDebug((object)$"[SC] enemy explosion scaled x{factor:F2} (size={size:F2} dmg={damage} force={forceMulti:F2})");
			}
		}

		private static void Postfix(ParticleScriptExplosion __instance, ParticlePrefabExplosion __result)
		{
			ScaleController scaleController = EnemyController(__instance);
			if (!((Object)(object)scaleController == (Object)null) && !((Object)(object)__result == (Object)null))
			{
				AudioPitchHelper.PitchOneShot((Component)(object)__result, scaleController._options.Factor, scaleController._options.AudioPresence);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerTumble), "SetupDone")]
	internal static class PlayerTumbleLinkPatch
	{
		private static void Postfix(PlayerTumble __instance)
		{
			PlayerAvatar playerAvatar = __instance.playerAvatar;
			ScaleController scaleController = ((playerAvatar != null) ? ((Component)playerAvatar).GetComponent<ScaleController>() : null);
			if (!((Object)(object)scaleController == (Object)null))
			{
				AttachLink(((Component)__instance).gameObject, scaleController);
				Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					AttachLink(((Component)componentsInChildren[i]).gameObject, scaleController);
				}
				Plugin.Log.LogDebug((object)("[SC] PlayerShrinkLink (tumble) attached → " + ((Object)((Component)__instance).gameObject).name + "  avatar=" + ((Object)((Component)scaleController).gameObject).name));
			}
		}

		private static void AttachLink(GameObject go, ScaleController ctrl)
		{
			(go.GetComponent<PlayerShrinkLink>() ?? go.AddComponent<PlayerShrinkLink>()).Controller = ctrl;
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
	internal static class PlayerDeathExpandPatch
	{
		private static void Postfix(PlayerAvatar __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if (!((Object)(object)component == (Object)null) && component.IsScaled && !component._invertedActive)
				{
					component.DispatchExpand();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHealth), "Hurt")]
	internal static class PlayerBonkPatch
	{
		private static void Prefix(PlayerHealth __instance, out int __state)
		{
			__state = __instance.health;
		}

		private static void Postfix(PlayerHealth __instance, int __state)
		{
			if (__instance.health >= __state)
			{
				return;
			}
			ScaleController scaleController = ((Component)__instance).GetComponentInParent<ScaleController>() ?? ((Component)__instance).GetComponentInChildren<ScaleController>();
			if ((Object)(object)scaleController == (Object)null)
			{
				return;
			}
			if (scaleController.IsScaled)
			{
				if (!scaleController._invertedActive)
				{
					scaleController.RequestBonkExpand();
				}
			}
			else if (scaleController._invertedActive)
			{
				scaleController.RequestInvertedReshrink();
			}
		}
	}
	[HarmonyPatch(typeof(ItemEquippable), "RequestEquip")]
	internal static class ShrunkEquipBlockPatch
	{
		private static bool Prefix(ItemEquippable __instance)
		{
			ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			bool flag = false;
			if (component.HandlerState is CartHandler.State state)
			{
				flag = state.AddedEquippable;
			}
			else if (component.HandlerState is ItemHandler.State state2)
			{
				flag = state2.AddedEquippable;
			}
			else if (component.HandlerState is VehicleHandler.State state3)
			{
				flag = state3.AddedEquippable;
			}
			if (!flag)
			{
				return true;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			ScaleController component2 = ((Component)instance).GetComponent<ScaleController>();
			if ((Object)(object)component2 != (Object)null && component2.IsScaled)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerCollisionGrounded), "Update")]
	internal static class GroundedWallJumpFix
	{
		private static void Postfix(PlayerCollisionGrounded __instance)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.Grounded)
			{
				return;
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)instance).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float num = __instance.Collider.radius * 1.5f;
				if (!Physics.Raycast(((Component)__instance).transform.position, Vector3.down, num, LayerMask.op_Implicit(__instance.LayerMask), (QueryTriggerInteraction)1))
				{
					__instance.Grounded = false;
					__instance.GroundedTimer = 0f;
					__instance.CollisionController.Grounded = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "OverrideGrabDistance")]
	internal static class GrabDistanceScalePatch
	{
		private static void Prefix(ref float dist)
		{
			if ((Object)(object)PhysGrabber.instance?.playerAvatar == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)PhysGrabber.instance.playerAvatar).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float factor = component._options.Factor;
				if (factor > 1f)
				{
					dist *= factor;
				}
				else
				{
					dist *= 0.7f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "OverrideGrabVerticalPosition")]
	internal static class GrabVerticalPositionScalePatch
	{
		private static void Prefix(ref float pos)
		{
			PhysGrabber instance = PhysGrabber.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				PlayerAvatar playerAvatar = instance.playerAvatar;
				obj = ((playerAvatar != null) ? ((Component)playerAvatar).GetComponent<ScaleController>() : null);
			}
			ScaleController scaleController = (ScaleController)obj;
			if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
			{
				float factor = scaleController._options.Factor;
				if (factor > 1f)
				{
					pos *= factor;
				}
				else
				{
					pos = 0f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "StartGrabbingPhysObject")]
	internal static class ForceGrabPointVerticalScalePatch
	{
		private static void Postfix(PhysGrabber __instance, PhysGrabObject ___grabbedPhysGrabObject)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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)
			PlayerAvatar playerAvatar = __instance.playerAvatar;
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)playerAvatar).GetComponent<ScaleController>();
			if ((Object)(object)component == (Object)null || !component.IsScaled || (Object)(object)___grabbedPhysGrabObject == (Object)null)
			{
				return;
			}
			Transform forceGrabPoint = ___grabbedPhysGrabObject.forceGrabPoint;
			if (!((Object)(object)forceGrabPoint == (Object)null) && ((Component)forceGrabPoint).gameObject.activeSelf)
			{
				PlayerLocalCamera localCamera = playerAvatar.localCamera;
				Transform val = ((localCamera != null) ? localCamera.GetOverrideTransform() : null);
				if (!((Object)(object)val == (Object)null))
				{
					float num = 0.3f * (1f - component._options.Factor);
					Vector3 val2 = val.up * num;
					Transform physGrabPointPuller = __instance.physGrabPointPuller;
					physGrabPointPuller.position += val2;
					Transform physGrabPointPlane = __instance.physGrabPointPlane;
					physGrabPointPlane.position += val2;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "CartSteer")]
	internal static class CartHandledDistancePatch
	{
		private static float ScalePullDist(float d, PhysGrabCart cart, PhysGrabber grabber)
		{
			ScaleController component = ((Component)cart).GetComponent<ScaleController>();
			if ((Object)(object)component != (Object)null && component.IsScaled)
			{
				return d * Mathf.Lerp(component._options.Factor, 1f, 0.15f);
			}
			if ((Object)(object)grabber == (Object)null)
			{
				return d;
			}
			ScaleController component2 = ((Component)grabber.playerAvatar).GetComponent<ScaleController>();
			if ((Object)(object)component2 != (Object)null && component2.IsScaled)
			{
				return d * Mathf.Lerp(1f, component2._options.Factor, 0.15f);
			}
			return d;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod)
		{
			MethodInfo lerpMethod = AccessTools.Method(typeof(Mathf), "Lerp", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(float)
			}, (Type[])null);
			MethodInfo scaleMethod = AccessTools.Method(typeof(CartHandledDistancePatch), "ScalePullDist", (Type[])null, (Type[])null);
			IList<LocalVariableInfo> localVariables = originalMethod.GetMethodBody().LocalVariables;
			int grabberIndex = -1;
			int num = 0;
			foreach (LocalVariableInfo item in localVariables)
			{
				if (item.LocalType == typeof(PhysGrabber))
				{
					num++;
					if (num == 2)
					{
						grabberIndex = item.LocalIndex;
						break;
					}
				}
			}
			if (grabberIndex == -1)
			{
				Plugin.Log.LogWarning((object)"[SC] CartSteer transpiler: second PhysGrabber local not found. Cart pull-distance scaling is DISABLED this session; if this appears after a game update, report it.");
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
				}
				yield break;
			}
			int injected = 0;
			foreach (CodeInstruction code in instructions)
			{
				yield return code;
				if (code.opcode == OpCodes.Call && (MethodInfo)code.operand == lerpMethod)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Ldloc, (object)grabberIndex);
					yield return new CodeInstruction(OpCodes.Call, (object)scaleMethod);
					injected++;
				}
			}
			if (injected == 0)
			{
				Plugin.Log.LogWarning((object)"[SC] CartSteer transpiler: no Mathf.Lerp callsites matched. Cart pull-distance scaling is DISABLED this session; if this appears after a game update, report it.");
			}
		}
	}
	[HarmonyPatch(typeof(CameraGlitch), "Update")]
	internal static class CameraGlitchScalePatch
	{
		private static void Postfix(CameraGlitch __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ScaleController component = ((Component)instance).GetComponent<ScaleController>();
			if (!((Object)(object)component == (Object)null) && component.IsScaled)
			{
				float num = ((component.OriginalScale.x > 0f) ? (component._t.localScale.x / component.OriginalScale.x) : 1f);
				if (!(num >= 1f) && !(num <= 0f))
				{
					Transform transform = ((Component)__instance).transform;
					transform.localScale /= num;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Footstep")]
	internal static class FootstepPitchPatch
	{
		private static void Prefix(PlayerAvatar __instance)
		{
			ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
			if ((Object)(object)component != (Object)null && component.IsScaled)
			{
				ScaleController.FootstepPitchMult = component._options.FootstepPitchMultiplier;
			}
		}

		private static void Postfix()
		{
			ScaleController.FootstepPitchMult = 1f;
		}
	}
	[HarmonyPatch(typeof(Sound), "Play", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(float),
		typeof(float),
		typeof(float)
	})]
	internal static class SoundPlayPitchPatch
	{
		private static void Postfix(AudioSource __result)
		{
			if (ScaleController.FootstepPitchMult != 1f && (Object)(object)__result != (Object)null)
			{
				__result.pitch *= ScaleController.FootstepPitchMult;
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class DriverFullyMountedScalePatch
	{
		private static void Postfix(ItemVehicle __instance, ref bool __result)
		{
			if (!__result && __instance.seats != null && __instance.seats.Length != 0 && !((Object)(object)__instance.seats[0].seatedPlayer == (Object)null))
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if ((Object)(object)component != (Object)null && component.IsScaled)
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ValuableTeethBot), "Update")]
	internal static class TeethVoiceScalePatch
	{
		private static void Postfix(ValuableTeethBot __instance)
		{
			ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
			if ((Object)(object)scaleController == (Object)null || !scaleController.IsScaled)
			{
				return;
			}
			float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
			foreach (PhysGrabber item in __instance.physGrabObject.playerGrabbing)
			{
				if (item.playerAvatar.voiceChatFetched)
				{
					item.playerAvatar.voiceChat.OverridePitch(1.25f * num, 0.1f, 0.1f, 0.2f, 0.05f, 100f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemWalkieTalkie), "Update")]
	internal static class WalkieVoiceScalePatch
	{
		private static void Postfix(ItemWalkieTalkie __instance)
		{
			ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
			if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
			{
				PlayerAvatar inThisWalkie = __instance.inThisWalkie;
				if (!((Object)(object)inThisWalkie == (Object)null) && inThisWalkie.voiceChatFetched && !inThisWalkie.isLocal)
				{
					float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
					inThisWalkie.voiceChat.OverridePitch(1.5f * num, 0.1f, 0.1f, 0.1f, 0f, 0f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerDeathHead), "Update")]
	internal static class DeathHeadVoiceScalePatch
	{
		private static void Postfix(PlayerDeathHead __instance)
		{
			if (__instance.spectated && !((Object)(object)__instance.playerAvatar == (Object)null) && __instance.playerAvatar.voiceChatFetched)
			{
				ScaleController scaleController = ((Component)__instance).GetComponent<ScaleController>() ?? ((Component)__instance).GetComponentInParent<ScaleController>();
				if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
				{
					float num = PlayerHandler.VoicePitchMult(scaleController._options.Factor);
					float num2 = (__instance.spectatedLowEnergy ? 0.5f : 1f);
					__instance.playerAvatar.voiceChat.OverridePitch(num2 * num, 0.2f, 0.2f, 0.1f, 0f, 0f);
				}
			}
		}
	}
	public class PlayerShrinkLink : MonoBehaviour
	{
		public ScaleController Controller;
	}
	[BepInPlugin("Vippy.ScalerCore", "ScalerCore", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static Harmony Harmony = null;

		internal static ManualLogSource Log = null;

		internal static readonly bool DiagMass = Environment.GetEnvironmentVariable("SCALERCORE_DIAG") == "1";

		internal static readonly bool DebugDraw = Environment.GetEnvironmentVariable("SCALERCORE_DEBUG") == "1" || File.Exists(Path.Combine(Paths.ConfigPath, "scalercore_debug"));

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("Vippy.ScalerCore");
			Harmony.PatchAll();
			((Component)this).gameObject.AddComponent<MapCollapse>();
			if (DebugDraw)
			{
				((Component)this).gameObject.AddComponent<ExtractionVolumeDebug>();
			}
		}
	}
	public class ScaleController : MonoBehaviourPunCallbacks
	{
		public static readonly HashSet<ScaleController> Scaled = new HashSet<ScaleController>();

		internal static float FootstepPitchMult = 1f;

		public static bool AllowManualScale = true;

		public Transform? ScaleTarget;

		internal IScaleHandler? Handler;

		internal object? HandlerState;

		internal bool HandlerOwnsScale;

		internal PhysGrabObject? _physGrabObject;

		internal Transform _t;

		internal Rigidbody? _rb;

		internal float _originalMass;

		private RoomVolumeCheck? _roomVolumeCheck;

		private Vector3 _originalRoomVolumeSize;

		private Vector3 _originalCheckPosition;

		private bool _isItem;

		internal ItemEquippable? _itemEquippable;

		internal List<ItemHandler.ScaledField>? _scaledItemFields;

		internal bool _invertedActive;

		internal Vector3 _target;

		internal Vector3 _animScale;

		internal bool _transitioning;

		internal float _currentAnimSpeed = ScaleOptions.Default.Speed;

		private Coroutine? _playerBounceAnim;

		private float _shrinkTimer;

		internal ScaleOptions _options;

		internal float _bonkImmuneTimer;

		internal string _displayName = "";

		internal PhotonView? _networkPV;

		internal AudioPitchHelper _audioPitch = new AudioPitchHelper();

		private float _pgoVanillaMassOriginal;

		public static bool ChallengeMode { get; set; }

		public Vector3 OriginalScale { get; internal set; }

		public bool IsScaled { get; private set; }

		public ScaleOptions CurrentOptions => _options;

		public ScaleTargets TargetType
		{
			get
			{
				if (!(Handler is PlayerHandler))
				{
					if (!(Handler is EnemyHandler))
					{
						if (!(Handler is ItemHandler))
						{
							if (!(Handler is VehicleHandler))
							{
								return ScaleTargets.Valuables;
							}
							return ScaleTargets.Items;
						}
						return ScaleTargets.Items;
					}
					return ScaleTargets.Enemies;
				}
				return ScaleTargets.Players;
			}
		}

		internal bool PhysicallyCapped
		{
			get
			{
				if (Handler is EnemyHandler && _options.EnemyPhysicalFactorCap > 0f && _options.Factor > 1f)
				{
					return _options.Factor > _options.EnemyPhysicalFactorCap;
				}
				return false;
			}
		}

		internal float PhysicalFactor
		{
			get
			{
				if (!PhysicallyCapped)
				{
					return _options.Factor;
				}
				return Mathf.Max(1f, _options.EnemyPhysicalFactorCap);
			}
		}

		private void Awake()
		{
			//IL_0013: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_t = ((Component)this).transform;
			OriginalScale = ((Component)this).transform.localScale;
			_target = OriginalScale;
			_animScale = OriginalScale;
		}

		private void Start()
		{
			//IL_0044: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			Handler = ScaleHandlerRegistry.Resolve(((Component)this).gameObject);
			Handler?.Setup(this);
			if ((Object)(object)ScaleTarget != (Object)null)
			{
				_t = ScaleTarget;
				OriginalScale = _t.localScale;
				_target = OriginalScale;
				_animScale = OriginalScale;
			}
			_rb = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)_rb != (Object)null)
			{
				_originalMass = _rb.mass;
			}
			if ((Object)(object)_physGrabObject == (Object)null)
			{
				_physGrabObject = ((Component)this).GetComponent<PhysGrabObject>();
			}
			_roomVolumeCheck = ((Component)this).GetComponent<RoomVolumeCheck>();
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_originalRoomVolumeSize = _roomVolumeCheck.currentSize;
				_originalCheckPosition = _roomVolumeCheck.CheckPosition;
			}
			EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
			_displayName = (((Object)(object)componentInParent != (Object)null) ? ((Object)((Component)componentInParent).gameObject).name : ((Object)((Component)this).gameObject).name);
			_isItem = (Object)(object)((Component)this).GetComponent<ItemAttributes>() != (Object)null;
			_itemEquippable = ((Component)this).GetComponent<ItemEquippable>();
			string text = ((Handler != null) ? Handler.GetType().Name.Replace("Handler", "").ToLower() : "base");
			EnemyParent componentInParent2 = ((Component)this).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent2 != (Object)null)
			{
				int num = 0;
				ScaleController[] componentsInChildren = ((Component)componentInParent2).GetComponentsInChildren<ScaleController>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)(object)this)
					{
						num++;
					}
				}
				if (num > 0)
				{
					Plugin.Log.LogWarning((object)$"[SC] *** DUPLICATE: {_displayName} already has {num} other ScaleController(s) under same EnemyParent ***");
				}
			}
			_networkPV = ((MonoBehaviourPun)this).photonView ?? ((Component)this).GetComponentInParent<PhotonView>();
			PhotonView? networkPV = _networkPV;
			if (networkPV != null)
			{
				networkPV.RefreshRpcMonoBehaviourCache();
			}
			EnemyHandler.State state = HandlerState as EnemyHandler.State;
			Plugin.Log.LogDebug((object)("[SC] Registered " + _displayName + " (" + text + ")" + $"  scale={OriginalScale}" + "  mass=" + (((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F2") : "none") + "  animTarget=" + (((Object)(object)state?.AnimTarget != (Object)null) ? ((Object)((Component)state.AnimTarget).gameObject).name : "NONE") + "  navAgent=" + (((Object)(object)state?.NavAgent != (Object)null) ? "yes" : "no")));
			if (Handler is PlayerHandler && SemiFunc.RunIsLobbyMenu())
			{
				((MonoBehaviour)this).StartCoroutine(LobbyPitchDeferred());
			}
			if (ChallengeMode && Handler is PlayerHandler && !SemiFunc.RunIsLobbyMenu())
			{
				((MonoBehaviour)this).StartCoroutine(ChallengeModeDeferred());
			}
		}

		private void Update()
		{
			bool flag = SemiFunc.IsMasterClientOrSingleplayer();
			if (flag)
			{
				if (IsScaled && _shrinkTimer > 0f)
				{
					_shrinkTimer -= Time.deltaTime;
					if (_shrinkTimer <= 0f)
					{
						DispatchExpand();
					}
				}
				if (_bonkImmuneTimer > 0f)
				{
					_bonkImmuneTimer -= Time.deltaTime;
				}
				if (IsScaled && Handler != null)
				{
					Handler.OnUpdate(this);
				}
			}
			if (!flag && IsScaled && Handler is PlayerHandler)
			{
				Handler.OnUpdate(this);
			}
			if (IsScaled && Handler is ValuableHandler)
			{
				ValuableHandler.OnDiagnoseMass(this, flag);
			}
		}

		private bool IsItemInInventory()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if ((Object)(object)_itemEquippable == (Object)null)
			{
				return false;
			}
			if (_itemEquippable.IsEquipped())
			{
				return true;
			}
			return (int)_itemEquippable.currentState > 0;
		}

		private void LateUpdate()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0148: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			bool flag = IsItemInInventory();
			bool flag2 = Handler is PlayerHandler;
			if (_transitioning && !flag2 && !flag)
			{
				float currentAnimSpeed = _currentAnimSpeed;
				Vector3 originalScale = OriginalScale;
				float num = currentAnimSpeed * ((Vector3)(ref originalScale)).magnitude;
				_animScale = Vector3.MoveTowards(_animScale, _target, num * Time.deltaTime);
				if (!HandlerOwnsScale)
				{
					_t.localScale = ClampPhysical(_animScale);
				}
				if (_animScale == _target)
				{
					_transitioning = false;
					Plugin.Log.LogDebug((object)$"[SC] LATE_ANIM DONE  {_displayName}  finalScale={_animScale}");
				}
			}
			Handler?.OnLateUpdate(this);
			if (!flag2 && !HandlerOwnsScale && IsScaled && !_transitioning && !flag)
			{
				Vector3 val = ClampPhysical(_target);
				if (_t.localScale != val)
				{
					Plugin.Log.LogDebug((object)$"[SC] LATE_FORCE  {_displayName}  was={_t.localScale}  forcing={val}");
				}
				_t.localScale = val;
			}
		}

		private Vector3 ClampPhysical(Vector3 intended)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (!PhysicallyCapped || OriginalScale.x <= 0f)
			{
				return intended;
			}
			Vector3 val = OriginalScale * Mathf.Max(1f, _options.EnemyPhysicalFactorCap);
			return new Vector3(Mathf.Min(intended.x, val.x), Mathf.Min(intended.y, val.y), Mathf.Min(intended.z, val.z));
		}

		private void ScalePgoMassOriginal(float f)
		{
			if (!((Object)(object)_physGrabObject == (Object)null) && !_isItem && !_options.PreserveMass)
			{
				if (_pgoVanillaMassOriginal == 0f)
				{
					_pgoVanillaMassOriginal = ((_physGrabObject.massOriginal > 0f) ? _physGrabObject.massOriginal : _originalMass);
				}
				if (!(_pgoVanillaMassOriginal <= 0f))
				{
					_physGrabObject.massOriginal = Mathf.Clamp(_pgoVanillaMassOriginal * f, 0.5f, _options.MassCap);
				}
			}
		}

		private void RestorePgoMassOriginal()
		{
			if ((Object)(object)_physGrabObject != (Object)null && _pgoVanillaMassOriginal > 0f)
			{
				_physGrabObject.massOriginal = _pgoVanillaMassOriginal;
			}
			_pgoVanillaMassOriginal = 0f;
		}

		public override void OnDisable()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviourPunCallbacks)this).OnDisable();
			if (IsScaled && Handler is EnemyHandler)
			{
				Plugin.Log.LogDebug((object)("[SC] DISABLE (despawn) " + _displayName + "  restoring scale"));
				_t.localScale = OriginalScale;
				_animScale = OriginalScale;
				_target = OriginalScale;
				_transitioning = false;
				IsScaled = false;
				_invertedActive = false;
				_shrinkTimer = 0f;
				Scaled.Remove(this);
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				Handler?.OnRestore(this, isBonk: false);
				_audioPitch.RestorePitch();
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
			}
		}

		private void OnDestroy()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (IsScaled)
			{
				_t.localScale = OriginalScale;
				PlayerHandler.State obj = HandlerState as PlayerHandler.State;
				if (obj != null)
				{
					PlayerVoiceChat voiceChat = obj.PlayerAvatar.voiceChat;
					if (voiceChat != null)
					{
						voiceChat.OverridePitchCancel();
					}
				}
				Handler?.OnDestroy(this);
			}
			Scaled.Remove(this);
		}

		public void DispatchShrink(ScaleOptions options)
		{
			//IL_0082: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: 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_0410: 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_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: 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)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			if (!ScaleManager.AllowDeadHeads && (Object)(object)((Component)this).GetComponent<PlayerDeathHead>() != (Object)null)
			{
				Plugin.Log.LogDebug((object)("[SC] DispatchShrink ignored: " + _displayName + " is a dead Semibot head and ScaleManager.AllowDeadHeads is off"));
				return;
			}
			Plugin.Log.LogDebug((object)$"[SC] DispatchShrink ENTER  {_displayName}  instanceID={((Object)this).GetInstanceID()}  IsScaled={IsScaled}  currentScale={_t.localScale}  GO={((Object)((Component)this).gameObject).name}");
			Stopwatch swApply = Stopwatch.StartNew();
			if (IsScaled)
			{
				if (Mathf.Approximately(options.Factor, _options.Factor))
				{
					DispatchExpand();
					if (_invertedActive)
					{
						_bonkImmuneTimer = _options.BonkImmuneDuration;
					}
					return;
				}
				Plugin.Log.LogDebug((object)$"[SC] RESCALE {_displayName}  {_options.Factor} → {options.Factor}");
				_options = options;
				_shrinkTimer = _options.Duration;
				if (_shrinkTimer < 0f)
				{
					_shrinkTimer = 0f;
				}
				float factor = _options.Factor;
				Vector3 val = OriginalScale * factor;
				_bonkImmuneTimer = _options.BonkImmuneDuration;
				_currentAnimSpeed = _options.Speed;
				ApplyScale(val);
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor;
				}
				if ((Object)(object)_rb != (Object)null && !_isItem && !_options.PreserveMass)
				{
					_rb.mass = Mathf.Clamp(_originalMass * factor, 0.5f, _options.MassCap);
				}
				ScalePgoMassOriginal(factor);
				SetForceGrabPoint(factor >= 1f);
				if (!_options.SuppressVoicePitch)
				{
					EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
					_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent != (Object)null) ? ((ScaleController)(object)componentInParent) : this), factor, _options.AudioPresence);
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = ItemHandler.OnShrinkFields(this, factor);
				if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_Shrink", (RpcTarget)1, new object[3]
					{
						val,
						PackOpts(),
						PackBools()
					});
				}
				WarnIfSlow("rescale");
				return;
			}
			if (options.Factor <= 0f)
			{
				options.Factor = ScaleOptions.Default.Factor;
			}
			if (options.Speed <= 0f)
			{
				options.Speed = ScaleOptions.Default.Speed;
			}
			_options = options;
			_invertedActive = _options.InvertedMode;
			IsScaled = true;
			_shrinkTimer = _options.Duration;
			if (_shrinkTimer < 0f)
			{
				_shrinkTimer = 0f;
			}
			_currentAnimSpeed = _options.Speed;
			Scaled.Add(this);
			float factor2 = _options.Factor;
			Vector3 val2 = OriginalScale * factor2;
			Vector3 val3 = OriginalScale - val2;
			float magnitude = ((Vector3)(ref val3)).magnitude;
			float speed = _options.Speed;
			val3 = OriginalScale;
			float num = speed * ((Vector3)(ref val3)).magnitude;
			float num2 = ((num > 0f) ? (magnitude / num * 1.1f) : 0.75f);
			_bonkImmuneTimer = Mathf.Max(num2, _options.BonkImmuneDuration);
			ApplyScale(val2);
			if (factor2 < 1f)
			{
				SetForceGrabPoint(active: false);
			}
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor2;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor2;
			}
			if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
			{
				Plugin.Log.LogDebug((object)$"[SC] RPC_Shrink SEND  {_displayName}  viewID={_networkPV.ViewID}  isMine={_networkPV.IsMine}  target={val2}");
				_networkPV.RPC("RPC_Shrink", (RpcTarget)1, new object[3]
				{
					val2,
					PackOpts(),
					PackBools()
				});
			}
			else
			{
				Plugin.Log.LogDebug((object)string.Format("[SC] RPC_Shrink SKIP  {0}  networkPV={1}  inRoom={2}", _displayName, ((Object)(object)_networkPV == (Object)null) ? "null" : "set", PhotonNetwork.InRoom));
			}
			PlayImpactEffect();
			Plugin.Log.LogDebug((object)("[SC] SHRINK " + _displayName + $"  factor={_options.Factor}" + $"  scale {OriginalScale} → {val2}" + $"  animTime={magnitude / ((num > 0f) ? num : 1f):F2}s" + $"  bonkImmune={_bonkImmuneTimer:F2}s" + "  shrinkDuration=" + ((_shrinkTimer > 0f) ? (_shrinkTimer.ToString("F0") + "s") : "infinite")));
			if ((Object)(object)_rb != (Object)null)
			{
				float num3 = _originalMass * factor2;
				if (!_isItem && !_options.PreserveMass)
				{
					_rb.mass = Mathf.Clamp(num3, 0.5f, _options.MassCap);
				}
				bool flag = !_isItem && !_options.PreserveMass && num3 < 0.5f;
				if (Plugin.DiagMass)
				{
					Plugin.Log.LogDebug((object)("[SC-DIAG][HOST] SHRINK_APPLY  " + _displayName + "  " + $"mass {_originalMass:F3} → {_rb.mass:F3}  wantRaw={num3:F3}  cap={_options.MassCap:F2}" + (flag ? "  *FLOOR_HIT*" : "") + (_isItem ? "  (item, mass untouched)" : "") + (_options.PreserveMass ? "  (PreserveMass, mass untouched)" : "") + (((Object)(object)_physGrabObject != (Object)null) ? $"  pgo.massOrig={_physGrabObject.massOriginal:F3}  pgo.timerAlter={_physGrabObject.timerAlterMass:F2}" : "")));
				}
			}
			ScalePgoMassOriginal(factor2);
			Handler?.OnScale(this);
			if (factor2 < 1f && (Object)(object)_physGrabObject != (Object)null && Handler is ValuableHandler)
			{
				_physGrabObject.OverrideIndestructible(0.5f);
			}
			if (!_options.SuppressVoicePitch)
			{
				EnemyParent componentInParent2 = ((Component)this).GetComponentInParent<EnemyParent>();
				_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent2 != (Object)null) ? ((ScaleController)(object)componentInParent2) : this), _options.Factor, _options.AudioPresence);
			}
			_scaledItemFields = ItemHandler.OnShrinkFields(this, _options.Factor);
			ScaleMapIcon(factor2);
			WarnIfSlow("fresh");
			void WarnIfSlow(string path)
			{
				swApply.Stop();
				if (swApply.ElapsedMilliseconds >= 10)
				{
					Plugin.Log.LogWarning((object)$"[SC] slow scale apply ({path}): {swApply.ElapsedMilliseconds}ms on {_displayName}");
				}
			}
		}

		public void DispatchExpand()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && IsScaled)
			{
				IsScaled = false;
				Scaled.Remove(this);
				float num = ((OriginalScale.x > 0f) ? (_t.localScale.x / OriginalScale.x) : 0f);
				Plugin.Log.LogDebug((object)("[SC] EXPAND (timer/shot) " + _displayName + $"  currentSize={num * 100f:F0}%" + string.Format("  mass {0} → {1:F3}", ((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F3") : "N/A", _originalMass)));
				_currentAnimSpeed = ResolveExpandSpeed();
				ApplyScale(OriginalScale);
				SetForceGrabPoint(active: true);
				if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_Expand", (RpcTarget)1, Array.Empty<object>());
				}
				PlayImpactEffect();
				PlayCameraShake();
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				Handler?.OnRestore(this, isBonk: false);
				if (!_options.SuppressVoicePitch)
				{
					_audioPitch.RestorePitch();
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
				ScaleMapIcon(1f);
			}
		}

		public void DispatchExpandNow()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || !IsScaled || _options.IgnoreBonkExpand)
			{
				return;
			}
			if (_bonkImmuneTimer > 0f)
			{
				Plugin.Log.LogDebug((object)$"[SC] BONK BLOCKED {_displayName}  immune={_bonkImmuneTimer:F2}s remaining");
				return;
			}
			IsScaled = false;
			_shrinkTimer = 0f;
			Scaled.Remove(this);
			float num = ((OriginalScale.x > 0f) ? (_t.localScale.x / OriginalScale.x) : 0f);
			Plugin.Log.LogDebug((object)("[SC] EXPAND (bonk/instant) " + _displayName + $"  currentSize={num * 100f:F0}%" + string.Format("  mass {0} → {1:F3}", ((Object)(object)_rb != (Object)null) ? _rb.mass.ToString("F3") : "N/A", _originalMass)));
			_currentAnimSpeed = ResolveExpandSpeed();
			ApplyScale(OriginalScale);
			SetForceGrabPoint(active: true);
			if ((Object)(object)_networkPV != (Object)null && PhotonNetwork.InRoom)
			{
				_networkPV.RPC("RPC_Expand", (RpcTarget)1, Array.Empty<object>());
			}
			PlayImpactEffect();
			PlayCameraShake();
			if ((Object)(object)_rb != (Object)null)
			{
				_rb.mass = _originalMass;
			}
			RestorePgoMassOriginal();
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition;
			}
			Handler?.OnRestore(this, isBonk: true);
			if (!_options.SuppressVoicePitch)
			{
				_audioPitch.RestorePitch();
			}
			ItemHandler.OnRestoreFields(_scaledItemFields);
			_scaledItemFields = null;
			ScaleMapIcon(1f);
		}

		private void ApplyScale(Vector3 target)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			_target = target;
			if (!PhysicallyCapped)
			{
				_animScale = _t.localScale;
			}
			_transitioning = true;
			if (Handler is PlayerHandler)
			{
				if (_playerBounceAnim != null)
				{
					((MonoBehaviour)this).StopCoroutine(_playerBounceAnim);
				}
				_playerBounceAnim = ((MonoBehaviour)this).StartCoroutine(PlayerBounceAnim(_t.localScale, target));
			}
		}

		private void PlayImpactEffect()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!_options.SuppressImpactFlash)
			{
				AssetManager instance = AssetManager.instance;
				if (instance != null)
				{
					instance.PhysImpactEffect(_t.position);
				}
			}
		}

		private void PlayCameraShake()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!_options.SuppressCameraShake)
			{
				SemiFunc.CameraShakeImpactDistance(_t.position, 2f, 0.1f, 1f, 8f);
			}
		}

		private float ResolveExpandSpeed()
		{
			if (!(_options.RestoreSpeed > 0f))
			{
				return _options.Speed;
			}
			return _options.RestoreSpeed;
		}

		private void ScaleMapIcon(float factor)
		{
			//IL_0036: 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)
			MapCustom val = ((Component)this).GetComponent<MapCustom>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)this).GetComponentInParent<MapCustom>();
			}
			if ((Object)(object)val?.mapCustomEntity != (Object)null)
			{
				((Component)val.mapCustomEntity).transform.localScale = Vector3.one * Mathf.Max(factor, 0.3f);
			}
		}

		private void SetForceGrabPoint(bool active)
		{
			if ((Object)(object)_physGrabObject != (Object)null && (Object)(object)_physGrabObject.forceGrabPoint != (Object)null)
			{
				((Component)_physGrabObject.forceGrabPoint).gameObject.SetActive(active);
			}
		}

		private static float BackOutEase(float t)
		{
			return 1f + 2.70158f * Mathf.Pow(t - 1f, 3f) + 1.70158f * Mathf.Pow(t - 1f, 2f);
		}

		private IEnumerator PlayerBounceAnim(Vector3 from, Vector3 to)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			float duration = 0.4f;
			float elapsed = 0f;
			while (elapsed < duration)
			{
				elapsed += Time.deltaTime;
				float num = BackOutEase(Mathf.Clamp01(elapsed / duration));
				_t.localScale = Vector3.LerpUnclamped(from, to, num);
				yield return null;
			}
			_t.localScale = to;
			_transitioning = false;
			_playerBounceAnim = null;
		}

		private IEnumerator ChallengeModeDeferred()
		{
			while ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				yield return null;
			}
			if (SemiFunc.IsMultiplayer())
			{
				PlayerHandler.State playerState = HandlerState as PlayerHandler.State;
				while ((Object)(object)playerState?.PlayerAvatar.voiceChat == (Object)null)
				{
					yield return null;
				}
			}
			if (!IsScaled && SemiFunc.IsMasterClientOrSingleplayer())
			{
				ScaleOptions options = ScaleOptions.Default;
				options.InvertedMode = true;
				options.Duration = 0f;
				DispatchShrink(options);
			}
		}

		private IEnumerator LobbyPitchDeferred()
		{
			for (int i = 0; i < 10; i++)
			{
				yield return null;
			}
			PlayerVoiceChat[] array = Object.FindObjectsOfType<PlayerVoiceChat>();
			foreach (PlayerVoiceChat val in array)
			{
				if (ChallengeMode)
				{
					val.OverridePitch(1.3f, 0.2f, 0.5f, 9999f, 0f, 0f);
				}
				else
				{
					val.OverridePitchCancel();
				}
			}
		}

		private float[] PackOpts()
		{
			return new float[10] { _options.Factor, _options.Speed, _options.MassCap, _options.SpeedFactor, _options.AnimSpeedMultiplier, _options.FootstepPitchMultiplier, _options.BonkImmuneDuration, _options.RestoreSpeed, _options.AudioPresence, _options.EnemyPhysicalFactorCap };
		}

		private bool[] PackBools()
		{
			return new bool[7] { _options.PreserveMass, _options.InvertedMode, _options.SuppressImpactFlash, _options.SuppressVoicePitch, _options.IgnoreBonkExpand, _options.RejectExternalApply, _options.SuppressCameraShake };
		}

		[PunRPC]
		private void RPC_Shrink(Vector3 target, float[] opts, bool[] flags, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_003a: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: 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)
			if (PhotonNetwork.InRoom && (info.Sender == null || info.Sender != PhotonNetwork.MasterClient))
			{
				return;
			}
			Plugin.Log.LogDebug((object)string.Format("[SC] RPC_Shrink RECV  {0}  target={1}  factor={2}  speed={3}  handler={4}", _displayName, target, opts[0], opts[1], Handler?.GetType().Name ?? "null"));
			_options.Factor = opts[0];
			_options.Speed = opts[1];
			_options.MassCap = opts[2];
			_options.SpeedFactor = opts[3];
			_options.AnimSpeedMultiplier = opts[4];
			_options.FootstepPitchMultiplier = opts[5];
			_options.BonkImmuneDuration = opts[6];
			_options.RestoreSpeed = ((opts.Length > 7) ? opts[7] : 0f);
			_options.AudioPresence = ((opts.Length > 8) ? opts[8] : 1f);
			_options.EnemyPhysicalFactorCap = ((opts.Length > 9) ? opts[9] : 0f);
			_options.PreserveMass = flags[0];
			_options.InvertedMode = flags[1];
			_options.SuppressImpactFlash = flags.Length > 2 && flags[2];
			_options.SuppressVoicePitch = flags.Length > 3 && flags[3];
			_options.IgnoreBonkExpand = flags.Length > 4 && flags[4];
			_options.RejectExternalApply = flags.Length > 5 && flags[5];
			_options.SuppressCameraShake = flags.Length > 6 && flags[6];
			_invertedActive = flags[1];
			float factor = _options.Factor;
			IsScaled = true;
			_currentAnimSpeed = _options.Speed;
			Scaled.Add(this);
			if ((Object)(object)_rb != (Object)null && !_isItem && !_options.PreserveMass)
			{
				_rb.mass = Mathf.Clamp(_originalMass * factor, 0.5f, _options.MassCap);
			}
			ScalePgoMassOriginal(factor);
			if ((Object)(object)_rb != (Object)null && Handler is ValuableHandler)
			{
				float num = _originalMass * factor;
				bool flag = !_isItem && !_options.PreserveMass && num < 0.5f;
				if (Plugin.DiagMass)
				{
					Plugin.Log.LogDebug((object)("[SC-DIAG][CLIENT] RPC_SHRINK_APPLY  " + _displayName + "  " + $"mass {_originalMass:F3} → {_rb.mass:F3}  wantRaw={num:F3}  cap={_options.MassCap:F2}" + (flag ? "  *FLOOR_HIT*" : "") + (((Object)(object)_physGrabObject != (Object)null) ? $"  pgo.massOrig={_physGrabObject.massOriginal:F3}" : "")));
				}
			}
			if ((Object)(object)_roomVolumeCheck != (Object)null)
			{
				_roomVolumeCheck.currentSize = _originalRoomVolumeSize * factor;
				_roomVolumeCheck.CheckPosition = _originalCheckPosition * factor;
			}
			ApplyScale(target);
			if (factor < 1f)
			{
				SetForceGrabPoint(active: false);
			}
			PlayImpactEffect();
			if (!_options.SuppressVoicePitch)
			{
				EnemyParent componentInParent = ((Component)this).GetComponentInParent<EnemyParent>();
				_audioPitch.ApplyPitch((Component)(object)(((Object)(object)componentInParent != (Object)null) ? ((ScaleController)(object)componentInParent) : this), factor, _options.AudioPresence);
			}
			_scaledItemFields = ItemHandler.OnShrinkFields(this, factor);
			Handler?.OnScale(this);
			if (factor < 1f && (Object)(object)_physGrabObject != (Object)null && Handler is ValuableHandler)
			{
				_physGrabObject.OverrideIndestructible(0.5f);
			}
			ScaleMapIcon(factor);
		}

		[PunRPC]
		private void RPC_Expand(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.InRoom || (info.Sender != null && info.Sender == PhotonNetwork.MasterClient))
			{
				IsScaled = false;
				Scaled.Remove(this);
				if ((Object)(object)_rb != (Object)null)
				{
					_rb.mass = _originalMass;
				}
				RestorePgoMassOriginal();
				if ((Object)(object)_roomVolumeCheck != (Object)null)
				{
					_roomVolumeCheck.currentSize = _originalRoomVolumeSize;
					_roomVolumeCheck.CheckPosition = _originalCheckPosition;
				}
				_currentAnimSpeed = ResolveExpandSpeed();
				ApplyScale(OriginalScale);
				SetForceGrabPoint(active: true);
				PlayImpactEffect();
				PlayCameraShake();
				if (!_options.SuppressVoicePitch)
				{
					_audioPitch.RestorePitch();
				}
				ItemHandler.OnRestoreFields(_scaledItemFields);
				_scaledItemFields = null;
				Handler?.OnRestore(this, isBonk: false);
				ScaleMapIcon(1f);
			}
		}

		[PunRPC]
		private void RPC_PlayerPitchCancel(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.InRoom && (info.Sender == null || info.Sender != PhotonNetwork.MasterClient))
			{
				return;
			}
			PlayerHandler.State state = HandlerState as PlayerHandler.State;
			if (state != null)
			{
				PlayerVoiceChat voiceChat = state.PlayerAvatar.voiceChat;
				if (voiceChat != null)
				{
					voiceChat.OverridePitchCancel();
				}
			}
			if (state != null)
			{
				PlayerHandler.RestoreVoicePresence(state);
			}
		}

		private bool SenderOwnsView(PhotonMessageInfo info)
		{
			//IL_0009: 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)
			if (!PhotonNetwork.InRoom)
			{
				return true;
			}
			if (info.Sender != null && (Object)(object)_networkPV != (Object)null)
			{
				return info.Sender == _networkPV.Owner;
			}
			return false;
		}

		public void RequestBonkExpand()
		{
			if (IsScaled)
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					DispatchExpandNow();
				}
				else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_RequestExpand", (RpcTarget)2, new object[1] { true });
				}
			}
		}

		public void RequestInvertedReshrink()
		{
			if (!IsScaled && _invertedActive && !(_bonkImmuneTimer > 0f))
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					DispatchShrink(_options);
				}
				else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
				{
					_networkPV.RPC("RPC_RequestInvertedReshrink", (RpcTarget)2, Array.Empty<object>());
				}
			}
		}

		[PunRPC]
		private void RPC_RequestInvertedReshrink(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && !IsScaled && _invertedActive)
			{
				ScaleOptions options = ScaleOptions.Default;
				options.InvertedMode = true;
				options.Duration = 0f;
				DispatchShrink(options);
			}
		}

		public void RequestManualShrink()
		{
			if (IsScaled)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (AllowManualScale)
				{
					DispatchShrink(ScaleOptions.Default);
				}
			}
			else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
			{
				_networkPV.RPC("RPC_RequestShrink", (RpcTarget)2, Array.Empty<object>());
			}
		}

		[PunRPC]
		private void RPC_RequestShrink(PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && AllowManualScale && !IsScaled)
			{
				DispatchShrink(ScaleOptions.Default);
			}
		}

		public void RequestManualExpand()
		{
			if (!IsScaled)
			{
				return;
			}
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (AllowManualScale)
				{
					DispatchExpand();
				}
			}
			else if ((Object)(object)_networkPV != (Object)null && _networkPV.IsMine && PhotonNetwork.InRoom)
			{
				_networkPV.RPC("RPC_RequestExpand", (RpcTarget)2, new object[1] { false });
			}
		}

		[PunRPC]
		private void RPC_RequestExpand(bool checkImmunity, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer() && SenderOwnsView(info) && IsScaled)
			{
				if (checkImmunity)
				{
					DispatchExpandNow();
				}
				else if (AllowManualScale)
				{
					DispatchExpand();
				}
			}
		}

		public static void CleanupAll()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			foreach (ScaleController item in Scaled)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				item._audioPitch.RestorePitch();
				ItemHandler.OnRestoreFields(item._scaledItemFields);
				item._scaledItemFields = null;
				PlayerHandler.State obj = item.HandlerState as PlayerHandler.State;
				if (obj != null)
				{
					PlayerVoiceChat voiceChat = obj.PlayerAvatar.voiceChat;
					if (voiceChat != null)
					{
						voiceChat.OverridePitchCancel();
					}
				}
				item.Handler?.OnRestore(item, isBonk: false);
				item.IsScaled = false;
				item._invertedActive = false;
				item._transitioning = false;
				item._target = item.OriginalScale;
				item._animScale = item.OriginalScale;
				item._t.localScale = item.OriginalScale;
			}
			Scaled.Clear();
		}

		public override void OnJoinedRoom()
		{
			PhotonView? networkPV = _networkPV;
			if (networkPV != null)
			{
				networkPV.RefreshRpcMonoBehaviourCache();
			}
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				if (ChallengeMode && Handler is PlayerHandler)
				{
					((MonoBehaviour)this).StartCoroutine(LobbyPitchDeferred());
				}
				if (IsScaled && !((Object)(object)_networkPV == (Object)null))
				{
					_networkPV.RPC("RPC_Shrink", newPlayer, new object[3]
					{
						_target,
						PackOpts(),
						PackBools()
					});
				}
			}
		}
	}
	public static class ScaleManager
	{
		public static bool AllowDeadHeads { get; set; }

		public static void Apply(GameObject target)
		{
			Apply(target, ScaleOptions.Default);
		}

		public static void Apply(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && !IsLockedFromExternal(controller) && IsTargetAllowed(controller, options.AllowedTargets))
			{
				controller.DispatchShrink(options);
			}
		}

		public static bool ApplyIfNotScaled(GameObject target)
		{
			return ApplyIfNotScaled(target, ScaleOptions.Default);
		}

		public static bool ApplyIfNotScaled(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null || controller.IsScaled)
			{
				return false;
			}
			if (IsLockedFromExternal(controller))
			{
				return false;
			}
			if (!IsTargetAllowed(controller, options.AllowedTargets))
			{
				return false;
			}
			controller.DispatchShrink(options);
			return true;
		}

		public static void ForceApply(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && IsTargetAllowed(controller, options.AllowedTargets))
			{
				controller.DispatchShrink(options);
			}
		}

		public static ScaleController? GetController(GameObject target)
		{
			ScaleController scaleController = target.GetComponent<ScaleController>();
			if (scaleController == null)
			{
				PlayerShrinkLink component = target.GetComponent<PlayerShrinkLink>();
				if (component == null)
				{
					return null;
				}
				scaleController = component.Controller;
			}
			return scaleController;
		}

		public static void Restore(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && !IsLockedFromExternal(controller))
			{
				controller.DispatchExpand();
			}
		}

		public static void RestoreImmediate(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null) && !IsLockedFromExternal(controller))
			{
				controller.DispatchExpandNow();
			}
		}

		public static void ForceRestore(GameObject target)
		{
			ScaleController controller = GetController(target);
			if (!((Object)(object)controller == (Object)null))
			{
				controller.DispatchExpand();
			}
		}

		public static bool UpdateOptions(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null || !controller.IsScaled)
			{
				return false;
			}
			if (IsLockedFromExternal(controller))
			{
				return false;
			}
			controller._options = options;
			return true;
		}

		public static bool ForceUpdateOptions(GameObject target, ScaleOptions options)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller == (Object)null || !controller.IsScaled)
			{
				return false;
			}
			controller._options = options;
			return true;
		}

		public static bool IsScaled(GameObject target)
		{
			ScaleController controller = GetController(target);
			if ((Object)(object)controller != (Object)null)
			{
				return controller.IsScaled;
			}
			return false;
		}

		public static void CleanupAll()
		{
			ScaleController.CleanupAll();
		}

		private static bool IsTargetAllowed(ScaleController ctrl, ScaleTargets allowed)
		{
			IScaleHandler handler = ctrl.Handler;
			if (!(handler is PlayerHandler))
			{
				if (!(handler is EnemyHandler))
				{
					if (handler is ItemHandler || handler is VehicleHandler)
					{
						return (allowed & ScaleTargets.Items) != 0;
					}
					return (allowed & ScaleTargets.Valuables) != 0;
				}
				return (allowed & ScaleTargets.Enemies) != 0;
			}
			return (allowed & ScaleTargets.Players) != 0;
		}

		private static bool IsLockedFromExternal(ScaleController ctrl)
		{
			if (ctrl.IsScaled)
			{
				return ctrl._options.RejectExternalApply;
			}
			return false;
		}
	}
	[Flags]
	public enum ScaleTargets
	{
		None = 0,
		Players = 1,
		Enemies = 2,
		Items = 4,
		Valuables = 8,
		All = 0xF
	}
	public struct ScaleOptions
	{
		public float Factor;

		public float Duration;

		public float Speed;

		public float RestoreSpeed;

		public float BonkImmuneDuration;

		public float MassCap;

		public float SpeedFactor;

		public float AnimSpeedMultiplier;

		public float FootstepPitchMultiplier;

		public float AudioPresence;

		public float EnemyPhysicalFactorCap;

		public ScaleTargets AllowedTargets;

		public bool InvertedMode;

		public bool SuppressValueDropExpand;

		public bool PreserveMass;

		public bool SuppressImpactFlash;

		public bool SuppressCameraShake;

		public bool SuppressVoicePitch;

		public bool IgnoreBonkExpand;

		public bool RejectExternalApply;

		public static ScaleOptions Growth => new ScaleOptions
		{
			Factor = 2f,
			Duration = 0f,
			Speed = 2f,
			RestoreSpeed = 0f,
			BonkImmuneDuration = 5f,
			MassCap = 500f,
			SpeedFactor = 1.25f,
			AnimSpeedMultiplier = 0.75f,
			FootstepPitchMultiplier = 0.55f,
			AudioPresence = 1f,
			EnemyPhysicalFactorCap = 1.4f,
			AllowedTargets = ScaleTargets.All,
			InvertedMode = false,
			SuppressValueDropExpand = false,
			PreserveMass = false,
			SuppressImpactFlash = false,
			SuppressCameraShake = false,
			SuppressVoicePitch = false,
			IgnoreBonkExpand = false,
			RejectExternalApply = false
		};

		public static ScaleOptions Default => new ScaleOptions
		{
			Factor = 0.4f,
			Duration = 0f,
			Speed = 2f,
			RestoreSpeed = 0f,
			BonkImmuneDuration = 5f,
			MassCap = 50f,
			SpeedFactor = 0.75f,
			AnimSpeedMultiplier = 1.5f,
			FootstepPitchMultiplier = 1.5f,
			AudioPresence = 1f,
			EnemyPhysicalFactorCap = 0f,
			AllowedTargets = ScaleTargets.All,
			InvertedMode = false,
			SuppressValueDropExpand = false,
			PreserveMass = false,
			SuppressImpactFlash = false,
			SuppressCameraShake = false,
			SuppressVoicePitch = false,
			IgnoreBonkExpand = false,
			RejectExternalApply = false
		};
	}
}
namespace ScalerCore.Utilities
{
	internal class AudioPitchHelper
	{
		private const float GrowVolumeBoost = 0.25f;

		private const float GrowReverbBoost = 0.15f;

		private Sound[]? _pitchedSounds;

		private float[]? _soundOriginalPitch;

		private float[]? _soundOriginalLoopPitch;

		private float[]? _soundOriginalVolume;

		private float[]? _soundOriginalLoopVolume;

		private float[]? _soundOriginalReverb;

		private float[]? _soundOriginalFalloff;

		private static readonly Dictionary<Type, FieldInfo[]> _soundFieldCache = new Dictionary<Type, FieldInfo[]>();

		private static float VolumeMult(float presence)
		{
			return 1f + 0.25f * Mathf.Clamp01(presence);
		}

		private static float ReverbMult(float presence)
		{
			return 1f + 0.15f * Mathf.Clamp01(presence);
		}

		private static float FalloffMult(float factor, float presence)
		{
			return Mathf.Lerp(1f, factor, Mathf.Clamp01(presence));
		}

		internal static Sound[] GatherSounds(Component root)
		{
			HashSet<Sound> hashSet = new HashSet<Sound>();
			List<Sound> list = new List<Sound>();
			MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Type type = ((object)val).GetType();
				if (!_soundFieldCache.TryGetValue(type, out FieldInfo[] value))
				{
					value = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
						where f.FieldType == typeof(Sound)
						select f).ToArray();
					_soundFieldCache[type] = value;
				}
				FieldInfo[] array = value;
				for (int num = 0; num < array.Length; num++)
				{
					object? value2 = array[num].GetValue(val);
					Sound val2 = (Sound)((value2 is Sound) ? value2 : null);
					if (val2 != null && hashSet.Add(val2))
					{
						list.Add(val2);
					}
				}
			}
			return list.ToArray();
		}

		private static float PitchMult(float factor)
		{
			if (!(factor >= 1f))
			{
				return Mathf.Clamp(1f + (1f - factor) * 0.5f, 1f, 2f);
			}
			return Mathf.Max(0.5f, 1f - (factor - 1f) * 0.35f);
		}

		internal static void PitchOneShot(Component root, float factor, float presence)
		{
			float num = PitchMult(factor);
			bool flag = factor > 1f;
			Sound[] array = GatherSounds(root);
			foreach (Sound val in array)
			{
				val.Pitch *= num;
				val.LoopPitch *= num;
				val.FalloffMultiplier *= FalloffMult(factor, presence);
				if (flag)
				{
					val.Volume = Mathf.Min(1f, val.Volume * VolumeMult(presence));
					val.ReverbMix = Mathf.Min(1f, val.ReverbMix * ReverbMult(presence));
				}
			}
		}

		internal void ApplyPitch(Component searchRoot, float factor, float presence)
		{
			if (_pitchedSounds != null)
			{
				RestorePitch();
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			float num = PitchMult(factor);
			bool flag = factor > 1f;
			_pitchedSounds = GatherSounds(searchRoot);
			_soundOriginalPitch = _pitchedSounds.Select((Sound s) => s.Pitch).ToArray();
			_soundOriginalLoopPitch = _pitchedSounds.Select((Sound s) => s.LoopPitch).ToArray();
			_soundOriginalVolume = _pitchedSounds.Select((Sound s) => s.Volume).ToArray();
			_soundOriginalLoopVolume = _pitchedSounds.Select((Sound s) => s.LoopVolume).ToArray();
			_soundOriginalReverb = _pitchedSounds.Select((Sound s) => s.ReverbMix).ToArray();
			_soundOriginalFalloff = _pitchedSounds.Select((Sound s) => s.FalloffMultiplier).ToArray();
			for (int num2 = 0; num2 < _pitchedSounds.Length; num2++)
			{
				Sound val = _pitchedSounds[num2];
				val.Pitch = _soundOriginalPitch[num2] * num;
				float num3 = _soundOriginalLoopPitch[num2];
				val.LoopPitch = num3 * num;
				val.FalloffMultiplier = _soundOriginalFalloff[num2] * FalloffMult(factor, presence);
				if (flag)
				{
					val.Volume = Mathf.Min(1f, _soundOriginalVolume[num2] * VolumeMult(presence));
					val.LoopVolume = Mathf.Min(1f, _soundOriginalLoopVolume[num2] * VolumeMult(presence));
					val.ReverbMix = Mathf.Min(1f, _soundOriginalReverb[num2] * ReverbMult(presence));
				}
				if ((Object)(object)val.Source != (Object)null && val.Source.isPlaying)
				{
					AudioSource source = val.Source;
					source.pitch *= num;
				}
			}
			Plugin.Log.LogDebug((object)string.Format("[SC]   sound treatment x{0:F2} pitch{1} on {2} Sound objects under {3}", num, flag ? ", grown presence" : "", _pitchedSounds.Length, ((Object)searchRoot.gameObject).name));
			stopwatch.Stop();
			if (stopwatch.ElapsedMilliseconds >= 5)
			{
				Plugin.Log.LogWarning((object)$"[SC] slow sound treatment: {stopwatch.ElapsedMilliseconds}ms for {_pitchedSounds.Length} sounds under {((Object)searchRoot.gameObject).name}");
			}
		}

		internal void RestorePitch()
		{
			if (_pitchedSounds == null)
			{
				return;
			}
			for (int i = 0; i < _pitchedSounds.Length; i++)
			{
				Sound val = _pitchedSounds[i];
				if (val != null)
				{
					val.Pitch = _soundOriginalPitch[i];
					val.LoopPitch = _soundOriginalLoopPitch[i];
					val.Volume = _soundOriginalVolume[i];
					val.LoopVolume = _soundOriginalLoopVolume[i];
					val.ReverbMix = _soundOriginalReverb[i];
					val.FalloffMultiplier = _soundOriginalFalloff[i];
					if ((Object)(object)val.Source != (Object)null && val.Source.isPlaying)
					{
						val.Source.pitch = _soundOriginalLoopPitch[i];
					}
				}
			}
			_pitchedSounds = null;
			_soundOriginalPitch = null;
			_soundOriginalLoopPitch = null;
			_soundOriginalVolume = null;
			_soundOriginalLoopVolume = null;
			_soundOriginalReverb = null;
			_soundOriginalFalloff = null;
		}
	}
	public class ExtractionVolumeDebug : MonoBehaviour
	{
		private readonly List<(BoxCollider col, Color color)> _boxes = new List<(BoxCollider, Color)>();

		private readonly List<RoomVolumeCheck> _checks = new List<RoomVolumeCheck>();

		private bool _built;

		private float _checkTimer;

		private Material? _lineMat;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[8];

		private static readonly Color ProbeIn = Color.red;

		private static readonly Color ProbeOut = new Color(0.2f, 1f, 0.4f, 1f);

		private void Update()
		{
			_checkTimer -= Time.deltaTime;
			if (_checkTimer > 0f)
			{
				return;
			}
			_checkTimer = 0.5f;
			if (SemiFunc.RunIsLevel() && (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated)
			{
				if (!_built)
				{
					RebuildVolumes();
				}
				RefreshChecks();
			}
			else if (_built || _checks.Count > 0)
			{
				Clear();
			}
		}

		private void RebuildVolumes()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			_boxes.Clear();
			ExtractionPoint[] array = Object.FindObjectsOfType<ExtractionPoint>();
			foreach (ExtractionPoint val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.roomVolume == (Object)null)
				{
					continue;
				}
				RoomVolume componentInChildren = val.roomVolume.GetComponentInChildren<RoomVolume>(true);
				Color item = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.Color : Color.cyan);
				item.a = 1f;
				BoxCollider[] componentsInChildren = val.roomVolume.GetComponentsInChildren<BoxCollider>(true);
				foreach (BoxCollider val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						_boxes.Add((val2, item));
					}
				}
			}
			_built = _boxes.Count > 0;
			if (_built)
			{
				Plugin.Log.LogInfo((object)$"[ExtractionDebug] showing {_boxes.Count} extraction volume collider(s)");
			}
		}

		private void RefreshChecks()
		{
			_checks.Clear();
			RoomVolumeCheck[] array = Object.FindObjectsOfType<RoomVolumeCheck>();
			foreach (RoomVolumeCheck val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.valuableObject != (Object)null)
				{
					_checks.Add(val);
				}
			}
		}

		private void Clear()
		{
			_boxes.Clear();
			_checks.Clear();
			_built = false;
		}

		private void OnRenderObject()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (_boxes.Count == 0 && _checks.Count == 0)
			{
				return;
			}
			GameDirector instance = GameDirector.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)Camera.current != (Object)(object)instance.MainCamera)
			{
				return;
			}
			EnsureMaterial();
			_lineMat.SetPass(0);
			GL.PushMatrix();
			GL.Begin(1);
			foreach (var (val, val2) in _boxes)
			{
				if (!((Object)(object)val == (Object)null))
				{
					GL.Color(val2);
					EmitBoxFromCollider(val);
				}
			}
			foreach (RoomVolumeCheck check in _checks)
			{
				if (!((Object)(object)check == (Object)null))
				{
					GL.Color(check.inExtractionPoint ? ProbeIn : ProbeOut);
					EmitProbeBox(check);
				}
			}
			GL.End();
			GL.PopMatrix();
		}

		private void EmitBoxFromCollider(BoxCollider col)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)col).transform;
			Vector3 center = col.center;
			Vector3 val = col.size * 0.5f;
			for (int i = 0; i < 8; i++)
			{
				_corners[i] = transform.TransformPoint(center + Vector3.Scale(val, Signs(i)));
			}
			EmitEdges();
		}

		private void EmitProbeBox(RoomVolumeCheck check)
		{
			//IL_0008: 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_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_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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)check).transform;
			Vector3 val = transform.position + transform.rotation * check.CheckPosition;
			Vector3 val2 = ((check.currentSize == Vector3.zero) ? transform.localScale : check.currentSize) * 0.5f;
			Quaternion rotation = transform.rotation;
			for (int i = 0; i < 8; i++)
			{
				_corners[i] = val + rotation * Vector3.Scale(val2, Signs(i));
			}
			EmitEdges();
		}

		private void EmitEdges()
		{
			//IL_001c: 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)
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					int num = i ^ (1 << j);
					if (num > i)
					{
						GL.Vertex(_corners[i]);
						GL.Vertex(_corners[num]);
					}
				}
			}
		}

		private static Vector3 Signs(int i)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(((i & 1) == 0) ? (-1f) : 1f, ((i & 2) == 0) ? (-1f) : 1f, ((i & 4) == 0) ? (-1f) : 1f);
		}

		private void EnsureMaterial()
		{
			//IL_001a: 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_002c: Expected O, but got Unknown
			if (!((Object)(object)_lineMat != (Object)null))
			{
				_lineMat = new Material(Shader.Find("Hidden/Internal-Colored"))
				{
					hideFlags = (HideFlags)61
				};
				_lineMat.SetInt("_SrcBlend", 5);
				_lineMat.SetInt("_DstBlend", 10);
				_lineMat.SetInt("_Cull", 0);
				_lineMat.SetInt("_ZWrite", 0);
				_lineMat.SetInt("_ZTest", 8);
			}
		}
	}
}
namespace ScalerCore.Patches
{
	[HarmonyPatch(typeof(PhysGrabObject), "OverrideMass")]
	internal static class DiagOverrideMassPatch
	{
		private static void Prefix(PhysGrabObject __instance, float value, float time)
		{
			if (Plugin.DiagMass)
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if (!((Object)(object)component == (Object)null) && component.IsScaled && component.TargetType == ScaleTargets.Valuables)
				{
					Plugin.Log.LogInfo((object)($"[SC-DIAG] PGO.OverrideMass({value:F3}, t={time:F2}s)  on {((Object)((Component)__instance).gameObject).name}" + $"  rbMassNow={__instance.rb.mass:F3}  pgo.massOriginal={__instance.massOriginal:F3}" + $"  pgo.alterMass={__instance.alterMassValue:F3}  pgo.timerAlter={__instance.timerAlterMass:F2}" + "  caller=" + DiagCaller.Resolve()));
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "ResetMass")]
	internal static class DiagResetMassPatch
	{
		private static void Prefix(PhysGrabObject __instance)
		{
			if (Plugin.DiagMass)
			{
				ScaleController component = ((Component)__instance).GetComponent<ScaleController>();
				if (!((Object)(object)component == (Object)null) && component.IsScaled && component.TargetType == ScaleTargets.Valuables)
				{
					Plugin.Log.LogInfo((object)("[SC-DIAG] PGO.ResetMass()  on " + ((Object)((Component)__instance).gameObject).name + $"  rbMassBefore={__instance.rb.mass:F3}  → pgo.massOriginal={__instance.massOriginal:F3}" + "  caller=" + DiagCaller.Resolve()));
				}
			}
		}
	}
	internal static class DiagCaller
	{
		public static string Resolve()
		{
			StackTrace stackTrace = new StackTrace(2, fNeedFileInfo: false);
			for (int i = 0; i < stackTrace.FrameCount; i++)
			{
				MethodBase method = stackTrace.GetFrame(i).GetMethod();
				if (!(method == null))
				{
					string text = method.DeclaringType?.Namespace ?? "";
					string text2 = method.DeclaringType?.Name ?? "?";
					if (!text.StartsWith("HarmonyLib") && !text.StartsWith("System.") && !text2.Contains("DiagOverrideMassPatch") && !text2.Contains("DiagResetMassPatch"))
					{
						return text2 + "." + method.Name;
					}
				}
			}
			return "<unknown>";
		}
	}
	internal static class EnemyPatchHelpers
	{
		internal static bool TryGetScaled(EnemyNavMeshAgent agent, out ScaleController? ctrl)
		{
			EnemyParent componentInParent = ((Component)agent).GetComponentInParent<EnemyParent>();
			ctrl = ((componentInParent != null) ? ((Component)componentInParent).GetComponentInChildren<ScaleController>() : null);
			if ((Object)(object)ctrl != (Object)null)
			{
				return ctrl.IsScaled;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent), "OverrideAgent")]
	internal static class NavOverrideSpeedPatch
	{
		private static void Prefix(EnemyNavMeshAgent __instance, ref float speed)
		{
			if (EnemyPatchHelpers.TryGetScaled(__instance, out ScaleController ctrl))
			{
				speed *= ctrl._options.SpeedFactor;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyNavMeshAgent), "UpdateAgent")]
	internal static class NavUpdateSpeedPatch
	{
		private static void Prefix(EnemyNavMeshAgent __instance, ref float speed)
		{
			if (EnemyPatchHelpers.TryGetScaled(__instance, out ScaleController ctrl))
			{
				speed *= ctrl._options.SpeedFactor;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyFloater), "UpdateState")]
	internal static class FloaterChargeMoveInPatch
	{
		private static void Postfix(EnemyFloater __instance)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			Enemy enemy = __instance.enemy;
			object obj;
			if (enemy == null)
			{
				obj = null;
			}
			else
			{
				EnemyRigidbody rigidbody = enemy.Rigidbody;
				obj = ((rigidbody != null) ? ((Component)rigidbody).GetComponent<ScaleController>() : null);
			}
			ScaleController scaleController = (ScaleController)obj;
			if ((Object)(object)scaleController == (Object)null || !scaleController.IsScaled)
			{
				return;
			}
			PlayerAvatar targetPlayer = __instance.targetPlayer;
			if (Object.op_Implicit((Object)(object)targetPlayer) && !(Vector3.Distance(__instance.feetTransform.position, ((Component)targetPlayer).transform.position) <= scaleController._options.Factor * 4f))
			{
				Enemy enemy2 = __instance.enemy;
				if (enemy2 != null)
				{
					enemy2.NavMeshAgent.SetDestination(((Component)targetPlayer).transform.position);
				}
			}
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "PlayerHurt")]
	internal static class KnockbackPatch
	{
		private static void Prefix(HurtCollider __instance, out (bool playerKill, int playerDamage, int tumbleDamage, float force, float torque) __state)
		{
			__state = (playerKill: __instance.playerKill, playerDamage: __instance.playerDamage, tumbleDamage: __instance.playerTumbleImpactHurtDamage, force: __instance.playerTumbleForce, torque: __instance.playerTumbleTorque);
			ScaleController scaleController = null;
			if ((Object)(object)__instance.enemyHost != (Object)null)
			{
				EnemyRigidbody rigidbody = __instance.enemyHost.Rigidbody;
				scaleController = ((rigidbody != null) ? ((Component)rigidbody).GetComponent<ScaleController>() : null);
			}
			else
			{
				EnemyParent componentInParent = ((Component)__instance).GetComponentInParent<EnemyParent>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					scaleController = ((Component)componentInParent).GetComponentInChildren<ScaleController>();
				}
			}
			if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
			{
				if (scaleController._options.Factor < 1f)
				{
					__instance.playerKill = false;
				}
				__instance.playerDamage = Mathf.RoundToInt((float)__instance.playerDamage * scaleController._options.Factor);
				__instance.playerTumbleImpactHurtDamage = Mathf.RoundToInt((float)__instance.playerTumbleImpactHurtDamage * scaleController._options.Factor);
				__instance.playerTumbleForce *= scaleController._options.Factor;
				__instance.playerTumbleTorque *= scaleController._options.Factor;
			}
		}

		private static void Postfix(HurtCollider __instance, (bool playerKill, int playerDamage, int tumbleDamage, float force, float torque) __state)
		{
			(__instance.playerKill, __instance.playerDamage, __instance.playerTumbleImpactHurtDamage, __instance.playerTumbleForce, __instance.playerTumbleTorque) = __state;
		}
	}
	[HarmonyPatch(typeof(EnemyHeartHuggerGasGuider), "Update")]
	internal static class HeartHuggerGasPullPatch
	{
		private static void Postfix(EnemyHeartHuggerGasGuider __instance)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance.enemyHeartHugger == (Object)null))
			{
				Enemy enemy = __instance.enemyHeartHugger.enemy;
				object obj;
				if (enemy == null)
				{
					obj = null;
				}
				else
				{
					EnemyRigidbody rigidbody = enemy.Rigidbody;
					obj = ((rigidbody != null) ? ((Component)rigidbody).GetComponent<ScaleController>() : null);
				}
				ScaleController scaleController = (ScaleController)obj;
				if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled)
				{
					Vector3 position = __instance.enemyHeartHugger.headCenterTransform.position;
					Vector3 val = ((Component)__instance).transform.position - position;
					((Component)__instance).transform.position = position + val * scaleController._options.Factor;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Hurt")]
	internal static class EnemyBonkPatch
	{
		private static void Postfix(EnemyHealth __instance)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				Enemy enemy = __instance.enemy;
				object obj;
				if (enemy == null)
				{
					obj = null;
				}
				else
				{
					EnemyRigidbody rigidbody = enemy.Rigidbody;
					obj = ((rigidbody != null) ? ((Component)rigidbody).GetComponent<ScaleController>() : null);
				}
				ScaleController scaleController = (ScaleController)obj;
				if (!((Object)(object)scaleController == (Object)null) && scaleController.IsScaled && !(scaleController._options.Factor >= 1f))
				{
					scaleController.DispatchExpandNow();
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class EnemyVisionShrunkCrouchPatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = typeof(EnemyVision).GetNestedTypes(BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.StartsWith("<Vision>"));
			if (type == null)
			{
				Plugin.Log.LogWarning((object)"[SC] EnemyVisionShrunkCrouchPatch: could not find Vision coroutine state machine");
				return null;
			}
			return AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null);
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo isCrouchingField = AccessTools.Field(typeof(PlayerAvatar), "isCrouching");
			MethodInfo helper = AccessTools.Method(typeof(EnemyVisionShrunkCrouchPatch), "IsEffectivelyCrouching", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldfld && instruction.operand is FieldInfo fieldInfo && fieldInfo == isCrouchingField)
				{
					yield return new CodeInstruction(OpCodes.Call, (object)helper);
				}
				else
				{
					yield return instruction;
				}
			}
		}

		internal static bool IsEffectivelyCrouching(PlayerAvatar pa)
		{
			if (pa.isCrouching)
			{
				return true;
			}
			ScaleController component = ((Component)pa).GetComponent<ScaleController>();
			if ((Object)(object)component != (Object)null && component.IsScaled)
			{
				return component._options.Factor < 1f;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyBeamer), "OnVision")]
	internal static class BeamerMeleeRangePatch
	{
		private static float ScaleMeleeRange(float range, EnemyBeamer beamer)
		{
			Enemy enemy = beamer.enemy;
			object obj;
			if (enemy == null)
			{
				obj = null;
			}
			else
			{
				EnemyRigidbody rigidbody = enemy.Rigidbody;
				obj = ((rigidbody != null) ? ((Component)rigidbody).GetComponent<ScaleController>() : null);
			}
			ScaleController scaleController = (ScaleController)obj;
			if ((Object)(object)scaleController == (Object)null || !scaleController.IsScaled)
			{
				return range;
			}
			return range * scaleController._options.Factor;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo helper = AccessTools.Method(typeof(BeamerMeleeRangePatch), "ScaleMeleeRange", (Type[])null, (Type[])null);
			int swapped = 0;
			foreach (CodeInstruction code in instructions)
			{
				yield return code;
				if (code.opcode == OpCodes.Ldc_R4 && code.operand is float num && num == 2.5f)
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)helper);
					swapped++;
				}
			}
			if (swapped != 1)
			{
				Plugin.Log.LogWarning((object)($"[SC] Beamer melee-range transpiler matched {swapped} constants (expected 1). " + "Scaled Beamers keep the vanilla melee trigger range this session; if this appears after a game update, report it."));
			}
		}
	}
}
namespace ScalerCore.Handlers
{
	internal class CartHandler : IScaleHandler
	{
		internal sealed class State
		{
			internal PhysGrabCart Cart;

			internal bool AddedEquippable;
		}

		public void Setup(ScaleController ctrl)
		{
			PhysGrabCart component = ((Component)ctrl).GetComponent<PhysGrabCart>();
			if (!((Object)(object)component == (Object)null))
			{
				ctrl.HandlerState = new State
				{
					Cart = component
				};
			}
		}

		public void OnScale(ScaleController ctrl)
		{
			State state = (State)ctrl.HandlerState;
			if (state != null)
			{
				state.AddedEquippable = PocketHelper.InjectEquippable(ctrl);
			}
		}

		public void OnRestore(ScaleController ctrl, bool isBonk)
		{
			State state = (State)ctrl.HandlerState;
			if (state != null && state.AddedEquippable)
			{
				PocketHelper.RemoveEquippable(ctrl);
				state.AddedEquippable = false;
			}
		}

		public void OnUpdate(ScaleController ctrl)
		{
		}

		public voi