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