Please disclose if any significant portion of your mod was created 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 GOIDA v1.0.7
BepInEx\plugins\LCTarotCard\LCTarrotCard.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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 JetBrains.Annotations; using LCTarrotCard.Cards; using LCTarrotCard.Items; using LCTarrotCard.Ressource; using LCTarrotCard.Util; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("LCTarrotCard")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("LCTarrotCard")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9457633A-7E87-4BDB-8892-B9C127F9C677")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.3.0")] namespace LCTarrotCard { [HarmonyPatch] public class Networker : NetworkBehaviour { public static bool AllowExtraLife; private static GameObject _networkPrefab; private static readonly int Closed = Animator.StringToHash("Closed"); private static readonly int Damage = Animator.StringToHash("Damage"); private static readonly int Limp = Animator.StringToHash("Limp"); public static Networker Instance { get; private set; } [ServerRpc(RequireOwnership = false)] public void KillPlayerServerRpc(int playerId, Vector3 velocity, CauseOfDeath causeOfDeath) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) KillPlayerClientRpc(playerId, velocity, causeOfDeath); } [ClientRpc] public void KillPlayerClientRpc(int playerId, Vector3 velocity, CauseOfDeath causeOfDeath) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB obj = StartOfRound.Instance.allPlayerScripts[playerId]; if (obj != null) { obj.KillPlayer(velocity, true, causeOfDeath, 0, default(Vector3)); } } [ServerRpc(RequireOwnership = false)] public void SetShipDoorStateServerRpc(bool opened) { SetShipDoorStateClientRpc(opened); } [ClientRpc] public void SetShipDoorStateClientRpc(bool opened) { HangarShipDoor[] array = Object.FindObjectsOfType<HangarShipDoor>(); foreach (HangarShipDoor val in array) { if (opened) { val.SetDoorOpen(); val.doorPower = 0f; } else { val.SetDoorClosed(); val.doorPower = 100f; } val.shipDoorsAnimator.SetBool(Closed, !opened); } } [ServerRpc(RequireOwnership = false)] public void OpenOrCloseRandomDoorServerRpc(int playerId) { OpenOrCloseRandomDoorClientRpc(playerId, new Random().Next()); } [ClientRpc] public void OpenOrCloseRandomDoorClientRpc(int playerId, int rngSeed) { Random random = new Random(rngSeed); DoorLock[] array = Object.FindObjectsOfType<DoorLock>(); foreach (DoorLock val in array) { if (random.Next(0, 2) == 0) { val.OpenOrCloseDoor(StartOfRound.Instance.allPlayerScripts[playerId]); } } } [ServerRpc(RequireOwnership = false)] public void BreakerOffServerRpc() { BreakerOffClientRpc(); } [ClientRpc] public void BreakerOffClientRpc() { RoundManager.Instance.SwitchPower(false); BreakerBox[] array = Object.FindObjectsOfType<BreakerBox>(); for (int i = 0; i < array.Length; i++) { array[i].SetSwitchesOff(); } } [ServerRpc(RequireOwnership = false)] public void AgroCoilheadOrSpawnServerRpc() { SpringManAI[] array = Object.FindObjectsOfType<SpringManAI>(); int num = 0; SpringManAI[] array2 = array; foreach (SpringManAI val in array2) { if (!((EnemyAI)val).isEnemyDead && ((NetworkBehaviour)val).IsSpawned) { num++; ((EnemyAI)val).SwitchToBehaviourState(1); } if (num >= 2) { return; } } SpawnCoilheadServerRpc(); } [ServerRpc(RequireOwnership = false)] public void SpawnCoilheadServerRpc() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) EnemyVent[] array = Object.FindObjectsOfType<EnemyVent>(); Vector3 position = array[Random.Range(0, array.Length)].floorNode.position; GameObject val = Object.Instantiate<GameObject>(Helper.Enemies.SpringMan.enemyPrefab, position, Quaternion.identity); val.GetComponentInChildren<NetworkObject>().Spawn(true); RoundManager.Instance.SpawnedEnemies.Add((EnemyAI)(object)val.GetComponent<SpringManAI>()); ((EnemyAI)val.GetComponent<SpringManAI>()).SetEnemyOutside(false); ((EnemyAI)val.GetComponent<SpringManAI>()).SwitchToBehaviourState(1); } [ServerRpc(RequireOwnership = false)] public void PopOrSpawnJesterServerRpc(float popDelay) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) bool flag = false; foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies) { JesterAI val = (JesterAI)(object)((spawnedEnemy is JesterAI) ? spawnedEnemy : null); if (val != null && !((EnemyAI)val).isEnemyDead) { flag = true; } } if (!flag) { EnemyVent[] array = Object.FindObjectsOfType<EnemyVent>(); Vector3 position = array[Random.Range(0, array.Length)].floorNode.position; GameObject val2 = Object.Instantiate<GameObject>(Helper.Enemies.Jester.enemyPrefab, position, Quaternion.identity); val2.GetComponentInChildren<NetworkObject>().Spawn(true); RoundManager.Instance.SpawnedEnemies.Add((EnemyAI)(object)val2.GetComponent<JesterAI>()); ((EnemyAI)val2.GetComponent<JesterAI>()).SetEnemyOutside(false); ((EnemyAI)val2.GetComponent<JesterAI>()).SwitchToBehaviourState(1); } ((MonoBehaviour)this).StartCoroutine(PopDelay(popDelay)); } [ServerRpc(RequireOwnership = false)] public void SpawnGiantOrDogServerRpc(int amount) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) GameObject[] array = GameObject.FindGameObjectsWithTag("OutsideAINode"); for (int i = 0; i < amount; i++) { Vector3 position = array[Random.Range(0, array.Length)].transform.position; if (Random.Range(0, 2) == 0) { PluginLogger.Debug("Spawn giant"); GameObject val = Object.Instantiate<GameObject>(Helper.Enemies.ForestGiant.enemyPrefab, position, Quaternion.identity); val.GetComponentInChildren<NetworkObject>().Spawn(true); RoundManager.Instance.SpawnedEnemies.Add((EnemyAI)(object)val.GetComponent<ForestGiantAI>()); ((EnemyAI)val.GetComponent<ForestGiantAI>()).SetEnemyOutside(true); } else { PluginLogger.Debug("Spawn dog"); GameObject val2 = Object.Instantiate<GameObject>(Helper.Enemies.MouthDog.enemyPrefab, position, Quaternion.identity); val2.GetComponentInChildren<NetworkObject>().Spawn(true); RoundManager.Instance.SpawnedEnemies.Add((EnemyAI)(object)val2.GetComponent<MouthDogAI>()); ((EnemyAI)val2.GetComponent<MouthDogAI>()).SetEnemyOutside(true); } } } [ServerRpc(RequireOwnership = false)] public void TeleportRandomEntityServerRpc(Vector3 position, bool inside) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) List<EnemyAI> spawnedEnemies = RoundManager.Instance.SpawnedEnemies; Helper.Shuffle(spawnedEnemies); using IEnumerator<EnemyAI> enumerator = spawnedEnemies.Where((EnemyAI enemy) => !enemy.isEnemyDead && enemy.isOutside == !inside && ((NetworkBehaviour)enemy).IsSpawned).GetEnumerator(); if (enumerator.MoveNext()) { EnemyAI current = enumerator.Current; PluginLogger.Debug("Enemy is outside ? " + current.isOutside + " player inside ? " + inside); string enemyName = current.enemyType.enemyName; Vector3 val = position; PluginLogger.Debug("Tp " + enemyName + " to " + ((object)(Vector3)(ref val)).ToString()); TeleportEnemy(current, position); } } [ServerRpc(RequireOwnership = false)] public void GhostBreatheServerRpc(Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GhostBreatheClientRpc(position); } [ClientRpc] public void GhostBreatheClientRpc(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) AudioSource.PlayClipAtPoint(Assets.GhostBreathe, position, 3f); } [ServerRpc(RequireOwnership = false)] public void TeleportEnemyAwayServerRpc() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies) { Vector3 position = spawnedEnemy.ChooseFarthestNodeFromPosition(((Component)spawnedEnemy).transform.position, false, 0, false, 50, false).position; TeleportEnemy(spawnedEnemy, position); } } [ServerRpc(RequireOwnership = false)] public void TeleportPlayerServerRpc(int playerId, Vector3 position, bool inside = true, bool insideShip = false) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) TeleportPlayerClientRpc(playerId, position, inside, insideShip); } [ClientRpc] public void TeleportPlayerClientRpc(int playerId, Vector3 position, bool inside = true, bool insideShip = false) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; val.StopSinkingServerRpc(); if (Object.op_Implicit((Object)(object)val.currentTriggerInAnimationWith)) { val.currentTriggerInAnimationWith.CancelAnimationExternally(); } val.inSpecialInteractAnimation = false; val.isClimbingLadder = false; val.isInElevator = insideShip; val.isInHangarShipRoom = insideShip; val.isInsideFactory = inside; val.averageVelocity = 0f; val.velocityLastFrame = Vector3.zero; val.TeleportPlayer(position, false, 0f, false, true); val.beamOutParticle.Play(); if (playerId == (int)GameNetworkManager.Instance.localPlayerController.playerClientId) { HUDManager.Instance.ShakeCamera((ScreenShakeType)1); } if (Object.op_Implicit((Object)(object)Object.FindObjectOfType<AudioReverbPresets>())) { if (val.isInsideFactory) { Object.FindObjectOfType<AudioReverbPresets>().audioPresets[2].ChangeAudioReverbForPlayer(val); } else { Object.FindObjectOfType<AudioReverbPresets>().audioPresets[3].ChangeAudioReverbForPlayer(val); } } } [ServerRpc(RequireOwnership = false)] public void SetPlayerHealthServerRpc(int playerId, int health) { SetPlayerHealthClientRpc(playerId, health); } [ClientRpc] public void SetPlayerHealthClientRpc(int playerId, int health) { if (health <= 0) { health = 1; } PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; int health2 = val.health; val.health = health; if (((NetworkBehaviour)val).IsOwner) { HUDManager.Instance.UpdateHealthUI(health, health2 > health); if (health <= 20 && !val.criticallyInjured) { HUDManager.Instance.ShakeCamera((ScreenShakeType)1); val.MakeCriticallyInjured(true); } else if (val.criticallyInjured && health > 20) { val.MakeCriticallyInjured(false); } } if (health2 > health) { return; } if (((NetworkBehaviour)val).IsOwner) { ((MonoBehaviour)this).StartCoroutine(SetPlayerUI(val, health <= 20)); ((UnityEvent)StartOfRound.Instance.LocalPlayerDamagedEvent).Invoke(); val.takingFallDamage = false; if (val.inSpecialInteractAnimation && !val.twoHandedAnimation) { val.playerBodyAnimator.SetTrigger(Damage); } val.specialAnimationWeight = 1f; val.PlayQuickSpecialAnimation(0.7f); } PlayerStats obj = val.playersManager.gameStats.allPlayerStats[val.playerClientId]; obj.damageTaken += health2 - health; val.timeSinceTakingDamage = Time.realtimeSinceStartup; } [ServerRpc(RequireOwnership = false)] public void DamagePlayerServerRpc(int playerId, int damage, Vector3 velocity, CauseOfDeath causeOfDeath) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) DamagePlayerClientRpc(playerId, damage, velocity, causeOfDeath); } [ClientRpc] public void DamagePlayerClientRpc(int playerId, int damage, Vector3 velocity, CauseOfDeath causeOfDeath) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) StartOfRound.Instance.allPlayerScripts[playerId].DamagePlayer(damage, true, true, causeOfDeath, 0, false, velocity); } [ServerRpc(RequireOwnership = false)] public void MultiplyInventoryValueServerRpc(int playerId, float multiplier) { MultiplyInventoryValueClientRpc(playerId, multiplier); } [ClientRpc] public void MultiplyInventoryValueClientRpc(int playerId, float multiplier) { GrabbableObject[] itemSlots = StartOfRound.Instance.allPlayerScripts[playerId].ItemSlots; foreach (GrabbableObject obj in itemSlots) { obj.SetScrapValue((int)((float)obj.scrapValue * multiplier)); } } [ServerRpc(RequireOwnership = false)] public void MultiplyRandomScrapValueServerRpc(float multiplier) { MultiplyRandomScrapValueClientRpc(multiplier, new Random().Next()); } [ClientRpc] public void MultiplyRandomScrapValueClientRpc(float multiplier, int randomSeed) { Random random = new Random(randomSeed); GrabbableObject[] array = Object.FindObjectsOfType<GrabbableObject>(); foreach (GrabbableObject val in array) { if (((Behaviour)val).enabled && val.itemProperties.isScrap && val.scrapValue > 0 && random.Next(0, 5) == 0) { val.SetScrapValue((int)((float)val.scrapValue * multiplier)); } } } [ServerRpc(RequireOwnership = false)] public void RevivePlayerServerRpc(int playerId) { RevivePlayerClientRpc(playerId); } [ClientRpc] public void RevivePlayerClientRpc(int playerId) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if (!val.isPlayerDead && !val.isPlayerControlled) { return; } val.ResetPlayerBloodObjects(true); val.isClimbingLadder = false; val.clampLooking = false; val.inVehicleAnimation = false; val.disableMoveInput = false; val.ResetZAndXRotation(); ((Collider)val.thisController).enabled = true; val.health = 100; val.hasBeenCriticallyInjured = false; val.disableLookInput = false; val.disableInteract = false; if (val.isPlayerDead) { val.isPlayerDead = false; val.isPlayerControlled = true; val.isInElevator = true; val.isInHangarShipRoom = true; val.isInsideFactory = false; val.parentedToElevatorLastFrame = false; val.overrideGameOverSpectatePivot = null; StartOfRound.Instance.SetPlayerObjectExtrapolate(false); val.TeleportPlayer(StartOfRound.Instance.playerSpawnPositions[0].position, false, 0f, false, true); val.setPositionOfDeadPlayer = false; val.DisablePlayerModel(StartOfRound.Instance.allPlayerObjects[playerId], true, true); ((Behaviour)val.helmetLight).enabled = false; val.Crouch(false); val.criticallyInjured = false; if (Object.op_Implicit((Object)(object)val.playerBodyAnimator)) { val.playerBodyAnimator.SetBool(Limp, false); } val.bleedingHeavily = false; val.activatingItem = false; val.twoHanded = false; val.inShockingMinigame = false; val.inSpecialInteractAnimation = false; val.freeRotationInInteractAnimation = 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 = 100; val.mapRadarDotAnimator.SetBool("dead", false); val.externalForceAutoFade = Vector3.zero; if (((NetworkBehaviour)val).IsOwner) { HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false); val.hasBegunSpectating = false; HUDManager.Instance.RemoveSpectateUI(); HUDManager.Instance.gameOverAnimator.SetTrigger("revive"); val.hinderedMultiplier = 1f; val.isMovementHindered = 0; val.sourcesCausingSinking = 0; val.reverbPreset = StartOfRound.Instance.shipReverb; } } if (((NetworkBehaviour)val).IsOwner) { SoundManager.Instance.earsRingingTimer = 0f; val.bleedingHeavily = false; val.criticallyInjured = false; val.playerBodyAnimator.SetBool(Limp, false); val.health = 100; HUDManager.Instance.UpdateHealthUI(100, false); val.spectatedPlayerScript = null; ((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false; StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, val); ((MonoBehaviour)this).StartCoroutine(SetPlayerUI(val)); } val.voiceMuffledByEnemy = false; SoundManager.Instance.playerVoicePitchTargets[playerId] = 1f; SoundManager.Instance.SetPlayerPitch(1f, playerId); if (Object.op_Implicit((Object)(object)val.currentVoiceChatIngameSettings)) { if (!Object.op_Implicit((Object)(object)val.currentVoiceChatIngameSettings.voiceAudio)) { val.currentVoiceChatIngameSettings.InitializeComponents(); } if (!Object.op_Implicit((Object)(object)val.currentVoiceChatIngameSettings.voiceAudio)) { return; } ((Component)val.currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false; } RagdollGrabbableObject[] array = Object.FindObjectsOfType<RagdollGrabbableObject>(); foreach (RagdollGrabbableObject val2 in array) { if (val2.ragdoll.playerObjectId != playerId) { continue; } if (!((GrabbableObject)val2).isHeld) { if (((NetworkBehaviour)this).IsServer) { if (((NetworkBehaviour)val2).NetworkObject.IsSpawned) { ((NetworkBehaviour)val2).NetworkObject.Despawn(true); } else { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } else if (Object.op_Implicit((Object)(object)((GrabbableObject)val2).playerHeldBy)) { ((GrabbableObject)val2).playerHeldBy.DropAllHeldItems(true, false); } } DeadBodyInfo[] array2 = Object.FindObjectsOfType<DeadBodyInfo>(); foreach (DeadBodyInfo val3 in array2) { if (val3.playerObjectId == playerId) { Object.Destroy((Object)(object)((Component)val3).gameObject); } } StartOfRound instance = StartOfRound.Instance; instance.livingPlayers++; StartOfRound.Instance.allPlayersDead = false; StartOfRound.Instance.UpdatePlayerVoiceEffects(); } [ServerRpc(RequireOwnership = false)] public void AllowExtraLifeServerRpc() { AllowExtraLifeClientRpc(allow: true); } [ClientRpc] public void AllowExtraLifeClientRpc(bool allow) { AllowExtraLife = allow; } [ServerRpc(RequireOwnership = false)] public void ExtraLifeServerRpc(int playerId) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (AllowExtraLife) { PluginLogger.Debug("extra life " + StartOfRound.Instance.allPlayerScripts[playerId].playerUsername); AllowExtraLifeClientRpc(allow: false); TeleportPlayerServerRpc(playerId, StartOfRound.Instance.playerSpawnPositions[0].position, inside: false, insideShip: true); ExtraLifeClientRpc(playerId); } } [ClientRpc] public void ExtraLifeClientRpc(int playerId) { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; val.health = 100; val.isPlayerDead = false; val.MakeCriticallyInjured(false); if (((NetworkBehaviour)val).IsOwner) { ((MonoBehaviour)this).StartCoroutine(SetPlayerUI(val)); HUDManager.Instance.UpdateHealthUI(100, false); } if (((NetworkBehaviour)StartOfRound.Instance.allPlayerScripts[playerId]).IsOwner) { HUDManager.Instance.DisplayTip("Extra life", "Thanks to the high priestess card, you are given an extra chance to live", false, false, "LC_Tip1"); } } private static IEnumerator SetPlayerUI(PlayerControllerB player, bool critical = false) { yield return (object)new WaitForFixedUpdate(); HUDManager.Instance.UpdateHealthUI(player.health, false); player.MakeCriticallyInjured(critical); } public static void TeleportEnemy(EnemyAI enemy, Vector3 position, bool exitEnter = false, bool outside = false) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (exitEnter) { enemy.SetEnemyOutside(outside); } if (((NetworkBehaviour)enemy).OwnerClientId != GameNetworkManager.Instance.localPlayerController.actualClientId) { enemy.ChangeOwnershipOfEnemy(GameNetworkManager.Instance.localPlayerController.actualClientId); } Vector3 position2 = enemy.ChooseClosestNodeToPosition(position, false, 0).position; enemy.serverPosition = position2; ((Component)enemy).transform.position = enemy.serverPosition; enemy.agent.Warp(enemy.serverPosition); enemy.SyncPositionToClients(); } private static IEnumerator PopDelay(float delay) { yield return (object)new WaitForSeconds(delay); PluginLogger.Debug("Popping jesters"); foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies) { JesterAI val = (JesterAI)(object)((spawnedEnemy is JesterAI) ? spawnedEnemy : null); if (val != null && !((EnemyAI)val).isEnemyDead) { ((EnemyAI)val).SwitchToBehaviourState(2); } } } public override void OnNetworkSpawn() { if ((Object)(object)NetworkManager.Singleton != (Object)null && (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer)) { Networker instance = Instance; if (instance != null) { ((Component)instance).gameObject.GetComponent<NetworkObject>().Despawn(true); } } Instance = this; ((NetworkBehaviour)this).OnNetworkSpawn(); } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void SpawnNetHandler() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Object.Instantiate<GameObject>(_networkPrefab, Vector3.zero, Quaternion.identity).GetComponent<NetworkObject>().Spawn(false); } } [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPostfix] private static void Init() { if (!((Object)(object)_networkPrefab != (Object)null)) { _networkPrefab = Assets.Bundle.LoadAsset<GameObject>("Assets/Tarrot/Networker.prefab"); _networkPrefab.AddComponent<Networker>(); NetworkManager.Singleton.AddNetworkPrefab(_networkPrefab); } } } [BepInPlugin("LCTarotCard", "Phasmophobia Tarot Card", "1.0.3")] public class Plugin : BaseUnityPlugin { public static Plugin Instance; internal static KeyboardShortcut DebugBtn = new KeyboardShortcut((KeyCode)96, Array.Empty<KeyCode>()); private Harmony harmony; public ManualLogSource logger; private void Awake() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (!((Object)(object)Instance != (Object)null)) { Instance = this; logger = Logger.CreateLogSource("LCTarotCard"); harmony = new Harmony("LCTarotCard"); Assets.Load(); AllCards.Init(); harmony.PatchAll(); NetcodePatcher(); } } private static void NetcodePatcher() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } } } [HarmonyPatch(typeof(PlayerControllerB))] internal class Test { [HarmonyPatch("Update")] [HarmonyPostfix] private static void TestPatch(PlayerControllerB __instance) { } } public static class PluginLogger { public static bool ShowDebug = true; public static void Debug(object o) { if (ShowDebug) { Plugin.Instance.logger.LogDebug((object)("[DEBUG] " + o)); } } public static void Info(object o) { Plugin.Instance.logger.LogInfo(o); } public static void Error(object o) { Plugin.Instance.logger.LogError((object)("[ERROR] " + o)); } public static void Warning(object o) { Plugin.Instance.logger.LogWarning((object)("[WARNING] " + o)); } } public static class PluginConstants { public const string PLUGIN_GUID = "LCTarotCard"; public const string PLUGIN_NAME = "Phasmophobia Tarot Card"; public const string PLUGIN_VERSION = "1.0.3"; internal const bool DEBUG_MODE = false; } } namespace LCTarrotCard.Util { [HarmonyPatch] public class Helper { public static class Enemies { public static EnemyType Baboon; public static EnemyType Slime; public static EnemyType BushWolf; public static EnemyType Butler; public static EnemyType ButlerBees; public static EnemyType Centipede; public static EnemyType ClaySurgeon; public static EnemyType Crawler; public static EnemyType DocileLocust; public static EnemyType Manticoil; public static EnemyType DressGirl; public static EnemyType FlowerMan; public static EnemyType FlowerSnake; public static EnemyType ForestGiant; public static EnemyType HoarderBug; public static EnemyType Jester; public static EnemyType LassoMan; public static EnemyType Masked; public static EnemyType MouthDog; public static EnemyType Nutcracker; public static EnemyType Puffer; public static EnemyType RadMech; public static EnemyType RedLocust; public static EnemyType RedPill; public static EnemyType Spider; public static EnemyType SandWorm; public static EnemyType SpringMan; public static readonly List<EnemyType> AllEnemies = new List<EnemyType>(); public static readonly List<EnemyType> SpawnableEnemies = new List<EnemyType>(); [CanBeNull] public static EnemyType GetByName(string name) { return ((IEnumerable<EnemyType>)AllEnemies).FirstOrDefault((Func<EnemyType, bool>)((EnemyType enemy) => enemy.enemyName == name)); } } private static readonly Random Rng = new Random(); public static void InitEnemies() { PluginLogger.Debug("InitEnemies"); EnemyType[] array = Resources.FindObjectsOfTypeAll<EnemyType>().Concat(Object.FindObjectsByType<EnemyType>((FindObjectsInactive)1, (FindObjectsSortMode)1)).ToArray(); PluginLogger.Debug("Found " + array.Length + " enemies"); EnemyType[] array2 = array; foreach (EnemyType val in array2) { PluginLogger.Debug("Found enemy : " + val.enemyName); if (!Enemies.AllEnemies.Contains(val)) { Enemies.AllEnemies.Add(val); if (val.enemyName != "Lasso" || val.enemyName != "Red pill") { Enemies.SpawnableEnemies.Add(val); } } switch (val.enemyName) { case "Baboon hawk": Enemies.Baboon = val; break; case "Blob": Enemies.Slime = val; break; case "Bush Wolf": Enemies.BushWolf = val; break; case "Butler": Enemies.Butler = val; break; case "Butler Bees": Enemies.ButlerBees = val; break; case "Centipede": Enemies.Centipede = val; break; case "Clay Surgeon": Enemies.ClaySurgeon = val; break; case "Crawler": Enemies.Crawler = val; break; case "Docile Locust Bees": Enemies.DocileLocust = val; break; case "Manticoil": Enemies.Manticoil = val; break; case "Girl": Enemies.DressGirl = val; break; case "Flowerman": Enemies.FlowerMan = val; break; case "Tulip Snake": Enemies.FlowerSnake = val; break; case "ForestGiant": Enemies.ForestGiant = val; break; case "Hoarding bug": Enemies.HoarderBug = val; break; case "Jester": Enemies.Jester = val; break; case "Lasso": Enemies.LassoMan = val; break; case "Masked": Enemies.Masked = val; break; case "MouthDog": Enemies.MouthDog = val; break; case "Nutcracker": Enemies.Nutcracker = val; break; case "Puffer": Enemies.Puffer = val; break; case "RadMech": Enemies.RadMech = val; break; case "Red Locust Bees": Enemies.RedLocust = val; break; case "Red pill": Enemies.RedPill = val; break; case "Bunker Spider": Enemies.Spider = val; break; case "Earth Leviathan": Enemies.SandWorm = val; break; case "Spring": Enemies.SpringMan = val; break; } } } public static void Shuffle<T>(IList<T> list) { int num = list.Count; while (num > 1) { num--; int num2 = Rng.Next(num + 1); int index = num2; int index2 = num; T value = list[num]; T value2 = list[num2]; list[index] = value; list[index2] = value2; } } public static GameObject ClosestAINode(Vector3 position, bool inside) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) GameObject[] obj = (inside ? GameObject.FindGameObjectsWithTag("AINode") : GameObject.FindGameObjectsWithTag("OutsideAINode")); GameObject result = null; float num = float.MaxValue; GameObject[] array = obj; foreach (GameObject val in array) { float num2 = Vector3.Distance(val.transform.position, position); if (num2 < num) { num = num2; result = val; } } return result; } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void InitEnemiesPatch() { InitEnemies(); } } public enum Planet { Experimentation, Assurance, Vow, Gordion, March, Adamance, Rend, Dine, Offense, Titan, Artifice, Liquidation, Embrion } public class SpawnRarity { private readonly int defaultValue; private readonly Item item; private readonly Dictionary<Planet, int> rarities = new Dictionary<Planet, int>(); public SpawnRarity(int baseValue, Item itemIn) { item = itemIn; defaultValue = baseValue; foreach (Planet value in Enum.GetValues(typeof(Planet))) { rarities.Add(value, baseValue); } } public int GetRarityFor(Planet planet) { return rarities[planet]; } public int GetRarityFor(int planet) { return rarities.Values.ToList()[planet]; } public void SetValues(int experimentation = -1, int assurance = -1, int vow = -1, int march = -1, int offense = -1, int adamance = -1, int rend = -1, int dine = -1, int titan = -1, int artifice = -1, int embrion = -1) { rarities[Planet.Experimentation] = experimentation; rarities[Planet.Assurance] = assurance; rarities[Planet.Vow] = vow; rarities[Planet.March] = march; rarities[Planet.Offense] = offense; rarities[Planet.Adamance] = adamance; rarities[Planet.Rend] = rend; rarities[Planet.Dine] = dine; rarities[Planet.Titan] = titan; rarities[Planet.Artifice] = artifice; rarities[Planet.Embrion] = embrion; } public void CopyRaritiesFrom(SpawnRarity other) { rarities[Planet.Experimentation] = other.rarities[Planet.Experimentation]; rarities[Planet.Assurance] = other.rarities[Planet.Assurance]; rarities[Planet.Vow] = other.rarities[Planet.Vow]; rarities[Planet.March] = other.rarities[Planet.March]; rarities[Planet.Offense] = other.rarities[Planet.Offense]; rarities[Planet.Adamance] = other.rarities[Planet.Adamance]; rarities[Planet.Rend] = other.rarities[Planet.Rend]; rarities[Planet.Dine] = other.rarities[Planet.Dine]; rarities[Planet.Titan] = other.rarities[Planet.Titan]; rarities[Planet.Artifice] = other.rarities[Planet.Artifice]; rarities[Planet.Embrion] = other.rarities[Planet.Embrion]; } public SpawnableItemWithRarity GetSpawnableItemForPlanet(Planet planet) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return new SpawnableItemWithRarity { spawnableItem = item, rarity = AccessRaritySafe((int)planet) }; } public SpawnableItemWithRarity GetSpawnableItemForPlanet(int planet) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown return new SpawnableItemWithRarity { spawnableItem = item, rarity = AccessRaritySafe(planet) }; } private int AccessRaritySafe(int planet) { try { return rarities.Values.ToList()[planet]; } catch (Exception) { } return defaultValue; } public void ApplySpawnRarity(SelectableLevel level) { level.spawnableScrap.Add(GetSpawnableItemForPlanet(level.levelID)); } } } namespace LCTarrotCard.Ressource { public static class Assets { public static class Materials { public static Material CardDeathMat; public static Material CardHangedMat; public static Material CardPriestessMat; public static Material CardDevilMat; public static Material CardFoolMat; public static Material CardHermitMat; public static Material CardMoonMat; public static Material CardSunMat; public static Material CardTowerMat; public static Material CardWheelMat; public static Material BurnAqua; public static Material BurnBlue; public static Material BurnGreen; public static Material BurnPurple; public static Material BurnRed; public static Material BurnWhite; public static Material BurnYellow; } internal static AssetBundle Bundle; public static Item TarotItem; public static GameObject SingleTarotCard; public static readonly List<AudioClip> PullCardClips = new List<AudioClip>(); public static AudioClip FoolCardSound; public static AudioClip GhostBreathe; public static SpawnRarity TarotRarity; public static void Load() { if (LoadBundle()) { LoadAssets(); InitSpawns(); } } private static bool LoadBundle() { Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("LCTarrotCard.Ressource.tarrotbundle"); if (manifestResourceStream == null) { PluginLogger.Error("Cannot load the asset bundle"); return false; } Bundle = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)Bundle != (Object)null) { return true; } PluginLogger.Error("Cannot load the asset bundle"); return false; } private static void LoadAssets() { TarotItem = LoadAsset<Item>("TarrotCard.asset"); TarotBehaviour tarotBehaviour = TarotItem.spawnPrefab.AddComponent<TarotBehaviour>(); ((GrabbableObject)tarotBehaviour).grabbable = true; ((GrabbableObject)tarotBehaviour).grabbableToEnemies = true; ((GrabbableObject)tarotBehaviour).itemProperties = TarotItem; SingleTarotCard = LoadAsset<GameObject>("single_card_prefab.prefab"); PullCardClips.Add(LoadAsset<AudioClip>("Sound/tarot_draw1.ogg")); PullCardClips.Add(LoadAsset<AudioClip>("Sound/tarot_draw2.ogg")); PullCardClips.Add(LoadAsset<AudioClip>("Sound/tarot_draw3.ogg")); FoolCardSound = LoadAsset<AudioClip>("Sound/fool.ogg"); GhostBreathe = LoadAsset<AudioClip>("Sound/breathe.ogg"); LoadMaterials(); } private static void LoadMaterials() { Materials.CardDeathMat = LoadAsset<Material>("Cards/DeathMat.mat"); Materials.CardHangedMat = LoadAsset<Material>("Cards/HangedManMat.mat"); Materials.CardPriestessMat = LoadAsset<Material>("Cards/HighPreistessMat.mat"); Materials.CardDevilMat = LoadAsset<Material>("Cards/TheDevilMat.mat"); Materials.CardFoolMat = LoadAsset<Material>("Cards/TheFoolMat.mat"); Materials.CardHermitMat = LoadAsset<Material>("Cards/TheHermitMat.mat"); Materials.CardMoonMat = LoadAsset<Material>("Cards/TheMoonMat.mat"); Materials.CardSunMat = LoadAsset<Material>("Cards/TheSunMat.mat"); Materials.CardTowerMat = LoadAsset<Material>("Cards/TowerMat.mat"); Materials.CardWheelMat = LoadAsset<Material>("Cards/WheelMat.mat"); Materials.BurnAqua = LoadAsset<Material>("Burn/AquaBurn.mat"); Materials.BurnBlue = LoadAsset<Material>("Burn/BlueBurn.mat"); Materials.BurnGreen = LoadAsset<Material>("Burn/GreenBurn.mat"); Materials.BurnPurple = LoadAsset<Material>("Burn/PurpleBurn.mat"); Materials.BurnRed = LoadAsset<Material>("Burn/RedBurn.mat"); Materials.BurnWhite = LoadAsset<Material>("Burn/WhiteBurn.mat"); Materials.BurnYellow = LoadAsset<Material>("Burn/YellowBurn.mat"); } private static void InitSpawns() { TarotRarity = new SpawnRarity(17, TarotItem); TarotRarity.SetValues(12, -1, 19, 21, -1, 22, 22, 23, 30, 25, 20); } private static T LoadAsset<T>(string assetPath) where T : Object { return Bundle.LoadAsset<T>("Assets/Tarrot/" + assetPath); } } [HarmonyPatch(typeof(GameNetworkManager))] internal class NetworkPatcher { [HarmonyPatch("Start")] [HarmonyPostfix] private static void RegisterNetworkPrefab() { NetworkManager component = ((Component)GameNetworkManager.Instance).GetComponent<NetworkManager>(); component.AddNetworkPrefab(Assets.TarotItem.spawnPrefab); component.AddNetworkPrefab(Assets.SingleTarotCard); } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatcher { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void RegisterItemsPatch(StartOfRound __instance) { SelectableLevel[] levels = __instance.levels; foreach (SelectableLevel level in levels) { Assets.TarotRarity.ApplySpawnRarity(level); } RegisterItem(Assets.TarotItem, __instance); } private static void RegisterItem(Item item, StartOfRound manager) { if (!manager.allItemsList.itemsList.Contains(item)) { manager.allItemsList.itemsList.Add(item); } } } } namespace LCTarrotCard.Patches { [HarmonyPatch(typeof(PlayerControllerB))] public class PlayerControllerBPatch { [HarmonyPatch("KillPlayer")] [HarmonyPrefix] private static bool AllowExtraLife(PlayerControllerB __instance) { if (!Networker.AllowExtraLife || !((NetworkBehaviour)__instance).IsOwner) { return true; } PluginLogger.Debug("Allowing extra life for player " + __instance.playerUsername); Networker.Instance.ExtraLifeServerRpc((int)__instance.playerClientId); return false; } } } namespace LCTarrotCard.Items { public class TarotBehaviour : GrabbableObject { private readonly AnimationCurve controlCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 0f, 0f, 0f, 0.5f, 0.5f), new Keyframe(1f, 1f, 0f, 0f, 0.5f, 0.5f) }); private int cardLeft = 10; private GameObject currentCard; private Card currentCardProperties; private bool drawingCoroutinePlaying; private bool isDrawingCard; private AudioSource itemAudio; private Vector3 originalCardScale; private PlayerControllerB playerWhoDrew; public override void Start() { //IL_0023: 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) ((GrabbableObject)this).Start(); itemAudio = ((Component)this).gameObject.GetComponent<AudioSource>(); originalCardScale = ((Component)this).gameObject.transform.localScale; } public override void ItemActivate(bool used, bool buttonDown = true) { if (!base.deactivated && StartOfRound.Instance.shipHasLanded && ((NetworkBehaviour)this).IsOwner && buttonDown && !isDrawingCard && base.isHeld && !((Object)(object)base.playerHeldBy == (Object)null) && cardLeft > 0) { isDrawingCard = true; DrawCardServerRpc(base.playerHeldBy.playerClientId); } } public override void SetControlTipsForItem() { List<string> list = new List<string>(base.itemProperties.toolTips); if (cardLeft > 0) { list.Add(cardLeft + " card" + ((cardLeft == 1) ? "" : "s") + " left"); } HUDManager.Instance.ChangeControlTipMultiple(list.ToArray(), true, base.itemProperties); } public void StartDrawingCard(int pulledCard) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)playerWhoDrew == (Object)null) { PluginLogger.Error("Trying to pull a card with a null player"); DestroyAfterDrawing(); return; } if (pulledCard < 0 || pulledCard >= AllCards.GetAllCardsAsList().Count) { PluginLogger.Error("Trying to pull a card with an invalid index"); DestroyAfterDrawing(); return; } cardLeft--; PluginLogger.Debug("Card left : " + cardLeft); ((GrabbableObject)this).SetControlTipsForItem(); if (cardLeft > 0) { float num = (float)cardLeft * 0.1f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(originalCardScale.x, originalCardScale.y * num, originalCardScale.z); ((Component)this).gameObject.transform.localScale = val; base.originalScale = val; } else { ((Component)((Component)this).gameObject.transform.GetChild(0)).gameObject.SetActive(false); } if (!drawingCoroutinePlaying) { Type type = AllCards.GetAllCardsAsList()[pulledCard]; currentCard = Object.Instantiate<GameObject>(Assets.SingleTarotCard, ((Component)this).gameObject.transform); Transform transform = currentCard.transform; transform.localEulerAngles += new Vector3(180f, 0f, 0f); PluginLogger.Debug("Card with type " + type.Name); currentCardProperties = (Card)Activator.CreateInstance(type, currentCard, itemAudio); currentCardProperties.InitCard(); ((MonoBehaviour)this).StartCoroutine(DrawingCoroutine()); } } private IEnumerator DrawingCoroutine() { drawingCoroutinePlaying = true; ((MonoBehaviour)this).StartCoroutine(currentCardProperties.CardPullingCoroutine()); yield return (object)new WaitForSeconds(0.5f); Vector3 initPos = currentCard.transform.localPosition; Vector3 endPos = currentCard.transform.localPosition + new Vector3(0.2f, 0f, 0f); float delta = 0f; while (delta < 0.5f) { currentCard.transform.localPosition = Vector3.Lerp(initPos, endPos, controlCurve.Evaluate(delta * 2f)); delta += Time.deltaTime; yield return null; } yield return (object)new WaitForSeconds(1.1f); if (((NetworkBehaviour)this).IsOwner) { try { currentCardProperties.ExecuteEffect(playerWhoDrew); } catch (Exception ex) { PluginLogger.Error("Error while executing card effect : " + ex); } } yield return (object)new WaitForSeconds(1f); drawingCoroutinePlaying = false; EndDrawingCard(); } public void EndDrawingCard() { if (!drawingCoroutinePlaying) { DestroyAfterDrawing(); } } private void DestroyAfterDrawing() { playerWhoDrew = null; if (Object.op_Implicit((Object)(object)currentCard)) { Object.Destroy((Object)(object)currentCard); } currentCardProperties = null; if (cardLeft <= 0) { DestroyServerRpc(); } isDrawingCard = false; } private void DestroyLocalClient() { itemAudio.volume = 0f; ((GrabbableObject)this).DestroyObjectInHand(base.playerHeldBy); base.deactivated = true; } [ServerRpc] public void DestroyServerRpc() { if (!((NetworkBehaviour)this).IsHost) { DestroyLocalClient(); } DestroyClientRpc(); } [ClientRpc] public void DestroyClientRpc() { DestroyLocalClient(); } [ServerRpc] public void DrawCardServerRpc(ulong playerWhoPulled) { Type item = AllCards.PullRandomCard(); int pulledCard = AllCards.GetAllCardsAsList().IndexOf(item); DrawCardClientRpc(playerWhoPulled, pulledCard); } [ClientRpc] public void DrawCardClientRpc(ulong playerWhoPulled, int pulledCard) { isDrawingCard = true; playerWhoDrew = StartOfRound.Instance.allPlayerScripts[playerWhoPulled]; if ((Object)(object)playerWhoDrew == (Object)null) { PluginLogger.Error("Player is null when drawing card"); } StartDrawingCard(pulledCard); } } } namespace LCTarrotCard.Cards { public static class AllCards { public static class ProbabilityTable { public static int TowerCard = 20; public static int WheelCard = 20; public static int SunCard = 5; public static int MoonCard = 5; public static int DevilCard = 10; public static int HermitCard = 10; public static int HighPriestessCard = 2; public static int DeathCard = 10; public static int HangedManCard = 1; public static int FoolCard = 17; } public static readonly Dictionary<Type, int> AllCardsWeighted = new Dictionary<Type, int>(); private static int _totalWeight; internal static void Init() { AllCardsWeighted.Add(typeof(TowerCard), ProbabilityTable.TowerCard); AllCardsWeighted.Add(typeof(WheelCard), ProbabilityTable.WheelCard); AllCardsWeighted.Add(typeof(SunCard), ProbabilityTable.SunCard); AllCardsWeighted.Add(typeof(MoonCard), ProbabilityTable.MoonCard); AllCardsWeighted.Add(typeof(DevilCard), ProbabilityTable.DevilCard); AllCardsWeighted.Add(typeof(HermitCard), ProbabilityTable.HermitCard); AllCardsWeighted.Add(typeof(HighPriestessCard), ProbabilityTable.HighPriestessCard); AllCardsWeighted.Add(typeof(DeathCard), ProbabilityTable.DeathCard); AllCardsWeighted.Add(typeof(HangedManCard), ProbabilityTable.HangedManCard); AllCardsWeighted.Add(typeof(FoolCard), ProbabilityTable.FoolCard); RecalculateTotalWeight(); } public static void RegisterCard(Type cardType, int weight) { if (!typeof(Card).IsAssignableFrom(cardType)) { PluginLogger.Warning("Trying to register a non-card type (type : " + cardType.Name + ")"); return; } if (AllCardsWeighted.ContainsKey(cardType)) { PluginLogger.Warning("Trying to register a card that is already registered (type : " + cardType.Name + ")"); return; } AllCardsWeighted.Add(cardType, weight); RecalculateTotalWeight(); } public static List<Type> GetAllCardsAsList() { return new List<Type>(AllCardsWeighted.Keys); } private static void RecalculateTotalWeight() { _totalWeight = 0; foreach (int value in AllCardsWeighted.Values) { _totalWeight += value; } } public static Type PullRandomCard() { int num = 0; int num2 = Random.Range(0, _totalWeight + 1); Type type = typeof(object); foreach (KeyValuePair<Type, int> item in AllCardsWeighted) { if (item.Value + num >= num2) { type = item.Key; break; } num += item.Value; } PluginLogger.Debug(type.Name); if (typeof(Card).IsAssignableFrom(type)) { return type; } PluginLogger.Warning("Trying to pull a card with a non-card type (type : " + type.Name + ")"); return typeof(FoolCard); } } public abstract class Card { protected static readonly AnimationCurve ControlCurve = new AnimationCurve((Keyframe[])(object)new Keyframe[2] { new Keyframe(0f, 0f, 0f, 0f, 0.5f, 0.5f), new Keyframe(1f, 1f, 0f, 0f, 0f, 0f) }); protected readonly AudioSource cardAudio; protected readonly GameObject cardPrefab; protected Card(GameObject cardPrefab, AudioSource audioSource) { this.cardPrefab = cardPrefab; cardAudio = audioSource; } public virtual void InitCard() { Renderer component = cardPrefab.GetComponent<Renderer>(); Material[] materials = component.materials; materials[0] = GetCardMaterial(); component.materials = materials; } public abstract Material GetCardMaterial(); public abstract Material GetCardBurn(); public abstract void ExecuteEffect(PlayerControllerB playerWhoDrew); public virtual IEnumerator CardPullingCoroutine() { cardAudio.PlayOneShot(Assets.PullCardClips[Random.Range(0, Assets.PullCardClips.Count)]); yield return (object)new WaitForSeconds(2.2f); Renderer cardRenderer = cardPrefab.GetComponent<Renderer>(); Material initMat0 = cardRenderer.materials[0]; Material initMat1 = cardRenderer.materials[1]; Material initMat2 = cardRenderer.materials[2]; float delta = 0f; while (delta < 0.3f) { cardRenderer.materials[0].Lerp(initMat0, GetCardBurn(), delta / 0.3f); cardRenderer.materials[1].Lerp(initMat1, GetCardBurn(), delta / 0.3f); cardRenderer.materials[2].Lerp(initMat2, GetCardBurn(), delta / 0.3f); delta += Time.deltaTime; yield return null; } yield return (object)new WaitForSeconds(0.2f); Vector3 initScale = cardPrefab.transform.localScale; float delta2 = 0f; while (delta2 < 0.3f) { cardPrefab.transform.localScale = initScale * (1f - ControlCurve.Evaluate(delta2 / 0.3f)); delta2 += Time.deltaTime; yield return null; } cardPrefab.transform.localScale = Vector3.zero; } } public class DeathCard : Card { public DeathCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardDeathMat; } public override Material GetCardBurn() { return Assets.Materials.BurnPurple; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { int num = Random.Range(0, 4); switch (num) { case 0: PluginLogger.Debug("Agroing coilhead or spawning one"); Networker.Instance.AgroCoilheadOrSpawnServerRpc(); break; case 1: PluginLogger.Debug("Pop or spawning jester"); Networker.Instance.PopOrSpawnJesterServerRpc(30f); break; default: PluginLogger.Debug("Spawning giant or dog"); Networker.Instance.SpawnGiantOrDogServerRpc(num - 1); break; } } } public class DevilCard : Card { public DevilCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardDevilMat; } public override Material GetCardBurn() { return Assets.Materials.BurnRed; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) int num = Random.Range(0, 4); if (!playerWhoDrew.isPlayerDead && playerWhoDrew.isPlayerControlled) { if (num <= 2) { Vector3 position = ((Component)playerWhoDrew).transform.position + ((Component)playerWhoDrew.gameplayCamera).transform.forward * 5f; Networker.Instance.TeleportRandomEntityServerRpc(position, playerWhoDrew.isInsideFactory); } else { ((MonoBehaviour)playerWhoDrew).StartCoroutine(WaitAndBlow(playerWhoDrew)); } } } private static IEnumerator WaitAndBlow(PlayerControllerB player) { yield return (object)new WaitForSeconds(2.5f); Networker.Instance.GhostBreatheServerRpc(((Component)player).transform.position); } } public class FoolCard : Card { private readonly Material[] allCardMat = (Material[])(object)new Material[9] { Assets.Materials.CardTowerMat, Assets.Materials.CardDeathMat, Assets.Materials.CardWheelMat, Assets.Materials.CardSunMat, Assets.Materials.CardMoonMat, Assets.Materials.CardDevilMat, Assets.Materials.CardHermitMat, Assets.Materials.CardPriestessMat, Assets.Materials.CardHangedMat }; private Material cardToMimic; public FoolCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override void InitCard() { cardToMimic = allCardMat[Random.Range(0, allCardMat.Length)]; base.InitCard(); } public override Material GetCardMaterial() { return cardToMimic; } public override Material GetCardBurn() { return Assets.Materials.BurnPurple; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { } public override IEnumerator CardPullingCoroutine() { cardAudio.PlayOneShot(Assets.PullCardClips[Random.Range(0, Assets.PullCardClips.Count)]); Renderer cardRenderer = cardPrefab.GetComponent<Renderer>(); yield return (object)new WaitForSeconds(1.8f); Material initMat = cardRenderer.materials[0]; Material initMat3 = cardRenderer.materials[1]; Material initMat5 = cardRenderer.materials[2]; cardAudio.PlayOneShot(Assets.FoolCardSound); float delta3 = 0f; while (delta3 < 0.15f) { cardRenderer.materials[0].Lerp(initMat, GetCardBurn(), delta3 / 0.3f); cardRenderer.materials[1].Lerp(initMat3, GetCardBurn(), delta3 / 0.3f); cardRenderer.materials[2].Lerp(initMat5, GetCardBurn(), delta3 / 0.3f); delta3 += Time.deltaTime; yield return null; } Material trMat0 = cardRenderer.materials[0]; Material trMat1 = cardRenderer.materials[1]; Material trMat2 = cardRenderer.materials[2]; delta3 = 0f; while (delta3 < 0.15f) { cardRenderer.materials[0].Lerp(trMat0, Assets.Materials.CardFoolMat, delta3 / 0.3f); cardRenderer.materials[1].Lerp(trMat1, initMat3, delta3 / 0.3f); cardRenderer.materials[2].Lerp(trMat2, initMat5, delta3 / 0.3f); delta3 += Time.deltaTime; yield return null; } Material[] materials = (Material[])(object)new Material[3] { Assets.Materials.CardFoolMat, initMat3, initMat5 }; cardRenderer.materials = materials; yield return (object)new WaitForSeconds(0.1f); initMat = cardRenderer.materials[0]; initMat3 = cardRenderer.materials[1]; initMat5 = cardRenderer.materials[2]; delta3 = 0f; while (delta3 < 0.3f) { cardRenderer.materials[0].Lerp(initMat, GetCardBurn(), delta3 / 0.3f); cardRenderer.materials[1].Lerp(initMat3, GetCardBurn(), delta3 / 0.3f); cardRenderer.materials[2].Lerp(initMat5, GetCardBurn(), delta3 / 0.3f); delta3 += Time.deltaTime; yield return null; } yield return (object)new WaitForSeconds(0.2f); Vector3 initScale = cardPrefab.transform.localScale; float delta4 = 0f; while (delta4 < 0.3f) { cardPrefab.transform.localScale = initScale * (1f - Card.ControlCurve.Evaluate(delta4 / 0.3f)); delta4 += Time.deltaTime; yield return null; } cardPrefab.transform.localScale = Vector3.zero; } } public class HangedManCard : Card { public HangedManCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardHangedMat; } public override Material GetCardBurn() { return Assets.Materials.BurnRed; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!playerWhoDrew.isPlayerDead && playerWhoDrew.isPlayerControlled) { Networker.Instance.KillPlayerServerRpc((int)playerWhoDrew.playerClientId, new Vector3(0f, 1f, 0f), (CauseOfDeath)0); } } } public class HermitCard : Card { public HermitCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardHermitMat; } public override Material GetCardBurn() { return Assets.Materials.BurnAqua; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (Random.Range(0, 2) == 0) { PluginLogger.Debug("Teleporting enemy away"); Networker.Instance.TeleportEnemyAwayServerRpc(); } else { PluginLogger.Debug("Teleporting player to random inside node"); Vector3 position = RoundManager.Instance.insideAINodes[Random.Range(0, RoundManager.Instance.insideAINodes.Length)].transform.position; Networker.Instance.TeleportPlayerServerRpc((int)playerWhoDrew.playerClientId, position); } } } public class HighPriestessCard : Card { public HighPriestessCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardPriestessMat; } public override Material GetCardBurn() { return Assets.Materials.BurnYellow; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { int num = -1; for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i]; PluginLogger.Debug("Checking player " + val.playerUsername + " isPlayerControlled: " + val.isPlayerControlled + " isPlayerDead: " + val.isPlayerDead); if (val.isPlayerDead) { num = i; break; } } if (num != -1) { PluginLogger.Debug("Reviving player " + StartOfRound.Instance.allPlayerScripts[num].playerUsername); Networker.Instance.RevivePlayerServerRpc(num); } else { PluginLogger.Debug("No dead player found, allowing extra life"); Networker.Instance.AllowExtraLifeServerRpc(); } } } public class MoonCard : Card { public MoonCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardMoonMat; } public override Material GetCardBurn() { return Assets.Materials.BurnWhite; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { int num = playerWhoDrew.ItemSlots.Count((GrabbableObject item) => Object.op_Implicit((Object)(object)item)); int num2 = Random.Range(0, 10); if (num2 > 6 && num > 2) { float multiplier = Random.Range(0.1f, 0.9f); PluginLogger.Debug("Multiplying inventory value by " + multiplier); Networker.Instance.MultiplyInventoryValueServerRpc((int)playerWhoDrew.playerClientId, multiplier); return; } if (num2 == 0) { float multiplier2 = Random.Range(0.1f, 0.9f); PluginLogger.Debug("Multiplying random scrap value by " + multiplier2); Networker.Instance.MultiplyRandomScrapValueServerRpc(multiplier2); return; } PluginLogger.Debug("Damaging player to 2 health"); if (!playerWhoDrew.isPlayerDead && playerWhoDrew.health > 2) { Networker.Instance.SetPlayerHealthServerRpc((int)playerWhoDrew.playerClientId, 2); } } } public class SunCard : Card { public SunCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardSunMat; } public override Material GetCardBurn() { return Assets.Materials.BurnYellow; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { int num = playerWhoDrew.ItemSlots.Count((GrabbableObject item) => Object.op_Implicit((Object)(object)item)); int num2 = Random.Range(0, 10); if (num2 > 6 && num > 2) { float multiplier = Random.Range(1.1f, 1.5f); PluginLogger.Debug("Multiplying inventory value by " + multiplier); Networker.Instance.MultiplyInventoryValueServerRpc((int)playerWhoDrew.playerClientId, multiplier); return; } if (num2 == 0) { float multiplier2 = Random.Range(1.1f, 1.5f); PluginLogger.Debug("Multiplying random scrap value by " + multiplier2); Networker.Instance.MultiplyRandomScrapValueServerRpc(multiplier2); return; } PluginLogger.Debug("Healing player to 100 health"); if (!playerWhoDrew.isPlayerDead && playerWhoDrew.health < 100) { Networker.Instance.SetPlayerHealthServerRpc((int)playerWhoDrew.playerClientId, 100); } } } public class TowerCard : Card { public TowerCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override Material GetCardMaterial() { return Assets.Materials.CardTowerMat; } public override Material GetCardBurn() { return Assets.Materials.BurnBlue; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { int num = Random.Range(0, 60); if (num == 0) { return; } if (num <= 22) { PluginLogger.Debug("Opening or closing random security doors"); TerminalAccessibleObject[] array = Object.FindObjectsOfType<TerminalAccessibleObject>(); foreach (TerminalAccessibleObject val in array) { if (val.isBigDoor && Random.Range(0, 2) == 0) { val.SetDoorToggleLocalClient(); } } } else if (num <= 40) { PluginLogger.Debug("Opening or closing rng doors"); Networker.Instance.OpenOrCloseRandomDoorServerRpc((int)playerWhoDrew.playerClientId); } else if (num <= 55) { PluginLogger.Debug("Inverting ship door state"); Networker.Instance.SetShipDoorStateServerRpc(StartOfRound.Instance.hangarDoorsClosed); } else { PluginLogger.Debug("Turning off breaker"); Networker.Instance.BreakerOffServerRpc(); } } } public class WheelCard : Card { private bool outcome; public WheelCard(GameObject cardPrefab, AudioSource audioSource) : base(cardPrefab, audioSource) { } public override void InitCard() { outcome = Random.Range(0, 2) == 0; base.InitCard(); } public override Material GetCardMaterial() { return Assets.Materials.CardWheelMat; } public override Material GetCardBurn() { if (!outcome) { return Assets.Materials.BurnRed; } return Assets.Materials.BurnGreen; } public override void ExecuteEffect(PlayerControllerB playerWhoDrew) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) int num = Random.Range(0, 2); if (outcome) { switch (num) { case 0: PluginLogger.Debug("Healing by 20 hp"); if (playerWhoDrew.health >= 80) { Networker.Instance.SetPlayerHealthServerRpc((int)playerWhoDrew.playerClientId, 100); } else { Networker.Instance.SetPlayerHealthServerRpc((int)playerWhoDrew.playerClientId, playerWhoDrew.health + 20); } break; case 1: PluginLogger.Debug("Multiplying some scrap value by 1.1"); Networker.Instance.MultiplyRandomScrapValueServerRpc(1.1f); break; } } else { switch (num) { case 0: PluginLogger.Debug("Damaging by 20 hp"); Networker.Instance.DamagePlayerServerRpc((int)playerWhoDrew.playerClientId, 20, default(Vector3), (CauseOfDeath)0); break; case 1: PluginLogger.Debug("Multiplying some scrap value by 0.9"); Networker.Instance.MultiplyRandomScrapValueServerRpc(0.9f); break; } } } } }