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 HideNSeek v1.2.0
HideNSeek.dll
Decompiled 2 years agousing System; using System.Collections; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using OPJosMod; using OPJosMod.HideNSeek.Config; using OPJosMod.HideNSeek.CustomRpc; using OPJosMod.HideNSeek.Utils; using OPJosMode.HideNSeek.Patches; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("OPJosMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OPJosMod")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("70095872-b952-4e27-bbc4-3d70d0238f39")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace OPJosMode.HideNSeek.Patches { [HarmonyPatch(typeof(EntranceTeleport))] internal class EntranceTeleportPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("FindExitPoint")] [HarmonyPrefix] private static bool findExitPointPatch() { if (PlayerControllerBPatch.isHider) { return false; } return true; } } [HarmonyPatch(typeof(TimeOfDay))] internal class TimeOfDayPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Update")] [HarmonyPrefix] private static void updatePatch(TimeOfDay __instance) { int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player #")).ToArray().Length; float daySpeedMultiplier = ConfigVariables.daySpeedMultiplier; __instance.globalTimeSpeedMultiplier = daySpeedMultiplier * 4f / (float)num; } } [HarmonyPatch(typeof(Turret))] internal class TurretPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Start")] [HarmonyPrefix] private static void startPatch(Turret __instance) { __instance.turretActive = false; } } [HarmonyPatch(typeof(RoundManager))] internal class RoundManagerPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("FinishGeneratingNewLevelClientRpc")] [HarmonyPostfix] private static void finishGeneratingNewLevelClientRpcPatch(RoundManager __instance) { if (PlayerControllerBPatch.isSeeker) { PlayerControllerBPatch.SetupSeeker(); } else { PlayerControllerBPatch.SetupHider(); } } [HarmonyPatch("LoadNewLevel")] [HarmonyPrefix] private static void loadNewLevelPatch(RoundManager __instance) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) mls.LogMessage((object)"load new level patch hit"); if (GameNetworkManager.Instance.isHostingGame) { __instance.currentMaxInsidePower = 0f; __instance.currentMaxOutsidePower = 0f; __instance.currentLevel.maxEnemyPowerCount = 0; __instance.currentLevel.maxOutsideEnemyPowerCount = 0; if (!ConfigVariables.shouldSpawnScrap) { __instance.scrapAmountMultiplier = 0f; } Vector3 position = __instance.playersManager.playerSpawnPositions[0].position; GeneralUtil.spawnItemAtLocation(ConfigVariables.seekerItem1, position); GeneralUtil.spawnItemAtLocation(ConfigVariables.seekerItem2, position); GeneralUtil.spawnItemAtLocation(ConfigVariables.seekerItem3, position); GeneralUtil.spawnItemAtLocation(ConfigVariables.seekerItem4, position); } } } [HarmonyPatch(typeof(FlashlightItem))] internal class FlashlightItemPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Start")] [HarmonyPrefix] private static void startPatch(FlashlightItem __instance) { if (__instance.flashlightTypeID == 1) { ((GrabbableObject)__instance).itemProperties.requiresBattery = false; __instance.flashlightBulb.intensity = __instance.flashlightBulb.intensity / (float)ConfigVariables.smallFlashlightPower; } else if (__instance.flashlightTypeID == 0) { ((GrabbableObject)__instance).itemProperties.weight = 1.05f * ConfigVariables.proFlashlightWeightMultiplier; ((GrabbableObject)__instance).itemProperties.batteryUsage = 300f * ConfigVariables.proFlashlightBatteryUsageMultiplier; } } } [HarmonyPatch(typeof(Terminal))] internal class TerminalPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Start")] [HarmonyPrefix] private static void startPatch(Terminal __instance) { if (GameNetworkManager.Instance.isHostingGame) { __instance.groupCredits = 123456789; __instance.SyncGroupCreditsServerRpc(__instance.groupCredits, __instance.numberOfItemsInDropship); } } [HarmonyPatch("RunTerminalEvents")] [HarmonyPrefix] private static void runTerminalEventsPatch(Terminal __instance) { if (GameNetworkManager.Instance.isHostingGame) { __instance.groupCredits = 123456789; __instance.SyncGroupCreditsServerRpc(__instance.groupCredits, __instance.numberOfItemsInDropship); } } } [HarmonyPatch(typeof(Shovel))] internal class ShovelPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("HitShovel")] [HarmonyPrefix] private static void hitShovelPatch(Shovel __instance) { __instance.shovelHitForce = 30; } } [HarmonyPatch(typeof(StartMatchLever))] internal class StartMatchLeverPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("PullLever")] [HarmonyPrefix] private static void pullLeverPatch(StartMatchLever __instance) { mls.LogMessage((object)"player pulled lever, set them to seeker"); PlayerControllerBPatch.isSeeker = true; PlayerControllerBPatch.isHider = false; } } [HarmonyPatch(typeof(HUDManager))] internal class HUDManagerPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("PingScan_performed")] [HarmonyPrefix] private static bool pingScan_performedPatch() { if (PlayerControllerBPatch.isSeeker) { return false; } return true; } [HarmonyPatch("FillEndGameStats")] [HarmonyPrefix] private static void fillEndGameStatsPatchPre(HUDManager __instance, ref EndOfGameStats stats) { for (int i = 0; i < RoundManager.Instance.playersManager.allPlayerScripts.Length; i++) { StartOfRound.Instance.gameStats.allPlayerStats[i].playerNotes.Clear(); if (RoundManager.Instance.playersManager.allPlayerScripts[i].isPlayerDead) { mls.LogMessage((object)$"player{i} is dead, so they lost"); StartOfRound.Instance.gameStats.allPlayerStats[i].playerNotes.Add("Lost the game :("); } else { mls.LogMessage((object)$"player{i} won!"); StartOfRound.Instance.gameStats.allPlayerStats[i].playerNotes.Add("Won the game!"); } } for (int j = 0; j < __instance.statsUIElements.playerNotesText.Length; j++) { PlayerControllerB val = RoundManager.Instance.playersManager.allPlayerScripts[j]; TextMeshProUGUI val2 = __instance.statsUIElements.playerNotesText[j]; if (!val.playerUsername.Contains("Player #")) { if (val.isPlayerDead) { ((TMP_Text)val2).text = "They lost :("; } else { ((TMP_Text)val2).text = "They Won!"; } } else { mls.LogMessage((object)$"dont put stats for player {j}"); ((TMP_Text)val2).text = ""; } } } [HarmonyPatch("FillEndGameStats")] [HarmonyPostfix] private static void fillEndGameStatsPatchPost(HUDManager __instance, ref EndOfGameStats stats) { ((Component)HUDManager.Instance.statsUIElements.allPlayersDeadOverlay).gameObject.SetActive(false); if (StartOfRound.Instance.localPlayerController.isPlayerDead) { ((TMP_Text)HUDManager.Instance.statsUIElements.gradeLetter).text = "L"; } else { ((TMP_Text)HUDManager.Instance.statsUIElements.gradeLetter).text = "W"; } } [HarmonyPatch("ApplyPenalty")] [HarmonyPrefix] private static bool applyPenaltyPatch(HUDManager __instance, ref int playersDead, ref int bodiesInsured) { return false; } public static void CustomDisplayTip(string headerText, string bodyText, bool makeSound = true) { HUDManager instance = HUDManager.Instance; ((TMP_Text)instance.tipsPanelHeader).text = headerText; ((TMP_Text)instance.tipsPanelBody).text = bodyText; instance.tipsPanelAnimator.SetTrigger("TriggerHint"); if (makeSound) { RoundManager.PlayRandomClip(instance.UIAudio, instance.tipsSFX, false, 1f, 0, 1000); } } public static void CustomDisplayBigMessage(string maingText, bool makeSound = true) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) ((Graphic)HUDManager.Instance.profitQuotaDaysLeftText).color = new Color(0.8431f, 0.2314f, 0.2196f, 1f); ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText).fontSize = 46f; ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText).fontStyle = (FontStyles)1; ((Transform)((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText).rectTransform).localScale = new Vector3(1f, 1.04f, 1.02f); ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText).text = "TO MEET PROFIT QUOTA"; Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(-21.78f, -59.48f, 12.15f); ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText).transform.position = position; ((Graphic)HUDManager.Instance.profitQuotaDaysLeftText2).color = new Color(0f, 0f, 0f, 1f); ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText2).text = maingText; ((TMP_Text)HUDManager.Instance.profitQuotaDaysLeftText2).fontSize = 46f; HUDManager.Instance.reachedProfitQuotaAnimator.SetTrigger("displayDaysLeft"); if (makeSound) { HUDManager.Instance.UIAudio.PlayOneShot(HUDManager.Instance.OneDayToMeetQuotaSFX); } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("Update")] [HarmonyPostfix] private static void startPatch(StartOfRound __instance) { ((TMP_Text)__instance.profitQuotaMonitorText).text = "Hide N Seek!"; ((TMP_Text)__instance.deadlineMonitorText).text = "Have fun and such"; ((Component)__instance.mapScreen).gameObject.SetActive(false); TimeOfDay.Instance.daysUntilDeadline = 4; TimeOfDay.Instance.timeUntilDeadline = 75500f; } [HarmonyPatch("ReviveDeadPlayers")] [HarmonyPrefix] private static void reviveDeadPlayersPatch(StartOfRound __instance) { mls.LogMessage((object)"revive dead players patch hit in start of round class, reset isSeeker and isHider"); PlayerControllerBPatch.resetRoleValues(); } [HarmonyPatch("ShipLeave")] [HarmonyPrefix] public static void shipLeavePatch(StartOfRound __instance) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (!StartOfRound.Instance.localPlayerController.isPlayerDead && PlayerControllerBPatch.isHider && TimeOfDay.Instance.currentDayTime + 10f > TimeOfDay.Instance.globalTimeAtEndOfDay) { mls.LogMessage((object)"ship taking off but player isn't dead"); ((Component)StartOfRound.Instance.localPlayerController).transform.position = RoundManager.Instance.playersManager.playerSpawnPositions[0].position; HUDManager.Instance.DisplayTip("Round Over!", "Stay on ship", false, false, "LC_Tip1"); } if (!StartOfRound.Instance.localPlayerController.isPlayerDead && PlayerControllerBPatch.isSeeker) { int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => x.isPlayerControlled).Count(); if (num == 1) { mls.LogMessage((object)"you won as seeker!"); ((Component)StartOfRound.Instance.localPlayerController).transform.position = RoundManager.Instance.playersManager.playerSpawnPositions[0].position; HUDManager.Instance.DisplayTip("Round Over!", "Stay on ship", false, false, "LC_Tip1"); } } PlayerControllerBPatch.resetRoleValues(); } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] public static void StartOfRoundSuitPatch(StartOfRound __instance) { if (GameNetworkManager.Instance.isHostingGame) { int[] array = new int[6] { 1, 2, 3, 24, 25, 26 }; int[] array2 = array; foreach (int num in array2) { ReflectionUtils.InvokeMethod(StartOfRound.Instance, "SpawnUnlockable", new object[1] { num }); } } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] public static void ResetShipSuitPatch(StartOfRound __instance) { if (GameNetworkManager.Instance.isHostingGame) { StartOfRoundSuitPatch(__instance); } } [HarmonyPatch("SetPlanetsWeather")] [HarmonyPostfix] private static void setPlanetsWeatherPatch(ref SelectableLevel[] ___levels) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < ___levels.Length; i++) { ___levels[i].currentWeather = (LevelWeatherType)(-1); } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { private static ManualLogSource mls; public static bool hasSetRole = false; public static bool isSeeker = false; public static bool isHider = false; private static Coroutine teleportCoroutine; private static Coroutine lockPlayerCoroutine; private static float lastCheckedTime; private static float checkGameOverFrequency = 5f; private static float lastUsedSeekerAbilityAt = Time.time; private static int lastCheckedAliveCount = -1; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void resetRoleValues() { hasSetRole = false; isSeeker = false; isHider = false; lastCheckedTime = Time.time; } [HarmonyPatch("Update")] [HarmonyPostfix] private static void updatePatch(PlayerControllerB __instance) { if (isSeeker) { if (ReflectionUtils.GetFieldValue<bool>(__instance, "isWalking")) { float fieldValue = ReflectionUtils.GetFieldValue<float>(__instance, "sprintMultiplier"); if (__instance.isSprinting) { float num = fieldValue * ConfigVariables.seekerSprintMultiplier; if (num < ConfigVariables.seekerMaxSprintSpeed) { ReflectionUtils.SetFieldValue(__instance, "sprintMultiplier", num); } } } if (Mouse.current.rightButton.wasPressedThisFrame) { if (Time.time - lastUsedSeekerAbilityAt > ConfigVariables.seekerAbilityCD) { lastUsedSeekerAbilityAt = Time.time; makeClosestPlayerWhistle(StartOfRound.Instance.localPlayerController); } else if (Time.time - lastUsedSeekerAbilityAt > 1f) { HUDManagerPatch.CustomDisplayTip("Ability on cooldown", $"for {(int)(ConfigVariables.seekerAbilityCD - (Time.time - lastUsedSeekerAbilityAt))} seconds", makeSound: false); } } } if (Time.time - lastCheckedTime > checkGameOverFrequency) { checkIfShouldEndRound(__instance); lastCheckedTime = Time.time; } if (isSeeker || isHider) { HUDManager.Instance.SetClockVisible(true); } } [HarmonyPatch("Start")] [HarmonyPrefix] private static void startPatch(PlayerControllerB __instance) { __instance.allHelmetLights[1].intensity = __instance.allHelmetLights[1].intensity / (float)ConfigVariables.smallFlashlightPower; __instance.jumpForce = ConfigVariables.jumpForce; ((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = ""; ((Component)HUDManager.Instance.holdButtonToEndGameEarlyMeter).gameObject.SetActive(false); ((TMP_Text)HUDManager.Instance.holdButtonToEndGameEarlyVotesText).text = ""; ((TMP_Text)HUDManager.Instance.holdButtonToEndGameEarlyText).text = ""; ((TMP_Text)HUDManager.Instance.spectatorTipText).text = ""; HUDManager.Instance.gameOverAnimator.SetTrigger("gameOver"); } [HarmonyPatch("KillPlayer")] [HarmonyPostfix] private static void killPlayerPatch(PlayerControllerB __instance) { if (isSeeker) { mls.LogMessage((object)"end game called as you are a seeker"); StartOfRound.Instance.EndGameServerRpc((int)__instance.playerClientId); } } private static void checkIfShouldEndRound(PlayerControllerB __instance) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) int totalPlayersCount = GeneralUtil.getTotalPlayersCount(); int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => x.isPlayerControlled).Count(); Vector3 position = RoundManager.Instance.playersManager.playerSpawnPositions[0].position; if (num < lastCheckedAliveCount && lastCheckedAliveCount != -1) { if (isSeeker) { HUDManagerPatch.CustomDisplayTip("Someone has Died!", $"{num} players remain", makeSound: false); } else if (isHider) { HUDManagerPatch.CustomDisplayBigMessage($"Someone Died! \n {num} players remain"); } } lastCheckedAliveCount = num; ((TMP_Text)HUDManager.Instance.spectatingPlayerText).text = $"|{num}/{totalPlayersCount} players remain|"; if (num == 1) { mls.LogMessage((object)$"one person alive, round over. totalPlayers:{num}"); StartOfRound.Instance.EndGameServerRpc((int)__instance.playerClientId); } } public static void SetupHider() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!hasSetRole) { HUDManager.Instance.DisplayTip("Role Set", "You are a Hider!", false, false, "LC_Tip1"); hasSetRole = true; mls.LogMessage((object)"setup player as a hider"); PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; isSeeker = false; isHider = true; teleportCoroutine = ((MonoBehaviour)localPlayerController).StartCoroutine(customTeleportPlayer(localPlayerController, RoundManager.FindMainEntrancePosition(false, false), 5f)); localPlayerController.isInsideFactory = true; } } public static void SetupSeeker() { if (!hasSetRole) { HUDManager.Instance.DisplayTip("Role Set", "You are Seeker!", false, false, "LC_Tip1"); hasSetRole = true; mls.LogMessage((object)"setup player as seeker"); PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; isSeeker = true; isHider = false; lockPlayerCoroutine = ((MonoBehaviour)localPlayerController).StartCoroutine(lockPlayer(localPlayerController, ConfigVariables.seekerDelay)); } } private static IEnumerator customTeleportPlayer(PlayerControllerB player, Vector3 location, float initalDelay) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (teleportCoroutine != null) { ((MonoBehaviour)player).StopCoroutine(teleportCoroutine); } yield return (object)new WaitForSeconds(initalDelay); player.DropAllHeldItemsAndSync(); yield return (object)new WaitForSeconds(1f); GameNetworkManager.Instance.localPlayerController.TeleportPlayer(location, false, 0f, false, true); } private static IEnumerator lockPlayer(PlayerControllerB player, float lockTime) { if (lockPlayerCoroutine != null) { ((MonoBehaviour)player).StopCoroutine(lockPlayerCoroutine); } yield return (object)new WaitForSeconds(1f); mls.LogMessage((object)"player locked in place"); player.playerCollider.enabled = false; for (int i = 0; (float)i < lockTime; i++) { yield return (object)new WaitForSeconds(1f); HUDManagerPatch.CustomDisplayTip($"{lockTime - (float)(i + 1)}", "seconds remain", makeSound: false); } HUDManagerPatch.CustomDisplayTip("GO FIND", "THEM!", makeSound: false); mls.LogMessage((object)"player unlocked!"); player.playerCollider.enabled = true; string message = MessageTaskUtil.GetCode(MessageTasks.StartedSeeking) + player.playerClientId; RpcMessage rpcMessage = new RpcMessage(message, (int)player.playerClientId, MessageCodes.Request); RpcMessageHandler.SendRpcMessage(rpcMessage); GeneralUtil.spawnHiderItem((int)player.playerClientId); } private static void makeClosestPlayerWhistle(PlayerControllerB localPlayer) { mls.LogMessage((object)"Making closest player whistle"); HUDManagerPatch.CustomDisplayTip("Closest Player", "made a noise", makeSound: false); PlayerControllerB val = findClosestPlayer(localPlayer); PlaySounds.PlayFart(val); string message = MessageTaskUtil.GetCode(MessageTasks.MakePlayerWhistle) + val.playerClientId; RpcMessage message2 = new RpcMessage(message, (int)localPlayer.playerClientId, MessageCodes.Request); RpcMessageHandler.SendRpcMessage(message2); } private static PlayerControllerB findClosestPlayer(PlayerControllerB localPlayer) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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; foreach (PlayerControllerB val in array) { if (val.playerClientId != localPlayer.playerClientId) { float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position); if (num2 < num) { result = val; num = num2; } } } return result; } } } namespace OPJosMod { public enum FlashlightTypes { ProFlashlight, NormalFlashlight } public enum BuyableItems { None = -1, WalkieTalkie, Flashlight, Shovel, LockPicker, ProFlashlight, StunGrenade, Boombox, TZPInhalant, ZapGun, Jetpack, ExtensionLadder, RadarBooster, SprayPaint } public static class GeneralUtil { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void spawnItemAtLocation(BuyableItems item, Vector3 location) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (GameNetworkManager.Instance.isHostingGame) { if (item != BuyableItems.None) { Terminal fieldValue = ReflectionUtils.GetFieldValue<Terminal>(HUDManager.Instance, "terminalScript"); GameObject val = Object.Instantiate<GameObject>(fieldValue.buyableItemsList[(int)item].spawnPrefab, location, Quaternion.identity, StartOfRound.Instance.localPlayerController.playersManager.propsContainer); val.GetComponent<GrabbableObject>().fallTime = 0f; val.GetComponent<NetworkObject>().Spawn(false); } } else { mls.LogError((object)$"tried to spawn item: {item} but can't as this is not the host"); } } public static void spawnHiderItem(int seekerId) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!GameNetworkManager.Instance.isHostingGame) { return; } PlayerControllerB[] allPlayersConneced = getAllPlayersConneced(); PlayerControllerB[] array = allPlayersConneced; foreach (PlayerControllerB val in array) { if ((int)val.playerClientId != seekerId) { mls.LogMessage((object)$"spawn hider item at {((Component)val).transform.position}"); spawnItemAtLocation(ConfigVariables.hiderItem, ((Component)val).transform.position); } else { mls.LogMessage((object)$"dont spawn hider item at this players position,{val.playerClientId} they are seeker"); } } } public static int getTotalPlayersCount() { PlayerControllerB[] array = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player #")).ToArray(); return array.Length; } public static PlayerControllerB[] getAllPlayersConneced() { return RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player #")).ToArray(); } } public static class PlaySounds { private static WhoopieCushionItem whoopieItem; private static AudioClip[] fartAudios; private static Vector3 lastPositionAtFart; private static int timesPlayingInOneSpot; public static void InitializePlaySounds() { whoopieItem = Resources.FindObjectsOfTypeAll<WhoopieCushionItem>()[0]; fartAudios = whoopieItem.fartAudios; } public static void PlayFart(PlayerControllerB player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) InitializePlaySounds(); AudioSource itemAudio = player.itemAudio; itemAudio.volume = 0.7f; itemAudio.maxDistance = 80f; if (Vector3.Distance(lastPositionAtFart, ((Component)player).transform.position) > 2f) { timesPlayingInOneSpot = 0; } timesPlayingInOneSpot++; lastPositionAtFart = ((Component)player).transform.position; RoundManager.PlayRandomClip(itemAudio, fartAudios, true, 1f, -1, 1000); RoundManager.Instance.PlayAudibleNoise(((Component)player).transform.position, 22f, 0.5f, timesPlayingInOneSpot, false, 101158); } } } namespace OPJosMod.HideNSeek { [BepInPlugin("OpJosMod.HideNSeek", "HideNSeek", "1.2.0")] public class OpJosMod : BaseUnityPlugin { private const string modGUID = "OpJosMod.HideNSeek"; private const string modName = "HideNSeek"; private const string modVersion = "1.2.0"; private readonly Harmony harmony = new Harmony("OpJosMod.HideNSeek"); private static OpJosMod Instance; internal ManualLogSource mls; private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; } mls = Logger.CreateLogSource("OpJosMod.HideNSeek"); mls.LogInfo((object)"mod has started"); setupConfig(); RpcMessageHandler.SetLogSource(mls); HUDManagerPatchForRPC.SetLogSource(mls); CompleteRecievedTasks.SetLogSource(mls); PlayerControllerBPatch.SetLogSource(mls); StartOfRoundPatch.SetLogSource(mls); StartMatchLeverPatch.SetLogSource(mls); RoundManagerPatch.SetLogSource(mls); HUDManagerPatch.SetLogSource(mls); EntranceTeleportPatch.SetLogSource(mls); ShovelPatch.SetLogSource(mls); TerminalPatch.SetLogSource(mls); GeneralUtil.SetLogSource(mls); FlashlightItemPatch.SetLogSource(mls); TurretPatch.SetLogSource(mls); TimeOfDayPatch.SetLogSource(mls); harmony.PatchAll(); } private void setupConfig() { ConfigEntry<float> val = ((BaseUnityPlugin)this).Config.Bind<float>("Seeker Delay", "SeekerDelay", 50f, "How long until the seeker can begin seeking"); ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>("Seeker Ability CD", "SeekerAbilityCD", 25f, "Cooldown for seekers ability"); ConfigEntry<int> val3 = ((BaseUnityPlugin)this).Config.Bind<int>("Small Flashlight Power", "SmallFlashlightPower", 2, "Fraction of brightness, ex) 5 = 1/5th power"); ConfigEntry<float> val4 = ((BaseUnityPlugin)this).Config.Bind<float>("Pro Flashlight Weight", "ProFlashlightWeight", 1.25f, "Weight Increase multiplier, higher number greater the weight."); ConfigEntry<float> val5 = ((BaseUnityPlugin)this).Config.Bind<float>("Pro Flashlight Battery Usage", "ProFlashlightBatteryUsage", 0.5f, "Influences how fast the battery depletes on the pro flashlight, 1 = games default speed"); ConfigEntry<float> val6 = ((BaseUnityPlugin)this).Config.Bind<float>("Seeking Sprint Multiplier", "SeekingSprintMultiplier", 1.01f, "How fast you accelerate as a seeker"); ConfigEntry<float> val7 = ((BaseUnityPlugin)this).Config.Bind<float>("Seeking Sprint Top Speed", "SeekingSprintTopSpeed", 3f, "The fastest the seeker can move"); ConfigEntry<float> val8 = ((BaseUnityPlugin)this).Config.Bind<float>("Day Speed Multiplier", "DaySpeedMultiplier", 2.5f, "Higher the number the faster days go, day speed auto adjusts with players"); ConfigEntry<bool> val9 = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn Scrap", "SpawnScrap", false, "should items scrap?"); ConfigEntry<float> val10 = ((BaseUnityPlugin)this).Config.Bind<float>("Jump Force", "JumpForce", 15f, "How strong your jump is, game default is 5"); ConfigEntry<BuyableItems> val11 = ((BaseUnityPlugin)this).Config.Bind<BuyableItems>("Seeker Item 1", "SeekerItem1", BuyableItems.Shovel, "Spawned Item for seeker"); ConfigEntry<BuyableItems> val12 = ((BaseUnityPlugin)this).Config.Bind<BuyableItems>("Seeker Item 2", "SeekerItem2", BuyableItems.Flashlight, "Spawned Item for seeker"); ConfigEntry<BuyableItems> val13 = ((BaseUnityPlugin)this).Config.Bind<BuyableItems>("Seeker Item 3", "SeekerItem3", BuyableItems.None, "Spawned Item for seeker"); ConfigEntry<BuyableItems> val14 = ((BaseUnityPlugin)this).Config.Bind<BuyableItems>("Seeker Item 4", "SeekerItem4", BuyableItems.None, "Spawned Item for seeker"); ConfigEntry<BuyableItems> val15 = ((BaseUnityPlugin)this).Config.Bind<BuyableItems>("Hider Item", "HidingItem", BuyableItems.StunGrenade, "Give Hiders some item to help"); ConfigVariables.seekerDelay = val.Value; ConfigVariables.seekerAbilityCD = val2.Value; ConfigVariables.smallFlashlightPower = val3.Value; ConfigVariables.proFlashlightWeightMultiplier = val4.Value; ConfigVariables.proFlashlightBatteryUsageMultiplier = val5.Value; ConfigVariables.seekerSprintMultiplier = val6.Value; ConfigVariables.seekerMaxSprintSpeed = val7.Value; ConfigVariables.daySpeedMultiplier = val8.Value; ConfigVariables.shouldSpawnScrap = val9.Value; ConfigVariables.jumpForce = val10.Value; ConfigVariables.seekerItem1 = val11.Value; ConfigVariables.seekerItem2 = val12.Value; ConfigVariables.seekerItem3 = val13.Value; ConfigVariables.seekerItem4 = val14.Value; ConfigVariables.hiderItem = val15.Value; } } } namespace OPJosMod.HideNSeek.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<T>(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<T>(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); } } } namespace OPJosMod.HideNSeek.Config { public static class ConfigVariables { public static float seekerDelay; public static float seekerAbilityCD; public static int smallFlashlightPower; public static float proFlashlightWeightMultiplier; public static float proFlashlightBatteryUsageMultiplier; public static float seekerSprintMultiplier; public static float seekerMaxSprintSpeed; public static float daySpeedMultiplier; public static bool shouldSpawnScrap; public static BuyableItems seekerItem1; public static BuyableItems seekerItem2; public static BuyableItems seekerItem3; public static BuyableItems seekerItem4; public static BuyableItems hiderItem; public static float jumpForce; } } namespace OPJosMod.HideNSeek.CustomRpc { public static class CompleteRecievedTasks { private static ManualLogSource mls; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } public static void SeekingStarted(string playerIdString) { if (PlayerControllerBPatch.isHider) { if (ConfigVariables.hiderItem == BuyableItems.None) { HUDManagerPatch.CustomDisplayTip("Careful!", "Seeker is on their way!"); } else { HUDManagerPatch.CustomDisplayTip("Seeker is on their way!", "an item dropped at your feet"); } } GeneralUtil.spawnHiderItem(int.Parse(playerIdString)); } public static void MakePlayerWhistle(string playerIdString) { int num = int.Parse(playerIdString); mls.LogMessage((object)$"make player{num} whistle"); PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[num]; PlaySounds.PlayFart(player); if ((int)StartOfRound.Instance.localPlayerController.playerClientId == num) { mls.LogMessage((object)"seeker made u make noise"); } } } [HarmonyPatch(typeof(HUDManager))] internal class HUDManagerPatchForRPC { private static ManualLogSource mls; private static float lastRecieved = Time.time; private static float messageWaitTime = 0.1f; public static void SetLogSource(ManualLogSource logSource) { mls = logSource; } [HarmonyPatch("AddPlayerChatMessageClientRpc")] [HarmonyPrefix] private static void addPlayerChatMessageClientRpcPatch(ref string chatMessage, ref int playerId) { if (MessageCodeUtil.stringContainsMessageCode(chatMessage) && Time.time - lastRecieved > messageWaitTime) { lastRecieved = Time.time; RpcMessageHandler.ReceiveRpcMessage(chatMessage, playerId); } } [HarmonyPatch("AddChatMessage")] [HarmonyPrefix] private static bool addChatMessagePatch(ref string chatMessage) { if (MessageCodeUtil.stringContainsMessageCode(chatMessage)) { return false; } return true; } } public enum MessageTasks { StartedSeeking, MakePlayerWhistle, ErrorNoTask } public static class MessageTaskUtil { public static string GetCode(MessageTasks code) { return code switch { MessageTasks.StartedSeeking => ":StartedSeeking:", MessageTasks.MakePlayerWhistle => ":MakeWhistle:", MessageTasks.ErrorNoTask => ":Error:", _ => ":Error:", }; } 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.StartedSeeking))) { return MessageTasks.StartedSeeking; } if (givenString.Contains(GetCode(MessageTasks.MakePlayerWhistle))) { return MessageTasks.MakePlayerWhistle; } return MessageTasks.ErrorNoTask; } } public enum MessageCodes { Request, Response } public static class MessageCodeUtil { public static string GetCode(MessageCodes code) { return code switch { MessageCodes.Request => ":rpcRequest:", MessageCodes.Response => ":rpcResponse:", _ => ":Error:", }; } public static bool stringContainsMessageCode(string givenString) { return givenString.Contains(GetCode(MessageCodes.Request)) || givenString.Contains(GetCode(MessageCodes.Response)); } public static string returnMessageWithoutCode(string message) { if (stringContainsMessageCode(message)) { int length = GetCode(MessageCodes.Request).Length; return message.Substring(length); } return message; } } public class RpcMessage { public string Message { get; set; } public int FromUser { get; set; } public MessageCodes MessageCode { get; set; } public RpcMessage(string message, int user, MessageCodes code) { Message = message; FromUser = user; MessageCode = code; } public string getMessageWithCode() { return MessageCodeUtil.GetCode(MessageCode) + Message; } } public static class RpcMessageHandler { private static ManualLogSource mls; 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) { if (!(Time.time - lastSentTime > messageWaitTime)) { return; } lastSentTime = Time.time; HUDManager instance = HUDManager.Instance; if ((Object)(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."); } } public static void ReceiveRpcMessage(string message, int 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); handleTask(messageTask, messageWithoutTask); SendRpcResponse(text); } else if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Response))) { mls.LogMessage((object)"got the response that the other clients recieved this message"); } } } public static void SendRpcResponse(string message) { RpcMessage message2 = new RpcMessage(message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Response); SendRpcMessage(message2); } private static void handleTask(MessageTasks task, string message) { switch (task) { case MessageTasks.StartedSeeking: CompleteRecievedTasks.SeekingStarted(message); break; case MessageTasks.MakePlayerWhistle: CompleteRecievedTasks.MakePlayerWhistle(message); break; case MessageTasks.ErrorNoTask: mls.LogError((object)"got an error task"); break; } } } }