From 3d26d79fb79867a37f85d6eca45b47c84156a80e Mon Sep 17 00:00:00 2001 From: mxyx0412 Date: Sat, 4 Jan 2025 06:28:44 +0800 Subject: [PATCH] Update v1.2.0.0 --- .editorconfig | 6 +- .github/workflows/build.yml | 4 +- CHANGELOG.md | 12 +- Strings.xlsx | Bin 85431 -> 85916 bytes TheOtherRoles.sln | 3 - TheOtherRoles/Buttons/Buttons.cs | 33 +- TheOtherRoles/CustomCosmetics/CustomColors.cs | 44 +- .../CustomHats/CustomHatManager.cs | 9 +- .../CustomCosmetics/CustomHats/HatsLoader.cs | 12 +- .../CustomHats/Patches/HatParentPatche.cs | 236 --- .../CustomHats/Patches/HatParentPatches.cs | 18 +- .../CustomHats/Patches/HatsTabPatches.cs | 13 +- .../CustomGameModes/GameModePatches.cs | 61 + TheOtherRoles/Helper/Helpers.cs | 53 +- TheOtherRoles/Main.cs | 11 +- TheOtherRoles/Modules/ChatCommands.cs | 4 +- TheOtherRoles/Modules/CrowdedPlayer.cs | 18 +- TheOtherRoles/Modules/KeyboardHandler.cs | 20 +- TheOtherRoles/Objects/Footprint.cs | 2 +- .../CreateModOptions.cs} | 113 +- TheOtherRoles/Options/CustomOptionHolder.cs | 4 +- TheOtherRoles/Options/CustomOptions.cs | 1449 ++++++++--------- TheOtherRoles/Options/ModOption.cs | 6 +- TheOtherRoles/Patches/CredentialsPatch.cs | 47 +- TheOtherRoles/Patches/EndGamePatch.cs | 387 ++--- TheOtherRoles/Patches/ExileControllerPatch.cs | 44 +- .../Patches/GameStartManagerPatch.cs | 61 +- TheOtherRoles/Patches/GetStringPatch.cs | 24 + TheOtherRoles/Patches/LobbyBehaviourPatch.cs | 27 + TheOtherRoles/Patches/LobbyRoleList.cs | 18 +- TheOtherRoles/Patches/MeetingHudPatch.cs | 10 +- TheOtherRoles/Patches/PlayerControlPatch.cs | 6 +- TheOtherRoles/Patches/RoleAssignmentPatch.cs | 22 +- TheOtherRoles/Patches/ShipStatusPatch.cs | 2 +- .../Patches/TransportationToolPatches.cs | 6 +- TheOtherRoles/Patches/UsablesPatch.cs | 4 +- TheOtherRoles/RPC.cs | 19 +- TheOtherRoles/Resources/Copy.png | Bin 0 -> 17161 bytes TheOtherRoles/Resources/CopyActive.png | Bin 0 -> 14765 bytes TheOtherRoles/Resources/CopyPasteBG.png | Bin 0 -> 13064 bytes TheOtherRoles/Resources/Minus_Button.png | Bin 0 -> 6295 bytes .../Resources/Minus_ButtonActive.png | Bin 0 -> 6897 bytes TheOtherRoles/Resources/Paste.png | Bin 0 -> 14822 bytes TheOtherRoles/Resources/PasteActive.png | Bin 0 -> 14227 bytes TheOtherRoles/Resources/Plus_Button.png | Bin 0 -> 7047 bytes TheOtherRoles/Resources/Plus_ButtonActive.png | Bin 0 -> 7541 bytes TheOtherRoles/Resources/Settings_Button.png | Bin 0 -> 13493 bytes .../Resources/Settings_ButtonActive.png | Bin 0 -> 13826 bytes TheOtherRoles/Resources/stringData.json | 34 +- TheOtherRoles/Roles/Crewmate/Prosecutor.cs | 6 +- TheOtherRoles/Roles/RoleHelpers.cs | 1 - TheOtherRoles/TasksHandler.cs | 4 +- TheOtherRoles/TheOtherRoles.csproj | 15 +- TheOtherRoles/Utilities/CachedPlayer.cs | 6 +- TheOtherRoles/packages.lock.json | 135 +- 55 files changed, 1441 insertions(+), 1568 deletions(-) delete mode 100644 TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatche.cs create mode 100644 TheOtherRoles/CustomGameModes/GameModePatches.cs rename TheOtherRoles/{Patches/ClientOptionsPatch.cs => Options/CreateModOptions.cs} (74%) create mode 100644 TheOtherRoles/Patches/GetStringPatch.cs create mode 100644 TheOtherRoles/Patches/LobbyBehaviourPatch.cs create mode 100644 TheOtherRoles/Resources/Copy.png create mode 100644 TheOtherRoles/Resources/CopyActive.png create mode 100644 TheOtherRoles/Resources/CopyPasteBG.png create mode 100644 TheOtherRoles/Resources/Minus_Button.png create mode 100644 TheOtherRoles/Resources/Minus_ButtonActive.png create mode 100644 TheOtherRoles/Resources/Paste.png create mode 100644 TheOtherRoles/Resources/PasteActive.png create mode 100644 TheOtherRoles/Resources/Plus_Button.png create mode 100644 TheOtherRoles/Resources/Plus_ButtonActive.png create mode 100644 TheOtherRoles/Resources/Settings_Button.png create mode 100644 TheOtherRoles/Resources/Settings_ButtonActive.png diff --git a/.editorconfig b/.editorconfig index 8d356572..35b791f3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,10 +1,12 @@ [*.cs] +charset = utf-8 dotnet_diagnostic.IDE0007.severity = silent dotnet_diagnostic.IDE0022.severity = silent dotnet_diagnostic.IDE0023.severity = silent dotnet_diagnostic.IDE0028.severity = none dotnet_diagnostic.IDE0031.severity = silent dotnet_diagnostic.IDE0046.severity = silent +dotnet_diagnostic.IDE0058.severity = silent dotnet_diagnostic.IDE0061.severity = silent dotnet_diagnostic.IDE0305.severity = silent dotnet_diagnostic.IDE1006.severity = silent @@ -16,10 +18,6 @@ dotnet_analyzer_diagnostic.severity = suggestion [*.cs] #### 命名样式 #### - -# IDE0058: -dotnet_diagnostic.IDE0058.severity = silent - # 命名规则 dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dac487e3..e8a81c16 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: - name: Download and Unzip BepInEx run: | - wget https://builds.bepinex.dev/projects/bepinex_be/697/BepInEx-Unity.IL2CPP-win-x86-6.0.0-be.697%2B5362580.zip -O BepInEx.zip + wget https://builds.bepinex.dev/projects/bepinex_be/725/BepInEx-Unity.IL2CPP-win-x86-6.0.0-be.725%2Be1974e2.zip -O BepInEx.zip unzip BepInEx.zip -d ./Release/ sudo chmod -R 777 ./Release @@ -47,7 +47,7 @@ jobs: unzip ExtraData.zip -d ./Release/ - name: Download Reactor - run: wget https://github.com/NuclearPowered/Reactor/releases/download/2.2.0/Reactor.dll -P ./Release/BepInEx/plugins + run: wget https://github.com/NuclearPowered/Reactor/releases/download/2.3.1/Reactor.dll -P ./Release/BepInEx/plugins - name: Set Build Configuration id: set-config diff --git a/CHANGELOG.md b/CHANGELOG.md index 82c91968..87478c5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ -v1.1.1.1更新日志 +v1.2.0.0 - Beta更新日志 -* 新增伪装者职业:狼之主 -* 新增附加能力:迷乱旋涡 -* 修复巨人的体型在其他玩家不可见的问题 -* 修复分散者的坐标问题 - -注:本次仅更新Lite分支 \ No newline at end of file +* 适配Among Us最新版本(2024.8.13~2024.11.26) +* 新增模组选项:游戏内显示聊天气泡 +* 新增模组选项:静音大厅BGM +* 新增模组选项:强制使用+25协议(目前启用该选项后,无法进入房间) diff --git a/Strings.xlsx b/Strings.xlsx index 3857c3a07489c4d6ea11b30ad5b6ca0bc87d3668..e5f7161e9e71f469ec14a3df05ca1f68b4c2b4c8 100644 GIT binary patch delta 61472 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 Dq5Huc delta 61087 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

