diff --git a/CHANGELOG.md b/CHANGELOG.md index a6c7258..3c42cd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ -v1.1.2.1更新日志 +v1.1.2.2更新日志 -* 修复掷弹兵使用技能时可能会导致所有玩家游戏卡死的问题 -* 怨灵: 新增选项 "拾取尸体后本轮会议结束才可复活" -* 还有其它一些小优化 \ No newline at end of file +* 优化游戏选项中常规选项的页面排版显示 +* 律师的目标如果掉线则律师会变成起诉人 + +问题修复: + +* 炸弹狂、纵火狂技能无法寻到目标 +* 怨灵会被分配到豺狼阵营 +* 非红狼阵营的职业无法使用键盘进入通风口 +* 污点证人在部分情况下无法得分 +* 鹈鹕被击杀时会卡在原地 \ No newline at end of file diff --git a/Strings.xlsx b/Strings.xlsx index 50efa15..a01d09e 100644 Binary files a/Strings.xlsx and b/Strings.xlsx differ diff --git a/TheOtherRoles/Buttons/Buttons.cs b/TheOtherRoles/Buttons/Buttons.cs index 83efdf6..9e1ecdd 100644 --- a/TheOtherRoles/Buttons/Buttons.cs +++ b/TheOtherRoles/Buttons/Buttons.cs @@ -257,7 +257,7 @@ public static void resetTimeMasterButton() SoundEffectsManager.stop("timemasterShield"); } - public static PlayerControl SetTarget(IEnumerable untarget = null, bool onlyCrewmates = false, + public static PlayerControl SetTarget(List untarget = null, bool onlyCrewmates = false, bool targetInVents = false, float distances = 0f, PlayerControl targetingPlayer = null) { return PlayerControlFixedUpdatePatch.SetTarget(onlyCrewmates, targetInVents, untarget, KillDistances: distances, targetingPlayer: targetingPlayer); @@ -586,11 +586,10 @@ public static void createButtonsPostfix(HudManager __instance) if (murderAttemptResult == MurderAttemptResult.PerformKill) { byte targetId = 0; - + var DeathReason = CustomDeathReason.SheriffKill; if (Sheriff.sheriffCanKillNeutral(target)) { targetId = target.PlayerId; - GameHistory.RpcOverrideDeathReasonAndKiller(target, CustomDeathReason.SheriffKill, PlayerControl.LocalPlayer); } else { @@ -598,21 +597,22 @@ public static void createButtonsPostfix(HudManager __instance) { case 0: targetId = PlayerControl.LocalPlayer.PlayerId; - GameHistory.RpcOverrideDeathReasonAndKiller(PlayerControl.LocalPlayer, CustomDeathReason.SheriffMisfire, PlayerControl.LocalPlayer); + DeathReason = CustomDeathReason.SheriffMisfire; break; case 1: targetId = target.PlayerId; - GameHistory.RpcOverrideDeathReasonAndKiller(target, CustomDeathReason.SheriffMisadventure, PlayerControl.LocalPlayer); + DeathReason = CustomDeathReason.SheriffMisadventure; break; case 2: targetId = target.PlayerId; + DeathReason = CustomDeathReason.SheriffMisadventure; + var killWriter2 = StartRPC(PlayerControl.LocalPlayer.NetId, CustomRPC.UncheckedMurderPlayer); killWriter2.Write(PlayerControl.LocalPlayer.PlayerId); killWriter2.Write(PlayerControl.LocalPlayer.PlayerId); killWriter2.Write(byte.MaxValue); killWriter2.EndRPC(); RPCProcedure.uncheckedMurderPlayer(PlayerControl.LocalPlayer.PlayerId, PlayerControl.LocalPlayer.PlayerId, byte.MaxValue); - GameHistory.RpcOverrideDeathReasonAndKiller(target, CustomDeathReason.SheriffMisadventure, PlayerControl.LocalPlayer); GameHistory.RpcOverrideDeathReasonAndKiller(PlayerControl.LocalPlayer, CustomDeathReason.SheriffMisfire, PlayerControl.LocalPlayer); break; } @@ -624,6 +624,7 @@ public static void createButtonsPostfix(HudManager __instance) killWriter.Write(byte.MaxValue); killWriter.EndRPC(); RPCProcedure.uncheckedMurderPlayer(PlayerControl.LocalPlayer.PlayerId, targetId, byte.MaxValue); + GameHistory.RpcOverrideDeathReasonAndKiller(target, DeathReason, PlayerControl.LocalPlayer); } if (murderAttemptResult == MurderAttemptResult.BodyGuardKill) checkMurderAttemptAndKill(PlayerControl.LocalPlayer, target); @@ -2264,7 +2265,7 @@ public static void createButtonsPostfix(HudManager __instance) () => { /* On Click */ - Bomber.currentBombTarget = SetTarget(); + Bomber.currentTarget = SetTarget(); if (Bomber.hasBombPlayer == null) SetPlayerOutline(Bomber.currentTarget, Bomber.color); return Bomber.currentTarget && PlayerControl.LocalPlayer.CanMove; }, diff --git a/TheOtherRoles/Helper/Helpers.cs b/TheOtherRoles/Helper/Helpers.cs index ba079ab..1e11b2c 100644 --- a/TheOtherRoles/Helper/Helpers.cs +++ b/TheOtherRoles/Helper/Helpers.cs @@ -241,7 +241,7 @@ public static bool checkAndDoVetKill(PlayerControl target) return shouldVetKill; } - public static bool isNeutral(PlayerControl player) + public static bool isNeutral(this PlayerControl player) { var roleInfo = RoleInfo.getRoleInfoForPlayer(player, false).FirstOrDefault(); return roleInfo != null && roleInfo.roleType == RoleType.Neutral; @@ -257,8 +257,8 @@ public static bool isKillerNeutral(PlayerControl player) player == Pelican.Player || player == Jackal.Sidekick || player == Pavlovsdogs.pavlovsowner || - Jackal.jackal.Contains(player) || - Pavlovsdogs.pavlovsdogs.Contains(player)); + Jackal.jackal.Any(x => x.PlayerId == player.PlayerId) || + Pavlovsdogs.pavlovsdogs.Any(x => x.PlayerId == player.PlayerId)); } public static bool isEvilNeutral(PlayerControl player) diff --git a/TheOtherRoles/Helper/ObjectHelper.cs b/TheOtherRoles/Helper/ObjectHelper.cs new file mode 100644 index 0000000..3a331d6 --- /dev/null +++ b/TheOtherRoles/Helper/ObjectHelper.cs @@ -0,0 +1,25 @@ +using TMPro; +using UnityEngine; + +namespace TheOtherRoles.Helper; + +public static class ObjectHelper +{ + /// + /// オブジェクトのコンポーネントを破棄します + /// + public static void DestroyTranslator(this GameObject obj) + { + if (obj == null) return; + obj.ForEachChild((Il2CppSystem.Action)DestroyTranslator); + TextTranslatorTMP[] translator = obj.GetComponentsInChildren(true); + translator?.Do(Object.Destroy); + } + /// + /// オブジェクトのコンポーネントを破棄します + /// + public static void DestroyTranslatorL(this MonoBehaviour obj) => obj?.gameObject?.DestroyTranslator(); + + public static void SetActive(this Transform tf, bool b) => tf.gameObject.SetActive(b); + public static void SetActive(this TextMeshPro tf, bool b) => tf.gameObject.SetActive(b); +} \ No newline at end of file diff --git a/TheOtherRoles/Modules/Debugger.cs b/TheOtherRoles/Modules/Debugger.cs index 86c581f..3765d76 100644 --- a/TheOtherRoles/Modules/Debugger.cs +++ b/TheOtherRoles/Modules/Debugger.cs @@ -1,4 +1,4 @@ -using static TheOtherRoles.Options.ModOption; +using static TheOtherRoles.Options.ModOption; namespace TheOtherRoles.Modules; @@ -34,5 +34,4 @@ public static void Postfix(EndGameNavigation __instance) __instance.NextGame(); } } - } diff --git a/TheOtherRoles/Modules/KeyboardHandler.cs b/TheOtherRoles/Modules/KeyboardHandler.cs index e20e679..112b725 100644 --- a/TheOtherRoles/Modules/KeyboardHandler.cs +++ b/TheOtherRoles/Modules/KeyboardHandler.cs @@ -55,6 +55,13 @@ private static void Postfix(KeyboardJoystick __instance) GameStartManager.Instance.countDownTimer = 0; } } + if (PlayerControl.LocalPlayer.IsAlive() && !PlayerControl.LocalPlayer.isImpostor()) + { + if (KeyboardJoystick.player.GetButtonDown(50)) + { + DestroyableSingleton.Instance.ImpostorVentButton.DoClick(); + } + } } public static string RandomString(int length) { diff --git a/TheOtherRoles/Modules/SimpleButton.cs b/TheOtherRoles/Modules/SimpleButton.cs new file mode 100644 index 0000000..4db9109 --- /dev/null +++ b/TheOtherRoles/Modules/SimpleButton.cs @@ -0,0 +1,95 @@ +using System; +using TMPro; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace TheOtherRoles.Modules; + +public class SimpleButton +{ + /// 新しいボタンを作成する + /// 親オブジェクト + /// オブジェクト名 + /// 通常時の背景色 + /// マウスホバー時の背景色 + /// クリック時に発火するアクション + /// ボタンのラベル + /// ボタンの大きさ + /// 初期状態でアクティブにするかどうか(デフォルトtrue) + public SimpleButton( + Transform parent, + string name, + Vector3 localPosition, + Color32 normalColor, + Color32 hoverColor, + Action action, + string label, + bool isActive = true) + { + if (baseButton == null) + throw new InvalidOperationException("baseButtonが未設定"); + + Button = Object.Instantiate(baseButton, parent); + Label = Button.transform.Find("FontPlacer/Text_TMP").GetComponent(); + NormalSprite = Button.inactiveSprites.GetComponent(); + HoverSprite = Button.activeSprites.GetComponent(); + buttonCollider = Button.GetComponent(); + + // ラベルをセンタリング + var container = Label.transform.parent; + Object.Destroy(Label.GetComponent()); + container.SetLocalX(0f); + Label.transform.SetLocalX(0f); + Label.horizontalAlignment = HorizontalAlignmentOptions.Center; + + Button.name = name; + Button.transform.localPosition = localPosition; + NormalSprite.color = normalColor; + HoverSprite.color = hoverColor; + Button.OnClick.AddListener(action); + Label.text = label; + Button.gameObject.SetActive(isActive); + } + public PassiveButton Button { get; } + public TextMeshPro Label { get; } + public SpriteRenderer NormalSprite { get; } + public SpriteRenderer HoverSprite { get; } + private readonly BoxCollider2D buttonCollider; + private Vector2 _scale; + public Vector2 Scale + { + get => _scale; + set => _scale = NormalSprite.size = HoverSprite.size = buttonCollider.size = value; + } + private float _fontSize; + public float FontSize + { + get => _fontSize; + set => _fontSize = Label.fontSize = Label.fontSizeMin = Label.fontSizeMax = value; + } + + private static PassiveButton baseButton; + public static void SetBase(PassiveButton passiveButton) + { + if (baseButton != null || passiveButton == null) + return; + // 複製 + baseButton = Object.Instantiate(passiveButton); + var label = baseButton.transform.Find("FontPlacer/Text_TMP").GetComponent(); + baseButton.gameObject.SetActive(false); + // シーン切替時に破棄されないようにする + Object.DontDestroyOnLoad(baseButton); + baseButton.name = "YuET_SimpleButtonBase"; + // 不要なコンポーネントを無効化 + Object.Destroy(baseButton.GetComponent()); + label.DestroyTranslatorL(); + label.fontSize = label.fontSizeMax = label.fontSizeMin = 3.5f; + label.enableWordWrapping = false; + label.text = "YuET SIMPLE BUTTON BASE"; + // 当たり判定がズレてるのを直す + var buttonCollider = baseButton.GetComponent(); + buttonCollider.offset = new(0f, 0f); + baseButton.OnClick = new(); + } + public static bool IsNullOrDestroyed(SimpleButton button) => button == null || button.Button == null; +} diff --git a/TheOtherRoles/Objects/Trap.cs b/TheOtherRoles/Objects/Trap.cs index c860856..e016b0d 100644 --- a/TheOtherRoles/Objects/Trap.cs +++ b/TheOtherRoles/Objects/Trap.cs @@ -157,7 +157,7 @@ public static void Update() target = trap; } } - if (target != null && player.PlayerId != Trapper.trapper.PlayerId && !player.Data.IsDead) + if (target?.revealed == false && player.PlayerId != Trapper.trapper.PlayerId && player.IsAlive()) { var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.TriggerTrap, SendOption.Reliable, -1); @@ -167,7 +167,6 @@ public static void Update() RPCProcedure.triggerTrap(player.PlayerId, (byte)target.instanceId); } - if (!player.Data.IsDead || player.PlayerId == Trapper.trapper.PlayerId) return; foreach (var trap in traps.Where(trap => !trap.trap.active)) trap.trap.SetActive(true); diff --git a/TheOtherRoles/Options/CustomOptionHolder.cs b/TheOtherRoles/Options/CustomOptionHolder.cs index 88c148f..a540f58 100644 --- a/TheOtherRoles/Options/CustomOptionHolder.cs +++ b/TheOtherRoles/Options/CustomOptionHolder.cs @@ -16,6 +16,8 @@ public class CustomOptionHolder public static string[] presets = ["预设 1", "预设 2", "预设 3", "Skeld预设", "Mira预设", "Polus预设", "Airship预设", "Fungle预设", "Submerged预设"]; + public static string[] mapOptions = ["ExpandOptions", "CollapseOptions"]; + public static CustomOption presetSelection; public static CustomOption neutralRolesCountMin; public static CustomOption neutralRolesCountMax; @@ -24,6 +26,12 @@ public class CustomOptionHolder public static CustomOption modifiersCountMin; public static CustomOption modifiersCountMax; + public static CustomOption MeetingOptions; + public static CustomOption SaboOptions; + public static CustomOption TaskOptions; + public static CustomOption MapOptions; + public static CustomOption DevicesOption; + public static CustomOption anyPlayerCanStopStart; public static CustomOption enableEventMode; public static CustomOption deadImpsBlockSabotage; @@ -624,6 +632,10 @@ public class CustomOptionHolder public static CustomOption debugMode; public static CustomOption disableGameEnd; + public static CustomOption exiledController; + public static CustomOption exiledReviveRole; + public static CustomOption exiledShowTeamNum; + public static CustomOption enableBetterPolus; public static CustomOption movePolusVents; @@ -700,12 +712,12 @@ private static byte ToByte(float f) public static void Load() { - vanillaSettings = TheOtherRolesPlugin.Instance.Config.Bind("Preset0", "VanillaOptions", ""); + vanillaSettings = Main.Instance.Config.Bind("Preset0", "VanillaOptions", ""); // Role Options presetSelection = Create(0, Types.General, cs(new Color32(204, 204, 0, 255), "presetSelection"), presets, null, true); - anyPlayerCanStopStart = Create(3, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0), "anyPlayerCanStopStart"), false, null, false); + anyPlayerCanStopStart = Create(3, Types.General, cs(new Color(204f / 255f, 204f / 255f, 0), "anyPlayerCanStopStart"), false); neutralRolesCountMin = Create(8, Types.General, cs(new Color32(204, 204, 0, 255), "neutralRolesCountMin"), 2f, 0f, 15f, 1f, null, true); neutralRolesCountMax = Create(9, Types.General, cs(new Color32(204, 204, 0, 255), "neutralRolesCountMax"), 2f, 0f, 15f, 1f); @@ -716,86 +728,96 @@ public static void Load() //-------------------------- Other options 1 - 599 -------------------------- // + //Global options resteButtonCooldown = Create(20, Types.General, "resteButtonCooldown", 20f, 2.5f, 30f, 2.5f, null, true); - maxNumberOfMeetings = Create(21, Types.General, "maxNumberOfMeetings", 10, 0, 15, 1, null, true); - blockSkippingInEmergencyMeetings = Create(22, Types.General, "blockSkippingInEmergencyMeetings", false); - noVoteIsSelfVote = Create(23, Types.General, "noVoteIsSelfVote", false, blockSkippingInEmergencyMeetings); - disableMeeting = Create(36, Types.General, "disableMeeting", false); - shieldFirstKill = Create(24, Types.General, "shieldFirstKill", false); - hidePlayerNames = Create(25, Types.General, "hidePlayerNames", false); - hideOutOfSightNametags = Create(26, Types.General, "hideOutOfSightNametags", true); - hideVentAnimOnShadows = Create(27, Types.General, "hideVentAnimOnShadows", false); - showButtonTarget = Create(28, Types.General, "showButtonTarget", true); - impostorSeeRoles = Create(30, Types.General, cs(Palette.ImpostorRed, "impostorSeeRoles"), false); - blockGameEnd = Create(29, Types.General, cs(Color.yellow, "blockGameEnd"), true); - deadImpsBlockSabotage = Create(32, Types.General, cs(Palette.ImpostorRed, "deadImpsBlockSabotage"), false); - randomLigherPlayer = Create(34, Types.General, "randomLigherPlayer", true); - disableSabotage = Create(35, Types.General, cs(Palette.ImpostorRed, "disableSabotage"), false, null); - allowModGuess = Create(31, Types.General, "allowModGuess", false); - //ghostSpeed = Create(33, Types.General, "ghostSpeed", 1f, 0.75f, 5f, 0.125f); - - guessReVote = Create(221, Types.General, "guessReVote", false, null, true); - guessExtendmeetingTime = Create(222, Types.General, "guessExtendmeetingTime", 15f, 0f, 60f, 5f); - - WireTaskIsRandomOption = Create(44, Types.General, "WireTaskIsRandomOption", false, null, true); - WireTaskNumOption = Create(45, Types.General, "WireTaskNumOption", 3f, 1f, 8f, 1f, WireTaskIsRandomOption); - transparentTasks = Create(40, Types.General, "transparentTasks", false); - disableMedbayWalk = Create(41, Types.General, "disableMedbayWalk", false); - allowParallelMedBayScans = Create(46, Types.General, "allowParallelMedBayScans", false); - finishTasksBeforeHauntingOrZoomingOut = Create(42, Types.General, "finishTasksBeforeHauntingOrZoomingOut", false); - disableTaskGameEnd = Create(43, Types.General, "disableTaskGameEnd", false); + shieldFirstKill = Create(21, Types.General, "shieldFirstKill", false); + hidePlayerNames = Create(22, Types.General, "hidePlayerNames", false); + hideOutOfSightNametags = Create(23, Types.General, "hideOutOfSightNametags", true); + hideVentAnimOnShadows = Create(24, Types.General, "hideVentAnimOnShadows", false); + showButtonTarget = Create(25, Types.General, "showButtonTarget", true); + impostorSeeRoles = Create(26, Types.General, cs(Palette.ImpostorRed, "impostorSeeRoles"), false); + blockGameEnd = Create(27, Types.General, cs(Color.yellow, "blockGameEnd"), true); + randomLigherPlayer = Create(28, Types.General, "randomLigherPlayer", true); + allowModGuess = Create(29, Types.General, "allowModGuess", false); + randomGameStartPosition = Create(30, Types.General, "randomGameStartPosition", false); + randomGameStartToVents = Create(31, Types.General, "randomGameStartToVents", true, randomGameStartPosition); + //ghostSpeed = Create(32, Types.General, "ghostSpeed", 1f, 0.75f, 5f, 0.125f); + + //Meeting options + MeetingOptions = Create(100, Types.General, cs(new Color32(255, 85, 234, byte.MaxValue), "MeetingOptions"), false, null, true); + disableMeeting = Create(101, Types.General, "disableMeeting", false, MeetingOptions); + maxNumberOfMeetings = Create(102, Types.General, "maxNumberOfMeetings", 10, 0, 15, 1, MeetingOptions); + blockSkippingInEmergencyMeetings = Create(103, Types.General, "blockSkippingInEmergencyMeetings", false, MeetingOptions); + noVoteIsSelfVote = Create(104, Types.General, "noVoteIsSelfVote", false, blockSkippingInEmergencyMeetings); + guessReVote = Create(105, Types.General, "guessReVote", false, MeetingOptions); + guessExtendmeetingTime = Create(106, Types.General, "guessExtendmeetingTime", 15f, 0f, 60f, 5f, guessReVote); + exiledController = Create(107, Types.General, "exileController", false, MeetingOptions); + exiledReviveRole = Create(108, Types.General, "exiledReviveRole", ["optionOff", "Role", "Team"], exiledController); + exiledShowTeamNum = Create(109, Types.General, "exiledShowTeamNum", false, exiledController); + + //Task options + TaskOptions = Create(200, Types.General, cs(Palette.CrewmateBlue, "TaskOptions"), false, null, true); + WireTaskIsRandomOption = Create(201, Types.General, "WireTaskIsRandomOption", false, TaskOptions); + WireTaskNumOption = Create(202, Types.General, "WireTaskNumOption", 3f, 1f, 8f, 1f, WireTaskIsRandomOption); + transparentTasks = Create(203, Types.General, "transparentTasks", false, TaskOptions); + disableMedbayWalk = Create(204, Types.General, "disableMedbayWalk", false, TaskOptions); + allowParallelMedBayScans = Create(205, Types.General, "allowParallelMedBayScans", false, TaskOptions); + finishTasksBeforeHauntingOrZoomingOut = Create(206, Types.General, "finishTasksBeforeHauntingOrZoomingOut", false, TaskOptions); + disableTaskGameEnd = Create(207, Types.General, "disableTaskGameEnd", false, TaskOptions); + + //Sabotage options + SaboOptions = Create(300, Types.General, cs(Palette.ImpostorRed, "SaboOptions"), false, null, true); + disableSabotage = Create(301, Types.General, cs(Palette.ImpostorRed, "disableSabotage"), false, SaboOptions); + deadImpsBlockSabotage = Create(302, Types.General, cs(Palette.ImpostorRed, "deadImpsBlockSabotage"), false, SaboOptions); + enableCamoComms = Create(303, Types.General, cs(Palette.ImpostorRed, "enableCamoComms"), false, SaboOptions, true); + IsReactorDurationSetting = Create(310, Types.General, "IsReactorDurationSetting", false, SaboOptions, true); + SkeldReactorTimeLimit = Create(311, Types.General, "SkeldReactorTimeLimit", 30f, 0f, 30f, 2.5f, IsReactorDurationSetting); + SkeldLifeSuppTimeLimit = Create(312, Types.General, "SkeldLifeSuppTimeLimit", 30f, 0f, 30f, 2.5f, IsReactorDurationSetting); + MiraLifeSuppTimeLimit = Create(313, Types.General, "MiraLifeSuppTimeLimit", 30f, 0f, 45f, 2.5f, IsReactorDurationSetting); + MiraReactorTimeLimit = Create(314, Types.General, "MiraReactorTimeLimit", 30f, 0f, 45f, 2.5f, IsReactorDurationSetting); + PolusReactorTimeLimit = Create(315, Types.General, "PolusReactorTimeLimit", 60f, 0f, 60f, 2.5f, IsReactorDurationSetting); + AirshipReactorTimeLimit = Create(316, Types.General, "AirshipReactorTimeLimit", 75f, 0f, 90f, 2.5f, IsReactorDurationSetting); + FungleReactorTimeLimit = Create(317, Types.General, "FungleReactorTimeLimit", 45f, 0f, 60f, 2.5f, IsReactorDurationSetting); //Map options - //enableMapOptions = Create(200, Types.General, "enableMapOptions", false, null, true); - - IsReactorDurationSetting = Create(201, Types.General, "IsReactorDurationSetting", false, null, true); - SkeldReactorTimeLimit = Create(202, Types.General, "SkeldReactorTimeLimit", 30f, 0f, 30f, 2.5f, IsReactorDurationSetting); - SkeldLifeSuppTimeLimit = Create(203, Types.General, "SkeldLifeSuppTimeLimit", 30f, 0f, 30f, 2.5f, IsReactorDurationSetting); - MiraLifeSuppTimeLimit = Create(204, Types.General, "MiraLifeSuppTimeLimit", 30f, 0f, 45f, 2.5f, IsReactorDurationSetting); - MiraReactorTimeLimit = Create(205, Types.General, "MiraReactorTimeLimit", 30f, 0f, 45f, 2.5f, IsReactorDurationSetting); - PolusReactorTimeLimit = Create(206, Types.General, "PolusReactorTimeLimit", 60f, 0f, 60f, 2.5f, IsReactorDurationSetting); - AirshipReactorTimeLimit = Create(207, Types.General, "AirshipReactorTimeLimit", 75f, 0f, 90f, 2.5f, IsReactorDurationSetting); - FungleReactorTimeLimit = Create(208, Types.General, "FungleReactorTimeLimit", 45f, 0f, 60f, 2.5f, IsReactorDurationSetting); - - randomGameStartPosition = Create(50, Types.General, "randomGameStartPosition", false, null, true); - randomGameStartToVents = Create(51, Types.General, "randomGameStartToVents", true, randomGameStartPosition); - - enableMiraModify = Create(70, Types.General, cs(Color.yellow, "Mira"), false, null, true); - miraVitals = Create(71, Types.General, "miraVitals", false, enableMiraModify); - - enableBetterPolus = Create(80, Types.General, cs(Color.yellow, "Polus"), false, null); - movePolusVents = Create(81, Types.General, "movePolusVents", false, enableBetterPolus); - addPolusVents = Create(82, Types.General, "addPolusVents", false, enableBetterPolus); - movePolusVitals = Create(83, Types.General, "movePolusVitals", false, enableBetterPolus); - swapNavWifi = Create(84, Types.General, "swapNavWifi", false, enableBetterPolus); - moveColdTemp = Create(85, Types.General, "moveColdTemp", false, enableBetterPolus); - - enableAirShipModify = Create(90, Types.General, cs(Color.yellow, "AirShip"), false, null); - airshipOptimize = Create(91, Types.General, "airshipOptimize", false, enableAirShipModify); - addAirShipVents = Create(92, Types.General, "addAirShipVents", false, enableAirShipModify); - airshipLadder = Create(93, Types.General, "airshipLadder", false, enableAirShipModify); - - enableFungleModify = Create(100, Types.General, cs(Color.yellow, "Fungle"), false, null); - fungleElectrical = Create(101, Types.General, "fungleElectrical", false, enableFungleModify); - - enableCamoComms = Create(120, Types.General, cs(Palette.ImpostorRed, "enableCamoComms"), false, null, true); - //fungleDisableCamoComms = Create(211, Types.General, "fungleDisableCamoComms", true, enableCamoComms); - restrictDevices = Create(121, Types.General, "restrictDevices", ["optionOff", "restrictDevices2", "restrictDevices3"], null); - //restrictAdmin = Create(122, Types.General, "restrictAdmin", 30f, 0f, 600f, 5f, restrictDevices); - restrictCameras = Create(123, Types.General, "restrictCameras", 30f, 0f, 600f, 5f, restrictDevices); - restrictVents = Create(124, Types.General, "restrictVents", 30f, 0f, 600f, 5f, restrictDevices); - disableCamsRound1 = Create(125, Types.General, "disableCamsRound1", false, null); - camsNightVision = Create(126, Types.General, "camsNightVision", false, null); - camsNoNightVisionIfImpVision = Create(127, Types.General, "camsNoNightVisionIfImpVision", false, camsNightVision); - - dynamicMap = Create(130, Types.General, "dynamicMap", false, null, true); - dynamicMapEnableSkeld = Create(131, Types.General, "Skeld", rates, dynamicMap); - dynamicMapEnableMira = Create(132, Types.General, "Mira", rates, dynamicMap); - dynamicMapEnablePolus = Create(133, Types.General, "Polus", rates, dynamicMap); - dynamicMapEnableAirShip = Create(134, Types.General, "Airship", rates, dynamicMap); - dynamicMapEnableFungle = Create(135, Types.General, "Fungle", rates, dynamicMap); - dynamicMapEnableSubmerged = Create(136, Types.General, "Submerged", rates, dynamicMap); - dynamicMapSeparateSettings = Create(137, Types.General, "dynamicMapSeparateSettings", false, dynamicMap); + MapOptions = Create(400, Types.General, cs(new Color32(223, 157, 192, byte.MaxValue), "MapOptions"), false, null, true); + //Mira + enableMiraModify = Create(420, Types.General, cs(Color.yellow, "Mira"), false, MapOptions); + miraVitals = Create(421, Types.General, "miraVitals", false, enableMiraModify); + //Polus + enableBetterPolus = Create(430, Types.General, cs(Color.yellow, "Polus"), false, MapOptions); + movePolusVents = Create(431, Types.General, "movePolusVents", false, enableBetterPolus); + addPolusVents = Create(432, Types.General, "addPolusVents", false, enableBetterPolus); + movePolusVitals = Create(433, Types.General, "movePolusVitals", false, enableBetterPolus); + swapNavWifi = Create(434, Types.General, "swapNavWifi", false, enableBetterPolus); + moveColdTemp = Create(435, Types.General, "moveColdTemp", false, enableBetterPolus); + //AirShip + enableAirShipModify = Create(440, Types.General, cs(Color.yellow, "AirShip"), false, MapOptions); + airshipOptimize = Create(441, Types.General, "airshipOptimize", false, enableAirShipModify); + addAirShipVents = Create(442, Types.General, "addAirShipVents", false, enableAirShipModify); + airshipLadder = Create(443, Types.General, "airshipLadder", false, enableAirShipModify); + //Fungle + enableFungleModify = Create(450, Types.General, cs(Color.yellow, "Fungle"), false, MapOptions); + fungleElectrical = Create(451, Types.General, "fungleElectrical", false, enableFungleModify); + //dynamicMap options + dynamicMap = Create(470, Types.General, "dynamicMap", false, MapOptions, true); + dynamicMapEnableSkeld = Create(471, Types.General, "Skeld", rates, dynamicMap); + dynamicMapEnableMira = Create(472, Types.General, "Mira", rates, dynamicMap); + dynamicMapEnablePolus = Create(473, Types.General, "Polus", rates, dynamicMap); + dynamicMapEnableAirShip = Create(474, Types.General, "Airship", rates, dynamicMap); + dynamicMapEnableFungle = Create(475, Types.General, "Fungle", rates, dynamicMap); + dynamicMapEnableSubmerged = Create(476, Types.General, "Submerged", rates, dynamicMap); + dynamicMapSeparateSettings = Create(477, Types.General, "dynamicMapSeparateSettings", false, dynamicMap); + + //Devices Option + DevicesOption = Create(500, Types.General, cs(new Color32(255, 50, 0, byte.MaxValue), "DevicesOption"), false, null, true); + restrictDevices = Create(501, Types.General, "restrictDevices", ["optionOff", "restrictDevices2", "restrictDevices3"], DevicesOption); + //restrictAdmin = Create(502, Types.General, "restrictAdmin", 30f, 0f, 600f, 5f, restrictDevices); + restrictCameras = Create(503, Types.General, "restrictCameras", 30f, 0f, 600f, 5f, restrictDevices); + restrictVents = Create(504, Types.General, "restrictVents", 30f, 0f, 600f, 5f, restrictDevices); + disableCamsRound1 = Create(505, Types.General, "disableCamsRound1", false, DevicesOption); + camsNightVision = Create(506, Types.General, "camsNightVision", false, DevicesOption); + camsNoNightVisionIfImpVision = Create(507, Types.General, "camsNoNightVisionIfImpVision", false, camsNightVision); debugMode = Create(900, Types.General, "debugMode", false, null, true); disableGameEnd = Create(901, Types.General, "DisableGameEnd", false, debugMode); @@ -952,9 +974,9 @@ public static void Load() amnisiacResetRole = Create(20112, Types.Neutral, "amnisiacResetRole", true, amnisiacSpawnRate); jesterSpawnRate = Create(20100, Types.Neutral, cs(Jester.color, "Jester"), rates, null, true); - jesterCanCallEmergency = Create(20101, Types.Neutral, "jesterCanCallEmergency", true, jesterSpawnRate); + jesterCanCallEmergency = Create(20101, Types.Neutral, "canCallEmergency", true, jesterSpawnRate); jesterCanVent = Create(20102, Types.Neutral, "jesterCanVent", true, jesterSpawnRate); - jesterHasImpostorVision = Create(20103, Types.Neutral, "jesterHasImpostorVision", true, jesterSpawnRate); + jesterHasImpostorVision = Create(20103, Types.Neutral, "hasImpVision", true, jesterSpawnRate); partTimerSpawnRate = Create(20290, Types.Neutral, cs(PartTimer.color, "PartTimer"), rates, null, true); partTimerCooldown = Create(20291, Types.Neutral, "partTimerCooldown", 20f, 2.5f, 60f, 2.5f, partTimerSpawnRate); @@ -989,7 +1011,7 @@ public static void Load() pavlovsownerCreateDogCooldown = Create(20253, Types.Neutral, "pavlovsownerCreateDogCooldown", 25f, 10f, 60f, 2.5f, pavlovsownerSpawnRate); pavlovsownerCreateDogNum = Create(20254, Types.Neutral, "pavlovsownerCreateDogNum", 3f, 1f, 15f, 1f, pavlovsownerSpawnRate); pavlovsownerCanUseSabo = Create(20255, Types.Neutral, "pavlovsownerCanUseSabo", true, pavlovsownerSpawnRate); - pavlovsownerHasImpostorVision = Create(20256, Types.Neutral, "pavlovsownerHasImpostorVision", true, pavlovsownerSpawnRate); + pavlovsownerHasImpostorVision = Create(20256, Types.Neutral, "hasImpVision", true, pavlovsownerSpawnRate); pavlovsownerCanUseVents = Create(20257, Types.Neutral, "pavlovsownerCanUseVents", ["Pavlovsdogs", "Pavlovsowner", "pavlovsownerCanUseVents3"], pavlovsownerSpawnRate); pavlovsownerRampage = Create(20260, Types.Neutral, "pavlovsownerRampage", true, pavlovsownerSpawnRate); @@ -1011,7 +1033,7 @@ public static void Load() swooperDuration = Create(20153, Types.Neutral, "swooperDuration", 15f, 1f, 20f, 0.5f, swooperSpawnRate); swooperSpeed = Create(20154, Types.Neutral, "swooperSpeed", 1.5f, 1f, 3f, 0.125f, swooperSpawnRate); swooperCanUseVents = Create(20155, Types.Neutral, "canUseVents", true, swooperSpawnRate); - swooperHasImpVision = Create(20156, Types.Neutral, "swooperHasImpVision", true, swooperSpawnRate); + swooperHasImpVision = Create(20156, Types.Neutral, "hasImpVision", true, swooperSpawnRate); werewolfSpawnRate = Create(20200, Types.Neutral, cs(Werewolf.color, "Werewolf"), rates, null, true); werewolfRampageCooldown = Create(20201, Types.Neutral, "werewolfRampageCooldown", 25f, 10f, 60f, 2.5f, werewolfSpawnRate); @@ -1020,7 +1042,7 @@ public static void Load() juggernautSpawnRate = Create(20210, Types.Neutral, cs(Juggernaut.color, "Juggernaut"), rates, null, true); juggernautCooldown = Create(20211, Types.Neutral, "juggernautCooldown", 25f, 2.5f, 60f, 2.5f, juggernautSpawnRate); - juggernautHasImpVision = Create(20212, Types.Neutral, "juggernautHasImpVision", true, juggernautSpawnRate); + juggernautHasImpVision = Create(20212, Types.Neutral, "hasImpVision", true, juggernautSpawnRate); juggernautCanUseVents = Create(20113, Types.Neutral, "canUseVents", true, juggernautSpawnRate); juggernautReducedkillEach = Create(20114, Types.Neutral, "juggernautReducedkillEach", 5f, 1f, 15f, 0.5f, juggernautSpawnRate); @@ -1034,7 +1056,7 @@ public static void Load() lawyerTargetKnows = Create(20182, Types.Neutral, "lawyerTargetKnows", true, lawyerSpawnRate); lawyerVision = Create(20183, Types.Neutral, "lawyerVision", 1.5f, 0.25f, 3f, 0.25f, lawyerSpawnRate); lawyerKnowsRole = Create(20184, Types.Neutral, "lawyerKnowsRole", true, lawyerSpawnRate); - lawyerCanCallEmergency = Create(20185, Types.Neutral, "lawyerCanCallEmergency", true, lawyerSpawnRate); + lawyerCanCallEmergency = Create(20185, Types.Neutral, "canCallEmergency", true, lawyerSpawnRate); lawyerStolenWin = Create(20189, Types.Neutral, "lawyerStolenWin", false, lawyerSpawnRate); lawyerTargetCanBeJester = Create(20186, Types.Neutral, "lawyerTargetCanBeJester", false, lawyerSpawnRate); @@ -1043,7 +1065,7 @@ public static void Load() pursuerBlanksNumber = Create(20273, Types.Neutral, "pursuerBlanksNumber", 6f, 1f, 20f, 1f, lawyerSpawnRate); executionerSpawnRate = Create(20190, Types.Neutral, cs(Executioner.color, "Executioner"), rates, null, true); - executionerCanCallEmergency = Create(20191, Types.Neutral, "executionerCanCallEmergency", true, executionerSpawnRate); + executionerCanCallEmergency = Create(20191, Types.Neutral, "canCallEmergency", true, executionerSpawnRate); executionerPromotesToLawyer = Create(20192, Types.Neutral, "executionerPromotesToLawyer", true, executionerSpawnRate); //executionerOnTargetDead = Create(20193, Types.Neutral, "目标死亡后变为", [cs(Pursuer.color, "Pursuer"), cs(Jester.color, "Jester"), cs(Amnisiac.color, "Amnisiac"), "Crewmate"], executionerSpawnRate); @@ -1069,8 +1091,8 @@ public static void Load() thiefCanKillSheriff = Create(20242, Types.Neutral, $"{"thiefCanKill".Translate()}{cs(Sheriff.color, "Sheriff".Translate())}", true, thiefSpawnRate); thiefCanKillDeputy = Create(20246, Types.Neutral, $"{"thiefCanKill".Translate()}{cs(Sheriff.color, "Deputy".Translate())}", true, thiefSpawnRate); thiefCanKillVeteran = Create(20247, Types.Neutral, $"{"thiefCanKill".Translate()}{cs(Veteran.color, "Veteran".Translate())}", true, thiefSpawnRate); - thiefHasImpVision = Create(20243, Types.Neutral, "thiefHasImpVision", true, thiefSpawnRate); - thiefCanUseVents = Create(20244, Types.Neutral, "thiefCanUseVents", true, thiefSpawnRate); + thiefHasImpVision = Create(20243, Types.Neutral, "hasImpVision", true, thiefSpawnRate); + thiefCanUseVents = Create(20244, Types.Neutral, "canUseVents", true, thiefSpawnRate); thiefCanStealWithGuess = Create(20245, Types.Neutral, "thiefCanStealWithGuess", true, thiefSpawnRate); //-------------------------- Crewmate Options 30000-39999 -------------------------- // @@ -1119,7 +1141,7 @@ public static void Load() prosecutorCanSeeVoteColors = Create(30111, Types.Crewmate, "mayorCanSeeVoteColors", true, prosecutorSpawnRate); prosecutorTasksNeededToSeeVoteColors = Create(30112, Types.Crewmate, "mayorTasksNeededToSeeVoteColors", 5f, 0f, 20f, 1f, prosecutorCanSeeVoteColors); prosecutorDiesOnIncorrectPros = Create(30371, Types.Crewmate, "prosecutorDiesOnIncorrectPros", true, prosecutorSpawnRate); - prosecutorCanCallEmergency = Create(30372, Types.Crewmate, "prosecutorCanCallEmergency", true, prosecutorSpawnRate); + prosecutorCanCallEmergency = Create(30372, Types.Crewmate, "canCallEmergency", true, prosecutorSpawnRate); engineerSpawnRate = Create(30120, Types.Crewmate, cs(Engineer.color, "Engineer"), rates, null, true); engineerRemoteFix = Create(30121, Types.Crewmate, "engineerRemoteFix", true, engineerSpawnRate); @@ -1164,7 +1186,7 @@ public static void Load() veteranAlertDuration = Create(30222, Types.Crewmate, "veteranAlertDuration", 12.5f, 2.5f, 20f, 0.5f, veteranSpawnRate); swapperSpawnRate = Create(30230, Types.Crewmate, cs(Swapper.color, "Swapper"), rates, null, true); - swapperCanCallEmergency = Create(30231, Types.Crewmate, "swapperCanCallEmergency", true, swapperSpawnRate); + swapperCanCallEmergency = Create(30231, Types.Crewmate, "canCallEmergency", true, swapperSpawnRate); swapperCanFixSabotages = Create(30232, Types.Crewmate, "swapperCanFixSabotages", true, swapperSpawnRate); swapperCanOnlySwapOthers = Create(30233, Types.Crewmate, "swapperCanOnlySwapOthers", false, swapperSpawnRate); swapperSwapsNumber = Create(30234, Types.Crewmate, "swapperSwapsNumber", 1f, 0f, 5f, 1f, swapperSpawnRate); @@ -1202,7 +1224,7 @@ public static void Load() prophetSpawnRate = Create(30360, Types.Crewmate, cs(Prophet.color, "Prophet"), rates, null, true); prophetCooldown = Create(30361, Types.Crewmate, "prophetCooldown", 20f, 5f, 60f, 2.5f, prophetSpawnRate); prophetNumExamines = Create(30362, Types.Crewmate, "prophetNumExamines", 4, 1, 10, 1, prophetSpawnRate); - prophetCanCallEmergency = Create(30363, Types.Crewmate, "prophetCanCallEmergency", true, prophetSpawnRate); + prophetCanCallEmergency = Create(30363, Types.Crewmate, "canCallEmergency", true, prophetSpawnRate); prophetIsRevealed = Create(30364, Types.Crewmate, "prophetIsRevealed", false, prophetSpawnRate); prophetExaminesToBeRevealed = Create(30365, Types.Crewmate, "prophetExaminesToBeRevealed", 3, 1, 10, 1, prophetIsRevealed); prophetKillCrewAsRed = Create(30366, Types.Crewmate, "prophetKillCrewAsRed", false, prophetSpawnRate); @@ -1217,8 +1239,8 @@ public static void Load() spySpawnRate = Create(30280, Types.Crewmate, cs(Spy.color, "Spy"), rates, null, true); spyCanDieToSheriff = Create(30281, Types.Crewmate, "spyCanDieToSheriff", false, spySpawnRate); spyImpostorsCanKillAnyone = Create(30282, Types.Crewmate, "spyImpostorsCanKillAnyone", true, spySpawnRate); - spyCanEnterVents = Create(30283, Types.Crewmate, "spyCanEnterVents", true, spySpawnRate); - spyHasImpostorVision = Create(30284, Types.Crewmate, "spyHasImpostorVision", true, spySpawnRate); + spyCanEnterVents = Create(30283, Types.Crewmate, "canUseVents", true, spySpawnRate); + spyHasImpostorVision = Create(30284, Types.Crewmate, "hasImpVision", true, spySpawnRate); portalmakerSpawnRate = Create(30290, Types.Crewmate, cs(Portalmaker.color, "Portalmaker"), rates, null, true); portalmakerCooldown = Create(30291, Types.Crewmate, "portalmakerCooldown", 15f, 10f, 60f, 2.5f, portalmakerSpawnRate); @@ -1258,7 +1280,7 @@ public static void Load() trapperMaxCharges = Create(30352, Types.Crewmate, "trapperMaxCharges", 5f, 1f, 15f, 1f, trapperSpawnRate); trapperRechargeTasksNumber = Create(30353, Types.Crewmate, "trapperRechargeTasksNumber", 2f, 1f, 15f, 1f, trapperSpawnRate); trapperTrapNeededTriggerToReveal = Create(30354, Types.Crewmate, "trapperTrapNeededTriggerToReveal", 2f, 1f, 10f, 1f, trapperSpawnRate); - trapperInfoType = Create(30356, Types.Crewmate, "trapperInfoType", ["trapperInfoType1", "trapperInfoType2", "trapperInfoType3"], trapperSpawnRate); + trapperInfoType = Create(30356, Types.Crewmate, "trapperInfoType", ["Role", "trapperInfoType2", "Name"], trapperSpawnRate); trapperTrapDuration = Create(30357, Types.Crewmate, "trapperTrapDuration", 5f, 1f, 15f, 0.5f, trapperSpawnRate); //-------------------------- Modifier (40000 - 49999) -------------------------- // diff --git a/TheOtherRoles/Options/CustomOptions.cs b/TheOtherRoles/Options/CustomOptions.cs index 57f658f..016b45d 100644 --- a/TheOtherRoles/Options/CustomOptions.cs +++ b/TheOtherRoles/Options/CustomOptions.cs @@ -93,7 +93,9 @@ public static CustomOption Create(int id, CustomOptionType type, string name, fl public static CustomOption Create(int id, CustomOptionType type, string name, bool defaultValue, CustomOption parent = null, bool isHeader = false, bool isHidden = false, Action onChange = null) { - return new CustomOption(id, type, name, ["optionOff", "optionOn"], defaultValue ? "optionOn" : "optionOff", parent, isHeader, isHidden, onChange); + var selections = name.Contains("Options") ? new[] { "ExpandOptions", "CollapseOptions" } : new[] { "optionOff", "optionOn" }; + var defaultSelection = defaultValue ? selections[1] : selections[0]; + return new CustomOption(id, type, name, selections, defaultSelection, parent, isHeader, isHidden, onChange); } // Static behaviour @@ -210,6 +212,8 @@ public string GetString() { "optionOn" => "" + sel.Translate() + "", "optionOff" => "" + sel.Translate() + "", + "ExpandOptions" => "" + sel.Translate() + "", + "CollapseOptions" => "" + sel.Translate() + "", _ => sel.Translate(), }; } diff --git a/TheOtherRoles/Options/ModOption.cs b/TheOtherRoles/Options/ModOption.cs index cd0ec6d..b84f6e8 100644 --- a/TheOtherRoles/Options/ModOption.cs +++ b/TheOtherRoles/Options/ModOption.cs @@ -87,6 +87,7 @@ public static void clearAndReloadMapOptions() ventsToSeal = new(); playerIcons = new Dictionary(); + NormalOptions.ConfirmImpostor = CustomOptionHolder.exiledController.GetBool() && CustomOptionHolder.exiledShowTeamNum.GetBool(); maxNumberOfMeetings = CustomOptionHolder.maxNumberOfMeetings.GetInt(); blockSkippingInEmergencyMeetings = CustomOptionHolder.blockSkippingInEmergencyMeetings.GetBool(); blockSkippingInEmergencyMeetings = CustomOptionHolder.blockSkippingInEmergencyMeetings.GetBool(); diff --git a/TheOtherRoles/Patches/EndGamePatch.cs b/TheOtherRoles/Patches/EndGamePatch.cs index a338386..feae146 100644 --- a/TheOtherRoles/Patches/EndGamePatch.cs +++ b/TheOtherRoles/Patches/EndGamePatch.cs @@ -158,7 +158,7 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En Lawyer.lawyer, Executioner.executioner, Witness.Player, - Specter.Player, + //Specter.Player, Thief.thief, Pelican.Player, Juggernaut.juggernaut, @@ -194,8 +194,8 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En var pelicanWin = gameOverReason == (GameOverReason)CustomGameOverReason.PelicanWin && Pelican.Player.IsAlive(); var arsonistWin = Arsonist.arsonist != null && gameOverReason == (GameOverReason)CustomGameOverReason.ArsonistWin; var doomsayerWin = Doomsayer.doomsayer != null && gameOverReason == (GameOverReason)CustomGameOverReason.DoomsayerWin; - var loversWin = Lovers.existingAndAlive() && (gameOverReason == (GameOverReason)CustomGameOverReason.LoversWin || - (GameManager.Instance.DidHumansWin(gameOverReason) && !Lovers.existingWithKiller())); + var loversWin = Lovers.IsAlive() && (gameOverReason == (GameOverReason)CustomGameOverReason.LoversWin || + (GameManager.Instance.DidHumansWin(gameOverReason) && !Lovers.isKillerLover())); var teamJackalWin = gameOverReason == (GameOverReason)CustomGameOverReason.TeamJackalWin && (Jackal.jackal.Any(x => x.IsAlive()) || Jackal.Sidekick.IsAlive()); var teamPavlovsWin = gameOverReason == (GameOverReason)CustomGameOverReason.TeamPavlovsWin && @@ -281,7 +281,7 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En else if (loversWin) { // Double win for lovers, crewmates also win - if (!Lovers.existingWithKiller()) + if (!Lovers.isKillerLover()) { AdditionalTempData.winCondition = WinCondition.LoversTeamWin; TempData.winners = new Il2CppSystem.Collections.Generic.List(); @@ -314,7 +314,7 @@ public static void Postfix(AmongUsClient __instance, [HarmonyArgument(0)] ref En // 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) + foreach (var player in Jackal.jackal.GroupBy(x => x.PlayerId).Select(g => g.First())) { var wpdFormerJackal = new WinningPlayerData(player.Data); wpdFormerJackal.IsImpostor = false; @@ -857,7 +857,7 @@ private static bool CheckAndEndGameForAkujoWin(ShipStatus __instance, PlayerStat statistics.TeamWerewolfAlive == 0 && statistics.TeamJackalAlive == 0 && statistics.TeamSwooperAlive == 0 && - !(statistics.TeamLoversAlive != 0 && Lovers.existingWithKiller()))) + !(statistics.TeamLoversAlive != 0 && Lovers.isKillerLover()))) { GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.AkujoWin, false); return true; @@ -916,9 +916,7 @@ private static bool CheckAndEndGameForSwooperWin(ShipStatus __instance, PlayerSt statistics.TeamWerewolfAlive == 0 && statistics.TeamPelicanAlive == 0 && statistics.TeamArsonistAlive == 0 && - !(statistics.TeamSwooperHasAliveLover && - statistics.TeamLoversAlive == 2) && - !killingCrewAlive()) + !(statistics.TeamSwooperHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive()) { //__instance.enabled = false; GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.SwooperWin, false); @@ -936,9 +934,7 @@ private static bool CheckAndEndGameForPelicanWin(ShipStatus __instance, PlayerSt statistics.TeamWerewolfAlive == 0 && statistics.TeamSwooperAlive == 0 && statistics.TeamArsonistAlive == 0 && - !(statistics.TeamPelicanHasAliveLover && - statistics.TeamLoversAlive == 2) && - !killingCrewAlive()) + !(statistics.TeamPelicanHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive()) { //__instance.enabled = false; GameManager.Instance.RpcEndGame((GameOverReason)CustomGameOverReason.PelicanWin, false); @@ -957,9 +953,7 @@ private static bool CheckAndEndGameForWerewolfWin(ShipStatus __instance, PlayerS statistics.TeamArsonistAlive == 0 && statistics.TeamPelicanAlive == 0 && statistics.TeamSwooperAlive == 0 && - !(statistics.TeamWerewolfHasAliveLover && - statistics.TeamLoversAlive == 2) && - !killingCrewAlive() + !(statistics.TeamWerewolfHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive() ) { //__instance.enabled = false; @@ -981,9 +975,7 @@ private static bool CheckAndEndGameForJuggernautWin(ShipStatus __instance, Playe statistics.TeamPelicanAlive == 0 && statistics.TeamArsonistAlive == 0 && statistics.TeamSwooperAlive == 0 && - !(statistics.TeamJuggernautHasAliveLover && - statistics.TeamLoversAlive == 2) && - !killingCrewAlive() + !(statistics.TeamJuggernautHasAliveLover && statistics.TeamLoversAlive == 2) && !killingCrewAlive() ) { //__instance.enabled = false; @@ -1121,79 +1113,78 @@ private void GetPlayerCounts() var juggernautLover = false; foreach (var playerInfo in GameData.Instance.AllPlayers.GetFastEnumerator()) - if (!playerInfo.Disconnected) - if (!playerInfo.IsDead) - { - numTotalAlive++; + if (!playerInfo.Disconnected && !playerInfo.IsDead) + { + numTotalAlive++; - var lover = isLover(playerInfo); - if (lover) numLoversAlive++; + var lover = isLover(playerInfo); + if (lover) numLoversAlive++; - if (playerInfo.Role.IsImpostor) - { - numImpostorsAlive++; - if (lover) impLover = true; - } + if (playerInfo.Role.IsImpostor) + { + numImpostorsAlive++; + if (lover) impLover = true; + } - if (Jackal.jackal != null && Jackal.jackal.Any(x => x.PlayerId == playerInfo.PlayerId)) - { - numJackalAlive++; - if (lover) jackalLover = true; - } + if (Jackal.jackal != null && Jackal.jackal.Any(x => x.PlayerId == playerInfo.PlayerId)) + { + numJackalAlive++; + if (lover) jackalLover = true; + } - if (Jackal.Sidekick != null && Jackal.Sidekick.PlayerId == playerInfo.PlayerId) - { - numJackalAlive++; - if (lover) jackalLover = true; - } + if (Jackal.Sidekick != null && Jackal.Sidekick.PlayerId == playerInfo.PlayerId) + { + numJackalAlive++; + if (lover) jackalLover = true; + } - if (Arsonist.arsonist != null && Arsonist.arsonist.PlayerId == playerInfo.PlayerId) - { - numArsonistAlive++; - if (lover) arsonistLover = true; - } + if (Arsonist.arsonist != null && Arsonist.arsonist.PlayerId == playerInfo.PlayerId) + { + numArsonistAlive++; + if (lover) arsonistLover = true; + } - if (Pavlovsdogs.pavlovsowner != null && Pavlovsdogs.pavlovsowner.PlayerId == playerInfo.PlayerId) - { - numPavlovsAlive++; - if (lover) pavlovsLover = true; - } + if (Pavlovsdogs.pavlovsowner != null && Pavlovsdogs.pavlovsowner.PlayerId == playerInfo.PlayerId) + { + numPavlovsAlive++; + if (lover) pavlovsLover = true; + } - if (Pavlovsdogs.pavlovsdogs != null && Pavlovsdogs.pavlovsdogs.Any(p => p.PlayerId == playerInfo.PlayerId)) - { - numPavlovsAlive++; - if (lover) pavlovsLover = true; - } + if (Pavlovsdogs.pavlovsdogs != null && Pavlovsdogs.pavlovsdogs.Any(p => p.PlayerId == playerInfo.PlayerId)) + { + numPavlovsAlive++; + if (lover) pavlovsLover = true; + } - if (Werewolf.werewolf != null && Werewolf.werewolf.PlayerId == playerInfo.PlayerId) - { - numWerewolfAlive++; - if (lover) werewolfLover = true; - } - if (Swooper.swooper != null && Swooper.swooper.PlayerId == playerInfo.PlayerId) - { - numSwooperAlive++; - if (lover) swooperLover = true; - } - if (Juggernaut.juggernaut != null && Juggernaut.juggernaut.PlayerId == playerInfo.PlayerId) - { - numJuggernautAlive++; - if (lover) juggernautLover = true; - } - if (Pelican.Player != null && Pelican.Player.PlayerId == playerInfo.PlayerId) - { - numPelicanAlive++; - if (lover) pelicanLover = true; - } - if (Akujo.akujo != null && Akujo.akujo.PlayerId == playerInfo.PlayerId) - { - numAkujoAlive++; - } - if (Akujo.honmei != null && Akujo.honmei.PlayerId == playerInfo.PlayerId) - { - numAkujoAlive++; - } + if (Werewolf.werewolf != null && Werewolf.werewolf.PlayerId == playerInfo.PlayerId) + { + numWerewolfAlive++; + if (lover) werewolfLover = true; + } + if (Swooper.swooper != null && Swooper.swooper.PlayerId == playerInfo.PlayerId) + { + numSwooperAlive++; + if (lover) swooperLover = true; + } + if (Juggernaut.juggernaut != null && Juggernaut.juggernaut.PlayerId == playerInfo.PlayerId) + { + numJuggernautAlive++; + if (lover) juggernautLover = true; + } + if (Pelican.Player != null && Pelican.Player.PlayerId == playerInfo.PlayerId) + { + numPelicanAlive++; + if (lover) pelicanLover = true; + } + if (Akujo.akujo != null && Akujo.akujo.PlayerId == playerInfo.PlayerId) + { + numAkujoAlive++; } + if (Akujo.honmei != null && Akujo.honmei.PlayerId == playerInfo.PlayerId) + { + numAkujoAlive++; + } + } TeamJackalAlive = numJackalAlive; TeamImpostorsAlive = numImpostorsAlive; diff --git a/TheOtherRoles/Patches/ExileControllerPatch.cs b/TheOtherRoles/Patches/ExileControllerPatch.cs index 123a14c..c5865c9 100644 --- a/TheOtherRoles/Patches/ExileControllerPatch.cs +++ b/TheOtherRoles/Patches/ExileControllerPatch.cs @@ -5,7 +5,6 @@ using AmongUs.GameOptions; using Hazel; using PowerTools; -using Sentry.Protocol; using TheOtherRoles.Buttons; using TheOtherRoles.Objects; using TheOtherRoles.Utilities; @@ -172,6 +171,39 @@ public static void Postfix(ExileController __instance) if (Balancer.currentAbilityUser != null && Balancer.IsDoubleExile && __instance.exiled?.PlayerId == Balancer.targetplayerleft.PlayerId) { __instance.completeString = GetString("二者一同放逐"); + return; + } + + var player = ExileController.Instance?.exiled?.Object; + if (CustomOptionHolder.exiledController.GetBool()) + { + if (CustomOptionHolder.exiledReviveRole.GetBool() && player != null) + { + switch (CustomOptionHolder.exiledReviveRole.GetQuantity()) + { + case 1: + break; + case 2: + __instance.completeString = $"{player.Data.PlayerName} 的职业是 {string.Join(" ", RoleInfo + .getRoleInfoForPlayer(player, false, false).Select(x => x.Name))}"; + break; + case 3: + __instance.completeString = $"{player.Data.PlayerName} 是 {teamString(player)}"; + break; + default: + break; + } + } + if (Prosecutor.ProsecuteThisMeeting && player != null) __instance.completeString += " (被起诉)"; + if (CustomOptionHolder.exiledShowTeamNum.GetBool() && player?.PlayerId != Jester.jester?.PlayerId) + { + var Impostors = PlayerControl.AllPlayerControls.ToArray().Where(x => x.isImpostor() && x.IsAlive() && x.PlayerId != player.PlayerId); + var Neutrals = PlayerControl.AllPlayerControls.ToArray().Where(x => x.isNeutral() && x.IsAlive() && x.PlayerId != player.PlayerId); + __instance.ImpostorText.text = + $"\n{cs(getTeamColor(RoleType.Impostor), "伪装者阵营剩余 " + Impostors.Count())}" + + $" | {cs(getTeamColor(RoleType.Neutral), "中立阵营剩余 " + Neutrals.Count())}"; + + } } } @@ -226,7 +258,7 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) } // Mini exile lose condition else if (exiled != null && Mini.mini != null && Mini.mini.PlayerId == exiled.PlayerId && !Mini.isGrownUp() && - !Mini.mini.Data.Role.IsImpostor && !isNeutral(Mini.mini)) + !Mini.mini.Data.Role.IsImpostor && !Mini.mini.isNeutral()) { Mini.triggerMiniLose = true; return; @@ -244,7 +276,7 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) AmongUsClient.Instance.FinishRpcImmediately(writer); Executioner.PromotesRole(); } - if (Witness.target != null && Witness.killerTarget != null) + if (Witness.target != null) { bool skip = exiled == null && Witness.skipMeeting; bool targetIsKillerAndNotExiled = Witness.target == Witness.killerTarget && (exiled?.Object == null || Witness.target != exiled?.Object); @@ -266,7 +298,6 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) if (Vortox.Player.IsAlive() && exiled == null) { Vortox.skipCount++; - Message($"迷乱旋涡胜利计数{Vortox.skipCount}"); if (Vortox.skipCount == Vortox.skipMeetingNum) Vortox.triggerImpWin = true; } @@ -464,7 +495,7 @@ private static void WrapUpPostfix(GameData.PlayerInfo exiled) if (InfoSleuth.infoSleuth != null && InfoSleuth.target != null && InfoSleuth.infoSleuth == PlayerControl.LocalPlayer) { - var isNotCrew = (isNeutral(InfoSleuth.target) || InfoSleuth.target.isImpostor()) ^ Vortox.Reversal; + var isNotCrew = (InfoSleuth.target.isNeutral() || InfoSleuth.target.isImpostor()) ^ Vortox.Reversal; var team = "的阵营是 " + getTeam(InfoSleuth.target); var info = InfoSleuth.infoType switch { @@ -492,10 +523,10 @@ static string getTeam(PlayerControl player) if (Vortox.Player.IsAlive()) { if (player.isCrew()) return rnd.Next(2) == 0 ? "NeutralRolesText".Translate() : "ImpostorRolesText".Translate(); - if (isNeutral(player) || player.isImpostor()) return "CrewmateRolesText".Translate(); + if (player.isNeutral() || player.isImpostor()) return "CrewmateRolesText".Translate(); } - return isNeutral(player) ? "NeutralRolesText".Translate() + return player.isNeutral() ? "NeutralRolesText".Translate() : player.isImpostor() ? "ImpostorRolesText".Translate() : "CrewmateRolesText".Translate(); } @@ -569,33 +600,4 @@ private static void Postfix() AntiTeleport.setPosition(); Chameleon.lastMoved.Clear(); } -} - -[HarmonyPatch(typeof(TranslationController), nameof(TranslationController.GetString), typeof(StringNames), - typeof(Il2CppReferenceArray))] -internal class ExileControllerMessagePatch -{ - private static void Postfix(ref string __result, [HarmonyArgument(0)] StringNames id) - { - try - { - if (ExileController.Instance != null && ExileController.Instance.exiled != null) - { - var player = playerById(ExileController.Instance.exiled.Object.PlayerId); - if (player == null) return; - // Exile role text - if (id is StringNames.ExileTextPN or StringNames.ExileTextSN or StringNames.ExileTextPP or StringNames.ExileTextSP) - __result = $"{player.Data.PlayerName} 的职业是 {string.Join(" ", RoleInfo.getRoleInfoForPlayer(player, false).Select(x => x.Name).ToArray())}"; - // Hide number of remaining impostors on Jester win - if (id is StringNames.ImpostorsRemainP or StringNames.ImpostorsRemainS) - if (Jester.jester != null && player.PlayerId == Jester.jester.PlayerId) - __result = ""; - if (Prosecutor.ProsecuteThisMeeting) __result += " (被起诉)"; - } - } - catch - { - // pass - Hopefully prevent leaving while exiling to softlock game - } - } } \ No newline at end of file diff --git a/TheOtherRoles/Patches/IntroPatch.cs b/TheOtherRoles/Patches/IntroPatch.cs index 54dba88..58593b5 100644 --- a/TheOtherRoles/Patches/IntroPatch.cs +++ b/TheOtherRoles/Patches/IntroPatch.cs @@ -184,7 +184,7 @@ internal class IntroPatch public static void setupIntroTeamIcons(IntroCutscene __instance, ref List yourTeam) { // Intro solo teams - if (isNeutral(PlayerControl.LocalPlayer)) + if (PlayerControl.LocalPlayer.isNeutral()) { var soloTeam = new List(); soloTeam.Add(PlayerControl.LocalPlayer); diff --git a/TheOtherRoles/Patches/MainMenuPatch.cs b/TheOtherRoles/Patches/MainMenuPatch.cs index 4039992..dae84b8 100644 --- a/TheOtherRoles/Patches/MainMenuPatch.cs +++ b/TheOtherRoles/Patches/MainMenuPatch.cs @@ -1,7 +1,6 @@ using System; using AmongUs.Data; using Assets.InnerNet; -using Il2CppSystem.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; @@ -14,7 +13,6 @@ namespace TheOtherRoles.Patches; public class MainMenuPatch { private static AnnouncementPopUp popUp; - private static void Prefix(MainMenuManager __instance) { var template = GameObject.Find("ExitGameButton"); @@ -137,7 +135,7 @@ private static void Prefix(MainMenuManager __instance) if (p == 1) { var backup = DataManager.Player.Announcements.allAnnouncements; - DataManager.Player.Announcements.allAnnouncements = new List(); + DataManager.Player.Announcements.allAnnouncements = new Il2CppSystem.Collections.Generic.List(); popUp.Init(false); DataManager.Player.Announcements.SetAnnouncements(new[] { creditsAnnouncement }); popUp.CreateAnnouncementList(); @@ -187,22 +185,4 @@ public static void Postfix(VersionShower __instance) { __instance.text.text = $"Among Us v{Application.version} - The Other Us Edited v{Main.Version}{"-Lite"}"; } -} -/* -[HarmonyPatch(typeof(MainMenuManager), nameof(MainMenuManager.Start)), HarmonyPriority(Priority.First)] -internal class TitleLogoPatch -{ - public static GameObject Sizer; - public static GameObject AULogo; - public static GameObject BottomButtonBounds; - private static void Postfix(MainMenuManager __instance) - { - if (!(Sizer = GameObject.Find("Sizer"))) return; - if (!(AULogo = GameObject.Find("LOGO-AU"))) return; - Sizer.transform.localPosition += new Vector3(0f, 0.12f, 0f); - AULogo.transform.localScale = new Vector3(0.66f, 0.67f, 1f); - AULogo.transform.position -= new Vector3(0f, 0.1f, 0f); - var logoRenderer = AULogo.GetComponent(); - logoRenderer.sprite = Helpers.loadSpriteFromResources("TheOtherRoles.Resources.mxyx-Logo.png", 60f); - } -}*/ \ No newline at end of file +} \ No newline at end of file diff --git a/TheOtherRoles/Patches/PlayerControlPatch.cs b/TheOtherRoles/Patches/PlayerControlPatch.cs index 84e2d1f..e0fcf69 100644 --- a/TheOtherRoles/Patches/PlayerControlPatch.cs +++ b/TheOtherRoles/Patches/PlayerControlPatch.cs @@ -23,7 +23,7 @@ public static class PlayerControlFixedUpdatePatch // Helpers public static PlayerControl SetTarget(bool onlyCrewmates = false, bool targetPlayersInVents = false, - IEnumerable untargetablePlayers = null, PlayerControl targetingPlayer = null, float KillDistances = 0f) + List untargetablePlayers = null, PlayerControl targetingPlayer = null, float KillDistances = 0f) { PlayerControl result = null; var num = GameOptionsData.KillDistances[Mathf.Clamp(GameOptionsManager.Instance.currentNormalGameOptions.KillDistance, 0, 3)]; @@ -692,7 +692,7 @@ private static void snitchUpdate() var forImpTeam = local.Data.Role.IsImpostor; var forKillerTeam = Snitch.Team == Snitch.includeNeutralTeam.KillNeutral && isKillerNeutral(local); var forEvilTeam = Snitch.Team == Snitch.includeNeutralTeam.EvilNeutral && isEvilNeutral(local); - var forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && isNeutral(local); + var forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && local.isNeutral(); if (numberOfTasks <= Snitch.taskCountForReveal && (forImpTeam || forKillerTeam || forEvilTeam || forNeutraTeam)) { @@ -712,7 +712,7 @@ private static void snitchUpdate() if (Mimic.mimic == p) arrowForImp = true; var arrowForKillerTeam = Snitch.Team == Snitch.includeNeutralTeam.KillNeutral && isKillerNeutral(p); var arrowForEvilTeam = Snitch.Team == Snitch.includeNeutralTeam.EvilNeutral && isEvilNeutral(p); - var arrowForNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && isNeutral(p); + var arrowForNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && p.isNeutral(); var targetsRole = RoleInfo.getRoleInfoForPlayer(p, false).FirstOrDefault(); if (!p.Data.IsDead && (arrowForImp || arrowForKillerTeam || arrowForEvilTeam || arrowForNeutraTeam)) @@ -752,7 +752,7 @@ private static void snitchTextUpdate() var forImpTeam = local.isImpostor(); var forKillerTeam = Snitch.Team == Snitch.includeNeutralTeam.KillNeutral && isKillerNeutral(local); var forEvilTeam = Snitch.Team == Snitch.includeNeutralTeam.EvilNeutral && isEvilNeutral(local); - var forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && isNeutral(local); + var forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && local.isNeutral(); if (numberOfTasks <= Snitch.taskCountForReveal && (forImpTeam || forKillerTeam || forEvilTeam || forNeutraTeam || isDead)) { @@ -1818,7 +1818,7 @@ public static void HandleMurderPostfix(PlayerControl __instance, PlayerControl t if (Pelican.Player == PlayerControl.LocalPlayer) { - _ = new LateTask(Pelican.PelicanDie, 0.5f); + _ = new LateTask(() => { Pelican.PelicanDie(); }, 0.5f); } } @@ -2080,7 +2080,7 @@ public static void Postfix(PlayerControl __instance) if (__instance.PlayerId == Pelican.Player?.PlayerId && Pelican.eatenPlayers?.Count > 0) { - foreach (var player in Pelican.eatenPlayers.ToArray().Where(p => p != null && p.Data.IsDead)) + foreach (var player in Pelican.eatenPlayers.Where(p => p != null && p.Data.IsDead)) { if (PlayerControl.LocalPlayer == player) { @@ -2157,3 +2157,37 @@ public static void Postfix(PlayerControl __instance) } } } + +[HarmonyPatch] +public static class DisconnectPatch +{ + [HarmonyPatch(typeof(GameData), nameof(GameData.HandleDisconnect), [typeof(PlayerControl), typeof(DisconnectReasons)]), HarmonyPostfix] + public static void DisconnectPostfix(PlayerControl player, DisconnectReasons reason) + { + Message($"玩家 {player?.Data?.PlayerName ?? "null"} 断开连接 {reason}", "HandleDisconnect"); + if (InGame) + { + if (player.isLover()) + { + Lovers.clearAndReload(); + } + + if (Lawyer.lawyer != null && Lawyer.target == player) + { + Lawyer.PromotesToPursuer(); + } + + if (Executioner.executioner != null && Executioner.target == player) + { + Executioner.PromotesRole(); + } + } + } + + + [HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.DisconnectInternal)), HarmonyPrefix] + public static void InnerNetPrefix(InnerNetClient __instance, DisconnectReasons reason, string stringReason) + { + Info($"断开连接 {reason}:{stringReason}, Ping:{__instance.Ping}", "InnerNet"); + } +} diff --git a/TheOtherRoles/Patches/RoleAssignmentPatch.cs b/TheOtherRoles/Patches/RoleAssignmentPatch.cs index a0c4d5e..dea178c 100644 --- a/TheOtherRoles/Patches/RoleAssignmentPatch.cs +++ b/TheOtherRoles/Patches/RoleAssignmentPatch.cs @@ -470,7 +470,7 @@ private static void assignRoleTargets(RoleAssignmentData data) // Executioner foreach (PlayerControl p in PlayerControl.AllPlayerControls) if (!p.Data.IsDead && !p.Data.Disconnected && p != Lovers.lover1 && p != Lovers.lover2 && - p != Mini.mini && !p.Data.Role.IsImpostor && !isNeutral(p) && p != Swapper.swapper) + p != Mini.mini && !p.Data.Role.IsImpostor && !p.isNeutral() && p != Swapper.swapper) possibleTargets.Add(p); if (possibleTargets.Count == 0) @@ -508,7 +508,7 @@ private static void assignModifiers() var crewPlayer = new List(players); impPlayer.RemoveAll(x => !x.Data.Role.IsImpostor); impPlayerL.RemoveAll(x => !x.Data.Role.IsImpostor); - crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || isNeutral(x)); + crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || x.isNeutral()); var modifierCount = Mathf.Min(players.Count + addMaxNum, modifierCountSettings); @@ -632,8 +632,8 @@ private static void assignGuesserGamemode() var neutralPlayer = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList(); var crewPlayer = PlayerControl.AllPlayerControls.ToArray().ToList().OrderBy(x => Guid.NewGuid()).ToList(); impPlayer.RemoveAll(x => !x.Data.Role.IsImpostor); - neutralPlayer.RemoveAll(x => !isNeutral(x) || x == Doomsayer.doomsayer); - crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || isNeutral(x)); + neutralPlayer.RemoveAll(x => !x.isNeutral() || x == Doomsayer.doomsayer); + crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || x.isNeutral()); assignGuesserGamemodeToPlayers(crewPlayer, CustomOptionHolder.guesserGamemodeCrewNumber.GetInt()); assignGuesserGamemodeToPlayers(neutralPlayer, @@ -736,7 +736,7 @@ private static void assignModifiersToPlayers(List modifiers, List !x.Data.Role.IsImpostor); var crewPlayer = new List(playerList); - crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || isNeutral(x)); + crewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || x.isNeutral()); if (modifiers.Contains(RoleId.Assassin)) { @@ -847,7 +847,7 @@ private static void assignModifiersToPlayers(List modifiers, List x.Data.Role.IsImpostor || isNeutral(x)); + shifterCrewPlayer.RemoveAll(x => x.Data.Role.IsImpostor || x.isNeutral()); } playerId = setModifierToRandomPlayer((byte)RoleId.Shifter, shifterCrewPlayer); crewPlayer.RemoveAll(x => x.PlayerId == playerId); diff --git a/TheOtherRoles/Patches/UpdatePatch.cs b/TheOtherRoles/Patches/UpdatePatch.cs index ccb8c2b..c92a93c 100644 --- a/TheOtherRoles/Patches/UpdatePatch.cs +++ b/TheOtherRoles/Patches/UpdatePatch.cs @@ -175,7 +175,7 @@ private static void setNameColors() bool forImp = localPlayer.Data.Role.IsImpostor; bool forKillerTeam = Snitch.Team == Snitch.includeNeutralTeam.KillNeutral && isKillerNeutral(localPlayer); bool forEvilTeam = Snitch.Team == Snitch.includeNeutralTeam.EvilNeutral && isEvilNeutral(localPlayer); - bool forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && isNeutral(localPlayer); + bool forNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && localPlayer.isNeutral(); if (numberOfTasks <= Snitch.taskCountForReveal && Snitch.snitch.IsAlive()) { @@ -195,7 +195,7 @@ private static void setNameColors() bool TargetsImp = p.Data.Role.IsImpostor; bool TargetsKillerTeam = Snitch.Team == Snitch.includeNeutralTeam.KillNeutral && isKillerNeutral(p); bool TargetsEvilTeam = Snitch.Team == Snitch.includeNeutralTeam.EvilNeutral && isEvilNeutral(p); - bool TargetsNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && isNeutral(p); + bool TargetsNeutraTeam = Snitch.Team == Snitch.includeNeutralTeam.AllNeutral && p.isNeutral(); var targetsRole = RoleInfo.getRoleInfoForPlayer(p, false).FirstOrDefault(); if (localPlayer == Snitch.snitch && (TargetsImp || TargetsKillerTeam || TargetsEvilTeam || TargetsNeutraTeam)) { diff --git a/TheOtherRoles/Patches/UsablesPatch.cs b/TheOtherRoles/Patches/UsablesPatch.cs index 2744bd1..3e82246 100644 --- a/TheOtherRoles/Patches/UsablesPatch.cs +++ b/TheOtherRoles/Patches/UsablesPatch.cs @@ -184,25 +184,25 @@ public static bool Prefix(Vent otherVent) } } -[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))] +[HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] internal class VentButtonVisibilityPatch { - private static void Postfix(PlayerControl __instance) + private static void Postfix(HudManager __instance) { - if (__instance.AmOwner && ShowButtons) + if (PlayerControl.LocalPlayer.AmOwner && ShowButtons) { - HudManager.Instance.ImpostorVentButton.Hide(); - HudManager.Instance.SabotageButton.Hide(); + __instance.ImpostorVentButton.Hide(); + __instance.SabotageButton.Hide(); if (ShowButtons) { - if (__instance.roleCanUseVents()) - HudManager.Instance.ImpostorVentButton.Show(); + if (PlayerControl.LocalPlayer.roleCanUseVents()) + __instance.ImpostorVentButton.Show(); - if (__instance.roleCanSabotage()) + if (PlayerControl.LocalPlayer.roleCanSabotage()) { - HudManager.Instance.SabotageButton.Show(); - HudManager.Instance.SabotageButton.gameObject.SetActive(true); + __instance.SabotageButton.Show(); + __instance.SabotageButton.gameObject.SetActive(true); } } } diff --git a/TheOtherRoles/RPC.cs b/TheOtherRoles/RPC.cs index 49d2da2..cd9c717 100644 --- a/TheOtherRoles/RPC.cs +++ b/TheOtherRoles/RPC.cs @@ -707,10 +707,13 @@ public static void dissectionBody(byte playerId, byte killerId) DeadBody[] array = Object.FindObjectsOfType(); + var list = new List(); + list.AddRange(MapData.MapSpawnPosition(false)); + list.AddRange(MapData.FindVentSpawnPositions(false)); + for (var i = 1; i < array.Length && array[i].ParentId == playerId; i++) { - var randomPosition = MapData.MapSpawnPosition().Random(); - array[i].transform.position = randomPosition; + array[i].transform.position = list.Random(); } } @@ -1162,11 +1165,7 @@ public static void erasePlayerRoles(byte playerId, bool ignoreModifier = true) if (player == Jester.jester) Jester.clearAndReload(); if (player == Werewolf.werewolf) Werewolf.clearAndReload(); if (player == Miner.miner) Miner.clearAndReload(); - if (player == Pelican.Player) - { - Pelican.Player = null; - Pelican.PelicanDie(); - } + if (player == Pelican.Player) Pelican.PelicanDie(true); if (player == Arsonist.arsonist) Arsonist.clearAndReload(); if (Guesser.isGuesser(player.PlayerId)) Guesser.clear(player.PlayerId); diff --git a/TheOtherRoles/Resources/stringData.json b/TheOtherRoles/Resources/stringData.json index 386de9c..80e5742 100644 --- a/TheOtherRoles/Resources/stringData.json +++ b/TheOtherRoles/Resources/stringData.json @@ -196,6 +196,17 @@ "0": "Swooper", "13": "隐身豺狼" }, + "Role": { + "0": "Role", + "13": "职业" + }, + "Team": { + "13": "阵营" + }, + "Name": { + "0": "Name", + "13": "名字" + }, "page1": { "0": "Page 1: Vanilla Settings \n\n", "11": "Page 1: バニラの設定 ¦バニラの設定", @@ -258,6 +269,12 @@ "0": "On", "13": "开启" }, + "ExpandOptions": { + "13": "展开" + }, + "CollapseOptions": { + "13": "收起" + }, "presetSelection": { "0": "Preset", "11": "プリセット", @@ -359,6 +376,21 @@ "0": "Maximum Modifiers", "13": "最大附加职业数" }, + "MeetingOptions": { + "13": "会议设置" + }, + "SaboOptions": { + "13": "破坏设置" + }, + "TaskOptions": { + "13": "任务设置" + }, + "MapOptions": { + "13": "地图设置" + }, + "DevicesOption": { + "13": "信息终端设置" + }, "resteButtonCooldown": { "0": "Game Start Cooldown", "13": "游戏开局时重置CD" @@ -619,6 +651,15 @@ "0": "Use Random Map Setting Presets", "13": "使用随机地图设置预设" }, + "exileController": { + "13": "驱逐显示" + }, + "exiledReviveRole": { + "13": "驱逐后显示玩家信息" + }, + "exiledShowTeamNum": { + "13": "驱逐后显示各阵营人数" + }, "debugMode": { "0": "Enable Debug Mode", "13": "开启 Debug 模式" @@ -1261,6 +1302,14 @@ "0": "Vulture Can Use Vents", "13": "可使用管道" }, + "hasImpVision": { + "0": "Have Impostor Vision", + "13": "拥有伪装者视野" + }, + "canCallEmergency": { + "0": "Executioner Can Call Emergency Meeting", + "13": "可以发起紧急会议" + }, "SpecterOptions": { "0": "Specter (Ghost)", "13": "怨灵 (幽灵职业)" @@ -1274,10 +1323,6 @@ "specterAfterMeetingRevived": { "13": "拾取尸体后本轮会议结束才可复活" }, - "jesterCanCallEmergency": { - "0": "Jester Can Call Emergency Meeting", - "13": "小丑可召开会议" - }, "jesterCanVent": { "0": "Jester Can Hide In Vent", "13": "小丑可使用管道" @@ -1410,10 +1455,6 @@ "pavlovsownerCanUseSabo": { "13": "可以破坏" }, - "pavlovsownerHasImpostorVision": { - "0": "Have Impostor Vision", - "13": "拥有伪装者视野" - }, "pavlovsownerCanUseVents": { "13": "可以使用管道" }, @@ -1445,10 +1486,6 @@ "0": "Swoop Speed", "13": "隐身时移速增加" }, - "swooperHasImpVision": { - "0": "Have Impostor Vision", - "13": "拥有伪装者视野" - }, "werewolfRampageCooldown": { "0": "Rampage Cooldown", "13": "狂暴冷却" @@ -1464,10 +1501,6 @@ "juggernautCooldown": { "13": "击杀冷却" }, - "juggernautHasImpVision": { - "0": "Have Impostor Vision", - "13": "拥有伪装者视野" - }, "juggernautReducedkillEach": { "13": "每次击杀后减少的cd" }, @@ -1497,10 +1530,6 @@ "0": "Lawyer Knows Target Role", "13": "可得知目标职业" }, - "lawyerCanCallEmergency": { - "0": "Lawyer Can Call Emergency Meeting", - "13": "可以发起紧急会议" - }, "lawyerTargetCanBeJester": { "0": "Lawyer Target Can Be The Jester", "13": "小丑可以成为律师的客户" @@ -1512,10 +1541,6 @@ "lawyerStolenWin": { "13": "存活会取代客户胜利" }, - "executionerCanCallEmergency": { - "0": "Executioner Can Call Emergency Meeting", - "13": "可以发起紧急会议" - }, "executionerPromotesToLawyer": { "13": "目标职业变更时可以晋升为律师" }, @@ -1623,10 +1648,6 @@ "0": "Thief Can Kill ", "13": "身份窃贼可以击杀 " }, - "thiefHasImpVision": { - "0": "Thief Has Impostor Vision", - "13": "身份窃贼拥有伪装者视野" - }, "thiefCanUseVents": { "0": "Thief Can Use Vents", "13": "身份窃贼可以使用管道" @@ -1680,10 +1701,6 @@ "0": "Prosecutor Dies When They Exile A Crewmate", "13": "驱逐船员会自杀" }, - "prosecutorCanCallEmergency": { - "0": "Prosecutor Can Call Emergency Meeting", - "13": "可以发起紧急会议" - }, "mayorTasksNeededToSeeVoteColors": { "0": "Completed Tasks Needed To See Vote Colors", "13": "获得窥视能力所需完成的任务数" @@ -1879,10 +1896,6 @@ "0": "Alert Duration", "13": "警戒持续时间" }, - "swapperCanCallEmergency": { - "0": "Swapper Can Call Emergency Meeting", - "13": "可以发起紧急会议" - }, "swapperCanFixSabotages": { "0": "Swapper Can Fix Sabotages", "13": "可修理紧急破坏" @@ -2023,10 +2036,6 @@ "0": "Number Of Examinations", "13": "预言总次数" }, - "prophetCanCallEmergency": { - "0": "Prophet Can Call Emergency Meeting", - "13": "可以召开紧急会议" - }, "prophetIsRevealed": { "0": "Prophet Is Revealed To The Killers", "13": "可以被杀手发现" @@ -2069,20 +2078,12 @@ }, "spyCanDieToSheriff": { "0": "Spy Can Die To Sheriff", - "13": "可被警长执法" + "13": "卧底可被警长执法" }, "spyImpostorsCanKillAnyone": { "0": "Impostors Can Kill Anyone If There Is A Spy", "13": "卧底在场时伪装者可击杀队友" }, - "spyCanEnterVents": { - "0": "Spy Can Enter Vents", - "13": "可使用管道" - }, - "spyHasImpostorVision": { - "0": "Spy Has Impostor Vision", - "13": "拥有伪装者视野" - }, "portalmakerCooldown": { "0": "Portalmaker Cooldown", "13": "构建星门冷却" @@ -2208,18 +2209,10 @@ "0": "Trap Information Type", "13": "陷阱信息类型" }, - "trapperInfoType1": { - "0": "Role", - "13": "职业" - }, "trapperInfoType2": { "0": "Good/Evil Role", "13": "善良/邪恶" }, - "trapperInfoType3": { - "0": "Name", - "13": "名字" - }, "trapperTrapDuration": { "0": "Trap Duration", "13": "陷阱定身时间" diff --git a/TheOtherRoles/Roles/Crewmate/Medium.cs b/TheOtherRoles/Roles/Crewmate/Medium.cs index 4d3c2bc..a5bc2a2 100644 --- a/TheOtherRoles/Roles/Crewmate/Medium.cs +++ b/TheOtherRoles/Roles/Crewmate/Medium.cs @@ -142,7 +142,7 @@ public static string getInfo(PlayerControl target, PlayerControl killer) condition = "个可以使用管道的玩家" + (count == 1 ? "" : ""); break; case 2: - count = alivePlayersList.Count(pc => isNeutral(pc) && !isKillerNeutral(pc)); + count = alivePlayersList.Count(pc => pc.isNeutral() && !isKillerNeutral(pc)); condition = $"名玩家{(count == 1 ? "" : "")}{(count == 1 ? "是" : "是")}非击杀型中立"; break; } diff --git a/TheOtherRoles/Roles/Crewmate/Prophet.cs b/TheOtherRoles/Roles/Crewmate/Prophet.cs index c669f0e..4a33530 100644 --- a/TheOtherRoles/Roles/Crewmate/Prophet.cs +++ b/TheOtherRoles/Roles/Crewmate/Prophet.cs @@ -34,7 +34,7 @@ public static bool IsRed(PlayerControl p) if (killCrewAsRed && (Sheriff.Player.Any(x => x == p) || p == Sheriff.Deputy || p == Veteran.veteran)) return true; - if (benignNeutralAsRed && isNeutral(p) && (Amnisiac.Player.Contains(p) || Pursuer.Player.Contains(p) || Survivor.Player.Contains(p))) return true; + if (benignNeutralAsRed && p.isNeutral() && (Amnisiac.Player.Contains(p) || Pursuer.Player.Contains(p) || Survivor.Player.Contains(p))) return true; return evilNeutralAsRed && isEvilNeutral(p); } diff --git a/TheOtherRoles/Roles/Ghost/Specter.cs b/TheOtherRoles/Roles/Ghost/Specter.cs index 0ddee36..4366cc2 100644 --- a/TheOtherRoles/Roles/Ghost/Specter.cs +++ b/TheOtherRoles/Roles/Ghost/Specter.cs @@ -10,7 +10,7 @@ public class Specter public static float duration; public static bool resetRole; - public static bool afterMeetingRevived; + public static bool afterMeetingRevive; public static bool revive; public static bool remember; @@ -20,7 +20,7 @@ public static void ClearAndReload() Player = null; revive = false; remember = !CustomOptionHolder.specterAfterMeetingTakeRole.GetBool(); - afterMeetingRevived = CustomOptionHolder.specterAfterMeetingRevived.GetBool(); + afterMeetingRevive = CustomOptionHolder.specterAfterMeetingRevived.GetBool(); resetRole = CustomOptionHolder.specterResetRole.GetBool(); duration = CustomOptionHolder.specterDuration.GetFloat(); } @@ -333,7 +333,7 @@ public static void TakeRole(byte targetId) } } - if (afterMeetingRevived) + if (afterMeetingRevive) { revive = true; return; diff --git a/TheOtherRoles/Roles/Modifier/Lovers.cs b/TheOtherRoles/Roles/Modifier/Lovers.cs index ebd35a2..aa2d18b 100644 --- a/TheOtherRoles/Roles/Modifier/Lovers.cs +++ b/TheOtherRoles/Roles/Modifier/Lovers.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; namespace TheOtherRoles.Roles.Modifier; @@ -20,35 +20,28 @@ public static bool isLover(this PlayerControl player) return player != null && (player == lover1 || player == lover2); } - public static bool existing() + public static bool IsAlive() { - return lover1 != null && lover2 != null && !lover1.Data.Disconnected && !lover2.Data.Disconnected; + // ADD NOT ACKED IS LOVER + return lover1.IsAlive() && lover2.IsAlive() && !notAckedExiledIsLover; } - public static bool existingAndAlive() + public static bool isKillerLover() { - return existing() && !lover1.Data.IsDead && !lover2.Data.IsDead && - !notAckedExiledIsLover; // ADD NOT ACKED IS LOVER + return lover1.isKiller() || lover2.isKiller(); } public static PlayerControl otherLover(PlayerControl player) { - if (!existing() || player == null) return null; + if (player == null) return null; if (player == lover1) return lover2; if (player == lover2) return lover1; return null; } - public static bool existingWithKiller() - { - return existing() && (lover1.isKiller() || lover2.isKiller()); - } - public static bool hasAliveKillingLover(this PlayerControl player) { - if (!existingAndAlive() || !existingWithKiller()) - return false; - return player != null && (player == lover1 || player == lover2); + return player.isLover() && IsAlive() && isKillerLover(); } public static void clearAndReload() diff --git a/TheOtherRoles/Roles/Modifier/Shifter.cs b/TheOtherRoles/Roles/Modifier/Shifter.cs index f20df78..b2f9316 100644 --- a/TheOtherRoles/Roles/Modifier/Shifter.cs +++ b/TheOtherRoles/Roles/Modifier/Shifter.cs @@ -42,7 +42,7 @@ public static bool isShiftNeutral(PlayerControl player) } } - return isNeutral(player); + return player.isNeutral(); } public static void shiftRole(PlayerControl player1, PlayerControl player2, bool repeat = true) diff --git a/TheOtherRoles/Roles/Neutral/Arsonist.cs b/TheOtherRoles/Roles/Neutral/Arsonist.cs index dfb0820..854fac4 100644 --- a/TheOtherRoles/Roles/Neutral/Arsonist.cs +++ b/TheOtherRoles/Roles/Neutral/Arsonist.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using UnityEngine; namespace TheOtherRoles.Roles.Neutral; diff --git a/TheOtherRoles/Roles/Neutral/Jester.cs b/TheOtherRoles/Roles/Neutral/Jester.cs index 2b53e8b..d767e20 100644 --- a/TheOtherRoles/Roles/Neutral/Jester.cs +++ b/TheOtherRoles/Roles/Neutral/Jester.cs @@ -1,4 +1,4 @@ -using UnityEngine; +using UnityEngine; namespace TheOtherRoles.Roles.Neutral; diff --git a/TheOtherRoles/Roles/Neutral/Pelican.cs b/TheOtherRoles/Roles/Neutral/Pelican.cs index 9879a87..e798690 100644 --- a/TheOtherRoles/Roles/Neutral/Pelican.cs +++ b/TheOtherRoles/Roles/Neutral/Pelican.cs @@ -24,23 +24,17 @@ public static void PelicanKill(byte targetId) eatenPlayers.Add(target); } - public static void PelicanDie() + public static void PelicanDie(bool clear = false) { - if (Player == null) + if (clear || Player?.Data.IsDead == true) { if (eatenPlayers.Any(x => x == PlayerControl.LocalPlayer)) { HudManager.Instance.PlayerCam.Target = PlayerControl.LocalPlayer; PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(Player.transform.position); } - eatenPlayers = new(); + clearAndReload(clear); } - - if (Player?.Data.IsDead == true) - { - HudManager.Instance.PlayerCam.Target = PlayerControl.LocalPlayer; - PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(Player.transform.position); - }; } public static void clearAndReload(bool clear = true) diff --git a/TheOtherRoles/Roles/RoleHelpers.cs b/TheOtherRoles/Roles/RoleHelpers.cs index 4f24836..c7ea0cc 100644 --- a/TheOtherRoles/Roles/RoleHelpers.cs +++ b/TheOtherRoles/Roles/RoleHelpers.cs @@ -421,13 +421,18 @@ public static void Postfix([HarmonyArgument(0)] PlayerControl player) public static bool otherNeutral(PlayerControl player) { - if (Pelican.Player == player) return false; - if (PartTimer.partTimer == player && PartTimer.target == null) return true; - if (Lawyer.lawyer == player && Lawyer.target.IsDead()) return true; - if (isNeutral(player) && !Jackal.jackal.Contains(player) && player != Jackal.Sidekick && - player != Pavlovsdogs.pavlovsowner && !Pavlovsdogs.pavlovsdogs.Contains(player)) - return true; - return false; + if (Pelican.Player == player || + (PartTimer.partTimer == player && PartTimer.target != null) || + (Lawyer.lawyer == player && Lawyer.target.IsAlive()) || + player == Jackal.Sidekick || + player == Pavlovsdogs.pavlovsowner || + Jackal.jackal.Any(x => x.PlayerId == player.PlayerId) || + Pavlovsdogs.pavlovsdogs.Any(x => x.PlayerId == player.PlayerId)) + { + return false; + } + + return player.isNeutral(); } private static void AssignRole(PlayerControl player, AssignType assignType) diff --git a/TheOtherRoles/SubmergedCompatibility.cs b/TheOtherRoles/SubmergedCompatibility.cs index 6f833db..d9d744e 100644 --- a/TheOtherRoles/SubmergedCompatibility.cs +++ b/TheOtherRoles/SubmergedCompatibility.cs @@ -4,7 +4,6 @@ using System.Reflection; using BepInEx; using BepInEx.Unity.IL2CPP; -using TheOtherRoles.Utilities; using UnityEngine; namespace TheOtherRoles; diff --git a/TheOtherRoles/TheOtherRoles.csproj b/TheOtherRoles/TheOtherRoles.csproj index 75bd9f0..93bae96 100644 --- a/TheOtherRoles/TheOtherRoles.csproj +++ b/TheOtherRoles/TheOtherRoles.csproj @@ -1,7 +1,7 @@  net6.0 - 1.1.2.1 + 1.1.2.2 TheOtherUs mxyx-club latest