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