using 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";
}