Please disclose if your mod was created primarily 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 DeadManWalking v1.0.2
DeadManWalking.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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; 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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] namespace DeadManWalking; [BepInPlugin("DeadManWalking", "DeadManWalking", "1.0.2")] public class Plugin : BaseUnityPlugin { private const string modGUID = "Eltyo.DeadManWalking"; private const string modName = "DeadManWalking"; private const string modVersion = "1.0.2"; 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Instance = this; LOGGER = Logger.CreateLogSource("Eltyo.DeadManWalking"); Harmony = new Harmony("DeadManWalking"); MaxRevives = ((BaseUnityPlugin)Instance).Config.Bind<int>("General", "Max Revives", 3, "The number of times a player can be revived in a single match."); ReviveTimeSeconds = ((BaseUnityPlugin)Instance).Config.Bind<float>("General", "Revive Timer Seconds", 30f, "The number of times a player can be revived in a single match."); ReviveOnBodyCollected = ((BaseUnityPlugin)Instance).Config.Bind<bool>("General", "Revive on body collected", true, "If true the player is revived when their body is collected."); ReviveAfterDeathOnTimer = ((BaseUnityPlugin)Instance).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) { LOGGER.LogError((object)("Failed to patch Revive System; '" + ex.Message + "'\n" + ex.StackTrace)); } LOGGER.LogInfo((object)"Plugin DeadManWalking is loaded!"); } private void OnDestroy() { Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal abstract class IReviveCondition { public abstract void Reset(); public abstract bool ShouldRevivePlayer(RevivePlayerMetric metric); } 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 void Revive(Vector3 revive_pos) { //IL_04b2: Unknown result type (might be due to invalid IL or missing references) if (!CanRevive()) { return; } int revivesLeft = RevivesLeft - 1; RevivesLeft = revivesLeft; Player.ResetPlayerBloodObjects(Player.isPlayerDead); if (Player.isPlayerDead || Player.isPlayerControlled) { Player.isClimbingLadder = false; Player.ResetZAndXRotation(); ((Collider)Player.thisController).enabled = true; Player.health = 100; Player.disableLookInput = false; if (Player.isPlayerDead) { Player.isPlayerDead = false; Player.isPlayerControlled = true; Player.isInElevator = false; Player.isInHangarShipRoom = false; Player.isInsideFactory = true; Player.wasInElevatorLastFrame = false; StartOfRound.Instance.SetPlayerObjectExtrapolate(false); Player.setPositionOfDeadPlayer = false; ((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); Player.deadBody = null; if ((Object)(object)Player == (Object)(object)GameNetworkManager.Instance.localPlayerController) { 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; HUDManager.Instance.HideHUD(false); } } SoundManager.Instance.earsRingingTimer = 0f; Player.voiceMuffledByEnemy = false; if ((Object)(object)Player.currentVoiceChatIngameSettings == (Object)null) { StartOfRound.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) { return; } ((Component)Player.currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false; } } StartOfRound instance = StartOfRound.Instance; instance.livingPlayers++; if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)(object)Player) { Player.bleedingHeavily = false; Player.criticallyInjured = false; Player.playerBodyAnimator.SetBool("Limp", false); Player.health = 100; HUDManager.Instance.UpdateHealthUI(100, false); Player.spectatedPlayerScript = null; ((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false; StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, Player); TimeOfDay.Instance.DisableAllWeather(false); StartOfRound.Instance.UpdatePlayerVoiceEffects(); ((Renderer)Player.thisPlayerModel).enabled = true; } else { ((Renderer)Player.thisPlayerModel).enabled = true; ((Renderer)Player.thisPlayerModelLOD1).enabled = true; ((Renderer)Player.thisPlayerModelLOD2).enabled = true; } Player.TeleportPlayer(revive_pos, false, 0f, false, true); } } 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; PlayerControllerB[] array = allPlayerScripts; foreach (PlayerControllerB val in array) { ulong actualClientId = val.actualClientId; string playerUsername = val.playerUsername; if (actualClientId != 0L || val.isHostPlayerObject) { 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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) 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) { ulong key = s_PlayerMetric.Key; RevivePlayerMetric value = s_PlayerMetric.Value; PlayerControllerB player = value.Player; if (!player.isPlayerDead || (player.actualClientId == 0L && !player.isHostPlayerObject)) { continue; } foreach (IReviveCondition s_ReviveAction in s_ReviveActions) { if (value.CanRevive() && s_ReviveAction.ShouldRevivePlayer(value)) { value.Revive(StartOfRound.Instance.middleOfShipNode.position + new Vector3(0f, -1.5f, 0f)); } } } } } internal class ReviveOnBodyCollected : IReviveCondition { public override void Reset() { } public override 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 override void Reset() { m_Timers.Clear(); } public override 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 = "DeadManWalking"; public const string PLUGIN_NAME = "DeadManWalking"; public const string PLUGIN_VERSION = "1.0.2"; }