diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 2f8d90b4c..a7b7b4772 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -3,11 +3,13 @@ using static TheOtherRoles.TheOtherRoles; using Types = TheOtherRoles.CustomOption.CustomOptionType; -namespace TheOtherRoles { - public class CustomOptionHolder { - public static string[] rates = new string[]{"0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"}; - public static string[] ratesModifier = new string[]{"1", "2", "3"}; - public static string[] presets = new string[]{"Preset 1", "Preset 2", "Preset 3", "Preset 4", "Preset 5"}; +namespace TheOtherRoles +{ + public class CustomOptionHolder + { + public static string[] rates = new string[] { "0%", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%" }; + public static string[] ratesModifier = new string[] { "1", "2", "3" }; + public static string[] presets = new string[] { "Preset 1", "Preset 2", "Preset 3", "Preset 4", "Preset 5" }; public static CustomOption presetSelection; public static CustomOption activateRoles; @@ -192,7 +194,7 @@ public class CustomOptionHolder { public static CustomOption cleanerSpawnRate; public static CustomOption cleanerCooldown; - + public static CustomOption warlockSpawnRate; public static CustomOption warlockCooldown; public static CustomOption warlockRootTime; @@ -248,7 +250,7 @@ public class CustomOptionHolder { public static CustomOption modifierSunglasses; public static CustomOption modifierSunglassesQuantity; public static CustomOption modifierSunglassesVision; - + public static CustomOption modifierMini; public static CustomOption modifierMiniGrowingUpDuration; @@ -259,12 +261,13 @@ public class CustomOptionHolder { public static CustomOption modifierInvert; public static CustomOption modifierInvertQuantity; public static CustomOption modifierInvertDuration; - + public static CustomOption maxNumberOfMeetings; public static CustomOption blockSkippingInEmergencyMeetings; public static CustomOption noVoteIsSelfVote; public static CustomOption hidePlayerNames; public static CustomOption allowParallelMedBayScans; + public static CustomOption randomSpawnLocations; public static CustomOption shieldFirstKill; public static CustomOption dynamicMap; @@ -277,18 +280,21 @@ public class CustomOptionHolder { internal static Dictionary blockedRolePairings = new Dictionary(); - public static string cs(Color c, string s) { + public static string cs(Color c, string s) + { return string.Format("{4}", ToByte(c.r), ToByte(c.g), ToByte(c.b), ToByte(c.a), s); } - - private static byte ToByte(float f) { + + private static byte ToByte(float f) + { f = Mathf.Clamp01(f); return (byte)(f * 255); } - public static void Load() { - - + public static void Load() + { + + // Role Options presetSelection = CustomOption.Create(0, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Preset"), presets, null, true); activateRoles = CustomOption.Create(1, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Enable Mod Roles And Block Vanilla Roles"), true, null, true); @@ -336,7 +342,7 @@ public static void Load() { warlockRootTime = CustomOption.Create(272, Types.Impostor, "Warlock Root Time", 5f, 0f, 15f, 1f, warlockSpawnRate); bountyHunterSpawnRate = CustomOption.Create(320, Types.Impostor, cs(BountyHunter.color, "Bounty Hunter"), rates, null, true); - bountyHunterBountyDuration = CustomOption.Create(321, Types.Impostor, "Duration After Which Bounty Changes", 60f, 10f, 180f, 10f, bountyHunterSpawnRate); + bountyHunterBountyDuration = CustomOption.Create(321, Types.Impostor, "Duration After Which Bounty Changes", 60f, 10f, 180f, 10f, bountyHunterSpawnRate); bountyHunterReducedCooldown = CustomOption.Create(322, Types.Impostor, "Cooldown After Killing Bounty", 2.5f, 0f, 30f, 2.5f, bountyHunterSpawnRate); bountyHunterPunishmentTime = CustomOption.Create(323, Types.Impostor, "Additional Cooldown After Killing Others", 20f, 0f, 60f, 2.5f, bountyHunterSpawnRate); bountyHunterShowArrow = CustomOption.Create(324, Types.Impostor, "Show Arrow Pointing Towards The Bounty", true, bountyHunterSpawnRate); @@ -362,8 +368,8 @@ public static void Load() { guesserNumberOfShots = CustomOption.Create(312, Types.Neutral, "Guesser Number Of Shots", 2f, 1f, 15f, 1f, guesserSpawnRate); guesserHasMultipleShotsPerMeeting = CustomOption.Create(313, Types.Neutral, "Guesser Can Shoot Multiple Times Per Meeting", false, guesserSpawnRate); guesserShowInfoInGhostChat = CustomOption.Create(314, Types.Neutral, "Guesses Visible In Ghost Chat", true, guesserSpawnRate); - guesserKillsThroughShield = CustomOption.Create(315, Types.Neutral, "Guesses Ignore The Medic Shield", true, guesserSpawnRate); - guesserEvilCanKillSpy = CustomOption.Create(316, Types.Neutral, "Evil Guesser Can Guess The Spy", true, guesserSpawnRate); + guesserKillsThroughShield = CustomOption.Create(315, Types.Neutral, "Guesses Ignore The Medic Shield", true, guesserSpawnRate); + guesserEvilCanKillSpy = CustomOption.Create(316, Types.Neutral, "Evil Guesser Can Guess The Spy", true, guesserSpawnRate); guesserSpawnBothRate = CustomOption.Create(317, Types.Neutral, "Both Guesser Spawn Rate", rates, guesserSpawnRate); guesserCantGuessSnitchIfTaksDone = CustomOption.Create(318, Types.Neutral, "Guesser Can't Guess Snitch When Tasks Completed", true, guesserSpawnRate); @@ -432,7 +438,7 @@ public static void Load() { lighterDuration = CustomOption.Create(114, Types.Crewmate, "Lighter Duration", 5f, 2.5f, 60f, 2.5f, lighterSpawnRate); detectiveSpawnRate = CustomOption.Create(120, Types.Crewmate, cs(Detective.color, "Detective"), rates, null, true); - detectiveAnonymousFootprints = CustomOption.Create(121, Types.Crewmate, "Anonymous Footprints", false, detectiveSpawnRate); + detectiveAnonymousFootprints = CustomOption.Create(121, Types.Crewmate, "Anonymous Footprints", false, detectiveSpawnRate); detectiveFootprintIntervall = CustomOption.Create(122, Types.Crewmate, "Footprint Intervall", 0.5f, 0.25f, 10f, 0.25f, detectiveSpawnRate); detectiveFootprintDuration = CustomOption.Create(123, Types.Crewmate, "Footprint Duration", 5f, 0.25f, 10f, 0.25f, detectiveSpawnRate); detectiveReportNameDuration = CustomOption.Create(124, Types.Crewmate, "Time Where Detective Reports Will Have Name", 0, 0, 60, 2.5f, detectiveSpawnRate); @@ -444,7 +450,7 @@ public static void Load() { timeMasterShieldDuration = CustomOption.Create(133, Types.Crewmate, "Time Master Shield Duration", 3f, 1f, 20f, 1f, timeMasterSpawnRate); medicSpawnRate = CustomOption.Create(140, Types.Crewmate, cs(Medic.color, "Medic"), rates, null, true); - medicShowShielded = CustomOption.Create(143, Types.Crewmate, "Show Shielded Player", new string[] {"Everyone", "Shielded + Medic", "Medic"}, medicSpawnRate); + medicShowShielded = CustomOption.Create(143, Types.Crewmate, "Show Shielded Player", new string[] { "Everyone", "Shielded + Medic", "Medic" }, medicSpawnRate); medicShowAttemptToShielded = CustomOption.Create(144, Types.Crewmate, "Shielded Player Sees Murder Attempt", false, medicSpawnRate); medicSetOrShowShieldAfterMeeting = CustomOption.Create(145, Types.Crewmate, "Shield Will Be Activated", new string[] { "Instantly", "Instantly, Visible\nAfter Meeting", "After Meeting" }, medicSpawnRate); @@ -459,10 +465,10 @@ public static void Load() { seerSpawnRate = CustomOption.Create(160, Types.Crewmate, cs(Seer.color, "Seer"), rates, null, true); - seerMode = CustomOption.Create(161, Types.Crewmate, "Seer Mode", new string[]{ "Show Death Flash + Souls", "Show Death Flash", "Show Souls"}, seerSpawnRate); + seerMode = CustomOption.Create(161, Types.Crewmate, "Seer Mode", new string[] { "Show Death Flash + Souls", "Show Death Flash", "Show Souls" }, seerSpawnRate); seerLimitSoulDuration = CustomOption.Create(163, Types.Crewmate, "Seer Limit Soul Duration", false, seerSpawnRate); seerSoulDuration = CustomOption.Create(162, Types.Crewmate, "Seer Soul Duration", 15f, 0f, 120f, 5f, seerLimitSoulDuration); - + hackerSpawnRate = CustomOption.Create(170, Types.Crewmate, cs(Hacker.color, "Hacker"), rates, null, true); hackerCooldown = CustomOption.Create(171, Types.Crewmate, "Hacker Cooldown", 30f, 5f, 60f, 5f, hackerSpawnRate); hackerHackeringDuration = CustomOption.Create(172, Types.Crewmate, "Hacker Duration", 10f, 2.5f, 60f, 2.5f, hackerSpawnRate); @@ -477,7 +483,7 @@ public static void Load() { trackerCanTrackCorpses = CustomOption.Create(203, Types.Crewmate, "Tracker Can Track Corpses", true, trackerSpawnRate); trackerCorpsesTrackingCooldown = CustomOption.Create(204, Types.Crewmate, "Corpses Tracking Cooldown", 30f, 5f, 120f, 5f, trackerCanTrackCorpses); trackerCorpsesTrackingDuration = CustomOption.Create(205, Types.Crewmate, "Corpses Tracking Duration", 5f, 2.5f, 30f, 2.5f, trackerCanTrackCorpses); - + snitchSpawnRate = CustomOption.Create(210, Types.Crewmate, cs(Snitch.color, "Snitch"), rates, null, true); snitchLeftTasksForReveal = CustomOption.Create(211, Types.Crewmate, "Task Count Where The Snitch Will Be Revealed", 1f, 0f, 5f, 1f, snitchSpawnRate); snitchIncludeTeamJackal = CustomOption.Create(212, Types.Crewmate, "Include Team Jackal", false, snitchSpawnRate); @@ -552,6 +558,7 @@ public static void Load() { hidePlayerNames = CustomOption.Create(6, Types.General, "Hide Player Names", false); allowParallelMedBayScans = CustomOption.Create(7, Types.General, "Allow Parallel MedBay Scans", false); shieldFirstKill = CustomOption.Create(8, Types.General, "Shield Last Game First Kill", false); + randomSpawnLocations = CustomOption.Create(1970, Types.General, "Random Spawn Locations", false); dynamicMap = CustomOption.Create(500, Types.General, "Play On A Random Map", false, null, false); dynamicMapEnableSkeld = CustomOption.Create(501, Types.General, "Enable Skeld Rotation", true, dynamicMap, false); @@ -561,13 +568,13 @@ public static void Load() { dynamicMapEnableSubmerged = CustomOption.Create(505, Types.General, "Enable Submerged Rotation", true, dynamicMap, false); - blockedRolePairings.Add((byte)RoleId.Vampire, new [] { (byte)RoleId.Warlock}); - blockedRolePairings.Add((byte)RoleId.Warlock, new [] { (byte)RoleId.Vampire}); - blockedRolePairings.Add((byte)RoleId.Spy, new [] { (byte)RoleId.Mini}); - blockedRolePairings.Add((byte)RoleId.Mini, new [] { (byte)RoleId.Spy}); - blockedRolePairings.Add((byte)RoleId.Vulture, new [] { (byte)RoleId.Cleaner}); - blockedRolePairings.Add((byte)RoleId.Cleaner, new [] { (byte)RoleId.Vulture}); - + blockedRolePairings.Add((byte)RoleId.Vampire, new[] { (byte)RoleId.Warlock }); + blockedRolePairings.Add((byte)RoleId.Warlock, new[] { (byte)RoleId.Vampire }); + blockedRolePairings.Add((byte)RoleId.Spy, new[] { (byte)RoleId.Mini }); + blockedRolePairings.Add((byte)RoleId.Mini, new[] { (byte)RoleId.Spy }); + blockedRolePairings.Add((byte)RoleId.Vulture, new[] { (byte)RoleId.Cleaner }); + blockedRolePairings.Add((byte)RoleId.Cleaner, new[] { (byte)RoleId.Vulture }); + } } } diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index e2e5ee6e8..fc76f15e4 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -8,17 +8,21 @@ using TheOtherRoles.Players; using TheOtherRoles.Utilities; -namespace TheOtherRoles.Patches { +namespace TheOtherRoles.Patches +{ [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.OnDestroy))] class IntroCutsceneOnDestroyPatch { public static PoolablePlayer playerPrefab; - public static void Prefix(IntroCutscene __instance) { + public static void Prefix(IntroCutscene __instance) + { // Generate and initialize player icons int playerCounter = 0; - if (CachedPlayer.LocalPlayer != null && FastDestroyableSingleton.Instance != null) { + if (CachedPlayer.LocalPlayer != null && FastDestroyableSingleton.Instance != null) + { Vector3 bottomLeft = new Vector3(-FastDestroyableSingleton.Instance.UseButton.transform.localPosition.x, FastDestroyableSingleton.Instance.UseButton.transform.localPosition.y, FastDestroyableSingleton.Instance.UseButton.transform.localPosition.z); - foreach (PlayerControl p in CachedPlayer.AllPlayers) { + foreach (PlayerControl p in CachedPlayer.AllPlayers) + { GameData.PlayerInfo data = p.Data; PoolablePlayer player = UnityEngine.Object.Instantiate(__instance.PlayerPrefab, FastDestroyableSingleton.Instance.transform); playerPrefab = __instance.PlayerPrefab; @@ -30,37 +34,137 @@ public static void Prefix(IntroCutscene __instance) { player.SetFlipX(true); MapOptions.playerIcons[p.PlayerId] = player; - if (CachedPlayer.LocalPlayer.PlayerControl == Arsonist.arsonist && p != Arsonist.arsonist) { + if (CachedPlayer.LocalPlayer.PlayerControl == Arsonist.arsonist && p != Arsonist.arsonist) + { player.transform.localPosition = bottomLeft + new Vector3(-0.25f, -0.25f, 0) + Vector3.right * playerCounter++ * 0.35f; player.transform.localScale = Vector3.one * 0.2f; player.setSemiTransparent(true); player.gameObject.SetActive(true); - } else if (CachedPlayer.LocalPlayer.PlayerControl == BountyHunter.bountyHunter) { + } + else if (CachedPlayer.LocalPlayer.PlayerControl == BountyHunter.bountyHunter) + { player.transform.localPosition = bottomLeft + new Vector3(-0.25f, 0f, 0); player.transform.localScale = Vector3.one * 0.4f; player.gameObject.SetActive(false); - } else { + } + else + { player.gameObject.SetActive(false); } } } + if (CustomOptionHolder.randomSpawnLocations.getBool() && PlayerControl.LocalPlayer != null) + { + int mapID = PlayerControl.GameOptions.MapId; + List skeldCoords = new List() + { + new Vector3(-1.1f, 5.8f, 0.0f), + new Vector3(9.5f, 3.7f, 0.0f), + new Vector3(4.9f, -3.8f, 0.0f), + new Vector3(18.2f, -3.8f, 0.0f), + new Vector3(7.5f, -14.1f, 0.0f), + new Vector3(4.7f, -15.4f, 0.0f), + new Vector3(-1.4f, -16.2f, 0.0f), + new Vector3(6.6f, -7.0f, 0.0f), + new Vector3(-7.3f, -4.7f, 0.0f), + new Vector3(-19.1f, -1.0f, 0.0f), + new Vector3(-21.4f, -5.0f, 0.0f), + new Vector3(-18.7f, -13.2f, 0.0f), + new Vector3(-6.2f, -7.9f, 0.0f), + new Vector3(-12.3f, -3.1f, 0.0f), + new Vector3(0.2f, -0.8f, 0.0f), + new Vector3(-3.8f, -9.9f, 0.0f), + new Vector3(9.4f, -9.0f, 0.0f), + new Vector3(4.5f, 3.5f, 0.0f), + new Vector3(-11.3f, 1.1f, 0.0f), + new Vector3(-12.3f, -14.7f, 0.0f), + new Vector3(0.2f, -17.1f, 0.0f) + + }; + List miraCoords = new List() + { + new Vector3(-4.7f, 3.9f, 0.0f), + new Vector3(-4.7f, -2.2f, 0.0f), + new Vector3(5.5f, -1.7f, 0.0f), + new Vector3(12.5f, -1.7f, 0.0f), + new Vector3(16.3f, 0.6f, 0.0f), + new Vector3(16.2f, 4.4f, 0.0f), + new Vector3(12.3f, 7.6f, 0.0f), + new Vector3(17.9f, 11.6f, 0.0f), + new Vector3(23.7f, 6.5f, 0.0f), + new Vector3(28.2f, -1.9f, 0.0f), + new Vector3(19.5f, -2.4f, 0.0f), + new Vector3(19.9f, 5.3f, 0.0f), + new Vector3(17.7f, 15.2f, 0.0f), + new Vector3(14.7f, 21.1f, 0.0f), + new Vector3(22.3f, 20.9f, 0.0f), + new Vector3(18.2f, 25.5f, 0.0f), + new Vector3(4.8f, 0.7f, 0.0f), + new Vector3(6.0f, 6.9f, 0.0f), + new Vector3(1.1f, 14.5f, 0.0f), + new Vector3(9.8f, 10.7f, 0.0f), + new Vector3(6.4f, 14.4f, 0.0f) + + }; + List polusCoords = new List() + { + new Vector3(16.7f, -0.8f, 0.0f), + new Vector3(4.7f, -7.4f, 0.0f), + new Vector3(3.0f, -12.4f, 0.0f), + new Vector3(10.1f, -12.2f, 0.0f), + new Vector3(1.4f, -16.3f, 0.0f), + new Vector3(1.3f, -23.8f, 0.0f), + new Vector3(8.3f, -25.3f, 0.0f), + new Vector3(12.2f, -15.5f, 0.0f), + new Vector3(10.4f, -23.0f, 0.0f), + new Vector3(22.3f, -25.2f, 0.0f), + new Vector3(19.7f, -16.3f, 0.0f), + new Vector3(30.5f, -15.6f, 0.0f), + new Vector3(25.9f, -12.9f, 0.0f), + new Vector3(27.8f, -7.1f, 0.0f), + new Vector3(34.0f, -5.6f, 0.0f), + new Vector3(39.9f, -9.8f, 0.0f), + new Vector3(23.8f, -24.6f, 0.0f), + new Vector3(21.4f, -11.7f, 0.0f), + new Vector3(24.3f, -3.0f, 0.0f), + new Vector3(14.2f, -15.4f, 0.0f), + new Vector3(19.4f, -14.9f, 0.0f), + new Vector3(11.7f, -9.7f, 0.0f), + new Vector3(24.7f, -9.7f, 0.0f) + + }; + Vector3 coords = PlayerControl.LocalPlayer.transform.position; + if (mapID == 0) + coords = skeldCoords[(rnd.Next(skeldCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % skeldCoords.Count()]; + else if (mapID == 1) + coords = miraCoords[(rnd.Next(miraCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % miraCoords.Count()]; + else if (mapID == 2) + coords = polusCoords[rnd.Next((polusCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % polusCoords.Count()]; + PlayerControl.LocalPlayer.transform.position = coords; + } + + // Force Bounty Hunter to load a new Bounty when the Intro is over - if (BountyHunter.bounty != null && CachedPlayer.LocalPlayer.PlayerControl == BountyHunter.bountyHunter) { + if (BountyHunter.bounty != null && CachedPlayer.LocalPlayer.PlayerControl == BountyHunter.bountyHunter) + { BountyHunter.bountyUpdateTimer = 0f; - if (FastDestroyableSingleton.Instance != null) { + if (FastDestroyableSingleton.Instance != null) + { Vector3 bottomLeft = new Vector3(-FastDestroyableSingleton.Instance.UseButton.transform.localPosition.x, FastDestroyableSingleton.Instance.UseButton.transform.localPosition.y, FastDestroyableSingleton.Instance.UseButton.transform.localPosition.z) + new Vector3(-0.25f, 1f, 0); BountyHunter.cooldownText = UnityEngine.Object.Instantiate(FastDestroyableSingleton.Instance.KillButton.cooldownTimerText, FastDestroyableSingleton.Instance.transform); BountyHunter.cooldownText.alignment = TMPro.TextAlignmentOptions.Center; BountyHunter.cooldownText.transform.localPosition = bottomLeft + new Vector3(0f, -1f, -1f); BountyHunter.cooldownText.gameObject.SetActive(true); } - } + } // First kill - if (AmongUsClient.Instance.AmHost && MapOptions.shieldFirstKill && MapOptions.firstKillName != "") { + if (AmongUsClient.Instance.AmHost && MapOptions.shieldFirstKill && MapOptions.firstKillName != "") + { PlayerControl target = PlayerControl.AllPlayerControls.ToArray().ToList().FirstOrDefault(x => x.Data.PlayerName.Equals(MapOptions.firstKillName)); - if (target != null) { + if (target != null) + { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetFirstKill, Hazel.SendOption.Reliable, -1); writer.Write(target.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -72,21 +176,26 @@ public static void Prefix(IntroCutscene __instance) { } [HarmonyPatch] - class IntroPatch { - public static void setupIntroTeamIcons(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) { + class IntroPatch + { + public static void setupIntroTeamIcons(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) + { // Intro solo teams - if (CachedPlayer.LocalPlayer.PlayerControl == Jester.jester || CachedPlayer.LocalPlayer.PlayerControl == Jackal.jackal || CachedPlayer.LocalPlayer.PlayerControl == Arsonist.arsonist || CachedPlayer.LocalPlayer.PlayerControl == Vulture.vulture || CachedPlayer.LocalPlayer.PlayerControl == Lawyer.lawyer) { + if (CachedPlayer.LocalPlayer.PlayerControl == Jester.jester || CachedPlayer.LocalPlayer.PlayerControl == Jackal.jackal || CachedPlayer.LocalPlayer.PlayerControl == Arsonist.arsonist || CachedPlayer.LocalPlayer.PlayerControl == Vulture.vulture || CachedPlayer.LocalPlayer.PlayerControl == Lawyer.lawyer) + { var soloTeam = new Il2CppSystem.Collections.Generic.List(); soloTeam.Add(CachedPlayer.LocalPlayer.PlayerControl); yourTeam = soloTeam; } // Add the Spy to the Impostor team (for the Impostors) - if (Spy.spy != null && CachedPlayer.LocalPlayer.Data.Role.IsImpostor) { + if (Spy.spy != null && CachedPlayer.LocalPlayer.Data.Role.IsImpostor) + { List players = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList(); var fakeImpostorTeam = new Il2CppSystem.Collections.Generic.List(); // The local player always has to be the first one in the list (to be displayed in the center) fakeImpostorTeam.Add(CachedPlayer.LocalPlayer.PlayerControl); - foreach (PlayerControl p in players) { + foreach (PlayerControl p in players) + { if (CachedPlayer.LocalPlayer.PlayerControl != p && (p == Spy.spy || p.Data.Role.IsImpostor)) fakeImpostorTeam.Add(p); } @@ -94,11 +203,13 @@ public static void setupIntroTeamIcons(IntroCutscene __instance, ref Il2CppSyst } } - public static void setupIntroTeam(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) { + public static void setupIntroTeam(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) + { List infos = RoleInfo.getRoleInfoForPlayer(CachedPlayer.LocalPlayer.PlayerControl); RoleInfo roleInfo = infos.Where(info => !info.isModifier).FirstOrDefault(); if (roleInfo == null) return; - if (roleInfo.isNeutral) { + if (roleInfo.isNeutral) + { var neutralColor = new Color32(76, 84, 78, 255); __instance.BackgroundBar.material.color = neutralColor; __instance.TeamTitle.text = "Neutral"; @@ -106,47 +217,56 @@ public static void setupIntroTeam(IntroCutscene __instance, ref Il2CppSystem.Co } } - public static IEnumerator EndShowRole(IntroCutscene __instance) { + public static IEnumerator EndShowRole(IntroCutscene __instance) + { yield return new WaitForSeconds(5f); __instance.YouAreText.gameObject.SetActive(false); __instance.RoleText.gameObject.SetActive(false); __instance.RoleBlurbText.gameObject.SetActive(false); __instance.ourCrewmate.gameObject.SetActive(false); - + } [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.ShowRole))] - class SetUpRoleTextPatch { - static public void SetRoleTexts(IntroCutscene __instance) { + class SetUpRoleTextPatch + { + static public void SetRoleTexts(IntroCutscene __instance) + { // Don't override the intro of the vanilla roles List infos = RoleInfo.getRoleInfoForPlayer(CachedPlayer.LocalPlayer.PlayerControl); RoleInfo roleInfo = infos.Where(info => !info.isModifier).FirstOrDefault(); RoleInfo modifierInfo = infos.Where(info => info.isModifier).FirstOrDefault(); __instance.RoleBlurbText.text = ""; - if (roleInfo != null) { + if (roleInfo != null) + { __instance.RoleText.text = roleInfo.name; __instance.RoleText.color = roleInfo.color; __instance.RoleBlurbText.text = roleInfo.introDescription; __instance.RoleBlurbText.color = roleInfo.color; } - if (modifierInfo != null) { + if (modifierInfo != null) + { if (modifierInfo.roleId != RoleId.Lover) __instance.RoleBlurbText.text += Helpers.cs(modifierInfo.color, $"\n{modifierInfo.introDescription}"); - else { + else + { PlayerControl otherLover = CachedPlayer.LocalPlayer.PlayerControl == Lovers.lover1 ? Lovers.lover2 : Lovers.lover1; __instance.RoleBlurbText.text += Helpers.cs(Lovers.color, $"\n♥ You are in love with {otherLover?.Data?.PlayerName ?? ""} ♥"); } } - if (Deputy.knowsSheriff && Deputy.deputy != null && Sheriff.sheriff != null) { + if (Deputy.knowsSheriff && Deputy.deputy != null && Sheriff.sheriff != null) + { if (infos.Any(info => info.roleId == RoleId.Sheriff)) __instance.RoleBlurbText.text += Helpers.cs(Sheriff.color, $"\nYour Deputy is {Deputy.deputy?.Data?.PlayerName ?? ""}"); else if (infos.Any(info => info.roleId == RoleId.Deputy)) __instance.RoleBlurbText.text += Helpers.cs(Sheriff.color, $"\nYour Sheriff is {Sheriff.sheriff?.Data?.PlayerName ?? ""}"); } } - public static bool Prefix(IntroCutscene __instance) { + public static bool Prefix(IntroCutscene __instance) + { if (!CustomOptionHolder.activateRoles.getBool()) return true; - FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(1f, new Action((p) => { + FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(1f, new Action((p) => + { SetRoleTexts(__instance); }))); return true; @@ -154,34 +274,43 @@ public static bool Prefix(IntroCutscene __instance) { } [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.BeginCrewmate))] - class BeginCrewmatePatch { - public static void Prefix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List teamToDisplay) { + class BeginCrewmatePatch + { + public static void Prefix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List teamToDisplay) + { setupIntroTeamIcons(__instance, ref teamToDisplay); } - public static void Postfix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List teamToDisplay) { + public static void Postfix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List teamToDisplay) + { setupIntroTeam(__instance, ref teamToDisplay); } } [HarmonyPatch(typeof(IntroCutscene), nameof(IntroCutscene.BeginImpostor))] - class BeginImpostorPatch { - public static void Prefix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) { + class BeginImpostorPatch + { + public static void Prefix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) + { setupIntroTeamIcons(__instance, ref yourTeam); } - public static void Postfix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) { + public static void Postfix(IntroCutscene __instance, ref Il2CppSystem.Collections.Generic.List yourTeam) + { setupIntroTeam(__instance, ref yourTeam); } } } [HarmonyPatch(typeof(Constants), nameof(Constants.ShouldHorseAround))] - public static class ShouldAlwaysHorseAround { + public static class ShouldAlwaysHorseAround + { public static bool isHorseMode; - public static bool Prefix(ref bool __result) { + public static bool Prefix(ref bool __result) + { if (isHorseMode != MapOptions.enableHorseMode && LobbyBehaviour.Instance != null) __result = isHorseMode; - else { + else + { __result = MapOptions.enableHorseMode; isHorseMode = MapOptions.enableHorseMode; } diff --git a/TheOtherRoles/Patches/MeetingPatch.cs b/TheOtherRoles/Patches/MeetingPatch.cs index 061d62bc3..942b2231a 100644 --- a/TheOtherRoles/Patches/MeetingPatch.cs +++ b/TheOtherRoles/Patches/MeetingPatch.cs @@ -10,9 +10,11 @@ using TheOtherRoles.Utilities; using UnityEngine; -namespace TheOtherRoles.Patches { +namespace TheOtherRoles.Patches +{ [HarmonyPatch] - class MeetingHudPatch { + class MeetingHudPatch + { static bool[] selections; static SpriteRenderer[] renderers; private static GameData.PlayerInfo target = null; @@ -22,12 +24,16 @@ class MeetingHudPatch { private static TMPro.TextMeshPro swapperConfirmButtonLabel; [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CheckForEndVoting))] - class MeetingCalculateVotesPatch { - private static Dictionary CalculateVotes(MeetingHud __instance) { + class MeetingCalculateVotesPatch + { + private static Dictionary CalculateVotes(MeetingHud __instance) + { Dictionary dictionary = new Dictionary(); - for (int i = 0; i < __instance.playerStates.Length; i++) { + for (int i = 0; i < __instance.playerStates.Length; i++) + { PlayerVoteArea playerVoteArea = __instance.playerStates[i]; - if (playerVoteArea.VotedFor != 252 && playerVoteArea.VotedFor != 255 && playerVoteArea.VotedFor != 254) { + if (playerVoteArea.VotedFor != 252 && playerVoteArea.VotedFor != 255 && playerVoteArea.VotedFor != 254) + { PlayerControl player = Helpers.playerById((byte)playerVoteArea.TargetPlayerId); if (player == null || player.Data == null || player.Data.IsDead || player.Data.Disconnected) continue; @@ -40,15 +46,18 @@ private static Dictionary CalculateVotes(MeetingHud __instance) { } } // Swapper swap votes - if (Swapper.swapper != null && !Swapper.swapper.Data.IsDead) { + if (Swapper.swapper != null && !Swapper.swapper.Data.IsDead) + { PlayerVoteArea swapped1 = null; PlayerVoteArea swapped2 = null; - foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) { + foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) + { if (playerVoteArea.TargetPlayerId == Swapper.playerId1) swapped1 = playerVoteArea; if (playerVoteArea.TargetPlayerId == Swapper.playerId2) swapped2 = playerVoteArea; } - if (swapped1 != null && swapped2 != null) { + if (swapped1 != null && swapped2 != null) + { if (!dictionary.ContainsKey(swapped1.TargetPlayerId)) dictionary[swapped1.TargetPlayerId] = 0; if (!dictionary.ContainsKey(swapped2.TargetPlayerId)) dictionary[swapped2.TargetPlayerId] = 0; int tmp = dictionary[swapped1.TargetPlayerId]; @@ -63,18 +72,22 @@ private static Dictionary CalculateVotes(MeetingHud __instance) { } - static bool Prefix(MeetingHud __instance) { - if (__instance.playerStates.All((PlayerVoteArea ps) => ps.AmDead || ps.DidVote)) { + static bool Prefix(MeetingHud __instance) + { + if (__instance.playerStates.All((PlayerVoteArea ps) => ps.AmDead || ps.DidVote)) + { // If skipping is disabled, replace skipps/no-votes with self vote - if (target == null && blockSkippingInEmergencyMeetings && noVoteIsSelfVote) { - foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) { + if (target == null && blockSkippingInEmergencyMeetings && noVoteIsSelfVote) + { + foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) + { if (playerVoteArea.VotedFor == byte.MaxValue - 1) playerVoteArea.VotedFor = playerVoteArea.TargetPlayerId; // TargetPlayerId } } - Dictionary self = CalculateVotes(__instance); + Dictionary self = CalculateVotes(__instance); bool tie; - KeyValuePair max = self.MaxPair(out tie); + KeyValuePair max = self.MaxPair(out tie); GameData.PlayerInfo exiled = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(v => !tie && v.PlayerId == max.Key && !v.IsDead); // TieBreaker @@ -82,7 +95,7 @@ static bool Prefix(MeetingHud __instance) { int maxVoteValue = self.Values.Max(); List potentialExiled = new List(); - + PlayerVoteArea tb = null; if (Tiebreaker.tiebreaker != null) tb = __instance.playerStates.ToArray().FirstOrDefault(x => x.TargetPlayerId == Tiebreaker.tiebreaker.PlayerId); @@ -97,12 +110,14 @@ static bool Prefix(MeetingHud __instance) { for (int i = 0; i < __instance.playerStates.Length; i++) { PlayerVoteArea playerVoteArea = __instance.playerStates[i]; - array[i] = new MeetingHud.VoterState { + array[i] = new MeetingHud.VoterState + { VoterId = playerVoteArea.TargetPlayerId, VotedForId = playerVoteArea.VotedFor }; - if (Tiebreaker.tiebreaker != null && tie && playerVoteArea.TargetPlayerId == Tiebreaker.tiebreaker.PlayerId && potentialExiled.FindAll(x => x != null && x.PlayerId == playerVoteArea.VotedFor).Count > 0) { + if (Tiebreaker.tiebreaker != null && tie && playerVoteArea.TargetPlayerId == Tiebreaker.tiebreaker.PlayerId && potentialExiled.FindAll(x => x != null && x.PlayerId == playerVoteArea.VotedFor).Count > 0) + { exiled = potentialExiled.ToArray().FirstOrDefault(v => v.PlayerId == playerVoteArea.VotedFor); tie = false; @@ -120,8 +135,10 @@ static bool Prefix(MeetingHud __instance) { } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.BloopAVoteIcon))] - class MeetingHudBloopAVoteIconPatch { - public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)]GameData.PlayerInfo voterPlayer, [HarmonyArgument(1)]int index, [HarmonyArgument(2)]Transform parent) { + class MeetingHudBloopAVoteIconPatch + { + public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] GameData.PlayerInfo voterPlayer, [HarmonyArgument(1)] int index, [HarmonyArgument(2)] Transform parent) + { SpriteRenderer spriteRenderer = UnityEngine.Object.Instantiate(__instance.PlayerVotePrefab); if (!PlayerControl.GameOptions.AnonymousVotes || (CachedPlayer.LocalPlayer.Data.IsDead && MapOptions.ghostsSeeVotes) || Mayor.mayor != null && CachedPlayer.LocalPlayer.PlayerControl == Mayor.mayor && Mayor.canSeeVoteColors && TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data).Item1 >= Mayor.tasksNeededToSeeVoteColors) PlayerControl.SetPlayerMaterialColors(voterPlayer.DefaultOutfit.ColorId, spriteRenderer); @@ -133,22 +150,26 @@ public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)]GameData.Pl parent.GetComponent().AddVote(spriteRenderer); return false; } - } + } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.PopulateResults))] - class MeetingHudPopulateVotesPatch { - - static bool Prefix(MeetingHud __instance, Il2CppStructArray states) { + class MeetingHudPopulateVotesPatch + { + + static bool Prefix(MeetingHud __instance, Il2CppStructArray states) + { // Swapper swap PlayerVoteArea swapped1 = null; PlayerVoteArea swapped2 = null; - foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) { + foreach (PlayerVoteArea playerVoteArea in __instance.playerStates) + { if (playerVoteArea.TargetPlayerId == Swapper.playerId1) swapped1 = playerVoteArea; if (playerVoteArea.TargetPlayerId == Swapper.playerId2) swapped2 = playerVoteArea; } bool doSwap = swapped1 != null && swapped2 != null && Swapper.swapper != null && !Swapper.swapper.Data.IsDead; - if (doSwap) { + if (doSwap) + { __instance.StartCoroutine(Effects.Slide3D(swapped1.transform, swapped1.transform.localPosition, swapped2.transform.localPosition, 1.5f)); __instance.StartCoroutine(Effects.Slide3D(swapped2.transform, swapped2.transform.localPosition, swapped1.transform.localPosition, 1.5f)); } @@ -156,7 +177,8 @@ static bool Prefix(MeetingHud __instance, Il2CppStructArray.Instance.GetString(StringNames.MeetingVotingResults, new Il2CppReferenceArray(0)); int num = 0; - for (int i = 0; i < __instance.playerStates.Length; i++) { + for (int i = 0; i < __instance.playerStates.Length; i++) + { PlayerVoteArea playerVoteArea = __instance.playerStates[i]; byte targetPlayerId = playerVoteArea.TargetPlayerId; // Swapper change playerVoteArea that gets the votes @@ -166,24 +188,30 @@ static bool Prefix(MeetingHud __instance, Il2CppStructArray skeldCoords = new List() + { + new Vector3(-1.1f, 5.8f, 0.0f), + new Vector3(9.5f, 3.7f, 0.0f), + new Vector3(4.9f, -3.8f, 0.0f), + new Vector3(18.2f, -3.8f, 0.0f), + new Vector3(7.5f, -14.1f, 0.0f), + new Vector3(4.7f, -15.4f, 0.0f), + new Vector3(-1.4f, -16.2f, 0.0f), + new Vector3(6.6f, -7.0f, 0.0f), + new Vector3(-7.3f, -4.7f, 0.0f), + new Vector3(-19.1f, -1.0f, 0.0f), + new Vector3(-21.4f, -5.0f, 0.0f), + new Vector3(-18.7f, -13.2f, 0.0f), + new Vector3(-6.2f, -7.9f, 0.0f), + new Vector3(-12.3f, -3.1f, 0.0f), + new Vector3(0.2f, -0.8f, 0.0f), + new Vector3(-3.8f, -9.9f, 0.0f), + new Vector3(9.4f, -9.0f, 0.0f), + new Vector3(4.5f, 3.5f, 0.0f), + new Vector3(-11.3f, 1.1f, 0.0f), + new Vector3(-12.3f, -14.7f, 0.0f), + new Vector3(0.2f, -17.1f, 0.0f) + + }; + List miraCoords = new List() + { + new Vector3(-4.7f, 3.9f, 0.0f), + new Vector3(-4.7f, -2.2f, 0.0f), + new Vector3(5.5f, -1.7f, 0.0f), + new Vector3(12.5f, -1.7f, 0.0f), + new Vector3(16.3f, 0.6f, 0.0f), + new Vector3(16.2f, 4.4f, 0.0f), + new Vector3(12.3f, 7.6f, 0.0f), + new Vector3(17.9f, 11.6f, 0.0f), + new Vector3(23.7f, 6.5f, 0.0f), + new Vector3(28.2f, -1.9f, 0.0f), + new Vector3(19.5f, -2.4f, 0.0f), + new Vector3(19.9f, 5.3f, 0.0f), + new Vector3(17.7f, 15.2f, 0.0f), + new Vector3(14.7f, 21.1f, 0.0f), + new Vector3(22.3f, 20.9f, 0.0f), + new Vector3(18.2f, 25.5f, 0.0f), + new Vector3(4.8f, 0.7f, 0.0f), + new Vector3(6.0f, 6.9f, 0.0f), + new Vector3(1.1f, 14.5f, 0.0f), + new Vector3(9.8f, 10.7f, 0.0f), + new Vector3(6.4f, 14.4f, 0.0f) + + }; + List polusCoords = new List() + { + new Vector3(16.7f, -0.8f, 0.0f), + new Vector3(4.7f, -7.4f, 0.0f), + new Vector3(3.0f, -12.4f, 0.0f), + new Vector3(10.1f, -12.2f, 0.0f), + new Vector3(1.4f, -16.3f, 0.0f), + new Vector3(1.3f, -23.8f, 0.0f), + new Vector3(8.3f, -25.3f, 0.0f), + new Vector3(12.2f, -15.5f, 0.0f), + new Vector3(10.4f, -23.0f, 0.0f), + new Vector3(22.3f, -25.2f, 0.0f), + new Vector3(19.7f, -16.3f, 0.0f), + new Vector3(30.5f, -15.6f, 0.0f), + new Vector3(25.9f, -12.9f, 0.0f), + new Vector3(27.8f, -7.1f, 0.0f), + new Vector3(34.0f, -5.6f, 0.0f), + new Vector3(39.9f, -9.8f, 0.0f), + new Vector3(23.8f, -24.6f, 0.0f), + new Vector3(21.4f, -11.7f, 0.0f), + new Vector3(24.3f, -3.0f, 0.0f), + new Vector3(14.2f, -15.4f, 0.0f), + new Vector3(19.4f, -14.9f, 0.0f), + new Vector3(11.7f, -9.7f, 0.0f), + new Vector3(24.7f, -9.7f, 0.0f) + + }; + Vector3 coords = PlayerControl.LocalPlayer.transform.position; + if (mapID == 0) + coords = skeldCoords[(rnd.Next(skeldCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % skeldCoords.Count()]; + else if (mapID == 1) + coords = miraCoords[(rnd.Next(miraCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % miraCoords.Count()]; + else if (mapID == 2) + coords = polusCoords[rnd.Next((polusCoords.Count) + PlayerControl.LocalPlayer.PlayerId) % polusCoords.Count()]; + PlayerControl.LocalPlayer.transform.position = coords; + } + } } - static void swapperOnClick(int i, MeetingHud __instance) { + static void swapperOnClick(int i, MeetingHud __instance) + { if (__instance.state == MeetingHud.VoteStates.Results || Swapper.charges <= 0) return; if (__instance.playerStates[i].AmDead) return; int selectedCount = selections.Where(b => b).Count(); SpriteRenderer renderer = renderers[i]; - if (selectedCount == 0) { + if (selectedCount == 0) + { renderer.color = Color.yellow; selections[i] = true; - } else if (selectedCount == 1) { - if (selections[i]) { + } + else if (selectedCount == 1) + { + if (selections[i]) + { renderer.color = Color.red; selections[i] = false; - } else { + } + else + { selections[i] = true; renderer.color = Color.yellow; swapperConfirmButtonLabel.text = Helpers.cs(Color.yellow, "Confirm Swap"); } - } else if (selectedCount == 2) { - if (selections[i]) { + } + else if (selectedCount == 2) + { + if (selections[i]) + { renderer.color = Color.red; selections[i] = false; swapperConfirmButtonLabel.text = Helpers.cs(Color.red, "Confirm Swap"); @@ -239,7 +369,8 @@ static void swapperOnClick(int i, MeetingHud __instance) { } } - static void swapperConfirm(MeetingHud __instance) { + static void swapperConfirm(MeetingHud __instance) + { __instance.playerStates[0].Cancel(); // This will stop the underlying buttons of the template from showing up if (__instance.state == MeetingHud.VoteStates.Results) return; if (selections.Where(b => b).Count() != 2) return; @@ -247,20 +378,28 @@ static void swapperConfirm(MeetingHud __instance) { PlayerVoteArea firstPlayer = null; PlayerVoteArea secondPlayer = null; - for (int A = 0; A < selections.Length; A++) { - if (selections[A]) { - if (firstPlayer == null) { + for (int A = 0; A < selections.Length; A++) + { + if (selections[A]) + { + if (firstPlayer == null) + { firstPlayer = __instance.playerStates[A]; - } else { + } + else + { secondPlayer = __instance.playerStates[A]; } renderers[A].color = Color.green; - } else if (renderers[A] != null) { + } + else if (renderers[A] != null) + { renderers[A].color = Color.gray; - } + } if (swapperButtonList[A] != null) swapperButtonList[A].OnClick.RemoveAllListeners(); // Swap buttons can't be clicked / changed anymore } - if (firstPlayer != null && secondPlayer != null) { + if (firstPlayer != null && secondPlayer != null) + { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SwapperSwap, Hazel.SendOption.Reliable, -1); writer.Write((byte)firstPlayer.TargetPlayerId); writer.Write((byte)secondPlayer.TargetPlayerId); @@ -274,7 +413,8 @@ static void swapperConfirm(MeetingHud __instance) { } private static GameObject guesserUI; - static void guesserOnClick(int buttonTarget, MeetingHud __instance) { + static void guesserOnClick(int buttonTarget, MeetingHud __instance) + { if (guesserUI != null || !(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted)) return; __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(false)); @@ -296,7 +436,8 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { exitButtonParent.transform.localPosition = new Vector3(2.725f, 2.1f, -5); exitButtonParent.transform.localScale = new Vector3(0.217f, 0.9f, 1); exitButton.GetComponent().OnClick.RemoveAllListeners(); - exitButton.GetComponent().OnClick.AddListener((System.Action)(() => { + exitButton.GetComponent().OnClick.AddListener((System.Action)(() => + { __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); UnityEngine.Object.Destroy(container.gameObject); })); @@ -304,11 +445,13 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { List buttons = new List(); Transform selectedButton = null; - foreach (RoleInfo roleInfo in RoleInfo.allRoleInfos) { - RoleId guesserRole = (Guesser.niceGuesser != null && CachedPlayer.LocalPlayer.PlayerId == Guesser.niceGuesser.PlayerId) ? RoleId.NiceGuesser : RoleId.EvilGuesser; + foreach (RoleInfo roleInfo in RoleInfo.allRoleInfos) + { + RoleId guesserRole = (Guesser.niceGuesser != null && CachedPlayer.LocalPlayer.PlayerId == Guesser.niceGuesser.PlayerId) ? RoleId.NiceGuesser : RoleId.EvilGuesser; if (roleInfo.isModifier || roleInfo.roleId == guesserRole || (!Guesser.evilGuesserCanGuessSpy && guesserRole == RoleId.EvilGuesser && roleInfo.roleId == RoleId.Spy)) continue; // Not guessable roles & modifier - - if (Guesser.guesserCantGuessSnitch && Snitch.snitch != null) { + + if (Guesser.guesserCantGuessSnitch && Snitch.snitch != null) + { var (playerCompleted, playerTotal) = TasksHandler.taskInfo(Snitch.snitch.Data); int numberOfLeftTasks = playerTotal - playerCompleted; if (numberOfLeftTasks <= 0 && roleInfo.roleId == RoleId.Snitch) continue; @@ -321,7 +464,7 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { TMPro.TextMeshPro label = UnityEngine.Object.Instantiate(textTemplate, button); button.GetComponent().sprite = FastDestroyableSingleton.Instance.GetNamePlateById("nameplate_NoPlate")?.viewData?.viewData?.Image; buttons.Add(button); - int row = i/5, col = i%5; + int row = i / 5, col = i % 5; buttonParent.localPosition = new Vector3(-3.47f + 1.75f * col, 1.5f - 0.45f * row, -5); buttonParent.localScale = new Vector3(0.55f, 0.55f, 1f); label.text = Helpers.cs(roleInfo.color, roleInfo.name); @@ -331,16 +474,21 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { int copiedIndex = i; button.GetComponent().OnClick.RemoveAllListeners(); - if (!CachedPlayer.LocalPlayer.Data.IsDead) button.GetComponent().OnClick.AddListener((System.Action)(() => { - if (selectedButton != button) { + if (!CachedPlayer.LocalPlayer.Data.IsDead) button.GetComponent().OnClick.AddListener((System.Action)(() => + { + if (selectedButton != button) + { selectedButton = button; buttons.ForEach(x => x.GetComponent().color = x == selectedButton ? Color.red : Color.white); - } else { + } + else + { PlayerControl focusedTarget = Helpers.playerById((byte)__instance.playerStates[buttonTarget].TargetPlayerId); - if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted) || focusedTarget == null || Guesser.remainingShots(CachedPlayer.LocalPlayer.PlayerId) <= 0 ) return; + if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted) || focusedTarget == null || Guesser.remainingShots(CachedPlayer.LocalPlayer.PlayerId) <= 0) return; - if (!Guesser.killsThroughShield && focusedTarget == Medic.shielded) { // Depending on the options, shooting the shielded player will not allow the guess, notifiy everyone about the kill attempt and close the window - __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); + if (!Guesser.killsThroughShield && focusedTarget == Medic.shielded) + { // Depending on the options, shooting the shielded player will not allow the guess, notifiy everyone about the kill attempt and close the window + __instance.playerStates.ToList().ForEach(x => x.gameObject.SetActive(true)); UnityEngine.Object.Destroy(container.gameObject); MessageWriter murderAttemptWriter = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); @@ -379,20 +527,25 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { } [HarmonyPatch(typeof(PlayerVoteArea), nameof(PlayerVoteArea.Select))] - class PlayerVoteAreaSelectPatch { - static bool Prefix(MeetingHud __instance) { + class PlayerVoteAreaSelectPatch + { + static bool Prefix(MeetingHud __instance) + { return !(CachedPlayer.LocalPlayer != null && Guesser.isGuesser(CachedPlayer.LocalPlayer.PlayerId) && guesserUI != null); } } - static void populateButtonsPostfix(MeetingHud __instance) { + static void populateButtonsPostfix(MeetingHud __instance) + { // Add Swapper Buttons - if (Swapper.swapper != null && CachedPlayer.LocalPlayer.PlayerControl == Swapper.swapper && !Swapper.swapper.Data.IsDead) { + if (Swapper.swapper != null && CachedPlayer.LocalPlayer.PlayerControl == Swapper.swapper && !Swapper.swapper.Data.IsDead) + { selections = new bool[__instance.playerStates.Length]; renderers = new SpriteRenderer[__instance.playerStates.Length]; swapperButtonList = new PassiveButton[__instance.playerStates.Length]; - for (int i = 0; i < __instance.playerStates.Length; i++) { + for (int i = 0; i < __instance.playerStates.Length; i++) + { PlayerVoteArea playerVoteArea = __instance.playerStates[i]; if (playerVoteArea.AmDead || (playerVoteArea.TargetPlayerId == Swapper.swapper.PlayerId && Swapper.canOnlySwapOthers)) continue; @@ -412,7 +565,7 @@ static void populateButtonsPostfix(MeetingHud __instance) { button.OnClick.RemoveAllListeners(); int copiedIndex = i; button.OnClick.AddListener((System.Action)(() => swapperOnClick(copiedIndex, __instance))); - + selections[i] = false; renderers[i] = renderer; } @@ -445,27 +598,34 @@ static void populateButtonsPostfix(MeetingHud __instance) { swapperConfirmButtonLabel.transform.localScale *= 1.7f; PassiveButton passiveButton = confirmSwapButton.GetComponent(); - passiveButton.OnClick.RemoveAllListeners(); + passiveButton.OnClick.RemoveAllListeners(); if (!CachedPlayer.LocalPlayer.Data.IsDead) passiveButton.OnClick.AddListener((Action)(() => swapperConfirm(__instance))); confirmSwapButton.parent.gameObject.SetActive(false); - __instance.StartCoroutine(Effects.Lerp(7.27f, new Action((p) => { // Button appears delayed, so that its visible in the voting screen only! - if (p == 1f) { + __instance.StartCoroutine(Effects.Lerp(7.27f, new Action((p) => + { // Button appears delayed, so that its visible in the voting screen only! + if (p == 1f) + { confirmSwapButton.parent.gameObject.SetActive(true); } }))); } //Fix visor in Meetings - foreach (PlayerVoteArea pva in __instance.playerStates) { - if(pva.PlayerIcon != null && pva.PlayerIcon.VisorSlot != null){ + foreach (PlayerVoteArea pva in __instance.playerStates) + { + if (pva.PlayerIcon != null && pva.PlayerIcon.VisorSlot != null) + { pva.PlayerIcon.VisorSlot.transform.position += new Vector3(0, 0, -1f); } } // Add overlay for spelled players - if (Witch.witch != null && Witch.futureSpelled != null) { - foreach (PlayerVoteArea pva in __instance.playerStates) { - if (Witch.futureSpelled.Any(x => x.PlayerId == pva.TargetPlayerId)) { + if (Witch.witch != null && Witch.futureSpelled != null) + { + foreach (PlayerVoteArea pva in __instance.playerStates) + { + if (Witch.futureSpelled.Any(x => x.PlayerId == pva.TargetPlayerId)) + { SpriteRenderer rend = (new GameObject()).AddComponent(); rend.transform.SetParent(pva.transform); rend.gameObject.layer = pva.Megaphone.gameObject.layer; @@ -476,8 +636,10 @@ static void populateButtonsPostfix(MeetingHud __instance) { } // Add Guesser Buttons - if (Guesser.isGuesser(CachedPlayer.LocalPlayer.PlayerId) && !CachedPlayer.LocalPlayer.Data.IsDead && Guesser.remainingShots(CachedPlayer.LocalPlayer.PlayerId) > 0) { - for (int i = 0; i < __instance.playerStates.Length; i++) { + if (Guesser.isGuesser(CachedPlayer.LocalPlayer.PlayerId) && !CachedPlayer.LocalPlayer.Data.IsDead && Guesser.remainingShots(CachedPlayer.LocalPlayer.PlayerId) > 0) + { + for (int i = 0; i < __instance.playerStates.Length; i++) + { PlayerVoteArea playerVoteArea = __instance.playerStates[i]; if (playerVoteArea.AmDead || playerVoteArea.TargetPlayerId == CachedPlayer.LocalPlayer.PlayerId) continue; @@ -496,7 +658,8 @@ static void populateButtonsPostfix(MeetingHud __instance) { } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.ServerStart))] - class MeetingServerStartPatch { + class MeetingServerStartPatch + { static void Postfix(MeetingHud __instance) { populateButtonsPostfix(__instance); @@ -504,19 +667,23 @@ static void Postfix(MeetingHud __instance) } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Deserialize))] - class MeetingDeserializePatch { - static void Postfix(MeetingHud __instance, [HarmonyArgument(0)]MessageReader reader, [HarmonyArgument(1)]bool initialState) + class MeetingDeserializePatch + { + static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] MessageReader reader, [HarmonyArgument(1)] bool initialState) { // Add swapper buttons - if (initialState) { + if (initialState) + { populateButtonsPostfix(__instance); } } } [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CoStartMeeting))] - class StartMeetingPatch { - public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)]GameData.PlayerInfo meetingTarget) { + class StartMeetingPatch + { + public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameData.PlayerInfo meetingTarget) + { // Resett Bait list Bait.active = new Dictionary(); // Safe AntiTeleport positions @@ -532,23 +699,27 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)]GameData // Add Portal info into Portalmaker Chat: - if (Portalmaker.portalmaker != null && CachedPlayer.LocalPlayer.PlayerControl == Portalmaker.portalmaker && !CachedPlayer.LocalPlayer.Data.IsDead) { - foreach (var entry in Portal.teleportedPlayers) { + if (Portalmaker.portalmaker != null && CachedPlayer.LocalPlayer.PlayerControl == Portalmaker.portalmaker && !CachedPlayer.LocalPlayer.Data.IsDead) + { + foreach (var entry in Portal.teleportedPlayers) + { float timeBeforeMeeting = ((float)(DateTime.UtcNow - entry.time).TotalMilliseconds) / 1000; string msg = Portalmaker.logShowsTime ? $"{(int)timeBeforeMeeting}s ago: " : ""; msg = msg + $"{entry.name} used the teleporter"; FastDestroyableSingleton.Instance.Chat.AddChat(CachedPlayer.LocalPlayer.PlayerControl, $"{msg}"); } } - + // Reset zoomed out ghosts Helpers.toggleZoom(reset: true); } } [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Update))] - class MeetingHudUpdatePatch { - static void Postfix(MeetingHud __instance) { + class MeetingHudUpdatePatch + { + static void Postfix(MeetingHud __instance) + { // Deactivate skip Button if skipping on emergency meetings is disabled if (target == null && blockSkippingInEmergencyMeetings) __instance.SkipVoteButton.gameObject.SetActive(false);