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 Medic v1.0.1
Medic.dll
Decompiled 2 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 HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("headclef")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+e32f63f334dfa99c523518261eb9e98081747ea5")] [assembly: AssemblyProduct("Medic")] [assembly: AssemblyTitle("Medic")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.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 Medic { [BepInPlugin("headclef.Medic", "Medic", "1.0.1")] public class Medic : BaseUnityPlugin { private const string PluginGuid = "headclef.Medic"; private const string PluginName = "Medic"; private const string PluginVersion = "1.0.1"; internal static ConfigEntry<KeyboardShortcut> ReviveKey; internal static ConfigEntry<float> ReviveRange; internal static ConfigEntry<float> ReviveCooldown; internal static ConfigEntry<int> ReviveHealth; internal static ConfigEntry<bool> SelfReviveEnabled; internal static ConfigEntry<float> SelfReviveCooldown; internal static ConfigEntry<int> 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0054: 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_0018: 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_0064: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown ReviveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Revive", "Revive Key", new KeyboardShortcut((KeyCode)114, Array.Empty<KeyCode>()), "Key to press to revive a nearby dead player."); ReviveRange = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "Revive Range", 3f, new ConfigDescription("Maximum distance to a dead player to revive them.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), Array.Empty<object>())); ReviveCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Revive", "Revive Cooldown", 5f, new ConfigDescription("Cooldown in seconds between revive attempts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); ReviveHealth = ((BaseUnityPlugin)this).Config.Bind<int>("Revive", "Revive Health", 100, new ConfigDescription("Health the revived player starts with.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>())); SelfReviveEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Self Revive", "Enabled", true, "Allow self-reviving when you are dead by pressing the revive key."); SelfReviveCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Self Revive", "Self Revive Cooldown", 10f, new ConfigDescription("Cooldown in seconds between self-revive attempts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>())); SelfReviveHealth = ((BaseUnityPlugin)this).Config.Bind<int>("Self Revive", "Self Revive Health", 50, new ConfigDescription("Health you start with after self-reviving.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>())); } } } namespace Medic.Patches { [HarmonyPatch] internal static class RevivePatch { private static float _lastReviveTime; private static float _lastSelfReviveTime; [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] [HarmonyPrefix] private static bool ReviveRPC_Prefix(PlayerAvatar __instance, bool _revivedByTruck, PhotonMessageInfo _info) { //IL_0014: 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_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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) //IL_00e1: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_0316: 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_02cd: 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() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) try { if (!Medic.SelfReviveEnabled.Value) { return; } KeyboardShortcut value = Medic.ReviveKey.Value; if (!((KeyboardShortcut)(ref value)).IsDown()) { return; } PlayerAvatar val = PlayerController.instance?.playerAvatarScript; if (!((Object)(object)val == (Object)null) && val.deadSet) { float value2 = Medic.SelfReviveCooldown.Value; if (Time.time - _lastSelfReviveTime < value2) { Medic.Logger.LogDebug((object)$"Self-revive on cooldown ({value2 - (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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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) try { if ((Object)(object)__instance != (Object)(object)PlayerController.instance) { return; } KeyboardShortcut value = Medic.ReviveKey.Value; if (!((KeyboardShortcut)(ref value)).IsDown()) { return; } float value2 = Medic.ReviveCooldown.Value; if (Time.time - _lastReviveTime < value2) { Medic.Logger.LogDebug((object)$"Revive on cooldown ({value2 - (Time.time - _lastReviveTime):F1}s remaining)"); return; } PlayerAvatar playerAvatarScript = __instance.playerAvatarScript; if ((Object)(object)playerAvatarScript == (Object)null || playerAvatarScript.deadSet) { return; } float value3 = Medic.ReviveRange.Value; Vector3 position = ((Component)__instance).transform.position; PlayerAvatar val = null; float num = float.MaxValue; List<PlayerAvatar> 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 <= value3 && 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)); } } } }