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 LC ReviveDeadPlayers v1.0.0
LC_ReviveDeadPlayers.dll
Decompiled 2 years 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 GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; 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("LC_ReviveDeadPlayers")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("A template for Lethal Company")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LC_ReviveDeadPlayers")] [assembly: AssemblyTitle("LC_ReviveDeadPlayers")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LC_ReviveDeadPlayers { [BepInPlugin("LC_ReviveDeadPlayers", "LC_ReviveDeadPlayers", "1.0.0")] public class Plugin : BaseUnityPlugin { public static ManualLogSource LOGGER; public static Plugin Instance { get; private set; } public Harmony Harmony { get; private set; } public ConfigEntry<int> MaxRevives { get; private set; } public ConfigEntry<float> ReviveTimeSeconds { get; private set; } public ConfigEntry<bool> ReviveOnBodyCollected { get; private set; } public ConfigEntry<bool> ReviveAfterDeathOnTimer { get; private set; } private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Instance = this; LOGGER = ((BaseUnityPlugin)this).Logger; Harmony = new Harmony("LC_ReviveDeadPlayers"); MaxRevives = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Max Revives", 3, "The number of times a player can be revived in a single match."); ReviveTimeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Revive Timer Seconds", 30f, "The number of times a player can be revived in a single match."); ReviveOnBodyCollected = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Revive on body collected", true, "If true the player is revived when their body is collected."); ReviveAfterDeathOnTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Revive on timer after death", true, "If true the player is revived based on a timer after they die."); if (ReviveOnBodyCollected.Value) { RevivePlayerSystem.AddReviveCondition(new ReviveOnBodyCollected()); } if (ReviveAfterDeathOnTimer.Value) { RevivePlayerSystem.AddReviveCondition(new ReviveOnTimer()); } try { Harmony.PatchAll(typeof(RevivePlayerSystem)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch Revive System; '" + ex.Message + "'\n" + ex.StackTrace)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LC_ReviveDeadPlayers is loaded!"); } } internal interface IReviveCondition { void Reset(); bool ShouldRevivePlayer(RevivePlayerMetric metric); Vector3 GetRevivePosition(RevivePlayerMetric _) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return StartOfRound.Instance.middleOfShipNode.position; } } internal class RevivePlayerMetric { public PlayerControllerB Player { get; } public int RevivesLeft { get; set; } public int ResetRevives { get; set; } public RevivePlayerMetric(PlayerControllerB player, int revives) { Player = player; RevivesLeft = revives; ResetRevives = revives; } public void Reset() { RevivesLeft = ResetRevives; } public bool CanRevive() { return RevivesLeft > 0; } public int GetPlayerIndex() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { throw new NullReferenceException("Start of round is null"); } for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if (val.actualClientId == Player.actualClientId && (val.actualClientId != 0L || val.isHostPlayerObject)) { return i; } } throw new ArgumentException("Unknown Player Index: " + (object)Player); } public void Revive(Vector3 revive_pos) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (!CanRevive()) { return; } int revivesLeft = RevivesLeft - 1; RevivesLeft = revivesLeft; StartOfRound instance = StartOfRound.Instance; int playerIndex = GetPlayerIndex(); instance.livingPlayers++; Player.isClimbingLadder = false; Player.ResetZAndXRotation(); ((Collider)Player.thisController).enabled = true; Player.health = 100; Player.disableLookInput = false; Player.isPlayerDead = false; Player.isPlayerControlled = true; Player.isInElevator = true; Player.isInHangarShipRoom = true; Player.isInsideFactory = false; Player.wasInElevatorLastFrame = false; instance.SetPlayerObjectExtrapolate(false); Player.TeleportPlayer(revive_pos, false, 0f, false, true); Player.setPositionOfDeadPlayer = false; Player.DisablePlayerModel(instance.allPlayerObjects[GetPlayerIndex()], true, true); ((Behaviour)Player.helmetLight).enabled = false; Player.Crouch(false); Player.criticallyInjured = false; if ((Object)(object)Player.playerBodyAnimator != (Object)null) { Player.playerBodyAnimator.SetBool("Limp", false); } Player.bleedingHeavily = false; Player.activatingItem = false; Player.twoHanded = false; Player.inSpecialInteractAnimation = false; Player.disableSyncInAnimation = false; Player.inAnimationWithEnemy = null; Player.holdingWalkieTalkie = false; Player.speakingToWalkieTalkie = false; Player.isSinking = false; Player.isUnderwater = false; Player.sinkingValue = 0f; Player.statusEffectAudio.Stop(); Player.DisableJetpackControlsLocally(); Player.health = 100; Player.mapRadarDotAnimator.SetBool("dead", false); if (((NetworkBehaviour)Player).IsOwner) { HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false); Player.hasBegunSpectating = false; HUDManager.Instance.RemoveSpectateUI(); HUDManager.Instance.gameOverAnimator.SetTrigger("revive"); Player.hinderedMultiplier = 1f; Player.isMovementHindered = 0; Player.sourcesCausingSinking = 0; Player.reverbPreset = instance.shipReverb; } SoundManager.Instance.earsRingingTimer = 0f; Player.voiceMuffledByEnemy = false; SoundManager.Instance.playerVoicePitchTargets[playerIndex] = 1f; SoundManager.Instance.SetPlayerPitch(1f, playerIndex); if ((Object)(object)Player.currentVoiceChatIngameSettings == (Object)null) { instance.RefreshPlayerVoicePlaybackObjects(); } if ((Object)(object)Player.currentVoiceChatIngameSettings != (Object)null) { if ((Object)(object)Player.currentVoiceChatIngameSettings.voiceAudio == (Object)null) { Player.currentVoiceChatIngameSettings.InitializeComponents(); } if (!((Object)(object)Player.currentVoiceChatIngameSettings.voiceAudio == (Object)null)) { ((Component)Player.currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false; } } } } internal static class RevivePlayerSystem { private static readonly List<IReviveCondition> s_ReviveActions = new List<IReviveCondition>(); private static readonly Dictionary<ulong, RevivePlayerMetric> s_PlayerMetrics = new Dictionary<ulong, RevivePlayerMetric>(); public static void AddReviveCondition(IReviveCondition condition) { s_ReviveActions.Add(condition); } public static void ClearReviveActions() { s_ReviveActions.Clear(); } [HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")] [HarmonyPrefix] private static void ResetMetricsOnRoundStart() { Plugin.LOGGER.LogError((object)"Round Manager Finished Level Generation!"); StartOfRound instance = StartOfRound.Instance; s_PlayerMetrics.Clear(); if ((Object)(object)instance == (Object)null) { Plugin.LOGGER.LogError((object)"Start of Round is null at 'FinishGeneratingNewLevelClientRpc'"); return; } s_ReviveActions.ForEach(delegate(IReviveCondition x) { x.Reset(); }); int value = Plugin.Instance.MaxRevives.Value; PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { ulong actualClientId = val.actualClientId; string playerUsername = val.playerUsername; if (actualClientId == 0L && !val.isHostPlayerObject) { break; } Plugin.LOGGER.LogInfo((object)$"Starting Revive Tracking for: '{actualClientId}' => '{playerUsername}'"); s_PlayerMetrics.Add(val.actualClientId, new RevivePlayerMetric(val, value)); } } [HarmonyPatch(typeof(StartOfRound), "Update")] [HarmonyPrefix] private static void TryRevivePlayers(ref StartOfRound __instance) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (!__instance.shipHasLanded || __instance.inShipPhase) { return; } if (s_PlayerMetrics.Count <= 0 || s_ReviveActions.Count <= 0) { Plugin.LOGGER.LogInfo((object)"No revive actions or players available to revive"); return; } foreach (KeyValuePair<ulong, RevivePlayerMetric> s_PlayerMetric in s_PlayerMetrics) { s_PlayerMetric.Deconstruct(out var key, out var value); ulong num = key; RevivePlayerMetric revivePlayerMetric = value; PlayerControllerB player = revivePlayerMetric.Player; if (!player.isPlayerDead || (player.actualClientId == 0L && !player.isHostPlayerObject)) { continue; } foreach (IReviveCondition s_ReviveAction in s_ReviveActions) { if (!revivePlayerMetric.CanRevive() || s_ReviveAction.ShouldRevivePlayer(revivePlayerMetric)) { Plugin.LOGGER.LogInfo((object)$"Reviving Player '{num}' => '{player.playerUsername}'"); revivePlayerMetric.Revive(s_ReviveAction.GetRevivePosition(revivePlayerMetric)); } } } } } internal class ReviveOnBodyCollected : IReviveCondition { public void Reset() { } public bool ShouldRevivePlayer(RevivePlayerMetric metric) { if (Plugin.Instance.ReviveOnBodyCollected.Value) { return metric.Player.deadBody.isInShip; } return false; } } internal class ReviveOnTimer : IReviveCondition { private readonly Dictionary<ulong, float> m_Timers = new Dictionary<ulong, float>(); public void Reset() { m_Timers.Clear(); } public bool ShouldRevivePlayer(RevivePlayerMetric metric) { if (!Plugin.Instance.ReviveAfterDeathOnTimer.Value || !metric.CanRevive()) { return false; } ulong actualClientId = metric.Player.actualClientId; float value = Plugin.Instance.ReviveTimeSeconds.Value; if (!m_Timers.TryGetValue(actualClientId, out var value2)) { m_Timers.Add(actualClientId, 0f); return false; } m_Timers[actualClientId] = value2 + Time.deltaTime; value2 = m_Timers[actualClientId]; if (value2 > value) { m_Timers[actualClientId] = 0f; return true; } return false; } } public static class PluginInfo { public const string PLUGIN_GUID = "LC_ReviveDeadPlayers"; public const string PLUGIN_NAME = "LC_ReviveDeadPlayers"; public const string PLUGIN_VERSION = "1.0.0"; } }