Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Better DeadHead v1.0.4
DeadHeadWASD.dll
Decompiled 3 months agousing 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); } } } } }