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 HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [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: AssemblyCompany("headclef")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.2.0")] [assembly: AssemblyInformationalVersion("1.1.2+52a031dd202614e6df7ec9b9cec947e643daca6d")] [assembly: AssemblyProduct("Medic")] [assembly: AssemblyTitle("Medic")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.2.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 Medic { [BepInPlugin("headclef.Medic", "Medic", "1.1.2")] public class Medic : BaseUnityPlugin { private const string PluginGuid = "headclef.Medic"; private const string PluginName = "Medic"; private const string PluginVersion = "1.1.2"; internal static ConfigEntry ReviveKey; internal static ConfigEntry ReviveRange; internal static ConfigEntry ReviveCooldown; internal static ConfigEntry ReviveHealth; internal static ConfigEntry SelfReviveEnabled; internal static ConfigEntry SelfReviveCooldown; internal static ConfigEntry SelfReviveHealth; internal static Medic Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { //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) //IL_004a: Expected O, but got Unknown //IL_004f: Expected O, but got Unknown Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; BindConfiguration(); if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void OnDestroy() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void BindConfiguration() { //IL_0017: 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_0063: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown ReviveKey = ((BaseUnityPlugin)this).Config.Bind("Revive", "Revive Key", new KeyboardShortcut((KeyCode)114, Array.Empty()), "Key to press to revive a nearby dead player."); ReviveRange = ((BaseUnityPlugin)this).Config.Bind("Revive", "Revive Range", 3f, new ConfigDescription("Maximum distance to a dead player to revive them.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 15f), Array.Empty())); ReviveCooldown = ((BaseUnityPlugin)this).Config.Bind("Revive", "Revive Cooldown", 5f, new ConfigDescription("Cooldown in seconds between revive attempts.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 60f), Array.Empty())); ReviveHealth = ((BaseUnityPlugin)this).Config.Bind("Revive", "Revive Health", 100, new ConfigDescription("Health the revived player starts with.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 200), Array.Empty())); SelfReviveEnabled = ((BaseUnityPlugin)this).Config.Bind("Self Revive", "Enabled", true, "Allow self-reviving when you are dead by pressing the revive key."); SelfReviveCooldown = ((BaseUnityPlugin)this).Config.Bind("Self Revive", "Self Revive Cooldown", 10f, new ConfigDescription("Cooldown in seconds between self-revive attempts.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 120f), Array.Empty())); SelfReviveHealth = ((BaseUnityPlugin)this).Config.Bind("Self Revive", "Self Revive Health", 50, new ConfigDescription("Health you start with after self-reviving.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 200), Array.Empty())); } } } namespace Medic.Patches { [HarmonyPatch] internal static class RevivePatch { private static float _lastReviveTime; private static float _lastSelfReviveTime; private static bool ReviveKeyPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Medic.ReviveKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!Input.GetKey(modifier)) { return false; } } return true; } [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] [HarmonyPrefix] private static bool ReviveRPC_Prefix(PlayerAvatar __instance, bool _revivedByTruck, PhotonMessageInfo _info) { //IL_0009: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_00a0: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.IsMultiplayer()) { return true; } if (_info.Sender == PhotonNetwork.MasterClient) { return true; } try { ManualLogSource logger = Medic.Logger; Player sender = _info.Sender; logger.LogDebug((object)("Bypassing MasterOnlyRPC for revive from " + (((sender != null) ? sender.NickName : null) ?? "unknown"))); if (!Object.op_Implicit((Object)(object)__instance.playerDeathHead)) { Medic.Logger.LogWarning((object)"Tried to revive without death head."); return false; } Vector3 val = __instance.playerDeathHead.physGrabObject.centerPoint - Vector3.up * 0.25f; Vector3 eulerAngles = ((Component)__instance.playerDeathHead.physGrabObject).transform.eulerAngles; if (SemiFunc.RunIsTutorial()) { val = Vector3.zero + Vector3.up * 2f - Vector3.right * 5f; ((Component)__instance.playerDeathHead).transform.position = val; } if (SemiFunc.IsMasterClientOrSingleplayer()) { __instance.tumble.physGrabObject.Teleport(val, ((Component)__instance).transform.rotation); } ((Component)__instance).transform.position = val; __instance.clientPositionCurrent = ((Component)__instance).transform.position; __instance.clientPosition = ((Component)__instance).transform.position; __instance.clientPhysRiding = false; ((Component)__instance).gameObject.SetActive(true); ((Component)__instance.playerAvatarVisuals).gameObject.SetActive(true); ((Component)__instance.playerAvatarVisuals).transform.position = ((Component)__instance).transform.position; __instance.playerAvatarVisuals.visualPosition = ((Component)__instance).transform.position; __instance.playerAvatarVisuals.Revive(); __instance.isDisabled = false; __instance.playerDeathHead.Reset(); __instance.playerDeathEffects.Reset(); __instance.playerReviveEffects.Trigger(); __instance.deadSet = false; __instance.deadTimer = __instance.deadTime; if (Object.op_Implicit((Object)(object)__instance.voiceChat)) { __instance.voiceChat.ToggleMixer(false, false); } __instance.playerAvatarCollision.SetCrouch(); __instance.playerHealth.SetMaterialGreen(); if (__instance.isLocal) { __instance.playerHealth.HealOther(1, true); __instance.playerTransform.position = ((Component)__instance).transform.position; ((Component)__instance.playerTransform.parent).gameObject.SetActive(true); if (!Object.op_Implicit((Object)(object)SpectateCamera.instance) || !SpectateCamera.instance.CheckState((State)2)) { CameraAim.Instance.SetPlayerAim(Quaternion.Euler(0f, eulerAngles.y, 0f), true); } ((Component)CameraPosition.instance).transform.position = val; CameraAim.Instance.OverrideNoSmooth(0.25f); GameDirector.instance.Revive(); SpectateCamera.instance.StopSpectate(); PlayerController.instance.Revive(eulerAngles); CameraGlitch.Instance.PlayLongHeal(); } __instance.RoomVolumeCheck.CheckSet(); } catch (Exception ex) { Medic.Logger.LogError((object)("ReviveRPC bypass exception: " + ex.Message)); } return false; } [HarmonyPatch(typeof(SpectateCamera), "Update")] [HarmonyPostfix] private static void SpectateCamera_Update_Postfix() { try { if (!Medic.SelfReviveEnabled.Value || !ReviveKeyPressed()) { return; } PlayerAvatar val = PlayerController.instance?.playerAvatarScript; if (!((Object)(object)val == (Object)null) && val.deadSet) { float value = Medic.SelfReviveCooldown.Value; if (Time.time - _lastSelfReviveTime < value) { Medic.Logger.LogDebug((object)$"Self-revive on cooldown ({value - (Time.time - _lastSelfReviveTime):F1}s remaining)"); return; } SelfRevive(val); _lastSelfReviveTime = Time.time; } } catch (Exception ex) { Medic.Logger.LogError((object)("Self-revive (spectate) exception: " + ex.Message)); } } [HarmonyPatch(typeof(PlayerController), "Update")] [HarmonyPostfix] private static void PlayerController_Update_Postfix(PlayerController __instance) { //IL_0095: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance != (Object)(object)PlayerController.instance || !ReviveKeyPressed()) { return; } float value = Medic.ReviveCooldown.Value; if (Time.time - _lastReviveTime < value) { Medic.Logger.LogDebug((object)$"Revive on cooldown ({value - (Time.time - _lastReviveTime):F1}s remaining)"); return; } PlayerAvatar playerAvatarScript = __instance.playerAvatarScript; if ((Object)(object)playerAvatarScript == (Object)null || playerAvatarScript.deadSet) { return; } float value2 = Medic.ReviveRange.Value; Vector3 position = ((Component)__instance).transform.position; PlayerAvatar val = null; float num = float.MaxValue; List list = SemiFunc.PlayerGetAll(); if (list == null) { return; } foreach (PlayerAvatar item in list) { if (!((Object)(object)item == (Object)(object)playerAvatarScript) && item.deadSet) { float num2 = Vector3.Distance(position, ((Component)item).transform.position); if (num2 <= value2 && num2 < num) { val = item; num = num2; } } } if ((Object)(object)val == (Object)null) { Medic.Logger.LogDebug((object)"No dead players in range to revive."); return; } RevivePlayer(val); _lastReviveTime = Time.time; } catch (Exception ex) { Medic.Logger.LogError((object)("Revive exception: " + ex.Message)); } } private static void RevivePlayer(PlayerAvatar deadPlayer) { try { int value = Medic.ReviveHealth.Value; string text = deadPlayer.playerName ?? "Unknown"; Medic.Logger.LogInfo((object)$"Reviving {text} with {value} HP..."); deadPlayer.Revive(false); if ((Object)(object)deadPlayer.playerHealth != (Object)null) { deadPlayer.playerHealth.health = value; deadPlayer.playerHealth.maxHealth = Mathf.Max(deadPlayer.playerHealth.maxHealth, value); if (SemiFunc.IsMultiplayer()) { deadPlayer.playerHealth.photonView.RPC("UpdateHealthRPC", (RpcTarget)1, new object[3] { value, deadPlayer.playerHealth.maxHealth, true }); } } Medic.Logger.LogInfo((object)("Revived " + text + " successfully!")); } catch (Exception ex) { Medic.Logger.LogError((object)("RevivePlayer exception: " + ex.Message)); } } private static void SelfRevive(PlayerAvatar localAvatar) { try { int value = Medic.SelfReviveHealth.Value; string text = localAvatar.playerName ?? "Unknown"; Medic.Logger.LogInfo((object)$"Self-reviving {text} with {value} HP..."); localAvatar.Revive(false); if ((Object)(object)localAvatar.playerHealth != (Object)null) { localAvatar.playerHealth.health = value; localAvatar.playerHealth.maxHealth = Mathf.Max(localAvatar.playerHealth.maxHealth, value); if (SemiFunc.IsMultiplayer()) { localAvatar.playerHealth.photonView.RPC("UpdateHealthRPC", (RpcTarget)1, new object[3] { value, localAvatar.playerHealth.maxHealth, true }); } } Medic.Logger.LogInfo((object)("Self-revived " + text + " successfully!")); } catch (Exception ex) { Medic.Logger.LogError((object)("SelfRevive exception: " + ex.Message)); } } } }