using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DeadHeadWASD")]
[assembly: AssemblyTitle("DeadHeadWASD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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 Empress.DeadHeadDrive
{
[BepInPlugin("Empress.DeadHeadDrive", "DeadHeadDrive", "1.1.2")]
public class DeadHeadDrivePlugin : BaseUnityPlugin, IOnEventCallback, IConnectionCallbacks, IInRoomCallbacks
{
internal struct InputState
{
public Vector2 Dir;
public float Time;
}
public const string PluginGuid = "Empress.DeadHeadDrive";
public const string PluginName = "DeadHeadDrive";
public const string PluginVersion = "1.1.2";
internal const byte EventCode = 177;
internal static ConfigEntry<bool> EnableWASD = null;
internal static ConfigEntry<float> Acceleration = null;
internal static ConfigEntry<float> MaxSpeed = null;
internal static ConfigEntry<float> EnergyDrainMultiplier = null;
internal static ConfigEntry<float> ExtraDrainWhileMoving = null;
private static readonly Dictionary<int, InputState> Inputs = new Dictionary<int, InputState>();
internal static DeadHeadDrivePlugin Instance { get; private set; } = null;
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
internal Harmony? Harmony { get; set; }
private void Awake()
{
//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_00ec: Expected O, but got Unknown
Instance = this;
((Component)this).gameObject.transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
EnableWASD = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "EnableWASD", true, "Allow WASD movement for the spectated death head.");
Acceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "Acceleration", 20f, "Acceleration (m/s^2) applied while holding WASD. Uses ForceMode.Acceleration.");
MaxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "MaxSpeed", 7.5f, "Horizontal speed cap for the head when using WASD.");
EnergyDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Energy", "EnergyDrainMultiplier", 0.5f, "Multiplier on head-energy drain (<1 slower, >1 faster).");
ExtraDrainWhileMoving = ((BaseUnityPlugin)this).Config.Bind<float>("Energy", "ExtraDrainWhileMoving", 0f, "Extra energy drained per second while moving with WASD.");
GameObject val = new GameObject("__DeadHeadDrive_Runtime")
{
hideFlags = (HideFlags)61
};
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<DeadHeadDriveRuntime>();
Patch();
Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} ready");
}
private void OnDestroy()
{
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
internal void Patch()
{
//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_0021: Expected O, but got Unknown
//IL_0026: Expected O, but got Unknown
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Harmony.PatchAll(Assembly.GetExecutingAssembly());
}
internal static void ClearInputs()
{
Inputs.Clear();
}
public void OnEvent(EventData photonEvent)
{
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
if (!DeadHeadDriveRuntime.RuntimeActive || !PhotonNetwork.IsMasterClient || photonEvent.Code != 177 || !(photonEvent.CustomData is object[] array) || array.Length < 3)
{
return;
}
int num = (int)array[0];
float num2 = (float)array[1];
float num3 = (float)array[2];
PhotonView val = PhotonView.Find(num);
if (!Object.op_Implicit((Object)(object)val))
{
return;
}
PlayerDeathHead component = ((Component)val).GetComponent<PlayerDeathHead>();
if (Object.op_Implicit((Object)(object)component))
{
PlayerAvatar playerAvatar = component.playerAvatar;
if (Object.op_Implicit((Object)(object)playerAvatar) && Object.op_Implicit((Object)(object)playerAvatar.photonView) && playerAvatar.photonView.OwnerActorNr == photonEvent.Sender)
{
Inputs[num] = new InputState
{
Dir = new Vector2(num2, num3),
Time = Time.time
};
}
}
}
public void OnConnected()
{
}
public void OnConnectedToMaster()
{
}
public void OnDisconnected(DisconnectCause cause)
{
DeadHeadDriveRuntime.FullDeactivate();
}
public void OnRegionListReceived(RegionHandler regionHandler)
{
}
public void OnCustomAuthenticationResponse(Dictionary<string, object> data)
{
}
public void OnCustomAuthenticationFailed(string debugMessage)
{
}
public void OnJoinedRoom()
{
DeadHeadDriveRuntime.TryActivate();
}
public void OnLeftRoom()
{
DeadHeadDriveRuntime.FullDeactivate();
}
public void OnPlayerEnteredRoom(Player newPlayer)
{
}
public void OnPlayerLeftRoom(Player otherPlayer)
{
}
public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
}
public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
{
}
public void OnMasterClientSwitched(Player newMasterClient)
{
}
internal static bool TryGetInput(PlayerDeathHead head, out Vector2 dir)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
dir = Vector2.zero;
if (!DeadHeadDriveRuntime.RuntimeActive)
{
return false;
}
PhotonView photonView = head.photonView;
if (!Object.op_Implicit((Object)(object)photonView))
{
return false;
}
if (!Inputs.TryGetValue(photonView.ViewID, out var value))
{
return false;
}
if (Time.time - value.Time > 0.25f)
{
return false;
}
dir = value.Dir;
return ((Vector2)(ref dir)).sqrMagnitude > 0.0001f;
}
}
internal sealed class DeadHeadDriveRuntime : MonoBehaviour
{
private static DeadHeadDriveRuntime? _inst;
private bool _wasActive;
internal static bool RuntimeActive { get; private set; }
private void Awake()
{
if (Object.op_Implicit((Object)(object)_inst) && (Object)(object)_inst != (Object)(object)this)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
_inst = this;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
SceneManager.activeSceneChanged += OnSceneChanged;
}
private void OnDestroy()
{
SceneManager.activeSceneChanged -= OnSceneChanged;
FullDeactivate();
}
private static void OnSceneChanged(Scene a, Scene b)
{
FullDeactivate();
}
private void OnDisable()
{
FullDeactivate();
}
private void Update()
{
try
{
if (!RuntimeReady())
{
if (_wasActive)
{
FullDeactivate();
}
}
else if (!_wasActive)
{
TryActivate();
}
}
catch
{
}
}
internal static bool RuntimeReady()
{
if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
{
return false;
}
if (SemiFunc.MenuLevel())
{
return false;
}
if (!Object.op_Implicit((Object)(object)LevelGenerator.Instance) || !LevelGenerator.Instance.Generated)
{
return false;
}
if (!Object.op_Implicit((Object)(object)PlayerAvatar.instance))
{
return false;
}
return true;
}
internal static void TryActivate()
{
DeadHeadDriveRuntime inst = _inst;
if (Object.op_Implicit((Object)(object)inst) && !inst._wasActive && RuntimeReady())
{
PhotonNetwork.AddCallbackTarget((object)DeadHeadDrivePlugin.Instance);
PhotonNetwork.AddCallbackTarget((object)DeadHeadDrivePlugin.Instance);
PhotonNetwork.AddCallbackTarget((object)DeadHeadDrivePlugin.Instance);
RuntimeActive = true;
inst._wasActive = true;
DeadHeadDrivePlugin.Logger.LogDebug((object)"[DeadHeadDrive] Runtime activated (in-room, level generated).");
}
}
internal static void FullDeactivate()
{
DeadHeadDriveRuntime inst = _inst;
if (!Object.op_Implicit((Object)(object)inst))
{
DeadHeadDrivePlugin.ClearInputs();
return;
}
if (!inst._wasActive && !RuntimeActive)
{
DeadHeadDrivePlugin.ClearInputs();
return;
}
RuntimeActive = false;
inst._wasActive = false;
PhotonNetwork.RemoveCallbackTarget((object)DeadHeadDrivePlugin.Instance);
PhotonNetwork.RemoveCallbackTarget((object)DeadHeadDrivePlugin.Instance);
PhotonNetwork.RemoveCallbackTarget((object)DeadHeadDrivePlugin.Instance);
DeadHeadDrivePlugin.ClearInputs();
DeadHeadDrivePlugin.Logger.LogDebug((object)"[DeadHeadDrive] Runtime deactivated (menu/lobby or scene change).");
}
}
[HarmonyPatch(typeof(SpectateCamera), "HeadEnergyLogic")]
public static class Patch_SpectateCamera_HeadEnergyLogic
{
private static FieldInfo? f_headEnergy;
private static void Prepare()
{
f_headEnergy = AccessTools.Field(typeof(SpectateCamera), "headEnergy");
}
private static void Prefix(SpectateCamera __instance, out float __state)
{
__state = GetEnergy(__instance);
}
private static void Postfix(SpectateCamera __instance, float __state)
{
if (DeadHeadDriveRuntime.RuntimeActive)
{
float energy = GetEnergy(__instance);
float num = Mathf.Max(0f, DeadHeadDrivePlugin.EnergyDrainMultiplier.Value);
if (energy < __state && num != 1f)
{
float num2 = __state - energy;
float num3 = num2 * num;
float num4 = num2 - num3;
SetEnergy(__instance, Mathf.Clamp01(energy + num4));
}
}
}
private static float GetEnergy(SpectateCamera inst)
{
if (f_headEnergy == null)
{
f_headEnergy = AccessTools.Field(typeof(SpectateCamera), "headEnergy");
}
return ((object)f_headEnergy == null) ? 0f : ((float)f_headEnergy.GetValue(inst));
}
private static void SetEnergy(SpectateCamera inst, float value)
{
if (f_headEnergy == null)
{
f_headEnergy = AccessTools.Field(typeof(SpectateCamera), "headEnergy");
}
f_headEnergy?.SetValue(inst, value);
}
}
[HarmonyPatch(typeof(PlayerDeathHead), "Update")]
public static class Patch_PlayerDeathHead_Update_SendInput
{
private static FieldInfo? f_spectated;
private static FieldInfo? f_overrideSpectated;
private static void Prepare()
{
f_spectated = AccessTools.Field(typeof(PlayerDeathHead), "spectated");
f_overrideSpectated = AccessTools.Field(typeof(PlayerDeathHead), "overrideSpectated");
}
private static void Postfix(PlayerDeathHead __instance)
{
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_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_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_020a: Unknown result type (might be due to invalid IL or missing references)
if (!DeadHeadDriveRuntime.RuntimeActive || !DeadHeadDrivePlugin.EnableWASD.Value || (Object)(object)__instance.playerAvatar == (Object)null || !__instance.playerAvatar.isLocal)
{
return;
}
object obj = f_spectated?.GetValue(__instance);
if (!(obj is bool) || !(bool)obj)
{
return;
}
obj = f_overrideSpectated?.GetValue(__instance);
bool flag = default(bool);
int num;
if (obj is bool)
{
flag = (bool)obj;
num = 1;
}
else
{
num = 0;
}
if (((uint)num & (flag ? 1u : 0u)) != 0)
{
return;
}
SpectateCamera instance = SpectateCamera.instance;
if ((Object)(object)instance != (Object)null)
{
FieldInfo fieldInfo = AccessTools.Field(typeof(SpectateCamera), "headEnergy");
if (fieldInfo != null && (float)fieldInfo.GetValue(instance) <= 0f)
{
return;
}
}
float num2 = SemiFunc.InputMovementX();
float num3 = SemiFunc.InputMovementY();
if (Mathf.Abs(num2) < 0.01f && Mathf.Abs(num3) < 0.01f)
{
Send(__instance, 0f, 0f);
return;
}
Transform transform = ((Component)__instance.playerAvatar.localCamera).transform;
Vector3 forward = transform.forward;
forward.y = 0f;
((Vector3)(ref forward)).Normalize();
Vector3 right = transform.right;
right.y = 0f;
((Vector3)(ref right)).Normalize();
Vector3 val = forward * num3 + right * num2;
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
Send(__instance, 0f, 0f);
return;
}
((Vector3)(ref val)).Normalize();
Send(__instance, val.x, val.z);
float num4 = Mathf.Max(0f, DeadHeadDrivePlugin.ExtraDrainWhileMoving.Value);
if (num4 > 0f && (Object)(object)instance != (Object)null)
{
FieldInfo fieldInfo2 = AccessTools.Field(typeof(SpectateCamera), "headEnergy");
if (fieldInfo2 != null)
{
float num5 = (float)fieldInfo2.GetValue(instance);
num5 = Mathf.Clamp01(num5 - num4 * Time.deltaTime);
fieldInfo2.SetValue(instance, num5);
}
}
}
private static void Send(PlayerDeathHead inst, float dx, float dz)
{
//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_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
if (DeadHeadDriveRuntime.RuntimeActive)
{
PhotonView photonView = inst.photonView;
if (Object.op_Implicit((Object)(object)photonView))
{
object[] array = new object[3] { photonView.ViewID, dx, dz };
RaiseEventOptions val = new RaiseEventOptions
{
Receivers = (ReceiverGroup)2
};
PhotonNetwork.RaiseEvent((byte)177, (object)array, val, SendOptions.SendUnreliable);
}
}
}
}
[HarmonyPatch(typeof(PlayerDeathHead), "FixedUpdate")]
public static class Patch_PlayerDeathHead_FixedUpdate_Apply
{
private static FieldInfo? f_spectated;
private static FieldInfo? f_overrideSpectated;
private static FieldInfo? f_physGrabObject;
private static FieldInfo? f_rb;
private static void Prepare()
{
f_spectated = AccessTools.Field(typeof(PlayerDeathHead), "spectated");
f_overrideSpectated = AccessTools.Field(typeof(PlayerDeathHead), "overrideSpectated");
f_physGrabObject = AccessTools.Field(typeof(PlayerDeathHead), "physGrabObject");
f_rb = AccessTools.Field(typeof(PhysGrabObject), "rb");
}
private static void Postfix(PlayerDeathHead __instance)
{
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
if (!DeadHeadDriveRuntime.RuntimeActive || !PhotonNetwork.IsMasterClient || !DeadHeadDrivePlugin.EnableWASD.Value)
{
return;
}
object obj = f_spectated?.GetValue(__instance);
if (!(obj is bool) || !(bool)obj)
{
return;
}
obj = f_overrideSpectated?.GetValue(__instance);
bool flag = default(bool);
int num;
if (obj is bool)
{
flag = (bool)obj;
num = 1;
}
else
{
num = 0;
}
if (((uint)num & (flag ? 1u : 0u)) != 0 || !DeadHeadDrivePlugin.TryGetInput(__instance, out var dir))
{
return;
}
object obj2 = f_physGrabObject?.GetValue(__instance);
if (obj2 == null)
{
return;
}
object? obj3 = f_rb?.GetValue(obj2);
Rigidbody val = (Rigidbody)((obj3 is Rigidbody) ? obj3 : null);
if (Object.op_Implicit((Object)(object)val))
{
float num2 = Mathf.Max(0f, DeadHeadDrivePlugin.Acceleration.Value);
val.AddForce(new Vector3(dir.x, 0f, dir.y) * num2, (ForceMode)5);
float num3 = Mathf.Max(0f, DeadHeadDrivePlugin.MaxSpeed.Value);
Vector3 velocity = val.velocity;
Vector3 val2 = default(Vector3);
((Vector3)(ref val2))..ctor(velocity.x, 0f, velocity.z);
if (((Vector3)(ref val2)).magnitude > num3)
{
Vector3 val3 = ((Vector3)(ref val2)).normalized * num3;
val.velocity = new Vector3(val3.x, velocity.y, val3.z);
}
}
}
}
}