s%VE8CL`o+ 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 H4G#E!`y6AL diff --git a/TheOtherRoles.sln b/TheOtherRoles.sln index 9d1b0064..d9e20ca6 100644 --- a/TheOtherRoles.sln +++ b/TheOtherRoles.sln @@ -18,7 +18,6 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Beta|Any CPU = Beta|Any CPU Debug|Any CPU = Debug|Any CPU - mxyx-club|Any CPU = mxyx-club|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution @@ -26,8 +25,6 @@ Global {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Beta|Any CPU.Build.0 = Beta|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Debug|Any CPU.ActiveCfg = Release|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Debug|Any CPU.Build.0 = Release|Any CPU - {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.mxyx-club|Any CPU.ActiveCfg = mxyx-club|Any CPU - {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.mxyx-club|Any CPU.Build.0 = mxyx-club|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.ActiveCfg = Release|Any CPU {11FBC798-BAF5-4EE5-9511-BE6DB0592F99}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection diff --git a/TheOtherRoles/Buttons/Buttons.cs b/TheOtherRoles/Buttons/Buttons.cs index 1b183796..9db931ce 100644 --- a/TheOtherRoles/Buttons/Buttons.cs +++ b/TheOtherRoles/Buttons/Buttons.cs @@ -97,7 +97,6 @@ internal static class HudManagerStartPatch public static CustomButton terroristButton; public static CustomButton defuseButton; public static CustomButton zoomOutButton; - public static CustomButton roleSummaryButton; public static Dictionary> deputyHandcuffedButtons; public static PoolablePlayer targetDisplay; @@ -390,39 +389,11 @@ public static void createButtonsPostfix(HudManager __instance) // get map id, or raise error to wait... var mapId = GameOptionsManager.Instance.currentNormalGameOptions.MapId; - roleSummaryButton = new CustomButton( - () => - { - if (LobbyRoleInfo.RolesSummaryUI == null) - LobbyRoleInfo.RoleSummaryOnClick(); - else - { - Object.Destroy(LobbyRoleInfo.RolesSummaryUI); - LobbyRoleInfo.RolesSummaryUI = null; - } - }, - () => { return PlayerControl.LocalPlayer != null && LobbyBehaviour.Instance; }, - () => - { - if (PlayerCustomizationMenu.Instance || GameSettingMenu.Instance) - { - if (LobbyRoleInfo.RolesSummaryUI != null) - Object.Destroy(LobbyRoleInfo.RolesSummaryUI); - } - return true; - }, - () => { }, - new ResourceSprite("TheOtherRoles.Resources.HelpButton.png", 85f), - new Vector3(0.4f, 3f, 0), - __instance, - null - ); - zoomOutButton = new CustomButton( () => { toggleZoom(); }, () => { - if (!CanSeeRoleInfo) return false; + if (!CanSeeRoleInfo || InMeeting) return false; if (PlayerControl.LocalPlayer.IsAlive()) return false; var (playerCompleted, playerTotal) = TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data); var numberOfLeftTasks = playerTotal - playerCompleted; @@ -430,7 +401,7 @@ public static void createButtonsPostfix(HudManager __instance) }, () => { return true; }, () => { }, - UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.ZoomOut.png", 85f), // Invisible button! + null, new Vector3(0.4f, 2.35f, 0f), __instance, KeyCode.KeypadPlus diff --git a/TheOtherRoles/CustomCosmetics/CustomColors.cs b/TheOtherRoles/CustomCosmetics/CustomColors.cs index a2049075..499ca5dd 100644 --- a/TheOtherRoles/CustomCosmetics/CustomColors.cs +++ b/TheOtherRoles/CustomCosmetics/CustomColors.cs @@ -104,7 +104,7 @@ public static void Load() var colorlist = Palette.PlayerColors.ToList(); var shadowlist = Palette.ShadowColors.ToList(); - var id = 50000; + var id = 60000; foreach (var entry in CustomColorData.OrderBy(entry => (int)entry.Key)) { var colorType = entry.Key; @@ -133,20 +133,56 @@ private class ColorStringPatch [HarmonyPriority(Priority.Last)] public static bool Prefix(ref string __result, [HarmonyArgument(0)] StringNames name) { - if ((int)name >= 50000) + if ((int)name >= 60000) { - var text = ColorStrings[(int)name]; - if (text != null) + if (ColorStrings.TryGetValue((int)name, out var text)) { __result = $"color{text}".Translate(); return false; } + else + { + Error($"Key '{(int)name}' not found in ColorStrings."); + } } return true; } } + [HarmonyPatch(typeof(ChatNotification), nameof(ChatNotification.SetUp))] + private class ChatNotificationColorsPatch + { + public static bool Prefix(ChatNotification __instance, PlayerControl sender, string text) + { + if (ShipStatus.Instance && !ModOption.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; + //Message($"{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 { diff --git a/TheOtherRoles/CustomCosmetics/CustomHats/CustomHatManager.cs b/TheOtherRoles/CustomCosmetics/CustomHats/CustomHatManager.cs index dbcd0e3a..4d2bb066 100644 --- a/TheOtherRoles/CustomCosmetics/CustomHats/CustomHatManager.cs +++ b/TheOtherRoles/CustomCosmetics/CustomHats/CustomHatManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; @@ -78,15 +78,12 @@ internal static HatData CreateHatBehaviour(CustomHatConfig ch, bool testOnly = f hat.name = ch.Name; hat.displayOrder = 99; - hat.ProductId = "hat_" + ch.Name.Replace(' ', '_'); + hat.ProductId = "Mod_" + ch.Name.Replace(' ', '_'); hat.InFront = !ch.Behind; hat.NoBounce = !ch.Bounce; hat.ChipOffset = new Vector2(0f, 0.2f); hat.Free = true; -#if MXYX_CLUB - if (ch.Adaptive && cachedShader != null) - viewData.AltShader = cachedShader; -#endif + var extend = new HatExtension { Author = ch.Author ?? "Unknown", diff --git a/TheOtherRoles/CustomCosmetics/CustomHats/HatsLoader.cs b/TheOtherRoles/CustomCosmetics/CustomHats/HatsLoader.cs index 154d1892..bdc8dc3a 100644 --- a/TheOtherRoles/CustomCosmetics/CustomHats/HatsLoader.cs +++ b/TheOtherRoles/CustomCosmetics/CustomHats/HatsLoader.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections; +using System.Collections.Generic; using System.IO; using System.Text.Json; using BepInEx.Unity.IL2CPP.Utils; @@ -124,9 +125,14 @@ private void ProcessHatsData(HatsConfigFile response) Message($"准备下载 {toDownload.Count} 项帽子文件"); + this.StartCoroutine(CoDownloadHats(toDownload)); + } + + private static IEnumerator CoDownloadHats(List toDownload) + { foreach (var fileName in toDownload) { - this.StartCoroutine(CoDownloadHatAsset(fileName)); + yield return CoDownloadHatAsset(fileName); } } @@ -146,7 +152,7 @@ private static IEnumerator CoDownloadHatAsset(string fileName) if (www.isNetworkError || www.isHttpError) { - Error(www.error); + Error($"{www.error} {fileName}"); yield break; } diff --git a/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatche.cs b/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatche.cs deleted file mode 100644 index 1de05f3f..00000000 --- a/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatche.cs +++ /dev/null @@ -1,236 +0,0 @@ -#if MXYX_CLUB -using System; -using System.IO; -using System.Linq; -using PowerTools; -using UnityEngine; - -namespace TheOtherRoles.CustomCosmetics.CustomHats.Patches; - -[HarmonyPatch(typeof(HatParent))] -internal static class HatParentPatches -{ - [HarmonyPatch(nameof(HatParent.SetHat), typeof(int))] - [HarmonyPriority(Priority.High)] - [HarmonyPrefix] - private static void SetHatPrefix(HatParent __instance) - { - SetCustomHat(__instance); - } - - [HarmonyPatch(nameof(HatParent.SetHat), typeof(HatData), typeof(int))] - [HarmonyPrefix] - private static bool SetHatPrefix(HatParent __instance, HatData hat, int color) - { - if (SetCustomHat(__instance)) return true; - __instance.PopulateFromHatViewData(); - __instance.SetMaterialColor(color); - return false; - } - - [HarmonyPatch(nameof(HatParent.SetHat), typeof(int))] - [HarmonyPrefix] - private static bool SetHatPrefix(HatParent __instance, int color) - { - if (!__instance.IsCached()) return true; - __instance.hatDataAsset = null; - __instance.PopulateFromHatViewData(); - __instance.SetMaterialColor(color); - return false; - } - - [HarmonyPatch(nameof(HatParent.UpdateMaterial))] - [HarmonyPrefix] - private static bool UpdateMaterialPrefix(HatParent __instance) - { - if (!__instance.TryGetCached(out var asset)) return true; - if (asset && asset.AltShader) - { - __instance.FrontLayer.sharedMaterial = asset.AltShader; - if (__instance.BackLayer) __instance.BackLayer.sharedMaterial = asset.AltShader; - } - else - { - __instance.FrontLayer.sharedMaterial = DestroyableSingleton.Instance.DefaultShader; - if (__instance.BackLayer) - __instance.BackLayer.sharedMaterial = DestroyableSingleton.Instance.DefaultShader; - } - - var colorId = __instance.matProperties.ColorId; - PlayerMaterial.SetColors(colorId, __instance.FrontLayer); - if (__instance.BackLayer) PlayerMaterial.SetColors(colorId, __instance.BackLayer); - - __instance.FrontLayer.material.SetInt(PlayerMaterial.MaskLayer, __instance.matProperties.MaskLayer); - if (__instance.BackLayer) - __instance.BackLayer.material.SetInt(PlayerMaterial.MaskLayer, __instance.matProperties.MaskLayer); - - var maskType = __instance.matProperties.MaskType; - switch (maskType) - { - case PlayerMaterial.MaskType.ScrollingUI: - if (__instance.FrontLayer) - __instance.FrontLayer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; - - if (__instance.BackLayer) - __instance.BackLayer.maskInteraction = SpriteMaskInteraction.VisibleInsideMask; - - break; - case PlayerMaterial.MaskType.Exile: - if (__instance.FrontLayer) - __instance.FrontLayer.maskInteraction = SpriteMaskInteraction.VisibleOutsideMask; - - if (__instance.BackLayer) - __instance.BackLayer.maskInteraction = SpriteMaskInteraction.VisibleOutsideMask; - - break; - default: - if (__instance.FrontLayer) __instance.FrontLayer.maskInteraction = SpriteMaskInteraction.None; - - if (__instance.BackLayer) __instance.BackLayer.maskInteraction = SpriteMaskInteraction.None; - - break; - } - if (__instance.matProperties.MaskLayer > 0) return false; - PlayerMaterial.SetMaskLayerBasedOnLocalPlayer(__instance.FrontLayer, __instance.matProperties.IsLocalPlayer); - if (!__instance.BackLayer) return false; - PlayerMaterial.SetMaskLayerBasedOnLocalPlayer(__instance.BackLayer, __instance.matProperties.IsLocalPlayer); - return false; - } - - [HarmonyPatch(nameof(HatParent.LateUpdate))] - [HarmonyPrefix] - private static bool LateUpdatePrefix(HatParent __instance) - { - if (!__instance.Parent || !__instance.Hat) return false; - if (!__instance.TryGetCached(out var hatViewData)) return true; - if (__instance.FrontLayer.sprite != hatViewData.ClimbImage && - __instance.FrontLayer.sprite != hatViewData.FloorImage) - { - if ((__instance.Hat.InFront || hatViewData.BackImage) && hatViewData.LeftMainImage) - __instance.FrontLayer.sprite = - __instance.Parent.flipX ? hatViewData.LeftMainImage : hatViewData.MainImage; - - if (hatViewData.BackImage && hatViewData.LeftBackImage) - { - __instance.BackLayer.sprite = - __instance.Parent.flipX ? hatViewData.LeftBackImage : hatViewData.BackImage; - return false; - } - - if (!hatViewData.BackImage && !__instance.Hat.InFront && hatViewData.LeftMainImage) - { - __instance.BackLayer.sprite = - __instance.Parent.flipX ? hatViewData.LeftMainImage : hatViewData.MainImage; - return false; - } - } - else if (__instance.FrontLayer.sprite == hatViewData.ClimbImage || - __instance.FrontLayer.sprite == hatViewData.LeftClimbImage) - { - var spriteAnimNodeSync = __instance.SpriteSyncNode != null - ? __instance.SpriteSyncNode - : __instance.GetComponent(); - if (spriteAnimNodeSync) spriteAnimNodeSync.NodeId = 0; - } - - return false; - } - - [HarmonyPatch(nameof(HatParent.SetFloorAnim))] - [HarmonyPrefix] - private static bool SetFloorAnimPrefix(HatParent __instance) - { - if (!__instance.TryGetCached(out var hatViewData)) return true; - __instance.BackLayer.enabled = false; - __instance.FrontLayer.enabled = true; - __instance.FrontLayer.sprite = hatViewData.FloorImage; - return false; - } - - [HarmonyPatch(nameof(HatParent.SetIdleAnim))] - [HarmonyPrefix] - private static bool SetIdleAnimPrefix(HatParent __instance, int colorId) - { - if (!__instance.Hat) return false; - if (!__instance.IsCached()) return true; - __instance.hatDataAsset = null; - __instance.PopulateFromHatViewData(); - __instance.SetMaterialColor(colorId); - return false; - } - - [HarmonyPatch(nameof(HatParent.SetClimbAnim))] - [HarmonyPrefix] - private static bool SetClimbAnimPrefix(HatParent __instance) - { - if (!__instance.TryGetCached(out var hatViewData)) return true; - if (!__instance.options.ShowForClimb) return false; - __instance.BackLayer.enabled = false; - __instance.FrontLayer.enabled = true; - __instance.FrontLayer.sprite = hatViewData.ClimbImage; - return false; - } - - [HarmonyPatch(nameof(HatParent.PopulateFromHatViewData))] - [HarmonyPrefix] - private static bool PopulateFromHatViewDataPrefix(HatParent __instance) - { - if (!__instance.TryGetCached(out var asset)) return true; - __instance.UpdateMaterial(); - - var spriteAnimNodeSync = __instance.SpriteSyncNode - ? __instance.SpriteSyncNode - : __instance.GetComponent(); - if (spriteAnimNodeSync) spriteAnimNodeSync.NodeId = __instance.Hat.NoBounce ? 1 : 0; - - if (__instance.Hat.InFront) - { - __instance.BackLayer.enabled = false; - __instance.FrontLayer.enabled = true; - __instance.FrontLayer.sprite = asset.MainImage; - } - else if (asset.BackImage) - { - __instance.BackLayer.enabled = true; - __instance.FrontLayer.enabled = true; - __instance.BackLayer.sprite = asset.BackImage; - __instance.FrontLayer.sprite = asset.MainImage; - } - else - { - __instance.BackLayer.enabled = true; - __instance.FrontLayer.enabled = false; - __instance.FrontLayer.sprite = null; - __instance.BackLayer.sprite = asset.MainImage; - } - - if (!__instance.options.Initialized || !__instance.HideHat()) return false; - __instance.FrontLayer.enabled = false; - __instance.BackLayer.enabled = false; - return false; - } - - private static bool SetCustomHat(HatParent hatParent) - { - var dirPath = Path.Combine(CosmeticsManager.CustomHatsDir, "Test"); - if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath); - if (!DestroyableSingleton.InstanceExists) return true; - var d = new DirectoryInfo(dirPath); - var filePaths = d.GetFiles("*.png").Select(x => x.FullName).ToArray(); - var hats = CustomHatManager.CreateHatDetailsFromFileNames(filePaths, true); - if (hats.Count <= 0) return false; - try - { - hatParent.Hat = CustomHatManager.CreateHatBehaviour(hats[0], true); - } - catch (Exception err) - { - Warn($"Unable to create test hat \n{err}"); - return true; - } - - return false; - } -} - -#endif \ No newline at end of file diff --git a/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatches.cs b/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatches.cs index c39c7d8a..79e4206f 100644 --- a/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatches.cs +++ b/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatParentPatches.cs @@ -1,4 +1,4 @@ -#if !MXYX_CLUB +#if !MXYX_CLUB using System; using System.IO; using System.Linq; @@ -162,7 +162,7 @@ private static bool SetFloorAnimPrefix(HatParent __instance) [HarmonyPrefix] private static bool SetIdleAnimPrefix(HatParent __instance, int colorId) { - if (!__instance.Hat) return false; + if (__instance.Hat == null || !__instance.Hat.ProductId.StartsWith("MOD_")) return true; if (!__instance.IsCached()) return true; __instance.viewAsset = null; __instance.PopulateFromViewData(); @@ -174,11 +174,13 @@ private static bool SetIdleAnimPrefix(HatParent __instance, int colorId) [HarmonyPrefix] private static bool SetClimbAnimPrefix(HatParent __instance) { - if (!__instance.TryGetCached(out var hatViewData)) return true; - if (!__instance.options.ShowForClimb) return false; - __instance.BackLayer.enabled = false; - __instance.FrontLayer.enabled = true; - __instance.FrontLayer.sprite = hatViewData.ClimbImage; + if (__instance.Hat == null || !__instance.Hat.ProductId.StartsWith("MOD_")) return true; + if (__instance.TryGetCached(out var hatViewData) && __instance.options.ShowForClimb) + { + __instance.BackLayer.enabled = false; + __instance.FrontLayer.enabled = true; + __instance.FrontLayer.sprite = hatViewData.ClimbImage; + } return false; } @@ -216,7 +218,7 @@ private static bool PopulateFromHatViewDataPrefix(HatParent __instance) __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/CustomCosmetics/CustomHats/Patches/HatsTabPatches.cs b/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatsTabPatches.cs index 74e8328d..22a46c0f 100644 --- a/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatsTabPatches.cs +++ b/TheOtherRoles/CustomCosmetics/CustomHats/Patches/HatsTabPatches.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using AmongUs.Data; @@ -8,14 +8,14 @@ namespace TheOtherRoles.CustomCosmetics.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++) { @@ -60,6 +60,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, @@ -99,7 +100,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/CustomGameModes/GameModePatches.cs b/TheOtherRoles/CustomGameModes/GameModePatches.cs new file mode 100644 index 00000000..de8d063d --- /dev/null +++ b/TheOtherRoles/CustomGameModes/GameModePatches.cs @@ -0,0 +1,61 @@ +using System; +using Hazel; +using TheOtherRoles.Utilities; +using TMPro; +using UnityEngine; +using UnityEngine.Events; +using static UnityEngine.UI.Button; + +namespace TheOtherRoles.CustomGameModes; + +[HarmonyPatch] +internal 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))] + private class LobbyInfoPanePatch + { + private static GameObject gameModeButton; + 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 = UnityEngine.Object.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 = 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)(() => + { + ModOption.gameMode = (CustomGamemodes)((int)(ModOption.gameMode + 1) % Enum.GetNames(typeof(CustomGamemodes)).Length); + __instance.StartCoroutine(Effects.Lerp(0.1f, new Action(p => { pButton.buttonText.text = cs(Color.yellow, GameModeText.GetComponent().text); }))); + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + (byte)CustomRPC.ShareGameMode, SendOption.Reliable, -1); + writer.Write((byte)ModOption.gameMode); + AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.shareGameMode((byte)ModOption.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/Helper/Helpers.cs b/TheOtherRoles/Helper/Helpers.cs index 95acdf3f..e93ae7df 100644 --- a/TheOtherRoles/Helper/Helpers.cs +++ b/TheOtherRoles/Helper/Helpers.cs @@ -123,7 +123,7 @@ public static bool killingCrewAlive() ///

/// 红狼视野 /// - public static bool hasImpVision(GameData.PlayerInfo player) + public static bool hasImpVision(NetworkedPlayerInfo player) { return player.Role.IsImpostor || (Jackal.jackal.Any(p => p.PlayerId == player.PlayerId) && Jackal.hasImpostorVision) @@ -297,7 +297,7 @@ public static string teamString(PlayerControl player) !MeetingHud.Instance && !ExileController.Instance; - public static void NoCheckStartMeeting(this PlayerControl reporter, GameData.PlayerInfo target, bool force = false) + public static void NoCheckStartMeeting(this PlayerControl reporter, NetworkedPlayerInfo target, bool force = false) { if (InMeeting) return; @@ -598,6 +598,39 @@ public static bool Contains(this IEnumerable list, T item, Func keySelector(x).Equals(keySelector(item))); } + public static int Count(this Il2CppSystem.Collections.Generic.List list, Func func = null) + { + int count = 0; + foreach (T obj in list) + if (func == null || func(obj)) + count++; + return count; + } + + public static Color HexToColor(string hex) + { + ColorUtility.TryParseHtmlString("#" + hex, out var color); + return color; + } + + public static ExileController.InitProperties GenerateExileInitProperties(NetworkedPlayerInfo player, bool voteTie) + { + ExileController.InitProperties initProperties = new(); + if (player != null) + { + initProperties.outfit = player.Outfits[PlayerOutfitType.Default]; + initProperties.networkedPlayer = player; + initProperties.isImpostor = player.Role.IsImpostor; + } + initProperties.voteTie = voteTie; + initProperties.confirmImpostor = GameManager.Instance.LogicOptions.GetConfirmImpostor(); + initProperties.totalImpostorCount = GameData.Instance.AllPlayers.Count((NetworkedPlayerInfo p) => p.Role.IsImpostor); + initProperties.remainingImpostorCount = GameData.Instance.AllPlayers.Count((NetworkedPlayerInfo p) => p.Role.IsImpostor && !p.IsDead && !p.Disconnected); + if (player != null && player.Role.IsImpostor && !player.Disconnected) + initProperties.remainingImpostorCount--; + return initProperties; + } + public static string readTextFromResources(string path) { var assembly = Assembly.GetExecutingAssembly(); @@ -1056,10 +1089,10 @@ public static Il2CppSystem.Collections.Generic.List GetClosestPla { Il2CppSystem.Collections.Generic.List playerControlList = new Il2CppSystem.Collections.Generic.List(); float lightRadius = radius * ShipStatus.Instance.MaxLightRadius; - Il2CppSystem.Collections.Generic.List allPlayers = GameData.Instance.AllPlayers; + Il2CppSystem.Collections.Generic.List allPlayers = GameData.Instance.AllPlayers; for (int index = 0; index < allPlayers.Count; ++index) { - GameData.PlayerInfo playerInfo = allPlayers[index]; + NetworkedPlayerInfo playerInfo = allPlayers[index]; if (!playerInfo.Disconnected && (!playerInfo.Object.Data.IsDead || includeDead)) { Vector2 vector2 = new Vector2(playerInfo.Object.GetTruePosition().x - truePosition.x, playerInfo.Object.GetTruePosition().y - truePosition.y); @@ -1343,12 +1376,14 @@ public static void toggleZoom(bool reset = false) cam.orthographicSize = orthographicSize; // The UI is scaled too, else we cant click the buttons. Downside: map is super small. - if (HudManagerStartPatch.zoomOutButton != null) + var tzGO = GameObject.Find("TOGGLEZOOMBUTTON"); + if (tzGO != null) { - HudManagerStartPatch.zoomOutButton.Sprite = zoomOutStatus - ? new ResourceSprite("TheOtherRoles.Resources.ZoomIn.png", 21f) - : new ResourceSprite("TheOtherRoles.Resources.ZoomOut.png", 85f); - HudManagerStartPatch.zoomOutButton.PositionOffset = zoomOutStatus ? new Vector3(-0.82f, 11.5f, 0) : new(0.4f, 2.35f, 0f); + var rend = tzGO.transform.Find("Inactive").GetComponent(); + var rendActive = tzGO.transform.Find("Active").GetComponent(); + rend.sprite = zoomOutStatus ? UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Plus_Button.png", 100f) : UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Minus_Button.png", 100f); + rendActive.sprite = zoomOutStatus ? UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Plus_ButtonActive.png", 100f) : UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Minus_ButtonActive.png", 100f); + tzGO.transform.localScale = new Vector3(1.2f, 1.2f, 1f) * (zoomOutStatus ? 4 : 1); } // This will move button positions to the correct position. diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index cb311612..fa27dd5e 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using AmongUs.Data; using BepInEx; using BepInEx.Configuration; @@ -35,6 +35,9 @@ public class TheOtherRolesPlugin : BasePlugin public static ConfigEntry ToggleCursor { get; set; } public static ConfigEntry ShowFPS { get; set; } public static ConfigEntry LocalHats { get; set; } + public static ConfigEntry MuteLobbyBGM { get; set; } + public static ConfigEntry ShowChatNotifications { get; set; } + public static ConfigEntry ForceUsePlus25Protocol { get; set; } public static ConfigEntry ShowKeyReminder { get; set; } public static ConfigEntry Ip { get; set; } public static ConfigEntry Port { get; set; } @@ -84,12 +87,17 @@ public override void Load() ShowFPS = Config.Bind("Custom", "Show FPS", true); ShowKeyReminder = Config.Bind("Custom", "ShowKeyReminder", true); LocalHats = Config.Bind("Custom", "Load Local Hats", false); + MuteLobbyBGM = Config.Bind("Custom", "Mute Lobby BGM", true); + ShowChatNotifications = Config.Bind("Custom", "Show Chat Notifications", true); + ForceUsePlus25Protocol = Config.Bind("Custom", "Force Use Plus 25 Protocol", false); Ip = Config.Bind("Custom", "Custom Server IP", "127.0.0.1"); Port = Config.Bind("Custom", "Custom Server Port", (ushort)22023); defaultRegions = ServerManager.DefaultRegions; UpdateRegions(); + // Removes vanilla Servers + ServerManager.DefaultRegions = new Il2CppReferenceArray(new IRegionInfo[0]); CrowdedPlayer.Start(); Harmony.PatchAll(); ModOption.reloadPluginOptions(); @@ -101,7 +109,6 @@ public override void Load() SubmergedCompatibility.Initialize(); MainMenuPatch.addSceneChangeCallbacks(); - AddToKillDistanceSetting.addKillDistance(); Info($"\n---------------\n Loading TheOtherUs completed!\n TheOtherUs-Edited v{VersionString}-Lite\n---------------"); } } diff --git a/TheOtherRoles/Modules/ChatCommands.cs b/TheOtherRoles/Modules/ChatCommands.cs index f86b7851..88285494 100644 --- a/TheOtherRoles/Modules/ChatCommands.cs +++ b/TheOtherRoles/Modules/ChatCommands.cs @@ -260,8 +260,8 @@ public static void Postfix(ChatBubble __instance, [HarmonyArgument(0)] string pl var sourcePlayer = PlayerControl.AllPlayerControls.ToList() .FirstOrDefault(x => x.Data != null && x.Data.PlayerName.Equals(playerName, StringComparison.Ordinal)); - if (CachedPlayer.LocalPlayer != null && CachedPlayer.LocalPlayer.Data.Role.IsImpostor && __instance != null - && (Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId)) + if (sourcePlayer != null && CachedPlayer.LocalPlayer != null && CachedPlayer.LocalPlayer.Data?.Role?.IsImpostor == true + && Spy.spy != null && sourcePlayer.PlayerId == Spy.spy.PlayerId) { __instance.NameText.color = Palette.ImpostorRed; } diff --git a/TheOtherRoles/Modules/CrowdedPlayer.cs b/TheOtherRoles/Modules/CrowdedPlayer.cs index cf400040..188c3956 100644 --- a/TheOtherRoles/Modules/CrowdedPlayer.cs +++ b/TheOtherRoles/Modules/CrowdedPlayer.cs @@ -6,7 +6,6 @@ using Reactor.Utilities.Extensions; using TMPro; using UnityEngine; -using Object = UnityEngine.Object; namespace TheOtherRoles.Modules; @@ -22,8 +21,8 @@ public static class CrowdedPlayer public static void Start() { if (!Enable) return; - NormalGameOptionsV07.RecommendedImpostors = NormalGameOptionsV07.MaxImpostors = Enumerable.Repeat(MaxPlayer, MaxPlayer).ToArray(); - NormalGameOptionsV07.MinPlayers = Enumerable.Repeat(4, MaxPlayer).ToArray(); + NormalGameOptionsV08.RecommendedImpostors = NormalGameOptionsV08.MaxImpostors = Enumerable.Repeat(MaxPlayer, MaxPlayer).ToArray(); + NormalGameOptionsV08.MinPlayers = Enumerable.Repeat(4, MaxPlayer).ToArray(); } [HarmonyPatch(typeof(SecurityLogger), nameof(SecurityLogger.Awake))] @@ -34,13 +33,18 @@ public static void SecurityLoggerPatch_Postfix(ref SecurityLogger __instance) __instance.Timers = new float[MaxPlayer]; } - [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))] + [HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Initialize))] [HarmonyPostfix] - public static void GameOptionsMenu_Start_Postfix(ref GameOptionsMenu __instance) + public static void GameOptionsMenu_Initialize_Postfix(GameOptionsMenu __instance) { if (!Enable) return; - var options = Object.FindObjectsOfType().FirstOrDefault(o => o.Title == StringNames.GameNumImpostors); - if (options != null) options.ValidRange = new FloatRange(0, MaxImpostor); + var numberOptions = __instance.GetComponentsInChildren(); + + var impostorsOption = numberOptions.FirstOrDefault(o => o.Title == StringNames.GameNumImpostors); + if (impostorsOption != null) + { + impostorsOption.ValidRange = new FloatRange(0, MaxImpostor); + } } [HarmonyPatch(typeof(GameOptionsData), nameof(GameOptionsData.AreInvalid))] diff --git a/TheOtherRoles/Modules/KeyboardHandler.cs b/TheOtherRoles/Modules/KeyboardHandler.cs index f3657f3e..5e4e97d9 100644 --- a/TheOtherRoles/Modules/KeyboardHandler.cs +++ b/TheOtherRoles/Modules/KeyboardHandler.cs @@ -1,19 +1,15 @@ -using System; using System.Collections.Generic; using System.Linq; using TheOtherRoles.Buttons; using TheOtherRoles.Patches; using TheOtherRoles.Utilities; using UnityEngine; -using Random = System.Random; namespace TheOtherRoles.Modules; [HarmonyPatch(typeof(KeyboardJoystick), nameof(KeyboardJoystick.Update))] public class KeyboardHandler { - //private static readonly string passwordHash = "d1f51dfdfd8d38027fd2ca9dfeb299399b5bdee58e6c0b3b5e9a45cd4e502848"; - private static readonly Random random = new((int)DateTime.Now.Ticks); private static readonly List bots = new(); private static void Postfix(KeyboardJoystick __instance) @@ -21,7 +17,7 @@ private static void Postfix(KeyboardJoystick __instance) if (AmongUsClient.Instance && (AmongUsClient.Instance.AmHost || ModOption.DebugMode)) { // 生成假人 - if (Input.GetKey(KeyCode.LeftControl) && Input.GetKey(KeyCode.F) && Input.GetKeyDown(KeyCode.Return) + /*if (Input.GetKey(KeyCode.LeftControl) && Input.GetKey(KeyCode.F) && Input.GetKeyDown(KeyCode.Return) && AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame && InGame) { var playerControl = UnityEngine.Object.Instantiate(AmongUsClient.Instance.PlayerPrefab); @@ -37,7 +33,7 @@ private static void Postfix(KeyboardJoystick __instance) playerControl.SetName(RandomString(6)); playerControl.SetColor((byte)random.Next(Palette.PlayerColors.Length)); GameData.Instance.RpcSetTasks(playerControl.PlayerId, Array.Empty()); - } + }*/ // 强制开始会议或结束会议 if (Input.GetKey(ModInputManager.metaControlInput.keyCode) && Input.GetKeyDown(ModInputManager.meetingInput.keyCode) && InGame) { @@ -59,11 +55,21 @@ private static void Postfix(KeyboardJoystick __instance) GameStartManager.Instance.countDownTimer = 0; } } + + if (Input.GetKeyDown(ModInputManager.helpInput.keyCode)) + { + if (LobbyRoleInfo.RolesSummaryUI == null) LobbyRoleInfo.RoleSummaryOnClick(); + else + { + Object.Destroy(LobbyRoleInfo.RolesSummaryUI); + LobbyRoleInfo.RolesSummaryUI = null; + } + } } public static string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); + return new string(Enumerable.Repeat(chars, length).Select(s => s[rnd.Next(s.Length)]).ToArray()); } } diff --git a/TheOtherRoles/Objects/Footprint.cs b/TheOtherRoles/Objects/Footprint.cs index 49efdca5..cd71a880 100644 --- a/TheOtherRoles/Objects/Footprint.cs +++ b/TheOtherRoles/Objects/Footprint.cs @@ -35,7 +35,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/Patches/ClientOptionsPatch.cs b/TheOtherRoles/Options/CreateModOptions.cs similarity index 74% rename from TheOtherRoles/Patches/ClientOptionsPatch.cs rename to TheOtherRoles/Options/CreateModOptions.cs index 96763efa..e7e92277 100644 --- a/TheOtherRoles/Patches/ClientOptionsPatch.cs +++ b/TheOtherRoles/Options/CreateModOptions.cs @@ -9,7 +9,7 @@ using static UnityEngine.UI.Button; using Object = UnityEngine.Object; -namespace TheOtherRoles.Patches; +namespace TheOtherRoles.Options; [HarmonyPatch(typeof(OptionsMenuBehaviour), nameof(OptionsMenuBehaviour.Start))] public static class StartOptionMenuPatch @@ -19,50 +19,42 @@ public static void UpdateCustomText(this ToggleButtonBehaviour button, Color col button.onState = false; button.Background.color = color; if (text != null) - { button.Text.text = text; - } if (button.Rollover) - { button.Rollover.ChangeOutColor(color); - } } public static void UpdateToggleText(this ToggleButtonBehaviour button, bool on, string text) { button.onState = on; - Color color = on ? new Color(0f, 1f, 0.16470589f, 1f) : Color.white; + var color = on ? new Color(0f, 1f, 0.16470589f, 1f) : Color.white; button.Background.color = color; button.Text.text = text + ": " + DestroyableSingleton.Instance.GetString(button.onState ? StringNames.SettingsOn : StringNames.SettingsOff, new Il2CppReferenceArray(0)); if (button.Rollover) - { button.Rollover.ChangeOutColor(color); - } } public static void UpdateButtonText(this ToggleButtonBehaviour button, string text, string state) { button.onState = false; - Color color = Color.white; + var color = Color.white; button.Background.color = color; button.Text.text = text + ": " + state; if (button.Rollover) - { button.Rollover.ChangeOutColor(color); - } } - private static ToggleButtonBehaviour AddButton(Vector2 pos, string name, Action onClicked, GameObject nebulaTab, GameObject toggleButtonTemplate) + private static ToggleButtonBehaviour AddButton(int index, string name, Action onClicked, GameObject nebulaTab, GameObject toggleButtonTemplate) { - GameObject button = Object.Instantiate(toggleButtonTemplate, null); + var button = Object.Instantiate(toggleButtonTemplate, null); button.transform.SetParent(nebulaTab.transform); button.transform.localScale = new Vector3(1f, 1f, 1f); - button.transform.localPosition = new Vector3(1.3f * ((pos.x * 2f) - 1f), 1.6f - (0.5f * pos.y), 0f); + button.transform.localPosition = new Vector3(1.3f * (index % 2 * 2 - 1), 1.6f - 0.5f * (index / 2), 0f); button.name = name; - ToggleButtonBehaviour result = button.GetComponent(); - PassiveButton passiveButton = button.GetComponent(); + var result = button.GetComponent(); + var passiveButton = button.GetComponent(); passiveButton.OnClick = new ButtonClickedEvent(); passiveButton.OnClick.AddListener((UnityAction)onClicked); return result; @@ -73,6 +65,9 @@ private static ToggleButtonBehaviour AddButton(Vector2 pos, string name, Action private static ToggleButtonBehaviour showKeyReminder; private static ToggleButtonBehaviour showFPS; private static ToggleButtonBehaviour localHats; + private static ToggleButtonBehaviour showChatNotifications; + private static ToggleButtonBehaviour muteLobbyBGM; + private static ToggleButtonBehaviour forceUsePlus25Protocol; public static void Postfix(OptionsMenuBehaviour __instance) { @@ -80,7 +75,7 @@ public static void Postfix(OptionsMenuBehaviour __instance) PassiveButton passiveButton; - //OĿ׷Ӥ + //設定項目を追加する GameObject nebulaTab = new("NebulaTab"); nebulaTab.transform.SetParent(__instance.transform); @@ -92,18 +87,20 @@ public static void Postfix(OptionsMenuBehaviour __instance) keyBindingTab.transform.localScale = new Vector3(1f, 1f, 1f); keyBindingTab.SetActive(false); - GameObject applyButtonTemplate = tabs[1].Content.transform.GetChild(0).FindChild("ApplyButton").gameObject; - GameObject toggleButtonTemplate = tabs[0].Content.transform.FindChild("MiscGroup").FindChild("StreamerModeButton").gameObject; + var applyButtonTemplate = tabs[1].Content.transform.GetChild(0).FindChild("ApplyButton").gameObject; + var toggleButtonTemplate = tabs[0].Content.transform.FindChild("MiscGroup").FindChild("StreamerModeButton").gameObject; + + var buttonIndex = 0; //EnableSoundEffects - enableSoundEffects = AddButton(new Vector2(0, 0), "EnableSoundEffects", () => + enableSoundEffects = AddButton(buttonIndex++, "EnableSoundEffects", () => { enableSoundEffects.UpdateToggleText(!enableSoundEffects.onState, GetString("EnableSoundEffectsText")); ModOption.enableSoundEffects = Main.EnableSoundEffects.Value = enableSoundEffects.onState; }, nebulaTab, toggleButtonTemplate); //ToggleCursor - toggleCursor = AddButton(new Vector2(0, 1), "ToggleCursor", () => + toggleCursor = AddButton(buttonIndex++, "ToggleCursor", () => { enableCursor(false); toggleCursor.UpdateToggleText(!toggleCursor.onState, GetString("ToggleCursorText")); @@ -112,33 +109,54 @@ public static void Postfix(OptionsMenuBehaviour __instance) }, nebulaTab, toggleButtonTemplate); //ShowFPS - showKeyReminder = AddButton(new Vector2(1, 0), "ShowKeyReminder", () => + showFPS = AddButton(buttonIndex++, "ShowFPS", () => + { + showFPS.UpdateToggleText(!showFPS.onState, GetString("ShowFPS")); + ModOption.showFPS = Main.ShowFPS.Value = showFPS.onState; + }, nebulaTab, toggleButtonTemplate); + + //ShowKeyReminder + showKeyReminder = AddButton(buttonIndex++, "ShowKeyReminder", () => { showKeyReminder.UpdateToggleText(!showKeyReminder.onState, GetString("ShowKeyReminder")); ModOption.showKeyReminder = Main.ShowKeyReminder.Value = showKeyReminder.onState; }, nebulaTab, toggleButtonTemplate); - //ShowFPS - showFPS = AddButton(new Vector2(1, 1), "ShowFPS", () => + //Mute Lobby BGM + muteLobbyBGM = AddButton(buttonIndex++, "MuteLobbyBGM", () => { - showFPS.UpdateToggleText(!showFPS.onState, GetString("ShowFPS")); - ModOption.showFPS = Main.ShowFPS.Value = showFPS.onState; + muteLobbyBGM.UpdateToggleText(!muteLobbyBGM.onState, GetString("MuteLobbyBGM")); + ModOption.MuteLobbyBGM = Main.MuteLobbyBGM.Value = muteLobbyBGM.onState; + }, nebulaTab, toggleButtonTemplate); + + //Show Chat Notifications + showChatNotifications = AddButton(buttonIndex++, "ShowChatNotificationsText", () => + { + showChatNotifications.UpdateToggleText(!showChatNotifications.onState, GetString("ShowChatNotificationsText")); + ModOption.ShowChatNotifications = Main.ShowChatNotifications.Value = showChatNotifications.onState; }, nebulaTab, toggleButtonTemplate); //LocalHats - localHats = AddButton(new Vector2(0, 2), "LocalHats", () => + localHats = AddButton(buttonIndex++, "LocalHats", () => { localHats.UpdateToggleText(!localHats.onState, GetString("LocalHatsText")); ModOption.localHats = Main.LocalHats.Value = localHats.onState; }, nebulaTab, toggleButtonTemplate); - //`굱ƥܥ + //Force Use Plus 25 Protocol + forceUsePlus25Protocol = AddButton(buttonIndex++, "ForceUsePlus25Protocol", () => + { + forceUsePlus25Protocol.UpdateToggleText(!forceUsePlus25Protocol.onState, GetString("ForceUsePlus25Protocol")); + Main.ForceUsePlus25Protocol.Value = forceUsePlus25Protocol.onState; + }, nebulaTab, toggleButtonTemplate); + + //キー割り当てボタン GameObject TextObject; List allKeyBindingButtons = new(); - int selectedKeyBinding = -1; + var selectedKeyBinding = -1; - GameObject defaultButton = Object.Instantiate(applyButtonTemplate, null); + var defaultButton = Object.Instantiate(applyButtonTemplate, null); defaultButton.transform.SetParent(keyBindingTab.transform); defaultButton.transform.localScale = new Vector3(1f, 1f, 1f); defaultButton.transform.localPosition = new Vector3(0f, -2.5f, 0f); @@ -155,9 +173,9 @@ public static void Postfix(OptionsMenuBehaviour __instance) selectedKeyBinding = -1; //_ = SoundManager.Instance.PlaySound(Module.MetaScreen.getSelectClip(), false, 0.8f); - for (int i = 0; i < ModInputManager.allInputs.Count; i++) + for (var i = 0; i < ModInputManager.allInputs.Count; i++) { - ModInputManager.ModInput input = ModInputManager.allInputs[i]; + var input = ModInputManager.allInputs[i]; input.resetToDefault(); allKeyBindingButtons[i].UpdateCustomText(Color.white, GetString("keyBinding." + input.identifier) + ": " + ModInputManager.allKeyCodes[input.keyCode].displayKey); } @@ -166,14 +184,14 @@ public static void Postfix(OptionsMenuBehaviour __instance) foreach (var input in ModInputManager.allInputs) { - int index = allKeyBindingButtons.Count; + var index = allKeyBindingButtons.Count; - GameObject inputButton = Object.Instantiate(toggleButtonTemplate, null); + var inputButton = Object.Instantiate(toggleButtonTemplate, null); inputButton.transform.SetParent(keyBindingTab.transform); inputButton.transform.localScale = new Vector3(1f, 1f, 1f); - inputButton.transform.localPosition = new Vector3(1.3f * ((index % 2 * 2) - 1), 1.5f - (0.5f * (index / 2)), 0f); + inputButton.transform.localPosition = new Vector3(1.3f * (index % 2 * 2 - 1), 1.5f - 0.5f * (index / 2), 0f); inputButton.name = input.identifier; - ToggleButtonBehaviour inputToggleButton = inputButton.GetComponent(); + var inputToggleButton = inputButton.GetComponent(); inputToggleButton.BaseText = 0; inputToggleButton.Text.text = GetString("keyBinding." + input.identifier) + ": " + ModInputManager.allKeyCodes[input.keyCode].displayKey; passiveButton = inputButton.GetComponent(); @@ -197,7 +215,7 @@ public static void Postfix(OptionsMenuBehaviour __instance) allKeyBindingButtons.Add(inputToggleButton); } - GameObject keyBindingButton = Object.Instantiate(applyButtonTemplate, null); + var keyBindingButton = Object.Instantiate(applyButtonTemplate, null); keyBindingButton.transform.SetParent(nebulaTab.transform); keyBindingButton.transform.localScale = new Vector3(1f, 1f, 1f); keyBindingButton.transform.localPosition = new Vector3(0f, -1.5f, 0f); @@ -228,14 +246,12 @@ IEnumerator getEnumerator() if (keyBindingTab.gameObject.active && Input.anyKeyDown && selectedKeyBinding != -1) { - foreach (KeyValuePair entry in ModInputManager.allKeyCodes) + foreach (var entry in ModInputManager.allKeyCodes) { if (!Input.GetKeyDown(entry.Key)) - { continue; - } - ModInputManager.ModInput input = ModInputManager.allInputs[selectedKeyBinding]; + var input = ModInputManager.allInputs[selectedKeyBinding]; input.changeKeyCode(entry.Key); allKeyBindingButtons[selectedKeyBinding].UpdateCustomText(Color.white, GetString("keyBinding." + input.identifier) + ": " + ModInputManager.allKeyCodes[input.keyCode].displayKey); selectedKeyBinding = -1; @@ -256,20 +272,20 @@ IEnumerator getEnumerator() : __instance.StartCoroutine(getEnumerator().WrapToIl2Cpp()); - //֤׷Ӥ + //タブを追加する tabs[^1] = Object.Instantiate(tabs[1], null); - TabGroup nebulaButton = tabs[^1]; + var nebulaButton = tabs[^1]; nebulaButton.gameObject.name = "NebulaButton"; nebulaButton.transform.SetParent(tabs[0].transform.parent); nebulaButton.transform.localScale = new Vector3(1f, 1f, 1f); nebulaButton.Content = nebulaTab; - GameObject textObj = nebulaButton.transform.FindChild("Text_TMP").gameObject; + var textObj = nebulaButton.transform.FindChild("Text_TMP").gameObject; textObj.GetComponent().enabled = false; textObj.GetComponent().text = "modOptionsTitle".Translate(); tabs.Add(Object.Instantiate(tabs[1], null)); - TabGroup keyBindingTabButton = tabs[^1]; + var keyBindingTabButton = tabs[^1]; keyBindingTabButton.gameObject.name = "KeyBindingButton"; keyBindingTabButton.transform.SetParent(tabs[0].transform.parent); keyBindingTabButton.transform.localScale = new Vector3(1f, 1f, 1f); @@ -286,7 +302,10 @@ IEnumerator getEnumerator() enableSoundEffects.UpdateToggleText(Main.EnableSoundEffects.Value, GetString("EnableSoundEffectsText")); showKeyReminder.UpdateToggleText(Main.ShowKeyReminder.Value, GetString("ShowKeyReminder")); toggleCursor.UpdateToggleText(Main.ToggleCursor.Value, GetString("ToggleCursorText")); + showChatNotifications.UpdateToggleText(Main.ShowChatNotifications.Value, GetString("ShowChatNotificationsText")); + muteLobbyBGM.UpdateToggleText(Main.MuteLobbyBGM.Value, GetString("MuteLobbyBGM")); localHats.UpdateToggleText(Main.LocalHats.Value, GetString("LocalHatsText")); + forceUsePlus25Protocol.UpdateToggleText(Main.ForceUsePlus25Protocol.Value, GetString("ForceUsePlus25Protocol")); passiveButton.OnMouseOver.Invoke(); } @@ -295,14 +314,14 @@ IEnumerator getEnumerator() float y = tabs[0].transform.localPosition.y, z = tabs[0].transform.localPosition.z; if (tabs.Count == 4) { - for (int i = 0; i < 3; i++) + for (var i = 0; i < 3; i++) { tabs[i].transform.localPosition = new Vector3(1.7f * (i - 1), y, z); } } else if (tabs.Count == 5) { - for (int i = 0; i < 4; i++) + for (var i = 0; i < 4; i++) { tabs[i].transform.localPosition = new Vector3(1.62f * (i - 1.5f), y, z); } diff --git a/TheOtherRoles/Options/CustomOptionHolder.cs b/TheOtherRoles/Options/CustomOptionHolder.cs index 053c383d..2a8d6937 100644 --- a/TheOtherRoles/Options/CustomOptionHolder.cs +++ b/TheOtherRoles/Options/CustomOptionHolder.cs @@ -828,7 +828,7 @@ public static void Load() eraserCanEraseAnyone = Create(10162, Types.Impostor, "eraserCanEraseAnyone", false, eraserSpawnRate); erasercanEraseGuess = Create(10163, Types.Impostor, "erasercanEraseGuess", false, eraserSpawnRate); - poucherSpawnRate = Create(10320, Types.Impostor, cs(Palette.ImpostorRed, "Poucher"), rates, null, true, () => + poucherSpawnRate = Create(10320, Types.Impostor, cs(Palette.ImpostorRed, "Poucher"), rates, null, true, false, () => { if (modifierPoucher.selection > 0) poucherSpawnRate.selection = 0; }); @@ -1272,7 +1272,7 @@ public static void Load() modifierDisperser = Create(40100, Types.Modifier, cs(Palette.ImpostorRed, "Disperser"), rates, null, true); modifierDisperserDispersesToVent = Create(40101, Types.Modifier, "modifierDisperserDispersesToVent", true, modifierDisperser); - modifierPoucher = Create(40370, Types.Modifier, cs(Palette.ImpostorRed, "Poucher"), rates, null, true, () => + modifierPoucher = Create(40370, Types.Modifier, cs(Palette.ImpostorRed, "Poucher"), rates, null, true, false, () => { poucherSpawnRate.selection = 0; }); diff --git a/TheOtherRoles/Options/CustomOptions.cs b/TheOtherRoles/Options/CustomOptions.cs index 64af1343..de94df4a 100644 --- a/TheOtherRoles/Options/CustomOptions.cs +++ b/TheOtherRoles/Options/CustomOptions.cs @@ -7,16 +7,11 @@ using BepInEx.Configuration; using BepInEx.Unity.IL2CPP; using Hazel; -using Il2CppSystem.Linq; using Reactor.Utilities.Extensions; -using TheOtherRoles.Buttons; -using TheOtherRoles.Patches; using TheOtherRoles.Utilities; using TMPro; using UnityEngine; -using UnityEngine.UI; using static TheOtherRoles.Options.CustomOption; -using Object = UnityEngine.Object; namespace TheOtherRoles.Options; @@ -35,27 +30,28 @@ public enum CustomOptionType public static List options = new(); public static int preset; public static ConfigEntry vanillaSettings; - - public int defaultSelection; - public ConfigEntry entry; + private const string FontStyle = "{0}"; public int id; - public bool isHeader; public string name; - public Action onChange; + public object[] selections; + + public int defaultSelection; + public ConfigEntry entry; + public int selection; public OptionBehaviour optionBehaviour; public CustomOption parent; - public int selection; - public object[] selections; + public bool isHeader; public CustomOptionType type; + public Action onChange; + public string heading = ""; + public bool isHidden; // Option creation - public CustomOption(int id, CustomOptionType type, string name, object[] selections, object defaultValue, - CustomOption parent, bool isHeader, Action onChange = null) + public CustomOption(int id, CustomOptionType type, string name, object[] selections, object defaultValue, CustomOption parent, bool isHeader, bool isHidden = false, Action onChange = null, string heading = "") { this.id = id; - //this.name = parent == null ? name : " - " + name; this.name = name; this.selections = selections; var index = Array.IndexOf(selections, defaultValue); @@ -64,34 +60,32 @@ public CustomOption(int id, CustomOptionType type, string name, object[] selecti this.isHeader = isHeader; this.type = type; this.onChange = onChange; + this.heading = heading; + this.isHidden = isHidden; selection = 0; if (id != 0) { entry = Main.Instance.Config.Bind($"Preset{preset}", id.ToString(), defaultSelection); selection = Mathf.Clamp(entry.Value, 0, selections.Length - 1); } - options.Add(this); } - public static CustomOption Create(int id, CustomOptionType type, string name, string[] selections, - CustomOption parent = null, bool isHeader = false, Action onChange = null) + public static CustomOption Create(int id, CustomOptionType type, string name, string[] selections, CustomOption parent = null, bool isHeader = false, bool isHidden = false, Action onChange = null, string heading = "") { - return new CustomOption(id, type, name, selections, "", parent, isHeader, onChange); + return new CustomOption(id, type, name, selections, "", parent, isHeader, isHidden, 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, bool isHidden = false, Action onChange = null, string heading = "") { List selections = new(); for (var 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, isHidden, onChange, heading); } - public static CustomOption Create(int id, CustomOptionType type, string name, bool defaultValue, - CustomOption parent = null, bool isHeader = false, Action onChange = null) + public static CustomOption Create(int id, CustomOptionType type, string name, bool defaultValue, CustomOption parent = null, bool isHeader = false, bool isHidden = false, Action onChange = null, string heading = "") { - return new CustomOption(id, type, name, ["optionOff", "optionOn"], defaultValue ? "optionOn" : "optionOff", parent, isHeader, onChange); + return new CustomOption(id, type, name, ["optionOff", "optionOn"], defaultValue ? "optionOn" : "optionOff", parent, isHeader, isHidden, onChange, heading); } // Static behaviour @@ -102,13 +96,11 @@ public static void switchPreset(int newPreset) preset = newPreset; vanillaSettings = Main.Instance.Config.Bind($"Preset{preset}", "GameOptions", ""); loadVanillaOptions(); - foreach (var option in options) + foreach (var option in options.Where(x => !x.IsHidden() && x.IsEnbaled())) { if (option.id == 0) continue; - option.entry = - Main.Instance.Config.Bind($"Preset{preset}", option.id.ToString(), - option.defaultSelection); + option.entry = Main.Instance.Config.Bind($"Preset{preset}", option.id.ToString(), option.defaultSelection); option.selection = Mathf.Clamp(option.entry.Value, 0, option.selections.Length - 1); if (option.optionBehaviour != null && option.optionBehaviour is StringOption stringOption) { @@ -120,32 +112,31 @@ public static void switchPreset(int newPreset) public static void saveVanillaOptions() { - vanillaSettings.Value = - Convert.ToBase64String( -#if MXYX_CLUB - GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameManager.Instance.LogicOptions.currentGameOptions)); -#else - GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameManager.Instance.LogicOptions.currentGameOptions, false)); -#endif + vanillaSettings.Value = Convert.ToBase64String(GameOptionsManager.Instance.gameOptionsFactory.ToBytes(GameManager.Instance.LogicOptions.currentGameOptions, false)); } - public static void loadVanillaOptions() + public static bool loadVanillaOptions() { var optionsString = vanillaSettings.Value; - if (optionsString == "") return; - GameOptionsManager.Instance.GameHostOptions = - GameOptionsManager.Instance.gameOptionsFactory.FromBytes(Convert.FromBase64String(optionsString)); + if (optionsString == "") return false; + var gameOptions = GameOptionsManager.Instance.gameOptionsFactory.FromBytes(Convert.FromBase64String(optionsString)); + if (gameOptions.Version < 8) + { + Message("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) { var option = options.FirstOrDefault(x => x.id == optionId); if (option == null) return; - var writer = AmongUsClient.Instance!.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, - (byte)CustomRPC.ShareOptions, SendOption.Reliable); + var writer = AmongUsClient.Instance!.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareOptions, SendOption.Reliable, -1); writer.Write((byte)1); writer.WritePacked((uint)option.id); writer.WritePacked(Convert.ToUInt32(option.selection)); @@ -154,14 +145,12 @@ public static void ShareOptionChange(uint optionId) public static void ShareOptionSelections() { - if (CachedPlayer.AllPlayers.Count <= 1 || - (!AmongUsClient.Instance!.AmHost && CachedPlayer.LocalPlayer.PlayerControl == null)) return; + if (CachedPlayer.AllPlayers.Count <= 1 || AmongUsClient.Instance!.AmHost == false && CachedPlayer.LocalPlayer.PlayerControl == null) return; var optionsList = new List(options); while (optionsList.Any()) { var amount = (byte)Math.Min(optionsList.Count, 200); // takes less than 3 bytes per option on average - var writer = AmongUsClient.Instance!.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, - (byte)CustomRPC.ShareOptions, SendOption.Reliable); + var writer = AmongUsClient.Instance!.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareOptions, SendOption.Reliable, -1); writer.Write(amount); for (var i = 0; i < amount; i++) { @@ -170,7 +159,6 @@ public static void ShareOptionSelections() writer.WritePacked((uint)option.id); writer.WritePacked(Convert.ToUInt32(option.selection)); } - AmongUsClient.Instance.FinishRpcImmediately(writer); } } @@ -204,7 +192,7 @@ public int GetQuantity() public string getString() { - var sel = selections[selection].ToString(); + string sel = selections[selection].ToString(); if (sel is "optionOn") return "" + sel.Translate() + ""; @@ -221,40 +209,76 @@ public virtual string getName() return name.Translate(); } + public virtual string getHeading() + { + if (heading == "") return ""; + return heading.Translate(); + } + // Option changes - public void updateSelection(int newSelection) + public void updateSelection(int newSelection, bool notifyUsers = true) { - selection = Mathf.Clamp((newSelection + selections.Length) % selections.Length, 0, selections.Length - 1); - try + newSelection = Mathf.Clamp((newSelection + selections.Length) % selections.Length, 0, selections.Length - 1); + + bool doNeedNotifier = AmongUsClient.Instance?.AmClient == true && notifyUsers && selection != newSelection; + if (doNeedNotifier) + { + DestroyableSingleton.Instance.Notifier.AddSettingsChangeMessage((StringNames)(id + 6000), getString(), 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; + if (doNeedNotifier) { - if (onChange != null) onChange(); + DestroyableSingleton.Instance.Notifier + .AddModSettingsChangeMessage((StringNames)(id + 6000), getString(), getName().Replace("- ", ""), false); } - catch + + try { - // ignored + onChange?.Invoke(); } + catch { } - if (optionBehaviour != null && optionBehaviour is StringOption stringOption) + if (optionBehaviour is not null and StringOption stringOption) { stringOption.oldValue = stringOption.Value = selection; stringOption.ValueText.text = getString(); - if (AmongUsClient.Instance?.AmHost != true || !CachedPlayer.LocalPlayer.PlayerControl) return; - if (id == 0 && selection != preset) - { - switchPreset(selection); // Switch presets - ShareOptionSelections(); - } - else if (entry != null) + if (AmongUsClient.Instance?.AmHost == true && CachedPlayer.LocalPlayer.PlayerControl) { - entry.Value = selection; // Save selection to config - ShareOptionChange((uint)id); // Share single selection + if (id == 0 && selection != preset) + { + switchPreset(selection); // Switch presets + ShareOptionSelections(); + } + else if (entry != null) + { + entry.Value = selection; // Save selection to config + ShareOptionChange((uint)id);// Share single selection + } } } else if (id == 0 && AmongUsClient.Instance?.AmHost == true && PlayerControl.LocalPlayer) - { - // Share the preset switch for random maps, even if the menu isnt open! + { // Share the preset switch for random maps, even if the menu isnt open! switchPreset(selection); - ShareOptionSelections(); // Share all selections + ShareOptionSelections();// Share all selections + } + // test + if (AmongUsClient.Instance?.AmClient == true) + { + try + { + if (GameStartManager.Instance != null && GameStartManager.Instance.LobbyInfoPane != null && GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane != null) + { + LobbyViewSettingsPaneChangeTabPatch.Postfix(GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane, GameStartManager.Instance.LobbyInfoPane.LobbyViewSettingsPane.currentTab); + } + } + catch { } } } @@ -274,7 +298,6 @@ public static byte[] serializeOptions() binaryWriter.Write((byte)(option.selection + (consecutive ? 128 : 0))); if (!consecutive) binaryWriter.Write((ushort)option.id); } - binaryWriter.Flush(); memoryStream.Position = 0L; return memoryStream.ToArray(); @@ -282,11 +305,14 @@ public static byte[] serializeOptions() } } - public static void deserializeOptions(byte[] inputValues) + public static int deserializeOptions(byte[] inputValues) { var reader = new BinaryReader(new MemoryStream(inputValues)); var lastId = -1; + var somethingApplied = false; + var errors = 0; while (reader.BaseStream.Position < inputValues.Length) + { try { int selection = reader.ReadByte(); @@ -301,489 +327,611 @@ public static void deserializeOptions(byte[] inputValues) { id = reader.ReadUInt16(); } - if (id == 0) continue; lastId = id; - var option = options.First(option => option.id == id); - option.updateSelection(selection); + CustomOption option = options.First(option => option.id == id); + option.entry = Main.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.getString(); + } + somethingApplied = true; } catch (Exception e) { - Warn($"{e}: 试图粘贴无效设置!"); + Warn($"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) public static void copyToClipboard() { - GUIUtility.systemCopyBuffer = - $"{Main.VersionString}!{Convert.ToBase64String(serializeOptions())}!{vanillaSettings.Value}"; + GUIUtility.systemCopyBuffer = $"{Main.VersionString}!{Convert.ToBase64String(serializeOptions())}!{vanillaSettings.Value}"; } - public static bool pasteFromClipboard() + public static int pasteFromClipboard() { var allSettings = GUIUtility.systemCopyBuffer; + var torOptionsFine = 0; + var vanillaOptionsFine = false; try { var settingsSplit = allSettings.Split("!"); - var versionInfo = settingsSplit[0]; + var versionInfo = Version.Parse(settingsSplit[0]); var torSettings = settingsSplit[1]; var vanillaSettingsSub = settingsSplit[2]; - deserializeOptions(Convert.FromBase64String(torSettings)); - - vanillaSettings.Value = vanillaSettingsSub; - loadVanillaOptions(); - return true; + torOptionsFine = deserializeOptions(Convert.FromBase64String(torSettings)); + ShareOptionSelections(); + if (Main.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) { - Warn($"{e}: 尝试粘贴无效设置!"); + Warn($"{e}: tried to paste invalid settings!\n{allSettings}"); + var 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))] -internal class GameOptionsMenuStartPatch +public static class CustomOptionsExtensions { - public static void Postfix(GameOptionsMenu __instance) + public static void AddModSettingsChangeMessage(this NotificationPopper popper, StringNames key, string value, string option, bool playSound = true) + { + string str = DestroyableSingleton.Instance.GetString(StringNames.LobbyChangeSettingNotification, "" + option + "", "" + value + ""); + popper.SettingsChangeMessageLogic(key, str, playSound); + } + + public static bool IsHidden(this CustomOption option) + { + return option.isHidden; + } + + public static bool IsEnbaled(this CustomOption option) { - switch (ModOption.gameMode) + var enabled = true; + var parent = option.parent; + while (parent != null && enabled) { - case CustomGamemodes.Classic: - createClassicTabs(__instance); - break; - case CustomGamemodes.Guesser: - createGuesserTabs(__instance); - break; + enabled = parent.selection != 0; + parent = parent.parent; } - // create copy to clipboard and paste from clipboard buttons. - var template = GameObject.Find("CloseButton"); - var copyButton = Object.Instantiate(template, template.transform.parent); - copyButton.transform.localPosition += Vector3.down * 0.8f; - var copyButtonPassive = copyButton.GetComponent(); - var copyButtonRenderer = copyButton.GetComponent(); - copyButtonRenderer.sprite = new ResourceSprite("TheOtherRoles.Resources.CopyButton.png", 175f); - copyButtonPassive.OnClick.RemoveAllListeners(); - copyButtonPassive.OnClick = new Button.ButtonClickedEvent(); - copyButtonPassive.OnClick.AddListener((Action)(() => + return !option.IsHidden() && enabled; + } +} + + +[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.ChangeTab))] +internal class GameOptionsMenuChangeTabPatch +{ + public static void Postfix(GameSettingMenu __instance, int tabNum, bool previewOnly) + { + if (previewOnly) return; + foreach (var tab in GameOptionsMenuStartPatch.currentTabs) { - copyToClipboard(); - copyButtonRenderer.color = Color.green; - __instance.StartCoroutine(Effects.Lerp(1f, new Action(p => - { - if (p > 0.95) - copyButtonRenderer.color = Color.white; - }))); - })); - var pasteButton = Object.Instantiate(template, template.transform.parent); - pasteButton.transform.localPosition += Vector3.down * 1.6f; - var pasteButtonPassive = pasteButton.GetComponent(); - var pasteButtonRenderer = pasteButton.GetComponent(); - pasteButtonRenderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.PasteButton.png", 175f); - pasteButtonPassive.OnClick.RemoveAllListeners(); - pasteButtonPassive.OnClick = new Button.ButtonClickedEvent(); - pasteButtonPassive.OnClick.AddListener((Action)(() => + if (tab != null) + tab.SetActive(false); + } + foreach (var pbutton in GameOptionsMenuStartPatch.currentButtons) { - pasteButtonRenderer.color = Color.yellow; - var success = pasteFromClipboard(); - pasteButtonRenderer.color = success ? Color.green : Color.red; - __instance.StartCoroutine(Effects.Lerp(1f, new Action(p => - { - if (p > 0.95) - pasteButtonRenderer.color = Color.white; - }))); - })); + pbutton.SelectButton(false); + } + if (tabNum > 2) + { + tabNum -= 3; + GameOptionsMenuStartPatch.currentTabs[tabNum].SetActive(true); + GameOptionsMenuStartPatch.currentButtons[tabNum].SelectButton(true); + } } +} - private static void createClassicTabs(GameOptionsMenu __instance) +[HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.SetTab))] +internal class LobbyViewSettingsPaneRefreshTabPatch +{ + public static bool Prefix(LobbyViewSettingsPane __instance) { - var isReturn = setNames( - new Dictionary - { - ["TORSettings"] = "theOtherRolesSettings".Translate(), - ["ImpostorSettings"] = "impostorRolesSettings".Translate(), - ["NeutralSettings"] = "neutralRolesSettings".Translate(), - ["CrewmateSettings"] = "crewmateRolesSettings".Translate(), - ["ModifierSettings"] = "modifierSettings".Translate() - }); - - if (isReturn) return; - - // Setup TOR tab - var template = Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = Object.FindObjectsOfType().FirstOrDefault(); - - var torSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); + if ((int)__instance.currentTab < 15) + { + LobbyViewSettingsPaneChangeTabPatch.Postfix(__instance, __instance.currentTab); + return false; + } + return true; + } +} - var impostorSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var impostorMenu = getMenu(impostorSettings, "ImpostorSettings"); +[HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.ChangeTab))] +internal class LobbyViewSettingsPaneChangeTabPatch +{ + public static void Postfix(LobbyViewSettingsPane __instance, StringNames category) + { + var tabNum = (int)category; - var neutralSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var neutralMenu = getMenu(neutralSettings, "NeutralSettings"); + foreach (var pbutton in LobbyViewSettingsPatch.currentButtons) + { + pbutton.SelectButton(false); + } + if (tabNum > 20) // StringNames are in the range of 3000+ + return; + __instance.taskTabButton.SelectButton(false); - var crewmateSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var crewmateMenu = getMenu(crewmateSettings, "CrewmateSettings"); + if (tabNum > 2) + { + tabNum -= 3; + //GameOptionsMenuStartPatch.currentTabs[tabNum].SetActive(true); + LobbyViewSettingsPatch.currentButtons[tabNum].SelectButton(true); + LobbyViewSettingsPatch.drawTab(__instance, LobbyViewSettingsPatch.currentButtonTypes[tabNum]); + } + } +} - var modifierSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var modifierMenu = getMenu(modifierSettings, "ModifierSettings"); +[HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.Update))] +internal class LobbyViewSettingsPaneUpdatePatch +{ + public static void Postfix(LobbyViewSettingsPane __instance) + { + if (LobbyViewSettingsPatch.currentButtons.Count == 0) + { + LobbyViewSettingsPatch.gameModeChangedFlag = true; + LobbyViewSettingsPatch.Postfix(__instance); - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); + } + } +} - var torTab = Object.Instantiate(roleTab, roleTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIcon.png"); - var impostorTab = Object.Instantiate(roleTab, torTab.transform); - var impostorTabHighlight = - getTabHighlight(impostorTab, "ImpostorTab", "TheOtherRoles.Resources.TabIconImpostor.png"); +[HarmonyPatch(typeof(LobbyViewSettingsPane), nameof(LobbyViewSettingsPane.Awake))] +internal class LobbyViewSettingsPatch +{ + public static List currentButtons = new(); + public static List currentButtonTypes = new(); + public static bool gameModeChangedFlag; - var neutralTab = Object.Instantiate(roleTab, impostorTab.transform); - var neutralTabHighlight = - getTabHighlight(neutralTab, "NeutralTab", "TheOtherRoles.Resources.TabIconNeutral.png"); + public static void Postfix(LobbyViewSettingsPane __instance) + { + currentButtons.ForEach(x => x?.Destroy()); + currentButtons.Clear(); + currentButtonTypes.Clear(); - var crewmateTab = Object.Instantiate(roleTab, neutralTab.transform); - var crewmateTabHighlight = - getTabHighlight(crewmateTab, "CrewmateTab", "TheOtherRoles.Resources.TabIconCrewmate.png"); + removeVanillaTabs(__instance); + createSettingTabs(__instance); + } - var modifierTab = Object.Instantiate(roleTab, crewmateTab.transform); - var modifierTabHighlight = - getTabHighlight(modifierTab, "ModifierTab", "TheOtherRoles.Resources.TabIconModifier.png"); + public static void removeVanillaTabs(LobbyViewSettingsPane __instance) + { + GameObject.Find("RolesTabs")?.Destroy(); + var overview = GameObject.Find("OverviewTab"); + if (!gameModeChangedFlag) + { + overview.transform.localScale = new Vector3(0.58f * overview.transform.localScale.x, overview.transform.localScale.y, overview.transform.localScale.z); + overview.transform.localPosition += new Vector3(-1.05f, 0f, 0f); - // 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; + } + overview.transform.Find("FontPlacer").transform.localScale = new Vector3(1.2f, 1f, 1f); + overview.transform.Find("FontPlacer").transform.localPosition = new Vector3(-0.1f, -0.1f, 0f); + gameModeChangedFlag = false; + } - var tabs = new[] { 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 (var i = 0; i < tabs.Length; i++) + public static void createSettingTabs(LobbyViewSettingsPane __instance) + { + // Handle different gamemodes and tabs needed therein. + var next = 3; + if (ModOption.gameMode is CustomGamemodes.Guesser or CustomGamemodes.Classic) { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - var copiedIndex = i; - button.OnClick = new Button.ButtonClickedEvent(); - button.OnClick.AddListener((Action)(() => { setListener(settingsHighlightMap, copiedIndex); })); + // create TOR settings + createCustomButton(__instance, next++, "TORSettings", "theOtherRolesSettings".Translate(), CustomOptionType.General); + // IMp + createCustomButton(__instance, next++, "ImpostorSettings", "impostorRolesSettings".Translate(), CustomOptionType.Impostor); + // Neutral + createCustomButton(__instance, next++, "NeutralSettings", "neutralRolesSettings".Translate(), CustomOptionType.Neutral); + // Crew + createCustomButton(__instance, next++, "CrewmateSettings", "crewmateRolesSettings".Translate(), CustomOptionType.Crewmate); + // Modifier + createCustomButton(__instance, next++, "ModifierSettings", "modifierSettings".Translate(), CustomOptionType.Modifier); + } + } - destroyOptions(new List> + 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) { - torMenu.GetComponentsInChildren().ToList(), - impostorMenu.GetComponentsInChildren().ToList(), - neutralMenu.GetComponentsInChildren().ToList(), - crewmateMenu.GetComponentsInChildren().ToList(), - modifierMenu.GetComponentsInChildren().ToList() - }); + torSettingsButton = UnityEngine.Object.Instantiate(buttonTemplate, buttonTemplate.transform.parent); + torSettingsButton.transform.localPosition += Vector3.right * 2.06f * (targetMenu - 2); + torSettingsButton.name = buttonName; + //torSettingsButton.transform.localScale += Vector3.right * 0.09f; + __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((Action)(() => + { + __instance.ChangeTab((StringNames)targetMenu); + })); + torSettingsPassiveButton.OnMouseOut.RemoveAllListeners(); + torSettingsPassiveButton.OnMouseOver.RemoveAllListeners(); + torSettingsPassiveButton.SelectButton(false); + currentButtons.Add(torSettingsPassiveButton); + currentButtonTypes.Add(optionType); + } + } - var torOptions = new List(); - var impostorOptions = new List(); - var neutralOptions = new List(); - var crewmateOptions = new List(); - var modifierOptions = new List(); + public static void drawTab(LobbyViewSettingsPane __instance, CustomOptionType optionType) + { + var relevantOptions = options.Where(x => !x.IsHidden() && x.IsEnbaled() && + (x.type == optionType || (x.type == CustomOptionType.Guesser && optionType == CustomOptionType.General))).ToList(); + // Exclude guesser options in neutral mode + if (ModOption.gameMode == CustomGamemodes.Guesser) + relevantOptions = relevantOptions.Where(x => !new List + { 10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 30100, 30101, 30102, 30103, 30104 }.Contains(x.id)).ToList(); - var menus = new List + for (var j = 0; j < __instance.settingsInfo.Count; j++) { - torMenu.transform, impostorMenu.transform, neutralMenu.transform, crewmateMenu.transform, - modifierMenu.transform - }; - var optionBehaviours = new List> - { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions }; + __instance.settingsInfo[j].gameObject.Destroy(); + } + __instance.settingsInfo.Clear(); - for (var i = 0; i < options.Count; i++) + var num = 1.44f; + var i = 0; + var singles = 0; + var headers = 0; + var lines = 0; + var curType = CustomOptionType.Modifier; + + foreach (var option in relevantOptions.Where(x => !x.IsHidden() && x.IsEnbaled())) { - var option = options[i]; - if ((int)option.type > 4) continue; - if (option.optionBehaviour == null) + if (option.isHeader || curType != option.type) { - var stringOption = Object.Instantiate(template, menus[(int)option.type]); - optionBehaviours[(int)option.type].Add(stringOption); - stringOption.OnValueChanged = new Action(o => { }); - stringOption.TitleText.text = option.getName(); - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.getString(); + curType = option.type; + if (i != 0) num -= 0.59f; + if (i % 2 != 0) singles++; + headers++; // for header + var categoryHeaderMasked = UnityEngine.Object.Instantiate(__instance.categoryHeaderOrigin); + categoryHeaderMasked.SetHeader(StringNames.ImpostorsCategory, 61); + var titleText = option.heading != "" ? option.getHeading() : option.getName(); + categoryHeaderMasked.Title.text = titleText; + var color = titleText.Contains("() { + { CustomOptionType.Impostor, "ImpostorRolesText".Translate() }, + { CustomOptionType.Neutral, "NeutralRolesText".Translate() }, + { CustomOptionType.Crewmate, "CrewmateRolesText".Translate() }, + { CustomOptionType.Modifier, "ModifiersText".Translate() } }[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; + var 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; + } + viewSettingsInfoPanel.transform.localPosition = new Vector3(num2, num, -2f); + var value = option.GetSelection(); + viewSettingsInfoPanel.SetInfo(StringNames.ImpostorsCategory, option.getString(), 61); + viewSettingsInfoPanel.titleText.text = option.getName(); + 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 = "optionSpawnChance".Translate(); + if ((int)optionType == 99) + { + var color = option.getName().Contains(" { torMenu, impostorMenu, neutralMenu, crewmateMenu, modifierMenu }, - new List> { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions }, - new List { torSettings, impostorSettings, neutralSettings, crewmateSettings, modifierSettings } - ); + } +} + +[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.CreateSettings))] +internal class GameOptionsMenuCreateSettingsPatch +{ + public static void Postfix(GameOptionsMenu __instance) + { + if (__instance.gameObject.name == "GAME SETTINGS TAB") + adaptTaskCount(__instance); + } - adaptTaskCount(__instance); + 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); } +} - private static void createGuesserTabs(GameOptionsMenu __instance) + +[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.Start))] +internal class GameOptionsMenuStartPatch +{ + public static List currentTabs = new(); + public static List currentButtons = new(); + public static void Postfix(GameSettingMenu __instance) { - var isReturn = setNames( - new Dictionary - { - ["TORSettings"] = "theOtherRolesSettings".Translate(), - ["GuesserSettings"] = "guesserSettings".Translate(), - ["ImpostorSettings"] = "impostorRolesSettings".Translate(), - ["NeutralSettings"] = "neutralRolesSettings".Translate(), - ["CrewmateSettings"] = "crewmateRolesSettings".Translate(), - ["ModifierSettings"] = "modifierSettings".Translate() - }); - - if (isReturn) return; - - // Setup TOR tab - var template = Object.FindObjectsOfType().FirstOrDefault(); - if (template == null) return; - var gameSettings = GameObject.Find("Game Settings"); - var gameSettingMenu = Object.FindObjectsOfType().FirstOrDefault(); - - var torSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var torMenu = getMenu(torSettings, "TORSettings"); - - var guesserSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var guesserMenu = getMenu(guesserSettings, "GuesserSettings"); - - var impostorSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var impostorMenu = getMenu(impostorSettings, "ImpostorSettings"); - - var neutralSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var neutralMenu = getMenu(neutralSettings, "NeutralSettings"); - - var crewmateSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var crewmateMenu = getMenu(crewmateSettings, "CrewmateSettings"); - - var modifierSettings = Object.Instantiate(gameSettings, gameSettings.transform.parent); - var modifierMenu = getMenu(modifierSettings, "ModifierSettings"); - - var roleTab = GameObject.Find("RoleTab"); - var gameTab = GameObject.Find("GameTab"); - - var torTab = Object.Instantiate(roleTab, gameTab.transform.parent); - var torTabHighlight = getTabHighlight(torTab, "TheOtherRolesTab", "TheOtherRoles.Resources.TabIcon.png"); - - var guesserTab = Object.Instantiate(roleTab, torTab.transform); - var guesserTabHighlight = - getTabHighlight(guesserTab, "GuesserTab", "TheOtherRoles.Resources.TabIconGuesserSettings.png"); - - var impostorTab = Object.Instantiate(roleTab, guesserTab.transform); - var impostorTabHighlight = - getTabHighlight(impostorTab, "ImpostorTab", "TheOtherRoles.Resources.TabIconImpostor.png"); - - var neutralTab = Object.Instantiate(roleTab, impostorTab.transform); - var neutralTabHighlight = - getTabHighlight(neutralTab, "NeutralTab", "TheOtherRoles.Resources.TabIconNeutral.png"); - - var crewmateTab = Object.Instantiate(roleTab, neutralTab.transform); - var crewmateTabHighlight = - getTabHighlight(crewmateTab, "CrewmateTab", "TheOtherRoles.Resources.TabIconCrewmate.png"); - - var modifierTab = 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[] { 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 (var i = 0; i < tabs.Length; i++) - { - var button = tabs[i].GetComponentInChildren(); - if (button == null) continue; - var copiedIndex = i; - button.OnClick = new Button.ButtonClickedEvent(); - button.OnClick.AddListener((Action)(() => { setListener(settingsHighlightMap, copiedIndex); })); - } + currentTabs.ForEach(x => x?.Destroy()); + currentButtons.ForEach(x => x?.Destroy()); + currentTabs = new(); + currentButtons = new(); - destroyOptions(new List> - { - torMenu.GetComponentsInChildren().ToList(), - guesserMenu.GetComponentsInChildren().ToList(), - impostorMenu.GetComponentsInChildren().ToList(), - neutralMenu.GetComponentsInChildren().ToList(), - crewmateMenu.GetComponentsInChildren().ToList(), - modifierMenu.GetComponentsInChildren().ToList() - }); - - var torOptions = new List(); - var guesserOptions = new List(); - var impostorOptions = new List(); - var neutralOptions = new List(); - var crewmateOptions = new List(); - var modifierOptions = new List(); - - - var menus = new List - { - torMenu.transform, impostorMenu.transform, neutralMenu.transform, crewmateMenu.transform, - modifierMenu.transform, guesserMenu.transform - }; - var optionBehaviours = new List> - { torOptions, impostorOptions, neutralOptions, crewmateOptions, modifierOptions, guesserOptions }; - var exludedIds = new List { 10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 30100, 30101, 30102, 30103, 30104 }; - - for (var i = 0; i < options.Count; i++) - { - var option = options[i]; - if (exludedIds.Contains(option.id)) continue; - if ((int)option.type > 5) continue; - if (option.optionBehaviour == null) - { - var stringOption = Object.Instantiate(template, menus[(int)option.type]); - optionBehaviours[(int)option.type].Add(stringOption); - stringOption.OnValueChanged = new Action(o => { }); - stringOption.TitleText.text = option.getName(); - stringOption.Value = stringOption.oldValue = option.selection; - stringOption.ValueText.text = option.getString(); + if (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; - option.optionBehaviour = stringOption; - } + removeVanillaTabs(__instance); - option.optionBehaviour.gameObject.SetActive(true); - } + createSettingTabs(__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 } - ); + var GOMGameObject = GameObject.Find("GAME SETTINGS TAB"); - adaptTaskCount(__instance); + // 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 = UnityHelper.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 = UnityEngine.Object.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 = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Copy.png", 100f); + copyButton.transform.GetChild(1).transform.localPosition = Vector3.zero; + copyButtonActiveRenderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.CopyActive.png", 100f); + copyButtonPassive.OnClick.RemoveAllListeners(); + copyButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); + copyButtonPassive.OnClick.AddListener((Action)(() => + { + copyToClipboard(); + copyButtonRenderer.color = Color.green; + copyButtonActiveRenderer.color = Color.green; + __instance.StartCoroutine(Effects.Lerp(1f, new Action((p) => + { + if (p > 0.95) + { + copyButtonRenderer.color = Color.white; + copyButtonActiveRenderer.color = Color.white; + } + }))); + })); + var pasteButton = UnityEngine.Object.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 = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Paste.png", 100f); + pasteButtonActiveRenderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.PasteActive.png", 100f); + pasteButtonPassive.OnClick.RemoveAllListeners(); + pasteButtonPassive.OnClick = new UnityEngine.UI.Button.ButtonClickedEvent(); + pasteButtonPassive.OnClick.AddListener((Action)(() => + { + pasteButtonRenderer.color = Color.yellow; + var 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 Action((p) => + { + if (p > 0.95) + { + pasteButtonRenderer.color = Color.white; + pasteButtonActiveRenderer.color = Color.white; + } + }))); + })); } - private static void setListener(Dictionary settingsHighlightMap, int index) + private static void createSettingTabs(GameSettingMenu __instance) { - foreach (var entry in settingsHighlightMap) + // Handle different gamemodes and tabs needed therein. + var next = 3; + if (ModOption.gameMode is CustomGamemodes.Guesser or CustomGamemodes.Classic) { - entry.Key.SetActive(false); - entry.Value.enabled = false; + // create TOR settings + createCustomButton(__instance, next++, "TORSettings", "theOtherRolesSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.General, "TORSettings"); + // Guesser if applicable + if (ModOption.gameMode == CustomGamemodes.Guesser) + { + createCustomButton(__instance, next++, "GuesserSettings", "guesserSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.Guesser, "GuesserSettings"); + } + // Imp + createCustomButton(__instance, next++, "ImpostorSettings", "impostorRolesSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.Impostor, "ImpostorSettings"); + + // Neutral + createCustomButton(__instance, next++, "NeutralSettings", "neutralRolesSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.Neutral, "NeutralSettings"); + // Crew + createCustomButton(__instance, next++, "CrewmateSettings", "crewmateRolesSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.Crewmate, "CrewmateSettings"); + // Modifier + createCustomButton(__instance, next++, "ModifierSettings", "modifierSettings".Translate()); + createGameOptionsMenu(__instance, CustomOptionType.Modifier, "ModifierSettings"); } - - settingsHighlightMap.ElementAt(index).Key.SetActive(true); - settingsHighlightMap.ElementAt(index).Value.enabled = true; } - private static void destroyOptions(List> optionBehavioursList) + private static void removeVanillaTabs(GameSettingMenu __instance) { - foreach (var optionBehaviours in optionBehavioursList) - foreach (var option in optionBehaviours) - Object.Destroy(option.gameObject); + GameObject.Find("What Is This?")?.Destroy(); + GameObject.Find("GamePresetButton")?.Destroy(); + GameObject.Find("RoleSettingsButton")?.Destroy(); + __instance.ChangeTab(1, false); } - - private static bool setNames(Dictionary gameObjectNameDisplayNameMap) + public static void createCustomButton(GameSettingMenu __instance, int targetMenu, string buttonName, string buttonText) { - foreach (var entry in gameObjectNameDisplayNameMap) - if (GameObject.Find(entry.Key) != null) + var leftPanel = GameObject.Find("LeftPanel"); + var leftLabel = GameObject.Find("GameSettingsLabel"); + var buttonTemplate = GameObject.Find("GameSettingsButton"); + leftLabel.transform.localPosition += new Vector3(0f, 0.02f); + if (targetMenu == 3) + { + buttonTemplate.transform.localPosition += Vector3.up * 2.15f; + buttonTemplate.transform.localScale *= Vector2.one * 0.75f; + } + var torSettingsButton = GameObject.Find(buttonName); + if (torSettingsButton == null) + { + torSettingsButton = UnityEngine.Object.Instantiate(buttonTemplate, leftPanel.transform); + torSettingsButton.transform.localPosition = buttonTemplate.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((Action)(() => { - // 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; - } - - return false; + __instance.ChangeTab(targetMenu, false); + })); + torSettingsPassiveButton.OnMouseOut.RemoveAllListeners(); + torSettingsPassiveButton.OnMouseOver.RemoveAllListeners(); + torSettingsPassiveButton.SelectButton(false); + currentButtons.Add(torSettingsPassiveButton); + } } - private static GameOptionsMenu getMenu(GameObject setting, string settingName) + public static void createGameOptionsMenu(GameSettingMenu __instance, CustomOptionType optionType, string settingName) { - var menu = setting.transform.FindChild("GameGroup").FindChild("SliderInner").GetComponent(); - setting.name = settingName; + var tabTemplate = GameObject.Find("GAME SETTINGS TAB"); + currentTabs.RemoveAll(x => x == null); - return menu; - } - - 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 = - UnityHelper.loadSpriteFromResources(tabSpritePath, 100f); - tab.name = "tabName"; + var torSettingsTab = UnityEngine.Object.Instantiate(tabTemplate, tabTemplate.transform.parent); + torSettingsTab.name = settingName; - return tabHighlight; + 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 (ModOption.gameMode == CustomGamemodes.Guesser) // Exclude guesser options in neutral mode + relevantOptions = relevantOptions.Where(x => !new List + { 10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 30100, 30101, 30102, 30103, 30104 }.Contains(x.id)).ToList(); + createSettings(torSettingsGOM, relevantOptions); + + currentTabs.Add(torSettingsTab); + torSettingsTab.SetActive(false); } - private static void setOptions(List menus, List> options, - List settings) + public static void createSettings(GameOptionsMenu menu, List options) { - if (!(menus.Count == options.Count && options.Count == settings.Count)) + var num = 1.5f; + foreach (var option in options) { - Error("List counts are not equal"); - return; + if (option.isHeader) + { + var categoryHeaderMasked = UnityEngine.Object.Instantiate(menu.categoryHeaderOrigin, Vector3.zero, Quaternion.identity, menu.settingsContainer); + categoryHeaderMasked.SetHeader(StringNames.ImpostorsCategory, 20); + + var titleText = option.heading != "" ? option.getHeading() : option.getName(); + var color = titleText.Contains("(true); + for (var i = 0; i < componentsInChildren.Length; i++) + { + componentsInChildren[i].material.SetInt(PlayerMaterial.MaskLayer, 20); + } + foreach (var textMeshPro in optionBehaviour.GetComponentsInChildren(true)) + { + textMeshPro.fontMaterial.SetFloat("_StencilComp", 3f); + textMeshPro.fontMaterial.SetFloat("_Stencil", 20); + } + + var stringOption = optionBehaviour as StringOption; + stringOption.OnValueChanged = new Action((o) => { }); + stringOption.TitleText.text = option.getName(); + if (option.isHeader && option.heading == "" && (option.type == CustomOptionType.Neutral || option.type == CustomOptionType.Crewmate || option.type == CustomOptionType.Impostor || option.type == CustomOptionType.Modifier)) + stringOption.TitleText.text = "optionSpawnChance".Translate(); + 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.getString(); + option.optionBehaviour = stringOption; + + menu.Children.Add(optionBehaviour); + num -= 0.45f; + menu.scrollBar.SetYBoundsMax(-num - 1.65f); } - for (var i = 0; i < menus.Count; i++) + for (var i = 0; i < menu.Children.Count; i++) { - menus[i].Children = options[i].ToArray(); - settings[i].gameObject.SetActive(false); + var optionBehaviour = menu.Children[i]; + if (AmongUsClient.Instance && !AmongUsClient.Instance.AmHost) + optionBehaviour.SetAsPlayer(); } } - - 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); - - var shortTasksOption = - __instance.Children.FirstOrDefault(x => x.name == "NumShortTasks").TryCast(); - if (shortTasksOption != null) shortTasksOption.ValidRange = new FloatRange(0f, 23f); - - var longTasksOption = __instance.Children.FirstOrDefault(x => x.name == "NumLongTasks").TryCast(); - if (longTasksOption != null) longTasksOption.ValidRange = new FloatRange(0f, 15f); - } } -[HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] +[HarmonyPatch(typeof(StringOption), nameof(StringOption.Initialize))] public class StringOptionEnablePatch { public static bool Prefix(StringOption __instance) { - var option = options.FirstOrDefault(option => option.optionBehaviour == __instance); + CustomOption option = options.FirstOrDefault(option => option.optionBehaviour == __instance); if (option == null) return true; - __instance.OnValueChanged = new Action(o => { }); - __instance.TitleText.text = option.getName(); + __instance.OnValueChanged = new Action((o) => { }); + //__instance.TitleText.text = option.getName(); __instance.Value = __instance.oldValue = option.selection; __instance.ValueText.text = option.getString(); @@ -796,9 +944,16 @@ public class StringOptionIncreasePatch { public static bool Prefix(StringOption __instance) { - var option = options.FirstOrDefault(option => option.optionBehaviour == __instance); + CustomOption option = options.FirstOrDefault(option => option.optionBehaviour == __instance); if (option == null) return true; option.updateSelection(option.selection + 1); + /*if (CustomOptionHolder.isMapSelectionOption(option)) + { + var currentGameOptions = GameOptionsManager.Instance.CurrentGameOptions; + currentGameOptions.SetByte(ByteOptionNames.MapId, (byte)option.selection); + GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions; + GameManager.Instance.LogicOptions.SyncOptions(); + }*/ return false; } } @@ -808,9 +963,16 @@ public class StringOptionDecreasePatch { public static bool Prefix(StringOption __instance) { - var option = options.FirstOrDefault(option => option.optionBehaviour == __instance); + CustomOption option = options.FirstOrDefault(option => option.optionBehaviour == __instance); if (option == null) return true; option.updateSelection(option.selection - 1); + /*if (CustomOptionHolder.isMapSelectionOption(option)) + { + var currentGameOptions = GameOptionsManager.Instance.CurrentGameOptions; + currentGameOptions.SetByte(ByteOptionNames.MapId, (byte)option.selection); + GameOptionsManager.Instance.GameHostOptions = GameOptionsManager.Instance.CurrentGameOptions; + GameManager.Instance.LogicOptions.SyncOptions(); + }*/ return false; } } @@ -821,27 +983,28 @@ public class StringOptionFixedUpdate public static void Postfix(StringOption __instance) { if (!IL2CPPChainloader.Instance.Plugins.TryGetValue("com.DigiWorm.LevelImposter", out var _)) return; - var option = options.FirstOrDefault(option => option.optionBehaviour == __instance); - if (option == null) return; + CustomOption option = options.FirstOrDefault(option => option.optionBehaviour == __instance); + //if (option == null || !CustomOptionHolder.isMapSelectionOption(option)) return; if (GameOptionsManager.Instance.CurrentGameOptions.MapId == 6) - if (option.optionBehaviour is not null and StringOption stringOption) + if (option.optionBehaviour != null && option.optionBehaviour is StringOption stringOption) { - stringOption.ValueText.text = option.selections[option.selection].ToString(); + stringOption.ValueText.text = option.getString(); } - else if (option.optionBehaviour is not null and StringOption stringOptionToo) + else if (option.optionBehaviour != null && option.optionBehaviour is StringOption stringOptionToo) { stringOptionToo.oldValue = stringOptionToo.Value = option.selection; - stringOptionToo.ValueText.text = option.selections[option.selection].ToString(); + stringOptionToo.ValueText.text = option.getString(); } } } + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcSyncSettings))] public class RpcSyncSettingsPatch { public static void Postfix() { - ShareOptionSelections(); + //CustomOption.ShareOptionSelections(); saveVanillaOptions(); } } @@ -859,73 +1022,19 @@ public static void Postfix() } } -[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Update))] -internal class GameOptionsMenuUpdatePatch -{ - private static float timer = 1f; - - public static void Postfix(GameOptionsMenu __instance) - { - // Return Menu Update if in normal among us settings - var gameSettingMenu = 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.2f) return; - timer = 0f; - - var offset = 2.75f; - foreach (var option in options) - { - if (GameObject.Find("ImpostorSettings") && option.type != CustomOptionType.Impostor) - continue; - if (GameObject.Find("NeutralSettings") && option.type != CustomOptionType.Neutral) - continue; - if (GameObject.Find("CrewmateSettings") && option.type != CustomOptionType.Crewmate) - continue; - if (GameObject.Find("ModifierSettings") && option.type != CustomOptionType.Modifier) - continue; - if (GameObject.Find("GuesserSettings") && option.type != CustomOptionType.Guesser) - continue; - if (option?.optionBehaviour != null && option.optionBehaviour.gameObject != null) - { - var 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] internal class GameOptionsDataPatch { - public static int maxPage = 7; - private static string buildRoleOptions() { - var impRoles = $"{"ImpostorRolesText".Translate()}{buildOptionsOfType(CustomOptionType.Impostor, true)}\n"; - var neutralRoles = $"{"NeutralRolesText".Translate()}{buildOptionsOfType(CustomOptionType.Neutral, true)}\n"; - var crewRoles = $"{"CrewmateRolesText".Translate()}{buildOptionsOfType(CustomOptionType.Crewmate, true)}\n"; - var modifiers = $"{"ModifierRolesText".Translate()}{buildOptionsOfType(CustomOptionType.Modifier, true)}"; + var impRoles = buildOptionsOfType(CustomOptionType.Impostor, true) + "\n"; + var neutralRoles = buildOptionsOfType(CustomOptionType.Neutral, true) + "\n"; + var crewRoles = buildOptionsOfType(CustomOptionType.Crewmate, true) + "\n"; + var modifiers = buildOptionsOfType(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 = options.Where(o => o.parent == customOption); @@ -933,27 +1042,26 @@ private static string buildModifierExtras(CustomOption customOption) if (customOption.GetSelection() == 0) return ""; if (quantity.Count == 1) return $" ({quantity[0].GetQuantity()})"; if (customOption == CustomOptionHolder.modifierLover) - return $" (1 {"EvilLove".Translate()}: {CustomOptionHolder.modifierLoverImpLoverRate.GetSelection() * 10}%)"; + return $" ({"EvilLove".Translate()} {CustomOptionHolder.modifierLoverImpLoverRate.GetSelection() * 10}%)"; return ""; } private static string buildOptionsOfType(CustomOptionType type, bool headerOnly) { var sb = new StringBuilder("\n"); - var options = CustomOption.options.Where(o => o.type == type); + var options = CustomOption.options.Where(o => o.type == type && !o.IsHidden()); if (ModOption.gameMode == CustomGamemodes.Guesser) { - if (type == CustomOptionType.General) options = CustomOption.options.Where(o => o.type == type || o.type == CustomOptionType.Guesser); + if (type == CustomOptionType.General) + options = CustomOption.options.Where(o => o.type == type || o.type == CustomOptionType.Guesser); var remove = new List { 10000, 10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, 30100, 30101, 30102, 30103, 30104 }; options = options.Where(x => !remove.Contains(x.id)); } else if (ModOption.gameMode == CustomGamemodes.Classic) - { - options = options.Where(x => - !(x.type == CustomOptionType.Guesser)); - } + options = options.Where(x => !(x.type == CustomOptionType.Guesser)); foreach (var option in options) + { if (option.parent == null) { var line = $"{option.getName()}: {option.getString()}"; @@ -969,9 +1077,9 @@ private static string buildOptionsOfType(CustomOptionType type, bool headerOnly) else if (option.id == 20135) //Sidekick sb.AppendLine($"- {cs(Jackal.color, "Sidekick".Translate())}: {option.getString()}"); } - + } if (headerOnly) return sb.ToString(); - sb = new StringBuilder(); + else sb = new StringBuilder(); foreach (var option in options) { @@ -1039,18 +1147,17 @@ private static string buildOptionsOfType(CustomOptionType type, bool headerOnly) } } } - return sb.ToString(); } + + public static int maxPage = 7; public static string buildAllOptions(string vanillaSettings = "", bool hideExtras = false) { if (vanillaSettings == "") vanillaSettings = GameOptionsManager.Instance.CurrentGameOptions.ToHudString(PlayerControl.AllPlayerControls.Count); var counter = Main.optionsPage; - var hudString = counter != 0 && !hideExtras - ? cs(DateTime.Now.Second % 2 == 0 ? Color.white : Color.red, "useScrollWheel".Translate()) - : ""; + var hudString = counter != 0 && !hideExtras ? "\n" : ""; maxPage = 7; switch (counter) @@ -1059,26 +1166,26 @@ public static string buildAllOptions(string vanillaSettings = "", bool hideExtra hudString += (!hideExtras ? "" : "page1".Translate()) + vanillaSettings; break; case 1: - hudString += "page2".Translate() + buildOptionsOfType(CustomOptionType.General, false); + hudString += $"{"page2".Translate()}\n{buildOptionsOfType(CustomOptionType.General, false)}"; break; case 2: - hudString += "page3".Translate() + buildRoleOptions(); + hudString += $"{"page3".Translate()}\n{buildRoleOptions()}"; break; case 3: - hudString += "page4".Translate() + buildOptionsOfType(CustomOptionType.Impostor, false); + hudString += $"{"page4".Translate()}\n{buildOptionsOfType(CustomOptionType.Impostor, false)}"; break; case 4: - hudString += "page5".Translate() + buildOptionsOfType(CustomOptionType.Neutral, false); + hudString += $"{"page5".Translate()}\n{buildOptionsOfType(CustomOptionType.Neutral, false)}"; break; case 5: - hudString += "page6".Translate() + buildOptionsOfType(CustomOptionType.Crewmate, false); + hudString += $"{"page6".Translate()}\n{buildOptionsOfType(CustomOptionType.Crewmate, false)}"; break; case 6: - hudString += "page7".Translate() + buildOptionsOfType(CustomOptionType.Modifier, false); + hudString += $"{"page7".Translate()}\n{buildOptionsOfType(CustomOptionType.Modifier, false)}"; break; } - if (!hideExtras || counter != 0) hudString += string.Format("pressTabForMore".Translate(), counter + 1, maxPage); + if (!hideExtras || counter != 0) hudString += string.Format(GetString("pressTabForMore"), counter + 1, maxPage); return hudString; } @@ -1086,102 +1193,8 @@ public static string buildAllOptions(string vanillaSettings = "", bool hideExtra [HarmonyPatch(typeof(IGameOptionsExtensions), nameof(IGameOptionsExtensions.ToHudString))] private static void Postfix(ref string __result) { - if (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) - return; // Allow Vanilla Hide N Seek - __result = buildAllOptions(__result); - } -} - -[HarmonyPatch] -public class AddToKillDistanceSetting -{ - [HarmonyPatch(typeof(GameOptionsData), nameof(GameOptionsData.AreInvalid))] - [HarmonyPrefix] - public static bool Prefix(GameOptionsData __instance, ref int maxExpectedPlayers) - { - //making the killdistances bound check higher since extra short is added - return __instance.MaxPlayers > maxExpectedPlayers || __instance.NumImpostors < 1 - || __instance.NumImpostors > 3 || __instance.KillDistance < 0 - || __instance.KillDistance >= - GameOptionsData.KillDistances.Count - || __instance.PlayerSpeedMod <= 0f || - __instance.PlayerSpeedMod > 3f; - } - - [HarmonyPatch(typeof(NormalGameOptionsV07), nameof(NormalGameOptionsV07.AreInvalid))] - [HarmonyPrefix] - public static bool Prefix(NormalGameOptionsV07 __instance, ref int maxExpectedPlayers) - { - return __instance.MaxPlayers > maxExpectedPlayers || __instance.NumImpostors < 1 - || __instance.NumImpostors > 3 || __instance.KillDistance < 0 - || __instance.KillDistance >= - GameOptionsData.KillDistances.Count - || __instance.PlayerSpeedMod <= 0f || - __instance.PlayerSpeedMod > 3f; - } - - [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] - [HarmonyPrefix] - public static void Prefix(StringOption __instance) - { - //prevents indexoutofrange exception breaking the setting if long happens to be selected - //when host opens the laptop - if (__instance.Title == StringNames.GameKillDistance && __instance.Value == 3) - { - __instance.Value = 1; - GameOptionsManager.Instance.currentNormalGameOptions.KillDistance = 1; - GameManager.Instance.LogicOptions.SyncOptions(); - } - } - - [HarmonyPatch(typeof(StringOption), nameof(StringOption.OnEnable))] - [HarmonyPostfix] - public static void Postfix(StringOption __instance) - { - if (__instance.Title == StringNames.GameKillDistance && __instance.Values.Count == 3) - __instance.Values = new Il2CppStructArray( - new[] - { - (StringNames)49999, StringNames.SettingShort, StringNames.SettingMedium, StringNames.SettingLong - }); - } - - [HarmonyPatch(typeof(IGameOptionsExtensions), nameof(IGameOptionsExtensions.AppendItem), - typeof(Il2CppSystem.Text.StringBuilder), typeof(StringNames), typeof(string))] - [HarmonyPrefix] - public static void Prefix(ref StringNames stringName, ref string value) - { - if (stringName == StringNames.GameKillDistance) - { - int index; - if (GameOptionsManager.Instance.currentGameMode == GameModes.Normal) - index = GameOptionsManager.Instance.currentNormalGameOptions.KillDistance; - else - { - index = GameOptionsManager.Instance.currentHideNSeekGameOptions.KillDistance; - } - value = GameOptionsData.KillDistanceStrings[index]; - } - } - - [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), - typeof(Il2CppReferenceArray))] - [HarmonyPriority(Priority.Last)] - public static bool Prefix(ref string __result, ref StringNames id) - { - if ((int)id == 49999) - { - __result = "KillDistancesVeryShort".Translate(); - return false; - } - - return true; - } - - public static void addKillDistance() - { - GameOptionsData.KillDistances = new Il2CppStructArray([0.6f, 1f, 1.8f, 2.5f]); - GameOptionsData.KillDistanceStrings = new Il2CppStringArray(["Very Short", "Short", "Medium", "Long"]); + if (GameOptionsManager.Instance.currentGameOptions.GameMode == GameModes.HideNSeek) return; // Allow Vanilla Hide N Seek + __result = buildAllOptions(vanillaSettings: __result); } } @@ -1191,75 +1204,54 @@ public static class GameOptionsNextPagePatch public static void Postfix(KeyboardJoystick __instance) { var page = Main.optionsPage; - if (Input.GetKeyDown(KeyCode.Tab)) Main.optionsPage = (Main.optionsPage + 1) % 7; - if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1)) Main.optionsPage = 0; - if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2)) Main.optionsPage = 1; - if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3)) Main.optionsPage = 2; - if (Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4)) Main.optionsPage = 3; - if (Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5)) Main.optionsPage = 4; - if (Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6)) Main.optionsPage = 5; - if (Input.GetKeyDown(KeyCode.Alpha7) || Input.GetKeyDown(KeyCode.Keypad7)) Main.optionsPage = 6; - if (Input.GetKeyDown(ModInputManager.showOptionPageInput.keyCode)) HudManagerUpdate.ToggleSettings(HudManager.Instance); + if (Input.GetKeyDown(KeyCode.Tab)) + Main.optionsPage = (Main.optionsPage + 1) % 7; + if (Input.GetKeyDown(KeyCode.Alpha1) || Input.GetKeyDown(KeyCode.Keypad1)) + Main.optionsPage = 0; + if (Input.GetKeyDown(KeyCode.Alpha2) || Input.GetKeyDown(KeyCode.Keypad2)) + Main.optionsPage = 1; + if (Input.GetKeyDown(KeyCode.Alpha3) || Input.GetKeyDown(KeyCode.Keypad3)) + Main.optionsPage = 2; + if (Input.GetKeyDown(KeyCode.Alpha4) || Input.GetKeyDown(KeyCode.Keypad4)) + Main.optionsPage = 3; + if (Input.GetKeyDown(KeyCode.Alpha5) || Input.GetKeyDown(KeyCode.Keypad5)) + Main.optionsPage = 4; + if (Input.GetKeyDown(KeyCode.Alpha6) || Input.GetKeyDown(KeyCode.Keypad6)) + Main.optionsPage = 5; + if (Input.GetKeyDown(KeyCode.Alpha7) || Input.GetKeyDown(KeyCode.Keypad7)) + Main.optionsPage = 6; + if (Input.GetKeyDown(ModInputManager.showOptionPageInput.keyCode)) + HudManagerUpdate.ToggleSettings(HudManager.Instance); if (Main.optionsPage >= GameOptionsDataPatch.maxPage) Main.optionsPage = 0; - - if (page != Main.optionsPage) - { - var position = (Vector3)FastDestroyableSingleton.Instance?.GameSettings?.transform.localPosition; - FastDestroyableSingleton.Instance.GameSettings.transform.localPosition = new Vector3(position.x, 2.9f, position.z); - } - - if (Input.GetKeyDown(ModInputManager.helpInput.keyCode)) - { - if (LobbyRoleInfo.RolesSummaryUI == null) - LobbyRoleInfo.RoleSummaryOnClick(); - else - { - Object.Destroy(LobbyRoleInfo.RolesSummaryUI); - LobbyRoleInfo.RolesSummaryUI = null; - } - } } } -[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 { +#pragma warning disable CS0649 + private static readonly TextMeshPro GameSettings; public static float - MinX, /*-5.3F*/ + 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; - private static readonly TextMeshPro[] settingsTMPs = new TextMeshPro[4]; - private static GameObject settingsBackground; - - private static PassiveButton toggleSettingsButton; - private static GameObject toggleSettingsButtonObject; - 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 var safeArea = Screen.safeArea; var aspect = Mathf.Min(Camera.main.aspect, safeArea.width / safeArea.height); var safeOrthographicSize = CameraSafeArea.GetSafeOrthographicSize(Camera.main); - MinX = 0.1f - (safeOrthographicSize * aspect); + MinX = 0.1f - safeOrthographicSize * aspect; if (!setLastPosition || aspect != lastAspect) { @@ -1271,38 +1263,38 @@ 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 LobbyTextRowHeight = 0.12F; - var maxY = Mathf.Max(MinY, (rows * LobbyTextRowHeight) + ((rows - 38) * LobbyTextRowHeight)); + var rows = GameSettings.text.Count(c => c == '\n'); + var LobbyTextRowHeight = 0.06F; + var maxY = Mathf.Max(MinY, rows * LobbyTextRowHeight + (rows - 38) * LobbyTextRowHeight); Scroller.ContentYBounds = new FloatRange(MinY, maxY); // 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; - var target = __instance.GameSettings.transform; + var 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; @@ -1324,7 +1316,7 @@ public static void Prefix2(HudManager __instance) if (!settingsTMPs[0]) return; foreach (var tmp in settingsTMPs) tmp.text = ""; var settingsString = GameOptionsDataPatch.buildAllOptions(hideExtras: true); - var blocks = settingsString.Split("\n\n", StringSplitOptions.RemoveEmptyEntries); + var blocks = settingsString.Split("\n\n", StringSplitOptions.RemoveEmptyEntries); ; var curString = ""; string curBlock; var j = 0; @@ -1346,19 +1338,22 @@ public static void Prefix2(HudManager __instance) if (j < settingsTMPs.Length) settingsTMPs[j].text = curString; var blockCount = 0; foreach (var tmp in settingsTMPs) + { if (tmp.text != "") blockCount++; + } for (var i = 0; i < blockCount; i++) + { settingsTMPs[i].transform.localPosition = new Vector3(-blockCount * 1.2f + 2.7f * i, 2.2f, -500f); + } } + private static TextMeshPro[] settingsTMPs = new 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; - settingsBackground = Object.Instantiate(__instance.FullScreen.gameObject, __instance.transform); + if (__instance.FullScreen == null || MapBehaviour.Instance && MapBehaviour.Instance.IsOpen) return; + settingsBackground = UnityEngine.Object.Instantiate(__instance.FullScreen.gameObject, __instance.transform); settingsBackground.SetActive(true); var renderer = settingsBackground.GetComponent(); renderer.color = new Color(0.2f, 0.2f, 0.2f, 0.9f); @@ -1366,7 +1361,7 @@ public static void OpenSettings(HudManager __instance) for (var i = 0; i < settingsTMPs.Length; i++) { - settingsTMPs[i] = Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform); + settingsTMPs[i] = UnityEngine.Object.Instantiate(__instance.KillButton.cooldownTimerText, __instance.transform); settingsTMPs[i].alignment = TextAlignmentOptions.TopLeft; settingsTMPs[i].enableWordWrapping = false; settingsTMPs[i].transform.localScale = Vector3.one * 0.25f; @@ -1377,8 +1372,7 @@ public static void OpenSettings(HudManager __instance) public static void CloseSettings() { foreach (var tmp in settingsTMPs) - if (tmp) - tmp.gameObject.Destroy(); + if (tmp) tmp.gameObject.Destroy(); if (settingsBackground) settingsBackground.Destroy(); } @@ -1389,54 +1383,55 @@ public static void ToggleSettings(HudManager __instance) else OpenSettings(__instance); } + private static PassiveButton toggleSettingsButton; + private static GameObject toggleSettingsButtonObject; + private static GameObject toggleZoomButtonObject; + private 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 = Object.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); - toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -0.66f, -500f); - var renderer = toggleSettingsButtonObject.GetComponent(); - renderer.sprite = new ResourceSprite("TheOtherRoles.Resources.CurrentSettingsButton.png", 180f); + toggleSettingsButtonObject = UnityEngine.Object.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); + toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -1.25f, -500f); + toggleSettingsButtonObject.name = "TOGGLESETTINGSBUTTON"; + var renderer = toggleSettingsButtonObject.transform.Find("Inactive").GetComponent(); + var rendererActive = toggleSettingsButtonObject.transform.Find("Active").GetComponent(); + toggleSettingsButtonObject.transform.Find("Background").localPosition = Vector3.zero; + renderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Settings_Button.png", 100f); + rendererActive.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Settings_ButtonActive.png", 100); toggleSettingsButton = toggleSettingsButtonObject.GetComponent(); toggleSettingsButton.OnClick.RemoveAllListeners(); toggleSettingsButton.OnClick.AddListener((Action)(() => ToggleSettings(__instance))); - _ = CustomButton.SetKeyGuideOnSmallButton(toggleSettingsButtonObject, ModInputManager.showOptionPageInput.keyCode); } + 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.8f, -500f); - toggleSettingsButtonObject.SetActive(__instance.MapButton.gameObject.active && !IsHideNSeek && !(MapBehaviour.Instance && MapBehaviour.Instance.IsOpen)); - toggleSettingsButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -0.66f, -500f); - } - - private static PassiveButton rolesSummaryButton; - private static GameObject rolesSummaryButtonObject; - [HarmonyPostfix] - public static void Postfix2(HudManager __instance) - { - if (!rolesSummaryButton || !rolesSummaryButtonObject) + if (!toggleZoomButton || !toggleZoomButtonObject) { // add a special button for settings viewing: - rolesSummaryButtonObject = Object.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); - rolesSummaryButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -1.31f, -500f); - var renderer = rolesSummaryButtonObject.GetComponent(); - renderer.sprite = new ResourceSprite("TheOtherRoles.Resources.HelpButton.png", 100f); - rolesSummaryButton = rolesSummaryButtonObject.GetComponent(); - rolesSummaryButton.OnClick.RemoveAllListeners(); - rolesSummaryButton.OnClick.AddListener((Action)(() => - { - if (LobbyRoleInfo.RolesSummaryUI == null) - LobbyRoleInfo.RoleSummaryOnClick(); - else - { - Object.Destroy(LobbyRoleInfo.RolesSummaryUI); - LobbyRoleInfo.RolesSummaryUI = null; - } - })); - _ = CustomButton.SetKeyGuideOnSmallButton(rolesSummaryButtonObject, ModInputManager.helpInput.keyCode); + toggleZoomButtonObject = UnityEngine.Object.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); + toggleZoomButtonObject.transform.localPosition = __instance.MapButton.transform.localPosition + new Vector3(0, -1.25f, -500f); + toggleZoomButtonObject.name = "TOGGLEZOOMBUTTON"; + var tZrenderer = toggleZoomButtonObject.transform.Find("Inactive").GetComponent(); + var tZArenderer = toggleZoomButtonObject.transform.Find("Active").GetComponent(); + toggleZoomButtonObject.transform.Find("Background").localPosition = Vector3.zero; + tZrenderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Minus_Button.png", 100f); + tZArenderer.sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.Minus_ButtonActive.png", 100); + toggleZoomButton = toggleZoomButtonObject.GetComponent(); + toggleZoomButton.OnClick.RemoveAllListeners(); + toggleZoomButton.OnClick.AddListener((Action)(() => toggleZoom())); } - - rolesSummaryButtonObject.SetActive(__instance.MapButton.gameObject.active && !IsHideNSeek && !(MapBehaviour.Instance && MapBehaviour.Instance.IsOpen)); - rolesSummaryButtonObject.transform.localPosition = __instance.MapButton.transform.transform.localPosition + new Vector3(0, -1.31f, -500f); + var (playerCompleted, playerTotal) = TasksHandler.taskInfo(CachedPlayer.LocalPlayer.Data); + var numberOfLeftTasks = playerTotal - playerCompleted; + var 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 = zoomOutStatus ? new Vector3(-1.27f, -7.92f, -52f) : new Vector3(0, -1.6f, -52f); + toggleZoomButtonObject.transform.localPosition = HudManager.Instance.MapButton.transform.localPosition + posOffset; } -} \ No newline at end of file +} diff --git a/TheOtherRoles/Options/ModOption.cs b/TheOtherRoles/Options/ModOption.cs index 74f58e5e..e3cbec2c 100644 --- a/TheOtherRoles/Options/ModOption.cs +++ b/TheOtherRoles/Options/ModOption.cs @@ -12,7 +12,7 @@ internal class ModOption public static int NumImpostors => GameOptionsManager.Instance.currentNormalGameOptions.NumImpostors; public static bool DebugMode => CustomOptionHolder.debugMode.GetBool(); public static bool DisableGameEnd => DebugMode && CustomOptionHolder.disableGameEnd.GetBool(); - public static NormalGameOptionsV07 NormalOptions => GameOptionsManager.Instance.currentNormalGameOptions; + public static NormalGameOptionsV08 NormalOptions => GameOptionsManager.Instance.currentNormalGameOptions; // Set values public static int maxNumberOfMeetings = 10; @@ -34,6 +34,8 @@ internal class ModOption public static bool randomLigherPlayer; public static bool disableMedscanWalking; public static bool isCanceled; + public static bool ShowChatNotifications = true; + public static bool MuteLobbyBGM; public static int restrictDevices; @@ -122,6 +124,8 @@ public static void reloadPluginOptions() enableSoundEffects = Main.EnableSoundEffects.Value; showKeyReminder = Main.ShowKeyReminder.Value; localHats = Main.LocalHats.Value; + ShowChatNotifications = Main.ShowChatNotifications.Value; + MuteLobbyBGM = Main.MuteLobbyBGM.Value; } public static void resetDeviceTimes() diff --git a/TheOtherRoles/Patches/CredentialsPatch.cs b/TheOtherRoles/Patches/CredentialsPatch.cs index 99177fca..d7b83fff 100644 --- a/TheOtherRoles/Patches/CredentialsPatch.cs +++ b/TheOtherRoles/Patches/CredentialsPatch.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System.Collections.Generic; +using AmongUs.GameOptions; using InnerNet; using TMPro; using UnityEngine; @@ -23,14 +24,11 @@ internal static class PingTrackerPatch private static void Postfix(PingTracker __instance) { - DeltaTime += (Time.deltaTime - DeltaTime) * 0.1f; var fps = Mathf.Ceil(1f / DeltaTime); - var PingText = $"Ping: {AmongUsClient.Instance.Ping}ms{(ModOption.showFPS ? $" FPS: {fps}" : "")}"; - __instance.text.SetOutlineThickness(0.1f); + var pingText = $"Ping: {AmongUsClient.Instance.Ping}ms{(ModOption.showFPS ? $" FPS: {fps}" : "")}"; var host = $"{"Host".Translate()}: {GameData.Instance?.GetHost()?.PlayerName}"; - - __instance.text.alignment = TextAlignmentOptions.TopRight; + __instance.text.SetOutlineThickness(0.01f); var position = __instance.GetComponent(); var gameModeText = ModOption.gameMode switch { @@ -38,19 +36,46 @@ private static void Postfix(PingTracker __instance) _ => "" }; if (ModOption.DebugMode) gameModeText += "(Debug Mode)"; - if (gameModeText != "") gameModeText = cs(Color.yellow, gameModeText) + "\n"; + + if (!string.IsNullOrEmpty(gameModeText)) gameModeText = cs(Color.yellow, gameModeText) + "\n"; + if (AmongUsClient.Instance.GameState == InnerNetClient.GameStates.Started) { - __instance.text.text = $"{GetString("TouTitle")} v{Main.Version + "\n" + GetString("inGameTitle")}\n{PingText}\n{gameModeText}"; - position.DistanceFromEdge = new Vector3(2.25f, 0.1f, 0); + __instance.text.alignment = TextAlignmentOptions.TopRight; + position.Alignment = AspectPosition.EdgeAlignments.RightTop; + __instance.text.text = $"{GetString("TouTitle")} v{Main.Version}\n{GetString("inGameTitle")}\n{gameModeText}{pingText}"; + position.DistanceFromEdge = new Vector3(2.7f, 0.1f, 0); } else { - __instance.text.text = $"{fullCredentialsVersion}\n {PingText}\n {gameModeText + fullCredentials}\n {host}"; - position.DistanceFromEdge = new Vector3(2.85f, 0.1f, 0); + __instance.text.alignment = TextAlignmentOptions.TopLeft; + position.Alignment = AspectPosition.EdgeAlignments.LeftTop; + __instance.text.text = $"{fullCredentialsVersion}\n{pingText}\n{gameModeText}{fullCredentials}\n{host}"; + position.DistanceFromEdge = new(0.4f, 0.06f); + try + { + UpdateGameModeText(); + } + catch { } } position.AdjustPosition(); } + + private static void UpdateGameModeText() + { + var gameModeText = ModOption.gameMode switch + { + CustomGamemodes.Guesser => GetString("isGuesserGm"), + CustomGamemodes.Classic => GetString("isClassicGM"), + _ => "" + }; + gameModeText = cs(Color.yellow, gameModeText); + var GameModeText = GameObject.Find("GameModeText")?.GetComponent(); + GameModeText.text = string.IsNullOrEmpty(gameModeText) ? (GameOptionsManager.Instance.currentGameOptions.GameMode + == GameModes.HideNSeek ? "isVanHideNSeekGM".Translate() : "isClassicGM".Translate()) : gameModeText; + var modeLabel = GameObject.Find("ModeLabel")?.GetComponentInChildren(); + modeLabel.text = "GameMode".Translate(); + } } [HarmonyPatch(typeof(MainMenuManager), nameof(MainMenuManager.Start))] diff --git a/TheOtherRoles/Patches/EndGamePatch.cs b/TheOtherRoles/Patches/EndGamePatch.cs index c6ffdc88..3a220b79 100644 --- a/TheOtherRoles/Patches/EndGamePatch.cs +++ b/TheOtherRoles/Patches/EndGamePatch.cs @@ -106,6 +106,8 @@ public static void Prefix(AmongUsClient __instance, [HarmonyArgument(0)] ref End public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref EndGameResult endGameResult) { + EndGameResult.CachedWinners = new Il2CppSystem.Collections.Generic.List(); + AdditionalTempData.clear(); List killRole = [ @@ -172,12 +174,6 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En notWinners.AddRange(Survivor.Player.Where(p => p != null)); if (Akujo.honmeiCannotFollowWin && Akujo.honmei != null) notWinners.Add(Akujo.honmei); - var winnersToRemove = new List(); - foreach (var winner in TempData.winners.GetFastEnumerator()) - if (notWinners.Any(x => x != null && x.Data.PlayerName == winner.PlayerName)) - winnersToRemove.Add(winner); - - foreach (var winner in winnersToRemove) TempData.winners.Remove(winner); var isCanceled = gameOverReason == (GameOverReason)CustomGameOverReason.Canceled; var everyoneDead = AdditionalTempData.playerRoles.All(x => !x.IsAlive); var miniLose = Mini.mini != null && gameOverReason == (GameOverReason)CustomGameOverReason.MiniLose; @@ -196,6 +192,8 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En (Jackal.jackal.Any(x => x.IsAlive()) || Jackal.sidekick.IsAlive()); var teamPavlovsWin = gameOverReason == (GameOverReason)CustomGameOverReason.TeamPavlovsWin && (Pavlovsdogs.pavlovsowner.IsAlive() || Pavlovsdogs.pavlovsdogs.Any(p => p.IsAlive())); + var crewmateWin = GameManager.Instance.DidHumansWin(gameOverReason) || + (gameOverReason is GameOverReason.HumansByVote or GameOverReason.HumansByTask); var vultureWin = Vulture.vulture != null && gameOverReason == (GameOverReason)CustomGameOverReason.VultureWin; var executionerWin = Executioner.executioner != null && gameOverReason == (GameOverReason)CustomGameOverReason.ExecutionerWin; var lawyerSoloWin = Lawyer.lawyer != null && gameOverReason == (GameOverReason)CustomGameOverReason.LawyerSoloWin; @@ -206,70 +204,55 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En : gameOverReason == (GameOverReason)CustomGameOverReason.AkujoWin); bool isPursurerLose = jesterWin || arsonistWin || miniLose || isCanceled || executionerWin; + var winners = new List(); + var isYou = true; + var isImpostor = false; + // Mini lose if (miniLose) { // If "no one is the Mini", it will display the Mini, but also show defeat to everyone - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Mini.mini.Data) { IsYou = false }; - TempData.winners.Add(wpd); + winners.Add(Mini.mini.Data); + isYou = false; AdditionalTempData.winCondition = WinCondition.MiniLose; } - else if (isCanceled) + else if (isCanceled || everyoneDead) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); AdditionalTempData.winCondition = WinCondition.Canceled; } // Jester win - else if (jesterWin) + if (jesterWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Jester.jester.Data); - TempData.winners.Add(wpd); + winners.Add(Jester.jester.Data); AdditionalTempData.winCondition = WinCondition.JesterWin; } // Witness win else if (witnessWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Witness.Player.Data); - TempData.winners.Add(wpd); + winners.Add(Witness.Player.Data); AdditionalTempData.winCondition = WinCondition.WitnessWin; } // Arsonist win else if (arsonistWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Arsonist.arsonist.Data); - TempData.winners.Add(wpd); + winners.Add(Arsonist.arsonist.Data); AdditionalTempData.winCondition = WinCondition.ArsonistWin; } - // Everyone Died - else if (everyoneDead) - { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - AdditionalTempData.winCondition = WinCondition.EveryoneDied; - } - // Vulture win else if (vultureWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Vulture.vulture.Data); - TempData.winners.Add(wpd); + winners.Add(Vulture.vulture.Data); AdditionalTempData.winCondition = WinCondition.VultureWin; } // Jester win else if (executionerWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Executioner.executioner.Data); - TempData.winners.Add(wpd); + winners.Add(Executioner.executioner.Data); AdditionalTempData.winCondition = WinCondition.ExecutionerWin; } @@ -280,106 +263,84 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En if (!Lovers.existingWithKiller()) { AdditionalTempData.winCondition = WinCondition.LoversTeamWin; - TempData.winners = 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)); + winners.Add(p.Data); else if (Pursuer.Player.Any(pc => pc == p) && Pursuer.Player.Any(pc => pc.IsAlive())) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); else if (Survivor.Player.Any(pc => pc == p) && Survivor.Player.Any(pc => pc.IsAlive())) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); else if (!notWinners.Contains(p) && !p.Data.Role.IsImpostor) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(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)); + winners.Add(Lovers.lover1.Data); + winners.Add(Lovers.lover2.Data); + } + } + + else if (crewmateWin) + { + AdditionalTempData.winCondition = WinCondition.TaskerWin; + foreach (var player in CachedPlayer.AllPlayers) + { + if (player == null) continue; + if (!player.Data.Role.IsImpostor && !notWinners.Contains(player)) + winners.Add(player.Data); + } + } + + else if (impostorWin) + { + isImpostor = true; + foreach (NetworkedPlayerInfo player in GameData.Instance.AllPlayers) + { + if (player.Role.IsImpostor) + winners.Add(player); } } // Jackal win condition (should be implemented using a proper GameOverReason in the future) else if (teamJackalWin) { - // Jackal wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.JackalWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); foreach (var player in Jackal.jackal) - { - var wpdFormerJackal = new WinningPlayerData(player.Data); - wpdFormerJackal.IsImpostor = false; - TempData.winners.Add(wpdFormerJackal); - } - // If there is a sidekick. The sidekick also wins + winners.Add(player.Data); if (Jackal.sidekick != null) - { - var wpdSidekick = new WinningPlayerData(Jackal.sidekick.Data); - wpdSidekick.IsImpostor = false; - TempData.winners.Add(wpdSidekick); - } + winners.Add(Jackal.sidekick.Data); } + else if (teamPavlovsWin) { - // Jackal wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.PavlovsWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Pavlovsdogs.pavlovsowner.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + winners.Add(Pavlovsdogs.pavlovsowner.Data); foreach (var player in Pavlovsdogs.pavlovsdogs) - { - var wpdFormerPavlovs = new WinningPlayerData(player.Data); - wpdFormerPavlovs.IsImpostor = false; - TempData.winners.Add(wpdFormerPavlovs); - } + winners.Add(player.Data); } + else if (werewolfWin) { - // Werewolf wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.WerewolfWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Werewolf.werewolf.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + winners.Add(Werewolf.werewolf.Data); } else if (juggernautWin) { // JuggernautWin wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.JuggernautWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Juggernaut.juggernaut.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); - } - - else if (impostorWin) - { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - foreach (GameData.PlayerInfo player in GameData.Instance.AllPlayers) - { - var wpd = new WinningPlayerData(player) { IsImpostor = true }; - if (player.Role.IsImpostor) - { - TempData.winners.Add(wpd); - } - } + winners.Add(Juggernaut.juggernaut.Data); } else if (doomsayerWin) { // DoomsayerWin wins if nobody except jackal is alive - AdditionalTempData.winCondition = WinCondition.DoomsayerWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Doomsayer.doomsayer.Data); - TempData.winners.Add(wpd); + winners.Add(Doomsayer.doomsayer.Data); AdditionalTempData.winCondition = WinCondition.DoomsayerWin; } @@ -388,10 +349,7 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En { // Swooper wins if nobody except jackal is alive AdditionalTempData.winCondition = WinCondition.SwooperWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - var wpd = new WinningPlayerData(Swooper.swooper.Data); - wpd.IsImpostor = false; - TempData.winners.Add(wpd); + winners.Add(Swooper.swooper.Data); } // Akujo win @@ -400,60 +358,57 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En if (Akujo.honmeiOptimizeWin && !Akujo.existingWithKiller()) { AdditionalTempData.winCondition = WinCondition.AkujoTeamWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); foreach (PlayerControl p in CachedPlayer.AllPlayers) { if (p == null) continue; if (p == Akujo.akujo || p == Akujo.honmei) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); else if (Pursuer.Player.Contains(p) && !p.Data.IsDead) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); else if (Survivor.Player.Contains(p) && !p.Data.IsDead) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); else if (!notWinners.Contains(p) && !p.Data.Role.IsImpostor) - TempData.winners.Add(new WinningPlayerData(p.Data)); + winners.Add(p.Data); } } else { AdditionalTempData.winCondition = WinCondition.AkujoSoloWin; - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - TempData.winners.Add(new WinningPlayerData(Akujo.akujo.Data)); - TempData.winners.Add(new WinningPlayerData(Akujo.honmei.Data)); + winners.Add(Akujo.akujo.Data); + winners.Add(Akujo.honmei.Data); } } // Lawyer solo win else if (lawyerSoloWin) { - TempData.winners = new Il2CppSystem.Collections.Generic.List(); - WinningPlayerData wpd = new(Lawyer.lawyer.Data); - TempData.winners.Add(wpd); + winners.Add(Lawyer.lawyer.Data); AdditionalTempData.winCondition = WinCondition.LawyerSoloWin; } // Possible Additional winner: Lawyer - if (!lawyerSoloWin && Lawyer.lawyer != null && Lawyer.target != null && - (!Lawyer.target.Data.IsDead || Lawyer.target == Jester.jester) && !Lawyer.notAckedExiled) + if (!lawyerSoloWin && Lawyer.lawyer.IsAlive() && Lawyer.target != null && Lawyer.target == Jester.jester && !Lawyer.notAckedExiled) { - WinningPlayerData winningClient = null; - foreach (var winner in TempData.winners.GetFastEnumerator()) - if (winner.PlayerName == Lawyer.target.Data.PlayerName) - winningClient = winner; + NetworkedPlayerInfo winningClient = null; + foreach (var winner in winners.ToArray()) + if (winner.PlayerId == Lawyer.target.PlayerId) winningClient = winner; + if (winningClient != null) { - if (!TempData.winners.ToArray().Any(x => x.PlayerName == Lawyer.lawyer.Data.PlayerName)) + if (!winners.ToArray().Any(x => x.PlayerId == Lawyer.lawyer.PlayerId)) { if (!Lawyer.lawyer.Data.IsDead && Lawyer.stolenWin) { - TempData.winners.Remove(winningClient); - TempData.winners.Add(new WinningPlayerData(Lawyer.lawyer.Data)); - AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerStolenWin); // The Lawyer replaces the client's victory + // The Lawyer replaces the client's victory + winners.Remove(winningClient); + winners.Add(Lawyer.lawyer.Data); + AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerStolenWin); } else { - TempData.winners.Add(new WinningPlayerData(Lawyer.lawyer.Data)); - AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerBonusWin); // The Lawyer wins with the client + // The Lawyer wins with the client + winners.Add(Lawyer.lawyer.Data); + AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalLawyerBonusWin); } } } @@ -464,8 +419,8 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En { foreach (var player in Pursuer.Player.Where(p => !p.Data.IsDead)) { - if (!TempData.winners.ToArray().Any(x => x.PlayerName == player.Data.PlayerName)) - TempData.winners.Add(new WinningPlayerData(player.Data)); + if (!winners.ToArray().Any(x => x.PlayerName == player.Data.PlayerName)) + winners.Add(player.Data); } AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalAlivePursuerWin); } @@ -475,17 +430,23 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En { foreach (var player in Survivor.Player.Where(p => !p.Data.IsDead)) { - if (!TempData.winners.ToArray().Any(x => x.PlayerName == player.Data.PlayerName)) - TempData.winners.Add(new WinningPlayerData(player.Data)); + if (!winners.ToArray().Any(x => x.PlayerName == player.Data.PlayerName)) + winners.Add(player.Data); } AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalAliveSurvivorWin); } - if (PartTimer.partTimer != null && PartTimer.target != null && TempData.winners.ToArray().Any(x => x.PlayerName == PartTimer.target.Data.PlayerName)) + if (PartTimer.partTimer != null && PartTimer.target != null && winners.ToArray().Any(x => x.PlayerId == PartTimer.target.Data.PlayerId)) { - TempData.winners.Add(new WinningPlayerData(PartTimer.partTimer.Data)); + winners.Add(PartTimer.partTimer.Data); AdditionalTempData.additionalWinConditions.Add(WinCondition.AdditionalPartTimerWin); } + + foreach (var data in winners.GroupBy(x => x.PlayerId).Select(g => g.First())) + { + EndGameResult.CachedWinners.Add(new CachedPlayerData(data) { IsYou = isYou, IsImpostor = isImpostor }); + } + Message($"游戏结束 {AdditionalTempData.winCondition}", "OnGameEnd"); // Reset Settings RPCProcedure.resetVariables(); @@ -498,10 +459,9 @@ public class EndGameManagerSetUpPatch public static void Postfix(EndGameManager __instance) { // Delete and readd PoolablePlayers always showing the name and role of the player - foreach (var pb in __instance.transform.GetComponentsInChildren()) - Object.Destroy(pb.gameObject); - var num = Mathf.CeilToInt(7.5f); - var list = TempData.winners.ToList().OrderBy(delegate (WinningPlayerData b) { return !b.IsYou ? 0 : -1; }).ToList(); + foreach (var pb in __instance.transform.GetComponentsInChildren()) Object.Destroy(pb.gameObject); + int num = Mathf.CeilToInt(7.5f); + var list = EndGameResult.CachedWinners.ToList().OrderBy(delegate (CachedPlayerData b) { return !b.IsYou ? 0 : -1; }).ToList(); for (var i = 0; i < list.Count; i++) { var winningPlayerData2 = list[i]; @@ -526,7 +486,7 @@ public static void Postfix(EndGameManager __instance) poolablePlayer.SetFlipX(i % 2 == 0); } - poolablePlayer.UpdateFromPlayerOutfit(winningPlayerData2, PlayerMaterial.MaskType.None, winningPlayerData2.IsDead, true); + poolablePlayer.UpdateFromPlayerOutfit(winningPlayerData2.Outfit, PlayerMaterial.MaskType.None, winningPlayerData2.IsDead, true); poolablePlayer.cosmetics.nameText.color = Color.white; poolablePlayer.cosmetics.nameText.transform.localScale = new Vector3(1f / vector.x, 1f / vector.y, 1f / vector.z); @@ -543,7 +503,39 @@ public static void Postfix(EndGameManager __instance) } } - // Additional code + // Create a dictionary for win conditions + var winConditionTexts = new Dictionary + { + { WinCondition.Canceled, (Color.gray, "CanceledEnd") }, + { WinCondition.EveryoneDied, (Palette.DisabledGrey, "EveryoneDied") }, + { WinCondition.JesterWin, (Jester.color, "JesterWin") }, + { WinCondition.DoomsayerWin, (Doomsayer.color, "DoomsayerWin") }, + { WinCondition.ArsonistWin, (Arsonist.color, "ArsonistWin") }, + { WinCondition.VultureWin, (Vulture.color, "VultureWin") }, + { WinCondition.LawyerSoloWin, (Lawyer.color, "LawyerSoloWin") }, + { WinCondition.WerewolfWin, (Werewolf.color, "WerewolfWin") }, + { WinCondition.WitnessWin, (Witness.color, "WitnessWin") }, + { WinCondition.JuggernautWin, (Juggernaut.color, "JuggernautWin") }, + { WinCondition.SwooperWin, (Swooper.color, "SwooperWin") }, + { WinCondition.ExecutionerWin, (Executioner.color, "ExecutionerWin") }, + { WinCondition.LoversTeamWin, (Lovers.color, "LoversTeamWin") }, + { WinCondition.LoversSoloWin, (Lovers.color, "LoversSoloWin") }, + { WinCondition.JackalWin, (Jackal.color, "JackalWin") }, + { WinCondition.PavlovsWin, (Pavlovsdogs.color, "PavlovsWin") }, + { WinCondition.AkujoSoloWin, (Akujo.color, "AkujoSoloWin") }, + { WinCondition.AkujoTeamWin, (Akujo.color, "AkujoTeamWin") }, + { WinCondition.MiniLose, (Mini.color, "MiniLose") }, + }; + + var winConditionMappings = new Dictionary + { + { WinCondition.AdditionalLawyerStolenWin, (Lawyer.color, "LawyerStolenWin") }, + { WinCondition.AdditionalLawyerBonusWin, (Lawyer.color, "LawyerBonusWin") }, + { WinCondition.AdditionalPartTimerWin, (PartTimer.color, "PartTimerWin") }, + { WinCondition.AdditionalAlivePursuerWin, (Pursuer.color, "起诉人存活") }, + { WinCondition.AdditionalAliveSurvivorWin, (Survivor.color, "幸存者存活") } + }; + var bonusText = Object.Instantiate(__instance.WinText.gameObject); var position1 = __instance.WinText.transform.position; bonusText.transform.position = new Vector3(position1.x, position1.y - 0.5f, position1.z); @@ -551,102 +543,11 @@ public static void Postfix(EndGameManager __instance) var textRenderer = bonusText.GetComponent(); textRenderer.text = ""; - switch (AdditionalTempData.winCondition) + if (winConditionTexts.TryGetValue(AdditionalTempData.winCondition, out var winText)) { - case WinCondition.Canceled: - textRenderer.text = "CanceledEnd".Translate(); - textRenderer.color = Color.gray; - __instance.BackgroundBar.material.SetColor("_Color", Color.gray); - break; - case WinCondition.EveryoneDied: - textRenderer.text = "EveryoneDied".Translate(); - textRenderer.color = Palette.DisabledGrey; - __instance.BackgroundBar.material.SetColor("_Color", Palette.DisabledGrey); - break; - case WinCondition.JesterWin: - textRenderer.text = "JesterWin".Translate(); - textRenderer.color = Jester.color; - __instance.BackgroundBar.material.SetColor("_Color", Jester.color); - break; - case WinCondition.DoomsayerWin: - textRenderer.text = "DoomsayerWin".Translate(); - textRenderer.color = Doomsayer.color; - __instance.BackgroundBar.material.SetColor("_Color", Doomsayer.color); - break; - case WinCondition.ArsonistWin: - textRenderer.text = "ArsonistWin".Translate(); - textRenderer.color = Arsonist.color; - __instance.BackgroundBar.material.SetColor("_Color", Arsonist.color); - break; - case WinCondition.VultureWin: - textRenderer.text = "VultureWin".Translate(); - textRenderer.color = Vulture.color; - __instance.BackgroundBar.material.SetColor("_Color", Vulture.color); - break; - case WinCondition.LawyerSoloWin: - textRenderer.text = "LawyerSoloWin".Translate(); - textRenderer.color = Lawyer.color; - __instance.BackgroundBar.material.SetColor("_Color", Lawyer.color); - break; - case WinCondition.WerewolfWin: - textRenderer.text = "WerewolfWin".Translate(); - textRenderer.color = Werewolf.color; - __instance.BackgroundBar.material.SetColor("_Color", Werewolf.color); - break; - case WinCondition.WitnessWin: - textRenderer.text = "WitnessWin".Translate(); - textRenderer.color = Witness.color; - __instance.BackgroundBar.material.SetColor("_Color", Witness.color); - break; - case WinCondition.JuggernautWin: - textRenderer.text = "JuggernautWin".Translate(); - textRenderer.color = Juggernaut.color; - __instance.BackgroundBar.material.SetColor("_Color", Juggernaut.color); - break; - case WinCondition.SwooperWin: - textRenderer.text = "SwooperWin".Translate(); - textRenderer.color = Swooper.color; - __instance.BackgroundBar.material.SetColor("_Color", Swooper.color); - break; - case WinCondition.ExecutionerWin: - textRenderer.text = "ExecutionerWin".Translate(); - textRenderer.color = Executioner.color; - __instance.BackgroundBar.material.SetColor("_Color", Executioner.color); - break; - case WinCondition.LoversTeamWin: - textRenderer.text = "LoversTeamWin".Translate(); - textRenderer.color = Lovers.color; - __instance.BackgroundBar.material.SetColor("_Color", Lovers.color); - break; - case WinCondition.LoversSoloWin: - textRenderer.text = "LoversSoloWin".Translate(); - textRenderer.color = Lovers.color; - __instance.BackgroundBar.material.SetColor("_Color", Lovers.color); - break; - case WinCondition.JackalWin: - textRenderer.text = "JackalWin".Translate(); - textRenderer.color = Jackal.color; - __instance.BackgroundBar.material.SetColor("_Color", Jackal.color); - break; - case WinCondition.PavlovsWin: - textRenderer.text = "PavlovsWin".Translate(); - textRenderer.color = Pavlovsdogs.color; - __instance.BackgroundBar.material.SetColor("_Color", Pavlovsdogs.color); - break; - case WinCondition.AkujoSoloWin: - textRenderer.text = "AkujoSoloWin".Translate(); - textRenderer.color = Akujo.color; - __instance.BackgroundBar.material.SetColor("_Color", Akujo.color); - break; - case WinCondition.AkujoTeamWin: - textRenderer.text = "AkujoTeamWin".Translate(); - textRenderer.color = Akujo.color; - __instance.BackgroundBar.material.SetColor("_Color", Akujo.color); - break; - case WinCondition.MiniLose: - textRenderer.text = "MiniLose".Translate(); - textRenderer.color = Mini.color; - break; + textRenderer.text = winText.Item2.Translate(); + textRenderer.color = winText.Item1; + __instance.BackgroundBar.material.SetColor("_Color", winText.Item1); } var winConditionsTexts = new List(); @@ -654,26 +555,22 @@ public static void Postfix(EndGameManager __instance) var survivorAlive = false; foreach (var cond in AdditionalTempData.additionalWinConditions) { - switch (cond) + if (winConditionMappings.TryGetValue(cond, out var mapping)) { - case WinCondition.AdditionalLawyerStolenWin: - winConditionsTexts.Add(cs(Lawyer.color, "LawyerStolenWin".Translate())); - break; - case WinCondition.AdditionalLawyerBonusWin: - winConditionsTexts.Add(cs(Lawyer.color, "LawyerBonusWin".Translate())); - break; - case WinCondition.AdditionalPartTimerWin: - winConditionsTexts.Add(cs(PartTimer.color, "PartTimerWin".Translate())); - break; - case WinCondition.AdditionalAlivePursuerWin: + if (cond == WinCondition.AdditionalAlivePursuerWin) + { pursuerAlive = true; - break; - case WinCondition.AdditionalAliveSurvivorWin: + } + else if (cond == WinCondition.AdditionalAliveSurvivorWin) + { survivorAlive = true; - break; + } + else + { + winConditionsTexts.Add(cs(mapping.Item1, mapping.Item2.Translate())); + } } } - if (pursuerAlive && survivorAlive) { winConditionsTexts.Add($"{cs(Pursuer.color, "起诉人")} & {cs(Survivor.color, "幸存者存活")}"); @@ -709,9 +606,7 @@ public static void Postfix(EndGameManager __instance) roleSummaryText.AppendLine("游戏总结:"); foreach (var data in AdditionalTempData.playerRoles) { - //var roles = string.Join(" ", data.Roles.Select(x => Helpers.cs(x.color, x.name))); var roles = data.RoleNames; - //if (data.IsGuesser) roles += " (Guesser)"; var taskInfo = data.TasksTotal > 0 ? $" - ({data.TasksCompleted}/{data.TasksTotal})" : ""; @@ -1051,7 +946,7 @@ private static bool CheckAndEndGameForImpostorWin(ShipStatus __instance, PlayerS { //__instance.enabled = false; GameOverReason endReason; - switch (TempData.LastDeathReason) + switch (GameData.LastDeathReason) { case DeathReason.Exile: endReason = GameOverReason.ImpostorByVote; @@ -1102,7 +997,7 @@ internal class RPCEndGamePatch { public static void Postfix(ref GameOverReason endReason) { - Message($"游戏结束 {(CustomGameOverReason)endReason}", "RpcEndGame"); + Message($"游戏结束 {(CustomGameOverReason)endReason} {endReason}", "RpcEndGame"); } } @@ -1131,7 +1026,7 @@ public PlayerStatistics(ShipStatus __instance) public int TeamJuggernautAlive { get; set; } public bool TeamJuggernautHasAliveLover { get; set; } - private static bool isLover(GameData.PlayerInfo p) + private static 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 9f5c286c..e964ea02 100644 --- a/TheOtherRoles/Patches/ExileControllerPatch.cs +++ b/TheOtherRoles/Patches/ExileControllerPatch.cs @@ -18,27 +18,28 @@ namespace TheOtherRoles.Patches; [HarmonyPriority(Priority.First)] internal class ExileControllerBeginPatch { - public static GameData.PlayerInfo lastExiled; + public static NetworkedPlayerInfo lastExiled; public static TextMeshPro confirmImpostorSecondText; private static bool IsSec; - public static bool Prefix(ExileController __instance, [HarmonyArgument(0)] ref GameData.PlayerInfo exiled, [HarmonyArgument(1)] bool tie) + public static bool Prefix(ExileController __instance, [HarmonyArgument(0)] ref ExileController.InitProperties init) { - lastExiled = exiled; - Message($"开始放逐: {exiled?.PlayerName ?? "null"}"); + lastExiled = init?.networkedPlayer; + var exiled = init?.networkedPlayer; + Message($"开始放逐: {init?.networkedPlayer?.PlayerName ?? "null"}"); if (Balancer.currentAbilityUser != null && Balancer.IsDoubleExile && !IsSec) { IsSec = true; - __instance.exiled = null; + __instance.initData.networkedPlayer = null; ExileController controller = Object.Instantiate(__instance, __instance.transform.parent); - controller.exiled = Balancer.targetplayerright.Data; - controller.Begin(controller.exiled, false); + controller.initData.networkedPlayer = Balancer.targetplayerright.Data; + controller.Begin(controller.initData); IsSec = false; controller.completeString = string.Empty; controller.Text.gameObject.SetActive(false); - controller.Player.UpdateFromEitherPlayerDataOrCache(controller.exiled, PlayerOutfitType.Default, PlayerMaterial.MaskType.Exile, includePet: false); + controller.Player.UpdateFromEitherPlayerDataOrCache(controller.initData.networkedPlayer, PlayerOutfitType.Default, PlayerMaterial.MaskType.Exile, includePet: false); controller.Player.ToggleName(active: false); - SkinViewData skin = ShipStatus.Instance.CosmeticsCache.GetSkin(controller.exiled.Outfits[PlayerOutfitType.Default].SkinId); + SkinViewData skin = ShipStatus.Instance.CosmeticsCache.GetSkin(controller.initData.networkedPlayer.Outfits[PlayerOutfitType.Default].SkinId); controller.Player.FixSkinSprite(skin.EjectFrame); AudioClip sound = null; if (controller.EjectSound != null) @@ -56,9 +57,10 @@ void createlate(int index) createlate(i); } _ = new LateTask(() => { controller.StopAllCoroutines(); controller.EjectSound = sound; controller.StartCoroutine(controller.Animate()); }, 0.6f); + ExileController.Instance = __instance; - __instance.exiled = Balancer.targetplayerleft.Data; - exiled = __instance.exiled; + init = GenerateExileInitProperties(Balancer.targetplayerleft.Data, false); + if (isFungle) { Helpers.SetActiveAllObject(controller.gameObject.GetChildren(), "RaftAnimation", false); @@ -168,7 +170,7 @@ public static void Postfix(ExileController __instance) confirmImpostorSecondText.text = changeStringBuilder.ToString(); confirmImpostorSecondText.gameObject.SetActive(true); - if (Balancer.currentAbilityUser != null && Balancer.IsDoubleExile && __instance.exiled?.PlayerId == Balancer.targetplayerleft.PlayerId) + if (Balancer.currentAbilityUser != null && Balancer.IsDoubleExile && __instance?.initData?.networkedPlayer?.PlayerId == Balancer.targetplayerleft?.PlayerId) { __instance.completeString = GetString("二者一同放逐"); } @@ -212,7 +214,7 @@ public static void Prefix(GameObject obj) } } - private static void WrapUpPostfix(GameData.PlayerInfo exiled) + private static void WrapUpPostfix(NetworkedPlayerInfo exiled) { Message("WrapUp"); if (CachedPlayer.LocalPlayer.IsDead) CanSeeRoleInfo = true; @@ -262,7 +264,7 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) } Witness.target = Witness.killerTarget = null; - if (Vortox.Player.IsAlive()) + if (Vortox.Player.IsAlive() && exiled == null) { Vortox.skipCount++; if (Vortox.skipCount == Vortox.skipMeetingNum) Vortox.triggerImpWin = true; @@ -515,7 +517,7 @@ private class BaseExileControllerPatch public static void Postfix(ExileController __instance) { Message("ExileController.WrapUp", "WrapUpPostfix"); - WrapUpPostfix(__instance.exiled); + WrapUpPostfix(__instance.initData?.networkedPlayer); } } @@ -525,7 +527,7 @@ private class AirshipExileControllerPatch public static void Postfix(AirshipExileController __instance) { Message("AirshipExileController.WrapUpAndSpawn", "WrapUpPostfix"); - WrapUpPostfix(__instance.exiled); + WrapUpPostfix(__instance.initData?.networkedPlayer); } public static bool Prefix(AirshipExileController __instance) @@ -533,14 +535,14 @@ public static bool Prefix(AirshipExileController __instance) if (Balancer.currentAbilityUser != null && Balancer.IsDoubleExile && __instance != ExileController.Instance) { - if (__instance.exiled != null) + if (__instance.initData?.networkedPlayer != null) { - PlayerControl @object = __instance.exiled.Object; + PlayerControl @object = __instance.initData?.networkedPlayer.Object; if (@object) { @object.Exiled(); } - __instance.exiled.IsDead = true; + __instance.initData.networkedPlayer.IsDead = true; } Object.Destroy(__instance.gameObject); } @@ -568,9 +570,9 @@ private static void Postfix(ref string __result, [HarmonyArgument(0)] StringName { try { - if (ExileController.Instance != null && ExileController.Instance.exiled != null) + if (ExileController.Instance != null && ExileController.Instance.initData.networkedPlayer != null) { - var player = playerById(ExileController.Instance.exiled.Object.PlayerId); + var player = playerById(ExileController.Instance.initData.networkedPlayer.Object.PlayerId); if (player == null) return; // Exile role text if (id is StringNames.ExileTextPN or StringNames.ExileTextSN or StringNames.ExileTextPP or StringNames.ExileTextSP) diff --git a/TheOtherRoles/Patches/GameStartManagerPatch.cs b/TheOtherRoles/Patches/GameStartManagerPatch.cs index f16ec3e6..ef32bf32 100644 --- a/TheOtherRoles/Patches/GameStartManagerPatch.cs +++ b/TheOtherRoles/Patches/GameStartManagerPatch.cs @@ -25,6 +25,7 @@ public static void Postfix(AmongUsClient __instance) { shareGameVersion(); } + GameStartManagerUpdatePatch.sendGamemode = true; } } @@ -33,8 +34,9 @@ public static class ConstantsPatch { public static void Postfix(ref int __result) { - if (AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame) - __result += 25; + if (!Main.ForceUsePlus25Protocol.Value) return; + if (AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame) __result += 25; + Message("强制使用 +25 协议", "NetworkModes"); } } @@ -64,6 +66,7 @@ public class GameStartManagerUpdatePatch private static bool update; private static string currentText = ""; private static GameObject copiedStartButton; + public static bool sendGamemode = true; public static void Prefix(GameStartManager __instance) { @@ -124,14 +127,20 @@ public static void Postfix(GameStartManager __instance) { 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(FastDestroyableSingleton.Instance.GetString(StringNames.GameStarting).Replace("{0}", "")) && CustomOptionHolder.anyPlayerCanStopStart.GetBool()) + { + __instance.GameStartText.text = string.Empty; + __instance.GameStartTextParent.SetActive(false); + } } if (__instance.startState != GameStartManager.StartingStates.Countdown) @@ -147,11 +156,10 @@ public static void Postfix(GameStartManager __instance) // Activate Stop-Button copiedStartButton = UnityEngine.Object.Instantiate(__instance.StartButton.gameObject, __instance.StartButton.gameObject.transform.parent); copiedStartButton.transform.localPosition = __instance.StartButton.transform.localPosition; - copiedStartButton.GetComponent().sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.StopClean.png", 180f); copiedStartButton.SetActive(true); var startButtonText = copiedStartButton.GetComponentInChildren(); - startButtonText.text = GetString("stopGameStartText"); - startButtonText.fontSize *= 0.62f; + startButtonText.text = ""; + startButtonText.fontSize *= 0.68f; startButtonText.fontSizeMax = startButtonText.fontSize; startButtonText.gameObject.transform.localPosition = Vector3.zero; PassiveButton startButtonPassiveButton = copiedStartButton.GetComponent(); @@ -165,11 +173,9 @@ void StopStartFunc() startButtonPassiveButton.OnClick.AddListener((Action)(() => StopStartFunc())); __instance.StartCoroutine(Effects.Lerp(.1f, new 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 @@ -186,19 +192,26 @@ void StopStartFunc() } __instance.GameStartText.text = $"{string.Format(GetString("errorHostNoVersion"), Math.Round(10 - kickingTimer))}"; - __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 = $"{GetString("errorDifferentVersion")}\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; + __instance.GameStartText.transform.localPosition = Vector3.zero; + __instance.GameStartText.transform.localScale = new Vector3(1.2f, 1.2f, 1f); if (!__instance.GameStartText.text.StartsWith(FastDestroyableSingleton.Instance.GetString(StringNames.GameStarting).Replace("{0}", ""))) { __instance.GameStartText.text = string.Empty; + __instance.GameStartTextParent.SetActive(false); } } @@ -210,10 +223,9 @@ void StopStartFunc() // Activate Stop-Button copiedStartButton = UnityEngine.Object.Instantiate(__instance.StartButton.gameObject, __instance.StartButton.gameObject.transform.parent); copiedStartButton.transform.localPosition = __instance.StartButton.transform.localPosition; - copiedStartButton.GetComponent().sprite = UnityHelper.loadSpriteFromResources("TheOtherRoles.Resources.StopClean.png", 180f); copiedStartButton.SetActive(true); var startButtonText = copiedStartButton.GetComponentInChildren(); - startButtonText.text = "STOP"; + startButtonText.text = ""; startButtonText.fontSize *= 0.62f; startButtonText.fontSizeMax = startButtonText.fontSize; startButtonText.gameObject.transform.localPosition = Vector3.zero; @@ -221,8 +233,7 @@ void StopStartFunc() void StopStartFunc() { - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, - (byte)CustomRPC.StopStart, SendOption.Reliable, AmongUsClient.Instance.HostId); + var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.StopStart, SendOption.Reliable, AmongUsClient.Instance.HostId); writer.Write(PlayerControl.LocalPlayer.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); copiedStartButton.Destroy(); @@ -232,12 +243,9 @@ void StopStartFunc() startButtonPassiveButton.OnClick.AddListener((Action)(() => StopStartFunc())); __instance.StartCoroutine(Effects.Lerp(.1f, new Action((p) => { - startButtonText.text = "STOP"; + startButtonText.text = ""; }))); - } - if (__instance.GameStartText.text.StartsWith(FastDestroyableSingleton.Instance.GetString(StringNames.GameStarting).Replace("{0}", "")) && CustomOptionHolder.anyPlayerCanStopStart.GetBool()) - __instance.GameStartText.transform.localPosition = __instance.StartButton.transform.localPosition + Vector3.up * 0.6f; } // Start Timer @@ -246,7 +254,7 @@ void StopStartFunc() 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; @@ -255,16 +263,16 @@ 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) { var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.ShareGameMode, SendOption.Reliable, -1); writer.Write((byte)ModOption.gameMode); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.shareGameMode((byte)ModOption.gameMode); + sendGamemode = false; } } } @@ -303,6 +311,7 @@ public static bool Prefix(GameStartManager __instance) break; } } + if (CustomOptionHolder.dynamicMap.GetBool() && continueStart) { // 0 = Skeld diff --git a/TheOtherRoles/Patches/GetStringPatch.cs b/TheOtherRoles/Patches/GetStringPatch.cs new file mode 100644 index 00000000..a8a21949 --- /dev/null +++ b/TheOtherRoles/Patches/GetStringPatch.cs @@ -0,0 +1,24 @@ +using System.Linq; + +namespace TheOtherRoles.Patches; + +[HarmonyPatch] +public class GetStringPatch +{ + [HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), [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/LobbyBehaviourPatch.cs b/TheOtherRoles/Patches/LobbyBehaviourPatch.cs new file mode 100644 index 00000000..129ca039 --- /dev/null +++ b/TheOtherRoles/Patches/LobbyBehaviourPatch.cs @@ -0,0 +1,27 @@ +namespace TheOtherRoles.Patches; + +[HarmonyPatch(typeof(LobbyBehaviour))] +public class LobbyBehaviourPatch +{ + public static int Frame; + + [HarmonyPatch(nameof(LobbyBehaviour.FixedUpdate)), HarmonyPostfix] + public static void UpdatePostfix(LobbyBehaviour __instance) + { + if (--Frame <= 0) + { + ISoundPlayer MapThemeSound = SoundManager.Instance.soundPlayers.Find(x => x.Name.Equals("MapTheme")); + if (ModOption.MuteLobbyBGM) + { + if (MapThemeSound == null) return; + SoundManager.Instance.StopNamedSound("MapTheme"); + } + else + { + if (MapThemeSound != null) return; + SoundManager.Instance.CrossFadeSound("MapTheme", __instance.MapTheme, 0.5f); + } + Frame = 15; + } + } +} \ No newline at end of file diff --git a/TheOtherRoles/Patches/LobbyRoleList.cs b/TheOtherRoles/Patches/LobbyRoleList.cs index 96ada38f..d40e4cd1 100644 --- a/TheOtherRoles/Patches/LobbyRoleList.cs +++ b/TheOtherRoles/Patches/LobbyRoleList.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using TheOtherRoles.Buttons; using TMPro; @@ -14,22 +14,6 @@ public static class LobbyRoleInfo private static TextMeshPro infoButtonText; private static TextMeshPro infoTitleText; - [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] - public static class RoleSummaryButtonHudUpdate - { - public static void Postfix(HudManager __instance) - { - if (!LobbyBehaviour.Instance || AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started) return; - try - { - //if (HudManagerStartPatch.roleSummaryButton == null) HudManagerStartPatch.createRoleSummaryButton(__instance); - if (HudManagerStartPatch.roleSummaryButton.Timer > 0f) HudManagerStartPatch.roleSummaryButton.Timer = 0f; - HudManagerStartPatch.roleSummaryButton.Update(); - } - catch { } - } - } - public static void RoleSummaryOnClick() { if (RolesSummaryUI != null) return; diff --git a/TheOtherRoles/Patches/MeetingHudPatch.cs b/TheOtherRoles/Patches/MeetingHudPatch.cs index c8e21168..92409a3f 100644 --- a/TheOtherRoles/Patches/MeetingHudPatch.cs +++ b/TheOtherRoles/Patches/MeetingHudPatch.cs @@ -20,7 +20,7 @@ internal class MeetingHudPatch { private static bool[] selections; private static SpriteRenderer[] renderers; - private static GameData.PlayerInfo target; + private static NetworkedPlayerInfo target; private static PassiveButton[] swapperButtonList; private static TextMeshPro meetingExtraButtonLabel; public static GameObject MeetingExtraButton; @@ -506,7 +506,7 @@ private static bool Prefix(MeetingHud __instance) [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.BloopAVoteIcon))] private 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 = Object.Instantiate(__instance.PlayerVotePrefab); var showVoteColors = !GameManager.Instance.LogicOptions.GetAnonymousVotes() || shouldShowGhostInfo() || @@ -661,7 +661,7 @@ private static bool Prefix(MeetingHud __instance, Il2CppStructArray private class MeetingHudVotingCompletedPatch { private static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte[] states, - [HarmonyArgument(1)] GameData.PlayerInfo exiled, [HarmonyArgument(2)] bool tie) + [HarmonyArgument(1)] NetworkedPlayerInfo exiled, [HarmonyArgument(2)] bool tie) { // Reset swapper values Swapper.playerId1 = byte.MaxValue; @@ -696,7 +696,7 @@ private static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte[] s private static void Prefix(MeetingHud __instance, [HarmonyArgument(0)] Il2CppStructArray states, - [HarmonyArgument(1)] GameData.PlayerInfo exiled, + [HarmonyArgument(1)] NetworkedPlayerInfo exiled, [HarmonyArgument(2)] bool tie) { if (tie && Balancer.currentAbilityUser != null) @@ -738,7 +738,7 @@ private static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] MessageR [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.StartMeeting))] private class StartMeetingPatch { - public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameData.PlayerInfo meetingTarget) + public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] NetworkedPlayerInfo meetingTarget) { var roomTracker = FastDestroyableSingleton.Instance.roomTracker; var roomId = byte.MinValue; diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index 131cf4d7..c0db3ce6 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -1962,7 +1962,7 @@ public static bool Prefix(PlayerControl __instance) return true; } - private static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] GameData.PlayerInfo target) + private static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] NetworkedPlayerInfo target) { Message($"报告玩家 {__instance.Data.PlayerName} 被报告尸体 {target?.PlayerName}", "CmdReportDeadBody"); // Medic or Detective report @@ -1984,8 +1984,8 @@ private static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] GameD float timer = (float)Math.Round(timeSinceDeath / 1000); if (Vortox.Reversal) { - timer += rnd.Next(-2, 3); - if (timer < 0) timer = 1; + timer += rnd.Next(-3, 4); + timer = Math.Max(0, timer); } if (isMedicReport) { diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index 9df7ec89..68df4dc0 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using AmongUs.GameOptions; @@ -11,7 +11,7 @@ namespace TheOtherRoles.Patches; -[HarmonyPatch(typeof(RoleOptionsCollectionV07), nameof(RoleOptionsCollectionV07.GetNumPerGame))] +[HarmonyPatch(typeof(RoleOptionsCollectionV08), nameof(RoleOptionsCollectionV08.GetNumPerGame))] internal class RoleOptionsDataGetNumPerGamePatch { public static void Postfix(ref int __result) @@ -56,7 +56,7 @@ internal class RoleManagerSelectRolesPatch public static void Postfix() { - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ResetVaribles, SendOption.Reliable); AmongUsClient.Instance.FinishRpcImmediately(writer); RPCProcedure.resetVariables(); @@ -447,7 +447,7 @@ private static void assignRoleTargets(RoleAssignmentData data) if (possibleTargets.Count == 0) { - var w = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var w = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LawyerPromotesToPursuer, SendOption.Reliable); AmongUsClient.Instance.FinishRpcImmediately(w); Lawyer.PromotesToPursuer(); @@ -455,7 +455,7 @@ private static void assignRoleTargets(RoleAssignmentData data) else { var target = possibleTargets[rnd.Next(0, possibleTargets.Count)]; - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.LawyerSetTarget, SendOption.Reliable); writer.Write(target.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -475,7 +475,7 @@ private static void assignRoleTargets(RoleAssignmentData data) if (possibleTargets.Count == 0) { - var w = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var w = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ExecutionerPromotesRole, SendOption.Reliable); AmongUsClient.Instance.FinishRpcImmediately(w); Executioner.PromotesRole(); @@ -483,7 +483,7 @@ private static void assignRoleTargets(RoleAssignmentData data) else { var target = possibleTargets[rnd.Next(0, possibleTargets.Count)]; - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ExecutionerSetTarget, SendOption.Reliable); writer.Write(target.PlayerId); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -678,7 +678,7 @@ private static void assignGuesserGamemodeToPlayers(List playerLis playerList.Remove(player2); } - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetGuesserGm, SendOption.Reliable); writer.Write(playerId); AmongUsClient.Instance.FinishRpcImmediately(writer); @@ -694,7 +694,7 @@ private static byte setRoleToRandomPlayer(byte roleId, List playe playerRoleMap.Add(new Tuple(playerId, roleId)); - var writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetRole, SendOption.Reliable); writer.Write(roleId); writer.Write(playerId); @@ -710,7 +710,7 @@ private static byte setModifierToRandomPlayer(byte modifierId, List 0) { - hand.SetPlayerColor(Morphling.morphTarget.CurrentOutfit, PlayerMaterial.MaskType.None); + hand.SetPlayerColor(Morphling.morphTarget.CurrentOutfit, PlayerMaterial.MaskType.None, 1); // Also set hat color, cause the line destroys it... player.RawSetHat(Morphling.morphTarget.Data.DefaultOutfit.HatId, Morphling.morphTarget.Data.DefaultOutfit.ColorId); } else { - hand.SetPlayerColor(player.CurrentOutfit, PlayerMaterial.MaskType.None); + hand.SetPlayerColor(player.CurrentOutfit, PlayerMaterial.MaskType.None, 1); } } else diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 75c1a495..8264bb78 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -18,7 +18,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, + 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; @@ -452,7 +452,7 @@ private 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, + 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; diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index d38d5f8d..46145f32 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -141,7 +141,7 @@ public enum RoleId public enum CustomRPC { // Main Controls - ResetVaribles = 80, + ResetVaribles = 100, ShareOptions, WorkaroundSetRoles, SetRole, @@ -155,10 +155,10 @@ public enum CustomRPC DynamicMapOption, SetGameStarting, StopStart, - ShareGameMode = 95, + ShareGameMode = 120, // Role functionality - FixLights = 100, + FixLights = 121, FixSubmergedOxygen, CleanBody, DissectionBody, @@ -321,7 +321,7 @@ public static void HandleShareOptions(byte numberOfOptions, MessageReader reader var optionId = reader.ReadPackedUInt32(); var selection = reader.ReadPackedUInt32(); var option = CustomOption.options.First(option => option.id == (int)optionId); - option.updateSelection((int)selection); + option.updateSelection((int)selection, i == numberOfOptions - 1); } } catch (Exception e) @@ -333,6 +333,13 @@ public static void HandleShareOptions(byte numberOfOptions, MessageReader reader public static void shareGameMode(byte gm) { gameMode = (CustomGamemodes)gm; + try + { + LobbyViewSettingsPatch.currentButtons?.ForEach(x => x.gameObject?.Destroy()); + LobbyViewSettingsPatch.currentButtons?.Clear(); + LobbyViewSettingsPatch.currentButtonTypes?.Clear(); + } + catch { } } public static void stopStart(byte playerId) @@ -584,7 +591,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); } } } @@ -2129,7 +2136,7 @@ private static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) if (!RpcNames!.ContainsKey(packetId)) return true; - if (DebugMode && callId != 95) Info($"接收 PlayerControl CustomRpc RpcId{callId} Rpc {RpcNames?[(CustomRPC)callId] ?? nameof(packetId)} Message Size {reader.Length}"); + if (DebugMode && callId != 120) Info($"接收 PlayerControl CustomRpc RpcId{callId} Rpc {RpcNames?[(CustomRPC)callId] ?? nameof(packetId)} Message Size {reader.Length}"); switch (packetId) { // Main Controls diff --git a/TheOtherRoles/Resources/Copy.png b/TheOtherRoles/Resources/Copy.png new file mode 100644 index 0000000000000000000000000000000000000000..1db34bbf70cef738ff92b5ff32d2eebdeaa7f8ce GIT binary patch literal 17161 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 literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/CopyPasteBG.png b/TheOtherRoles/Resources/CopyPasteBG.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f47cce48e9404ef115793e5d92db858d0bc9ea GIT binary patch literal 13064 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 FzX7Z8dvpK* literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/Minus_ButtonActive.png b/TheOtherRoles/Resources/Minus_ButtonActive.png new file mode 100644 index 0000000000000000000000000000000000000000..2cd4b5a09b5ffa4dc6f2f5f95c4b4dd9ab4d43e4 GIT binary patch literal 6897 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 literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/PasteActive.png b/TheOtherRoles/Resources/PasteActive.png new file mode 100644 index 0000000000000000000000000000000000000000..b80d73bf80b46baf6dcceb2d2c59a0e1687b1e7c GIT binary patch literal 14227 zcmeHuWmH_-)+O!`2=0Xwpm28&?k+(K*P;mS?(QDk-Q6L$2ZD#7ArK%qNt4|B?z^x1 z>#zHb(f#k$7*%!l-gC{h_S|djQ)ir05h_Zr(NTy{prD}8Wo0DQp1*aU-%3cZ&!651 zay?K`WKo_PIuJDzH-Hn^(Zbpe1b}!rfdC+PYYQkS_qFOQYp_9UOYu)L94@%4DW_TK zMKqh+??8a8e8b)e{#hh<(xgHz>=z3zsQE8HZ~Wr!L>?Kd-Lcin+dtdg;p^M=TuL;b z8TD@E#N0eQrL7%s-CSPMew{(hErp5OdD6Q)cru#lJVWgYn^rywLtVP_FnN3wkIFk) zF=D=ISDg(P6sejCSvwH#@5Ns~fO%4!*w>nfQzytH^#1W9B;aRE&y-KC{l%zGY0d2ib{U4c?uESI_j2bVV7Fcxe z-jCPHBHwino)69RPj1Ea`fL_&A#SZ>{&YHE6%o11%iG$lHY&aR{*$jV)8#tLFfJp0 zf2OFXu#nvS6JT%Whwgsmx!>*qxR=OiNu@g}nML4q+qPq0(3+3A<8z0A!`A2#twgl% z!$9Fp()wXLQKX|Uf~}0jVwyltFdm-nrAgvuU*iuirmvf=8y^+5+rNRk76h30HBh9t zeh?e^bALrcTQNZsH$=o6(5mplT8gzfjv&yNFV~ zClIIQTRPc%RCK=S7QVaTOqZg38KWtqh?-*{#ht{ z9Q(0Vq4ImnkqnDmkQT?sFB7$OeGw_zx~|Pjtsj%;V+BsTCTcoQed(LAl?0FW)Rlxz zug|vp*-Zu@kgj9<`mVKc%$iU09et8hxJf15MMr{*0LsJX zC4)OXi=w$8&<6IjRX)R)R6l!*ZhHTdb5HD)dn)B-IQ^iEb7}$HjNkX6ioi&8rCrlYmFLQxsvEoiGTE8piQ)H_QxiXp%$9^k=}FQlkqi-9 zpv!wK!P;^bLSqiU@*uV*5Jb`*rD$@ZZm}~wuoVb2?h7{6e^GfYlX=V^aO3!?-$Ot> z<892+id{eYt??j2w>!@OY0PPt^zjBt2C^M>K&ca|CW(BBW!V=&RY80FZ6x9Mla}g2 zA@w1KcPSoC!%#sJo%dF5S2-dVQ%fFrW`@PpTnhX?+77L>=t(XWCM-N-41R;f83BnT zqompsow!eud>fYU9Uv^tXkr!)b#exv$t0NK6}o5{^RUf_UC+XbI=c4-{sTvn_cqCR z^!Ht!>lSyj(@b7N%Pxi)Jv1YH(^#h9WMo`dMv2Um7jZ!_T#^Hyp$lI&?rSMpVgO8O zc}nqx4kU>x$lp3%fCEo#A+$-6CmC>8+Eyh#OS>~}$4y$VR%e996<0kJzX}LOVC_Rm z6!>H5!lknt+NC>ujF8(6ZHfDEgmlY4m8(_G*z9?|S$VNno+0CCN}lNeN9Jn$`Ia@4 z$49zVJvm!-2U?pmIj)G40<~)q%9EM#k;A3lFf&nQy84@3V~V6QXCvYFwI8>nNgG|W zO6lv&Z5#7NjtuCTnYJ2Y0`T8?>5AtxByhMR5HJ%W%MvIFVW_JGOVra?-|;ORn$>u; z2k_3Py4I>|>M97|v|U64XT43PKZOx$*wK~=me=zB>_AoA9Qf*?!j&W)S&IK2F*NR6 zlBPYEHmfE3LumnF0KwNe>2;U^aghZ_h=^>wsAq}-8%$-EKDEEAHe%hf5dDDJgVOLG ztwC;gY|`rw5I%U#7G+Tmk7!N3*wO*$+p2tHYOWligmqQll*&bJG}72$DzP9U9=SAm>6n;6ZyzkG-yd&l9eJ@Yvv>2ffB;e2pa4| zohL8Hi@pc{J-rI$JP8Ocoq2<$8aB}7gkSceG*6l9!m%qR;|XN z-xCuFbdR#rW9|?G+ha0mwT|~7xbk~9eqAa|CZaI;%kT2jJXzh4KB({#EfT+cs;%Vf z_%uK5kbKI2b8IGsBWh)Qw#5Rw@WVSJh89Yw+>Rdh355v6fR*W*BD{m1QYl5$jVs^B z;e_wlp};F4D0VKn7VBBF=%ZBMLSRABvrNZ|1;=Mf6Bro1De7Bp&Az#NxyqI$EzC2e zYL;m&rh7H8r*xPZFPm;7yl`D_xdq7D*!WmSs4y5r(2|P_ajufVq>LjwjLg* zp9T3yGzYx`JGg5y2q?+;J@L%GOtDv=8O~3sj_F&l3I~mB!$pCeOh#|IQ;2_fAa%~V zT0^x}sGngY84Rn&?O4}}G%oJZ3{;eZ_+rs6_T=6;f=nCQ76Q*^>^x|QQw$A ztnaE;6JYEQ*`sTQY=WiR`c)>Mob{t2L#zr!p2Q`Y7c z<*meH7e23=!Iif7b(QO?rQeoS&;EQ2%9W$Bx`rLXy0X6*)>G5>OpaahbcOiVjLsX4 zxeW9b4diK{=G?N8+}I->+X&LIKGE5jo8F*0*dXWF2ub4Nbx$mxk)1?c22!|Ic_)r< z5$5+3DlE#MCsBE63gj^1{xs|0BR6Ud)R#9L^z@Da&6655akB}hdSpQ>k&lRTl3Tn% z7yBiRtax*kkQ&8Y0+ET2e)MVD=P7YyWLNf5Di#5Tx#B8n#__W z*9QhortVmT<{_JikB3W=6N#|ulP^ACqc^fa76&`#Z2FBIHzc||Lu5P5g+d!-ihU!| z>O>pj&e-MsPM|Mmrr0LXSGKau2D8$>FOnT&Ty9yta1Fc5YZ*QK`XNhw5oZ0x)n;@S zcJ-LTU2QTn0ZGxTw={-bQ>ue#-A;UJXBlRp9THt)wy=vM-Iy038S;08*v%Z$Fi7IS zhi$6{65;#ms~?A9VWd>*;6)m|GD)`uL9|v zQ{M^9o_8fVNlw+;b~(X(crlv-T2g}425>Ynv^t!q355Y8x|6s!^u>DRe0SsX_e&9O zeGAzFsXV5@VxuD-Ej5;!35QL2WhVZlKzzSZC;E>(F*DTboccMp?a+6#hiqpCJ11ux zRr0p^iB3%Qg-eXpp@qn(W(e~=b?GxS*go0~=88p8SkdTiE(obTDul0K0?T+KYdc9< z;vScfTG7!YW;k>FxeP&Y2sbzTw7c)ZYTr-lLFAs;^sDAUw$8SBuBjm zEF$u0hf$2a91y4d)ahqMI&Xu44(GEY9XC%1cBZaLJ0;*`_u8DJ`Brn#pqGBvB{S2T zb{3UM)FN6q10~$x=^NL*JTpt}>g8k4me+R|flps=HsUi#g-BKq=F#9w5dvU9kJKuB zciatSNY}sN_H<}i)VMq%$p0`BKToZUyh+00`XUwn{N*CUXB(|AmP2{lDtXQH$9?yQ zCgmgVtaY*|^qmAT#lGIZlLBC?IPWQ1eK+BF zGE_v%7}q?xAp$5C#u1AID1Jg+DOFwH3t7)Js)^HL5pw#ovfrX9xvOTSUJNZnfA;G# zzEt$@QLzpoK$im|!cBMKgMai(s?cmQVrtc}88oH~4)Kv7)~EUyW^N}ap$>BWkQ9)S@iW{oxX@^0bk(L6F>a_XCfV{sc>d1w3)O-K>-n34P< z>~JutO6j-7oON1sST0KSpE93I@i#BcRAw7%^514Ef1CV~dStw_Z!Tjl+=HVpKXX$k zzf;5LqDS$~_m$YWaMXkc?3{p3}np@XB{Oi4GI` zPu-p(?+R7Zrf$t4fz`wBbFX{mPsZIGFHa^VWD1z$G?p{3z^tl~#6UEL?O_Ys;qQBu zX_mG5&^Ckwp03H+$Eg?sIAdikTNyv+i?6IAD?mpUHf2TEhLcNDm$hk&ZyKN0ZFbEg z7&Au}zwOE2pI!vq{A}~a%-@w@3tMOPB|M!Z_D56P9aKDWUU*})zW9Y@{VK|ct(S|5 zT>5^+9+fUbUM?;P(;u4`8u&m)C~)Kmi+B2-m$~t=jWkFp-3^+%OySzlSE?RpO;7Tn z1n}|A;ZKrcXpUGs7JHf$2i#KZk0*mOFk5pY&R?0|8YM=MnofANhEBcqSH*KIaJatk z?ylIKKvyMjw1526w?&zo`Xe}AMGIA#c=NMJNWQPuhVM_k5AEE*K4^pjLnaQtwu#PY z!Kh{C{G3Lk^X5arU`-`ojr((EG$ktFQ}Cx5maYS0q(>jKiW4^z1lj{pOH0~_;4es$ zPKEcB_8*pSh9KXsYJLor7g8rN#ixek$xe3@#%X-JC{smYdmwE>4k7p!t;l&3*7M-> zsWp*PS?&$Z-I>smBiU3KA+RNId6_5ze&$;nYIPLR%^JJt=Jx=V5%e9hEFm@lYOq_I znEgYNBuA5lI(Ys^*fKu$ZtVhYZlc^&B}Gp0%h#=4C`~1rWeca^%a5>ciP4YMIUK6B zx}Mu(YIob2$ox>Tt zP@%l3HbCu$6Q;oqN=8|8%l!KkcQ_j@*bOCL^o?Fx<2P;|(>Y$Jofq*}Cy}J2XwvZg zm3c1L9?GV;xlD(J*n)b=lX6L}vnb!b*yj`mu@~;w#+pzDUxhPO8|Uo0#QmF~~e zvah!w<|hej)RE~`4;)nkAk8n!b)#J@qo8@7^mlioE-1Sq_8qzOlCm5&b+T3xl;c8g zE)^AUx2F4Bt<=m69l>H6Z!W?e7(%43ZaMX0`rAc44eTpn$t=t}I(bo{IwP1DoCEPj z?f6N=?VF&a7vd9243BZPD%)6W9!!ALZmF+q`U|#A_zGO;aF6QigK5&X2hc?Z=bXfS$GD zV^UDO`$XP)D&6jta;tXGoV$7IO4xZsfcK>U8(L;*FL-tERT^w=VBk9i+RXYV54%Kf zDI(af!3Gr8ghtyBO1dKGAIAPWpAg@gC7{LVty%R0P9B^W?l;TOM&eP`6SG zLR*-=Uu&gje5D8KDE;yYqW0rrY-9|ot1#DPQSMwwPN^GCG zanmJ+05|Tbi(yoFX7py{G38L&?uLyE=P{CtX|*v5$y0tap|WE)tU3jnsO(wv!>?V^d?Cf1qrL{ z>({^KPMEr6Q&JF~_xY(-tgvXO2g1!kbF_A?tFXM-u9%AOLW_qt7JtCN+$Aa{;y9aN zJTlI7b`oM<#v_&2RZg&9$+oTZtdn>%QWI(ZjnN+#1F>h^2i1fJs`};Knkg5tYsfN_ z6k>sv8PZa?TLhTO<`NZ^QnQgh8qnMF{sLEH33vdMccq)4&1V*AEX85A3d?*&4}0 zHUUy}6LdU+o9hd6t}o}X3#2NlUT>Z0K`f%ngwp~T^7k(&n@eOQERb?^5!hB%2UMer zYY#KGVKsM}z>3vkNrbPU-DpO3FwYb`E)D8nyXK|Ui*jYkVpq3K1%WWZAS3IxcP`(~>s!Rm_B_2(hVH*~QT`T<04Ki# zuPFPLXbeEwnsvw=wPC!;$fd&+`dLA0PMVN_MxbXfY3E@gkh_sOv}#2aDb*U7OCniv+8QlS0b8GN6pw zWv!BWPgTs;O23m*6gv=Q6)=q1Y44tS7OS|p9kUhLNyZG%`_Tg8t2M#FE33DB#QSM} z*-MoTw)~9%K<_j3Br?rY*!-}!Rg&0*$hMWFb734#MhOw&iQGUq+5mc zsTceux0`4hI$#f9gUnkB$o@mp zbuk9J5@lUli5HIkk?M1|9vc$yq#kweNx1kE@Qx`d889iNEF!={4Y1YXJs%n;J{eRl z8GB+Gz6q*cXh!}fK}nQEiMKX1x8^l>q*|q{1HVtepB2*|=1S0;D%c)Hfgya#6as#6 zD3G&7T|<~v)ExhH9E~4fQF@tv^GF50sPV-^-f_ksC?PCQseUm-FF~D0H#)l}F$x3I zcOTUC;~sW1ZaZ1N(Y~aWx3ZW^U5!M4I_icW$d84E@DeUnZ^1dzCvxXhZn0AbF~`LE zRRhVFkzz0YdES&1p9#1%(F)Gqq>nT`#PNU`(^okVa)-6pd6IiHOk6u;Brd_and{l7 z`gxRDq~-WkvC>Y?&g$#8jECKjOvI9pHM{W52;-7I*W9lUF938ESFu@lF+`>zB+<~gUja=u^fv?QsS8oCtM)} z;?#qCF#A;)-l5**xVLHsfBR-I+>QQ%yhCfJ=_O6>ETx_5s_o}KUL4nB8}jpUtWm{x zZT=XcpEFaHc(xDhmax!?i$vZVUeavqG3I{qz%C5&1U~9`ab-y3VAV3l})0m1W4kFk_R>}e8?loI{q|upV3dawy3t(qcxKX&7^b8!~ znGX_cMpv-rvjx<<6hQ?*9mujTePj-2Wdgdbr&ERk?!(X+pighv8c^PjwM2d?OThWc z9x8k+syR74TX>vpAWn{#Ggp^!`$}F7i<Va!w6w#e);2@I_Bw4k6YqN)|hg;dz!;K8mP(`bkZ!k_oUgqrMIsH_9?!-xKZb6 zmxIj0FT&3%$?uzh-K9)wdwWI&H)9XwsD)u_F{x@`k^(-Q->)wcyld&3Y-$?}MjmA6 z7Xh(B*dC&j&s9giSQjT)WEM{PFK^)+d)w0r1LiHd#zD`EjgQC0(hCp7Nkm9I@&dZZb$vXYa{}z!CYN5S!rF zwIXl$CJLOFbJHl{2`>i_NP4piBHOpy)fB=W(NVpfwN@N;XM3~Pvt)}E4qhC+2*vOX z$PUE2!(Gev>ZrQ(5i$>QqRA4=tIUv6^NFjBF_<56s-06;biXf*doQkwztbX|-_P5e zuC;Rs7;d4F$Y5g^#GIIa)xpPFd`^Mz8oMsn_e76rRV*(+3|8%_TzwQe4&hNtolOVc zPWsqPsmT|a7>;xyAh*E5_~l(>nfM1f0xZH!^K8kF#yrTtKIhprq;6uo_t6oD63Wm= zpAOzbxR?_wdxGft8n3}Jx-~1>>SvRr1Xy&nCRW$cAuL16qx2AJOT`?(K%W*2`Xpzk zhNi6!X4ub)J{UKeq}PwLzOw=SguSp9d$0s`60hB&T1F64bFCG;rJzk4$nTg7w@tT8q$uEJ)Pohw8rCP#aBtl-m{U#74?c2+;oX#B; z6*)x43npZGpF4%Gg+90P0p%CjWt8Z!yNjjxgfblG_^C?E**)Pm9M}O@GIQiP2%JC3 znO`ZV_ibsaLqS1@SW8H#$Vy23TS1@qab zE;o#u4Me0E6!obZWYHxis+{ns_Qyy9cc~YlWu{2-lZ#0iAxwfRD?;Ahy-^oTXI_3a zzQxAueRMBp*f;9JS0YMzfH{}K&fzIEA-CD?>-h)~CfW4i&Z;UODK|>~%{PBhF%rcXbVux%$@9dN5NAf~ZV|=S+`-g`Q zEm?H_KMC9B*M8W*rr%L_Z!S~5?(5@ra^6_p6WRtN68O&3NPwwDQdF2=&MdDKJ&e!s z4)t9Rmib4IVB?E*fg4bWVSPFg4J(418z1>v{mz>9Z(wUm!M&J+m2*%~FS4zlpA*ng zRNyyrv}ZOkcQgetyW2ZGKSuxsB`D(VWMXCuf&ffGmevkJlxLm2lmKgUAxdp7MOH;8 z36Pbwj3*eR?y00<=4orjXHF?1j3VgH|4d*Hf|vl@?d=>~_}zslfAjJ`AOGrRp#=Pf zKx~C5bre+q5{_UHfRmY%nH4DIZvB>>QWymw2sXFiSCf?flj6B0L}>+qIPtTvxVgD8 zyKyi(f-PCt`1tr(SlL#k# z75}n!aQRckXFXZmO`KTRm|0ou?f=EX1tRtKpZ@+!3m1*&$2C~gKrW81U^9@^TaW{U z>hDgS>|9;`?$gx;^sDQ4+;-*`EYCsx_WXC7*RqN#f7$$!(bC%9>9@r%^xu)@W`E(F zT)}p~G3I70AUlx#b099y%xwRHhge(ubAkS4KEFo(mq4D~{l)(;=zr+-JC@(N@=H3J zx&Cr0D=9?zD_(wcM>A`4{@;gu7Q7a0e9w!*1>)caa1WWqm#}1DTnyn}E2v zcsMwIQ~g>8elZnUAxd^;)_?Y>*qJ~q9KrU_=<{f5-Dr=wB>iV2GO|*j5>=Y-$5CgZ%eA{}uQz zCbj3?&IJPYko`YQ>VLus{*kaU&$f2RZ-I`eRG7v;Hj=0PuSo;5RY*Lw*;N zx1c{#?ODe^hRm!?94tZ4`|Y2__K$w+|00o1d006)%sKdg92UHMKu%L$ZlI|tI~S0Z zhs)HAkIl@Cm*mcN~do@4%_@A(Axe7xB7dmOLx||MT@{_Wl2K0Ra5R$-kxVf8_d)T>q8= z{}%W^+4Uc}{w)RmE%1M`>;IWtDF3|V201+c?sI#-pdPz^bqWOqqobmrA@zJwp0d0e zzqn%3)2Gxb)#=Oblg4ruW3O_rz4x{1S0;3PMm2l#dU3L}bA9Y~=jni>N4QUthAc zG~2;posLe8wsxu7dRTvd^0aixnmUS%Ov##B-HtA+fuZoZ1?A=zy!Zt8z(DNSScbfO zij0h)nK{nl5~lnDo53Od&TfvPV!?_^P~U+4(1?0#yIO0T;IKvifJ99#Qb-6* zc24ZVGEq`8N?4fx)GTInblB_yZhSmtW|l?&pk`Y;%ez9v;NZaNx!{?3-qJGBs_MY$ z+0fZ}u9DK1F|l05rTpa;N=+>|adD)nX|L-W!6DMM^{!*@-;Pc2l$K#cM!o6oG4AQ}ot#Dq4MPqM^_!Z( zh>SGt?KAG_6{@HdsjQNzZ$u3XPgq(>Tw0NBXyh-e5Gb$YDlVbP&i0v{<}WL!&dR3B z%mR;$;U^>zCM8A8EvhuPzRJzRjf>|lDP=1x;wvi`D6eoIpET?3M~{erjEm47V>6%J1- z^V~polF@a6g2EX5^@bjGEHi)ZM1;sHN+BL1;39C*D=NBmK|#Uo$x4c8=nQse#2Be- z5{&XiPsLzKHpQe1*eSdTb;JyZeisnHj}x9CE3x_BT^8)G)*)F?<}bNv@vc}_Iz!4P zGg$WQ$xvvfotXSXx82QHPVY?HjK>q$E!Snb`#@JiLjxxwn73`Nf}lAR5!hN_5u{Zb zvy{X;JU(Of2|IU*mce6Yh9*BTmxlnEjixs~kgxHj`IB@Gyp($NP^yKc^#<*e=UB^C z^yK7ZG!x=?Mz70M(fN8;;${08510nFn_)pBrH)4?be7eYK_yVRF&*6<4TE-wG&49M z^?QSWXrf?MU1M!AaG&yQKsYsV<4DTuO{%!Q+(hJckJ_7nBOk%NC&cp>cHK2Su~SMu zM%^5g9B-8wF<}jOp^8tzDF*8IHg$5XX7G#4;sV;Fht^dYuTU)YqfA+Sdov0f&{9ge_i_!?KS% zMvd!>pOM*v#}Tmj_&D2re9YxDiwp$!f)e)--mS7EhC-a;-Q<#1bk07X&^;e)?NE># z1sSZSkQLR)fyT~`B^k6syENT)gC{-*qCWIV9qdq*R*Th~eMQ#le!2GsUXXzAVw_8w zYDdE;e(}sX;bfVT9M_)UZ5+FK+~=nye#3-HwAHt?uXHSE#!%eP!*5yF#$e*Cf2izshapkIbMm2YL;(emFCy09T zuDRYh@T4eWlA7HGKAJ^iv~u1B$dpkwYatn^&;#`Vk{mNLu1&~3sh?6`ZLa?DzSf&( zWX*!b2fd~T`MXkHT+D}Co+M3|tlkva>xO{o5|6Eo%s}9GnC1R)7RQ=%N{odYUml}? z-H%E(JjHY5zR6Nw#j@lx57hJRu#4Tzeh<2hv8zd-rM#isW{YM0#E!OCKj83XkqzD9l! zNzPeVl`c>avF~w&cGO>#;N_S=-4||ZJbux*PoEyl zlgQax8{yl<=vRe;7o45p3F$)8EQ^^&Klyi2dtZ)T>ZHPD(4M~&ZCQ=hlLLxZS@-C3 z6PD@=Qt&*P-wWUo(dSS}!h(3h$wqqN)NCFN_pZn(zP7_<&4ngnP-3z3A@hp?(@^b-yP{)e8fA@EXq zS4dJq3owM};4|V!uuORg0_*@i+RwD|)N2gH;~!6s`xPRq-KRTshhdd6LI^(*9gtD1 VzQ+mJJa2(evQkQtHR8sB{{#4B_QU`H literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/Plus_Button.png b/TheOtherRoles/Resources/Plus_Button.png new file mode 100644 index 0000000000000000000000000000000000000000..35335d5370f2768ac1f02008f61c86dd10b7221c GIT binary patch literal 7047 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 literal 0 HcmV?d00001 diff --git a/TheOtherRoles/Resources/Settings_ButtonActive.png b/TheOtherRoles/Resources/Settings_ButtonActive.png new file mode 100644 index 0000000000000000000000000000000000000000..813c937c11708ea37eb1d8ed0db7aa15fd430917 GIT binary patch literal 13826 zcmeHuWmH?;)-Ddk9ZHb^#VrI4#jUuv6mK8_f;S276fN$qMO&muaV<^@6nBb4u>wU3 zwVU>R&pGe8-*?Y<&lvaqJITmS_FB(;=3LL3bFIC{9*NS^xlcmKK!|~XL87jvY=HhY zM}G_n@X$xfmdCLe7`MZHj2@v3Af5m>gsUyw2?juUyTJf3FSsoRhSy?Mwp|+Ay@arz zjx_Z+-t~+NNL&2+Z`X<%+yw;|9n~%cB2<~ctJMS}haVq)3SP*48y5H8RvM}8E5F{1 z7HT|WJ@{O9Z2bItz)GNE*Ky|V0dMm`_;!+C=a2l&i*HA*EfQ|4y!mgGl&<%C8g}pW zTOIADhgZkt#0;H5%t=yTvf7Q4AjR~?8&LdU8J)t>&jJ2FGlBy(EN_;b9g!E8H-Y)D zRtd~evpRz?%c^=i44og|+q^7nHOp%X^>X;T-eSk%l*DIaIyVrb{TaS1T_MZN(+)#( zXP&UZeVV%b!+I;d@67QJ#)%?q5wk zhG~~_A8y>a7JkcVyzF-Sr~C3jv%@DF;kFNTZ3moFr$A{qN$l;@=A`tW8@o12j_N~q z*avb3`(xf}kb{U%bK1|SNhu_9Bng+goAT%6HjE?id&QBqArG3Sl!AfG}(_c+`+9Ug4|k-HGyTb&^9l=YO*7+0}8nNZ$ByvEqnTT}k+bho%Ab zhzU=`{4QY@g)xEGK2VXVcT>bM+k(R<8A-_LDWx$IE9P{EhTN)Rz{QNnCw8cK=h4FH z%=G|E^POok<*T7ZKt4cVs=QsMU*emi5Ai0?78z3T(O4=ehD$^SK>*xl_^d$ZO&{O9^n;IB+yR?8K1ThRp6~GR>n#`qVz1M zAV-}3)FMbReOP1@?y8v+{5UHz!2$U?OdevO&@ffzdC`Xd`@5>rz7sY_2WWZed5iO*T|sd<9ca`-<(! zL``N|BdUE&iNY&&=^D~BDQS@Q!S7Nr7+R{ebu?rFYLknH%5xlBqa*RP`W^I2V5pAm1v7*~nWuV&B0XG=6@vhAOmcV7(Y&q}$rL>0)B zFu2d`XiVdJ=L%P*@4?=0nLdQ%QV&tW3y%6vM9Sw@C&Tt4214gZ zC-Xq<++kMA=8qSlBQwFu8l-I%gUmW#DSv)gjDUB!voZm66L@bI2{2(qj();ZTa?*I zElu5uZ@Wb~eoT$2+G_7M5GKpocGY`3fYzIO(8YQe%pt+ERvD1{CeV(3YUT?3zB}`2 z@!=ff7_mpVFed5|K-zawR`Kr%K=-23F&cdcu> z9OwBjW_9~7RcjjLy+sI`-p|q78bFF&sZ?}=Ff}yA+jPITAK9LroQ8anAHrfOKc^;{ zR8g-}ylAQ|S;d{}>Pz#XGyh3xwr}C~UDK(;v*$t#pNAGXUHZU$^8IDCLI zwj15Axu3u&0*rcs(h@_)pqfm(7^HKeysLwY7^xH7X1918Y(Cv9pAnmAGGz)5xjk)0 zcn&^x!3wLVE9N?3sALiRNNFa97a1am&kea#$d4!1q32%nq(M%h?C}?)NZ5V8x>kgB zr1w~*%^mSKiYYybJEp6^pJ8Vq@hum*4>dHy{HZpNiOvcW^Q6g{>Sbaa$|HRj2O{1) z#9Vvcg5B<;;KfDI1(SQ-YW^+@WUH@BwfoXx@(B?jucG8aY1f)k48YTMU7t|uzC^UQ zDtpcuyhpXt8FH_du#S!}R^F7xtyARQUi5G|hnRY#@Pm%G$pE6EOli^1%*+buZd^&G zPbMr}eU`D|cG|3JBckuJ6vvIlc$j$~G><9WDB3m8Z$jU^>|MS^qhId9Xcf9={q(A? z9?Vcw(R)sMkiHrdlHVt}Y6PVs&C{IQ_b2G@pW=BDWG(k`A^9SX0c9*u3*LzZ6trjc z;^79CSsExra@@QETy*ERdQqRJ>T*+FOGLy=YBy?AM{{4>x7CT6ZS= zpo%+}tJB=}Y?ZJRzR#Lh-y9x#(z!7U;f}n)FhO=L8Hh!{6A6Fg^xpJvmIg1iN`khR zSlwV_HY;VH-XQ6=3EM~=P8V

mCJntpUuK(9&#l&u^q#Bvnk2S9yhx_nq0!BG#>p zT2T)w3i;czbz?YS6?@(dR}Lag9~{QK?lJws~;+;KL@;o16@3yJQ^Qf&5tT>RRb`qG;W?VPs~4w7I`D+b|3 z*d{NT9&_pNfk@Ne=-n&vjl)XZEZA9deG$N|31cJz;&D%ZGe_EZ=r0dcxjg?)>9YCq z=29T)eyRQg<1GO~LT6tkmjUV8LwV$#SC5(7SKV|y-_+{Cx|EAlh?#R^**QwM)LKVt zL)Jozt<6J-q-V+-GDE50w)+Fe&qtvS#ga_i1EY`1{H{{g%MIRCj1yqd?{InvPtHf< zQj=XflCVAdp*8eQ+rUP%r|o zHQ6z(mFzT+O>0esaeZD}hLC<1r7jLG1rlIM(-!y}tOLL#%7!RbFdp9HZq~Rh>Qr^I zju>mj)OWb~WnpPCQOsWF35jOhkh@P*^ODOO=Xo4&7kz%Bd%yJ(UIAzm*(!D{z$V9w z-dY?^-)16Cy0*%AOTNhS^&^FHKl4pr4YzMe$&m zBC#A@Y63AQz;MYytRJ~NdeXsV7`IC3B5Ty2b9^Y4#_WD!M7+n}pzv9qyhopatIpZO zNJduV9CI3PkE*V7gPrWVu}Pq&&&5<_7e~hpeD*_<<#*8oSM{2Jtc#{%W4X~Av&olT zLp}$0Lkh6uxNo2j^RD%K-pDGb%&|Enoe-4vHp1`j-#1ZJ>kaz|y4Fx^imH3sxK4%$ zIn33oiDbrMdIFnR=$Bjwk?+D+sw^d3$)u;KpU4#aIs$CtU?qrT?`24l6F6RqCY2mk zJbDqX_q-HHaSCc6>&tRtKH$Frgf|*H>I;AI4SZK;I;qa#^nhJT(Kocv_|eqxBInU3 zdl2=Knyk`C%Q#&vzPb#6wcbN}TN=pXM0CsbhC2AJK1UpR!&ZAC|3;U{s2*xGqk=U` zn4MLWLfDUYXeUk!TT)Mw?I#7n!;=Z2*f}-jS6JGSqYpn}C6wYc8Jjg>Xx3q6ljw&m zM}|>bpjuvn*QooH#o?$%tvj9owYzQYi8L9Blln0j-=sC&X+yyr+WTf0N&8%7up978 zGt*DxZ5)^C2V55~4^2rSgq~z#Q+gOu-$W;<$ zreM|5;%Cg(UBzD$dL8j{{nMO|k)u_P!0WZ)54jxy4Ca2opvV4dEfE|Ex%1M`ne87= zj!M5kaW=TOY8`T4wCTw4`VY+tK2cbF$@7^~!E(-q`1!8?bW+`-)E!KTwU-N~trD^H z$?oLobUrQ6y@`9UV#;KTdv9Wkbs6405g)ELDGtED9=5(Ouva*?>O5n(kNGXHUd>#{ zNvo4vnZG~Vz0Z|RV(7u>Hps?K*{vxaumD`_Zq`X!B(GQuFTQ$+eF0vSC@n5nXMl3> ze%4M__hO^{31ENaNJD?i%~GL*&4l$%I45s2X*j-yUa&qZ>UoYz=#_f-+05glpzKOH zR@DmfGG_vUa+<8O5R<2H;~hFP*JetGh0Iq)MK^tuMOIl6j+qR?$;!6L?tAX2o3mnk zN_jxiWOg6Nmfnv&`wEUbxh=dTte3(Q?KG*PPUH z^%1*((IBO#lr+pDjOiJ>J z(L;6Km{3g8%h)3|kRa;rkAnWKQDpLTJA}lgIUl__Ei5EjbT2VOm0{=68 z0{<#|Mq)6w;uUT74Xdy8U1=;f&j^BK_hf}?V+vEP0uBwVm2+7$T!NuXF{Szm8s(Q{ zb&_oTAt{^eW2zo%MjVdcmdhsJdof8XasZV%Ba4w+E$WK+YANlnj1yC_-t89zzlTb6 z2aO?y4tWnO=2?rBC22-j79vOLcv%%Bc3%gCuDg}v)Ct+)HdH@{Ws{sza80vdh4J%n zB=!_YzSl%rMI(IG<2JrD^3JK93IGLx3H{GjmT~c!@sy#r?@PbCX>}>9If6`L66io9@S#%s9cWD-T%h9Ew<-h_7$a()T>OD@k^09Q|y$jj#J2nX=ww z+&XpgGM^Q27url4S4_`#)_&pu1}GWac&7zK%iUvd*H$`WCE##Wi7Ef|{b#*uC0{KO zK{0p_(85qX>*Ac7=5eq2Vndf$9UiTjr!O!(Sy>M%s2G7&SVr4H`D}|Y67Wi^C9mr8=Eq^ zJuOLR*{=H!q}5+1!E934n9L=%Fystehm$U2e79T0IYe6dJ$9Px?mvOmSH8v(um)nz zW$f22q>x?db?l3W^$-4Ck;;U6juA_yPfW>g%V`hO{p9 zjiiZTMe6!}-bNMKSFHoDUj&CFxyLTO7+CGsV`&o3@I(yhDlDxZVJd2T>A0-br7Ia+ zak%hqTcm!rIuCWhd|=5Ltll66Zcj;1qmdgQuQ?PG2utH^EeGPgg8cU;dbBmeiXNd?3S1FRIH(^ zXWfTeCTax38>|%6Z{6ut-ka+f87}r#h=|%4-lhs`7`YomVC>(x|0O_wH!g>K_-HF# z_D;$%bghi^a#sepFsBmZ0~SGqhfTH8XuOertH7f$7GAKpyT20Z zx+(IJF-Rf8`PIF_+x!$n{akmM&qZc>r$0@74O7uEZ$bv)S9q+X&t&OuISDUv?Awk+ z&eECVJdI&1={VZFblE3Bar(U(u{XXP`avr`UI<#SfTUp^Z1VLFT~%U8kQZ7hS)- z>;!-5dl$juuj95|^Io--F8YK$Kwp%a3oh<20aLt2#qXSI#{~@YoJ06;)WpBa#F(Y< zF~kW!pB12&HQRDR#E*BD2huG_udA;!&Je@tS+~uBnu4%z&_{stF%yJ9!AxJ zyT^OZ*o*Ubn1VLJfaJGnH6_P??*7(xP|je^E33pX8@u$*!BNM3r}#qbN)I@x{Jh%}b!q#_yNFK_-=B0szc}@AUPxtVCN3Ez9L?@+2l+V5C*}KIz!?^vCG}%xN)n2` z?V0n?xA`G!$YDsbv~rZ)_A-U4^M3pmOA*JSgU&qr+x7e~(-lneHM^RdSB5)mUA`hw ziL{ze6JDrtm+?m!XWuPYvdO5Ky=-D-3~BgY`GVf0;fX4(+oZ?0-ER(LKPWx{*!sZ6 zIYh7WgJ|P4chwHt6@Fyj6H9$;pNtU{7r=sX6>QN5r@7-k8z=$4@HsFG`B486oM~BaCWHHJu>6OA!^^Vs0I?lopEkPY>$H{q z_^BmY6RFS>Jc0f-J7ERdsr}HKhLX~mg!-w}7b;^{#OdYz&WVPUMrkTz_>K`+&-)rZ zKGNEjNs@+*2s!eA%KQo|!kxwZ*z9XfL80`Ev@#TzHKhg*-XiQ2dpsshJ>2V09vnT9 zaUSL~@uQHH2=vLhkt$1Y-KDPfEU^;&cJMVjJP#bmLVS39L9PHaf>sgyq~q%%eePG0 z_~udEgWyF3&_j_uVL!|dOD^gU%QoCoR4uLwry=(9o% z?(ppk&@7I9ojx2#*$|$uk;oP ztE4i_Z&*d)Y6j+vxN{*-S)w1{)7e=tnd2&)VD~Nbs86V9e6upJr`YUyBDcEYyWD{t zY8q8xyF_2$kd_#u(y!&ALfl@2{e7>8I)qZ>!pnh`Wc<{fjK%5`oAleS%lXgEhBJvz zqWbE!B=|SnH$G}>?zZbPTC1qD%5pJ_?S=Hko2Od@Y?`}0TFYc*&&^>crHBrrO*6}& zAxZU0lB_Ie*e1H2PBUhfGh+}Yc06oF{|^3^r+SJ}kvKY%9g_mYJ1>8WmaV~|I74kR zV7gas?+evd((r3c)j02zLPf;4wZM}$GZ8uAV@}-X@?WE!1BtPNEeb4OAAPb}s?Nvw zVYjB?c=J~5@lNu&gCP+MX2()@zq?`bRnS|e$7|~8#KVc-M8o`;z2u&|j$rvW$MRI>x>~~oy`0_9kI*nMq~*NaAU2LL6u=s02X~QS`_$IO27p6l*o?)rf!c0LFnhR~ z4+3WBqhn;_<7fkhvdPI3N_$D637lal2*AtP$ptCpCByccR|@_6SF;cs;5P*2D8u$h zTMwY*ihuz`1w{pc0xDi`4-lIyAwU`dwUshZR{fI#eI~;2v4myC9BXSd%LztDe0LT&zzb8|;H{l-9TgkVlE zXLKM)G_&wO;Zbnge@xInjptX-e+dNb?(h8ng#Mdezhn8WtCX^dG=~zv7jG zy4t{@QonynK*2zeBnT)VVha%#5EU1L30T`$g9WUuttBL&ViF*0N#I|o)LoD$h>H#E z7ZsXZ5RT>nfxx!bqLQKlP@sq{nnJ=_KoSBH7Lb$_5f&2%fo)*6f2Ghxz|oZear$di zzo?*SDq$cD3b7Tp6#$Cb+6ahR+u90%K_GDfTL@4>93qPT0^9zM=GQz(Dd?%ouz>{s zAphN>=LA97x+0v>yC7fIxY=A{=!Qy4DUb8`Qt%`R~AgXEH#qc1RS$Tm63+)c=N){v%=4 z(6+7!@4xsrggyD=?2jeM3I1Cu0O0pBAO*4cLw+R00|xy)1!x`r=(4egxY)ta>+PS# z_P2KUf0M`%F%d}{YnYgTuq0SiKoklA3qT|!gatt2HWDC^wS)*1@<&GeogL|Fi}HjZ zU2G=Sf5834{?8o!pUnRX`@>qv z)y*4S#r7y&PnUn`{=WhK!Jq}Vfw>@E|5fOJh5RAQUp69i%zw0@H#qcuDfIUZ^Uo~# zRY?CIUw>xb|3?pK>i;p{l-%{Y;0{;>oLE8K4gE{D04n;TOqtvxk z@b~a&NySOa-&##$U=a4HD=QdzEgt2VIGG#Y9t_-FHj%lEX_91)KjPn{yL#qq|a8kWeWw1=tbr76!j zvz@=~pX{|^fHKrN7ZNl~s<)UAPL$8p0I5GJmUGqcQpiigwwTSN=Ci1xf-1*sCDcm} zX_I{UDpERRb5G4=zXm*QB7f8^u$IQZM(d_Y>qgYf@k(H~pu#CFc%GWa;=`-8W$`<~ zltPvfo2!@-TFG7JZEv{ds*|)hCE8!p($JhLPwB*oA1Njywu67RR;4z^Ii^_+@nveA zjU%07xG38f5pJ;Hd?tpRupXTv_IL zY`vWe3Vwl2<0?Dx2H%$H`M#F|_&lF)=$Tlux9hFDwZ&FIbE4`Rb1e+}gS!`q%58uH zb}(&szUjD|*tD+0xU8r)?MVw4ywHGf3dnQTY~Ksa9BPst-5{|5*jdRR0_?K6Y}^At0KX z?&_2dO40zOYV9~m3UB5JYb84gM#IOXJH1Yl6^p3%!iAaiTyLdm1ViW>;)%^<{d8e8 z+5WOSx^NW*{i+m2LVY(wjTIHy$`cwoWHBUS+n|`deg2%>)ow8(tYRREZU)J>`Y)#dgUa#Udr=7A&o9$QkzXiz{(7pscLkIcWq0 z=n5}NTMcanOX*x(O|H&GxX>dX4mZAVAYC1N<~53~dmuGoA>2}Mdw-8amP;n*PNr2Hbo{5AsnTt{1&I(G>@+1 zJ3Sc@K#;@!-|xmH@llHRZD4p)pq+$gV)n2c5`;%vY;N{Tp4xk9elFSsmvghijIl{$ zwzh^N%Dnw7OXJUPDHzV!GFLB$4%%A%>@Gu?tirpx-+z$=E8PbWR#J4A!Wjvt1?6Uz z8#2k1eHCV{Gw|l{d*_Q)e?AJO(m1WcjyJS2sQV#cE~kk znqK~_A^d&2wBAHnHp1$sths<`$p@~g)&6YHv|~}TXHL_#CuCf)W^+EdXJMa}(-djyDcj!XvfJis229y_cLK0@{u~uc4562} z7t#uGY zdCHW0)&E4I(B#_mOS$87Z&)&AQ*SVNQ`z`4TQSosFTJB~Z!WKE9gY4ga z97>wK6yLnMA$Q>HppF?p_Y)_Mj&>1>Ry>hm+-aymsmH!@Cz5vF%h_vI<;_(jXnCAy zo%QTs9k_!2Z-r5kN&1sPYgK~98z1l%S!HWUO)FU!ebm;|BA$J%X^rV z71V=mQdI>DdZrpHrP|*14zr&$c-|K)CxbqG*7Mw>qh@Az{fZ@{;zEkM&!29vgL>lR zDe}pYA$J`!#lYysuVLDC{joa<3(Cq4Al0KRt;(65JD5ddpeBCpXGELshT2s!XO4Ee zQI+Vu){Z5tiMJVzr{or_4Z`+1BDHi_?)ME3ws7!+-DjUUX2Y;tm{48>O496aZq2;? z%-rSq)gy1E&bcwLv&lh(qy*+SzoNn|H88OfUwLcZ5${Vw$-QgU&&)V$?E)7_ID^1U zfMDoNX5{F~LSSX7$C#~3RBz8jDQ8`H3#Z4yoY6XxZ+;2#Vc%!}Egzv@qXA)j8^ID5 zO)=+IR!B!F|2G$-k30iMh{ChyuHo=He?yvWojL5!x0$)uVrgjXvy^wR%L=tZN?=G( zk~_XRL2yC{O8jkVEdl3pQ%5LaS=-tVs8lah3K=Mv_j9QYB_5q%ZPNQg6R&#ud_3=t z1D5$=>)5!Q^q8s<(#;3uQn6I@)`RE6LSRtxgY4U8P#0f+4gGbVosX?Ish&JknW8ci zA6F4l*|>n@w+I(6dRD;Ng~9HHi{ycL@XJjbZk2!_c-HtXdoMSxnWle=0Qpe=%fgec z%l?gsUEeb<7G^sre@ID5#fze(x%@!L*rqc_KZ{USgxRa~vi|0kRI(42W`l+#_l8z> z7o>S`OnTS8*Z=I@Mxl4g_tH<5rhJ+%h(BtD8osL}c1KJsTV17T0bQz|URX)-9b(@$O)({!r)8HQFu?(z>F%l_j$I zxaC2P6pf-=@ioQjk8>&=OX;q)gB%^M`&ld|Gc0e$+)NK;_z9PdH#nrk)a|^2?vTVz zQ`3F8Dj{@xZ>9A8vk;J4m;X!FzBSp5O5THOGj1N7b+4SUlWzVd80LpAnW6jnO~N$M zr}bp)ri|p%w#5UYhLztBmbI^#1YiqAxU$^V$Ube>qlrB?dPnyN!J^Lljbc)q*>p^8jOsEq}))0{3^*wN@8M+FDh!w zt3$i~%S9AXGp^qXcGuo1>bBw|v9B^|tjd=~gHs&7%VVdZDf&di9S;;o?Bkcff*9XE zp5Ku>yz`}TP*hW_gpoEc_4Q$B%0$yXcGqoGi)FSm@axn^iN;dU_Gpyy`!@}URy6BH jbMEF-!8u2apZK*HW^ke$^+NO|E{3{_j&il)Modified by mxyx.club\nBased on TheOtherUs", "13": "模组修改:沫夏悠轩 " }, + "GameMode": { + "0": "Game Mode", + "13": "游戏模式" + }, + "isClassicGM": { + "0": "Classic", + "13": "经典模式" + }, + "isVanHideNSeekGM": { + "0": "Van. HideNSeek", + "13": "原版躲猫猫" + }, "isHideNSeekGM": { - "0": "HideNSeek", + "0": "TOU Hide N Seek", "13": "猎杀模式" }, "isGuesserGm": { diff --git a/TheOtherRoles/Roles/Crewmate/Prosecutor.cs b/TheOtherRoles/Roles/Crewmate/Prosecutor.cs index 1a7136d6..7f0e4b2f 100644 --- a/TheOtherRoles/Roles/Crewmate/Prosecutor.cs +++ b/TheOtherRoles/Roles/Crewmate/Prosecutor.cs @@ -1,4 +1,4 @@ -using Hazel; +using Hazel; using TheOtherRoles.Utilities; using TMPro; using UnityEngine; @@ -173,7 +173,7 @@ public static bool Prefix(PlayerVoteArea __instance) [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.StartMeeting))] public class StartMeetingPatch { - private static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameData.PlayerInfo meetingTarget) + private static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] NetworkedPlayerInfo meetingTarget) { if (__instance == null) return; if (prosecutor != null) StartProsecute = false; @@ -201,7 +201,7 @@ public static void ExileControllerPostfix(ExileController __instance) { if (prosecutor != null && ProsecuteThisMeeting) { - var exiled = __instance.exiled?.Object; + var exiled = __instance.initData.networkedPlayer?.Object; if (exiled != null && exiled == exiled.isCrew() && diesOnIncorrectPros) { prosecutor.Exiled(); diff --git a/TheOtherRoles/Roles/RoleHelpers.cs b/TheOtherRoles/Roles/RoleHelpers.cs index a58510ce..6896665e 100644 --- a/TheOtherRoles/Roles/RoleHelpers.cs +++ b/TheOtherRoles/Roles/RoleHelpers.cs @@ -16,7 +16,6 @@ public static bool CanSeeRoleInfo { if (PlayerControl.LocalPlayer == Specter.Player) _CanSeeRoleInfo = false; else if (Specter.Player.isLover() && Lovers.otherLover(Specter.Player) == PlayerControl.LocalPlayer) _CanSeeRoleInfo = false; - else if (Akujo.isAkujoTeam(Specter.Player) && Akujo.otherLover(Specter.Player) == PlayerControl.LocalPlayer) _CanSeeRoleInfo = false; else _CanSeeRoleInfo = value; } } diff --git a/TheOtherRoles/TasksHandler.cs b/TheOtherRoles/TasksHandler.cs index 09c2e7e6..aebbeba6 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) { var TotalTasks = 0; var CompletedTasks = 0; @@ -26,7 +26,7 @@ public static Tuple taskInfo(GameData.PlayerInfo playerInfo) [HarmonyPatch(typeof(GameData), nameof(GameData.RecomputeTaskCounts))] private static class GameDataRecomputeTaskCountsPatch { - private static bool ShouldCountTasks(GameData.PlayerInfo playerInfo) + private static bool ShouldCountTasks(NetworkedPlayerInfo playerInfo) { return !(playerInfo.Object && playerInfo.Object.hasAliveKillingLover()) && playerInfo.PlayerId != Thief.thief?.PlayerId diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 146e8cb6..4e89a75a 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,30 +1,23 @@  net6.0 - 1.1.1.1 + 1.2.0.0 TheOtherUs mxyx-club latest true true embedded - Debug;Release;mxyx-club;Beta + Debug;Release;Beta - - - - - - - - - + + diff --git a/TheOtherRoles/Utilities/CachedPlayer.cs b/TheOtherRoles/Utilities/CachedPlayer.cs index 3259c070..af4d8450 100644 --- a/TheOtherRoles/Utilities/CachedPlayer.cs +++ b/TheOtherRoles/Utilities/CachedPlayer.cs @@ -12,7 +12,7 @@ public class CachedPlayer public static readonly Dictionary PlayerPtrs = new(); public static readonly List AllPlayers = new(); public static CachedPlayer LocalPlayer; - public GameData.PlayerInfo Data; + public NetworkedPlayerInfo Data => PlayerControl.Data; public CustomNetworkTransform NetTransform; public PlayerControl PlayerControl; public byte PlayerId; @@ -70,13 +70,12 @@ 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() { foreach (var cachedPlayer in CachedPlayer.AllPlayers) { - cachedPlayer.Data = cachedPlayer.PlayerControl.Data; cachedPlayer.PlayerId = cachedPlayer.PlayerControl.PlayerId; } } @@ -87,7 +86,6 @@ public static void AddCachedDataOnAddPlayer() { foreach (var cachedPlayer in CachedPlayer.AllPlayers) { - cachedPlayer.Data = cachedPlayer.PlayerControl.Data; cachedPlayer.PlayerId = cachedPlayer.PlayerControl.PlayerId; } } diff --git a/TheOtherRoles/packages.lock.json b/TheOtherRoles/packages.lock.json index 1b08c43a..575c74e2 100644 --- a/TheOtherRoles/packages.lock.json +++ b/TheOtherRoles/packages.lock.json @@ -4,9 +4,9 @@ "net6.0": { "AmongUs.GameLibs.Steam": { "type": "Direct", - "requested": "[2024.6.4, )", - "resolved": "2024.6.4", - "contentHash": "WTu/h9xYZ3r4RZP4yJQq3YPF31HV6cg7NN9Cd2DbZHloYUhMsD//xdE0x3k6YDRy9zbfhlJoUFTFDRcLipZEDQ==" + "requested": "[2024.9.4, )", + "resolved": "2024.9.4", + "contentHash": "5ZzigeztB4Y3xBM84Xl4bLBS/GGVe7tyZB6RxvUXHZS0xUP3RxqTGLeiB+xZSBlwD77aMrkZK0uJEh+MYvDB/A==" }, "BepInEx.IL2CPP.MSBuild": { "type": "Direct", @@ -22,19 +22,19 @@ }, "BepInEx.Unity.IL2CPP": { "type": "Direct", - "requested": "[6.0.0-be.697, )", - "resolved": "6.0.0-be.697", - "contentHash": "+ahFT8WkKZ8m9NCdXgQI05M34/mdE1MXmLnLRKhqpjId6mqDQf9ORJ1bCPifdkbgYJjteIvey9EreCfmD9Vndw==", + "requested": "[6.0.0-be.725, )", + "resolved": "6.0.0-be.725", + "contentHash": "lb6atWrBnVnQVOlaLBF3irZlbnA8gI46Jw/YlLBaeGra14W0q4aPVjUO5ODaBFzq/U0e7iAxzUNzesp3WPJ/tA==", "dependencies": { - "BepInEx.Core": "6.0.0-be.697", - "BepInEx.Unity.Common": "6.0.0-be.697", + "BepInEx.Core": "6.0.0-be.725", + "BepInEx.Unity.Common": "6.0.0-be.725", "HarmonyX": "2.10.2", "Iced": "1.21.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.972" + "MonoMod.RuntimeDetour": "22.7.31.1", + "Samboy063.Cpp2IL.Core": "2022.1.0-pre-release.18" } }, "Reactor": { @@ -48,46 +48,45 @@ }, "AsmResolver": { "type": "Transitive", - "resolved": "5.5.0", - "contentHash": "IuOC+b/D/da4fohYVNwo/NL+8w+q89O9B32bLotegJ+hmFlBEpQEKgtyhxc9ZfEd+x0KzwzD52RISuyLgf/BAA==" + "resolved": "6.0.0-beta.1", + "contentHash": "M5btCR/rmrx32jZsoN6CLQ/VQk8lN8hvPb6lgojua7pjNoo7StAl92koMC8qz4vzZyH2CNqxLSDoswRvyyK/vA==" }, "AsmResolver.DotNet": { "type": "Transitive", - "resolved": "5.5.0", - "contentHash": "T19DazP0h4qKXwPspTEB0ZzwlftPuvVAd68HhsS8eNYd9lRd/rtppcBmM2QLQdZeGGNJc+QEzLiAW+wrA3nKAw==", + "resolved": "6.0.0-beta.1", + "contentHash": "PTq8nNQvhgTxF1iARCknffCsu7Iq9B0kN7TVC8iMaU7uEYog3xvVqH/0+TreY8GW74/+MqhZt/yEFsvS4oAduQ==", "dependencies": { - "AsmResolver.PE": "5.5.0", - "System.Text.Json": "6.0.8" + "AsmResolver.PE": "6.0.0-beta.1" } }, "AsmResolver.PE": { "type": "Transitive", - "resolved": "5.5.0", - "contentHash": "bSPe0A+z4iEAabpD9h7ACQ5dkcTirx4fx05P194u/+OIUqlexHf7Zq/PEPdOkesbqHoZmgVmJ1H0GWqqouvZfA==", + "resolved": "6.0.0-beta.1", + "contentHash": "KadLvx/zzFCJyF+E4jG6jPE1d0iJquzL6+hm8GBivBAs6nwHC8s6g4c857QwQCzXMWza6Vz5Q+3hFiNuOfKaWQ==", "dependencies": { - "AsmResolver.PE.File": "5.5.0" + "AsmResolver.PE.File": "6.0.0-beta.1" } }, "AsmResolver.PE.File": { "type": "Transitive", - "resolved": "5.5.0", - "contentHash": "XHWHnPQf0e0VEJPTaWMoiajuikF0n0fDXS2XWzEXM+/xcY+LABsp1p7ETlg+bFsDVITQRtNTa/xV8eSDlSZjNQ==", + "resolved": "6.0.0-beta.1", + "contentHash": "+lusB9UMHevI5aQsu73NQ1ctPMLFvyHAsEf8vjaJ/py+kX1DkU0JkbERtBRmaf58/hBZ7cyrE7gFnjoo7Bbg7A==", "dependencies": { - "AsmResolver": "5.5.0" + "AsmResolver": "6.0.0-beta.1" } }, "AssetRipper.CIL": { "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "l639dKLllpJ5TcX+Z1OVYz+hsKVZyMpEm59Dl4Qd6YrCHPVj9yPtF/UNjn9nFxoDm7suEFP/0vlZD/bSeXjz6Q==", + "resolved": "1.1.0", + "contentHash": "nSz1cBjgVeKv+esfDtyQGC1mY9b4C4NFStytdoa9DMozDC8uth6930kAsuWZEivj9GqWSqENnaQUGnl23WpmnQ==", "dependencies": { - "AsmResolver.DotNet": "5.5.0" + "AsmResolver.DotNet": "6.0.0-beta.1" } }, "AssetRipper.Gee.External.Capstone": { "type": "Transitive", - "resolved": "2.3.1", - "contentHash": "WVujToXc2sB5nVEY4iMpjhsQaqGw5RjG3c0Hl1qT/pZMbfwtafpaOwAa0G/GS5gd2jcuJwrsG880Pkyjkhi3vQ==" + "resolved": "2.3.2", + "contentHash": "wOr5PQPL/2ZfD7+ebt6cpRbUhSzSY5nlHGHjjzuQRiU5zkQlqQNwWDLX0M3smrm5IkaDvONkmDjFMKTlZJmyuQ==" }, "AssetRipper.Primitives": { "type": "Transitive", @@ -96,27 +95,27 @@ }, "BepInEx.Core": { "type": "Transitive", - "resolved": "6.0.0-be.697", - "contentHash": "6p/zLtBja8BEA5+FwFwH1lUg8avO725mZKRw0P1JbuXj/XUZL8Qy5n0c7COiq/dJ58nCyW5J/ldeYUHM0c4vRA==", + "resolved": "6.0.0-be.725", + "contentHash": "xBqYH8OtmEfwe7ZRvQDkJF4cPRgyoykcYRXcuszeVWI+0e/7IYZ316wT3HhRU/GLQE6FijuMFGag73jTxMmoxA==", "dependencies": { "HarmonyX": "2.10.2", - "MonoMod.Utils": "22.5.1.1", + "MonoMod.Utils": "22.7.31.1", "SemanticVersioning": "2.0.2" } }, "BepInEx.Unity.Common": { "type": "Transitive", - "resolved": "6.0.0-be.697", - "contentHash": "6eTjN4vBy7veWUwCVWqfvL05fQ4MskpjD4wIsD0FF8g0kF/1lKjsK0Fmyb4N78vSrvm/tV1quhHChCh2SQU0GQ==", + "resolved": "6.0.0-be.725", + "contentHash": "2onnkxl2Ai88JwhxXXZld6bKjICwhLav/msfK9tIVJObCcxJkvWWGGXmUD+KquQtKjNj4hrExWwZa+zPnbUsTA==", "dependencies": { "AssetRipper.Primitives": "3.1.3", - "MonoMod.Utils": "22.5.1.1" + "MonoMod.Utils": "22.7.31.1" } }, "Disarm": { "type": "Transitive", - "resolved": "2022.1.0-master.26", - "contentHash": "YnZEbRGr0nG+N3G8WbRQ4Lkg8dTD3oso9iJlCVBmyhEyhLyqs+drBs1kWQbQqFPnb9mi/RJ++R9bPb+L3HF03Q==" + "resolved": "2022.1.0-master.34", + "contentHash": "sxzTci5eSdl+sFoaGsMZIp7X/eB5ZzplM3CppvD1CWoiZ8rSa43XGLC19G5e8n6mjutNBfN9yL+RER5PCspHFg==" }, "HarmonyX": { "type": "Transitive", @@ -191,11 +190,11 @@ }, "MonoMod.RuntimeDetour": { "type": "Transitive", - "resolved": "22.5.1.1", - "contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==", + "resolved": "22.7.31.1", + "contentHash": "nxVJTvQbWAujaogt5XX3eAy7d22t66Z88aWg9sirPLO9rR/6yNCHAyZpgxXrOsIobZVW0IEZPqNMOBhgke25/w==", "dependencies": { "Mono.Cecil": "0.11.4", - "MonoMod.Utils": "22.5.1.1", + "MonoMod.Utils": "22.7.31.1", "System.Collections.NonGeneric": "4.3.0", "System.ComponentModel.TypeConverter": "4.3.0", "System.IO.FileSystem.Primitives": "4.3.0", @@ -206,8 +205,8 @@ }, "MonoMod.Utils": { "type": "Transitive", - "resolved": "22.5.1.1", - "contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==", + "resolved": "22.7.31.1", + "contentHash": "nI0E1oadXS1iMbfwfCzYF08C1jRQR9cnnHv66a4BSPd4sGu2p6g4BmctCWsdAB6oGKkSJUhcfHfxcfTsDyB94Q==", "dependencies": { "Mono.Cecil": "0.11.4", "System.Collections.NonGeneric": "4.3.0", @@ -318,31 +317,31 @@ }, "Samboy063.Cpp2IL.Core": { "type": "Transitive", - "resolved": "2022.1.0-development.972", - "contentHash": "nCO5VGiZzMqdtf1yZZQwhJ+DHklSBqDxF25mTsfw8mP56wt4TBYiQyXnj2EASqbz2VN0+NqUB3jlcuOgD0gNHg==", + "resolved": "2022.1.0-pre-release.18", + "contentHash": "eX9d1IK05jWaEaeuMAE0L5WYHT7thtxz+aWLL/CAaCzZ0TzRPD+WFTjJ0KQO0YWBVO300CX3GwmPmf7TNO+wUg==", "dependencies": { - "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.20.0", - "Samboy063.LibCpp2IL": "2022.1.0-development.972", - "StableNameDotNet": "0.1.0-development.972" + "AsmResolver.DotNet": "6.0.0-beta.1", + "AssetRipper.CIL": "1.1.0", + "AssetRipper.Gee.External.Capstone": "2.3.2", + "Disarm": "2022.1.0-master.34", + "Iced": "1.21.0", + "Samboy063.LibCpp2IL": "2022.1.0-pre-release.18", + "StableNameDotNet": "0.1.0-pre-release.15" } }, "Samboy063.LibCpp2IL": { "type": "Transitive", - "resolved": "2022.1.0-development.972", - "contentHash": "8GtNi2i4CVXlunDyNhV1cZrxWNxlPejD5VPHgQ14bYrTjG8Rn7nGDt64B5cklGUT/FMADA9t/ZAALTMJ6UXpTA==", + "resolved": "2022.1.0-pre-release.18", + "contentHash": "9zJdTAeErpwJpYDHYwwI0MAC1OyBEfC1ce7dpAOYRUUYCfeaKVWxnSCcyaoY6HDzIoxPkhbfllbwOe49ZmUYuQ==", "dependencies": { - "AssetRipper.Primitives": "2.1.0", - "Samboy063.WasmDisassembler": "2022.1.0-development.972" + "AssetRipper.Primitives": "3.1.2", + "Samboy063.WasmDisassembler": "2022.1.0-pre-release.15" } }, "Samboy063.WasmDisassembler": { "type": "Transitive", - "resolved": "2022.1.0-development.972", - "contentHash": "lfbUsyjArvISK9oJBx+QmDwtjXg425K66BmLUoeqzJ11kt0EAUMM34qGEMDceNyNYfl5Op5RpS+krkq/sudM4g==" + "resolved": "2022.1.0-pre-release.15", + "contentHash": "e6qw81SHS+fS7iZ3qfqZBavVarYbkPElNgDCANF6dNFTYq5+hc80am+4FqQDl+ZVNS47bZDZobxIzHhmriCXGg==" }, "SemanticVersioning": { "type": "Transitive", @@ -351,8 +350,8 @@ }, "StableNameDotNet": { "type": "Transitive", - "resolved": "0.1.0-development.972", - "contentHash": "1G965uhTTEI5sKU/CFMGuhzuxDophrYS2otI3Ej+BAhbEOq//LFWpoEwhaWW5moKW0K56ZCqvB8YqnEKyk9kbA==" + "resolved": "0.1.0-pre-release.15", + "contentHash": "aIkEOo8V76vE+9CppHpTFLGXalBw6TAl4/tb6vadmS+gHJMshTVehzQv9cJXy4xZDdANV1uGMRaUFZERcDA2xQ==" }, "System.Collections": { "type": "Transitive", @@ -679,11 +678,6 @@ "Microsoft.NETCore.Targets": "1.1.0" } }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, "System.Runtime.Extensions": { "type": "Transitive", "resolved": "4.3.0", @@ -882,23 +876,6 @@ "System.Runtime": "4.3.0" } }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Text.Json": { - "type": "Transitive", - "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" - } - }, "System.Threading": { "type": "Transitive", "resolved": "4.3.0",