diff --git a/README.md b/README.md index 4e04661ad..7ac7ef69f 100644 --- a/README.md +++ b/README.md @@ -42,15 +42,16 @@ The [Role Assignment](#role-assignment) section explains how the roles are being # Releases | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| 2024.6.18s| v4.6.0| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.6.0/TheOtherRoles.zip) | 2024.3.5s| v4.5.3| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.3/TheOtherRoles.zip) -| 2024.3.5s| v4.5.2| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.2/TheOtherRoles.zip) -| 2023.11.28s| v4.5.1| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.1/TheOtherRoles.zip)
Click to show older versions | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| 2024.3.5s| v4.5.2| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.2/TheOtherRoles.zip) +| 2023.11.28s| v4.5.1| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.1/TheOtherRoles.zip) | 2023.11.28s| v4.5.0| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.5.0/TheOtherRoles.zip) | 2023.07.12s| v4.4.2| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.4.2/TheOtherRoles.zip) | 2023.07.12s| v4.4.1| [Download](https://github.com/TheOtherRolesAU/TheOtherRoles/releases/download/v4.4.1/TheOtherRoles.zip) @@ -133,6 +134,20 @@ The [Role Assignment](#role-assignment) section explains how the roles are being
Click to show the Changelog + +** Version 4.6.0** +- Updated to Among Us version 2024.6.18 (Vanilla Update with new UI elements and many Server Side Changes) +- Added a completely new UI for the Mod's Options, using the new Vanilla Design. +- Added a button to switch gamemodes in the lobby +- Added an option to enable the Chat-Notification in game (in Mod Options) +- Fixed a bug where the shielding the bomber would show a murder attempt on the bomber, when they plant a bomb (sorry Vlesk) +- Fixed a bug in PropHunt, where the background of the Prop-Display was visible in the cameras +- Fixed a bug where guessing a player would sometimes not return the votes to the voters +- Fixed a bug where the Lawyer would not properly die when guessing the client +- Removed: Disabled Vanilla Servers for now, as the mod is incompatible with them in its / their current state. Thanks to Miniduikboat for making custom servers great again! +- Experimental: Advanded users can try to install the mod on the Windows Store Version of Among Us. No Support Provided! + + **Version 4.5.3** - Added a new role: Yo-Yo (Impostor) - Mark and blink to a position, then blink back to the start of the blink! - Added a new option to Jackal And Sidekick: Jackal / Sidekick can sabotage lights (cooldown syncs with Imp Sabotages) diff --git a/TheOtherRoles.sln b/TheOtherRoles.sln index 3c00efe92..a61126ed9 100644 --- a/TheOtherRoles.sln +++ b/TheOtherRoles.sln @@ -1,6 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheOtherRoles", "TheOtherRoles\TheOtherRoles.csproj", "{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}" +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheOtherRoles", "TheOtherRoles\TheOtherRoles.csproj", "{11FBC798-BAF5-4EE5-9511-BE6DB0592F99}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TheOtherUpdater", "TheOtherUpdater\TheOtherUpdater.vcxproj", "{73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}" EndProject @@ -19,4 +22,10 @@ Global {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Release|Any CPU.ActiveCfg = Release|Win32 {73A5662B-9C59-4C97-95C5-F5B2A8BBDDCA}.Release|Any CPU.Build.0 = Release|Win32 EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0CC3F51E-CC66-4122-B4CB-3A0B59DE563C} + EndGlobalSection EndGlobal diff --git a/TheOtherRoles/Buttons.cs b/TheOtherRoles/Buttons.cs index 763bbda98..7c56ec1c5 100644 --- a/TheOtherRoles/Buttons.cs +++ b/TheOtherRoles/Buttons.cs @@ -277,7 +277,7 @@ private static void setButtonTargetDisplay(PlayerControl target, CustomButton bu // Add poolable player to the button so that the target outfit is shown button.actionButton.cooldownTimerText.transform.localPosition = new Vector3(0, 0, -1f); // Before the poolable player targetDisplay = UnityEngine.Object.Instantiate(Patches.IntroCutsceneOnDestroyPatch.playerPrefab, button.actionButton.transform); - GameData.PlayerInfo data = target.Data; + NetworkedPlayerInfo data = target.Data; target.SetPlayerMaterialColors(targetDisplay.cosmetics.currentBodySprite.BodySprite); targetDisplay.SetSkin(data.DefaultOutfit.SkinId, data.DefaultOutfit.ColorId); targetDisplay.SetHat(data.DefaultOutfit.HatId, data.DefaultOutfit.ColorId); @@ -364,7 +364,7 @@ public static void createButtonsPostfix(HudManager __instance) { Vector2 truePosition2 = component.TruePosition; if (Vector2.Distance(truePosition2, truePosition) <= CachedPlayer.LocalPlayer.PlayerControl.MaxReportDistance && CachedPlayer.LocalPlayer.PlayerControl.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false)) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); + NetworkedPlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.CleanBody, Hazel.SendOption.Reliable, -1); writer.Write(playerInfo.PlayerId); @@ -1177,7 +1177,7 @@ public static void createButtonsPostfix(HudManager __instance) { Vector2 truePosition2 = component.TruePosition; if (Vector2.Distance(truePosition2, truePosition) <= CachedPlayer.LocalPlayer.PlayerControl.MaxReportDistance && CachedPlayer.LocalPlayer.PlayerControl.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false)) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); + NetworkedPlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.CleanBody, Hazel.SendOption.Reliable, -1); writer.Write(playerInfo.PlayerId); @@ -1448,7 +1448,7 @@ public static void createButtonsPostfix(HudManager __instance) { Vector2 truePosition = CachedPlayer.LocalPlayer.PlayerControl.GetTruePosition(); Vector2 truePosition2 = component.TruePosition; if (Vector2.Distance(truePosition2, truePosition) <= CachedPlayer.LocalPlayer.PlayerControl.MaxReportDistance && CachedPlayer.LocalPlayer.PlayerControl.CanMove && !PhysicsHelpers.AnythingBetween(truePosition, truePosition2, Constants.ShipAndObjectsMask, false)) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); + NetworkedPlayerInfo playerInfo = GameData.Instance.GetPlayerById(component.ParentId); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.CleanBody, Hazel.SendOption.Reliable, -1); writer.Write(playerInfo.PlayerId); @@ -1796,7 +1796,7 @@ public static void createButtonsPostfix(HudManager __instance) { // Bomber button bomberButton = new CustomButton( () => { - if (Helpers.checkMuderAttempt(Bomber.bomber, Bomber.bomber) != MurderAttemptResult.BlankKill) { + if (Helpers.checkMuderAttempt(Bomber.bomber, Bomber.bomber, ignoreMedic: true) != MurderAttemptResult.BlankKill) { var pos = CachedPlayer.LocalPlayer.transform.position; byte[] buff = new byte[sizeof(float) * 2]; Buffer.BlockCopy(BitConverter.GetBytes(pos.x), 0, buff, 0 * sizeof(float), sizeof(float)); @@ -1931,7 +1931,6 @@ public static void createButtonsPostfix(HudManager __instance) { Buffer.BlockCopy(BitConverter.GetBytes(pos.y), 0, buff, 1 * sizeof(float), sizeof(float)); if (Yoyo.markedLocation == null) { - TheOtherRolesPlugin.Logger.LogMessage($"marked location is null in button press"); MessageWriter writer = AmongUsClient.Instance.StartRpc(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YoyoMarkLocation, Hazel.SendOption.Reliable); writer.WriteBytesAndSize(buff); writer.EndMessage(); @@ -1942,9 +1941,7 @@ public static void createButtonsPostfix(HudManager __instance) { yoyoButton.HasEffect = false; yoyoButton.buttonText = "Blink"; } else { - TheOtherRolesPlugin.Logger.LogMessage("in else for some reason"); // Jump to location - TheOtherRolesPlugin.Logger.LogMessage($"trying to blink!"); var exit = (Vector3)Yoyo.markedLocation; if (SubmergedCompatibility.IsSubmerged) { SubmergedCompatibility.ChangeFloor(exit.y > -7); @@ -2061,7 +2058,7 @@ public static void createButtonsPostfix(HudManager __instance) { }, () => { return true; }, () => { return; }, - Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MinusButton.png", 150f), // Invisible button! + null, // Invisible button! new Vector3(0.4f, 2.8f, 0), __instance, KeyCode.KeypadPlus diff --git a/TheOtherRoles/CustomGameModes/GameModePatches.cs b/TheOtherRoles/CustomGameModes/GameModePatches.cs new file mode 100644 index 000000000..9aa18d61f --- /dev/null +++ b/TheOtherRoles/CustomGameModes/GameModePatches.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Epic.OnlineServices.Presence; +using HarmonyLib; +using TheOtherRoles.Utilities; +using TMPro; +using UnityEngine; +using static UnityEngine.UI.Button; +using UnityEngine.Events; +using Hazel; +using TheOtherRoles.Players; + +namespace TheOtherRoles.CustomGameModes { + [HarmonyPatch] + class GameModePatches { + /* + Creates a button in the info pane in the lobby to cycle through the game modes of TOR. + */ + [HarmonyPatch(typeof(LobbyInfoPane), nameof(LobbyInfoPane.Update))] + class LobbyInfoPanePatch { + + private static GameObject gameModeButton = null; + public static void Postfix(LobbyInfoPane __instance) { + if (gameModeButton != null|| !AmongUsClient.Instance.AmHost) { return; } + + var template = GameObject.Find("PRIVATE BUTTON"); + var GameModeText = GameObject.Find("GameModeText"); + if (template == null || GameModeText== null) { return; } + gameModeButton = GameObject.Instantiate(template, template.transform.parent); //, GameModeText.transform); + gameModeButton.transform.localPosition = template.transform.localPosition + new Vector3(0f, 0.65f, -2f); + gameModeButton.name = "TOR GameModeButton"; + + var pButton = gameModeButton.GetComponent(); + pButton.buttonText.text = GameModeText.GetComponent().text; + pButton.OnClick.RemoveAllListeners(); + pButton.OnClick = new ButtonClickedEvent(); + __instance.StartCoroutine(Effects.Lerp(0.1f, new Action(p => { pButton.buttonText.text = Helpers.cs(Color.yellow, GameModeText.GetComponent().text); }))); + gameModeButton.transform.GetChild(1).GetComponent().color = new Color(0.1f, 0.1f, 0.1f); + gameModeButton.transform.GetChild(2).GetComponent().color = new Color(0f, 0f, 0f); + pButton.OnClick.AddListener((Action)(() => + { + TORMapOptions.gameMode = (CustomGamemodes)((int)(TORMapOptions.gameMode + 1) % Enum.GetNames(typeof(CustomGamemodes)).Length); + __instance.StartCoroutine(Effects.Lerp(0.1f, new Action(p => { pButton.buttonText.text = Helpers.cs(Color.yellow, GameModeText.GetComponent().text); }))); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareGamemode, Hazel.SendOption.Reliable, -1); + writer.Write((byte)TORMapOptions.gameMode); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.shareGamemode((byte)TORMapOptions.gameMode); + })); + pButton.OnMouseOut = new UnityEvent(); + pButton.OnMouseOver = new UnityEvent(); + pButton.OnMouseOver.AddListener((Action)(() => { + gameModeButton.transform.GetChild(1).gameObject.SetActive(true); + gameModeButton.transform.GetChild(2).gameObject.SetActive(false); + })); + pButton.OnMouseOut.AddListener((Action)(() => { + gameModeButton.transform.GetChild(1).gameObject.SetActive(false); + gameModeButton.transform.GetChild(2).gameObject.SetActive(true); + })); + + } + } + } +} diff --git a/TheOtherRoles/CustomGameModes/PropHunt.cs b/TheOtherRoles/CustomGameModes/PropHunt.cs index 633e14002..7d0aa0635 100644 --- a/TheOtherRoles/CustomGameModes/PropHunt.cs +++ b/TheOtherRoles/CustomGameModes/PropHunt.cs @@ -12,6 +12,8 @@ using TheOtherRoles.Utilities; using TMPro; using UnityEngine; +using static TheOtherRoles.Snitch; +using static UnityEngine.GraphicsBuffer; namespace TheOtherRoles.CustomGameModes { [HarmonyPatch] @@ -122,17 +124,13 @@ public static Sprite getIntroSprite(int index) { return Helpers.loadSpriteFromResources($"TheOtherRoles.Resources.IntroAnimation.intro_{index + 1000}.png", 150f, cache: false); } - public static void updateWhitelistedObjects() { + public static void updateWhitelistedObjects(bool debug=false) { string allNames = Helpers.readTextFromResources("TheOtherRoles.Resources.Txt.Props.txt"); - bool debug = false; if (debug) { allNames = Helpers.readTextFromFile(System.IO.Directory.GetCurrentDirectory() + "\\Props.txt"); } - TheOtherRolesPlugin.Logger.LogMessage($"after debug"); + whitelistedObjects = allNames.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).ToList(); - TheOtherRolesPlugin.Logger.LogMessage($"after split"); - - TheOtherRolesPlugin.Logger.LogMessage($"Last element: {whitelistedObjects.Last()}"); } @@ -172,6 +170,7 @@ public static void poolablePlayerUpdate() { if (poolablesBackground == null) { poolablesBackground = new GameObject("poolablesBackground"); poolablesBackground.AddComponent(); + poolablesBackground.layer = LayerMask.NameToLayer("UI"); if (poolablesBackgroundSprite == null) poolablesBackgroundSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.poolablesBackground.jpg", 200f); } poolablesBackground.transform.SetParent(HudManager.Instance.transform); @@ -193,15 +192,13 @@ public static void poolablePlayerUpdate() { poolablePlayer.cosmetics.nameText.fontSize = 4; } else { // Display Prop - poolablePlayer.cosmetics.nameText.text = Helpers.cs(Palette.CrewmateBlue, pc.Data.PlayerName); ; - if (isCurrentlyRevealed.ContainsKey(pc.PlayerId)) { - - } + poolablePlayer.cosmetics.nameText.text = Helpers.cs(Palette.CrewmateBlue, pc.Data.PlayerName); } // update currently revealed: if (isCurrentlyRevealed.ContainsKey(pc.PlayerId)) { if (!revealRenderer.ContainsKey(pc.PlayerId)) { var go = new GameObject($"reveal_renderer_{pc.PlayerId}"); + go.layer = LayerMask.NameToLayer("UI"); go.AddComponent(); go.transform.SetParent(poolablePlayer.transform.parent, false); go.SetActive(true); @@ -257,6 +254,7 @@ public static void speedboostUpdate() { } public static void dangerMeterUpdate() { + if (!HudManager.Instance || !HudManager.Instance.DangerMeter) return; if (HudManager.Instance.DangerMeter.gameObject.active) { float dist = 55f; float dist2 = 15f; @@ -358,7 +356,7 @@ public static GameObject FindClosestDisguiseObject(GameObject origin, float radi Collider2D bestCollider = null; float bestDist = 9999; if (whitelistedObjects == null || whitelistedObjects.Count == 0 || verbose) { - updateWhitelistedObjects(); + updateWhitelistedObjects(true); } foreach (Collider2D collider in Physics2D.OverlapCircleAll(origin.transform.position, radius)) { if (verbose) { @@ -522,7 +520,7 @@ public static void MapSetPostfix() { // Make sure the map in the settings is in [HarmonyPatch(typeof(MapConsole), nameof(MapConsole.CanUse))] [HarmonyPostfix] - public static void AdminCanUsePostfix(MapConsole __instance, GameData.PlayerInfo pc, ref bool canUse, ref bool couldUse, ref float __result) { + public static void AdminCanUsePostfix(MapConsole __instance, NetworkedPlayerInfo pc, ref bool canUse, ref bool couldUse, ref float __result) { if (!PropHunt.isPropHuntGM || !PlayerControl.LocalPlayer.Data.Role.IsImpostor) return; if (canUse) { if (HudManagerStartPatch.propHuntAdminButton.Timer > 0) { @@ -565,7 +563,7 @@ public static void KillButtonHighlightPatch(ActionButton __instance) { [HarmonyPrefix] public static bool CheckClickPatch(KillButton __instance) { if (!PropHunt.isPropHuntGM) return true; - __instance.DoClick(); + __instance.DoClick(); return false; } @@ -574,7 +572,7 @@ public static bool CheckClickPatch(KillButton __instance) { [HarmonyPrefix] public static bool KillButtonClickPatch(KillButton __instance) { if (!PropHunt.isPropHuntGM || __instance.isCoolingDown || PlayerControl.LocalPlayer.Data.IsDead || PlayerControl.LocalPlayer.inVent) return false; - + var targets = PlayerControl.LocalPlayer.Data.Role.GetPlayersInAbilityRangeSorted(RoleBehaviour.GetTempPlayerList(), true).ToArray(); __instance.SetTarget(PlayerControl.LocalPlayer.Data.Role.GetPlayersInAbilityRangeSorted(RoleBehaviour.GetTempPlayerList(), true).ToArray().FirstOrDefault()); if (__instance.currentTarget == null) { @@ -587,6 +585,14 @@ public static bool KillButtonClickPatch(KillButton __instance) { return false; } + [HarmonyPatch(typeof(RoleBehaviour), nameof(RoleBehaviour.IsValidTarget))] + [HarmonyPrefix] + public static bool IsValidTarget(RoleBehaviour __instance, NetworkedPlayerInfo target, ref bool __result) { + if (!PropHunt.isPropHuntGM) return true; + __result = !(target == null) && !target.Disconnected && !target.IsDead && target.PlayerId != __instance.Player.PlayerId && !(target.Role == null) && !(target.Object == null) && !target.Object.inVent && !target.Object.inMovingPlat; + return false; + } + [HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.Show))] [HarmonyPrefix] public static void MapBehaviourShowPatch(MapBehaviour __instance, ref MapOptions opts) { @@ -594,7 +600,7 @@ public static void MapBehaviourShowPatch(MapBehaviour __instance, ref MapOptions if (opts.Mode == MapOptions.Modes.Sabotage) opts.Mode = MapOptions.Modes.Normal; } - + // Disable a lot of stuff [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CmdReportDeadBody))] [HarmonyPatch(typeof(Vent), nameof(Vent.SetOutline))] diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 505590c0e..0b1772e06 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -426,22 +426,21 @@ 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); - anyPlayerCanStopStart = CustomOption.Create(2, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Any Player Can Stop The Start"), false, null, false); + if (Utilities.EventUtility.canBeEnabled) enableEventMode = CustomOption.Create(10423, Types.General, cs(Color.green, "Enable Special Mode"), true, null, true); // Using new id's for the options to not break compatibilty with older versions - crewmateRolesCountMin = CustomOption.Create(300, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Crewmate Roles"), 15f, 0f, 15f, 1f, null, true); - crewmateRolesCountMax = CustomOption.Create(301, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Crewmate Roles"), 15f, 0f, 15f, 1f); - crewmateRolesFill = CustomOption.Create(308, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Fill Crewmate Roles\n(Ignores Min/Max)"), false); + crewmateRolesCountMin = CustomOption.Create(300, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Crewmate Roles"), 15f, 0f, 15f, 1f, null, true, heading: "Min/Max Roles"); + crewmateRolesCountMax = CustomOption.Create(301, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Crewmate Roles"), 15f, 0f, 15f, 1f); neutralRolesCountMin = CustomOption.Create(302, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Neutral Roles"), 15f, 0f, 15f, 1f); neutralRolesCountMax = CustomOption.Create(303, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Neutral Roles"), 15f, 0f, 15f, 1f); impostorRolesCountMin = CustomOption.Create(304, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Impostor Roles"), 15f, 0f, 15f, 1f); impostorRolesCountMax = CustomOption.Create(305, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Impostor Roles"), 15f, 0f, 15f, 1f); modifiersCountMin = CustomOption.Create(306, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Minimum Modifiers"), 15f, 0f, 15f, 1f); modifiersCountMax = CustomOption.Create(307, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Maximum Modifiers"), 15f, 0f, 15f, 1f); - + crewmateRolesFill = CustomOption.Create(308, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Fill Crewmate Roles\n(Ignores Min/Max)"), false); + mafiaSpawnRate = CustomOption.Create(18, Types.Impostor, cs(Janitor.color, "Mafia"), rates, null, true); janitorCooldown = CustomOption.Create(19, Types.Impostor, "Janitor Cooldown", 30f, 10f, 60f, 2.5f, mafiaSpawnRate); @@ -687,7 +686,7 @@ public static void Load() { trapperTrapDuration = CustomOption.Create(454, Types.Crewmate, "Trap Duration", 5f, 1f, 15f, 1f, trapperSpawnRate); // Modifier (1000 - 1999) - modifiersAreHidden = CustomOption.Create(1009, Types.Modifier, cs(Color.yellow, "Hide After Death Modifiers"), true, null, true); + modifiersAreHidden = CustomOption.Create(1009, Types.Modifier, cs(Color.yellow, "VIP, Bait & Bloody Are Hidden"), true, null, true, heading: cs(Color.yellow, "Hide After Death Modifiers")); modifierBloody = CustomOption.Create(1000, Types.Modifier, cs(Color.yellow, "Bloody"), rates, null, true); modifierBloodyQuantity = CustomOption.Create(1001, Types.Modifier, cs(Color.yellow, "Bloody Quantity"), ratesModifier, modifierBloody); @@ -734,13 +733,13 @@ public static void Load() { modifierShifter = CustomOption.Create(1100, Types.Modifier, cs(Color.yellow, "Shifter"), rates, null, true); // Guesser Gamemode (2000 - 2999) - guesserGamemodeCrewNumber = CustomOption.Create(2001, Types.Guesser, cs(Guesser.color, "Number of Crew Guessers"), 15f, 1f, 15f, 1f, null, true); - guesserGamemodeNeutralNumber = CustomOption.Create(2002, Types.Guesser, cs(Guesser.color, "Number of Neutral Guessers"), 15f, 1f, 15f, 1f, null, true); - guesserGamemodeImpNumber = CustomOption.Create(2003, Types.Guesser, cs(Guesser.color, "Number of Impostor Guessers"), 15f, 1f, 15f, 1f, null, true); - guesserForceJackalGuesser = CustomOption.Create(2007, Types.Guesser, "Force Jackal Guesser", false, null, true); + guesserGamemodeCrewNumber = CustomOption.Create(2001, Types.Guesser, cs(Guesser.color, "Number of Crew Guessers"), 15f, 1f, 15f, 1f, null, true, heading: "Amount of Guessers"); + guesserGamemodeNeutralNumber = CustomOption.Create(2002, Types.Guesser, cs(Guesser.color, "Number of Neutral Guessers"), 15f, 1f, 15f, 1f, null); + guesserGamemodeImpNumber = CustomOption.Create(2003, Types.Guesser, cs(Guesser.color, "Number of Impostor Guessers"), 15f, 1f, 15f, 1f, null); + guesserForceJackalGuesser = CustomOption.Create(2007, Types.Guesser, "Force Jackal Guesser", false, null, true, heading: "Force Guessers"); guesserGamemodeSidekickIsAlwaysGuesser = CustomOption.Create(2012, Types.Guesser, "Sidekick Is Always Guesser", false, null); - guesserForceThiefGuesser = CustomOption.Create(2011, Types.Guesser, "Force Thief Guesser", false, null, true); - guesserGamemodeHaveModifier = CustomOption.Create(2004, Types.Guesser, "Guessers Can Have A Modifier", true, null); + guesserForceThiefGuesser = CustomOption.Create(2011, Types.Guesser, "Force Thief Guesser", false, null); + guesserGamemodeHaveModifier = CustomOption.Create(2004, Types.Guesser, "Guessers Can Have A Modifier", true, null, true, heading: "General Guesser Settings"); guesserGamemodeNumberOfShots = CustomOption.Create(2005, Types.Guesser, "Guesser Number Of Shots", 3f, 1f, 15f, 1f, null); guesserGamemodeHasMultipleShotsPerMeeting = CustomOption.Create(2006, Types.Guesser, "Guesser Can Shoot Multiple Times Per Meeting", false, null); guesserGamemodeKillsThroughShield = CustomOption.Create(2008, Types.Guesser, "Guesses Ignore The Medic Shield", true, null); @@ -764,7 +763,7 @@ public static void Load() { hideNSeekCanSabotage = CustomOption.Create(3019, Types.HideNSeekMain, cs(Color.yellow, "Enable Sabotages"), false); hideNSeekHunterWaiting = CustomOption.Create(3022, Types.HideNSeekMain, cs(Color.yellow, "Time The Hunter Needs To Wait"), 15f, 2.5f, 60f, 2.5f); - hunterLightCooldown = CustomOption.Create(3005, Types.HideNSeekRoles, cs(Color.red, "Hunter Light Cooldown"), 30f, 5f, 60f, 1f, null, true); + hunterLightCooldown = CustomOption.Create(3005, Types.HideNSeekRoles, cs(Color.red, "Hunter Light Cooldown"), 30f, 5f, 60f, 1f, null, true, heading: "Hunter Lights Settings"); hunterLightDuration = CustomOption.Create(3006, Types.HideNSeekRoles, cs(Color.red, "Hunter Light Duration"), 5f, 1f, 60f, 1f); hunterLightVision = CustomOption.Create(3007, Types.HideNSeekRoles, cs(Color.red, "Hunter Light Vision"), 3f, 1f, 5f, 0.25f); hunterLightPunish = CustomOption.Create(3008, Types.HideNSeekRoles, cs(Color.red, "Hunter Light Punish In Sec"), 5f, 0f, 30f, 1f); @@ -775,20 +774,20 @@ public static void Load() { hunterArrowDuration = CustomOption.Create(3013, Types.HideNSeekRoles, cs(Color.red, "Hunter Arrow Duration"), 5f, 0f, 60f, 1f); hunterArrowPunish = CustomOption.Create(3014, Types.HideNSeekRoles, cs(Color.red, "Hunter Arrow Punish In Sec"), 5f, 0f, 30f, 1f); - huntedShieldCooldown = CustomOption.Create(3015, Types.HideNSeekRoles, cs(Color.gray, "Hunted Shield Cooldown"), 30f, 5f, 60f, 1f, null, true); + huntedShieldCooldown = CustomOption.Create(3015, Types.HideNSeekRoles, cs(Color.gray, "Hunted Shield Cooldown"), 30f, 5f, 60f, 1f, null, true, heading: "Hunter Shields Settings"); huntedShieldDuration = CustomOption.Create(3016, Types.HideNSeekRoles, cs(Color.gray, "Hunted Shield Duration"), 5f, 1f, 60f, 1f); huntedShieldRewindTime = CustomOption.Create(3018, Types.HideNSeekRoles, cs(Color.gray, "Hunted Rewind Time"), 3f, 1f, 10f, 1f); huntedShieldNumber = CustomOption.Create(3026, Types.HideNSeekRoles, cs(Color.gray, "Hunted Shield Number"), 3f, 1f, 15f, 1f); // Prop Hunt General Options propHuntMap = CustomOption.Create(4020, Types.PropHunt, cs(Color.yellow, "Map"), new string[] { "The Skeld", "Mira", "Polus", "Airship", "Fungle", "Submerged", "LI Map"}, null, true, onChange: ()=> { int map = propHuntMap.selection; if (map >= 3) map++; GameOptionsManager.Instance.currentNormalGameOptions.MapId = (byte)map;}); - propHuntTimer = CustomOption.Create(4021, Types.PropHunt, cs(Color.yellow, "Timer In Min"), 5f, 1f, 30f, 0.5f); + propHuntTimer = CustomOption.Create(4021, Types.PropHunt, cs(Color.yellow, "Timer In Min"), 5f, 1f, 30f, 0.5f, null, true, heading: "General PropHunt Settings"); propHuntUnstuckCooldown = CustomOption.Create(4011, Types.PropHunt, cs(Color.yellow, "Unstuck Cooldown"), 30f, 2.5f, 60f, 2.5f); propHuntUnstuckDuration = CustomOption.Create(4012, Types.PropHunt, cs(Color.yellow, "Unstuck Duration"), 2f, 1f, 60f, 1f); propHunterVision = CustomOption.Create(4006, Types.PropHunt, cs(Color.yellow, "Hunter Vision"), 0.5f, 0.25f, 2f, 0.25f); propVision = CustomOption.Create(4007, Types.PropHunt, cs(Color.yellow, "Prop Vision"), 2f, 0.25f, 5f, 0.25f); // Hunter Options - propHuntNumberOfHunters = CustomOption.Create(4000, Types.PropHunt, cs(Color.red, "Number Of Hunters"), 1f, 1f, 5f, 1f, null, true); + propHuntNumberOfHunters = CustomOption.Create(4000, Types.PropHunt, cs(Color.red, "Number Of Hunters"), 1f, 1f, 5f, 1f, null, true, heading: "Hunter Settings"); hunterInitialBlackoutTime = CustomOption.Create(4001, Types.PropHunt, cs(Color.red, "Hunter Initial Blackout Duration"), 10f, 5f, 20f, 1f); hunterMissCooldown = CustomOption.Create(4004, Types.PropHunt, cs(Color.red, "Kill Cooldown After Miss"), 10f, 2.5f, 60f, 2.5f); hunterHitCooldown = CustomOption.Create(4005, Types.PropHunt, cs(Color.red, "Kill Cooldown After Hit"), 10f, 2.5f, 60f, 2.5f); @@ -799,7 +798,7 @@ public static void Load() { propHuntFindCooldown = CustomOption.Create(4023, Types.PropHunt, cs(Color.red, "Find Cooldown"), 60f, 2.5f, 1800f, 2.5f); propHuntFindDuration = CustomOption.Create(4024, Types.PropHunt, cs(Color.red, "Find Duration"), 5f, 1f, 15f, 1f); // Prop Options - propBecomesHunterWhenFound = CustomOption.Create(4003, Types.PropHunt, cs(Palette.CrewmateBlue, "Props Become Hunters When Found"), false, null, true); + propBecomesHunterWhenFound = CustomOption.Create(4003, Types.PropHunt, cs(Palette.CrewmateBlue, "Props Become Hunters When Found"), false, null, true, heading: "Prop Settings"); propHuntInvisEnabled = CustomOption.Create(4013, Types.PropHunt, cs(Palette.CrewmateBlue, "Invisibility Enabled"), true, null, true); propHuntInvisCooldown = CustomOption.Create(4014, Types.PropHunt, cs(Palette.CrewmateBlue, "Invisibility Cooldown"), 120f, 10f, 1800f, 2.5f, propHuntInvisEnabled); propHuntInvisDuration = CustomOption.Create(4015, Types.PropHunt, cs(Palette.CrewmateBlue, "Invisibility Duration"), 5f, 1f, 30f, 1f, propHuntInvisEnabled); @@ -811,19 +810,21 @@ public static void Load() { // Other options - maxNumberOfMeetings = CustomOption.Create(3, Types.General, "Number Of Meetings (excluding Mayor meeting)", 10, 0, 15, 1, null, true); + maxNumberOfMeetings = CustomOption.Create(3, Types.General, "Number Of Meetings (excluding Mayor meeting)", 10, 0, 15, 1, null, true, heading: "Gameplay Settings"); + anyPlayerCanStopStart = CustomOption.Create(2, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0, 1f), "Any Player Can Stop The Start"), false, null, false); blockSkippingInEmergencyMeetings = CustomOption.Create(4, Types.General, "Block Skipping In Emergency Meetings", false); noVoteIsSelfVote = CustomOption.Create(5, Types.General, "No Vote Is Self Vote", false, blockSkippingInEmergencyMeetings); 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); finishTasksBeforeHauntingOrZoomingOut = CustomOption.Create(9, Types.General, "Finish Tasks Before Haunting Or Zooming Out", true); - camsNightVision = CustomOption.Create(11, Types.General, "Cams Switch To Night Vision If Lights Are Off", false, null, true); + deadImpsBlockSabotage = CustomOption.Create(13, Types.General, "Block Dead Impostor From Sabotaging", false, null, false); + camsNightVision = CustomOption.Create(11, Types.General, "Cams Switch To Night Vision If Lights Are Off", false, null, true, heading: "Night Vision Cams"); camsNoNightVisionIfImpVision = CustomOption.Create(12, Types.General, "Impostor Vision Ignores Night Vision Cams", false, camsNightVision, false); - deadImpsBlockSabotage = CustomOption.Create(13, Types.General, cs(Palette.ImpostorRed, "Block Dead Impostor From Sabotaging"), false, null, false); - dynamicMap = CustomOption.Create(500, Types.General, "Play On A Random Map", false, null, true); + + dynamicMap = CustomOption.Create(500, Types.General, "Play On A Random Map", false, null, true, heading: "Random Maps"); dynamicMapEnableSkeld = CustomOption.Create(501, Types.General, "Skeld", rates, dynamicMap, false); dynamicMapEnableMira = CustomOption.Create(502, Types.General, "Mira", rates, dynamicMap, false); dynamicMapEnablePolus = CustomOption.Create(503, Types.General, "Polus", rates, dynamicMap, false); diff --git a/TheOtherRoles/Helpers.cs b/TheOtherRoles/Helpers.cs index 3071494f2..5f587171b 100644 --- a/TheOtherRoles/Helpers.cs +++ b/TheOtherRoles/Helpers.cs @@ -357,7 +357,7 @@ public static void setDefaultLook(this PlayerControl target, bool enforceNightVi if (Helpers.MushroomSabotageActive()) { var instance = ShipStatus.Instance.CastFast().specialSabotage; MushroomMixupSabotageSystem.CondensedOutfit condensedOutfit = instance.currentMixups[target.PlayerId]; - GameData.PlayerOutfit playerOutfit = instance.ConvertToPlayerOutfit(condensedOutfit); + NetworkedPlayerInfo.PlayerOutfit playerOutfit = instance.ConvertToPlayerOutfit(condensedOutfit); target.MixUpOutfit(playerOutfit); } else target.setLook(target.Data.PlayerName, target.Data.DefaultOutfit.ColorId, target.Data.DefaultOutfit.HatId, target.Data.DefaultOutfit.VisorId, target.Data.DefaultOutfit.SkinId, target.Data.DefaultOutfit.PetId, enforceNightVisionUpdate); @@ -450,7 +450,7 @@ public static bool roleCanUseVents(this PlayerControl player) { return roleCouldUse; } - public static MurderAttemptResult checkMuderAttempt(PlayerControl killer, PlayerControl target, bool blockRewind = false, bool ignoreBlank = false, bool ignoreIfKillerIsDead = false) { + public static MurderAttemptResult checkMuderAttempt(PlayerControl killer, PlayerControl target, bool blockRewind = false, bool ignoreBlank = false, bool ignoreIfKillerIsDead = false, bool ignoreMedic = false) { var targetRole = RoleInfo.getRoleInfoForPlayer(target, false).FirstOrDefault(); // Modified vanilla checks @@ -474,7 +474,7 @@ public static MurderAttemptResult checkMuderAttempt(PlayerControl killer, Player } // Block impostor shielded kill - if (Medic.shielded != null && Medic.shielded == target) { + if (!ignoreMedic && Medic.shielded != null && Medic.shielded == target) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(killer.NetId, (byte)CustomRPC.ShieldedMurderAttempt, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.shieldedMurderAttempt(); @@ -606,10 +606,15 @@ public static void toggleZoom(bool reset=false) { if (cam != null && cam.gameObject.name == "UI Camera") cam.orthographicSize = orthographicSize; // The UI is scaled too, else we cant click the buttons. Downside: map is super small. } - if (HudManagerStartPatch.zoomOutButton != null) { - HudManagerStartPatch.zoomOutButton.Sprite = zoomOutStatus ? Helpers.loadSpriteFromResources("TheOtherRoles.Resources.PlusButton.png", 75f) : Helpers.loadSpriteFromResources("TheOtherRoles.Resources.MinusButton.png", 150f); - HudManagerStartPatch.zoomOutButton.PositionOffset = zoomOutStatus ? new Vector3(0f, 3f, 0) : new Vector3(0.4f, 2.8f, 0); + var tzGO = GameObject.Find("TOGGLEZOOMBUTTON"); + if (tzGO != null) { + var rend = tzGO.transform.Find("Inactive").GetComponent(); + var rendActive = tzGO.transform.Find("Active").GetComponent(); + rend.sprite = zoomOutStatus ? Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Plus_Button.png", 100f) : Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Minus_Button.png", 100f); + rendActive.sprite = zoomOutStatus ? Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Plus_ButtonActive.png", 100f) : Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Minus_ButtonActive.png", 100f); + tzGO.transform.localScale = new Vector3(1.2f, 1.2f, 1f) * (zoomOutStatus ? 4 : 1); } + ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen); // This will move button positions to the correct position. } @@ -654,7 +659,7 @@ public static async Task checkBeta() { } } - public static bool hasImpVision(GameData.PlayerInfo player) { + public static bool hasImpVision(NetworkedPlayerInfo player) { return player.Role.IsImpostor || ((Jackal.jackal != null && Jackal.jackal.PlayerId == player.PlayerId || Jackal.formerJackals.Any(x => x.PlayerId == player.PlayerId)) && Jackal.hasImpostorVision) || (Sidekick.sidekick != null && Sidekick.sidekick.PlayerId == player.PlayerId && Sidekick.hasImpostorVision) diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index bc502cea0..066a0bff3 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -33,7 +33,7 @@ namespace TheOtherRoles public class TheOtherRolesPlugin : BasePlugin { public const string Id = "me.eisbison.theotherroles"; - public const string VersionString = "4.5.3"; + public const string VersionString = "4.6.0"; public static uint betaDays = 0; // amount of days for the build to be usable (0 for infinite!) public static Version Version = Version.Parse(VersionString); @@ -54,6 +54,7 @@ public class TheOtherRolesPlugin : BasePlugin public static ConfigEntry EnableSoundEffects { get; set; } public static ConfigEntry EnableHorseMode { get; set; } public static ConfigEntry ShowVentsOnMap { get; set; } + public static ConfigEntry ShowChatNotifications { get; set; } public static ConfigEntry Ip { get; set; } public static ConfigEntry Port { get; set; } public static ConfigEntry ShowPopUpVersion { get; set; } @@ -108,11 +109,13 @@ public override void Load() { EnableHorseMode = Config.Bind("Custom", "Enable Horse Mode", false); ShowPopUpVersion = Config.Bind("Custom", "Show PopUp", "0"); ShowVentsOnMap = Config.Bind("Custom", "Show vent positions on minimap", false); - + ShowChatNotifications = Config.Bind("Custom", "Show Chat Notifications", true); + Ip = Config.Bind("Custom", "Custom Server IP", "127.0.0.1"); Port = Config.Bind("Custom", "Custom Server Port", (ushort)22023); defaultRegions = ServerManager.DefaultRegions; - + // Removes vanilla Servers + ServerManager.DefaultRegions = new Il2CppReferenceArray(new IRegionInfo[0]); UpdateRegions(); DebugMode = Config.Bind("Custom", "Enable Debug Mode", "false"); @@ -178,12 +181,12 @@ public static void Postfix(KeyboardJoystick __instance) // Spawn dummys - if (Input.GetKeyDown(KeyCode.F)) { + /*if (Input.GetKeyDown(KeyCode.F)) { var playerControl = UnityEngine.Object.Instantiate(AmongUsClient.Instance.PlayerPrefab); var i = playerControl.PlayerId = (byte) GameData.Instance.GetAvailableId(); bots.Add(playerControl); - GameData.Instance.AddPlayer(playerControl); + GameData.Instance.AddPlayer(playerControl, new InnerNet.ClientData(0)); AmongUsClient.Instance.Spawn(playerControl, -2, InnerNet.SpawnFlags.None); playerControl.transform.position = CachedPlayer.LocalPlayer.transform.position; @@ -191,8 +194,8 @@ public static void Postfix(KeyboardJoystick __instance) playerControl.NetTransform.enabled = false; playerControl.SetName(RandomString(10)); playerControl.SetColor((byte) random.Next(Palette.PlayerColors.Length)); - GameData.Instance.RpcSetTasks(playerControl.PlayerId, new byte[0]); - } + playerControl.Data.RpcSetTasks(new byte[0]); + }*/ // Terminate round if(Input.GetKeyDown(KeyCode.L)) { diff --git a/TheOtherRoles/MapOptions.cs b/TheOtherRoles/MapOptions.cs index 83cce2d65..7df9c3071 100644 --- a/TheOtherRoles/MapOptions.cs +++ b/TheOtherRoles/MapOptions.cs @@ -19,6 +19,7 @@ static class TORMapOptions { public static bool enableHorseMode = false; public static bool shieldFirstKill = false; public static bool ShowVentsOnMap = true; + public static bool ShowChatNotifications = true; public static CustomGamemodes gameMode = CustomGamemodes.Classic; // Updating values @@ -54,7 +55,8 @@ public static void reloadPluginOptions() { enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value; enableHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; ShowVentsOnMap = TheOtherRolesPlugin.ShowVentsOnMap.Value; - + ShowChatNotifications = TheOtherRolesPlugin.ShowChatNotifications.Value; + //Patches.ShouldAlwaysHorseAround.isHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; } } diff --git a/TheOtherRoles/Modules/BepInExUpdater.cs b/TheOtherRoles/Modules/BepInExUpdater.cs index 42b3591e4..4f994a705 100644 --- a/TheOtherRoles/Modules/BepInExUpdater.cs +++ b/TheOtherRoles/Modules/BepInExUpdater.cs @@ -19,8 +19,8 @@ namespace TheOtherRoles.Modules; public class BepInExUpdater : MonoBehaviour { - public const string RequiredBepInExVersion = "6.0.0-be.688+49015217f3becf052d33fa4658ac19229f5daa3a"; - public const string BepInExDownloadURL = "https://builds.bepinex.dev/projects/bepinex_be/688/BepInEx-Unity.IL2CPP-win-x86-6.0.0-be.688%2B4901521.zip"; + public const string RequiredBepInExVersion = "6.0.0-be.692+851521cc126e4f9d841d2d9bfe857558f0395939"; + public const string BepInExDownloadURL = "https://builds.bepinex.dev/projects/bepinex_be/692/BepInEx-Unity.IL2CPP-win-x86-6.0.0-be.692%2B851521c.zip"; public static bool UpdateRequired => Paths.BepInExVersion.ToString() != RequiredBepInExVersion; public void Awake() diff --git a/TheOtherRoles/Modules/ChatCommands.cs b/TheOtherRoles/Modules/ChatCommands.cs index 4cabe69da..331a91363 100644 --- a/TheOtherRoles/Modules/ChatCommands.cs +++ b/TheOtherRoles/Modules/ChatCommands.cs @@ -115,7 +115,7 @@ public static void Postfix(HudManager __instance) { public static class SetBubbleName { public static void Postfix(ChatBubble __instance, [HarmonyArgument(0)] string playerName) { PlayerControl sourcePlayer = PlayerControl.AllPlayerControls.ToArray().ToList().FirstOrDefault(x => x.Data != null && x.Data.PlayerName.Equals(playerName)); - if (CachedPlayer.LocalPlayer != null && CachedPlayer.LocalPlayer.Data.Role.IsImpostor && (Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId || Sidekick.sidekick != null && Sidekick.wasTeamRed && sourcePlayer.PlayerId == Sidekick.sidekick.PlayerId || Jackal.jackal != null && Jackal.wasTeamRed && sourcePlayer.PlayerId == Jackal.jackal.PlayerId) && __instance != null) __instance.NameText.color = Palette.ImpostorRed; + if (sourcePlayer != null && CachedPlayer.LocalPlayer != null && CachedPlayer.LocalPlayer.Data?.Role?.IsImpostor == true && (Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId || Sidekick.sidekick != null && Sidekick.wasTeamRed && sourcePlayer.PlayerId == Sidekick.sidekick.PlayerId || Jackal.jackal != null && Jackal.wasTeamRed && sourcePlayer.PlayerId == Jackal.jackal.PlayerId) && __instance != null) __instance.NameText.color = Palette.ImpostorRed; } } diff --git a/TheOtherRoles/Modules/CustomColors.cs b/TheOtherRoles/Modules/CustomColors.cs index 495af2413..980055350 100644 --- a/TheOtherRoles/Modules/CustomColors.cs +++ b/TheOtherRoles/Modules/CustomColors.cs @@ -184,6 +184,36 @@ public static bool Prefix(ref string __result, [HarmonyArgument(0)] StringNames return true; } } + + [HarmonyPatch(typeof(ChatNotification), nameof(ChatNotification.SetUp))] + private class ChatNotificationColorsPatch { + public static bool Prefix(ChatNotification __instance, PlayerControl sender, string text) { + if (ShipStatus.Instance && !TORMapOptions.ShowChatNotifications) { + return false; + } + __instance.timeOnScreen = 5f; + __instance.gameObject.SetActive(true); + __instance.SetCosmetics(sender.Data); + string str; + Color color; + try { + str = ColorUtility.ToHtmlStringRGB(Palette.TextColors[__instance.player.ColorId]); + color = Palette.TextOutlineColors[__instance.player.ColorId]; + } catch { + Color32 c = Palette.PlayerColors[__instance.player.ColorId]; + str = ColorUtility.ToHtmlStringRGB(c); + + color = c.r + c.g + c.b > 180 ? Palette.Black : Palette.White; + TheOtherRolesPlugin.Logger.LogMessage($"{c.r}, {c.g}, {c.b}"); + } + __instance.playerColorText.text = __instance.player.ColorBlindName; + __instance.playerNameText.text = "" + (string.IsNullOrEmpty(sender.Data.PlayerName) ? "..." : sender.Data.PlayerName); + __instance.playerNameText.outlineColor = color; + __instance.chatText.text = text; + return false; + } + } + [HarmonyPatch(typeof(PlayerTab), nameof(PlayerTab.OnEnable))] private static class PlayerTabEnablePatch { public static void Postfix(PlayerTab __instance) { // Replace instead @@ -224,7 +254,7 @@ public static void Postfix() { [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CheckColor))] private static class PlayerControlCheckColorPatch { private static bool isTaken(PlayerControl player, uint color) { - foreach (GameData.PlayerInfo p in GameData.Instance.AllPlayers.GetFastEnumerator()) + foreach (NetworkedPlayerInfo p in GameData.Instance.AllPlayers.GetFastEnumerator()) if (!p.Disconnected && p.PlayerId != player.PlayerId && p.DefaultOutfit.ColorId == color) return true; return false; diff --git a/TheOtherRoles/Modules/CustomHats/Patches/HatParentPatches.cs b/TheOtherRoles/Modules/CustomHats/Patches/HatParentPatches.cs index ecfaa72b6..958ca0242 100644 --- a/TheOtherRoles/Modules/CustomHats/Patches/HatParentPatches.cs +++ b/TheOtherRoles/Modules/CustomHats/Patches/HatParentPatches.cs @@ -219,7 +219,6 @@ private static bool PopulateFromHatViewDataPrefix(HatParent __instance) { spriteAnimNodeSync.NodeId = __instance.Hat.NoBounce ? 1 : 0; } - if (__instance.Hat.InFront) { __instance.BackLayer.enabled = false; @@ -240,8 +239,7 @@ private static bool PopulateFromHatViewDataPrefix(HatParent __instance) __instance.FrontLayer.sprite = null; __instance.BackLayer.sprite = asset.MainImage; } - - if (!__instance.options.Initialized || !__instance.HideHat()) return false; + if (/*!__instance.options.Initialized ||*/ !__instance.HideHat()) return false; __instance.FrontLayer.enabled = false; __instance.BackLayer.enabled = false; return false; diff --git a/TheOtherRoles/Modules/CustomHats/Patches/HatsTabPatches.cs b/TheOtherRoles/Modules/CustomHats/Patches/HatsTabPatches.cs index 5a258e4c8..ca2587b3a 100644 --- a/TheOtherRoles/Modules/CustomHats/Patches/HatsTabPatches.cs +++ b/TheOtherRoles/Modules/CustomHats/Patches/HatsTabPatches.cs @@ -10,14 +10,15 @@ namespace TheOtherRoles.Modules.CustomHats.Patches; -[HarmonyPatch(typeof(HatsTab))] +[HarmonyPatch] internal static class HatsTabPatches { private static TextMeshPro textTemplate; - - [HarmonyPatch(nameof(HatsTab.OnEnable))] - [HarmonyPostfix] - private static void OnEnablePostfix(HatsTab __instance) + + + [HarmonyPatch(typeof(HatsTab), nameof(HatsTab.OnEnable))] + [HarmonyPrefix] + private static bool OnEnablePrefix(HatsTab __instance) { for (var i = 0; i < __instance.scroller.Inner.childCount; i++) { @@ -66,6 +67,7 @@ private static void OnEnablePostfix(HatsTab __instance) } __instance.scroller.ContentYBounds.max = -(yOffset + 4.1f); + return false; } private static float CreateHatPackage(List> hats, string packageName, float yStart, @@ -106,7 +108,7 @@ private static float CreateHatPackage(List> hats, s colorChip.Button.OnClick.AddListener((Action)(() => hatsTab.SelectHat(hat))); } colorChip.Button.ClickMask = hatsTab.scroller.Hitbox; - colorChip.Inner.SetMaskType(PlayerMaterial.MaskType.ScrollingUI); + colorChip.Inner.SetMaskType(PlayerMaterial.MaskType.SimpleUI); hatsTab.UpdateMaterials(colorChip.Inner.FrontLayer, hat); var background = colorChip.transform.FindChild("Background"); var foreground = colorChip.transform.FindChild("ForeGround"); diff --git a/TheOtherRoles/Modules/CustomOptions.cs b/TheOtherRoles/Modules/CustomOptions.cs index eec9887f9..dd5b4bd69 100644 --- a/TheOtherRoles/Modules/CustomOptions.cs +++ b/TheOtherRoles/Modules/CustomOptions.cs @@ -17,6 +17,7 @@ using BepInEx.Unity.IL2CPP; using BepInEx; using static ShipStatus; +using TMPro; namespace TheOtherRoles { public class CustomOption { @@ -48,10 +49,11 @@ public enum CustomOptionType { public bool isHeader; public CustomOptionType type; public Action onChange = null; + public string heading = ""; // Option creation - public CustomOption(int id, CustomOptionType type, string name, System.Object[] selections, System.Object defaultValue, CustomOption parent, bool isHeader, Action onChange = null) { + public CustomOption(int id, CustomOptionType type, string name, System.Object[] selections, System.Object defaultValue, CustomOption parent, bool isHeader, Action onChange = null, string heading = "") { this.id = id; this.name = parent == null ? name : "- " + name; this.selections = selections; @@ -61,6 +63,7 @@ public CustomOption(int id, CustomOptionType type, string name, System.Object[] this.isHeader = isHeader; this.type = type; this.onChange = onChange; + this.heading = heading; selection = 0; if (id != 0) { entry = TheOtherRolesPlugin.Instance.Config.Bind($"Preset{preset}", id.ToString(), defaultSelection); @@ -69,19 +72,19 @@ public CustomOption(int id, CustomOptionType type, string name, System.Object[] options.Add(this); } - public static CustomOption Create(int id, CustomOptionType type, string name, string[] selections, CustomOption parent = null, bool isHeader = false, Action onChange = null) { - return new CustomOption(id, type, name, selections, "", parent, isHeader, onChange); + public static CustomOption Create(int id, CustomOptionType type, string name, string[] selections, CustomOption parent = null, bool isHeader = false, Action onChange = null, string heading = "") { + return new CustomOption(id, type, name, selections, "", parent, isHeader, onChange, heading); } - public static CustomOption Create(int id, CustomOptionType type, string name, float defaultValue, float min, float max, float step, CustomOption parent = null, bool isHeader = false, Action onChange = null) { + public static CustomOption Create(int id, CustomOptionType type, string name, float defaultValue, float min, float max, float step, CustomOption parent = null, bool isHeader = false, Action onChange = null, string heading = "") { List selections = new(); for (float s = min; s <= max; s += step) selections.Add(s); - return new CustomOption(id, type, name, selections.ToArray(), defaultValue, parent, isHeader, onChange); + return new CustomOption(id, type, name, selections.ToArray(), defaultValue, parent, isHeader, onChange, heading); } - public static CustomOption Create(int id, CustomOptionType type, string name, bool defaultValue, CustomOption parent = null, bool isHeader = false, Action onChange = null) { - return new CustomOption(id, type, name, new string[]{"Off", "On"}, defaultValue ? "On" : "Off", parent, isHeader, onChange); + public static CustomOption Create(int id, CustomOptionType type, string name, bool defaultValue, CustomOption parent = null, bool isHeader = false, Action onChange = null, string heading = "") { + return new CustomOption(id, type, name, new string[]{"Off", "On"}, defaultValue ? "On" : "Off", parent, isHeader, onChange, heading); } // Static behaviour @@ -107,13 +110,19 @@ public static void saveVanillaOptions() { vanillaSettings.Value = Convert.ToBase64String(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameManager.Instance.LogicOptions.currentGameOptions, false)); } - public static void loadVanillaOptions() { + public static bool loadVanillaOptions() { string optionsString = vanillaSettings.Value; - if (optionsString == "") return; - GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.gameOptionsFactory.FromBytes(Convert.FromBase64String(optionsString)); + if (optionsString == "") return false; + IGameOptions gameOptions = GameOptionsManager.Instance.gameOptionsFactory.FromBytes(Convert.FromBase64String(optionsString)); + if (gameOptions.Version < 8) { + TheOtherRolesPlugin.Logger.LogMessage("tried to paste old settings, not doing this!"); + return false; + } + GameOptionsManager.Instance.GameHostOptions = gameOptions; GameOptionsManager.Instance.CurrentGameOptions = GameOptionsManager.Instance.GameHostOptions; GameManager.Instance.LogicOptions.SetGameOptions(GameOptionsManager.Instance.CurrentGameOptions); GameManager.Instance.LogicOptions.SyncOptions(); + return true; } public static void ShareOptionChange(uint optionId) { @@ -163,10 +172,18 @@ public int getQuantity() { return selection + 1; } - // Option changes - public void updateSelection(int newSelection) { - selection = Mathf.Clamp((newSelection + selections.Length) % selections.Length, 0, selections.Length - 1); + public void updateSelection(int newSelection, bool notifyUsers = true) { + newSelection = Mathf.Clamp((newSelection + selections.Length) % selections.Length, 0, selections.Length - 1); + if (AmongUsClient.Instance?.AmClient == true && notifyUsers && selection != newSelection) { + DestroyableSingleton.Instance.Notifier.AddSettingsChangeMessage((StringNames)(this.id + 6000), selections[newSelection].ToString(), false); + try { + if (GameStartManager.Instance != null && GameStartManager.Instance.LobbyInfoPane != null && GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane != null && GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane.gameObject.activeSelf) { + LobbyViewSettingsPaneChangeTabPatch.Postfix(GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane, GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane.currentTab); + } + } catch { } + } + selection = newSelection; try { if (onChange != null) onChange(); } catch { } @@ -208,9 +225,11 @@ public static byte[] serializeOptions() { } } - public static void deserializeOptions(byte[] inputValues) { + public static int deserializeOptions(byte[] inputValues) { BinaryReader reader = new BinaryReader(new MemoryStream(inputValues)); int lastId = -1; + bool somethingApplied = false; + int errors = 0; while (reader.BaseStream.Position < inputValues.Length) { try { int selection = reader.ReadByte(); @@ -224,12 +243,20 @@ public static void deserializeOptions(byte[] inputValues) { } if (id == 0) continue; lastId = id; - CustomOption option = CustomOption.options.First(option => option.id == id); - option.updateSelection(selection); + CustomOption option = options.First(option => option.id == id); + option.entry = TheOtherRolesPlugin.Instance.Config.Bind($"Preset{preset}", option.id.ToString(), option.defaultSelection); + option.selection = selection; + if (option.optionBehaviour != null && option.optionBehaviour is StringOption stringOption) { + stringOption.oldValue = stringOption.Value = option.selection; + stringOption.ValueText.text = option.selections[option.selection].ToString(); + } + somethingApplied = true; } catch (Exception e) { - TheOtherRolesPlugin.Logger.LogWarning($"{e}: while deserializing - tried to paste invalid settings!"); + TheOtherRolesPlugin.Logger.LogWarning($"id:{lastId}:{e}: while deserializing - tried to paste invalid settings!"); + errors++; } } + return Convert.ToInt32(somethingApplied) + (errors > 0 ? 0 : 1); } // Copy to or paste from clipboard (as string) @@ -237,587 +264,527 @@ public static void copyToClipboard() { GUIUtility.systemCopyBuffer = $"{TheOtherRolesPlugin.VersionString}!{Convert.ToBase64String(serializeOptions())}!{vanillaSettings.Value}"; } - public static bool pasteFromClipboard() { + public static int pasteFromClipboard() { string allSettings = GUIUtility.systemCopyBuffer; + int torOptionsFine = 0; + bool vanillaOptionsFine = false; try { var settingsSplit = allSettings.Split("!"); - string versionInfo = settingsSplit[0]; + Version versionInfo = Version.Parse(settingsSplit[0]); string torSettings = settingsSplit[1]; string vanillaSettingsSub = settingsSplit[2]; - deserializeOptions(Convert.FromBase64String(torSettings)); - - vanillaSettings.Value = vanillaSettingsSub; - loadVanillaOptions(); - return true; + torOptionsFine = deserializeOptions(Convert.FromBase64String(torSettings)); + ShareOptionSelections(); + if (TheOtherRolesPlugin.Version > versionInfo && versionInfo < Version.Parse("4.6.0")) { + vanillaOptionsFine = false; + FastDestroyableSingleton.Instance.Chat.AddChat(PlayerControl.LocalPlayer, "Host Info: Pasting vanilla settings failed, TOR Options applied!"); + } else { + vanillaSettings.Value = vanillaSettingsSub; + vanillaOptionsFine = loadVanillaOptions(); + } } catch (Exception e) { - TheOtherRolesPlugin.Logger.LogWarning($"{e}: tried to paste invalid settings!"); + TheOtherRolesPlugin.Logger.LogWarning($"{e}: tried to paste invalid settings!\n{allSettings}"); + string errorStr = allSettings.Length > 2 ? allSettings.Substring(0, 3) : "(empty clipboard) "; + FastDestroyableSingleton.Instance.Chat.AddChat(PlayerControl.LocalPlayer, $"Host Info: You tried to paste invalid settings: \"{errorStr}...\""); SoundEffectsManager.Load(); SoundEffectsManager.play("fail"); - return false; } + return Convert.ToInt32(vanillaOptionsFine) + torOptionsFine; } } - [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))] - class GameOptionsMenuStartPatch { - public static void Postfix(GameOptionsMenu __instance) { - switch (TORMapOptions.gameMode) { - case CustomGamemodes.Classic: - createClassicTabs(__instance); - break; - case CustomGamemodes.Guesser: - createGuesserTabs(__instance); - break; - case CustomGamemodes.HideNSeek: - createHideNSeekTabs(__instance); - break; - case CustomGamemodes.PropHunt: - createPropHuntTabs(__instance); - break; - } - // create copy to clipboard and paste from clipboard buttons. - var template = GameObject.Find("CloseButton"); - var copyButton = GameObject.Instantiate(template, template.transform.parent); - copyButton.transform.localPosition += Vector3.down * 0.8f; - var copyButtonPassive = copyButton.GetComponent(); - var copyButtonRenderer = copyButton.GetComponent(); - copyButtonRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CopyButton.png", 175f); - copyButtonPassive.OnClick.RemoveAllListeners(); - copyButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - copyButtonPassive.OnClick.AddListener((System.Action)(() => { - copyToClipboard(); - copyButtonRenderer.color = Color.green; - __instance.StartCoroutine(Effects.Lerp(1f, new System.Action((p) => { - if (p > 0.95) - copyButtonRenderer.color = Color.white; - }))); - })); - var pasteButton = GameObject.Instantiate(template, template.transform.parent); - pasteButton.transform.localPosition += Vector3.down * 1.6f; - var pasteButtonPassive = pasteButton.GetComponent(); - var pasteButtonRenderer = pasteButton.GetComponent(); - pasteButtonRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.PasteButton.png", 175f); - pasteButtonPassive.OnClick.RemoveAllListeners(); - pasteButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - pasteButtonPassive.OnClick.AddListener((System.Action)(() => { - pasteButtonRenderer.color = Color.yellow; - bool success = pasteFromClipboard(); - pasteButtonRenderer.color = success ? Color.green : Color.red; - __instance.StartCoroutine(Effects.Lerp(1f, new System.Action((p) => { - if (p > 0.95) - pasteButtonRenderer.color = Color.white; - }))); - })); + [HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.ChangeTab))] + class GameOptionsMenuChangeTabPatch { + public static void Postfix(GameSettingMenu __instance, int tabNum, bool previewOnly) { + if (previewOnly) return; + foreach (var tab in GameOptionsMenuStartPatch.currentTabs) { + if (tab != null) + tab.SetActive(false); + } + foreach (var pbutton in GameOptionsMenuStartPatch.currentButtons) { + pbutton.SelectButton(false); + } + if (tabNum > 2) { + tabNum -= 3; + GameOptionsMenuStartPatch.currentTabs[tabNum].SetActive(true); + GameOptionsMenuStartPatch.currentButtons[tabNum].SelectButton(true); + } } + } - private static void createClassicTabs(GameOptionsMenu __instance) { - bool isReturn = setNames( - new Dictionary() { - ["TORSettings"] = "The Other Roles Settings", - ["ImpostorSettings"] = "Impostor Roles Settings", - ["NeutralSettings"] = "Neutral Roles Settings", - ["CrewmateSettings"] = "Crewmate Roles Settings", - ["ModifierSettings"] = "Modifier Settings" - }); - - if (isReturn) return; - - // Setup TOR tab - var template = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - - var torSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); - - var impostorSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var impostorMenu = getMenu(impostorSettings, "ImpostorSettings"); - - var neutralSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var neutralMenu = getMenu(neutralSettings, "NeutralSettings"); - - var crewmateSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var crewmateMenu = getMenu(crewmateSettings, "CrewmateSettings"); - - var modifierSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var modifierMenu = getMenu(modifierSettings, "ModifierSettings"); - - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); - - var torTab = UnityEngine.Object.Instantiate(roleTab, roleTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIcon.png"); - - var impostorTab = UnityEngine.Object.Instantiate(roleTab, torTab.transform); - var impostorTabHighlight = getTabHighlight(impostorTab, "ImpostorTab", "TheOtherRoles.Resources.TabIconImpostor.png"); - - var neutralTab = UnityEngine.Object.Instantiate(roleTab, impostorTab.transform); - var neutralTabHighlight = getTabHighlight(neutralTab, "NeutralTab", "TheOtherRoles.Resources.TabIconNeutral.png"); - - var crewmateTab = UnityEngine.Object.Instantiate(roleTab, neutralTab.transform); - var crewmateTabHighlight = getTabHighlight(crewmateTab, "CrewmateTab", "TheOtherRoles.Resources.TabIconCrewmate.png"); - - var modifierTab = UnityEngine.Object.Instantiate(roleTab, crewmateTab.transform); - var modifierTabHighlight = getTabHighlight(modifierTab, "ModifierTab", "TheOtherRoles.Resources.TabIconModifier.png"); - - // Position of Tab Icons - gameTab.transform.position += Vector3.left * 3f; - roleTab.transform.position += Vector3.left * 3f; - torTab.transform.position += Vector3.left * 2f; - impostorTab.transform.localPosition = Vector3.right * 1f; - neutralTab.transform.localPosition = Vector3.right * 1f; - crewmateTab.transform.localPosition = Vector3.right * 1f; - modifierTab.transform.localPosition = Vector3.right * 1f; - - var tabs = new GameObject[] { gameTab, roleTab, torTab, impostorTab, neutralTab, crewmateTab, modifierTab }; - var settingsHighlightMap = new Dictionary { - [gameSettingMenu.RegularGameSettings] = gameSettingMenu.GameSettingsHightlight, - [gameSettingMenu.RolesSettings.gameObject] = gameSettingMenu.RolesSettingsHightlight, - [torSettings.gameObject] = torTabHighlight, - [impostorSettings.gameObject] = impostorTabHighlight, - [neutralSettings.gameObject] = neutralTabHighlight, - [crewmateSettings.gameObject] = crewmateTabHighlight, - [modifierSettings.gameObject] = modifierTabHighlight - }; - for (int i = 0; i < tabs.Length; i++) { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - int copiedIndex = i; - button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - button.OnClick.AddListener((System.Action)(() => { - setListener(settingsHighlightMap, copiedIndex); - })); + [HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.SetTab))] + class LobbyViewSettingsPaneRefreshTabPatch { + public static bool Prefix(LobbyViewSettingsPane __instance) { + if ((int)__instance.currentTab < 15) { + LobbyViewSettingsPaneChangeTabPatch.Postfix(__instance, __instance.currentTab); + return false; } + return true; + } + } - destroyOptions(new List>{ - torMenu.GetComponentsInChildren().ToList(), - impostorMenu.GetComponentsInChildren().ToList(), - neutralMenu.GetComponentsInChildren().ToList(), - crewmateMenu.GetComponentsInChildren().ToList(), - modifierMenu.GetComponentsInChildren().ToList() - }); - - List torOptions = new List(); - List impostorOptions = new List(); - List neutralOptions = new List(); - List crewmateOptions = new List(); - List modifierOptions = new List(); - - - List menus = new List() { torMenu.transform, impostorMenu.transform, neutralMenu.transform, crewmateMenu.transform, modifierMenu.transform }; - List> optionBehaviours = new List>() { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions }; - - for (int i = 0; i < CustomOption.options.Count; i++) { - CustomOption option = CustomOption.options[i]; - if ((int)option.type > 4) continue; - if (option.optionBehaviour == null) { - StringOption stringOption = UnityEngine.Object.Instantiate(template, menus[(int)option.type]); - optionBehaviours[(int)option.type].Add(stringOption); - stringOption.OnValueChanged = new Action((o) => { }); - stringOption.TitleText.text = option.name; - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.selections[option.selection].ToString(); + [HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.ChangeTab))] + class LobbyViewSettingsPaneChangeTabPatch { + public static void Postfix(LobbyViewSettingsPane __instance, StringNames category) { + int tabNum = (int)category; - option.optionBehaviour = stringOption; - } - option.optionBehaviour.gameObject.SetActive(true); + foreach (var pbutton in LobbyViewSettingsPatch.currentButtons) { + pbutton.SelectButton(false); } + if (tabNum > 20) // StringNames are in the range of 3000+ + return; + __instance.taskTabButton.SelectButton(false); - setOptions( - new List { torMenu, impostorMenu, neutralMenu, crewmateMenu, modifierMenu }, - new List> { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions }, - new List { torSettings, impostorSettings, neutralSettings, crewmateSettings, modifierSettings } - ); + if (tabNum > 2) { + tabNum -= 3; + //GameOptionsMenuStartPatch.currentTabs[tabNum].SetActive(true); + LobbyViewSettingsPatch.currentButtons[tabNum].SelectButton(true); + LobbyViewSettingsPatch.drawTab(__instance, LobbyViewSettingsPatch.currentButtonTypes[tabNum]); + } + } + } - adaptTaskCount(__instance); + [HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.Update))] + class LobbyViewSettingsPaneUpdatePatch { + public static void Postfix(LobbyViewSettingsPane __instance) { + if (LobbyViewSettingsPatch.currentButtons.Count == 0) { + LobbyViewSettingsPatch.gameModeChangedFlag = true; + LobbyViewSettingsPatch.Postfix(__instance); + + } } + } + - private static void createGuesserTabs(GameOptionsMenu __instance) { - bool isReturn = setNames( - new Dictionary() { - ["TORSettings"] = "The Other Roles Settings", - ["GuesserSettings"] = "Guesser Mode Settings", - ["ImpostorSettings"] = "Impostor Roles Settings", - ["NeutralSettings"] = "Neutral Roles Settings", - ["CrewmateSettings"] = "Crewmate Roles Settings", - ["ModifierSettings"] = "Modifier Settings" - }); - - if (isReturn) return; - - // Setup TOR tab - var template = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - - var torSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); - - var guesserSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var guesserMenu = getMenu(guesserSettings, "GuesserSettings"); - - var impostorSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var impostorMenu = getMenu(impostorSettings, "ImpostorSettings"); - - var neutralSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var neutralMenu = getMenu(neutralSettings, "NeutralSettings"); - - var crewmateSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var crewmateMenu = getMenu(crewmateSettings, "CrewmateSettings"); - - var modifierSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var modifierMenu = getMenu(modifierSettings, "ModifierSettings"); - - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); - - var torTab = UnityEngine.Object.Instantiate(roleTab, gameTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIcon.png"); - - var guesserTab = UnityEngine.Object.Instantiate(roleTab, torTab.transform); - var guesserTabHighlight = getTabHighlight(guesserTab, "GuesserTab", "TheOtherRoles.Resources.TabIconGuesserSettings.png"); - - var impostorTab = UnityEngine.Object.Instantiate(roleTab, guesserTab.transform); - var impostorTabHighlight = getTabHighlight(impostorTab, "ImpostorTab", "TheOtherRoles.Resources.TabIconImpostor.png"); - - var neutralTab = UnityEngine.Object.Instantiate(roleTab, impostorTab.transform); - var neutralTabHighlight = getTabHighlight(neutralTab, "NeutralTab", "TheOtherRoles.Resources.TabIconNeutral.png"); - - var crewmateTab = UnityEngine.Object.Instantiate(roleTab, neutralTab.transform); - var crewmateTabHighlight = getTabHighlight(crewmateTab, "CrewmateTab", "TheOtherRoles.Resources.TabIconCrewmate.png"); - - var modifierTab = UnityEngine.Object.Instantiate(roleTab, crewmateTab.transform); - var modifierTabHighlight = getTabHighlight(modifierTab, "ModifierTab", "TheOtherRoles.Resources.TabIconModifier.png"); - - roleTab.active = false; - // Position of Tab Icons - gameTab.transform.position += Vector3.left * 3f; - torTab.transform.position += Vector3.left * 3f; - guesserTab.transform.localPosition = Vector3.right * 1f; - impostorTab.transform.localPosition = Vector3.right * 1f; - neutralTab.transform.localPosition = Vector3.right * 1f; - crewmateTab.transform.localPosition = Vector3.right * 1f; - modifierTab.transform.localPosition = Vector3.right * 1f; - - var tabs = new GameObject[] { gameTab, torTab, impostorTab, neutralTab, crewmateTab, modifierTab, guesserTab }; - var settingsHighlightMap = new Dictionary { - [gameSettingMenu.RegularGameSettings] = gameSettingMenu.GameSettingsHightlight, - [torSettings.gameObject] = torTabHighlight, - [impostorSettings.gameObject] = impostorTabHighlight, - [neutralSettings.gameObject] = neutralTabHighlight, - [crewmateSettings.gameObject] = crewmateTabHighlight, - [modifierSettings.gameObject] = modifierTabHighlight, - [guesserSettings.gameObject] = guesserTabHighlight - }; - for (int i = 0; i < tabs.Length; i++) { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - int copiedIndex = i; - button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - button.OnClick.AddListener((System.Action)(() => { - setListener(settingsHighlightMap, copiedIndex); + [HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.Awake))] + class LobbyViewSettingsPatch{ + public static List currentButtons = new(); + public static List currentButtonTypes = new(); + public static bool gameModeChangedFlag = false; + + public static void createCustomButton(LobbyViewSettingsPane __instance, int targetMenu, string buttonName, string buttonText, CustomOptionType optionType) { + buttonName = "View" + buttonName; + var buttonTemplate = GameObject.Find("OverviewTab"); + var torSettingsButton = GameObject.Find(buttonName); + if (torSettingsButton == null) { + torSettingsButton = GameObject.Instantiate(buttonTemplate, buttonTemplate.transform.parent); + torSettingsButton.transform.localPosition += Vector3.right * 1.75f * (targetMenu - 2); + torSettingsButton.name = buttonName; + __instance.StartCoroutine(Effects.Lerp(2f, new Action(p => { torSettingsButton.transform.FindChild("FontPlacer").GetComponentInChildren().text = buttonText; }))); + var torSettingsPassiveButton = torSettingsButton.GetComponent(); + torSettingsPassiveButton.OnClick.RemoveAllListeners(); + torSettingsPassiveButton.OnClick.AddListener((System.Action)(() => { + __instance.ChangeTab((StringNames)targetMenu); })); + torSettingsPassiveButton.OnMouseOut.RemoveAllListeners(); + torSettingsPassiveButton.OnMouseOver.RemoveAllListeners(); + torSettingsPassiveButton.SelectButton(false); + currentButtons.Add(torSettingsPassiveButton); + currentButtonTypes.Add(optionType); } + } - destroyOptions(new List>{ - torMenu.GetComponentsInChildren().ToList(), - guesserMenu.GetComponentsInChildren().ToList(), - impostorMenu.GetComponentsInChildren().ToList(), - neutralMenu.GetComponentsInChildren().ToList(), - crewmateMenu.GetComponentsInChildren().ToList(), - modifierMenu.GetComponentsInChildren().ToList() - }); - - List torOptions = new List(); - List guesserOptions = new List(); - List impostorOptions = new List(); - List neutralOptions = new List(); - List crewmateOptions = new List(); - List modifierOptions = new List(); - - - List menus = new List() { torMenu.transform, impostorMenu.transform, neutralMenu.transform, crewmateMenu.transform, modifierMenu.transform, guesserMenu.transform }; - List> optionBehaviours = new List>() { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions, guesserOptions }; - List exludedIds = new List { 310, 311, 312, 313, 314, 315, 316, 317, 318 }; - - for (int i = 0; i < CustomOption.options.Count; i++) { - CustomOption option = CustomOption.options[i]; - if (exludedIds.Contains(option.id)) continue; - if ((int)option.type > 5) continue; - if (option.optionBehaviour == null) { - StringOption stringOption = UnityEngine.Object.Instantiate(template, menus[(int)option.type]); - optionBehaviours[(int)option.type].Add(stringOption); - stringOption.OnValueChanged = new Action((o) => { }); - stringOption.TitleText.text = option.name; - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.selections[option.selection].ToString(); + public static void Postfix(LobbyViewSettingsPane __instance) { + currentButtons.ForEach(x => x?.Destroy()); + currentButtons.Clear(); + currentButtonTypes.Clear(); - option.optionBehaviour = stringOption; - } - option.optionBehaviour.gameObject.SetActive(true); - } + removeVanillaTabs(__instance); - setOptions( - new List { torMenu, impostorMenu, neutralMenu, crewmateMenu, modifierMenu, guesserMenu }, - new List> { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions, guesserOptions }, - new List { torSettings, impostorSettings, neutralSettings, crewmateSettings, modifierSettings, guesserSettings } - ); + createSettingTabs(__instance); - adaptTaskCount(__instance); } - private static void createHideNSeekTabs(GameOptionsMenu __instance) { - bool isReturn = setNames( - new Dictionary(){ - ["TORSettings"] = "The Other Roles Settings", - ["HideNSeekSettings"] = "Hide 'N Seek Settings" - }); - - if (isReturn) return; - - // Setup TOR tab - var template = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - - var torSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); - - var hideNSeekSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var hideNSeekMenu = getMenu(hideNSeekSettings, "HideNSeekSettings"); - - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); - - var torTab = UnityEngine.Object.Instantiate(roleTab, gameTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIconHideNSeekSettings.png"); - - var hideNSeekTab = UnityEngine.Object.Instantiate(roleTab, torTab.transform); - var hideNSeekTabHighlight = getTabHighlight(hideNSeekTab, "HideNSeekTab", "TheOtherRoles.Resources.TabIconHideNSeekRoles.png"); - - roleTab.active = false; - gameTab.active = false; - - // Position of Tab Icons - torTab.transform.position += Vector3.left * 3f; - hideNSeekTab.transform.position += Vector3.right * 1f; - - var tabs = new GameObject[] { torTab, hideNSeekTab}; - var settingsHighlightMap = new Dictionary { - [torSettings.gameObject] = torTabHighlight, - [hideNSeekSettings.gameObject] = hideNSeekTabHighlight - }; - for (int i = 0; i < tabs.Length; i++) { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - int copiedIndex = i; - button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - button.OnClick.AddListener((System.Action)(() => { - setListener(settingsHighlightMap, copiedIndex); - })); + public static void removeVanillaTabs(LobbyViewSettingsPane __instance) { + GameObject.Find("RolesTabs")?.Destroy(); + var overview = GameObject.Find("OverviewTab"); + if (!gameModeChangedFlag) { + overview.transform.localScale = new Vector3(0.5f * overview.transform.localScale.x, overview.transform.localScale.y, overview.transform.localScale.z); + overview.transform.localPosition += new Vector3(-1.2f, 0f, 0f); + } + overview.transform.Find("FontPlacer").transform.localScale = new Vector3(1.35f, 1f, 1f); + overview.transform.Find("FontPlacer").transform.localPosition = new Vector3(-0.6f, -0.1f, 0f); + gameModeChangedFlag = false; + } - destroyOptions(new List>{ - torMenu.GetComponentsInChildren().ToList(), - hideNSeekMenu.GetComponentsInChildren().ToList() - }); - - List torOptions = new List(); - List hideNSeekOptions = new List(); - - List menus = new List() { torMenu.transform, hideNSeekMenu.transform}; - List> optionBehaviours = new List>() { torOptions, hideNSeekOptions }; - - for (int i = 0; i < CustomOption.options.Count; i++) { - CustomOption option = CustomOption.options[i]; - if (option.type != CustomOptionType.HideNSeekMain && option.type != CustomOptionType.HideNSeekRoles) continue; - if (option.optionBehaviour == null) { - int index = (int)option.type - 6; - StringOption stringOption = UnityEngine.Object.Instantiate(template, menus[index]); - optionBehaviours[index].Add(stringOption); - stringOption.OnValueChanged = new Action((o) => { }); - stringOption.TitleText.text = option.name; - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.selections[option.selection].ToString(); + public static void drawTab(LobbyViewSettingsPane __instance, CustomOptionType optionType) { + + var relevantOptions = options.Where(x => x.type == optionType || x.type == CustomOption.CustomOptionType.Guesser && optionType == CustomOptionType.General).ToList(); + + if ((int)optionType == 99) { + // Create 4 Groups with Role settings only + relevantOptions.Clear(); + relevantOptions.AddRange(options.Where(x => x.type == CustomOptionType.Impostor && x.isHeader)); + relevantOptions.AddRange(options.Where(x => x.type == CustomOptionType.Neutral && x.isHeader)); + relevantOptions.AddRange(options.Where(x => x.type == CustomOptionType.Crewmate && x.isHeader)); + relevantOptions.AddRange(options.Where(x => x.type == CustomOptionType.Modifier && x.isHeader)); + foreach (var option in options) { + if (option.parent != null && option.parent.getSelection() > 0) { + if (option.id == 103) //Deputy + relevantOptions.Insert(relevantOptions.IndexOf(CustomOptionHolder.sheriffSpawnRate) + 1, option); + else if (option.id == 224) //Sidekick + relevantOptions.Insert(relevantOptions.IndexOf(CustomOptionHolder.jackalSpawnRate) + 1, option); + else if (option.id == 358) //Prosecutor + relevantOptions.Insert(relevantOptions.IndexOf(CustomOptionHolder.lawyerSpawnRate) + 1, option); + } + } + } + + if (TORMapOptions.gameMode == CustomGamemodes.Guesser) // Exclude guesser options in neutral mode + relevantOptions = relevantOptions.Where(x => !(new List { 310, 311, 312, 313, 314, 315, 316, 317, 318 }).Contains(x.id)).ToList(); + + for (int j = 0; j < __instance.settingsInfo.Count; j++) { + __instance.settingsInfo[j].gameObject.Destroy(); + } + __instance.settingsInfo.Clear(); + + float num = 1.44f; + int i = 0; + int singles = 0; + int headers = 0; + int lines = 0; + var curType = CustomOptionType.Modifier; + + foreach (var option in relevantOptions) { + if (option.isHeader && (int)optionType != 99 || (int)optionType == 99 && curType != option.type) { + curType = option.type; + if (i != 0) num -= 0.59f; + if (i % 2 != 0) singles++; + headers++; // for header + CategoryHeaderMasked categoryHeaderMasked = UnityEngine.Object.Instantiate(__instance.categoryHeaderOrigin); + categoryHeaderMasked.SetHeader(StringNames.ImpostorsCategory, 61); + categoryHeaderMasked.Title.text = option.heading != "" ? option.heading : option.name; + if ((int)optionType == 99) + categoryHeaderMasked.Title.text = new Dictionary() { { CustomOptionType.Impostor, "Impostor Roles" }, { CustomOptionType.Neutral, "Neutral Roles" }, + { CustomOptionType.Crewmate, "Crewmate Roles" }, { CustomOptionType.Modifier, "Modifiers" } }[curType]; + categoryHeaderMasked.Title.outlineColor = Color.white; + categoryHeaderMasked.Title.outlineWidth = 0.2f; + categoryHeaderMasked.transform.SetParent(__instance.settingsContainer); + categoryHeaderMasked.transform.localScale = Vector3.one; + categoryHeaderMasked.transform.localPosition = new Vector3(-9.77f, num, -2f); + __instance.settingsInfo.Add(categoryHeaderMasked.gameObject); + num -= 0.85f; + i = 0; + } - option.optionBehaviour = stringOption; + ViewSettingsInfoPanel viewSettingsInfoPanel = UnityEngine.Object.Instantiate(__instance.infoPanelOrigin); + viewSettingsInfoPanel.transform.SetParent(__instance.settingsContainer); + viewSettingsInfoPanel.transform.localScale = Vector3.one; + float num2; + if (i % 2 == 0) { + lines++; + num2 = -8.95f; + if (i > 0) { + num -= 0.59f; + } + } else { + num2 = -3f; } - option.optionBehaviour.gameObject.SetActive(true); + viewSettingsInfoPanel.transform.localPosition = new Vector3(num2, num, -2f); + int value = option.getSelection(); + viewSettingsInfoPanel.SetInfo(StringNames.ImpostorsCategory, option.selections[value].ToString(), 61); + viewSettingsInfoPanel.titleText.text = option.name; + if (option.isHeader && (int)optionType != 99 && option.heading == "" && (option.type == CustomOptionType.Neutral || option.type == CustomOptionType.Crewmate || option.type == CustomOptionType.Impostor || option.type == CustomOptionType.Modifier)) { + viewSettingsInfoPanel.titleText.text = "Spawn Chance"; + } + if ((int)optionType == 99) { + viewSettingsInfoPanel.titleText.outlineColor = Color.white; + viewSettingsInfoPanel.titleText.outlineWidth = 0.2f; + if (option.type == CustomOptionType.Modifier) + viewSettingsInfoPanel.settingText.text = viewSettingsInfoPanel.settingText.text + GameOptionsDataPatch.buildModifierExtras(option); + } + __instance.settingsInfo.Add(viewSettingsInfoPanel.gameObject); + + i++; } + float actual_spacing = (headers * 0.85f + lines * 0.59f) / (headers + lines); + __instance.scrollBar.CalculateAndSetYBounds((float)(__instance.settingsInfo.Count + singles * 2 + headers), 2f, 6f, actual_spacing); - setOptions( - new List{torMenu, hideNSeekMenu}, - new List> {torOptions, hideNSeekOptions}, - new List {torSettings, hideNSeekSettings} - ); + } - torSettings.gameObject.SetActive(true); - torTabHighlight.enabled = true; - gameSettingMenu.RegularGameSettings.SetActive(false); - gameSettingMenu.GameSettingsHightlight.enabled = false; + public static void createSettingTabs(LobbyViewSettingsPane __instance) { + // Handle different gamemodes and tabs needed therein. + int next = 3; + if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic) { + + // create TOR settings + createCustomButton(__instance, next++, "TORSettings", "TOR Settings", CustomOptionType.General); + // create TOR settings + createCustomButton(__instance, next++, "RoleOverview", "Role Overview", (CustomOptionType)99); + // IMp + createCustomButton(__instance, next++, "ImpostorSettings", "Impostor Roles", CustomOptionType.Impostor); + + // Neutral + createCustomButton(__instance, next++, "NeutralSettings", "Neutral Roles", CustomOptionType.Neutral); + // Crew + createCustomButton(__instance, next++, "CrewmateSettings", "Crewmate Roles", CustomOptionType.Crewmate); + // Modifier + createCustomButton(__instance, next++, "ModifierSettings", "Modifiers", CustomOptionType.Modifier); + + } else if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) { + // create Main HNS settings + createCustomButton(__instance, next++, "HideNSeekMain", "Hide 'N' Seek", CustomOptionType.HideNSeekMain); + // create HNS Role settings + createCustomButton(__instance, next++, "HideNSeekRoles", "Hide 'N' Seek Roles", CustomOptionType.HideNSeekRoles); + } else if (TORMapOptions.gameMode == CustomGamemodes.PropHunt) { + createCustomButton(__instance, next++, "PropHunt", "Prop Hunt", CustomOptionType.PropHunt); + } } + } + [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.CreateSettings))] + class GameOptionsMenuCreateSettingsPatch { + public static void Postfix(GameOptionsMenu __instance) { + if (__instance.gameObject.name == "GAME SETTINGS TAB") + adaptTaskCount(__instance); + } - private static void createPropHuntTabs(GameOptionsMenu __instance) { - bool isReturn = setNames( - new Dictionary() { - ["TORSettings"] = "Prop Hunt Settings" - }); + private static void adaptTaskCount(GameOptionsMenu __instance) { + // Adapt task count for main options + var commonTasksOption = __instance.Children.ToArray().FirstOrDefault(x => x.TryCast()?.intOptionName == Int32OptionNames.NumCommonTasks).Cast(); + if (commonTasksOption != null) commonTasksOption.ValidRange = new FloatRange(0f, 4f); + var shortTasksOption = __instance.Children.ToArray().FirstOrDefault(x => x.TryCast()?.intOptionName == Int32OptionNames.NumShortTasks).TryCast(); + if (shortTasksOption != null) shortTasksOption.ValidRange = new FloatRange(0f, 23f); + var longTasksOption = __instance.Children.ToArray().FirstOrDefault(x => x.TryCast()?.intOptionName == Int32OptionNames.NumLongTasks).TryCast(); + if (longTasksOption != null) longTasksOption.ValidRange = new FloatRange(0f, 15f); + } + } - if (isReturn) return; - // Setup TOR tab - var template = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); + [HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.Start))] + class GameOptionsMenuStartPatch { + public static List currentTabs = new(); + public static List currentButtons = new(); - var torSettings = UnityEngine.Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); + public static void Postfix(GameSettingMenu __instance) { + currentTabs.ForEach(x => x?.Destroy()); + currentButtons.ForEach(x => x?.Destroy()); + currentTabs = new(); + currentButtons = new(); - var torTab = UnityEngine.Object.Instantiate(roleTab, gameTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIconPropHuntSettings.png"); + if (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; - roleTab.active = false; - gameTab.active = false; + removeVanillaTabs(__instance); - // Position of Tab Icons - torTab.transform.position += Vector3.left * 3f; - - var tabs = new GameObject[] {torTab}; - var settingsHighlightMap = new Dictionary { - [torSettings.gameObject] = torTabHighlight - }; - for (int i = 0; i < tabs.Length; i++) { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - int copiedIndex = i; - button.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); - button.OnClick.AddListener((System.Action)(() => { - setListener(settingsHighlightMap, copiedIndex); - })); - } - - destroyOptions(new List>{ - torMenu.GetComponentsInChildren().ToList(), - }); - - List torOptions = new List(); - - List menus = new List() { torMenu.transform }; - List> optionBehaviours = new List>() { torOptions }; - - for (int i = 0; i < CustomOption.options.Count; i++) { - CustomOption option = CustomOption.options[i]; - if (option.type != CustomOptionType.PropHunt) continue; - if (option.optionBehaviour == null) { - int index = 0; - StringOption stringOption = UnityEngine.Object.Instantiate(template, menus[index]); - optionBehaviours[index].Add(stringOption); - stringOption.OnValueChanged = new Action((o) => { }); - stringOption.TitleText.text = option.name; - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.selections[option.selection].ToString(); + createSettingTabs(__instance); - option.optionBehaviour = stringOption; - } - option.optionBehaviour.gameObject.SetActive(true); - } + var GOMGameObject = GameObject.Find("GAME SETTINGS TAB"); - setOptions( - new List { torMenu}, - new List> { torOptions }, - new List { torSettings } - ); - torSettings.gameObject.SetActive(true); - torTabHighlight.enabled = true; - gameSettingMenu.RegularGameSettings.SetActive(false); - gameSettingMenu.GameSettingsHightlight.enabled = false; - } - - private static void setListener(Dictionary settingsHighlightMap, int index) { - foreach (KeyValuePair entry in settingsHighlightMap) { - entry.Key.SetActive(false); - entry.Value.enabled = false; - } - settingsHighlightMap.ElementAt(index).Key.SetActive(true); - settingsHighlightMap.ElementAt(index).Value.enabled = true; + // create copy to clipboard and paste from clipboard buttons. + var template = GameObject.Find("PlayerOptionsMenu(Clone)").transform.Find("CloseButton").gameObject; + var holderGO = new GameObject("copyPasteButtonParent"); + var bgrenderer = holderGO.AddComponent(); + bgrenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CopyPasteBG.png", 175f); + holderGO.transform.SetParent(template.transform.parent, false); + holderGO.transform.localPosition = template.transform.localPosition + new Vector3(-8.3f, 0.73f, -2f); + holderGO.layer = template.layer; + holderGO.SetActive(true); + var copyButton = GameObject.Instantiate(template, holderGO.transform); + copyButton.transform.localPosition = new Vector3(-0.3f, 0.02f, -2f); + var copyButtonPassive = copyButton.GetComponent(); + var copyButtonRenderer = copyButton.GetComponentInChildren(); + var copyButtonActiveRenderer = copyButton.transform.GetChild(1).GetComponent(); + copyButtonRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Copy.png", 100f); + copyButton.transform.GetChild(1).transform.localPosition = Vector3.zero; + copyButtonActiveRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CopyActive.png", 100f); + copyButtonPassive.OnClick.RemoveAllListeners(); + copyButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); + copyButtonPassive.OnClick.AddListener((System.Action)(() => { + copyToClipboard(); + copyButtonRenderer.color = Color.green; + copyButtonActiveRenderer.color = Color.green; + __instance.StartCoroutine(Effects.Lerp(1f, new System.Action((p) => { + if (p > 0.95) { + copyButtonRenderer.color = Color.white; + copyButtonActiveRenderer.color = Color.white; + } + }))); + })); + var pasteButton = GameObject.Instantiate(template, holderGO.transform); + pasteButton.transform.localPosition = new Vector3(0.3f, 0.02f, -2f); + var pasteButtonPassive = pasteButton.GetComponent(); + var pasteButtonRenderer = pasteButton.GetComponentInChildren(); + var pasteButtonActiveRenderer = pasteButton.transform.GetChild(1).GetComponent(); + pasteButtonRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Paste.png", 100f); + pasteButtonActiveRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.PasteActive.png", 100f); + pasteButtonPassive.OnClick.RemoveAllListeners(); + pasteButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); + pasteButtonPassive.OnClick.AddListener((System.Action)(() => { + pasteButtonRenderer.color = Color.yellow; + int success = pasteFromClipboard(); + pasteButtonRenderer.color = success == 3 ? Color.green : success == 0 ? Color.red : Color.yellow; + pasteButtonActiveRenderer.color = success == 3 ? Color.green : success == 0 ? Color.red : Color.yellow; + __instance.StartCoroutine(Effects.Lerp(1f, new System.Action((p) => { + if (p > 0.95) { + pasteButtonRenderer.color = Color.white; + pasteButtonActiveRenderer.color = Color.white; + } + }))); + })); } - private static void destroyOptions (List> optionBehavioursList) { - foreach (List optionBehaviours in optionBehavioursList) { - foreach (OptionBehaviour option in optionBehaviours) - UnityEngine.Object.Destroy(option.gameObject); - } - } + private static void createSettings(GameOptionsMenu menu, List options) { + float num = 1.5f; + foreach (CustomOption option in options) { + if (option.isHeader) { + CategoryHeaderMasked categoryHeaderMasked = UnityEngine.Object.Instantiate(menu.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, menu.settingsContainer); + categoryHeaderMasked.SetHeader(StringNames.ImpostorsCategory, 20); + categoryHeaderMasked.Title.text = option.heading != "" ? option.heading : option.name; + categoryHeaderMasked.Title.outlineColor = Color.white; + categoryHeaderMasked.Title.outlineWidth = 0.2f; + categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f; + categoryHeaderMasked.transform.localPosition = new Vector3(-0.903f, num, -2f); + num -= 0.63f; + } + OptionBehaviour optionBehaviour = UnityEngine.Object.Instantiate(menu.stringOptionOrigin, Vector3.zero, Quaternion.identity, menu.settingsContainer); + optionBehaviour.transform.localPosition = new Vector3(0.952f, num, -2f); + optionBehaviour.SetClickMask(menu.ButtonClickMask); + + // "SetUpFromData" + SpriteRenderer[] componentsInChildren = optionBehaviour.GetComponentsInChildren(true); + for (int i = 0; i < componentsInChildren.Length; i++) { + componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20); + } + foreach (TextMeshPro textMeshPro in optionBehaviour.GetComponentsInChildren(true)) { + textMeshPro.fontMaterial.SetFloat("_StencilComp", 3f); + textMeshPro.fontMaterial.SetFloat("_Stencil", (float)20); + } - private static bool setNames (Dictionary gameObjectNameDisplayNameMap) { - foreach (KeyValuePair entry in gameObjectNameDisplayNameMap) { - if (GameObject.Find(entry.Key) != null) { // Settings setup has already been performed, fixing the title of the tab and returning - GameObject.Find(entry.Key).transform.FindChild("GameGroup").FindChild("Text").GetComponent().SetText(entry.Value); - return true; + var stringOption = optionBehaviour as StringOption; + stringOption.OnValueChanged = new Action((o) => { }); + stringOption.TitleText.text = option.name; + if (option.isHeader && option.heading == "" && (option.type == CustomOptionType.Neutral || option.type == CustomOptionType.Crewmate || option.type == CustomOptionType.Impostor || option.type == CustomOptionType.Modifier)) { + stringOption.TitleText.text = "Spawn Chance"; } + if (stringOption.TitleText.text.Length > 25) + stringOption.TitleText.fontSize = 2.2f; + if (stringOption.TitleText.text.Length > 40) + stringOption.TitleText.fontSize = 2f; + stringOption.Value = stringOption.oldValue = option.selection; + stringOption.ValueText.text = option.selections[option.selection].ToString(); + option.optionBehaviour = stringOption; + + menu.Children.Add(optionBehaviour); + num -= 0.45f; + menu.scrollBar.SetYBoundsMax(-num - 1.65f); } - return false; - } - - private static GameOptionsMenu getMenu(GameObject setting, string settingName) { - var menu = setting.transform.FindChild("GameGroup").FindChild("SliderInner").GetComponent(); - setting.name = settingName; - - return menu; + for (int i = 0; i < menu.Children.Count; i++) { + OptionBehaviour optionBehaviour = menu.Children[i]; + if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost) { + optionBehaviour.SetAsPlayer(); + } + } } - private static SpriteRenderer getTabHighlight (GameObject tab, string tabName, string tabSpritePath) { - var tabHighlight = tab.transform.FindChild("Hat Button").FindChild("Tab Background").GetComponent(); - tab.transform.FindChild("Hat Button").FindChild("Icon").GetComponent().sprite = Helpers.loadSpriteFromResources(tabSpritePath, 100f); - tab.name = "tabName"; - - return tabHighlight; + private static void removeVanillaTabs(GameSettingMenu __instance) { + GameObject.Find("What Is This?")?.Destroy(); + GameObject.Find("GamePresetButton")?.Destroy(); + GameObject.Find("RoleSettingsButton")?.Destroy(); + __instance.ChangeTab(1, false); } - private static void setOptions (List menus, List> options, List settings) { - if (!(menus.Count == options.Count && options.Count == settings.Count)) { - TheOtherRolesPlugin.Logger.LogError("List counts are not equal"); - return; + public static void createCustomButton(GameSettingMenu __instance, int targetMenu, string buttonName, string buttonText) { + var leftPanel = GameObject.Find("LeftPanel"); + var buttonTemplate = GameObject.Find("GameSettingsButton"); + if (targetMenu == 3) { + buttonTemplate.transform.localPosition -= Vector3.up * 0.85f; + buttonTemplate.transform.localScale *= Vector2.one * 0.75f; } - for (int i = 0; i < menus.Count; i++) { - menus[i].Children = options[i].ToArray(); - settings[i].gameObject.SetActive(false); + var torSettingsButton = GameObject.Find(buttonName); + if (torSettingsButton == null) { + torSettingsButton = GameObject.Instantiate(buttonTemplate, leftPanel.transform); + torSettingsButton.transform.localPosition += Vector3.up * 0.5f * (targetMenu - 2); + torSettingsButton.name = buttonName; + __instance.StartCoroutine(Effects.Lerp(2f, new Action(p => { torSettingsButton.transform.FindChild("FontPlacer").GetComponentInChildren().text = buttonText; }))); + var torSettingsPassiveButton = torSettingsButton.GetComponent(); + torSettingsPassiveButton.OnClick.RemoveAllListeners(); + torSettingsPassiveButton.OnClick.AddListener((System.Action)(() => { + __instance.ChangeTab(targetMenu, false); + })); + torSettingsPassiveButton.OnMouseOut.RemoveAllListeners(); + torSettingsPassiveButton.OnMouseOver.RemoveAllListeners(); + torSettingsPassiveButton.SelectButton(false); + currentButtons.Add(torSettingsPassiveButton); } } - private static void adaptTaskCount(GameOptionsMenu __instance) { - // Adapt task count for main options - var commonTasksOption = __instance.Children.FirstOrDefault(x => x.name == "NumCommonTasks").TryCast(); - if (commonTasksOption != null) commonTasksOption.ValidRange = new FloatRange(0f, 4f); + public static void createGameOptionsMenu(GameSettingMenu __instance, CustomOptionType optionType, string settingName) { + var tabTemplate = GameObject.Find("GAME SETTINGS TAB"); + currentTabs.RemoveAll(x => x == null); - var shortTasksOption = __instance.Children.FirstOrDefault(x => x.name == "NumShortTasks").TryCast(); - if (shortTasksOption != null) shortTasksOption.ValidRange = new FloatRange(0f, 23f); + var torSettingsTab = GameObject.Instantiate(tabTemplate, tabTemplate.transform.parent); + torSettingsTab.name = settingName; + + var torSettingsGOM = torSettingsTab.GetComponent(); + foreach (var child in torSettingsGOM.Children) { + child.Destroy(); + } + torSettingsGOM.scrollBar.transform.FindChild("SliderInner").DestroyChildren(); + torSettingsGOM.Children.Clear(); + var relevantOptions = options.Where(x => x.type == optionType).ToList(); + if (TORMapOptions.gameMode == CustomGamemodes.Guesser) // Exclude guesser options in neutral mode + relevantOptions = relevantOptions.Where(x => !(new List { 310, 311, 312, 313, 314, 315, 316, 317, 318 }).Contains(x.id)).ToList(); + createSettings(torSettingsGOM, relevantOptions); + + currentTabs.Add(torSettingsTab); + torSettingsTab.SetActive(false); + } - var longTasksOption = __instance.Children.FirstOrDefault(x => x.name == "NumLongTasks").TryCast(); - if (longTasksOption != null) longTasksOption.ValidRange = new FloatRange(0f, 15f); + private static void createSettingTabs(GameSettingMenu __instance) { + // Handle different gamemodes and tabs needed therein. + int next = 3; + if (TORMapOptions.gameMode == CustomGamemodes.Guesser || TORMapOptions.gameMode == CustomGamemodes.Classic) { + + // create TOR settings + createCustomButton(__instance, next++, "TORSettings", "TOR Settings"); + createGameOptionsMenu(__instance, CustomOptionType.General, "TORSettings"); + // Guesser if applicable + if (TORMapOptions.gameMode == CustomGamemodes.Guesser) { + createCustomButton(__instance, next++, "GuesserSettings", "Guesser Settings"); + createGameOptionsMenu(__instance, CustomOptionType.Guesser, "GuesserSettings"); + } + // IMp + createCustomButton(__instance, next++, "ImpostorSettings", "Impostor Roles"); + createGameOptionsMenu(__instance, CustomOptionType.Impostor, "ImpostorSettings"); + + // Neutral + createCustomButton(__instance, next++, "NeutralSettings", "Neutral Roles"); + createGameOptionsMenu(__instance, CustomOptionType.Neutral, "NeutralSettings"); + // Crew + createCustomButton(__instance, next++, "CrewmateSettings", "Crewmate Roles"); + createGameOptionsMenu(__instance, CustomOptionType.Crewmate, "CrewmateSettings"); + // Modifier + createCustomButton(__instance, next++, "ModifierSettings", "Modifiers"); + createGameOptionsMenu(__instance, CustomOptionType.Modifier, "ModifierSettings"); + + } else if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) { + // create Main HNS settings + createCustomButton(__instance, next++, "HideNSeekMain", "Hide 'N' Seek"); + createGameOptionsMenu(__instance, CustomOptionType.HideNSeekMain, "HideNSeekMain"); + // create HNS Role settings + createCustomButton(__instance, next++, "HideNSeekRoles", "Hide 'N' Seek Roles"); + createGameOptionsMenu(__instance, CustomOptionType.HideNSeekRoles, "HideNSeekRoles"); + } else if (TORMapOptions.gameMode == CustomGamemodes.PropHunt) { + createCustomButton(__instance, next++, "PropHunt", "Prop Hunt"); + createGameOptionsMenu(__instance, CustomOptionType.PropHunt, "PropHunt"); + } } } - [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] + [HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))] public class StringOptionEnablePatch { public static bool Prefix(StringOption __instance) { CustomOption option = CustomOption.options.FirstOrDefault(option => option.optionBehaviour == __instance); if (option == null) return true; __instance.OnValueChanged = new Action((o) => {}); - __instance.TitleText.text = option.name; + //__instance.TitleText.text = option.name; __instance.Value = __instance.oldValue = option.selection; __instance.ValueText.text = option.selections[option.selection].ToString(); @@ -884,7 +851,7 @@ public class RpcSyncSettingsPatch { public static void Postfix() { - CustomOption.ShareOptionSelections(); + //CustomOption.ShareOptionSelections(); CustomOption.saveVanillaOptions(); } } @@ -900,54 +867,6 @@ public static void Postfix() { } - [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Update))] - class GameOptionsMenuUpdatePatch - { - private static float timer = 1f; - public static void Postfix(GameOptionsMenu __instance) { - // Return Menu Update if in normal among us settings - var gameSettingMenu = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(); - if (gameSettingMenu.RegularGameSettings.active || gameSettingMenu.RolesSettings.gameObject.active) return; - - __instance.GetComponentInParent().ContentYBounds.max = -0.5F + __instance.Children.Length * 0.55F; - timer += Time.deltaTime; - if (timer < 0.1f) return; - timer = 0f; - - float offset = 2.75f; - foreach (CustomOption option in CustomOption.options) { - if (GameObject.Find("TORSettings") && option.type != CustomOption.CustomOptionType.General && option.type != CustomOptionType.HideNSeekMain && option.type != CustomOptionType.PropHunt) - continue; - if (GameObject.Find("ImpostorSettings") && option.type != CustomOption.CustomOptionType.Impostor) - continue; - if (GameObject.Find("NeutralSettings") && option.type != CustomOption.CustomOptionType.Neutral) - continue; - if (GameObject.Find("CrewmateSettings") && option.type != CustomOption.CustomOptionType.Crewmate) - continue; - if (GameObject.Find("ModifierSettings") && option.type != CustomOption.CustomOptionType.Modifier) - continue; - if (GameObject.Find("GuesserSettings") && option.type != CustomOption.CustomOptionType.Guesser) - continue; - if (GameObject.Find("HideNSeekSettings") && option.type != CustomOption.CustomOptionType.HideNSeekRoles) - continue; - if (option?.optionBehaviour != null && option.optionBehaviour.gameObject != null) { - bool enabled = true; - var parent = option.parent; - while (parent != null && enabled) { - enabled = parent.selection != 0; - parent = parent.parent; - } - option.optionBehaviour.gameObject.SetActive(enabled); - if (enabled) { - offset -= option.isHeader ? 0.75f : 0.5f; - option.optionBehaviour.transform.localPosition = new Vector3(option.optionBehaviour.transform.localPosition.x, offset, option.optionBehaviour.transform.localPosition.z); - } - } - } - } - } - - [HarmonyPatch] class GameOptionsDataPatch { @@ -958,7 +877,7 @@ private static string buildRoleOptions() { var modifiers = buildOptionsOfType(CustomOption.CustomOptionType.Modifier, true); return impRoles + neutralRoles + crewRoles + modifiers; } - private static string buildModifierExtras(CustomOption customOption) { + public static string buildModifierExtras(CustomOption customOption) { // find options children with quantity var children = CustomOption.options.Where(o => o.parent == customOption); var quantity = children.Where(o => o.name.Contains("Quantity")).ToList(); @@ -1156,7 +1075,7 @@ public static bool Prefix(NormalGameOptionsV07 __instance, ref int maxExpectedPl || __instance.PlayerSpeedMod <= 0f || __instance.PlayerSpeedMod > 3f; } - [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] + [HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))] [HarmonyPrefix] public static void Prefix(StringOption __instance) @@ -1170,7 +1089,7 @@ public static void Prefix(StringOption __instance) } } - [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] + [HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))] [HarmonyPostfix] public static void Postfix(StringOption __instance) @@ -1252,39 +1171,27 @@ public static void Postfix(KeyboardJoystick __instance) if (Input.GetKeyDown(KeyCode.F1)) HudManagerUpdate.ToggleSettings(HudManager.Instance); if (TheOtherRolesPlugin.optionsPage >= GameOptionsDataPatch.maxPage) TheOtherRolesPlugin.optionsPage = 0; - - if (page != TheOtherRolesPlugin.optionsPage) { - Vector3 position = (Vector3)FastDestroyableSingleton.Instance?.GameSettings?.transform.localPosition; - FastDestroyableSingleton.Instance.GameSettings.transform.localPosition = new Vector3(position.x, 2.9f, position.z); - } } } - [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] - public class GameSettingsScalePatch { - public static void Prefix(HudManager __instance) { - if (__instance.GameSettings != null) __instance.GameSettings.fontSize = 1.2f; - } - } - - - // This class is taken and adapted from Town of Us Reactivated, https://github.com/eDonnes124/Town-Of-Us-R/blob/master/source/Patches/CustomOption/Patches.cs, Licensed under GPLv3 + //This class is taken and adapted from Town of Us Reactivated, https://github.com/eDonnes124/Town-Of-Us-R/blob/master/source/Patches/CustomOption/Patches.cs, Licensed under GPLv3 [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] public class HudManagerUpdate { + private static GameObject GameSettingsObject; + private static TextMeshPro GameSettings; public static float MinX,/*-5.3F*/ OriginalY = 2.9F, MinY = 2.9F; - public static Scroller Scroller; private static Vector3 LastPosition; private static float lastAspect; private static bool setLastPosition = false; public static void Prefix(HudManager __instance) { - if (__instance.GameSettings?.transform == null) return; + if (GameSettings?.transform == null) return; // Sets the MinX position to the left edge of the screen + 0.1 units Rect safeArea = Screen.safeArea; @@ -1301,11 +1208,11 @@ public static void Prefix(HudManager __instance) { CreateScroller(__instance); - Scroller.gameObject.SetActive(__instance.GameSettings.gameObject.activeSelf); + Scroller.gameObject.SetActive(GameSettings.gameObject.activeSelf); if (!Scroller.gameObject.active) return; - var rows = __instance.GameSettings.text.Count(c => c == '\n'); + var rows = GameSettings.text.Count(c => c == '\n'); float LobbyTextRowHeight = 0.06F; var maxY = Mathf.Max(MinY, rows * LobbyTextRowHeight + (rows - 38) * LobbyTextRowHeight); @@ -1313,24 +1220,24 @@ public static void Prefix(HudManager __instance) { // Prevent scrolling when the player is interacting with a menu if (CachedPlayer.LocalPlayer?.PlayerControl.CanMove != true) { - __instance.GameSettings.transform.localPosition = LastPosition; + GameSettings.transform.localPosition = LastPosition; return; } - if (__instance.GameSettings.transform.localPosition.x != MinX || - __instance.GameSettings.transform.localPosition.y < MinY) return; + if (GameSettings.transform.localPosition.x != MinX || + GameSettings.transform.localPosition.y < MinY) return; - LastPosition = __instance.GameSettings.transform.localPosition; + LastPosition = GameSettings.transform.localPosition; } private static void CreateScroller(HudManager __instance) { if (Scroller != null) return; - Transform target = __instance.GameSettings.transform; + Transform target = GameSettings.transform; Scroller = new GameObject("SettingsScroller").AddComponent(); - Scroller.transform.SetParent(__instance.GameSettings.transform.parent); + Scroller.transform.SetParent(GameSettings.transform.parent); Scroller.gameObject.layer = 5; Scroller.transform.localScale = Vector3.one; @@ -1381,9 +1288,7 @@ public static void Prefix2(HudManager __instance) { private static TMPro.TextMeshPro[] settingsTMPs = new TMPro.TextMeshPro[4]; private static GameObject settingsBackground; public static void OpenSettings(HudManager __instance) { - if (__instance.FullScreen == null || MapBehaviour.Instance && MapBehaviour.Instance.IsOpen - /*|| AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started*/ - || GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; + if (__instance.FullScreen == null || MapBehaviour.Instance && MapBehaviour.Instance.IsOpen) return; settingsBackground = GameObject.Instantiate(__instance.FullScreen.gameObject, __instance.transform); settingsBackground.SetActive(true); var renderer = settingsBackground.GetComponent(); @@ -1413,20 +1318,52 @@ public static void ToggleSettings(HudManager __instance) { static PassiveButton toggleSettingsButton; static GameObject toggleSettingsButtonObject; + + static GameObject toggleZoomButtonObject; + static PassiveButton toggleZoomButton; + [HarmonyPostfix] public static void Postfix(HudManager __instance) { + if (AmongUsClient.Instance.GameState != InnerNet.InnerNetClient.GameStates.Started) return; if (!toggleSettingsButton || !toggleSettingsButtonObject) { // add a special button for settings viewing: toggleSettingsButtonObject = GameObject.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); - toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -0.66f, -500f); - SpriteRenderer renderer = toggleSettingsButtonObject.GetComponent(); - renderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.CurrentSettingsButton.png", 180f); + toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -1.25f, -500f); + toggleSettingsButtonObject.name = "TOGGLESETTINGSBUTTON"; + SpriteRenderer renderer = toggleSettingsButtonObject.transform.Find("Inactive").GetComponent(); + SpriteRenderer rendererActive = toggleSettingsButtonObject.transform.Find("Active").GetComponent(); + toggleSettingsButtonObject.transform.Find("Background").localPosition = Vector3.zero; + renderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Settings_Button.png", 100f); + rendererActive.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Settings_ButtonActive.png", 100); toggleSettingsButton = toggleSettingsButtonObject.GetComponent(); toggleSettingsButton.OnClick.RemoveAllListeners(); toggleSettingsButton.OnClick.AddListener((Action)(() => ToggleSettings(__instance))); } toggleSettingsButtonObject.SetActive(__instance.MapButton.gameObject.active && !(MapBehaviour.Instance && MapBehaviour.Instance.IsOpen) && GameOptionsManager.Instance.currentGameOptions.GameMode != GameModes.HideNSeek); - toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -0.66f, -500f); + toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -0.8f, -500f); + + + if (!toggleZoomButton || !toggleZoomButtonObject) { + // add a special button for settings viewing: + toggleZoomButtonObject = GameObject.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); + toggleZoomButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -1.25f, -500f); + toggleZoomButtonObject.name = "TOGGLEZOOMBUTTON"; + SpriteRenderer tZrenderer = toggleZoomButtonObject.transform.Find("Inactive").GetComponent(); + SpriteRenderer tZArenderer = toggleZoomButtonObject.transform.Find("Active").GetComponent(); + toggleZoomButtonObject.transform.Find("Background").localPosition = Vector3.zero; + tZrenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Minus_Button.png", 100f); + tZArenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Minus_ButtonActive.png", 100); + toggleZoomButton = toggleZoomButtonObject.GetComponent(); + toggleZoomButton.OnClick.RemoveAllListeners(); + toggleZoomButton.OnClick.AddListener((Action)(() => Helpers.toggleZoom())); + } + var (playerCompleted, playerTotal) = TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data); + int numberOfLeftTasks = playerTotal - playerCompleted; + bool zoomButtonActive = !(CachedPlayer.LocalPlayer.PlayerControl == null || !CachedPlayer.LocalPlayer.Data.IsDead || (CachedPlayer.LocalPlayer.Data.Role.IsImpostor && !CustomOptionHolder.deadImpsBlockSabotage.getBool())); + zoomButtonActive &= numberOfLeftTasks <= 0 || !CustomOptionHolder.finishTasksBeforeHauntingOrZoomingOut.getBool(); + toggleZoomButtonObject.SetActive(zoomButtonActive); + var posOffset = Helpers.zoomOutStatus ? new Vector3(-1.27f, -7.92f, -52f) : new Vector3(0, -1.6f, -52f); + toggleZoomButtonObject.transform.localPosition = HudManager.Instance.MapButton.transform.localPosition + posOffset; } } } diff --git a/TheOtherRoles/Objects/Footprint.cs b/TheOtherRoles/Objects/Footprint.cs index 3c27bd905..88faa78a7 100644 --- a/TheOtherRoles/Objects/Footprint.cs +++ b/TheOtherRoles/Objects/Footprint.cs @@ -34,7 +34,7 @@ private class Footprint { public Transform Transform; public SpriteRenderer Renderer; public PlayerControl Owner; - public GameData.PlayerInfo Data; + public NetworkedPlayerInfo Data; public float Lifetime; public Footprint() { diff --git a/TheOtherRoles/Objects/Silhouette.cs b/TheOtherRoles/Objects/Silhouette.cs index 5d0f09f9e..7d2cfaab2 100644 --- a/TheOtherRoles/Objects/Silhouette.cs +++ b/TheOtherRoles/Objects/Silhouette.cs @@ -29,7 +29,6 @@ public static Sprite getSilhouetteSprite() { public Silhouette(Vector3 p, float duration = 1f, bool visibleForEveryOne = true) { if (duration <= 0f) { - TheOtherRolesPlugin.Logger.LogMessage("silhouette: permanent!"); permanent = true; } this.visibleForEveryOne = visibleForEveryOne; @@ -71,7 +70,6 @@ public static void UpdateAll() { } if (current.timeRemaining < 0 && !current.permanent) { - TheOtherRolesPlugin.Logger.LogMessage($"update: permanent: {current.permanent}, time: {current.timeRemaining}"); current.gameObject.SetActive(false); UnityEngine.Object.Destroy(current.gameObject); silhouettes.Remove(current); diff --git a/TheOtherRoles/Patches/ClientOptionsPatch.cs b/TheOtherRoles/Patches/ClientOptionsPatch.cs index f212c5cf8..36b2b6189 100644 --- a/TheOtherRoles/Patches/ClientOptionsPatch.cs +++ b/TheOtherRoles/Patches/ClientOptionsPatch.cs @@ -22,6 +22,7 @@ public static class ClientOptionsPatch new("Show Lighter / Darker", () => TORMapOptions.showLighterDarker = TheOtherRolesPlugin.ShowLighterDarker.Value = !TheOtherRolesPlugin.ShowLighterDarker.Value, TheOtherRolesPlugin.ShowLighterDarker.Value), new("Enable Sound Effects", () => TORMapOptions.enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value = !TheOtherRolesPlugin.EnableSoundEffects.Value, TheOtherRolesPlugin.EnableSoundEffects.Value), new("Show Vents On Map", () => TORMapOptions.ShowVentsOnMap = TheOtherRolesPlugin.ShowVentsOnMap.Value = !TheOtherRolesPlugin.ShowVentsOnMap.Value, TheOtherRolesPlugin.ShowVentsOnMap.Value), + new("Show Chat Notifications", () => TORMapOptions.ShowChatNotifications = TheOtherRolesPlugin.ShowChatNotifications.Value = !TheOtherRolesPlugin.ShowChatNotifications.Value, TheOtherRolesPlugin.ShowChatNotifications.Value), }; private static GameObject popUp; diff --git a/TheOtherRoles/Patches/ConstantsPatch.cs b/TheOtherRoles/Patches/ConstantsPatch.cs index c9a5fc3fb..7670cfeeb 100644 --- a/TheOtherRoles/Patches/ConstantsPatch.cs +++ b/TheOtherRoles/Patches/ConstantsPatch.cs @@ -4,8 +4,8 @@ namespace TheOtherRoles.Patches { [HarmonyPatch(typeof(Constants), nameof(Constants.GetBroadcastVersion))] public static class ConstantsPatch { public static void Postfix(ref int __result) { - if (AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame) - __result += 25; + /*if (AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame) + __result += 25;*/ } } } \ No newline at end of file diff --git a/TheOtherRoles/Patches/CredentialsPatch.cs b/TheOtherRoles/Patches/CredentialsPatch.cs index 1f9fbd5e1..bc252ff5b 100644 --- a/TheOtherRoles/Patches/CredentialsPatch.cs +++ b/TheOtherRoles/Patches/CredentialsPatch.cs @@ -1,4 +1,5 @@ -using HarmonyLib; +using AmongUs.GameOptions; +using HarmonyLib; using System; using System.Collections.Generic; using System.Net.Http; @@ -32,8 +33,9 @@ internal static class PingTrackerPatch { static void Postfix(PingTracker __instance){ - __instance.text.alignment = TextAlignmentOptions.TopRight; + __instance.text.alignment = TextAlignmentOptions.Top; var position = __instance.GetComponent(); + position.Alignment = AspectPosition.EdgeAlignments.Top; if (AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started) { string gameModeText = $""; if (HideNSeek.isHideNSeekGM) gameModeText = $"Hide 'N Seek"; @@ -47,11 +49,17 @@ static void Postfix(PingTracker __instance){ if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek) gameModeText = $"Hide 'N Seek"; else if (TORMapOptions.gameMode == CustomGamemodes.Guesser) gameModeText = $"Guesser"; else if (TORMapOptions.gameMode == CustomGamemodes.PropHunt) gameModeText = $"Prop Hunt"; - if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText) + "\n"; + if (gameModeText != "") gameModeText = Helpers.cs(Color.yellow, gameModeText); + + __instance.text.text = $"{fullCredentialsVersion}\n{fullCredentials}\n {__instance.text.text}"; + position.DistanceFromEdge = new Vector3( 0f, 0.1f, 0); - var host = $"Host: {GameData.Instance?.GetHost()?.PlayerName}"; - __instance.text.text = $"{fullCredentialsVersion}\n {gameModeText + fullCredentials}\n {host}\n {__instance.text.text}"; - position.DistanceFromEdge = new Vector3(3.5f, 0.1f, 0); + try { + var GameModeText = GameObject.Find("GameModeText")?.GetComponent(); + GameModeText.text = gameModeText == "" ? (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek ? "Van. HideNSeek" : "Classic" ): gameModeText; + var ModeLabel = GameObject.Find("ModeLabel")?.GetComponentInChildren(); + ModeLabel.text = "Game Mode"; + } catch { } } position.AdjustPosition(); } diff --git a/TheOtherRoles/Patches/EndGamePatch.cs b/TheOtherRoles/Patches/EndGamePatch.cs index 8a1c2fd57..485c62110 100644 --- a/TheOtherRoles/Patches/EndGamePatch.cs +++ b/TheOtherRoles/Patches/EndGamePatch.cs @@ -101,11 +101,11 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End notWinners.AddRange(Jackal.formerJackals); - List winnersToRemove = new List(); - foreach (WinningPlayerData winner in TempData.winners.GetFastEnumerator()) { + List winnersToRemove = new List(); + foreach (CachedPlayerData winner in EndGameResult.CachedWinners.GetFastEnumerator()) { if (notWinners.Any(x => x.Data.PlayerName == winner.PlayerName)) winnersToRemove.Add(winner); } - foreach (var winner in winnersToRemove) TempData.winners.Remove(winner); + foreach (var winner in winnersToRemove) EndGameResult.CachedWinners.Remove(winner); bool jesterWin = Jester.jester != null && gameOverReason == (GameOverReason)CustomGameOverReason.JesterWin; bool arsonistWin = Arsonist.arsonist != null && gameOverReason == (GameOverReason)CustomGameOverReason.ArsonistWin; @@ -119,42 +119,42 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End // Mini lose if (miniLose) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Mini.mini.Data); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Mini.mini.Data); wpd.IsYou = false; // If "no one is the Mini", it will display the Mini, but also show defeat to everyone - TempData.winners.Add(wpd); + EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.MiniLose; } // Jester win else if (jesterWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Jester.jester.Data); - TempData.winners.Add(wpd); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Jester.jester.Data); + EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.JesterWin; } // Arsonist win else if (arsonistWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Arsonist.arsonist.Data); - TempData.winners.Add(wpd); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Arsonist.arsonist.Data); + EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.ArsonistWin; } // Vulture win else if (vultureWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Vulture.vulture.Data); - TempData.winners.Add(wpd); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Vulture.vulture.Data); + EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.VultureWin; } // Jester win else if (prosecutorWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Lawyer.lawyer.Data); - TempData.winners.Add(wpd); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Lawyer.lawyer.Data); + EndGameResult.CachedWinners.Add(wpd); AdditionalTempData.winCondition = WinCondition.ProsecutorWin; } @@ -163,23 +163,23 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End // Double win for lovers, crewmates also win if (!Lovers.existingWithKiller()) { AdditionalTempData.winCondition = WinCondition.LoversTeamWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); foreach (PlayerControl p in CachedPlayer.AllPlayers) { if (p == null) continue; if (p == Lovers.lover1 || p == Lovers.lover2) - TempData.winners.Add(new WinningPlayerData(p.Data)); + EndGameResult.CachedWinners.Add(new CachedPlayerData(p.Data)); else if (p == Pursuer.pursuer && !Pursuer.pursuer.Data.IsDead) - TempData.winners.Add(new WinningPlayerData(p.Data)); + EndGameResult.CachedWinners.Add(new CachedPlayerData(p.Data)); else if (p != Jester.jester && p != Jackal.jackal && p != Sidekick.sidekick && p != Arsonist.arsonist && p != Vulture.vulture && !Jackal.formerJackals.Contains(p) && !p.Data.Role.IsImpostor) - TempData.winners.Add(new WinningPlayerData(p.Data)); + EndGameResult.CachedWinners.Add(new CachedPlayerData(p.Data)); } } // Lovers solo win else { AdditionalTempData.winCondition = WinCondition.LoversSoloWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - TempData.winners.Add(new WinningPlayerData(Lovers.lover1.Data)); - TempData.winners.Add(new WinningPlayerData(Lovers.lover2.Data)); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + EndGameResult.CachedWinners.Add(new CachedPlayerData(Lovers.lover1.Data)); + EndGameResult.CachedWinners.Add(new CachedPlayerData(Lovers.lover2.Data)); } } @@ -187,41 +187,41 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)]ref End else if (teamJackalWin) { // Jackal wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.JackalWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new WinningPlayerData(Jackal.jackal.Data); + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + CachedPlayerData wpd = new CachedPlayerData(Jackal.jackal.Data); wpd.IsImpostor = false; - TempData.winners.Add(wpd); + EndGameResult.CachedWinners.Add(wpd); // If there is a sidekick. The sidekick also wins if (Sidekick.sidekick != null) { - WinningPlayerData wpdSidekick = new WinningPlayerData(Sidekick.sidekick.Data); + CachedPlayerData wpdSidekick = new CachedPlayerData(Sidekick.sidekick.Data); wpdSidekick.IsImpostor = false; - TempData.winners.Add(wpdSidekick); + EndGameResult.CachedWinners.Add(wpdSidekick); } foreach(var player in Jackal.formerJackals) { - WinningPlayerData wpdFormerJackal = new WinningPlayerData(player.Data); + CachedPlayerData wpdFormerJackal = new CachedPlayerData(player.Data); wpdFormerJackal.IsImpostor = false; - TempData.winners.Add(wpdFormerJackal); + EndGameResult.CachedWinners.Add(wpdFormerJackal); } } // Possible Additional winner: Lawyer if (Lawyer.lawyer != null && Lawyer.target != null && (!Lawyer.target.Data.IsDead || Lawyer.target == Jester.jester) && !Pursuer.notAckedExiled && !Lawyer.isProsecutor) { - WinningPlayerData winningClient = null; - foreach (WinningPlayerData winner in TempData.winners.GetFastEnumerator()) { + CachedPlayerData winningClient = null; + foreach (CachedPlayerData winner in EndGameResult.CachedWinners.GetFastEnumerator()) { if (winner.PlayerName == Lawyer.target.Data.PlayerName) winningClient = winner; } if (winningClient != null) { // The Lawyer wins if the client is winning (and alive, but if he wasn't the Lawyer shouldn't exist anymore) - if (!TempData.winners.ToArray().Any(x => x.PlayerName == Lawyer.lawyer.Data.PlayerName)) - TempData.winners.Add(new WinningPlayerData(Lawyer.lawyer.Data)); + if (!EndGameResult.CachedWinners.ToArray().Any(x => x.PlayerName == Lawyer.lawyer.Data.PlayerName)) + EndGameResult.CachedWinners.Add(new CachedPlayerData(Lawyer.lawyer.Data)); AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerBonusWin); // The Lawyer wins together with the client } } // Possible Additional winner: Pursuer - if (Pursuer.pursuer != null && !Pursuer.pursuer.Data.IsDead && !Pursuer.notAckedExiled && !isPursurerLose && !TempData.winners.ToArray().Any(x => x.IsImpostor)) { - if (!TempData.winners.ToArray().Any(x => x.PlayerName == Pursuer.pursuer.Data.PlayerName)) - TempData.winners.Add(new WinningPlayerData(Pursuer.pursuer.Data)); + if (Pursuer.pursuer != null && !Pursuer.pursuer.Data.IsDead && !Pursuer.notAckedExiled && !isPursurerLose && !EndGameResult.CachedWinners.ToArray().Any(x => x.IsImpostor)) { + if (!EndGameResult.CachedWinners.ToArray().Any(x => x.PlayerName == Pursuer.pursuer.Data.PlayerName)) + EndGameResult.CachedWinners.Add(new CachedPlayerData(Pursuer.pursuer.Data)); AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalAlivePursuerWin); } @@ -242,16 +242,16 @@ public static void Postfix(EndGameManager __instance) { UnityEngine.Object.Destroy(pb.gameObject); } int num = Mathf.CeilToInt(7.5f); - List list = TempData.winners.ToArray().ToList().OrderBy(delegate(WinningPlayerData b) + List list = EndGameResult.CachedWinners.ToArray().ToList().OrderBy(delegate(CachedPlayerData b) { if (!b.IsYou) { return 0; } return -1; - }).ToList(); + }).ToList(); for (int i = 0; i < list.Count; i++) { - WinningPlayerData winningPlayerData2 = list[i]; + CachedPlayerData CachedPlayerData2 = list[i]; int num2 = (i % 2 == 0) ? -1 : 1; int num3 = (i + 1) / 2; float num4 = (float)num3 / (float)num; @@ -262,21 +262,21 @@ public static void Postfix(EndGameManager __instance) { float num7 = Mathf.Lerp(1f, 0.65f, num4) * 0.9f; Vector3 vector = new Vector3(num7, num7, 1f); poolablePlayer.transform.localScale = vector; - if (winningPlayerData2.IsDead) { + if (CachedPlayerData2.IsDead) { poolablePlayer.SetBodyAsGhost(); poolablePlayer.SetDeadFlipX(i % 2 == 0); } else { poolablePlayer.SetFlipX(i % 2 == 0); } - poolablePlayer.UpdateFromPlayerOutfit(winningPlayerData2, PlayerMaterial.MaskType.None, winningPlayerData2.IsDead, true); + poolablePlayer.UpdateFromPlayerOutfit(CachedPlayerData2.Outfit, PlayerMaterial.MaskType.None, CachedPlayerData2.IsDead, true); poolablePlayer.cosmetics.nameText.color = Color.white; poolablePlayer.cosmetics.nameText.transform.localScale = new Vector3(1f / vector.x, 1f / vector.y, 1f / vector.z); poolablePlayer.cosmetics.nameText.transform.localPosition = new Vector3(poolablePlayer.cosmetics.nameText.transform.localPosition.x, poolablePlayer.cosmetics.nameText.transform.localPosition.y, -15f); - poolablePlayer.cosmetics.nameText.text = winningPlayerData2.PlayerName; + poolablePlayer.cosmetics.nameText.text = CachedPlayerData2.PlayerName; foreach(var data in AdditionalTempData.playerRoles) { - if (data.PlayerName != winningPlayerData2.PlayerName) continue; + if (data.PlayerName != CachedPlayerData2.PlayerName) continue; var roles = poolablePlayer.cosmetics.nameText.text += $"\n{string.Join("\n", data.Roles.Select(x => Helpers.cs(x.color, x.name)))}"; } @@ -495,7 +495,7 @@ private static bool CheckAndEndGameForImpostorWin(ShipStatus __instance, PlayerS if (statistics.TeamImpostorsAlive >= statistics.TotalAlive - statistics.TeamImpostorsAlive && statistics.TeamJackalAlive == 0 && !(statistics.TeamImpostorHasAliveLover && statistics.TeamLoversAlive == 2)) { //__instance.enabled = false; GameOverReason endReason; - switch (TempData.LastDeathReason) { + switch (GameData.LastDeathReason) { case DeathReason.Exile: endReason = GameOverReason.ImpostorByVote; break; @@ -550,7 +550,7 @@ public PlayerStatistics(ShipStatus __instance) { GetPlayerCounts(); } - private bool isLover(GameData.PlayerInfo p) { + private bool isLover(NetworkedPlayerInfo p) { return (Lovers.lover1 != null && Lovers.lover1.PlayerId == p.PlayerId) || (Lovers.lover2 != null && Lovers.lover2.PlayerId == p.PlayerId); } diff --git a/TheOtherRoles/Patches/ExileControllerPatch.cs b/TheOtherRoles/Patches/ExileControllerPatch.cs index 50e1f831b..12b1ea2f3 100644 --- a/TheOtherRoles/Patches/ExileControllerPatch.cs +++ b/TheOtherRoles/Patches/ExileControllerPatch.cs @@ -13,8 +13,8 @@ namespace TheOtherRoles.Patches { [HarmonyPatch(typeof(ExileController), nameof(ExileController.Begin))] [HarmonyPriority(Priority.First)] class ExileControllerBeginPatch { - public static GameData.PlayerInfo lastExiled; - public static void Prefix(ExileController __instance, [HarmonyArgument(0)]ref GameData.PlayerInfo exiled, [HarmonyArgument(1)]bool tie) { + public static NetworkedPlayerInfo lastExiled; + public static void Prefix(ExileController __instance, [HarmonyArgument(0)]ref NetworkedPlayerInfo exiled, [HarmonyArgument(1)]bool tie) { lastExiled = exiled; // Medic shield @@ -158,7 +158,7 @@ public static void Prefix(GameObject obj) { } } - static void WrapUpPostfix(GameData.PlayerInfo exiled) { + static void WrapUpPostfix(NetworkedPlayerInfo exiled) { // Prosecutor win condition if (exiled != null && Lawyer.lawyer != null && Lawyer.target != null && Lawyer.isProsecutor && Lawyer.target.PlayerId == exiled.PlayerId && !Lawyer.lawyer.Data.IsDead) Lawyer.triggerProsecutorWin = true; diff --git a/TheOtherRoles/Patches/GameStartManagerPatch.cs b/TheOtherRoles/Patches/GameStartManagerPatch.cs index c5eb05338..afe8f4b0e 100644 --- a/TheOtherRoles/Patches/GameStartManagerPatch.cs +++ b/TheOtherRoles/Patches/GameStartManagerPatch.cs @@ -24,6 +24,7 @@ public static void Postfix(AmongUsClient __instance) { if (CachedPlayer.LocalPlayer != null) { Helpers.shareGameVersion(); } + GameStartManagerUpdatePatch.sendGamemode = true; } } @@ -49,6 +50,7 @@ public class GameStartManagerUpdatePatch { private static bool update = false; private static string currentText = ""; private static GameObject copiedStartButton; + public static bool sendGamemode = true; public static void Prefix(GameStartManager __instance) { if (!GameData.Instance ) return; // No instance @@ -63,15 +65,12 @@ public static void Postfix(GameStartManager __instance) { Helpers.shareGameVersion(); } - // Check version handshake infos + // Check version handshake infos bool versionMismatch = false; string message = ""; foreach (InnerNet.ClientData client in AmongUsClient.Instance.allClients.ToArray()) { if (client.Character == null) continue; - var dummyComponent = client.Character.GetComponent(); - if (dummyComponent != null && dummyComponent.enabled) - continue; else if (!playerVersions.ContainsKey(client.Id)) { versionMismatch = true; message += $"{client.Character.Data.PlayerName} has a different or no version of The Other Roles\n"; @@ -90,39 +89,39 @@ public static void Postfix(GameStartManager __instance) { } } } - // Display message to the host if (AmongUsClient.Instance.AmHost) { if (versionMismatch) { - __instance.StartButton.color = __instance.startLabelText.color = Palette.DisabledClear; __instance.GameStartText.text = message; - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 2; + __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 5; + __instance.GameStartText.transform.localScale = new Vector3(2f, 2f, 1f); + __instance.GameStartTextParent.SetActive(true); } else { - __instance.StartButton.color = __instance.startLabelText.color = ((__instance.LastPlayerCount >= __instance.MinPlayers) ? Palette.EnabledColor : Palette.DisabledClear); - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition; + __instance.GameStartText.transform.localPosition = Vector3.zero; + __instance.GameStartText.transform.localScale = new Vector3(1.2f, 1.2f, 1f); + if (!__instance.GameStartText.text.StartsWith("Starting")) { + __instance.GameStartText.text = String.Empty; + __instance.GameStartTextParent.SetActive(false); + } } if (__instance.startState != GameStartManager.StartingStates.Countdown) copiedStartButton?.Destroy(); - // Make starting info available to clients: if (startingTimer <= 0 && __instance.startState == GameStartManager.StartingStates.Countdown) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetGameStarting, Hazel.SendOption.Reliable, -1); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.setGameStarting(); - // Activate Stop-Button copiedStartButton = GameObject.Instantiate(__instance.StartButton.gameObject, __instance.StartButton.gameObject.transform.parent); copiedStartButton.transform.localPosition = __instance.StartButton.transform.localPosition; - copiedStartButton.GetComponent().sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.StopClean.png", 180f); copiedStartButton.SetActive(true); var startButtonText = copiedStartButton.GetComponentInChildren(); - startButtonText.text = "STOP"; + startButtonText.text = ""; startButtonText.fontSize *= 0.8f; startButtonText.fontSizeMax = startButtonText.fontSize; startButtonText.gameObject.transform.localPosition = Vector3.zero; PassiveButton startButtonPassiveButton = copiedStartButton.GetComponent(); - void StopStartFunc() { __instance.ResetStartState(); copiedStartButton.Destroy(); @@ -130,14 +129,13 @@ void StopStartFunc() { } startButtonPassiveButton.OnClick.AddListener((Action)(() => StopStartFunc())); __instance.StartCoroutine(Effects.Lerp(.1f, new System.Action((p) => { - startButtonText.text = "STOP"; + startButtonText.text = ""; }))); + } - if (__instance.startState == GameStartManager.StartingStates.Countdown) - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 0.6f; } - + // Client update with handshake infos else { if (!playerVersions.ContainsKey(AmongUsClient.Instance.HostId) || TheOtherRolesPlugin.Version.CompareTo(playerVersions[AmongUsClient.Instance.HostId].version) != 0) { @@ -149,14 +147,21 @@ void StopStartFunc() { } __instance.GameStartText.text = $"The host has no or a different version of The Other Roles\nYou will be kicked in {Math.Round(10 - kickingTimer)}s"; - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 2; + __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 5; + __instance.GameStartText.transform.localScale = new Vector3(2f, 2f, 1f); + __instance.GameStartTextParent.SetActive(true); } else if (versionMismatch) { __instance.GameStartText.text = $"Players With Different Versions:\n" + message; - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 2; + __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 5; + __instance.GameStartText.transform.localScale = new Vector3(2f, 2f, 1f); + __instance.GameStartTextParent.SetActive(true); } else { - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition; - if (!__instance.GameStartText.text.StartsWith("Starting")) + __instance.GameStartText.transform.localPosition = Vector3.zero; + __instance.GameStartText.transform.localScale = new Vector3(1.2f, 1.2f, 1f); + if (!__instance.GameStartText.text.StartsWith("Starting")) { __instance.GameStartText.text = String.Empty; + __instance.GameStartTextParent.SetActive(false); + } } if (!__instance.GameStartText.text.StartsWith("Starting") || !CustomOptionHolder.anyPlayerCanStopStart.getBool()) @@ -166,10 +171,9 @@ void StopStartFunc() { // Activate Stop-Button copiedStartButton = GameObject.Instantiate(__instance.StartButton.gameObject, __instance.StartButton.gameObject.transform.parent); copiedStartButton.transform.localPosition = __instance.StartButton.transform.localPosition; - copiedStartButton.GetComponent().sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.StopClean.png", 180f); copiedStartButton.SetActive(true); var startButtonText = copiedStartButton.GetComponentInChildren(); - startButtonText.text = "STOP"; + startButtonText.text = ""; startButtonText.fontSize *= 0.8f; startButtonText.fontSizeMax = startButtonText.fontSize; startButtonText.gameObject.transform.localPosition = Vector3.zero; @@ -185,20 +189,16 @@ void StopStartFunc() { } startButtonPassiveButton.OnClick.AddListener((Action)(() => StopStartFunc())); __instance.StartCoroutine(Effects.Lerp(.1f, new System.Action((p) => { - startButtonText.text = "STOP"; + startButtonText.text = ""; }))); - } - if (__instance.GameStartText.text.StartsWith("Starting") && CustomOptionHolder.anyPlayerCanStopStart.getBool()) - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 0.6f; } - // Start Timer if (startingTimer > 0) { startingTimer -= Time.deltaTime; } // Lobby timer - if (!GameData.Instance) return; // No instance + if (!GameData.Instance || !__instance.PlayerCounter) return; // No instance if (update) currentText = __instance.PlayerCounter.text; @@ -207,14 +207,14 @@ void StopStartFunc() { int seconds = (int)timer % 60; string suffix = $" ({minutes:00}:{seconds:00})"; - __instance.PlayerCounter.text = currentText + suffix; - __instance.PlayerCounter.autoSizeTextContainer = true; + if (!AmongUsClient.Instance) return; - if (AmongUsClient.Instance.AmHost) { + if (AmongUsClient.Instance.AmHost && sendGamemode && CachedPlayer.LocalPlayer != null) { MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareGamemode, Hazel.SendOption.Reliable, -1); writer.Write((byte) TORMapOptions.gameMode); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.shareGamemode((byte) TORMapOptions.gameMode); + sendGamemode = false; } } } @@ -262,13 +262,15 @@ public static bool Prefix(GameStartManager __instance) { // 4 = Airship // 5 = Submerged byte chosenMapId = 0; - List probabilities = new List(); - probabilities.Add(CustomOptionHolder.dynamicMapEnableSkeld.getSelection() / 10f); - probabilities.Add(CustomOptionHolder.dynamicMapEnableMira.getSelection() / 10f); - probabilities.Add(CustomOptionHolder.dynamicMapEnablePolus.getSelection() / 10f); - probabilities.Add(CustomOptionHolder.dynamicMapEnableAirShip.getSelection() / 10f); - probabilities.Add(CustomOptionHolder.dynamicMapEnableFungle.getSelection() / 10f); - probabilities.Add(CustomOptionHolder.dynamicMapEnableSubmerged.getSelection() / 10f); + List probabilities = + [ + CustomOptionHolder.dynamicMapEnableSkeld.getSelection() / 10f, + CustomOptionHolder.dynamicMapEnableMira.getSelection() / 10f, + CustomOptionHolder.dynamicMapEnablePolus.getSelection() / 10f, + CustomOptionHolder.dynamicMapEnableAirShip.getSelection() / 10f, + CustomOptionHolder.dynamicMapEnableFungle.getSelection() / 10f, + CustomOptionHolder.dynamicMapEnableSubmerged.getSelection() / 10f, + ]; // if any map is at 100%, remove all maps that are not! if (probabilities.Contains(1.0f)) { diff --git a/TheOtherRoles/Patches/GetStringPatch.cs b/TheOtherRoles/Patches/GetStringPatch.cs new file mode 100644 index 000000000..a39580a76 --- /dev/null +++ b/TheOtherRoles/Patches/GetStringPatch.cs @@ -0,0 +1,31 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TheOtherRoles.Patches { + [HarmonyPatch] + class GetStringPatch { + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), new[] { + typeof(StringNames), + typeof(Il2CppReferenceArray) + })] + public static bool Prefix(TranslationController __instance, StringNames id, ref string __result) { + if ((int)id < 6000) { + return true; + } + string ourString = ""; + + // For now only do this in custom options. + int idInt = (int)id - 6000; + CustomOption opt = CustomOption.options.FirstOrDefault(x => x.id == idInt); + ourString = opt?.name; + + __result = ourString; + + return false; + } + } +} diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index 101b97a88..e2bb76795 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -27,7 +27,7 @@ public static void Prefix(IntroCutscene __instance) { bottomLeft = new Vector3(xpos / 2, ypos/2, -61f); foreach (PlayerControl p in CachedPlayer.AllPlayers) { - GameData.PlayerInfo data = p.Data; + NetworkedPlayerInfo data = p.Data; PoolablePlayer player = UnityEngine.Object.Instantiate(__instance.PlayerPrefab, FastDestroyableSingleton.Instance.transform); playerPrefab = __instance.PlayerPrefab; p.SetPlayerMaterialColors(player.cosmetics.currentBodySprite.BodySprite); @@ -241,7 +241,6 @@ static public void SetRoleTexts(IntroCutscene __instance) { } } public static bool Prefix(IntroCutscene __instance) { - if (!CustomOptionHolder.activateRoles.getBool()) return true; seed = rnd.Next(5000); FastDestroyableSingleton.Instance.StartCoroutine(Effects.Lerp(1f, new Action((p) => { SetRoleTexts(__instance); diff --git a/TheOtherRoles/Patches/MeetingPatch.cs b/TheOtherRoles/Patches/MeetingPatch.cs index 0a9023d17..e73bbf3de 100644 --- a/TheOtherRoles/Patches/MeetingPatch.cs +++ b/TheOtherRoles/Patches/MeetingPatch.cs @@ -17,7 +17,7 @@ namespace TheOtherRoles.Patches { class MeetingHudPatch { static bool[] selections; static SpriteRenderer[] renderers; - private static GameData.PlayerInfo target = null; + private static NetworkedPlayerInfo target = null; private const float scale = 0.65f; private static TMPro.TextMeshPro meetingExtraButtonText; private static PassiveButton[] swapperButtonList; @@ -79,10 +79,10 @@ static bool Prefix(MeetingHud __instance) { Dictionary self = CalculateVotes(__instance); bool tie; KeyValuePair max = self.MaxPair(out tie); - GameData.PlayerInfo exiled = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(v => !tie && v.PlayerId == max.Key && !v.IsDead); + NetworkedPlayerInfo exiled = GameData.Instance.AllPlayers.ToArray().FirstOrDefault(v => !tie && v.PlayerId == max.Key && !v.IsDead); // TieBreaker - List potentialExiled = new List(); + List potentialExiled = new List(); bool skipIsTie = false; if (self.Count > 0) { Tiebreaker.isTiebreak = false; @@ -138,7 +138,7 @@ static bool Prefix(MeetingHud __instance) { [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.BloopAVoteIcon))] class MeetingHudBloopAVoteIconPatch { - public static bool Prefix(MeetingHud __instance, GameData.PlayerInfo voterPlayer, int index, Transform parent) { + public static bool Prefix(MeetingHud __instance, NetworkedPlayerInfo voterPlayer, int index, Transform parent) { var spriteRenderer = UnityEngine.Object.Instantiate(__instance.PlayerVotePrefab); var showVoteColors = !GameManager.Instance.LogicOptions.GetAnonymousVotes() || (CachedPlayer.LocalPlayer.Data.IsDead && TORMapOptions.ghostsSeeVotes) || @@ -200,7 +200,7 @@ private static bool Prefix(MeetingHud __instance, Il2CppStructArray() { RoleId.Janitor, RoleId.Godfather, RoleId.Mafioso }.Contains(roleInfo.roleId) && CustomOptionHolder.mafiaSpawnRate.getSelection() == 0) continue; + else if (new List() { RoleId.Janitor, RoleId.Godfather, RoleId.Mafioso }.Contains(roleInfo.roleId) && (CustomOptionHolder.mafiaSpawnRate.getSelection() == 0 || GameOptionsManager.Instance.currentGameOptions.NumImpostors < 3)) continue; else if (roleInfo.roleId == RoleId.Sidekick && (!CustomOptionHolder.jackalCanCreateSidekick.getBool() || CustomOptionHolder.jackalSpawnRate.getSelection() == 0)) continue; if (roleInfo.roleId == RoleId.Deputy && (CustomOptionHolder.deputySpawnRate.getSelection() == 0 || CustomOptionHolder.sheriffSpawnRate.getSelection() == 0)) continue; if (roleInfo.roleId == RoleId.Pursuer && CustomOptionHolder.lawyerSpawnRate.getSelection() == 0) continue; @@ -654,7 +654,7 @@ static void Postfix(MeetingHud __instance, [HarmonyArgument(0)]MessageReader rea [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.StartMeeting))] class StartMeetingPatch { - public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)]GameData.PlayerInfo meetingTarget) { + public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)]NetworkedPlayerInfo meetingTarget) { RoomTracker roomTracker = FastDestroyableSingleton.Instance?.roomTracker; byte roomId = Byte.MinValue; if (roomTracker != null && roomTracker.LastRoom != null) { diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index 213d1e2f8..ace0e5f25 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -1133,7 +1133,7 @@ public static bool Prefix(PlayerControl __instance) { [HarmonyPatch(typeof(PlayerControl), nameof(CachedPlayer.LocalPlayer.PlayerControl.CmdReportDeadBody))] class BodyReportPatch { - static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]GameData.PlayerInfo target) + static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]NetworkedPlayerInfo target) { // Medic or Detective report bool isMedicReport = Medic.medic != null && Medic.medic == CachedPlayer.LocalPlayer.PlayerControl && __instance.PlayerId == Medic.medic.PlayerId; diff --git a/TheOtherRoles/Patches/RegionMenuPatch.cs b/TheOtherRoles/Patches/RegionMenuPatch.cs index 2f69c758b..b9363c767 100644 --- a/TheOtherRoles/Patches/RegionMenuPatch.cs +++ b/TheOtherRoles/Patches/RegionMenuPatch.cs @@ -36,6 +36,7 @@ public static class RegionMenuOpenPatch { private static TextBoxTMP ipField; private static TextBoxTMP portField; + private static GameObject serverWarning; public static void Postfix(RegionMenu __instance) { if (!__instance.TryCast()) return; @@ -141,6 +142,20 @@ void onFocusLost() { TheOtherRolesPlugin.UpdateRegions(); } } + + if (serverWarning == null) { + var tmplt = __instance.ButtonPool.activeChildren[^1] ; + serverWarning = GameObject.Instantiate(tmplt.transform.GetChild(0).gameObject, tmplt.transform); + var comp = serverWarning.GetComponent(); + comp.fontSizeMin = 2; + comp.fontSizeMax = 2; + serverWarning.transform.localPosition = new Vector3(0f, -3f, -10f); + __instance.StartCoroutine(Effects.Lerp(0.1f, new Action((p) => { + comp.text = Helpers.cs(Color.red, "Vanilla Servers Are Currently Not Compatible With TOR"); + }))); + serverWarning.SetActive(true); + } + } } diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 31c7855d7..ded2828b3 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -11,10 +11,10 @@ using TheOtherRoles.CustomGameModes; namespace TheOtherRoles.Patches { - [HarmonyPatch(typeof(RoleOptionsCollectionV07), nameof(RoleOptionsCollectionV07.GetNumPerGame))] + [HarmonyPatch(typeof(RoleOptionsCollectionV08), nameof(RoleOptionsCollectionV08.GetNumPerGame))] class RoleOptionsDataGetNumPerGamePatch{ public static void Postfix(ref int __result) { - if (CustomOptionHolder.activateRoles.getBool() && GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal) __result = 0; // Deactivate Vanilla Roles if the mod roles are active + if (GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal) __result = 0; // Deactivate Vanilla Roles if the mod roles are active } } @@ -52,8 +52,7 @@ public static void Postfix() { AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.resetVariables(); if (TORMapOptions.gameMode == CustomGamemodes.HideNSeek || TORMapOptions.gameMode == CustomGamemodes.PropHunt || GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; // Don't assign Roles in Hide N Seek - if (CustomOptionHolder.activateRoles.getBool()) // Don't assign Roles in Tutorial or if deactivated - assignRoles(); + assignRoles(); } private static void assignRoles() { @@ -66,7 +65,7 @@ private static void assignRoles() { assignRoleTargets(data); // Assign targets for Lawyer & Prosecutor if (isGuesserGamemode) assignGuesserGamemode(); assignModifiers(); // Assign modifier - setRolesAgain(); + //setRolesAgain(); } public static RoleAssignmentData getRoleAssignmentData() { @@ -524,7 +523,7 @@ private static byte setRoleToRandomPlayer(byte roleId, List playe playerRoleMap.Add(new Tuple(playerId, roleId)); - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.SetRole, Hazel.SendOption.Reliable, -1); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetRole, Hazel.SendOption.Reliable, -1); writer.Write(roleId); writer.Write(playerId); AmongUsClient.Instance.FinishRpcImmediately(writer); diff --git a/TheOtherRoles/Patches/ShipStatusPatch.cs b/TheOtherRoles/Patches/ShipStatusPatch.cs index 18d48a222..26c739231 100644 --- a/TheOtherRoles/Patches/ShipStatusPatch.cs +++ b/TheOtherRoles/Patches/ShipStatusPatch.cs @@ -14,7 +14,7 @@ public class ShipStatusPatch { [HarmonyPrefix] [HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CalculateLightRadius))] - public static bool Prefix(ref float __result, ShipStatus __instance, [HarmonyArgument(0)] GameData.PlayerInfo player) { + public static bool Prefix(ref float __result, ShipStatus __instance, [HarmonyArgument(0)] NetworkedPlayerInfo player) { if ((!__instance.Systems.ContainsKey(SystemTypes.Electrical) && !Helpers.isFungle()) || GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return true; // If Game Mode is PropHunt: diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 6c6569f1e..0da7c82fb 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -19,7 +19,7 @@ namespace TheOtherRoles.Patches { [HarmonyPatch(typeof(Vent), nameof(Vent.CanUse))] public static class VentCanUsePatch { - public static bool Prefix(Vent __instance, ref float __result, [HarmonyArgument(0)] GameData.PlayerInfo pc, [HarmonyArgument(1)] ref bool canUse, [HarmonyArgument(2)] ref bool couldUse) { + public static bool Prefix(Vent __instance, ref float __result, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] ref bool canUse, [HarmonyArgument(2)] ref bool couldUse) { if (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return true; float num = float.MaxValue; PlayerControl @object = pc.Object; @@ -271,7 +271,7 @@ static void Postfix(EmergencyMinigame __instance) { [HarmonyPatch(typeof(Console), nameof(Console.CanUse))] public static class ConsoleCanUsePatch { - public static bool Prefix(ref float __result, Console __instance, [HarmonyArgument(0)] GameData.PlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse) { + public static bool Prefix(ref float __result, Console __instance, [HarmonyArgument(0)] NetworkedPlayerInfo pc, [HarmonyArgument(1)] out bool canUse, [HarmonyArgument(2)] out bool couldUse) { canUse = couldUse = false; if (Swapper.swapper != null && Swapper.swapper == CachedPlayer.LocalPlayer.PlayerControl) return !__instance.TaskTypes.Any(x => x == TaskTypes.FixLights || x == TaskTypes.FixComms); @@ -340,7 +340,7 @@ static void Postfix(VitalsMinigame __instance) { if (Hacker.hacker != null && Hacker.hacker == CachedPlayer.LocalPlayer.PlayerControl && Hacker.hackerTimer > 0) { for (int k = 0; k < __instance.vitals.Length; k++) { VitalsPanel vitalsPanel = __instance.vitals[k]; - GameData.PlayerInfo player = vitalsPanel.PlayerInfo; + NetworkedPlayerInfo player = vitalsPanel.PlayerInfo; // Hacker update if (vitalsPanel.IsDead) { @@ -416,7 +416,7 @@ static bool Prefix(MapCountOverlay __instance) { num2++; DeadBody bodyComponent = collider2D.GetComponent(); if (bodyComponent) { - GameData.PlayerInfo playerInfo = GameData.Instance.GetPlayerById(bodyComponent.ParentId); + NetworkedPlayerInfo playerInfo = GameData.Instance.GetPlayerById(bodyComponent.ParentId); if (playerInfo != null) { var color = Palette.PlayerColors[playerInfo.DefaultOutfit.ColorId]; if (Hacker.onlyColorType) diff --git a/TheOtherRoles/Players/CachedPlayer.cs b/TheOtherRoles/Players/CachedPlayer.cs index 2cbee9abf..39dcf9728 100644 --- a/TheOtherRoles/Players/CachedPlayer.cs +++ b/TheOtherRoles/Players/CachedPlayer.cs @@ -19,7 +19,7 @@ public class CachedPlayer public PlayerControl PlayerControl; public PlayerPhysics PlayerPhysics; public CustomNetworkTransform NetTransform; - public GameData.PlayerInfo Data; + public NetworkedPlayerInfo Data; public byte PlayerId; public static implicit operator bool(CachedPlayer player) @@ -99,7 +99,7 @@ public static void RemoveCachedPlayerPatch(PlayerControl __instance) CachedPlayer.PlayerPtrs.Remove(__instance.Pointer); } - [HarmonyPatch(typeof(GameData), nameof(GameData.Deserialize))] + [HarmonyPatch(typeof(NetworkedPlayerInfo), nameof(NetworkedPlayerInfo.Deserialize))] [HarmonyPostfix] public static void AddCachedDataOnDeserialize() { diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index 8c1166366..1c9da7bf2 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -16,6 +16,7 @@ using AmongUs.Data; using AmongUs.GameOptions; using Assets.CoreScripts; +using Reactor.Utilities.Extensions; namespace TheOtherRoles { public enum RoleId { @@ -83,7 +84,7 @@ enum CustomRPC { // Main Controls - ResetVaribles = 60, + ResetVaribles = 100, ShareOptions, ForceEnd, WorkaroundSetRoles, @@ -101,7 +102,7 @@ enum CustomRPC // Role functionality - EngineerFixLights = 101, + EngineerFixLights = 120, EngineerFixSubmergedOxygen, EngineerUsedRepair, CleanBody, @@ -197,7 +198,7 @@ public static void HandleShareOptions(byte numberOfOptions, MessageReader reader uint optionId = reader.ReadPackedUInt32(); uint selection = reader.ReadPackedUInt32(); CustomOption option = CustomOption.options.First(option => option.id == (int)optionId); - option.updateSelection((int)selection); + option.updateSelection((int)selection, i == numberOfOptions - 1); } } catch (Exception e) { TheOtherRolesPlugin.Logger.LogError("Error while deserializing options: " + e.Message); @@ -212,7 +213,7 @@ public static void forceEnd() { { GameData.Instance.GetPlayerById(player.PlayerId); // player.RemoveInfected(); (was removed in 2022.12.08, no idea if we ever need that part again, replaced by these 2 lines.) - player.SetRole(RoleTypes.Crewmate); + player.CoSetRole(RoleTypes.Crewmate, true); player.MurderPlayer(player); player.Data.IsDead = true; @@ -222,6 +223,9 @@ public static void forceEnd() { public static void shareGamemode(byte gm) { TORMapOptions.gameMode = (CustomGamemodes) gm; + LobbyViewSettingsPatch.currentButtons?.ForEach(x => x.gameObject?.Destroy()); + LobbyViewSettingsPatch.currentButtons?.Clear(); + LobbyViewSettingsPatch.currentButtonTypes?.Clear(); } public static void stopStart(byte playerId) { @@ -249,7 +253,7 @@ public static void workaroundSetRoles(byte numberOfRoles, MessageReader reader) public static void setRole(byte roleId, byte playerId) { foreach (PlayerControl player in CachedPlayer.AllPlayers) { if (player.PlayerId == playerId) { - switch((RoleId)roleId) { + switch ((RoleId)roleId) { case RoleId.Jester: Jester.jester = player; break; @@ -259,7 +263,7 @@ public static void setRole(byte roleId, byte playerId) { case RoleId.Portalmaker: Portalmaker.portalmaker = player; break; - case RoleId.Engineer: + case RoleId.Engineer: Engineer.engineer = player; break; case RoleId.Sheriff: @@ -389,7 +393,7 @@ public static void setRole(byte roleId, byte playerId) { } if (AmongUsClient.Instance.AmHost && Helpers.roleCanUseVents(player) && !player.Data.Role.IsImpostor) { player.RpcSetRole(RoleTypes.Engineer); - player.SetRole(RoleTypes.Engineer); + player.CoSetRole(RoleTypes.Engineer, true); } } } @@ -981,6 +985,7 @@ public static void guesserShoot(byte killerId, byte dyingTargetId, byte guessedT } } + bool lawyerDiedAdditionally = false; if (Lawyer.lawyer != null && !Lawyer.isProsecutor && Lawyer.lawyer.PlayerId == killerId && Lawyer.target != null && Lawyer.target.PlayerId == dyingTargetId) { // Lawyer guessed client. if (CachedPlayer.LocalPlayer.PlayerControl == Lawyer.lawyer) { @@ -988,6 +993,8 @@ public static void guesserShoot(byte killerId, byte dyingTargetId, byte guessedT if (MeetingHudPatch.guesserUI != null) MeetingHudPatch.guesserUIExitButton.OnClick.Invoke(); } Lawyer.lawyer.Exiled(); + lawyerDiedAdditionally = true; + GameHistory.overrideDeathReasonAndKiller(Lawyer.lawyer, DeadPlayer.CustomDeathReason.LawyerSuicide, guesser); } dyingTarget.Exiled(); @@ -997,15 +1004,15 @@ public static void guesserShoot(byte killerId, byte dyingTargetId, byte guessedT HandleGuesser.remainingShots(killerId, true); if (Constants.ShouldPlaySfx()) SoundManager.Instance.PlaySound(dyingTarget.KillSfx, false, 0.8f); if (MeetingHud.Instance) { - MeetingHudPatch.swapperCheckAndReturnSwap(MeetingHud.Instance, dyingTargetId); foreach (PlayerVoteArea pva in MeetingHud.Instance.playerStates) { - if (pva.TargetPlayerId == dyingTargetId || pva.TargetPlayerId == partnerId) { + if (pva.TargetPlayerId == dyingTargetId || pva.TargetPlayerId == partnerId || lawyerDiedAdditionally && Lawyer.lawyer.PlayerId == pva.TargetPlayerId) { pva.SetDead(pva.DidReport, true); pva.Overlay.gameObject.SetActive(true); + MeetingHudPatch.swapperCheckAndReturnSwap(MeetingHud.Instance, pva.TargetPlayerId); } //Give players back their vote if target is shot dead - if (pva.VotedFor != dyingTargetId || pva.VotedFor != partnerId) continue; + if (pva.VotedFor != dyingTargetId && pva.VotedFor != partnerId && (!lawyerDiedAdditionally || Lawyer.lawyer.PlayerId != pva.VotedFor)) continue; pva.UnsetVote(); var voteAreaPlayer = Helpers.playerById(pva.TargetPlayerId); if (!voteAreaPlayer.AmOwner) continue; @@ -1311,7 +1318,6 @@ public static void yoyoMarkLocation(byte[] buff) { } public static void yoyoBlink(bool isFirstJump, byte[] buff) { - TheOtherRolesPlugin.Logger.LogMessage($"blink fistjumpo: {isFirstJump}"); if (Yoyo.yoyo == null || Yoyo.markedLocation == null) return; var markedPos = (Vector3)Yoyo.markedLocation; Yoyo.yoyo.NetTransform.SnapTo(markedPos); diff --git a/TheOtherRoles/Resources/Copy.png b/TheOtherRoles/Resources/Copy.png new file mode 100644 index 000000000..1db34bbf7 Binary files /dev/null and b/TheOtherRoles/Resources/Copy.png differ diff --git a/TheOtherRoles/Resources/CopyActive.png b/TheOtherRoles/Resources/CopyActive.png new file mode 100644 index 000000000..f19ecd788 Binary files /dev/null and b/TheOtherRoles/Resources/CopyActive.png differ diff --git a/TheOtherRoles/Resources/CopyPasteBG.png b/TheOtherRoles/Resources/CopyPasteBG.png new file mode 100644 index 000000000..c8f47cce4 Binary files /dev/null and b/TheOtherRoles/Resources/CopyPasteBG.png differ diff --git a/TheOtherRoles/Resources/Minus_Button.png b/TheOtherRoles/Resources/Minus_Button.png new file mode 100644 index 000000000..8453665e5 Binary files /dev/null and b/TheOtherRoles/Resources/Minus_Button.png differ diff --git a/TheOtherRoles/Resources/Minus_ButtonActive.png b/TheOtherRoles/Resources/Minus_ButtonActive.png new file mode 100644 index 000000000..2cd4b5a09 Binary files /dev/null and b/TheOtherRoles/Resources/Minus_ButtonActive.png differ diff --git a/TheOtherRoles/Resources/Paste.png b/TheOtherRoles/Resources/Paste.png new file mode 100644 index 000000000..8bae0fc27 Binary files /dev/null and b/TheOtherRoles/Resources/Paste.png differ diff --git a/TheOtherRoles/Resources/PasteActive.png b/TheOtherRoles/Resources/PasteActive.png new file mode 100644 index 000000000..b80d73bf8 Binary files /dev/null and b/TheOtherRoles/Resources/PasteActive.png differ diff --git a/TheOtherRoles/Resources/Plus_Button.png b/TheOtherRoles/Resources/Plus_Button.png new file mode 100644 index 000000000..35335d537 Binary files /dev/null and b/TheOtherRoles/Resources/Plus_Button.png differ diff --git a/TheOtherRoles/Resources/Plus_ButtonActive.png b/TheOtherRoles/Resources/Plus_ButtonActive.png new file mode 100644 index 000000000..ac30e9ba6 Binary files /dev/null and b/TheOtherRoles/Resources/Plus_ButtonActive.png differ diff --git a/TheOtherRoles/Resources/Settings_Button.png b/TheOtherRoles/Resources/Settings_Button.png new file mode 100644 index 000000000..9119e37e7 Binary files /dev/null and b/TheOtherRoles/Resources/Settings_Button.png differ diff --git a/TheOtherRoles/Resources/Settings_ButtonActive.png b/TheOtherRoles/Resources/Settings_ButtonActive.png new file mode 100644 index 000000000..813c937c1 Binary files /dev/null and b/TheOtherRoles/Resources/Settings_ButtonActive.png differ diff --git a/TheOtherRoles/TasksHandler.cs b/TheOtherRoles/TasksHandler.cs index 96ae2d319..8ce050a5b 100644 --- a/TheOtherRoles/TasksHandler.cs +++ b/TheOtherRoles/TasksHandler.cs @@ -6,7 +6,7 @@ namespace TheOtherRoles { [HarmonyPatch] public static class TasksHandler { - public static Tuple taskInfo(GameData.PlayerInfo playerInfo) { + public static Tuple taskInfo(NetworkedPlayerInfo playerInfo) { int TotalTasks = 0; int CompletedTasks = 0; if (!playerInfo.Disconnected && playerInfo.Tasks != null && diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 9c056c16f..500b87477 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,14 +1,15 @@  net6.0 - 4.5.3 + 4.6.0 TheOtherRoles Eisbison latest true true - x86 + AnyCPU true + AnyCPU @@ -16,9 +17,9 @@ - + - + @@ -32,5 +33,5 @@ - + diff --git a/TheOtherRoles/packages.lock.json b/TheOtherRoles/packages.lock.json index 3bcb0fd0c..e83bd9970 100644 --- a/TheOtherRoles/packages.lock.json +++ b/TheOtherRoles/packages.lock.json @@ -4,9 +4,9 @@ "net6.0": { "AmongUs.GameLibs.Steam": { "type": "Direct", - "requested": "[2024.3.5, )", - "resolved": "2024.3.5", - "contentHash": "5KOcBSFnql0DmrL82GikWb5I+KLvD8h8RsS28BKTCws2fPKwWauUm/L9Zh73pIHcnOMCpvnAxWeZh/AqxAEI0Q==" + "requested": "[2024.6.18, )", + "resolved": "2024.6.18", + "contentHash": "xb+HP1xXn4/ES8AgXpk9xeoW568LFYw5NTjY6bHwd6vQjHDf2kT1xHMmQ1me5Vfee/Gp69YIMZDXUAUToG7Elg==" }, "BepInEx.IL2CPP.MSBuild": { "type": "Direct", @@ -16,19 +16,19 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.688, )", - "resolved": "6.0.0-be.688", - "contentHash": "a68J6PA9AdgYlj8HeuEK1hM4Vv+j1x/6TflK5/PaYAd05/TPdjNI09LsSTIOaS9hdWZwCcpPEw/HxLhXaQKodw==", + "requested": "[6.0.0-be.692, )", + "resolved": "6.0.0-be.692", + "contentHash": "rYjnJCN2APD/04dZUKhRCbu30jhzseIKd0+pfaWWgfDJNggd8rq+whEzM/ZC0fEkkLgcIkEgbtX2LuSqsCrIgg==", "dependencies": { - "BepInEx.Core": "6.0.0-be.688", - "BepInEx.Unity.Common": "6.0.0-be.688", + "BepInEx.Core": "6.0.0-be.692", + "BepInEx.Unity.Common": "6.0.0-be.692", "HarmonyX": "2.10.1", - "Iced": "1.18.0", - "Il2CppInterop.Generator": "1.4.6-ci.389", - "Il2CppInterop.HarmonySupport": "1.4.6-ci.389", - "Il2CppInterop.Runtime": "1.4.6-ci.389", + "Iced": "1.20.0", + "Il2CppInterop.Generator": "1.4.6-ci.426", + "Il2CppInterop.HarmonySupport": "1.4.6-ci.426", + "Il2CppInterop.Runtime": "1.4.6-ci.426", "MonoMod.RuntimeDetour": "22.5.1.1", - "Samboy063.Cpp2IL.Core": "2022.1.0-development.866" + "Samboy063.Cpp2IL.Core": "2022.1.0-development.972" } }, "Reactor": { @@ -42,48 +42,56 @@ }, "AsmResolver": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "7PjujQzgQ3wjzqZYT4CY8SV6zx7FY6swIwj3Yk4QLolLqo9sBPb7FLF3W30QFvCsCkNfiVWXlSbeZKs4xGgQOQ==" + "resolved": "5.5.0", + "contentHash": "IuOC+b/D/da4fohYVNwo/NL+8w+q89O9B32bLotegJ+hmFlBEpQEKgtyhxc9ZfEd+x0KzwzD52RISuyLgf/BAA==" }, "AsmResolver.DotNet": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "oKrBU94OaSrbbTwydvpLRFalYxozrNXGkl13nIkm823ZFQtPNYOiOMJb5DQLvkCJlWyis7q865tg803T5zg9IA==", + "resolved": "5.5.0", + "contentHash": "T19DazP0h4qKXwPspTEB0ZzwlftPuvVAd68HhsS8eNYd9lRd/rtppcBmM2QLQdZeGGNJc+QEzLiAW+wrA3nKAw==", "dependencies": { - "AsmResolver.PE": "5.1.0", - "System.Text.Json": "6.0.7" + "AsmResolver.PE": "5.5.0", + "System.Text.Json": "6.0.8" } }, "AsmResolver.PE": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "XD3iAgLSInJIODKUUlpHWXf8MR9H1SFMb1lsmabb4GxxxnDQRPjMxjglv2NOCjQQuNB2Oh0bvjHE7ewf82UqyQ==", + "resolved": "5.5.0", + "contentHash": "bSPe0A+z4iEAabpD9h7ACQ5dkcTirx4fx05P194u/+OIUqlexHf7Zq/PEPdOkesbqHoZmgVmJ1H0GWqqouvZfA==", "dependencies": { - "AsmResolver.PE.File": "5.1.0" + "AsmResolver.PE.File": "5.5.0" } }, "AsmResolver.PE.File": { "type": "Transitive", - "resolved": "5.1.0", - "contentHash": "YituBYe0Fh471sXQMfu+f4tWKX/JZvRwrX6g/SVsr4XkUIUzYi/aGT3/QvjHoYx19fE1KYOB6zBKqPkkOK7HPw==", + "resolved": "5.5.0", + "contentHash": "XHWHnPQf0e0VEJPTaWMoiajuikF0n0fDXS2XWzEXM+/xcY+LABsp1p7ETlg+bFsDVITQRtNTa/xV8eSDlSZjNQ==", "dependencies": { - "AsmResolver": "5.1.0" + "AsmResolver": "5.5.0" } }, - "AssetRipper.Primitives": { + "AssetRipper.CIL": { "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "nrgwUMa69ztOfMKbmytNI3mU/fuN3eWptq2Mu8aLg2ly394w51KJbUx5z477HbRvabD8TD8rM4wRe6EBqB2xdA==" + "resolved": "1.0.0", + "contentHash": "l639dKLllpJ5TcX+Z1OVYz+hsKVZyMpEm59Dl4Qd6YrCHPVj9yPtF/UNjn9nFxoDm7suEFP/0vlZD/bSeXjz6Q==", + "dependencies": { + "AsmResolver.DotNet": "5.5.0" + } }, - "AssetRipper.VersionUtilities": { + "AssetRipper.Gee.External.Capstone": { "type": "Transitive", - "resolved": "1.2.1", - "contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA==" + "resolved": "2.3.1", + "contentHash": "WVujToXc2sB5nVEY4iMpjhsQaqGw5RjG3c0Hl1qT/pZMbfwtafpaOwAa0G/GS5gd2jcuJwrsG880Pkyjkhi3vQ==" + }, + "AssetRipper.Primitives": { + "type": "Transitive", + "resolved": "3.1.1", + "contentHash": "GhFAVMWpG8MyZscQxwYCd1HSS36UhIQeW0Gn9iPYiininZWlo8RTV9tGYv0CNNXw5bODYJtXf4qiqo6sQOVAEg==" }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.688", - "contentHash": "34VErIttx6PckRukoaRXIb6ZF5oby+9Oktt9E3ZafOGzA0lBWOmY/BKHfg766XZBplE06KijHp+vrryCjfLP7Q==", + "resolved": "6.0.0-be.692", + "contentHash": "I/JuhVhOXUFRrSxy7MqMHpygKoYNt39XY5V8e7PTLbq+nfCBGYzOhszcPx90Wj5xGPx6IFuABJocWAbFDHUddA==", "dependencies": { "HarmonyX": "2.10.1", "MonoMod.Utils": "22.5.1.1", @@ -92,10 +100,10 @@ }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.688", - "contentHash": "RRPG9sEgIdGgut0LOSQopW+6mMpE0LDggKZWfLBBeaJj1p0WFrVBCqEAruFLO0FrwT/+dEC7EtV62n13RV1JfA==", + "resolved": "6.0.0-be.692", + "contentHash": "QYsp8Sf4kQwmx4qwFLhS7SW+Dp67iBibb0zo5IdMQXGmS0KY2WH7/SZ+fFmG6ce06BT+E58wsxk0rU6NW0qWbg==", "dependencies": { - "AssetRipper.VersionUtilities": "1.2.1", + "AssetRipper.Primitives": "3.1.1", "MonoMod.Utils": "22.5.1.1" } }, @@ -115,13 +123,13 @@ }, "Iced": { "type": "Transitive", - "resolved": "1.18.0", - "contentHash": "G60lZOvbvqttA+SBSv/yY6/wUboXKJlkffhSNR9iOrx0M5gpcK1TRr6xrFR+qAhqIAhvrsPF1jkn9fYb4lEufQ==" + "resolved": "1.20.0", + "contentHash": "cjk+vNDIatLI5vQ22tOCAzsgowZ32Ob1Fy4ljQSfqfzMe5ATKXU+dMPRE6+cIUUFetoyyWkUJArJoxe3QwDXAA==" }, "Il2CppInterop.Common": { "type": "Transitive", - "resolved": "1.4.6-ci.389", - "contentHash": "KTyf2f66Q2mS9a6xhvoPWwD0VzRIoskPMVQehaVMo1dx4Di1FPFsKqukQ+ob6wgP5Rbnx53kiH0PY+IRSb35XA==", + "resolved": "1.4.6-ci.426", + "contentHash": "pI0kU0qqJKMP6z9eFz4+WJtGIwklfPxW2yWEY9vKnrN9bbYMusK3v5uFWV8al7S/HPSATV5jNWH1hyTvP7kglA==", "dependencies": { "Iced": "1.17.0", "Microsoft.Extensions.Logging.Abstractions": "6.0.1", @@ -130,36 +138,31 @@ }, "Il2CppInterop.Generator": { "type": "Transitive", - "resolved": "1.4.6-ci.389", - "contentHash": "XJX4sn/RzAEBNIZZXuyDcLZrFx5tCoahujDu5aKWjApiMj/nTRQAxZn17daIIvd9aHqLaAfiWWth5QDLIt2bKw==", + "resolved": "1.4.6-ci.426", + "contentHash": "kecdx/vbNl0RtfzfYW592jU8PMyq1JbzpvoJSvqwO+tV6icp9SljXy6yG8bT/wt0gaPj9mFUNDTe2Wu6M6XGZQ==", "dependencies": { - "Il2CppInterop.Common": "1.4.6-ci.389", + "Il2CppInterop.Common": "1.4.6-ci.426", "Mono.Cecil": "0.11.3" } }, "Il2CppInterop.HarmonySupport": { "type": "Transitive", - "resolved": "1.4.6-ci.389", - "contentHash": "Xd2zK6sLqwA0ReyUy83SWKcALwY99fq6vVL5gFOMN5Ct8OOVhtNIws0ysCWsfx1GL0RJiRYfR4pza/MmWRz4PQ==", + "resolved": "1.4.6-ci.426", + "contentHash": "rd2T5o6SybIc12hmX3HktTF5n27hFb0w4mNSExq7h1YsmrNlt7x+Ac1MBnnB0JwPLIg7w8LjnKjoIX6Gf626ng==", "dependencies": { "HarmonyX": "2.10.0", - "Il2CppInterop.Runtime": "1.4.6-ci.389" + "Il2CppInterop.Runtime": "1.4.6-ci.426" } }, "Il2CppInterop.Runtime": { "type": "Transitive", - "resolved": "1.4.6-ci.389", - "contentHash": "nzYjuVzDG/O8+AQ8ax3WVHf+ZVsQKrVtp/yvuW8XoEPLdkbgryIrMo75dvN+tPqxOU3o2MPt9MZ9j25P5aVJMw==", + "resolved": "1.4.6-ci.426", + "contentHash": "0O0oI7gOqJixrsjvh1firhuGYK3Yr0uDLp6Q+t5CfcTMmeEX8Plk3pqAP9ZYyilBvh7uW0gv4Golqz08L1GXug==", "dependencies": { "Iced": "1.17.0", - "Il2CppInterop.Common": "1.4.6-ci.389" + "Il2CppInterop.Common": "1.4.6-ci.426" } }, - "js6pak.Gee.External.Capstone": { - "type": "Transitive", - "resolved": "2.1.0", - "contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA==" - }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", "resolved": "6.0.1", @@ -309,15 +312,16 @@ }, "Samboy063.Cpp2IL.Core": { "type": "Transitive", - "resolved": "2022.1.0-development.866", - "contentHash": "QPMuix/3jRngWBdNSLhAbm9BHYf95Ln1Ph1eCK/cDZdVibxFDFP3a6Yczyx1p7GbN7bRQwrhs2skPJSS/z3m2w==", + "resolved": "2022.1.0-pre-release.13", + "contentHash": "d3/E3e2rCDlnRiFdNyLxE94XKabsCdMEzVblzsraodYxQhjCXacn75KHkp3Jwj+6Y8A3usehMInDWep4L/+TQQ==", "dependencies": { - "AsmResolver.DotNet": "5.1.0", + "AsmResolver.DotNet": "5.5.0", + "AssetRipper.CIL": "1.0.0", + "AssetRipper.Gee.External.Capstone": "2.3.1", "Disarm": "2022.1.0-master.26", - "Iced": "1.18.0", - "Samboy063.LibCpp2IL": "2022.1.0-development.866", - "StableNameDotNet": "0.1.0-development.866", - "js6pak.Gee.External.Capstone": "2.1.0" + "Iced": "1.20.0", + "Samboy063.LibCpp2IL": "2022.1.0-pre-release.13", + "StableNameDotNet": "0.1.0-pre-release.13" } }, "Samboy063.LibCpp2IL": { @@ -882,8 +886,8 @@ }, "System.Text.Json": { "type": "Transitive", - "resolved": "6.0.7", - "contentHash": "/Tf/9XjprpHolbcDOrxsKVYy/mUG/FS7aGd9YUgBVEiHeQH4kAE0T1sMbde7q6B5xcrNUsJ5iW7D1RvHudQNqA==", + "resolved": "6.0.8", + "contentHash": "WhW6zPEgRZoo+c1NEvSSmrME4+LqXmW6tcsRFsEiSMeco+qZ9rpLs7tT53EIkE/s9GNTYS4/STQoaGiKDSWifQ==", "dependencies": { "System.Runtime.CompilerServices.Unsafe": "6.0.0", "System.Text.Encodings.Web": "6.0.0"