diff --git a/Strings.xlsx b/Strings.xlsx index 39e3458..79ebad9 100644 Binary files a/Strings.xlsx and b/Strings.xlsx differ diff --git a/TheOtherRoles/CustomGameModes/FreePlayGM.cs b/TheOtherRoles/CustomGameModes/FreePlayGM.cs index c2eefd6..cad6dae 100644 --- a/TheOtherRoles/CustomGameModes/FreePlayGM.cs +++ b/TheOtherRoles/CustomGameModes/FreePlayGM.cs @@ -90,7 +90,7 @@ void SetWidget(int tab) FortuneTeller.meetingFlag = false; } RPCProcedure.resetAchievement(); - roleScreen.CloseScreen(); + roleScreen?.CloseScreen(); })), 4); } else if (tab == 1) @@ -110,7 +110,7 @@ void SetWidget(int tab) })), 4)} ); } - roleScreen.SetContext(gui.VerticalHolder(GUIAlignment.Center, new List() { holder, TORGUIContextEngine.API.VerticalMargin(0.15f), gui.ScrollView(GUIAlignment.Center, new(7.4f, 3.5f), null, inner, out _) }), out _); + roleScreen?.SetContext(gui.VerticalHolder(GUIAlignment.Center, new List() { holder, TORGUIContextEngine.API.VerticalMargin(0.15f), gui.ScrollView(GUIAlignment.Center, new(7.4f, 3.5f), null, inner, out _) }), out _); } SetWidget(0); diff --git a/TheOtherRoles/CustomOptionHolder.cs b/TheOtherRoles/CustomOptionHolder.cs index 445239f..4c4325f 100644 --- a/TheOtherRoles/CustomOptionHolder.cs +++ b/TheOtherRoles/CustomOptionHolder.cs @@ -336,6 +336,7 @@ public class CustomOptionHolder { public static CustomOption evilHackerSpawnRate; public static CustomOption evilHackerCanHasBetterAdmin; public static CustomOption evilHackerCanCreateMadmate; + public static CustomOption evilHackerCanSeeDoorStatus; public static CustomOption evilHackerCanCreateMadmateFromJackal; public static CustomOption evilHackerCanInheritAbility; public static CustomOption createdMadmateCanDieToSheriff; @@ -554,6 +555,7 @@ public class CustomOptionHolder { public static CustomOption fungleElectrical; public static CustomOption miraVitals; public static CustomOption randomGameStartPosition; + public static CustomOption noticeNewDeadBodies; public static CustomOption activateProps; public static CustomOption numAccelTraps; public static CustomOption accelerationDuration; @@ -740,8 +742,9 @@ public static void Load() { evilHackerSpawnRate = CustomOption.Create(8001, Types.Impostor, cs(EvilHacker.color, "evilHacker"), rates, null, true); evilHackerCanHasBetterAdmin = CustomOption.Create(8002, Types.Impostor, "evilHackerCanHasBetterAdmin", false, evilHackerSpawnRate); + evilHackerCanSeeDoorStatus = CustomOption.Create(8015, Types.Impostor, "evilHackerCanSeeDoorStatus", true, evilHackerSpawnRate); evilHackerCanCreateMadmate = CustomOption.Create(8000, Types.Impostor, "evilHackerCanCreateMadmate", true, evilHackerSpawnRate); - evilHackerCanCreateMadmateFromJackal = CustomOption.Create(8005, Types.Impostor, "evilHackerCanCreateMadmateFromJackal", true, evilHackerCanCreateMadmate); + evilHackerCanCreateMadmateFromJackal = CustomOption.Create(8013, Types.Impostor, "evilHackerCanCreateMadmateFromJackal", true, evilHackerCanCreateMadmate); createdMadmateCanDieToSheriff = CustomOption.Create(8004, Types.Impostor, "createdMadmateCanDieToSheriff", true, evilHackerCanCreateMadmate); createdMadmateCanEnterVents = CustomOption.Create(8005, Types.Impostor, "createdMadmateCanEnterVents", true, evilHackerCanCreateMadmate); createdMadmateCanFixComm = CustomOption.Create(8006, Types.Impostor, "createdMadmateCanFixComm", false, evilHackerCanCreateMadmate); @@ -759,7 +762,7 @@ public static void Load() { trapperTrapRange = CustomOption.Create(8021, Types.Impostor, "trapperTrapRange", 1f, 0.5f, 5f, 0.1f, trapperSpawnRate, false, "unitMeters"); trapperMaxDistance = CustomOption.Create(8022, Types.Impostor, "trapperMaxDistance", 10f, 1f, 50f, 1f, trapperSpawnRate, false, "unitMeters"); trapperPenaltyTime = CustomOption.Create(8023, Types.Impostor, "trapperPenaltyTime", 10f, 0f, 50f, 1f, trapperSpawnRate, false, "unitSeconds"); - trapperBonusTime = CustomOption.Create(8024, Types.Impostor, "trapperBonusTime", 8f, 0f, 9f, 1f, trapperSpawnRate, false, "unitSeconds"); + trapperBonusTime = CustomOption.Create(8024, Types.Impostor, "trapperBonusTime", 10f, 0f, 50f, 1f, trapperSpawnRate, false, "unitSeconds"); mimicSpawnRate = CustomOption.Create(5000, Types.Impostor, cs(MimicK.color, "mimic"), rates, null, true); mimicCountAsOne = CustomOption.Create(5001, Types.Impostor, "mimicCountAsOne", true, mimicSpawnRate); @@ -1213,8 +1216,6 @@ public static void Load() { allowParallelMedBayScans = CustomOption.Create(7, Types.General, "allowParallelMedBayScans", false); shieldFirstKill = CustomOption.Create(8, Types.General, "shieldFirstKill", false); finishTasksBeforeHauntingOrZoomingOut = CustomOption.Create(9, Types.General, "finishTasksBeforeHauntingOrZoomingOut", true); - camsNightVision = CustomOption.Create(11, Types.General, "camsNightVision", false, null, true, heading: "headingNightVision"); - camsNoNightVisionIfImpVision = CustomOption.Create(12, Types.General, "camsNoNightVisionIfImpVision", false, camsNightVision, false); additionalVents = CustomOption.Create(5060, Types.General, "additionalVents", false); specimenVital = CustomOption.Create(5061, Types.General, "specimenVital", false); miraVitals = CustomOption.Create(6075, Types.General, "miraVitals", false); @@ -1223,6 +1224,11 @@ public static void Load() { airshipAdditionalSpawn = CustomOption.Create(6073, Types.General, "airshipAdditionalSpawn", false); fungleElectrical = CustomOption.Create(6074, Types.General, "fungleElectrical", false); randomGameStartPosition = CustomOption.Create(6071, Types.General, "randomGameStartPosition", false); + noticeNewDeadBodies = CustomOption.Create(6098, Types.General, "noticeNewDeadBodies", true); + + camsNightVision = CustomOption.Create(11, Types.General, "camsNightVision", false, null, true, heading: "headingNightVision"); + camsNoNightVisionIfImpVision = CustomOption.Create(12, Types.General, "camsNoNightVisionIfImpVision", false, camsNightVision, false); + activateProps = CustomOption.Create(6083, Types.General, "activateProps", false, null, true, heading: "headingPropSetting"); numAccelTraps = CustomOption.Create(6084, Types.General, "numAccelTraps", 1f, 0f, 5f, 1f, activateProps, false, "unitScrews"); accelerationDuration = CustomOption.Create(6085, Types.General, "accelerationDuration", 5f, 1f, 20f, 1f, activateProps, false, "unitSeconds"); diff --git a/TheOtherRoles/Main.cs b/TheOtherRoles/Main.cs index 315602f..7fcd830 100644 --- a/TheOtherRoles/Main.cs +++ b/TheOtherRoles/Main.cs @@ -60,6 +60,7 @@ public class TheOtherRolesPlugin : BasePlugin public static ConfigEntry ShowPopUpVersion { get; set; } public static ConfigEntry ToggleCursor { get; set; } public static ConfigEntry ShowChatNotifications { get; set; } + public static ConfigEntry ShowVentsOnMap { get; set; } public static Sprite ModStamp; @@ -113,7 +114,8 @@ public override void Load() { EnableSoundEffects = Config.Bind("Custom", "Enable Sound Effects", true); EnableHorseMode = Config.Bind("Custom", "Enable Horse Mode", false); ShowPopUpVersion = Config.Bind("Custom", "Show PopUp", "0"); - ShowChatNotifications = Config.Bind("Custom", "Show Chat Notifications", true); + ShowChatNotifications = Config.Bind("Custom", "Show Chat Notifications", true); + ShowVentsOnMap = Config.Bind("Custom", "Show Vent Positions On Minimap", false); Ip = Config.Bind("Custom", "Custom Server IP", "127.0.0.1"); Port = Config.Bind("Custom", "Custom Server Port", (ushort)22023); diff --git a/TheOtherRoles/MapOptions.cs b/TheOtherRoles/MapOptions.cs index f9a213a..29b7102 100644 --- a/TheOtherRoles/MapOptions.cs +++ b/TheOtherRoles/MapOptions.cs @@ -20,6 +20,7 @@ static class TORMapOptions { public static bool enableHorseMode = false; public static bool shieldFirstKill = false; public static bool ShowChatNotifications = true; + public static bool ShowVentsOnMap = true; public static CustomGamemodes gameMode = CustomGamemodes.Classic; // Updating values @@ -56,6 +57,7 @@ public static void reloadPluginOptions() { enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value; enableHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; ShowChatNotifications = TheOtherRolesPlugin.ShowChatNotifications.Value; + ShowVentsOnMap = TheOtherRolesPlugin.ShowVentsOnMap.Value; //Patches.ShouldAlwaysHorseAround.isHorseMode = TheOtherRolesPlugin.EnableHorseMode.Value; } diff --git a/TheOtherRoles/Patches/ClientOptionsPatch.cs b/TheOtherRoles/Patches/ClientOptionsPatch.cs index c7cfc24..d125ca5 100644 --- a/TheOtherRoles/Patches/ClientOptionsPatch.cs +++ b/TheOtherRoles/Patches/ClientOptionsPatch.cs @@ -7,6 +7,7 @@ using UnityEngine.Events; using static UnityEngine.UI.Button; using Object = UnityEngine.Object; +using System.Linq; namespace TheOtherRoles.Patches { @@ -23,6 +24,7 @@ public static class ClientOptionsPatch new SelectionBehaviour("toggleCursor", () => TORMapOptions.toggleCursor = TheOtherRolesPlugin.ToggleCursor.Value = !TheOtherRolesPlugin.ToggleCursor.Value, TheOtherRolesPlugin.ToggleCursor.Value), new SelectionBehaviour("enableSoundEffects", () => TORMapOptions.enableSoundEffects = TheOtherRolesPlugin.EnableSoundEffects.Value = !TheOtherRolesPlugin.EnableSoundEffects.Value, TheOtherRolesPlugin.EnableSoundEffects.Value), new("showChatNotification", () => TORMapOptions.ShowChatNotifications = TheOtherRolesPlugin.ShowChatNotifications.Value = !TheOtherRolesPlugin.ShowChatNotifications.Value, TheOtherRolesPlugin.ShowChatNotifications.Value), + new("showVentsOnMap", () => TORMapOptions.ShowVentsOnMap = TheOtherRolesPlugin.ShowVentsOnMap.Value = !TheOtherRolesPlugin.ShowVentsOnMap.Value, TheOtherRolesPlugin.ShowVentsOnMap.Value), }; private static GameObject popUp; @@ -31,6 +33,7 @@ public static class ClientOptionsPatch private static ToggleButtonBehaviour moreOptions; private static TextMeshPro titleTextTitle; private static List modButtons = new(); + private static int page = 1; private static ToggleButtonBehaviour buttonPrefab; private static Vector3? _origin; @@ -156,17 +159,17 @@ private static void CheckSetTitle() private static void SetUpOptions() { - if (popUp.transform.GetComponentInChildren()) return; + //if (popUp.transform.GetComponentInChildren()) return; foreach (var button in modButtons) { if (button != null) GameObject.Destroy(button.gameObject); } modButtons = new List(); - - for (var i = 0; i < AllOptions.Length; i++) + int length = (page * 10) < AllOptions.Length ? page * 10 : AllOptions.Length; + for (var i = 0; i + ((page - 1) * 10) < length; i++) { - var info = AllOptions[i]; + var info = AllOptions[i + ((page - 1) * 10)]; var button = Object.Instantiate(buttonPrefab, popUp.transform); var pos = new Vector3(i % 2 == 0 ? -1.17f : 1.17f, 1.3f - i / 2 * 0.8f, -.5f); @@ -213,6 +216,59 @@ private static void SetUpOptions() modButtons.Add(button); } + + if (page * 10 < AllOptions.Length) + { + var button = Object.Instantiate(buttonPrefab, popUp.transform); + var pos = new Vector3(1.2f, -2.5f, -0.5f); + var transform = button.transform; + transform.localPosition = pos; + button.Text.text = ModTranslation.getString("next"); + button.Text.fontSizeMin = button.Text.fontSizeMax = 2.2f; + button.Text.font = Object.Instantiate(titleText.font); + button.Text.GetComponent().sizeDelta = new Vector2(2, 2); + button.gameObject.SetActive(true); + var passiveButton = button.GetComponent(); + var colliderButton = button.GetComponent(); + colliderButton.size = new Vector2(2.2f, .7f); + passiveButton.OnClick = new ButtonClickedEvent(); + passiveButton.OnMouseOut = new UnityEvent(); + passiveButton.OnMouseOver = new UnityEvent(); + passiveButton.OnClick.AddListener((Action)(() => + { + page += 1; + SetUpOptions(); + })); + passiveButton.OnMouseOver.AddListener((Action)(() => button.Background.color = new Color32(34, 139, 34, byte.MaxValue))); + passiveButton.OnMouseOut.AddListener((Action)(() => button.Background.color = Color.white)); + modButtons.Add(button); + } + if (page > 1) + { + var button = Object.Instantiate(buttonPrefab, popUp.transform); + var pos = new Vector3(-1.2f, -2.5f, -0.5f); + var transform = button.transform; + transform.localPosition = pos; + button.Text.text = ModTranslation.getString("previous"); + button.Text.fontSizeMin = button.Text.fontSizeMax = 2.2f; + button.Text.font = Object.Instantiate(titleText.font); + button.Text.GetComponent().sizeDelta = new Vector2(2, 2); + button.gameObject.SetActive(true); + var passiveButton = button.GetComponent(); + var colliderButton = button.GetComponent(); + colliderButton.size = new Vector2(2.2f, .7f); + passiveButton.OnClick = new ButtonClickedEvent(); + passiveButton.OnMouseOut = new UnityEvent(); + passiveButton.OnMouseOver = new UnityEvent(); + passiveButton.OnClick.AddListener((Action)(() => + { + page -= 1; + SetUpOptions(); + })); + passiveButton.OnMouseOver.AddListener((Action)(() => button.Background.color = new Color32(34, 139, 34, byte.MaxValue))); + passiveButton.OnMouseOut.AddListener((Action)(() => button.Background.color = Color.white)); + modButtons.Add(button); + } } private static IEnumerable GetAllChilds(this GameObject Go) diff --git a/TheOtherRoles/Patches/MapBehaviourPatch.cs b/TheOtherRoles/Patches/MapBehaviourPatch.cs index ec7cc91..0f27544 100644 --- a/TheOtherRoles/Patches/MapBehaviourPatch.cs +++ b/TheOtherRoles/Patches/MapBehaviourPatch.cs @@ -19,7 +19,17 @@ class MapBehaviourPatch { public static Dictionary herePoints = new(); public static SpriteRenderer targetHerePoint; - public static Dictionary impostorHerePoint; + public static Dictionary impostorHerePoint; + + public static Sprite Vent = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Vent.png", 150f); + + public static List> VentNetworks = new(); + + public static Dictionary mapIcons = new(); + + public static Sprite doorClosedSprite; + public static Dictionary doorMarks; + public static Il2CppArrayBase plainDoors = null; public static Dictionary> realTasks = new(); public static void resetRealTasks() @@ -60,7 +70,26 @@ public static void shareRealTasks() public static void reset() { herePoints = new(); - impostorHerePoint = new(); + impostorHerePoint = new(); + foreach (var mapIcon in mapIcons.Values) + { + mapIcon.Destroy(); + } + mapIcons = new(); + VentNetworks = new(); + if (doorMarks != null) + { + foreach (var mark in doorMarks.Values) + { + if (mark != null) UnityEngine.Object.Destroy(mark?.gameObject); + } + doorMarks.Clear(); + doorMarks = null; + } + if (plainDoors != null) + { + plainDoors = null; + } } private static bool evilTrackerShowTask(MapTaskOverlay __instance) @@ -174,6 +203,48 @@ static void Postfix(MapBehaviour __instance) { impostorHerePoint[p.PlayerId].transform.localPosition = pos; } } + } + + if (EvilHacker.canSeeDoorStatus && ((EvilHacker.evilHacker != null && CachedPlayer.LocalPlayer.PlayerId == EvilHacker.evilHacker.PlayerId) || EvilHacker.isInherited())) + { + if (doorClosedSprite == null) + { + doorClosedSprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.Cross.png", 500f); + } + doorMarks ??= new(); + plainDoors = GameObject.FindObjectsOfType(); + foreach (var door in plainDoors) + { + Vector3 pos = door.gameObject.transform.position / MapUtilities.CachedShipStatus.MapScale; + pos.z = -10f; + String key = $"{pos.x},{pos.y}"; + SpriteRenderer mark; + if (doorMarks.ContainsKey(key)) + { + mark = doorMarks[key]; + if (mark == null) mark = GameObject.Instantiate(__instance.HerePoint, __instance.HerePoint.transform.parent); + } + else + { + mark = GameObject.Instantiate(__instance.HerePoint, __instance.HerePoint.transform.parent); + doorMarks.Add(key, mark); + } + if (mark != null) + { + if (!door.IsOpen) + { + mark.gameObject.SetActive(true); + mark.sprite = doorClosedSprite; + PlayerMaterial.SetColors(0, mark); + mark.transform.localPosition = pos; + mark.gameObject.SetActive(true); + } + else + { + mark.gameObject.SetActive(false); + } + } + } } if (Snitch.snitch != null && CachedPlayer.LocalPlayer.PlayerId == Snitch.snitch.PlayerId && !Snitch.snitch.Data.IsDead && Snitch.mode != Snitch.Mode.Chat) { @@ -211,8 +282,122 @@ static void Postfix(MapBehaviour __instance) { } } } + + foreach (var vent in MapUtilities.CachedShipStatus.AllVents) + { + if (vent.name.StartsWith("JackInThe") && !(PlayerControl.LocalPlayer == Trickster.trickster || PlayerControl.LocalPlayer.Data.IsDead)) continue; //for trickster vents + + if (!TheOtherRolesPlugin.ShowVentsOnMap.Value) + { + if (mapIcons.Count > 0) + { + mapIcons.Values.Do((x) => x.Destroy()); + mapIcons.Clear(); + } + break; + } + + var Instance = DestroyableSingleton.Instance; + var task = PlayerControl.LocalPlayer.myTasks.ToArray().FirstOrDefault(x => x.TaskType == TaskTypes.VentCleaning); + + var location = vent.transform.position / MapUtilities.CachedShipStatus.MapScale; + location.z = -2f; //show above sabotage buttons + + GameObject MapIcon; + if (!mapIcons.ContainsKey($"vent {vent.Id} icon")) + { + MapIcon = GameObject.Instantiate(__instance.HerePoint.gameObject, __instance.HerePoint.transform.parent); + mapIcons.Add($"vent {vent.Id} icon", MapIcon); + } + else + { + MapIcon = mapIcons[$"vent {vent.Id} icon"]; + } + + MapIcon.GetComponent().sprite = Vent; + + MapIcon.name = $"vent {vent.Id} icon"; + MapIcon.transform.localPosition = location; + + if (task?.IsComplete == false && task.FindConsoles()[0].ConsoleId == vent.Id) + { + MapIcon.transform.localScale *= 0.6f; + } + if (vent.name.StartsWith("JackInThe")) + { + MapIcon.GetComponent().sprite = JackInTheBox.getBoxAnimationSprite(0); + MapIcon.transform.localScale = new Vector3(0.5f, 0.5f, 1); + MapIcon.GetComponent().color = vent.isActiveAndEnabled ? Color.yellow : Color.yellow.SetAlpha(0.5f); + } + + if (AllVentsRegistered(Instance)) + { + var array = VentNetworks.ToArray(); + foreach (var connectedgroup in VentNetworks) + { + var index = Array.IndexOf(array, connectedgroup); + if (connectedgroup[0].name.StartsWith("JackInThe")) + continue; + connectedgroup.Do(x => GetIcon(x).GetComponent().color = Palette.PlayerColors[index]); + } + continue; + } + + HandleMiraOrSub(); + + var network = GetNetworkFor(vent); + if (network == null) + { + VentNetworks.Add(new(vent.NearbyVents.Where(x => x != null)) { vent }); + } + else + { + if (!network.Any(x => x == vent)) network.Add(vent); + } + } + HudManagerUpdate.CloseSettings(); CustomOverlay.hideInfoOverlay(); + } + + public static List GetNetworkFor(Vent vent) + { + return VentNetworks.FirstOrDefault(x => x.Any(y => y == vent || y == vent.Left || y == vent.Center || y == vent.Right)); + } + + public static bool AllVentsRegistered(MapTaskOverlay __instance) + { + foreach (var vent in MapUtilities.CachedShipStatus.AllVents) + { + if (!vent.isActiveAndEnabled) continue; + var network = GetNetworkFor(vent); + if (network == null || !network.Any(x => x == vent)) return false; + if (!mapIcons.ContainsKey($"vent {vent.Id} icon")) return false; + } + return true; + } + + public static GameObject GetIcon(Vent vent) + { + var icon = mapIcons[$"vent {vent.Id} icon"]; + return icon; + } + + public static void HandleMiraOrSub() + { + if (VentNetworks.Count != 0) return; + + if (Helpers.isMira()) + { + var vents = MapUtilities.CachedShipStatus.AllVents.Where(x => !x.name.Contains("JackInTheBoxVent_")); + VentNetworks.Add(vents.ToList()); + return; + } + if (MapUtilities.CachedShipStatus.Type == SubmergedCompatibility.SUBMERGED_MAP_TYPE) + { + var vents = MapUtilities.CachedShipStatus.AllVents.Where(x => x.Id is 12 or 13 or 15 or 16); + VentNetworks.Add(vents.ToList()); + } } } } diff --git a/TheOtherRoles/Patches/MeetingPatch.cs b/TheOtherRoles/Patches/MeetingPatch.cs index cd49813..fed9daa 100644 --- a/TheOtherRoles/Patches/MeetingPatch.cs +++ b/TheOtherRoles/Patches/MeetingPatch.cs @@ -17,7 +17,8 @@ using Il2CppSystem.Reflection; using TheOtherRoles.MetaContext; using BepInEx.Unity.IL2CPP.Utils.Collections; - +using System.IO; + namespace TheOtherRoles.Patches { [HarmonyPatch] class MeetingHudPatch { @@ -616,7 +617,7 @@ static void guesserOnClick(int buttonTarget, MeetingHud __instance) { static void yasunaOnClick(int buttonTarget, MeetingHud __instance) { if (Yasuna.yasuna != null && (Yasuna.yasuna.Data.IsDead || Yasuna.specialVoteTargetPlayerId != byte.MaxValue)) return; - if (!(__instance.state == MeetingHud.VoteStates.Voted || __instance.state == MeetingHud.VoteStates.NotVoted || __instance.state == MeetingHud.VoteStates.Results)) return; + if (__instance.state is not (MeetingHud.VoteStates.Voted or MeetingHud.VoteStates.NotVoted or MeetingHud.VoteStates.Results)) return; if (__instance.playerStates[buttonTarget].AmDead) return; var yasunaPVA = __instance.playerStates.FirstOrDefault(t => t.TargetPlayerId == Yasuna.yasuna.PlayerId); @@ -627,29 +628,15 @@ static void yasunaOnClick(int buttonTarget, MeetingHud __instance) } byte targetId = __instance.playerStates[buttonTarget].TargetPlayerId; - RPCProcedure.yasunaSpecialVote(CachedPlayer.LocalPlayer.PlayerControl.PlayerId, targetId); MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YasunaSpecialVote, Hazel.SendOption.Reliable, -1); writer.Write(CachedPlayer.LocalPlayer.PlayerControl.PlayerId); writer.Write(targetId); AmongUsClient.Instance.FinishRpcImmediately(writer); + RPCProcedure.yasunaSpecialVote(CachedPlayer.LocalPlayer.PlayerControl.PlayerId, targetId); if (!CachedPlayer.LocalPlayer.PlayerControl.Data.Role.IsImpostor) Yasuna.yasunaAcTokenChallenge.Value.targetId = targetId; else Yasuna.evilYasunaAcTokenChallenge.Value.targetId = targetId; - __instance.SkipVoteButton.gameObject.SetActive(false); - for (int i = 0; i < __instance.playerStates.Length; i++) - { - PlayerVoteArea voteArea = __instance.playerStates[i]; - voteArea.ClearButtons(); - Transform t = voteArea.transform.FindChild("SpecialVoteButton"); - if (t != null && voteArea.TargetPlayerId != targetId) - t.gameObject.SetActive(false); - } - if (AmongUsClient.Instance.AmHost) - { - PlayerControl target = Helpers.playerById(targetId); - if (target != null) - MeetingHud.Instance.CmdCastVote(CachedPlayer.LocalPlayer.PlayerControl.PlayerId, target.PlayerId); - } + __instance.playerStates[buttonTarget].VoteForMe(); } [HarmonyPatch(typeof(PlayerVoteArea), nameof(PlayerVoteArea.Select))] @@ -992,6 +979,37 @@ public static void Postfix(MeetingIntroAnimation __instance, ref Il2CppSystem.Co } } + // From Town-Of-Us-R + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CoIntro))] + public static class ShowNewDead + { + public static Sprite megaphone => Helpers.loadSpriteFromResources("TheOtherRoles.Resources.DeadMegaphone.png", 100f); + public static readonly List ReportedBodies = new(); + public static void Postfix(MeetingHud __instance, NetworkedPlayerInfo reportedBody, Il2CppReferenceArray deadBodies) + { + ReportedBodies.Clear(); + if (!CustomOptionHolder.noticeNewDeadBodies.getBool()) return; + foreach (var player in __instance.playerStates) + { + if (deadBodies?.Any(x => x.PlayerId == player.TargetPlayerId) == true) + { + if (reportedBody != null && player.TargetPlayerId == reportedBody.PlayerId) + { + player.Megaphone.gameObject.SetActive(true); + player.Megaphone.enabled = true; + player.Megaphone.transform.localEulerAngles = Vector3.zero; + player.Megaphone.transform.localScale = Vector3.one; + player.Megaphone.sprite = megaphone; + } + player.HighlightedFX.enabled = true; + player.HighlightedFX.color = Palette.ImpostorRed; + + ReportedBodies.Add(player.TargetPlayerId); + } + } + } + } + [HarmonyPatch(typeof(MeetingIntroAnimation), nameof(MeetingIntroAnimation.Init))] public static class MeetingIntroAnimationInitPatch { @@ -1243,6 +1261,15 @@ static void Postfix(MeetingHud __instance) { __instance.StartCoroutine(Effects.SwayX(playerState.transform)); } } + + if (CustomOptionHolder.noticeNewDeadBodies.getBool()) + { + foreach (var state in __instance.playerStates) + { + if (ShowNewDead.ReportedBodies?.Contains(state.TargetPlayerId) == true) + if (!state.HighlightedFX.enabled) state.HighlightedFX.enabled = true; + } + } } } diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index b7f9092..aaffc4f 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -1922,6 +1922,7 @@ public static void miniCooldownUpdate() { HudManagerStartPatch.witchSpellButton.MaxTimer = (Witch.cooldown + Witch.currentCooldownAddition) * multiplier; HudManagerStartPatch.assassinButton.MaxTimer = Assassin.cooldown * multiplier; HudManagerStartPatch.thiefKillButton.MaxTimer = Thief.cooldown * multiplier; + HudManagerStartPatch.serialKillerButton.MaxTimer = SerialKiller.suicideTimer * (Mini.isGrownUp() ? 2f : 1f); } } @@ -2550,8 +2551,8 @@ public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)]PlayerC { if (Trap.isTrapped(target) && !Trapper.isTrapKill) // トラップにかかっている対象をキルした場合のボーナス { - Trapper.trapper.killTimer = GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown - Trapper.bonusTime; - HudManagerStartPatch.trapperSetTrapButton.Timer = Trapper.cooldown - Trapper.bonusTime; + Trapper.trapper.killTimer = Mathf.Max(1f, GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown - Trapper.bonusTime); + HudManagerStartPatch.trapperSetTrapButton.Timer = Mathf.Max(1f, Trapper.cooldown - Trapper.bonusTime); } else if (Trap.isTrapped(target) && Trapper.isTrapKill) // トラップキルした場合のペナルティ { diff --git a/TheOtherRoles/Patches/ShipStatusPatch.cs b/TheOtherRoles/Patches/ShipStatusPatch.cs index e308649..e5ede0c 100644 --- a/TheOtherRoles/Patches/ShipStatusPatch.cs +++ b/TheOtherRoles/Patches/ShipStatusPatch.cs @@ -117,7 +117,7 @@ public static bool Prefix(ShipStatus __instance) GameOptionsManager.Instance.currentNormalGameOptions.NumShortTasks = Mathf.RoundToInt(CustomOptionHolder.hideNSeekShortTasks.getFloat()); GameOptionsManager.Instance.currentNormalGameOptions.NumLongTasks = Mathf.RoundToInt(CustomOptionHolder.hideNSeekLongTasks.getFloat()); } - + MapBehaviourPatch.VentNetworks.Clear(); return true; } diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 5d8c3d6..7262f43 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -217,11 +217,10 @@ public static bool Prefix(KillButton __instance) { [HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.Show))] public static class MapBehaviourShowPatch { public static void Prefix(MapBehaviour __instance, ref MapOptions opts) { - if (!CachedPlayer.LocalPlayer.PlayerControl.roleCanUseSabotage()) { - if (opts.Mode == MapOptions.Modes.Sabotage) opts.Mode = MapOptions.Modes.Normal; - } - else { - if (opts.Mode == MapOptions.Modes.Normal) opts.Mode = MapOptions.Modes.Sabotage; + bool blockSabotageJanitor = Janitor.janitor != null && Janitor.janitor == CachedPlayer.LocalPlayer.PlayerControl; + bool blockSabotageMafioso = Mafioso.mafioso != null && Mafioso.mafioso == CachedPlayer.LocalPlayer.PlayerControl && Godfather.godfather != null && !Godfather.godfather.Data.IsDead; + if (blockSabotageJanitor || blockSabotageMafioso) { + if (opts.Mode == MapOptions.Modes.Sabotage) opts.Mode = MapOptions.Modes.Normal; } } } diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index b6c600b..3f0c69d 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -3473,12 +3473,6 @@ static void Postfix([HarmonyArgument(0)]byte callId, [HarmonyArgument(1)]Message byte id = reader.ReadByte(); byte targetId = reader.ReadByte(); RPCProcedure.yasunaSpecialVote(id, targetId); - if (AmongUsClient.Instance.AmHost && Yasuna.isYasuna(id)) - { - int clientId = Helpers.GetClientId(Yasuna.yasuna); - MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(CachedPlayer.LocalPlayer.PlayerControl.NetId, (byte)CustomRPC.YasunaSpecialVote_DoCastVote, Hazel.SendOption.Reliable, clientId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } break; case (byte)CustomRPC.YasunaSpecialVote_DoCastVote: RPCProcedure.yasunaSpecialVote_DoCastVote(); diff --git a/TheOtherRoles/Resources/DeadCorpse.png b/TheOtherRoles/Resources/DeadCorpse.png new file mode 100644 index 0000000..32e8c9b Binary files /dev/null and b/TheOtherRoles/Resources/DeadCorpse.png differ diff --git a/TheOtherRoles/Resources/DeadMegaphone.png b/TheOtherRoles/Resources/DeadMegaphone.png new file mode 100644 index 0000000..bb8468a Binary files /dev/null and b/TheOtherRoles/Resources/DeadMegaphone.png differ diff --git a/TheOtherRoles/Resources/Vent.png b/TheOtherRoles/Resources/Vent.png new file mode 100644 index 0000000..29fa8f4 Binary files /dev/null and b/TheOtherRoles/Resources/Vent.png differ diff --git a/TheOtherRoles/Resources/stringData.json b/TheOtherRoles/Resources/stringData.json index 33d568f..27e200a 100644 --- a/TheOtherRoles/Resources/stringData.json +++ b/TheOtherRoles/Resources/stringData.json @@ -199,6 +199,10 @@ "13": "\u968f\u673a\u51fa\u751f\u70b9", "14": "\u96a8\u6a5f\u51fa\u751f\u9ede" }, + "noticeNewDeadBodies": { + "0": "Notice New Dead Bodies", + "13": "\u4f1a\u8bae\u4e2d\u7a81\u51fa\u663e\u793a\u672c\u8f6e\u6b7b\u4ea1\u73a9\u5bb6" + }, "activateProps": { "0": "Activate Props", "11": "\u5c0f\u9053\u5177\u3092\u6709\u52b9\u5316", @@ -740,14 +744,6 @@ "13": "\u9690\u853d\u6301\u7eed\u65f6\u95f4", "14": "\u96b1\u853d\u6301\u7e8c\u6642\u9593" }, - "camouflagerEnableEffect": { - "0": "Enable Camo Rough Effect", - "13": "\u542f\u7528\u9690\u853d\u6a21\u7cca\u89c6\u91ce" - }, - "camouflagerImpIgnore": { - "0": "Impostors Ignore Camo Effect", - "13": "\u5185\u9b3c\u65e0\u89c6\u9690\u853d\u6a21\u7cca\u6548\u679c" - }, "vampire": { "0": "Vampire", "11": "\u30f4\u30a1\u30f3\u30d1\u30a4\u30a2", @@ -3669,6 +3665,18 @@ "11": "\u753b\u9762\u4e0a\u90e8\u306e\u30c1\u30e3\u30c3\u30c8\u901a\u77e5\u3092\u8868\u793a\u3059\u308b", "13": "\u542f\u7528\u804a\u5929\u63d0\u793a" }, + "showVentsOnMap": { + "0": "Show Vents On Map", + "13": "\u5728\u5730\u56fe\u4e0a\u663e\u793a\u7ba1\u9053\u4f4d\u7f6e" + }, + "next": { + "0": "Next", + "13": "\u4e0b\u4e00\u9875" + }, + "previous": { + "0": "Previous", + "13": "\u4e0a\u4e00\u9875" + }, "modOptionsText": { "0": "Mod Options...", "11": "MOD\u30aa\u30d7\u30b7\u30e7\u30f3", @@ -5529,6 +5537,10 @@ "13": "\u90aa\u6076\u7684\u9ed1\u5ba2\u53ef\u4ee5\u5c06\u8c7a\u72fc\u53d8\u4e3a\u53db\u5f92", "14": "\u90aa\u60e1\u7684\u9ed1\u5ba2\u53ef\u4ee5\u5c07\u8c7a\u72fc\u8b8a\u70ba\u53db\u5f92" }, + "evilHackerCanSeeDoorStatus": { + "0": "Evil HAcker Can See Door Status", + "13": "\u90aa\u6076\u7684\u9ed1\u5ba2\u53ef\u4ee5\u770b\u89c1\u95e8\u5173\u95ed\u72b6\u6001" + }, "createdMadmateCanDieToSheriff": { "0": "Created Madmate Can Die To Sheriff", "11": "\u4efb\u547d\u3057\u305f\u30de\u30c3\u30c9\u30e1\u30a4\u30c8\u306f\u30b7\u30a7\u30ea\u30d5\u306b\u5207\u3089\u308c\u308b\u304b", diff --git a/TheOtherRoles/TheOtherRoles.cs b/TheOtherRoles/TheOtherRoles.cs index f4e60fd..d4f34b2 100644 --- a/TheOtherRoles/TheOtherRoles.cs +++ b/TheOtherRoles/TheOtherRoles.cs @@ -3635,7 +3635,8 @@ public static class EvilHacker public static PlayerControl evilHacker; public static Color color = Palette.ImpostorRed; public static bool canHasBetterAdmin = false; - public static bool canCreateMadmate = false; + public static bool canCreateMadmate = false; + public static bool canSeeDoorStatus = true; public static bool canCreateMadmateFromJackal; public static bool canInheritAbility; public static PlayerControl fakeMadmate; @@ -3685,7 +3686,8 @@ public static void clearAndReload() canCreateMadmate = CustomOptionHolder.evilHackerCanCreateMadmate.getBool(); canHasBetterAdmin = CustomOptionHolder.evilHackerCanHasBetterAdmin.getBool(); canCreateMadmateFromJackal = CustomOptionHolder.evilHackerCanCreateMadmateFromJackal.getBool(); - canInheritAbility = CustomOptionHolder.evilHackerCanInheritAbility.getBool(); + canInheritAbility = CustomOptionHolder.evilHackerCanInheritAbility.getBool(); + canSeeDoorStatus = CustomOptionHolder.evilHackerCanSeeDoorStatus.getBool(); acTokenChallenge = null; } }