diff --git a/Modules/AURoleOptions.cs b/Modules/AURoleOptions.cs index 18ac4a4e5..f83163363 100644 --- a/Modules/AURoleOptions.cs +++ b/Modules/AURoleOptions.cs @@ -66,5 +66,10 @@ public static bool ShapeshifterLeaveSkin get => Opt.GetBool(BoolOptionNames.ShapeshifterLeaveSkin); set => Opt.SetBool(BoolOptionNames.ShapeshifterLeaveSkin, value); } + public static bool NoisemakerImpostorAlert + { + get => Opt.GetBool(BoolOptionNames.NoisemakerImpostorAlert); + set => Opt.SetBool(BoolOptionNames.NoisemakerImpostorAlert, value); + } } } \ No newline at end of file diff --git a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs index adece0901..93315e846 100644 --- a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs +++ b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs @@ -93,6 +93,10 @@ public override IGameOptions BuildGameOptions() opt.SetBool(BoolOptionNames.AnonymousVotes, false); break; } + if (!role.IsImpostor()) + { + AURoleOptions.NoisemakerImpostorAlert = true; + } var roleClass = player.GetRoleClass(); roleClass?.ApplyGameOptions(opt); diff --git a/Patches/ExilePatch.cs b/Patches/ExilePatch.cs index fdcf3c8ab..e65526038 100644 --- a/Patches/ExilePatch.cs +++ b/Patches/ExilePatch.cs @@ -17,11 +17,11 @@ public static void Postfix(ExileController __instance) { try { - WrapUpPostfix(__instance.exiled); + WrapUpPostfix(__instance.initData.networkedPlayer); } finally { - WrapUpFinalizer(__instance.exiled); + WrapUpFinalizer(__instance.initData.networkedPlayer); } } } @@ -33,11 +33,11 @@ public static void Postfix(AirshipExileController __instance) { try { - WrapUpPostfix(__instance.exiled); + WrapUpPostfix(__instance.initData.networkedPlayer); } finally { - WrapUpFinalizer(__instance.exiled); + WrapUpFinalizer(__instance.initData.networkedPlayer); } } } diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index 8d66b928f..07f106842 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -339,7 +339,7 @@ public static void Postfix() OptionItem.SyncAllOptions(); } } - [HarmonyPatch(typeof(RolesSettingsMenu), nameof(RolesSettingsMenu.Start))] + [HarmonyPatch(typeof(RolesSettingsMenu), nameof(RolesSettingsMenu.InitialSetup))] public static class RolesSettingsMenuPatch { public static void Postfix(RolesSettingsMenu __instance) diff --git a/Patches/onGameStartedPatch.cs b/Patches/onGameStartedPatch.cs index fcaa27aaf..df1c07423 100644 --- a/Patches/onGameStartedPatch.cs +++ b/Patches/onGameStartedPatch.cs @@ -153,15 +153,13 @@ public static void Prefix() PlayerControl.LocalPlayer.RpcSetRole(RoleTypes.Crewmate); PlayerControl.LocalPlayer.Data.IsDead = true; } - Dictionary<(byte, byte), RoleTypes> rolesMap = new(); foreach (var (role, info) in CustomRoleManager.AllRolesInfo) { if (info.IsDesyncImpostor) { - AssignDesyncRole(role, AllPlayers, senders, rolesMap, BaseRole: info.BaseRoleType.Invoke()); + AssignDesyncRole(role, AllPlayers, senders, BaseRole: info.BaseRoleType.Invoke()); } } - MakeDesyncSender(senders, rolesMap); } //以下、バニラ側の役職割り当てが入る } @@ -173,7 +171,7 @@ public static void Postfix() // 不要なオブジェクトの削除 RpcSetRoleReplacer.senders = null; - RpcSetRoleReplacer.OverriddenSenderList = null; + RpcSetRoleReplacer.DesyncImpostorList = null; RpcSetRoleReplacer.StoragedData = null; //Utils.ApplySuffix(); @@ -345,7 +343,7 @@ public static void Postfix() Utils.SyncAllSettings(); SetColorPatch.IsAntiGlitchDisabled = false; } - private static void AssignDesyncRole(CustomRoles role, List AllPlayers, Dictionary senders, Dictionary<(byte, byte), RoleTypes> rolesMap, RoleTypes BaseRole, RoleTypes hostBaseRole = RoleTypes.Crewmate) + private static void AssignDesyncRole(CustomRoles role, List AllPlayers, Dictionary senders, RoleTypes BaseRole, RoleTypes hostBaseRole = RoleTypes.Crewmate) { if (!role.IsPresent()) return; @@ -358,53 +356,26 @@ private static void AssignDesyncRole(CustomRoles role, List AllPl var player = AllPlayers[rand.Next(0, AllPlayers.Count)]; AllPlayers.Remove(player); PlayerState.GetByPlayerId(player.PlayerId).SetMainRole(role); + RpcSetRoleReplacer.DesyncImpostorList.Add(player.PlayerId); - var selfRole = player.PlayerId == hostId ? hostBaseRole : BaseRole; - var othersRole = player.PlayerId == hostId ? RoleTypes.Crewmate : RoleTypes.Scientist; - - //Desync役職視点 - foreach (var target in Main.AllPlayerControls) + var hostRole = player.PlayerId == hostId ? hostBaseRole : RoleTypes.Crewmate; + foreach (var seer in Main.AllPlayerControls) { - if (player.PlayerId != target.PlayerId) + if (seer.PlayerId == hostId) { - rolesMap[(player.PlayerId, target.PlayerId)] = othersRole; + //ホスト視点は即確定 + player.StartCoroutine(player.CoSetRole(hostRole, false)); } else { - rolesMap[(player.PlayerId, target.PlayerId)] = selfRole; - } - } - - //他者視点 - foreach (var seer in Main.AllPlayerControls) - { - if (player.PlayerId != seer.PlayerId) - { - rolesMap[(seer.PlayerId, player.PlayerId)] = othersRole; + var assignRole = seer.PlayerId == player.PlayerId ? BaseRole : RoleTypes.Scientist; + senders[player.PlayerId].RpcSetRole(player, assignRole, seer.GetClientId()); } } - RpcSetRoleReplacer.OverriddenSenderList.Add(senders[player.PlayerId]); - //ホスト視点はロール決定 - player.StartCoroutine(player.CoSetRole(othersRole, false)); + //vailla配役の回避 player.Data.IsDead = true; } } - public static void MakeDesyncSender(Dictionary senders, Dictionary<(byte, byte), RoleTypes> rolesMap) - { - var hostId = PlayerControl.LocalPlayer.PlayerId; - foreach (var seer in Main.AllPlayerControls) - { - var sender = senders[seer.PlayerId]; - foreach (var target in Main.AllPlayerControls) - { - if (rolesMap.TryGetValue((seer.PlayerId, target.PlayerId), out var role)) - { - sender.RpcSetRole(seer, role, target.GetClientId()); - } - } - } - } - private static List AssignCustomRolesFromList(CustomRoles role, List players, int RawCount = -1) { if (players == null || players.Count <= 0) return null; @@ -480,8 +451,7 @@ class RpcSetRoleReplacer public static bool doReplace = false; public static Dictionary senders; public static List<(PlayerControl, RoleTypes)> StoragedData = new(); - // 役職Desyncなど別の処理でSetRoleRpcを書き込み済みなため、追加の書き込みが不要なSenderのリスト - public static List OverriddenSenderList; + public static List DesyncImpostorList; public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] RoleTypes roleType) { if (doReplace && senders != null) @@ -493,21 +463,24 @@ public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] RoleTyp } public static void Release() { - foreach (var sender in senders) + foreach (var (player, role) in StoragedData) { - if (OverriddenSenderList.Contains(sender.Value)) continue; - if (sender.Value.CurrentState != CustomRpcSender.State.InRootMessage) - throw new InvalidOperationException("A CustomRpcSender had Invalid State."); + //ホスト視点は即確定 + player.StartCoroutine(player.CoSetRole(role, false)); - foreach (var pair in StoragedData) + var impostorRole = role is RoleTypes.Impostor or RoleTypes.Shapeshifter or RoleTypes.Phantom; + if (impostorRole && DesyncImpostorList.Count != 0) + { + foreach (var seer in Main.AllPlayerControls) + { + var assignRole = DesyncImpostorList.Contains(seer.PlayerId) ? RoleTypes.Scientist : role; + senders[player.PlayerId].RpcSetRole(player, assignRole, seer.GetClientId()); + } + } + else { - pair.Item1.StartCoroutine(pair.Item1.CoSetRole(pair.Item2, false)); - sender.Value.AutoStartRpc(pair.Item1.NetId, (byte)RpcCalls.SetRole, Utils.GetPlayerById(sender.Key).GetClientId()) - .Write((ushort)pair.Item2) - .Write(false) - .EndRpc(); + senders[player.PlayerId].RpcSetRole(player, role); } - sender.Value.EndMessage(); } doReplace = false; } @@ -515,7 +488,7 @@ public static void StartReplace(Dictionary senders) { RpcSetRoleReplacer.senders = senders; StoragedData = new(); - OverriddenSenderList = new(); + DesyncImpostorList = new(); doReplace = true; } } diff --git a/main.cs b/main.cs index 21dda5e17..89a01156b 100644 --- a/main.cs +++ b/main.cs @@ -59,9 +59,9 @@ public class Main : BasePlugin public static readonly Version ParsedForkVersion = Version.Parse(ForkVersion); public const string PluginGuid = "com.emptybottle.townofhost"; - public const string PluginVersion = "5.1.7"; + public const string PluginVersion = "5.1.8"; // サポートされている最低のAmongUsバージョン - public static readonly string LowestSupportedVersion = "2024.6.18"; + public static readonly string LowestSupportedVersion = "2024.8.13"; // このバージョンのみで公開ルームを無効にする場合 public static readonly bool IsPublicAvailableOnThisVersion = false; // プレリリースかどうか