using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using HarmonyLib;
using Peak;
using Peak.Afflictions;
using Photon.Pun;
using Photon.Voice.Unity;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace StatueLife;
[BepInPlugin("local.statuelife", "StatueLife", "0.2.0")]
public sealed class Plugin : BaseUnityPlugin
{
private sealed class FrozenBody
{
private readonly Rigidbody[] rigs;
private readonly RigidbodyConstraints[] constraints;
private readonly Vector3[] positions;
private readonly Quaternion[] rotations;
private readonly Animator animator;
private readonly float speed;
internal FrozenBody(Character c)
{
rigs = (from p in c.refs.ragdoll.partDict.Values
select ((Component)p).GetComponent<Rigidbody>() into r
where (Object)(object)r != (Object)null
select r).Distinct().ToArray();
constraints = rigs.Select((Rigidbody r) => r.constraints).ToArray();
positions = rigs.Select((Rigidbody r) => r.position).ToArray();
rotations = rigs.Select((Rigidbody r) => r.rotation).ToArray();
animator = c.refs.animator;
speed = (((Object)(object)animator == (Object)null) ? 1f : animator.speed);
Hold();
}
internal void Hold()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < rigs.Length; i++)
{
if (!((Object)(object)rigs[i] == (Object)null))
{
rigs[i].constraints = (RigidbodyConstraints)126;
rigs[i].position = positions[i];
rigs[i].rotation = rotations[i];
if (!rigs[i].isKinematic)
{
rigs[i].linearVelocity = Vector3.zero;
rigs[i].angularVelocity = Vector3.zero;
}
}
}
if ((Object)(object)animator != (Object)null)
{
animator.speed = 0f;
}
}
internal void Restore()
{
for (int i = 0; i < rigs.Length; i++)
{
if ((Object)(object)rigs[i] != (Object)null)
{
rigs[i].constraints = constraints[i];
}
}
if ((Object)(object)animator != (Object)null)
{
animator.speed = speed;
}
}
}
internal static Plugin Instance;
internal static volatile bool LocalFrozen;
internal static bool Curing;
internal static readonly HashSet<Character> GivingUp = new HashSet<Character>();
private readonly Dictionary<Character, FrozenBody> bodies = new Dictionary<Character, FrozenBody>();
private Harmony harmony;
private readonly HashSet<int> shatteringViews = new HashSet<int>();
private void Awake()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
Instance = this;
harmony = new Harmony("local.statuelife");
try
{
harmony.PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"StatueLife 0.2.0 loaded (local player only). Friends do not need the mod. Y = shatter; blowgun = cure.");
}
catch (Exception ex)
{
harmony.UnpatchSelf();
((BaseUnityPlugin)this).Logger.LogError((object)("StatueLife could not install its hooks; disabled. " + ex));
((Behaviour)this).enabled = false;
}
}
internal static bool Frozen(Character c)
{
if ((Object)(object)c != (Object)null && c.IsLocal && ((MonoBehaviourPun)c).photonView.IsMine && !c.isBot && (Object)(object)c.data != (Object)null && !c.data.dead && c.data.shouldPetrify)
{
return !GivingUp.Contains(c);
}
return false;
}
private void Update()
{
Character localCharacter = Character.localCharacter;
LocalFrozen = Frozen(localCharacter);
if (LocalFrozen && Application.isFocused && Keyboard.current != null && ((ButtonControl)Keyboard.current.yKey).wasPressedThisFrame && !((Object)(object)GUIManager.instance == (Object)null) && !GUIManager.instance.windowBlockingInput && !GUIManager.instance.wheelActive)
{
ExecuteGiveUp(localCharacter);
}
}
private void ExecuteGiveUp(Character c)
{
if (Frozen(c))
{
GivingUp.Add(c);
Release(c);
LocalFrozen = false;
((MonoBehaviourPun)c).photonView.RPC("RPCA_Die", (RpcTarget)0, new object[0]);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Statue shattered by give-up: " + ((MonoBehaviourPun)c).photonView.ViewID));
}
}
private void LateUpdate()
{
foreach (Character item in new List<Character>(bodies.Keys))
{
if (!Frozen(item))
{
Release(item);
}
}
foreach (Character item2 in new List<Character>(GivingUp))
{
if ((Object)(object)item2 == (Object)null || ((Object)(object)item2.data != (Object)null && !item2.data.dead && !item2.data.shouldPetrify))
{
GivingUp.Remove(item2);
}
}
Character[] array = Character.AllCharacters.ToArray();
foreach (Character val in array)
{
if (Frozen(val))
{
if (!bodies.TryGetValue(val, out var value))
{
value = new FrozenBody(val);
bodies.Add(val, value);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Living statue: " + ((MonoBehaviourPun)val).photonView.ViewID));
}
value.Hold();
}
}
}
internal void Release(Character c)
{
if (bodies.TryGetValue(c, out var value))
{
value.Restore();
bodies.Remove(c);
}
}
internal static void Cure(Character c)
{
if (Frozen(c) && ((MonoBehaviourPun)c).photonView.IsMine)
{
Curing = true;
try
{
c.data.SetPetrify(0);
}
finally
{
Curing = false;
}
c.data.passOutValue = 0f;
c.refs.afflictions.killedByDagger = false;
AccessTools.Method(typeof(CharacterCustomization), "ClearPetrify", (Type[])null, (Type[])null).Invoke(c.refs.customization, null);
Instance.Release(c);
if (c.IsLocal)
{
LocalFrozen = false;
}
((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Blowgun cured statue: " + ((MonoBehaviourPun)c).photonView.ViewID));
}
}
internal IEnumerator Shatter(PetrifiedScout scout)
{
if ((Object)(object)scout == (Object)null || !shatteringViews.Add(((MonoBehaviourPun)scout).photonView.ViewID))
{
yield break;
}
yield return null;
if (!((Object)(object)scout == (Object)null))
{
int viewId = ((MonoBehaviourPun)scout).photonView.ViewID;
((MonoBehaviourPun)scout).photonView.RPC("RPC_BreakPetrifiedScout", (RpcTarget)0, new object[0]);
if (((MonoBehaviourPun)scout).photonView.IsMine || PhotonNetwork.IsMasterClient)
{
PhotonNetwork.Destroy(((Component)scout).gameObject);
}
shatteringViews.Remove(viewId);
}
}
private void OnGUI()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (LocalFrozen)
{
GUI.Box(new Rect((float)Screen.width / 2f - 240f, (float)(Screen.height - 100), 480f, 64f), "PETRIFIED — You are still alive.\nA friend's blowgun cures you. Y = shatter and die.\nVoice chat is muted while petrified.");
}
}
private void OnDestroy()
{
if (harmony != null)
{
harmony.UnpatchSelf();
}
foreach (FrozenBody value in bodies.Values)
{
value.Restore();
}
bodies.Clear();
GivingUp.Clear();
shatteringViews.Clear();
LocalFrozen = false;
if ((Object)(object)Instance == (Object)(object)this)
{
Instance = null;
}
}
}
[HarmonyPatch(typeof(Character), "HandleLife")]
internal static class LifePatch
{
private static bool Prefix(Character __instance)
{
if (!Plugin.Frozen(__instance))
{
return true;
}
__instance.data.passOutValue = 1f;
return false;
}
}
[HarmonyPatch]
internal static class DeathPatch
{
private static IEnumerable<MethodBase> TargetMethods()
{
try
{
string[] array = new string[7] { "Die", "DieInstantly", "DieInstantlyLocal", "RPCA_Die", "RPCA_SetDead", "PassOut", "RPCA_PassOut" };
foreach (string name in array)
{
yield return AccessTools.Method(typeof(Character), name, (Type[])null, (Type[])null);
}
}
finally
{
}
}
private static bool Prefix(Character __instance)
{
return !Plugin.Frozen(__instance);
}
}
[HarmonyPatch(typeof(CharacterData), "SetPetrify")]
internal static class PermanentPatch
{
private static bool Prefix(CharacterData __instance, int __0, ref bool __state)
{
Character component = ((Component)__instance).GetComponent<Character>();
__state = (Object)(object)component != (Object)null && component.IsLocal && __instance.shouldPetrify;
if (!Plugin.Curing && Plugin.Frozen(component))
{
return __0 >= 100;
}
return true;
}
private static void Postfix(CharacterData __instance, bool __state)
{
if (!__state || __instance.shouldPetrify)
{
return;
}
Character component = ((Component)__instance).GetComponent<Character>();
if (!((Object)(object)component == (Object)null))
{
__instance.passOutValue = 0f;
if ((Object)(object)component.refs.customization != (Object)null)
{
AccessTools.Field(typeof(CharacterCustomization), "petrifyStarted").SetValue(component.refs.customization, false);
}
Plugin.Instance.Release(component);
if (component.IsLocal)
{
Plugin.LocalFrozen = false;
}
}
}
}
[HarmonyPatch(typeof(CharacterInput), "Sample")]
internal static class InputPatch
{
private static readonly FieldInfo[] Buttons = (from f in typeof(CharacterInput).GetFields(BindingFlags.Instance | BindingFlags.Public)
where f.FieldType == typeof(bool) && f.Name != "pauseWasPressed" && f.Name != "itemSwitchBlocked"
select f).ToArray();
private static void Postfix(CharacterInput __instance)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
Character localCharacter = Character.localCharacter;
if (Plugin.Frozen(localCharacter) && object.ReferenceEquals(localCharacter.input, __instance))
{
FieldInfo[] buttons = Buttons;
foreach (FieldInfo fieldInfo in buttons)
{
fieldInfo.SetValue(__instance, false);
}
__instance.movementInput = Vector2.zero;
__instance.scrollInput = 0f;
}
}
}
[HarmonyPatch]
internal static class MovePatch
{
private static IEnumerable<MethodBase> TargetMethods()
{
try
{
string[] array = new string[5] { "CheckMovement", "CheckJump", "CheckSprint", "CheckGravity", "CheckStand" };
foreach (string name in array)
{
yield return AccessTools.Method(typeof(Character), name, (Type[])null, (Type[])null);
}
}
finally
{
}
}
private static void Postfix(Character __instance, ref bool __result)
{
if (Plugin.Frozen(__instance))
{
__result = false;
}
}
}
[HarmonyPatch]
internal static class SlotsPatch
{
private static IEnumerable<MethodBase> TargetMethods()
{
try
{
string[] array = new string[4] { "SelectSlotWasPressed", "SelectSlotIsPressed", "HotbarKeyWasPressed", "HotbarKeyIsPressed" };
foreach (string name in array)
{
yield return AccessTools.Method(typeof(CharacterInput), name, (Type[])null, (Type[])null);
}
}
finally
{
}
}
private static void Postfix(CharacterInput __instance, ref bool __result)
{
Character localCharacter = Character.localCharacter;
if (Plugin.Frozen(localCharacter) && object.ReferenceEquals(localCharacter.input, __instance))
{
__result = false;
}
}
}
[HarmonyPatch(typeof(CharacterData), "set_dead")]
internal static class DeadSetterPatch
{
private static bool Prefix(CharacterData __instance, bool __0)
{
if (__0)
{
return !Plugin.Frozen(((Component)__instance).GetComponent<Character>());
}
return true;
}
}
[HarmonyPatch(typeof(Action_RaycastDart), "RPC_DartImpact")]
internal static class DartPatch
{
private static void Prefix(int __0, ref Character __state)
{
Character val = default(Character);
if (Character.GetCharacterWithPhotonID(__0, ref val) && Plugin.Frozen(val) && ((MonoBehaviourPun)val).photonView.IsMine)
{
__state = val;
}
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo original = AccessTools.Method(typeof(CharacterAfflictions), "AddAffliction", new Type[2]
{
typeof(Affliction),
typeof(bool)
}, (Type[])null);
MethodInfo replacement = AccessTools.Method(typeof(DartPatch), "ApplyDartAffliction", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, original))
{
instruction.opcode = OpCodes.Call;
instruction.operand = replacement;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
throw new InvalidOperationException("Unexpected blowgun implementation; refusing partial patch.");
}
}
private static void ApplyDartAffliction(CharacterAfflictions target, Affliction affliction, bool fromRPC)
{
Character component = ((Component)target).GetComponent<Character>();
if (!Plugin.Frozen(component))
{
target.AddAffliction(affliction, fromRPC);
}
}
private static void Postfix(Character __state)
{
if ((Object)(object)__state != (Object)null)
{
Plugin.Cure(__state);
}
}
}
[HarmonyPatch(typeof(PetrifiedScout), "RPC_SpawnPetrifiedScout")]
internal static class ShatterPatch
{
private static void Postfix(PetrifiedScout __instance, int __0)
{
Character val = default(Character);
if (Character.GetCharacterWithPhotonID(__0, ref val) && val.IsLocal && Plugin.GivingUp.Contains(val))
{
((MonoBehaviour)Plugin.Instance).StartCoroutine(Plugin.Instance.Shatter(__instance));
}
}
}
[HarmonyPatch(typeof(CharacterVoiceHandler), "PushToTalk")]
internal static class TransmitPatch
{
private static void Postfix(CharacterVoiceHandler __instance, Character ___m_character, Recorder ___m_Recorder, ref bool ___m_currentlyTransmitting)
{
if (Plugin.Frozen(___m_character))
{
__instance.transmitting = false;
___m_currentlyTransmitting = false;
if ((Object)(object)___m_Recorder != (Object)null)
{
___m_Recorder.TransmitEnabled = false;
}
}
}
}
[HarmonyPatch(typeof(CharacterVoiceHandler), "OnAudioFilterRead")]
internal static class ReceivePatch
{
private static void Postfix(float[] __0)
{
if (Plugin.LocalFrozen && __0 != null)
{
Array.Clear(__0, 0, __0.Length);
}
}
}