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 Defibrillator v1.0.0
Defibrillator.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalLib.Modules; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; 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: AssemblyCompany("Defibrillator")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Defibrillator")] [assembly: AssemblyTitle("Defibrillator")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 DefibMod { internal static class DefibFactory { private static readonly List<(Renderer renderer, Color color)> Parts = new List<(Renderer, Color)>(); private static bool _assetsApplied; internal static AudioClip ShockClip; private static readonly Color CaseRed = new Color(0.78f, 0.08f, 0.08f); private static readonly Color Dark = new Color(0.1f, 0.1f, 0.11f); private static readonly Color ScreenGreen = new Color(0.1f, 0.45f, 0.2f); private static readonly Color White = new Color(0.95f, 0.95f, 0.95f); private static readonly Color PaddleYellow = new Color(0.95f, 0.75f, 0.1f); public static Item Create() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: 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_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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) GameObject val = NetworkPrefabs.CreateNetworkPrefab("DefibrillatorItem"); val.layer = 6; val.tag = "PhysicsProp"; MeshRenderer mainObjectRenderer = Part(val, "Case", new Vector3(0f, -0.17f, 0f), new Vector3(0.4f, 0.26f, 0.16f), CaseRed); Part(val, "Handle", new Vector3(0f, -0.005f, 0f), new Vector3(0.18f, 0.025f, 0.04f), Dark); Part(val, "HandlePostL", new Vector3(-0.08f, -0.025f, 0f), new Vector3(0.025f, 0.045f, 0.03f), Dark); Part(val, "HandlePostR", new Vector3(0.08f, -0.025f, 0f), new Vector3(0.025f, 0.045f, 0.03f), Dark); Part(val, "Screen", new Vector3(0.08f, -0.13f, 0.081f), new Vector3(0.15f, 0.08f, 0.005f), ScreenGreen); Part(val, "CrossH", new Vector3(-0.1f, -0.13f, 0.081f), new Vector3(0.08f, 0.022f, 0.005f), White); Part(val, "CrossV", new Vector3(-0.1f, -0.13f, 0.081f), new Vector3(0.022f, 0.08f, 0.005f), White); Part(val, "PaddleL", new Vector3(-0.09f, -0.24f, 0.095f), new Vector3(0.1f, 0.06f, 0.03f), PaddleYellow); Part(val, "PaddleR", new Vector3(0.09f, -0.24f, 0.095f), new Vector3(0.1f, 0.06f, 0.03f), PaddleYellow); BoxCollider obj = val.AddComponent<BoxCollider>(); ((Collider)obj).isTrigger = true; obj.center = new Vector3(0f, -0.16f, 0.02f); obj.size = new Vector3(0.42f, 0.32f, 0.22f); GameObject val2 = new GameObject("ScanNode") { layer = 22 }; val2.transform.SetParent(val.transform, false); val2.transform.localPosition = new Vector3(0f, -0.15f, 0f); BoxCollider obj2 = val2.AddComponent<BoxCollider>(); ((Collider)obj2).isTrigger = true; obj2.size = Vector3.one * 0.5f; ScanNodeProperties obj3 = val2.AddComponent<ScanNodeProperties>(); obj3.headerText = "Defibrillator"; obj3.subText = "Shock a teammate's body to revive them"; obj3.nodeType = 0; obj3.minRange = 1; obj3.maxRange = 13; obj3.requiresLineOfSight = true; obj3.creatureScanID = -1; AudioSource val3 = val.AddComponent<AudioSource>(); val3.playOnAwake = false; val3.spatialBlend = 1f; val3.rolloffMode = (AudioRolloffMode)1; val3.maxDistance = 25f; Item val4 = ScriptableObject.CreateInstance<Item>(); ((Object)val4).name = "DefibrillatorItem"; val4.itemName = "Defibrillator"; val4.creditsWorth = Plugin.Price.Value; val4.weight = 1f + Mathf.Max(0f, Plugin.WeightLbs.Value) / 105f; val4.isScrap = false; val4.twoHanded = false; val4.twoHandedAnimation = false; val4.holdButtonUse = false; val4.requiresBattery = true; val4.batteryUsage = 600f; val4.itemIsTrigger = false; val4.canBeGrabbedBeforeGameStart = true; val4.isConductiveMetal = true; val4.itemSpawnsOnGround = true; val4.allowDroppingAheadOfPlayer = true; val4.grabAnim = ""; val4.verticalOffset = 0.3f; val4.restingRotation = Vector3.zero; val4.positionOffset = Plugin.ParseVec(Plugin.HoldPosition.Value, new Vector3(0f, 0.05f, 0f)); val4.rotationOffset = Plugin.ParseVec(Plugin.HoldRotation.Value, Vector3.zero); val4.toolTips = new string[1] { "Shock body : [LMB]" }; val4.spawnPositionTypes = new List<ItemGroup>(); val4.meshVariants = (Mesh[])(object)new Mesh[0]; val4.materialVariants = (Material[])(object)new Material[0]; val4.highestSalePercentage = 80; val4.spawnPrefab = val; DefibrillatorItem defibrillatorItem = val.AddComponent<DefibrillatorItem>(); ((GrabbableObject)defibrillatorItem).itemProperties = val4; ((GrabbableObject)defibrillatorItem).grabbable = true; ((GrabbableObject)defibrillatorItem).grabbableToEnemies = true; ((GrabbableObject)defibrillatorItem).mainObjectRenderer = mainObjectRenderer; defibrillatorItem.shockAudio = val3; return val4; } private static MeshRenderer Part(GameObject parent, string name, Vector3 pos, Vector3 size, Color color) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>()); ((Object)obj).name = name; obj.layer = 6; obj.transform.SetParent(parent.transform, false); obj.transform.localPosition = pos; obj.transform.localScale = size; MeshRenderer component = obj.GetComponent<MeshRenderer>(); Parts.Add(((Renderer)(object)component, color)); return component; } public static void ApplyVanillaAssets() { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (_assetsApplied || (Object)(object)StartOfRound.Instance == (Object)null) { return; } try { List<Item> vanilla = StartOfRound.Instance.allItemsList.itemsList; Material val = null; foreach (Item item3 in vanilla) { if (!((Object)(object)item3 == (Object)null) && !((Object)(object)item3.spawnPrefab == (Object)null) && !((Object)(object)item3 == (Object)(object)Plugin.DefibItem)) { MeshRenderer componentInChildren = item3.spawnPrefab.GetComponentInChildren<MeshRenderer>(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null && ((Renderer)componentInChildren).sharedMaterial.HasProperty("_BaseColor")) { val = ((Renderer)componentInChildren).sharedMaterial; break; } } } if ((Object)(object)val != (Object)null) { foreach (var part in Parts) { Renderer item = part.renderer; Color item2 = part.color; Material val2 = new Material(val) { name = "Defib_" + ((Object)item).name }; string[] array = new string[4] { "_BaseColorMap", "_NormalMap", "_MaskMap", "_EmissiveColorMap" }; foreach (string text in array) { if (val2.HasProperty(text)) { val2.SetTexture(text, (Texture)null); } } val2.DisableKeyword("_NORMALMAP"); val2.DisableKeyword("_MASKMAP"); val2.SetColor("_BaseColor", item2); if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0.1f); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", 0.45f); } item.sharedMaterial = val2; } } else { Plugin.Log.LogWarning((object)"Couldn't find a vanilla material to copy; the defibrillator may look pink."); } Item val3 = new string[4] { "Zap gun", "Pro-flashlight", "Flashlight", "Walkie-talkie" }.Select((string n) => ((IEnumerable<Item>)vanilla).FirstOrDefault((Func<Item, bool>)((Item val4) => (Object)(object)val4 != (Object)null && val4.itemName == n))).FirstOrDefault<Item>((Func<Item, bool>)((Item val4) => (Object)(object)val4 != (Object)null)); if ((Object)(object)val3 != (Object)null) { Plugin.DefibItem.itemIcon = val3.itemIcon; Plugin.DefibItem.grabSFX = val3.grabSFX; Plugin.DefibItem.dropSFX = val3.dropSFX; Plugin.DefibItem.pocketSFX = val3.pocketSFX; } _assetsApplied = true; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to apply vanilla assets: " + ex)); } } public static AudioClip GetShockClip() { if ((Object)(object)ShockClip != (Object)null) { return ShockClip; } try { ItemCharger val = Object.FindObjectOfType<ItemCharger>(); if ((Object)(object)val != (Object)null) { object value = Traverse.Create((object)val).Field("zapAudio").GetValue(); AudioSource val2 = (AudioSource)((value is AudioSource) ? value : null); if (val2 != null && (Object)(object)val2.clip != (Object)null) { return ShockClip = val2.clip; } } ShockClip = ((IEnumerable<AudioClip>)Resources.FindObjectsOfTypeAll<AudioClip>()).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => ((Object)c).name.IndexOf("zap", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)c).name.IndexOf("shock", StringComparison.OrdinalIgnoreCase) >= 0)); } catch (Exception ex) { Plugin.Log.LogDebug((object)("No shock clip: " + ex.Message)); } return ShockClip; } } public class DefibrillatorItem : GrabbableObject { public AudioSource shockAudio; private bool _charging; private float _nextUseTime; private static float ShockCost => 1f / (float)Mathf.Max(1, Plugin.ShocksPerBattery.Value); public override void ItemActivate(bool used, bool buttonDown = true) { ((GrabbableObject)this).ItemActivate(used, buttonDown); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (buttonDown && !((Object)(object)base.playerHeldBy == (Object)null) && !((Object)(object)base.playerHeldBy != (Object)(object)localPlayerController) && !_charging && !(Time.time < _nextUseTime)) { PlayerControllerB val = ReviveNetwork.FindRevivableBody(localPlayerController, Plugin.Range.Value); if ((Object)(object)val == (Object)null) { _nextUseTime = Time.time + 1f; HUDManager.Instance.DisplayTip("Defibrillator", "No body in range. Stand right next to a dead teammate.", false, false, "LC_Tip1"); } else if (base.insertedBattery == null || base.insertedBattery.charge + 0.001f < ShockCost) { _nextUseTime = Time.time + 1f; HUDManager.Instance.DisplayTip("Defibrillator", "Battery too low. Charge it at the ship.", true, false, "LC_Tip1"); } else { ((MonoBehaviour)this).StartCoroutine(ChargeAndShock(val)); } } } private IEnumerator ChargeAndShock(PlayerControllerB target) { _charging = true; PlayerControllerB holder = base.playerHeldBy; yield return (object)new WaitForSeconds(Mathf.Max(0f, Plugin.ChargeUpTime.Value)); _charging = false; _nextUseTime = Time.time + 1f; if ((Object)(object)base.playerHeldBy == (Object)null || (Object)(object)base.playerHeldBy != (Object)(object)holder || base.isPocketed || holder.isPlayerDead) { yield break; } if (!ReviveNetwork.IsRevivable(target, holder, Plugin.Range.Value + 0.75f)) { HUDManager.Instance.DisplayTip("Defibrillator", "Lost contact with the body.", false, false, "LC_Tip1"); yield break; } base.insertedBattery.charge = Mathf.Max(0f, base.insertedBattery.charge - ShockCost); if (base.insertedBattery.charge <= 0.001f) { base.insertedBattery.empty = true; } ((GrabbableObject)this).SyncBatteryServerRpc((int)(base.insertedBattery.charge * 100f)); ReviveNetwork.RequestRevive(target, holder); } public void PlayShockEffects() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) AudioClip shockClip = DefibFactory.GetShockClip(); if ((Object)(object)shockClip != (Object)null && (Object)(object)shockAudio != (Object)null) { shockAudio.PlayOneShot(shockClip, 1f); } if ((Object)(object)RoundManager.Instance != (Object)null) { RoundManager.Instance.PlayAudibleNoise(((Component)this).transform.position, 15f, 0.8f, 0, base.isInShipRoom, 0); } } } [BepInPlugin("markj.defibrillator", "Defibrillator", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "markj.defibrillator"; public const string Name = "Defibrillator"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static Item DefibItem; internal static ConfigEntry<int> Price; internal static ConfigEntry<int> ShocksPerBattery; internal static ConfigEntry<int> ReviveHealth; internal static ConfigEntry<float> Range; internal static ConfigEntry<float> ChargeUpTime; internal static ConfigEntry<float> WeightLbs; internal static ConfigEntry<string> HoldPosition; internal static ConfigEntry<string> HoldRotation; private void Awake() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Price = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Price", 250, "Store price in credits. Everyone in the lobby should use the same value."); ShocksPerBattery = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ShocksPerBattery", 3, "Revives per full battery. Recharge it at the ship's charging station."); ReviveHealth = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ReviveHealth", 50, new ConfigDescription("Health a revived player comes back with.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 2.5f, "How close (in metres) you need to be to a body."); ChargeUpTime = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChargeUpTime", 1.5f, "Seconds between pressing use and the shock. Stay near the body while it charges."); WeightLbs = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WeightLbs", 12f, "Item weight in pounds."); HoldPosition = ((BaseUnityPlugin)this).Config.Bind<string>("Visuals", "HoldPosition", "0,0.05,0", "x,y,z offset of the model in your hand. Tweak if it looks off."); HoldRotation = ((BaseUnityPlugin)this).Config.Bind<string>("Visuals", "HoldRotation", "0,0,0", "x,y,z rotation of the model in your hand. Tweak if it looks off."); DefibItem = DefibFactory.Create(); Items.RegisterShopItem(DefibItem, Price.Value); new Harmony("markj.defibrillator").PatchAll(typeof(Patches)); Log.LogInfo((object)"Defibrillator 1.0.0 loaded."); } internal static Vector3 ParseVec(string s, Vector3 fallback) { //IL_005b: 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) string[] array = s.Split(','); if (array.Length == 3 && float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return new Vector3(result, result2, result3); } return fallback; } } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void StartOfRoundAwake() { DefibFactory.ApplyVanillaAssets(); } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void StartOfRoundStart() { ReviveNetwork.Register(); } } internal static class ReviveNetwork { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestRevive; public static HandleNamedMessageDelegate <1>__OnDoRevive; } private const string RequestMsg = "Defibrillator_RequestRevive"; private const string ReviveMsg = "Defibrillator_DoRevive"; public static void Register() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val != null) { val.UnregisterNamedMessageHandler("Defibrillator_RequestRevive"); val.UnregisterNamedMessageHandler("Defibrillator_DoRevive"); object obj = <>O.<0>__OnRequestRevive; if (obj == null) { HandleNamedMessageDelegate val2 = OnRequestRevive; <>O.<0>__OnRequestRevive = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Defibrillator_RequestRevive", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnDoRevive; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnDoRevive; <>O.<1>__OnDoRevive = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Defibrillator_DoRevive", (HandleNamedMessageDelegate)obj2); } } public static PlayerControllerB FindRevivableBody(PlayerControllerB reviver, float range) { //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_0044: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB result = null; float num = float.MaxValue; PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (IsRevivable(val, reviver, range)) { float num2 = Vector3.Distance(ClosestBodyPoint(val.deadBody, ((Component)reviver).transform.position), ((Component)reviver).transform.position); if (num2 < num) { num = num2; result = val; } } } return result; } public static bool IsRevivable(PlayerControllerB p, PlayerControllerB reviver, float range) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) if ((Object)(object)p == (Object)null || (Object)(object)reviver == (Object)null || (Object)(object)p == (Object)(object)reviver) { return false; } if (!p.isPlayerDead || p.disconnectedMidGame) { return false; } DeadBodyInfo deadBody = p.deadBody; if ((Object)(object)deadBody == (Object)null || deadBody.deactivated || !((Component)deadBody).gameObject.activeInHierarchy) { return false; } if ((Object)(object)deadBody.grabBodyObject != (Object)null && deadBody.grabBodyObject.isHeld) { return false; } return Vector3.Distance(ClosestBodyPoint(deadBody, ((Component)reviver).transform.position), ((Component)reviver).transform.position) <= range; } private static Vector3 ClosestBodyPoint(DeadBodyInfo body, Vector3 from) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0099: Unknown result type (might be due to invalid IL or missing references) if (body.bodyParts == null || body.bodyParts.Length == 0) { return ((Component)body).transform.position; } return (from b in body.bodyParts where (Object)(object)b != (Object)null select ((Component)b).transform.position).OrderBy(delegate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_000c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = pos - from; return ((Vector3)(ref val)).sqrMagnitude; }).DefaultIfEmpty(((Component)body).transform.position).First(); } public unsafe static void RequestRevive(PlayerControllerB target, PlayerControllerB reviver) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) NetworkManager singleton = NetworkManager.Singleton; if (singleton.IsServer) { ServerHandleRequest((int)target.playerClientId, (int)reviver.playerClientId, singleton.LocalClientId); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { int num = (int)target.playerClientId; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); num = (int)reviver.playerClientId; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Defibrillator_RequestRevive", 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnRequestRevive(ulong sender, FastBufferReader r) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsServer) { int targetId = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref targetId, default(ForPrimitives)); int reviverId = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref reviverId, default(ForPrimitives)); ServerHandleRequest(targetId, reviverId, sender); } } private unsafe static void ServerHandleRequest(int targetId, int reviverId, ulong sender) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: 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) PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; if (targetId < 0 || targetId >= allPlayerScripts.Length || reviverId < 0 || reviverId >= allPlayerScripts.Length) { return; } PlayerControllerB val = allPlayerScripts[targetId]; PlayerControllerB val2 = allPlayerScripts[reviverId]; if (val2.actualClientId != sender || val2.isPlayerDead || !val2.isPlayerControlled || !IsRevivable(val, val2, Plugin.Range.Value + 3f)) { return; } Vector3 pos = ClosestBodyPoint(val.deadBody, ((Component)val2).transform.position) + Vector3.up * 0.5f; int health = Mathf.Clamp(Plugin.ReviveHealth.Value, 1, 100); GrabbableObject grabBodyObject = val.deadBody.grabBodyObject; List<ulong> list = NetworkManager.Singleton.ConnectedClientsIds.Where((ulong id) => id != 0).ToList(); if (list.Count > 0) { FastBufferWriter val3 = default(FastBufferWriter); ((FastBufferWriter)(ref val3))..ctor(32, (Allocator)2, -1); try { ((FastBufferWriter)(ref val3)).WriteValueSafe<int>(ref targetId, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe<int>(ref reviverId, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe<float>(ref pos.x, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe<float>(ref pos.y, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe<float>(ref pos.z, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe<int>(ref health, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Defibrillator_DoRevive", (IReadOnlyList<ulong>)list, val3, (NetworkDelivery)2); } finally { ((IDisposable)(*(FastBufferWriter*)(&val3))/*cast due to .constrained prefix*/).Dispose(); } } DoRevive(val, val2, pos, health); if ((Object)(object)grabBodyObject != (Object)null && (Object)(object)((NetworkBehaviour)grabBodyObject).NetworkObject != (Object)null && ((NetworkBehaviour)grabBodyObject).NetworkObject.IsSpawned) { ((NetworkBehaviour)grabBodyObject).NetworkObject.Despawn(true); } } private static void OnDoRevive(ulong sender, FastBufferReader r) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) if (sender == 0L) { int num = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num3, default(ForPrimitives)); float num4 = default(float); ((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num4, default(ForPrimitives)); float num5 = default(float); ((FastBufferReader)(ref r)).ReadValueSafe<float>(ref num5, default(ForPrimitives)); int health = default(int); ((FastBufferReader)(ref r)).ReadValueSafe<int>(ref health, default(ForPrimitives)); PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; if (num >= 0 && num < allPlayerScripts.Length && num2 >= 0 && num2 < allPlayerScripts.Length) { DoRevive(allPlayerScripts[num], allPlayerScripts[num2], new Vector3(num3, num4, num5), health); } } } private static void DoRevive(PlayerControllerB p, PlayerControllerB reviver, Vector3 pos, int health) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || !p.isPlayerDead) { return; } StartOfRound instance = StartOfRound.Instance; bool flag = (Object)(object)p == (Object)(object)GameNetworkManager.Instance.localPlayerController; int num = (int)p.playerClientId; Plugin.Log.LogInfo((object)(reviver?.playerUsername + " revived " + p.playerUsername)); try { if ((Object)(object)p.deadBody != (Object)null) { try { p.deadBody.DeactivateBody(false); } catch (Exception ex) { Plugin.Log.LogWarning((object)ex.Message); } p.deadBody = null; } R.Call(p, "ResetPlayerBloodObjects", true); p.isClimbingLadder = false; p.clampLooking = false; p.disableMoveInput = false; p.disableLookInput = false; R.Set(p, "disableInteract", false); R.Set(p, "inVehicleAnimation", false); p.ResetZAndXRotation(); ((Collider)p.thisController).enabled = true; p.health = health; p.hasBeenCriticallyInjured = false; p.isPlayerDead = false; p.isPlayerControlled = true; if ((Object)(object)reviver != (Object)null) { p.isInElevator = reviver.isInElevator; p.isInHangarShipRoom = reviver.isInHangarShipRoom; p.isInsideFactory = reviver.isInsideFactory; } R.Set(p, "parentedToElevatorLastFrame", false); R.Set(p, "overrideGameOverSpectatePivot", null); R.Call(instance, "SetPlayerObjectExtrapolate", false); p.TeleportPlayer(pos, false, 0f, false, true); R.Set(p, "setPositionOfDeadPlayer", false); p.DisablePlayerModel(((Component)p).gameObject, true, true); if (flag) { ((Renderer)p.thisPlayerModelArms).enabled = true; } if ((Object)(object)p.helmetLight != (Object)null) { ((Behaviour)p.helmetLight).enabled = false; } p.Crouch(false); p.criticallyInjured = health < 20; p.bleedingHeavily = false; if ((Object)(object)p.playerBodyAnimator != (Object)null) { p.playerBodyAnimator.SetBool("Limp", p.criticallyInjured); } p.activatingItem = false; p.twoHanded = false; p.inShockingMinigame = false; p.inSpecialInteractAnimation = false; p.inAnimationWithEnemy = null; p.holdingWalkieTalkie = false; p.speakingToWalkieTalkie = false; R.Set(p, "freeRotationInInteractAnimation", false); R.Set(p, "disableSyncInAnimation", false); R.Set(p, "isSinking", false); R.Set(p, "isUnderwater", false); R.Set(p, "sinkingValue", 0f); R.Set(p, "externalForceAutoFade", Vector3.zero); R.Set(p, "causeOfDeath", (object)(CauseOfDeath)0); if ((Object)(object)p.statusEffectAudio != (Object)null) { p.statusEffectAudio.Stop(); } R.Call(p, "DisableJetpackControlsLocally"); if ((Object)(object)p.mapRadarDotAnimator != (Object)null) { p.mapRadarDotAnimator.SetBool("dead", false); } p.voiceMuffledByEnemy = false; if (flag) { ReviveLocalView(p, health); } if ((Object)(object)SoundManager.Instance != (Object)null && num < SoundManager.Instance.playerVoicePitchTargets.Length) { SoundManager.Instance.playerVoicePitchTargets[num] = 1f; SoundManager.Instance.SetPlayerPitch(1f, num); } instance.livingPlayers = Mathf.Min(instance.livingPlayers + 1, instance.connectedPlayersAmount + 1); instance.allPlayersDead = false; instance.UpdatePlayerVoiceEffects(); } catch (Exception ex2) { Plugin.Log.LogError((object)("Revive failed partway: " + ex2)); } if ((Object)(object)reviver != (Object)null && reviver.currentlyHeldObjectServer is DefibrillatorItem defibrillatorItem) { defibrillatorItem.PlayShockEffects(); } } private static void ReviveLocalView(PlayerControllerB p, int health) { HUDManager instance = HUDManager.Instance; StartOfRound instance2 = StartOfRound.Instance; R.Set(p, "hasBegunSpectating", false); p.spectatedPlayerScript = null; R.Set(p, "hinderedMultiplier", 1f); R.Set(p, "isMovementHindered", 0); R.Set(p, "sourcesCausingSinking", 0); R.Call(instance, "RemoveSpectateUI"); object obj = R.Get(instance, "gameOverAnimator"); object obj2 = ((obj is Animator) ? obj : null); if (obj2 != null) { ((Animator)obj2).SetTrigger("revive"); } object obj3 = R.Get(instance, "gasHelmetAnimator"); object obj4 = ((obj3 is Animator) ? obj3 : null); if (obj4 != null) { ((Animator)obj4).SetBool("gasEmitting", false); } object obj5 = R.Get(instance, "audioListenerLowPass"); Behaviour val = (Behaviour)((obj5 is Behaviour) ? obj5 : null); if (val != null) { val.enabled = false; } R.Call(instance2, "SetSpectateCameraToGameOverMode", false, p); instance2.SwitchCamera(p.gameplayCamera); R.Call(p, "ChangeAudioListenerToObject", ((Component)p.gameplayCamera).gameObject); R.Call(instance, "HideHUD", false); instance.UpdateHealthUI(health, false); R.Set(SoundManager.Instance, "earsRingingTimer", 0f); instance.DisplayTip("Revived", "A teammate shocked you back to life!", false, false, "LC_Tip1"); } } internal static class R { private static readonly HashSet<string> Warned = new HashSet<string>(); private static void Warn(string what) { if (Warned.Add(what)) { Plugin.Log.LogWarning((object)("Game member not found (game version difference?): " + what)); } } public static object Get(object obj, string name) { if (obj == null) { return null; } FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name); if (fieldInfo != null) { return fieldInfo.GetValue(obj); } PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), name); if (propertyInfo != null && propertyInfo.CanRead) { return propertyInfo.GetValue(obj); } Warn(obj.GetType().Name + "." + name); return null; } public static void Set(object obj, string name, object value) { if (obj == null) { return; } try { FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name); if (fieldInfo != null) { fieldInfo.SetValue(obj, value); return; } PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), name); if (propertyInfo != null && propertyInfo.CanWrite) { propertyInfo.SetValue(obj, value); } else { Warn(obj.GetType().Name + "." + name); } } catch (Exception ex) { Warn(obj.GetType().Name + "." + name + " (" + ex.Message + ")"); } } public static void Call(object obj, string name, params object[] args) { if (obj == null) { return; } try { List<MethodInfo> declaredMethods = AccessTools.GetDeclaredMethods(obj.GetType()); IEnumerable<MethodInfo> second; if (!(obj.GetType().BaseType != null)) { second = Enumerable.Empty<MethodInfo>(); } else { IEnumerable<MethodInfo> declaredMethods2 = AccessTools.GetDeclaredMethods(obj.GetType().BaseType); second = declaredMethods2; } MethodInfo methodInfo = declaredMethods.Concat(second).FirstOrDefault((MethodInfo m) => m.Name == name && m.GetParameters().Length >= args.Length && m.GetParameters().Skip(args.Length).All((ParameterInfo pi) => pi.HasDefaultValue)); if (methodInfo == null) { Warn(obj.GetType().Name + "." + name + "()"); return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int num = 0; num < parameters.Length; num++) { array[num] = ((num < args.Length) ? args[num] : parameters[num].DefaultValue); } methodInfo.Invoke(obj, array); } catch (Exception ex) { Plugin.Log.LogWarning((object)(obj.GetType().Name + "." + name + "() threw: " + (ex.InnerException?.Message ?? ex.Message))); } } } }