using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; 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 OPJosMod.ReviveCompany.CustomRpc; using OPJosMod.ReviveCompany.Patches; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Erksmit.LethalRevives")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalRevives")] [assembly: AssemblyTitle("Erksmit.LethalRevives")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 LethalRevives { public static class MyPluginInfo { public const string PLUGIN_GUID = "Erksmit.LethalRevives"; public const string PLUGIN_NAME = "LethalRevives"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace OPJosMod.ReviveCompany { public static class ConfigVariables { public static float reviveTime; public static bool reviveTeleportedBodies; public static Key ReviveButton; public static bool CanPickUpBodies; public static float DeadPlayerWeight; public static int ReviveToHealth; public static bool LimitedRevives; public static float RevivesPerLevelMultiplier; public static int HardAmountOfLives; public static int ExtraHealthLostPerRevive; public static bool InfiniteReviveTime; public static int TimeUnitlCantBeRevived; } public static class GeneralUtil { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static Vector3 StringToVector3(string str) { //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_004f: Unknown result type (might be due to invalid IL or missing references) string[] array = str.Trim('(', ')').Split(new char[1] { ',' }); float num = float.Parse(array[0]); float num2 = float.Parse(array[1]); float num3 = float.Parse(array[2]); return new Vector3(num, num2, num3); } public static RagdollGrabbableObject GetClosestDeadBody(Vector3 position) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) RagdollGrabbableObject result = null; float num = float.MaxValue; RagdollGrabbableObject[] array = Object.FindObjectsOfType(); RagdollGrabbableObject[] array2 = array; RagdollGrabbableObject[] array3 = array2; foreach (RagdollGrabbableObject val in array3) { float num2 = Vector3.Distance(((Component)val).transform.position, position); if (num2 < num) { result = val; num = num2; } } return result; } public static PlayerControllerB GetClosestAlivePlayer(Vector3 position) { //IL_0044: 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) PlayerControllerB result = null; float num = float.MaxValue; PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts; PlayerControllerB[] array = allPlayerScripts; PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if (!val.isPlayerDead) { float num2 = Vector3.Distance(((Component)val).transform.position, position); if (num2 < num) { result = val; num = num2; } } } return result; } public static string simplifyObjectNames(string ogName) { string text = ogName; int num = text.IndexOf("("); if (num != -1) { text = text.Substring(0, num).Trim(); } return text; } public static void RevivePlayer(int playerId) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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) //IL_00a4: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0113: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0271: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) //IL_0552: Unknown result type (might be due to invalid IL or missing references) //IL_055d: Expected O, but got Unknown //IL_062b: Unknown result type (might be due to invalid IL or missing references) //IL_0636: Expected O, but got Unknown //IL_05ed: Unknown result type (might be due to invalid IL or missing references) //IL_05f3: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Unknown result type (might be due to invalid IL or missing references) //IL_05fd: Unknown result type (might be due to invalid IL or missing references) //IL_0601: Unknown result type (might be due to invalid IL or missing references) //IL_0607: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_0611: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Unknown result type (might be due to invalid IL or missing references) //IL_061b: Unknown result type (might be due to invalid IL or missing references) if (playerId >= RoundManager.Instance.playersManager.allPlayerScripts.Length || playerId < 0) { Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} as it is outside the range of the allPlayerScripts array"); return; } PlayerControllerB val = RoundManager.Instance.playersManager.allPlayerScripts[playerId]; if ((Object)val != (Object)null && !val.isPlayerDead) { Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} player is already alive! do nothing more"); return; } Vector3 val2 = val.serverPlayerPosition; if ((Object)val.deadBody != (Object)null && (Object)((Component)val.deadBody).transform != (Object)null) { _ = ((Component)val.deadBody).transform.position; bool flag = true; val2 = ((Component)val.deadBody).transform.position; PlayerControllerB closestAlivePlayer = GetClosestAlivePlayer(((Component)val.deadBody).transform.position); if ((Object)closestAlivePlayer != (Object)null && Vector3.Distance(val2, ((Component)closestAlivePlayer).transform.position) > 7f) { val2 = ((Component)closestAlivePlayer).transform.position; } } bool isInsideFactory = false; PlayerControllerB closestAlivePlayer2 = GetClosestAlivePlayer(((Component)val.deadBody).transform.position); if ((Object)closestAlivePlayer2 != (Object)null) { isInsideFactory = closestAlivePlayer2.isInsideFactory; } StartOfRound instance = StartOfRound.Instance; instance.livingPlayers++; StartOfRound.Instance.allPlayersDead = false; StartOfRound.Instance.UpdatePlayerVoiceEffects(); GlobalVariables.RemainingRevives--; if (GlobalVariables.RemainingRevives < 100) { HUDManager.Instance.DisplayTip(val.playerUsername + " was revived", $"{GlobalVariables.RemainingRevives} revives remain!", false, false, "LC_Tip1"); } int num = (int)val.playerClientId; val.ResetPlayerBloodObjects(val.isPlayerDead); val.isClimbingLadder = false; val.ResetZAndXRotation(); ((Collider)val.thisController).enabled = true; val.health = ConfigVariables.ReviveToHealth; val.disableLookInput = false; if (val.isPlayerDead) { val.isPlayerDead = false; val.isPlayerControlled = true; val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = isInsideFactory; val.TeleportPlayer(val2, false, 0f, false, true); val.setPositionOfDeadPlayer = false; val.DisablePlayerModel(StartOfRound.Instance.allPlayerObjects[num], true, true); ((Behaviour)val.helmetLight).enabled = false; val.Crouch(false); val.criticallyInjured = false; if ((Object)(object)val.playerBodyAnimator != (Object)null) { val.playerBodyAnimator.SetBool("Limp", false); } val.bleedingHeavily = false; val.activatingItem = false; val.twoHanded = false; val.inSpecialInteractAnimation = false; val.disableSyncInAnimation = false; val.inAnimationWithEnemy = null; val.holdingWalkieTalkie = false; val.speakingToWalkieTalkie = false; val.isSinking = false; val.isUnderwater = false; val.sinkingValue = 0f; val.statusEffectAudio.Stop(); val.DisableJetpackControlsLocally(); val.health = ConfigVariables.ReviveToHealth; val.mapRadarDotAnimator.SetBool("dead", false); val.hasBegunSpectating = false; val.hinderedMultiplier = 1f; val.isMovementHindered = 0; val.sourcesCausingSinking = 0; val.reverbPreset = StartOfRound.Instance.shipReverb; } SoundManager.Instance.earsRingingTimer = 0f; val.voiceMuffledByEnemy = false; SoundManager.Instance.playerVoicePitchTargets[num] = 1f; SoundManager.Instance.SetPlayerPitch(1f, num); if ((Object)(object)val.currentVoiceChatIngameSettings == (Object)null) { StartOfRound.Instance.RefreshPlayerVoicePlaybackObjects(); } if ((Object)(object)val.currentVoiceChatIngameSettings != (Object)null) { if ((Object)(object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null) { val.currentVoiceChatIngameSettings.InitializeComponents(); } if ((Object)(object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null) { return; } ((Component)val.currentVoiceChatIngameSettings.voiceAudio).GetComponent().overridingLowPass = false; } PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (localPlayerController.playerClientId == val.playerClientId) { GlobalVariables.AmountOfTimesRevived++; int num2 = ConfigVariables.ReviveToHealth - GlobalVariables.AmountOfTimesRevived * ConfigVariables.ExtraHealthLostPerRevive; localPlayerController.bleedingHeavily = false; localPlayerController.criticallyInjured = false; localPlayerController.playerBodyAnimator.SetBool("Limp", false); localPlayerController.health = num2; localPlayerController.spectatedPlayerScript = null; ((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false; StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, localPlayerController); StartOfRound.Instance.SetPlayerObjectExtrapolate(false); HUDManager.Instance.UpdateHealthUI(num2, true); HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false); HUDManager.Instance.RemoveSpectateUI(); HUDManager.Instance.gameOverAnimator.SetTrigger("revive"); } RagdollGrabbableObject closestDeadBody = GetClosestDeadBody(((Component)val).transform.position); if ((Object)closestDeadBody != (Object)null) { if (!((GrabbableObject)closestDeadBody).isHeld) { if (((NetworkBehaviour)StartOfRound.Instance).IsServer) { if (((NetworkBehaviour)closestDeadBody).NetworkObject.IsSpawned) { ((NetworkBehaviour)closestDeadBody).NetworkObject.Despawn(true); } else { Object.Destroy((Object)(object)((Component)closestDeadBody).gameObject); } } } else if (((GrabbableObject)closestDeadBody).isHeld && (Object)(object)((GrabbableObject)closestDeadBody).playerHeldBy != (Object)null) { ((GrabbableObject)closestDeadBody).playerHeldBy.DropAllHeldItems(true, false, false, false, default(Vector3), default(Vector3), default(Vector3), default(Vector3), default(Vector3)); } if ((Object)closestDeadBody.ragdoll != (Object)null) { Object.Destroy((Object)(object)((Component)closestDeadBody.ragdoll).gameObject); } } if (localPlayerController.isPlayerDead) { HUDManager.Instance.UpdateBoxesSpectateUI(); } } public static void ResetAllPlayerInfos() { GlobalVariables.PlayerInfos.Clear(); PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts; PlayerControllerB[] array = allPlayerScripts; foreach (PlayerControllerB val in array) { GlobalVariables.PlayerInfos.Add(new PlayerInfo { PlayerId = (int)val.playerClientId }); } } public static bool HasPlayerTeleported(int playerClientId) { int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId); if (num != -1) { return GlobalVariables.PlayerInfos[num].HasBeenTeleported; } return false; } public static void SetPlayerAsTeleported(int playerClientId) { int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId); if (num != -1) { GlobalVariables.PlayerInfos[num].HasBeenTeleported = true; } } public static void SetPlayerDiedAt(int playerClientId) { int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId); if (num != -1) { GlobalVariables.PlayerInfos[num].TimeDiedAt = Time.time; } } public static float GetPlayersDiedAtTime(int playerClientId) { int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId); if (num != -1) { return GlobalVariables.PlayerInfos[num].TimeDiedAt; } return Time.time; } } public static class GlobalVariables { public static bool ModActivated = false; public static List PlayerInfos = new List(); public static int RemainingRevives = int.MaxValue; public static int AmountOfTimesRevived = 0; } public class PlayerInfo { public int PlayerId { get; set; } public bool HasBeenTeleported { get; set; } public float TimeDiedAt { get; set; } } [BepInPlugin("OpJosMod.ReviveCompany", "ReviveCompany", "1.4.0")] public class OpJosMod : BaseUnityPlugin { private const string modGUID = "OpJosMod.ReviveCompany"; private const string modName = "ReviveCompany"; private const string modVersion = "1.4.0"; private readonly Harmony harmony = new Harmony("OpJosMod.ReviveCompany"); private static OpJosMod Instance; internal ManualLogSource mls; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if ((Object)Instance == (Object)null) { Instance = this; } mls = new ManualLogSource("OpJosMod.ReviveCompany"); Logger.Sources.Add((ILogSource)(object)mls); mls.LogInfo((object)"Test"); setupConfig(); PatchesForRPC.SetLogSource(mls); RpcMessageHandler.SetLogSource(mls); CompleteRecievedTasks.SetLogSource(mls); ResponseHandler.SetLogSource(mls); PlayerControllerBPatch.SetLogSource(mls); ShipTeleporterPatch.SetLogSource(mls); StartOfRoundPatch.SetLogSource(mls); RagdollGrabbableObjectPatch.SetLogSource(mls); GeneralUtil.SetLogSource(mls); harmony.PatchAll(); } private void setupConfig() { //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) ConfigEntry val = ((BaseUnityPlugin)this).Config.Bind("Revive Time", "ReviveTime", 5f, "How long it takes to revive someone"); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind("ReviveButton", "ReviveButton", (Key)32, "Button Used to Revive Players"); ConfigEntry val3 = ((BaseUnityPlugin)this).Config.Bind("Can Pick Up Bodies", "CanPickUpBodies", true, "Toggle if you can pick up bodies."); ConfigEntry val4 = ((BaseUnityPlugin)this).Config.Bind("Dead Body Weight Multiplier", "DeadBodyWeight", 3.25f, "How heavy are the dead players."); ConfigEntry val5 = ((BaseUnityPlugin)this).Config.Bind("Can Revive Teleported Bodies", "CanReviveTeleportedBodies", false, "Toggle for if you are able to revive dead players you teleport back to the ship"); ConfigEntry val6 = ((BaseUnityPlugin)this).Config.Bind("Health you revive with.", "HealthYouReviveWith", 25, "How much health you revive with."); ConfigEntry val7 = ((BaseUnityPlugin)this).Config.Bind("Extra Health Lost Per Revive", "ExtraHealthLostPerRevive", 5, "If player is revived more than once per level, revive with this much less HP each time"); ConfigEntry val8 = ((BaseUnityPlugin)this).Config.Bind("Limit amount of revives", "LimitAmountOfRevives", true, "do you want to have limited revives?"); ConfigEntry val9 = ((BaseUnityPlugin)this).Config.Bind("Revives Per Level Multiplier", "RevivesPerLevelMultiplier", 1.25f, "How many revives you get per level, mulitplied by players in game. ex) value set to 2 and have 4 players then you get 8 revives."); ConfigEntry val10 = ((BaseUnityPlugin)this).Config.Bind("Set Amount of Revives", "SetAmountOfRevives", 0, "Set amount of revives per level. If not at 0 This will override the revive amount being set by the (Revives Per Level Multiplier) setting"); ConfigEntry val11 = ((BaseUnityPlugin)this).Config.Bind("Infinite Revive Time", "InfiniteReviveTime", false, "Can you alwasy revive someone no longer how long they have been dead?"); ConfigEntry val12 = ((BaseUnityPlugin)this).Config.Bind("Time Until Cant Be Revived", "TimeUntilCantBeRevived", 120, "How long someone can be dead for and still be revived in seconds"); ConfigVariables.reviveTime = val.Value; ConfigVariables.ReviveButton = val2.Value; ConfigVariables.CanPickUpBodies = val3.Value; ConfigVariables.DeadPlayerWeight = val4.Value; ConfigVariables.reviveTeleportedBodies = val5.Value; ConfigVariables.ReviveToHealth = val6.Value; ConfigVariables.LimitedRevives = val8.Value; ConfigVariables.RevivesPerLevelMultiplier = val9.Value; ConfigVariables.HardAmountOfLives = val10.Value; ConfigVariables.ExtraHealthLostPerRevive = val7.Value; ConfigVariables.InfiniteReviveTime = val11.Value; ConfigVariables.TimeUnitlCantBeRevived = val12.Value; } } } namespace OPJosMod.ReviveCompany.CustomRpc { public static class ResponseHandler { private static ManualLogSource mls; private static float LastSendTime; private static RpcMessage ResendMessageMessage; private static bool StartWaitForResend; private static int TotalResponses; private static int TotalSentMessages; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void RecievedResponse(MessageTasks messageTask) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown if (messageTask == MessageTasks.RevivePlayer && !((Object)StartOfRound.Instance == (Object)null) && StartOfRound.Instance.allPlayerScripts != null) { TotalResponses++; } } public static void SentMessageNeedResponses(RpcMessage message) { LastSendTime = Time.time; ResendMessageMessage = message; StartWaitForResend = true; TotalResponses = 0; TotalSentMessages = 0; } public static void CalculateIfShouldResend() { if (ResendMessageMessage == null || ResendMessageMessage.Task != MessageTasks.RevivePlayer || !StartWaitForResend || !(Time.time - LastSendTime > 2f)) { return; } if (TotalSentMessages > 4) { mls.LogError((object)"No longer retrying message send as it has already sent 5 extra times."); LastSendTime = 0f; StartWaitForResend = false; TotalResponses = 0; TotalSentMessages = 0; return; } int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player")).ToList().Count(); mls.LogMessage((object)$"TotalResponses:{TotalResponses}, playerCount:{num}"); if (TotalResponses > num - 2 || num - 2 < 0) { LastSendTime = 0f; StartWaitForResend = false; TotalResponses = 0; TotalSentMessages = 0; } else { mls.LogMessage((object)"resending revive message as dont have enough responses"); TotalSentMessages++; LastSendTime = Time.time; RpcMessageHandler.SendRpcMessage(ResendMessageMessage); ResendMessageMessage.Task = MessageTasks.TurnOffGhostMode; RpcMessageHandler.SendRpcMessage(ResendMessageMessage); ResendMessageMessage.Task = MessageTasks.RevivePlayer; } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatchResponseHandler { [HarmonyPatch("Update")] [HarmonyPostfix] private static void patchUpdate(PlayerControllerB __instance) { if (GlobalVariables.ModActivated && ((NetworkBehaviour)__instance).IsOwner) { ResponseHandler.CalculateIfShouldResend(); } } } public static class CompleteRecievedTasks { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void ModActivated(string modName) { if (mls.SourceName == modName) { mls.LogMessage((object)"Mod Activated"); GlobalVariables.ModActivated = true; } } public static void RevivePlayer(string playerIdString) { if (int.TryParse(playerIdString, out var result)) { GeneralUtil.RevivePlayer(result); } else { mls.LogError((object)("Error: Invalid player ID '" + playerIdString + "' did not revive")); } } } public static class PatchesForRPC { public static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } } [HarmonyPatch(typeof(HUDManager))] internal static class HUDManagerPatchForRPC { private static float lastRecievedAt = Time.time; private static string lastRecievedMessage = null; private static float messageWaitTime = 0.5f; [HarmonyPatch("AddPlayerChatMessageClientRpc")] [HarmonyPrefix] private static void addPlayerChatMessageClientRpcPatch(ref string chatMessage, ref int playerId) { string text = MessageCodeUtil.returnMessageNoSeperators(chatMessage); if (MessageCodeUtil.stringContainsMessageCode(chatMessage) && (Time.time - lastRecievedAt > messageWaitTime || text != lastRecievedMessage) && playerId != (int)GameNetworkManager.Instance.localPlayerController.playerClientId) { lastRecievedAt = Time.time; lastRecievedMessage = text; RpcMessageHandler.ReceiveRpcMessage(chatMessage, playerId); } } [HarmonyPatch("AddChatMessage")] [HarmonyPrefix] private static bool addChatMessagePatch(ref string chatMessage) { if (MessageCodeUtil.stringContainsMessageCode(chatMessage)) { return false; } return true; } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatchForRPC { [CompilerGenerated] private sealed class d__3 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public StartOfRound __instance; private RpcMessage 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; if (((NetworkBehaviour)__instance).IsHost) { GlobalVariables.ModActivated = true; 5__1 = new RpcMessage(MessageTasks.ModActivated, PatchesForRPC.mls.SourceName, (int)__instance.localPlayerController.playerClientId, MessageCodes.Request); RpcMessageHandler.SendRpcMessage(5__1); 5__1 = null; } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch("OnClientConnect")] [HarmonyPostfix] private static void patchOnClientConnect(StartOfRound __instance) { ((MonoBehaviour)__instance).StartCoroutine(activateModForOthers(__instance)); } [HarmonyPatch("Start")] [HarmonyPostfix] private static void patchStart(StartOfRound __instance) { if (((NetworkBehaviour)__instance).IsHost) { GlobalVariables.ModActivated = true; } } [HarmonyPatch("OnLocalDisconnect")] [HarmonyPostfix] private static void patchOnLocalDisconnect(StartOfRound __instance) { GlobalVariables.ModActivated = false; } [IteratorStateMachine(typeof(d__3))] private static IEnumerator activateModForOthers(StartOfRound __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { __instance = __instance }; } } public enum MessageCodes { Request, Response } public static class MessageCodeUtil { public static string GetCode(MessageCodes code) { if (1 == 0) { } string result = code switch { MessageCodes.Request => ":rpcRequest:", MessageCodes.Response => ":rpcResponse:", _ => ":Error:", }; if (1 == 0) { } return result; } public static bool stringContainsMessageCode(string givenString) { if (string.IsNullOrEmpty(givenString)) { return false; } return givenString.Contains(GetCode(MessageCodes.Request)) || givenString.Contains(GetCode(MessageCodes.Response)); } public static string returnMessageWithoutCode(string message) { if (stringContainsMessageCode(message)) { message = message.Replace(GetCode(MessageCodes.Request), string.Empty); message = message.Replace(GetCode(MessageCodes.Response), string.Empty); } return message; } public static string returnMessageNoSeperators(string message) { if (stringContainsMessageCode(message)) { return new string(message.Where((char c) => c != ':').ToArray()); } return message; } } public enum MessageTasks { ModActivated, RevivePlayer, TurnOffGhostMode, ErrorNoTask } public static class MessageTaskUtil { public static string GetCode(MessageTasks code) { if (1 == 0) { } string result = code switch { MessageTasks.ModActivated => ":ModActivated:", MessageTasks.RevivePlayer => ":RevivePlayer:", MessageTasks.TurnOffGhostMode => ":TurnOffGhostMode:", MessageTasks.ErrorNoTask => ":Error:", _ => ":Error:", }; if (1 == 0) { } return result; } public static string getMessageWithoutTask(string message) { foreach (MessageTasks value in Enum.GetValues(typeof(MessageTasks))) { string code2 = GetCode(value); message = message.Replace(code2, ""); } return message.Trim(); } public static MessageTasks getMessageTask(string givenString) { if (givenString.Contains(GetCode(MessageTasks.ModActivated))) { return MessageTasks.ModActivated; } if (givenString.Contains(GetCode(MessageTasks.RevivePlayer))) { return MessageTasks.RevivePlayer; } if (givenString.Contains(GetCode(MessageTasks.TurnOffGhostMode))) { return MessageTasks.TurnOffGhostMode; } return MessageTasks.ErrorNoTask; } } public class RpcMessage { public MessageTasks Task { get; set; } public string Message { get; set; } public int FromUser { get; set; } public MessageCodes MessageCode { get; set; } public RpcMessage(MessageTasks task, string message, int user, MessageCodes code) { Task = task; Message = message; FromUser = user; MessageCode = code; } public string getMessageWithCode() { return MessageCodeUtil.GetCode(MessageCode) + MessageTaskUtil.GetCode(Task) + Message; } } public static class RpcMessageHandler { private static ManualLogSource mls; private static RpcMessage lastSentMessage = null; private static float lastSentTime = Time.time; private static float messageWaitTime = 0.5f; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void SendRpcMessage(RpcMessage message) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if (Time.time - lastSentTime > messageWaitTime || lastSentMessage != message) { mls.LogMessage((object)$"Sending rpc message: {message.getMessageWithCode()}, user:{message.FromUser}"); lastSentTime = Time.time; lastSentMessage = message; HUDManager instance = HUDManager.Instance; if ((Object)instance != (Object)null) { MethodInfo method = typeof(HUDManager).GetMethod("AddPlayerChatMessageServerRpc", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { object[] parameters = new object[2] { message.getMessageWithCode(), message.FromUser }; method.Invoke(instance, parameters); } else { mls.LogError((object)"AddPlayerChatMessageServerRpc method not found in HUDManager class."); } } else { mls.LogError((object)"HUDManager.Instance is null."); } } else { mls.LogError((object)("didnt' send message as it was too soon and was the same message as last message " + message.getMessageWithCode())); } } public static void ReceiveRpcMessage(string message, int user) { mls.LogMessage((object)$"recieved message: {message}, user:{user}"); if (user != (int)StartOfRound.Instance.localPlayerController.playerClientId) { string text = MessageCodeUtil.returnMessageWithoutCode(message); if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Request))) { MessageTasks messageTask = MessageTaskUtil.getMessageTask(text); string messageWithoutTask = MessageTaskUtil.getMessageWithoutTask(text); SendRpcResponse(messageTask, messageWithoutTask); handleTask(messageTask, messageWithoutTask); } else if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Response))) { ResponseHandler.RecievedResponse(MessageTaskUtil.getMessageTask(text)); } } } public static void SendRpcResponse(MessageTasks task, string message) { try { RpcMessage message2 = new RpcMessage(task, message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Response); SendRpcMessage(message2); } catch (Exception arg) { mls.LogError((object)$"failed to send response message: {arg}"); } } private static void handleTask(MessageTasks task, string message) { try { switch (task) { case MessageTasks.ModActivated: CompleteRecievedTasks.ModActivated(message); break; case MessageTasks.RevivePlayer: CompleteRecievedTasks.RevivePlayer(message); break; case MessageTasks.ErrorNoTask: mls.LogError((object)"got an error task"); break; case MessageTasks.TurnOffGhostMode: break; } } catch (Exception arg) { mls.LogError((object)$"failed handlign rpc task: {arg}, task:{task}, message:{message}"); } } } } namespace OPJosMod.ReviveCompany.Patches { [HarmonyPatch(typeof(RagdollGrabbableObject))] internal class RagdollGrabbableObjectPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Start")] [HarmonyPrefix] private static void patchStart(RagdollGrabbableObject __instance) { if (GlobalVariables.ModActivated) { ((GrabbableObject)__instance).itemProperties.weight = ConfigVariables.DeadPlayerWeight; } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("EndOfGame")] [HarmonyPrefix] private static void patchEndOfGame() { if (GlobalVariables.ModActivated) { mls.LogMessage((object)"reset bodies teleported list"); GeneralUtil.ResetAllPlayerInfos(); } } [HarmonyPatch("openingDoorsSequence")] [HarmonyPrefix] private static void patchOpeningDoorsSequence() { if (GlobalVariables.ModActivated) { mls.LogMessage((object)"round starting, reseting allowed revive count"); GeneralUtil.ResetAllPlayerInfos(); setStartingRevives(); } } private static void setStartingRevives() { int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => x.isPlayerControlled).Count(); GlobalVariables.AmountOfTimesRevived = 0; if (ConfigVariables.LimitedRevives) { if (ConfigVariables.HardAmountOfLives != 0) { GlobalVariables.RemainingRevives = ConfigVariables.HardAmountOfLives; } else { GlobalVariables.RemainingRevives = Mathf.RoundToInt((float)num * ConfigVariables.RevivesPerLevelMultiplier); } } else { GlobalVariables.RemainingRevives = int.MaxValue; } } } [HarmonyPatch(typeof(ShipTeleporter))] internal class ShipTeleporterPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("beamUpPlayer")] [HarmonyPrefix] private static void patchbeamUpPlayer() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (GlobalVariables.ModActivated) { PlayerControllerB targetedPlayer = StartOfRound.Instance.mapScreen.targetedPlayer; if (!((Object)targetedPlayer == (Object)null) && !((Object)targetedPlayer.redirectToEnemy != (Object)null) && !((Object)targetedPlayer.deadBody == (Object)null) && targetedPlayer.isPlayerDead) { GeneralUtil.SetPlayerAsTeleported((int)targetedPlayer.playerClientId); } } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { private static ManualLogSource mls; private static int interactableObjectsMask = 832; private static float StartedReviveAt = Time.time; private static bool StartedRevive = false; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Interact_performed")] [HarmonyPrefix] private static bool interact_performedPatch(PlayerControllerB __instance) { if (!GlobalVariables.ModActivated) { return true; } if (ConfigVariables.CanPickUpBodies) { return true; } if (((NetworkBehaviour)__instance).IsOwner && !__instance.isPlayerDead && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject) && !canUse(__instance)) { return false; } return true; } [HarmonyPatch("KillPlayerClientRpc")] [HarmonyPrefix] private static void killPlayerClientRpcPatch(PlayerControllerB __instance, ref int playerId) { if (GlobalVariables.ModActivated) { GeneralUtil.SetPlayerDiedAt(playerId); } } [HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")] [HarmonyPostfix] private static void setHoverTipAndCurrentInteractTriggerPatch(PlayerControllerB __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (!GlobalVariables.ModActivated) { return; } if (!canUse(__instance) && ((TMP_Text)__instance.cursorTip).text != "") { if (((ButtonControl)Keyboard.current[ConfigVariables.ReviveButton]).isPressed) { if (!StartedRevive) { StartedRevive = true; StartedReviveAt = Time.time; } else if (Time.time - StartedReviveAt > ConfigVariables.reviveTime) { RagdollGrabbableObject closestDeadBody = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position); if (!canRevive(closestDeadBody)) { ((TMP_Text)__instance.cursorTip).text = "[Can't Revive Player!]"; return; } StartedRevive = false; RpcMessage message = new RpcMessage(MessageTasks.RevivePlayer, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request); RpcMessageHandler.SendRpcMessage(message); ResponseHandler.SentMessageNeedResponses(message); GeneralUtil.RevivePlayer((int)closestDeadBody.ragdoll.playerScript.playerClientId); RpcMessage message2 = new RpcMessage(MessageTasks.TurnOffGhostMode, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request); RpcMessageHandler.SendRpcMessage(message2); } ((TMP_Text)__instance.cursorTip).text = $"[Reviving! {(int)Mathf.Round(Time.time - StartedReviveAt)}/{ConfigVariables.reviveTime}s]"; return; } if (ConfigVariables.InfiniteReviveTime) { ((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!]"; } else { RagdollGrabbableObject closestDeadBody2 = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position); double num = Math.Round((float)ConfigVariables.TimeUnitlCantBeRevived - (Time.time - GeneralUtil.GetPlayersDiedAtTime((int)closestDeadBody2.ragdoll.playerScript.playerClientId))); if (num > 0.0) { ((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!] {num}s Left!"; } else { ((TMP_Text)__instance.cursorTip).text = "0 Time Left!"; } } StartedRevive = false; } else { StartedRevive = false; } } private static bool canUse(PlayerControllerB __instance) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Ray val = default(Ray); ((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, ref val2, __instance.grabDistance, interactableObjectsMask)) { GrabbableObject component = ((Component)((RaycastHit)(ref val2)).collider).GetComponent(); if ((Object)(object)component != (Object)null) { string text = GeneralUtil.simplifyObjectNames(((Object)component).name); if (text == "RagdollGrabbableObject") { return false; } } } return true; } private static bool canRevive(RagdollGrabbableObject revivingBody) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (GlobalVariables.RemainingRevives <= 0) { return false; } if ((Object)revivingBody != (Object)null && (Object)revivingBody.ragdoll != (Object)null && (Object)revivingBody.ragdoll.playerScript != (Object)null && GameNetworkManager.Instance.localPlayerController.playerClientId == revivingBody.ragdoll.playerScript.playerClientId) { return false; } int playerClientId = (int)revivingBody.ragdoll.playerScript.playerClientId; if (GeneralUtil.HasPlayerTeleported(playerClientId) && !ConfigVariables.reviveTeleportedBodies) { return false; } mls.LogInfo((object)(Time.time + " | " + GeneralUtil.GetPlayersDiedAtTime(playerClientId))); if (Time.time - GeneralUtil.GetPlayersDiedAtTime(playerClientId) > (float)ConfigVariables.TimeUnitlCantBeRevived && !ConfigVariables.InfiniteReviveTime) { return false; } return true; } } } namespace OPJosMod.ReviveCompany.Utils { public class ReflectionUtils { public static void InvokeMethod(object obj, string methodName, object[] parameters) { Type type = obj.GetType(); MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); method.Invoke(obj, parameters); } public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters) { MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); method.Invoke(obj, parameters); } public static void SetPropertyValue(object obj, string propertyName, object value) { Type type = obj.GetType(); PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); property.SetValue(obj, value); } public static T InvokeMethod(object obj, string methodName, object[] parameters) { Type type = obj.GetType(); MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return (T)method.Invoke(obj, parameters); } public static T GetFieldValue(object obj, string fieldName) { Type type = obj.GetType(); FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return (T)field.GetValue(obj); } public static void SetFieldValue(object obj, string fieldName, object value) { Type type = obj.GetType(); FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); field.SetValue(obj, value); } } }