From 22265fcf8e820f0ca9ef12f120b655f565635928 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Mon, 2 Jun 2025 10:00:51 +0200 Subject: [PATCH] fix --- GameMode/HotPotato.cs | 8 +++++++- Main.cs | 4 ++-- Modules/CustomRpcSender.cs | 2 +- Modules/ExtendedPlayerControl.cs | 2 +- Modules/GuessManager.cs | 23 ++++++++++++++++++++--- Modules/RPC.cs | 3 +-- Modules/Utils.cs | 1 + Patches/ChatCommandPatch.cs | 6 +++++- Patches/GameOptionsMenuPatch.cs | 2 +- Patches/IntroPatch.cs | 1 + Resources/Lang/en_US.json | 11 ++++++----- Roles/AddOns/Crewmate/Stressed.cs | 2 +- Roles/AddOns/Impostor/Damocles.cs | 2 +- Roles/Crewmate/Medic.cs | 30 +++++++++++++++++++++++++----- Roles/Crewmate/SwordsMan.cs | 1 + Roles/Impostor/Mafioso.cs | 2 +- Roles/Neutral/Glitch.cs | 2 +- Roles/Neutral/Vulture.cs | 17 +++++++++++++++-- 18 files changed, 91 insertions(+), 28 deletions(-) diff --git a/GameMode/HotPotato.cs b/GameMode/HotPotato.cs index 76e0a616c..75b2ba3fa 100644 --- a/GameMode/HotPotato.cs +++ b/GameMode/HotPotato.cs @@ -20,6 +20,7 @@ internal static class HotPotato private static (byte HolderID, byte LastHolderID, int TimeLeft, int RoundNum) HotPotatoState; private static Dictionary SurvivalTimes; private static float DefaultSpeed; + private static long LastPassTS; public static bool CanPassViaKillButton => HolderCanPassViaKillButton.GetBool(); @@ -64,6 +65,7 @@ internal static class HotPotato public static void OnGameStart() { HotPotatoState = (byte.MaxValue, byte.MaxValue, Time.GetInt(), 1); + LastPassTS = Utils.TimeStamp; } public static int GetSurvivalTime(byte id) @@ -97,7 +99,7 @@ internal static class HotPotato [SuppressMessage("ReSharper", "UnusedMember.Local")] public static void Postfix(PlayerControl __instance) { - if (!CustomGameMode.HotPotato.IsActiveOrIntegrated() || !Main.IntroDestroyed || !AmongUsClient.Instance.AmHost || !GameStates.IsInTask || __instance.PlayerId >= 254) return; + if (!CustomGameMode.HotPotato.IsActiveOrIntegrated() || !Main.IntroDestroyed || !AmongUsClient.Instance.AmHost || !GameStates.IsInTask || __instance.PlayerId >= 254 || Utils.GameStartTimeStamp + 15 > Utils.TimeStamp) return; PlayerControl Holder = Utils.GetPlayerById(HotPotatoState.HolderID); @@ -128,6 +130,8 @@ internal static class HotPotato return; } + if (Utils.GameStartTimeStamp + 30 > now && LastPassTS == now) return; + PlayerControl[] aapc = Main.AllAlivePlayerControls; Vector2 pos = Holder.Pos(); if (HotPotatoState.HolderID != __instance.PlayerId || !aapc.Any(x => x.PlayerId != HotPotatoState.HolderID && (x.PlayerId != HotPotatoState.LastHolderID || aapc.Length == 2) && Vector2.Distance(x.Pos(), pos) <= Range.GetFloat())) return; @@ -190,6 +194,8 @@ internal static class HotPotato } catch (Exception ex) { Logger.Exception(ex, "HotPotatoManager.FixedUpdatePatch.PassHotPotato"); } finally { Utils.NotifyRoles(SpecifyTarget: target); } + + LastPassTS = Utils.TimeStamp; } } } \ No newline at end of file diff --git a/Main.cs b/Main.cs index 3403f3232..de0d6aa32 100644 --- a/Main.cs +++ b/Main.cs @@ -35,8 +35,8 @@ public class Main : BasePlugin private const string DebugKeyHash = "c0fd562955ba56af3ae20d7ec9e64c664f0facecef4b3e366e109306adeae29d"; private const string DebugKeySalt = "59687b"; private const string PluginGuid = "com.gurge44.endlesshostroles"; - public const string PluginVersion = "5.6.4"; - public const string PluginDisplayVersion = "5.6.4"; + public const string PluginVersion = "5.6.5"; + public const string PluginDisplayVersion = "5.6.5"; public const bool TestBuild = false; public const string NeutralColor = "#ffab1b"; diff --git a/Modules/CustomRpcSender.cs b/Modules/CustomRpcSender.cs index 8ee986f1a..0f9e62bd1 100644 --- a/Modules/CustomRpcSender.cs +++ b/Modules/CustomRpcSender.cs @@ -643,7 +643,7 @@ public static class CustomRpcSenderExtensions else notifies[text] = expireTS; - bool returnValue = pc.IsNonHostModClient(); + bool returnValue = pc.IsNonHostModdedClient(); if (returnValue) NameNotifyManager.SendRPC(sender, pc.PlayerId, text, expireTS, overrideAll); if (setName) returnValue |= Utils.WriteSetNameRpcsToSender(ref sender, false, false, false, false, false, false, pc, [pc], [], out bool senderWasCleared) && !senderWasCleared; diff --git a/Modules/ExtendedPlayerControl.cs b/Modules/ExtendedPlayerControl.cs index 461a097bb..d99b08f12 100644 --- a/Modules/ExtendedPlayerControl.cs +++ b/Modules/ExtendedPlayerControl.cs @@ -884,7 +884,7 @@ internal static class ExtendedPlayerControl return Main.PlayerStates.TryGetValue(player.PlayerId, out PlayerState state) ? state.TaskState : new(); } - public static bool IsNonHostModClient(this PlayerControl pc) + public static bool IsNonHostModdedClient(this PlayerControl pc) { return pc.IsModdedClient() && !pc.IsHost(); } diff --git a/Modules/GuessManager.cs b/Modules/GuessManager.cs index 9cae1c239..734501366 100644 --- a/Modules/GuessManager.cs +++ b/Modules/GuessManager.cs @@ -563,11 +563,18 @@ public static class GuessManager if (playerVoteArea.VotedFor != pc.PlayerId) continue; playerVoteArea.UnsetVote(); + meetingHud.SetDirtyBit(1U); PlayerControl voteAreaPlayer = Utils.GetPlayerById(playerVoteArea.TargetPlayerId); + if (voteAreaPlayer == null) continue; - if (!voteAreaPlayer.AmOwner) meetingHud.RpcClearVote(voteAreaPlayer.OwnerId); - else meetingHud.ClearVote(); + if (!voteAreaPlayer.AmOwner) + { + meetingHud.RpcClearVote(voteAreaPlayer.OwnerId); + meetingHud.SetDirtyBit(1U); + } + else + meetingHud.ClearVote(); } MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.GuessKill, SendOption.Reliable); @@ -595,7 +602,17 @@ public static class GuessManager PlayerVoteArea voteArea = MeetingHud.Instance.playerStates.First(x => x.TargetPlayerId == pc.PlayerId); - if (voteArea.DidVote) voteArea.UnsetVote(); + if (voteArea.DidVote) + { + voteArea.UnsetVote(); + + if (AmongUsClient.Instance.AmHost) + { + meetingHud.SetDirtyBit(1U); + meetingHud.RpcClearVote(pc.OwnerId); + meetingHud.SetDirtyBit(1U); + } + } voteArea.AmDead = true; voteArea.Overlay.gameObject.SetActive(true); diff --git a/Modules/RPC.cs b/Modules/RPC.cs index b64a78010..6735ede98 100644 --- a/Modules/RPC.cs +++ b/Modules/RPC.cs @@ -1015,9 +1015,8 @@ internal static class RPCHandlerPatch int chargePercent = reader.ReadInt32(); long lastUpdate = long.Parse(reader.ReadString()); (Main.PlayerStates[id].Role as Chronomancer)?.ReceiveRPC(isRampaging, chargePercent, lastUpdate); - } - break; + } case CustomRPC.SetMedicalerProtectList: { Medic.ReceiveRPCForProtectList(reader); diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 1f217be8b..48428227b 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -3200,6 +3200,7 @@ public static class Utils LateTask.New(() => { + if (pc.CurrentOutfit.PetId != "") return; var sender = CustomRpcSender.Create("Reassign pet", SendOption.Reliable); string petId = PetsHelper.GetPetId(); PetsHelper.SetPet(pc, petId, sender); diff --git a/Patches/ChatCommandPatch.cs b/Patches/ChatCommandPatch.cs index 50856eb28..4791cea9d 100644 --- a/Patches/ChatCommandPatch.cs +++ b/Patches/ChatCommandPatch.cs @@ -2428,7 +2428,11 @@ internal static class ChatCommands Main.NickName = args[1]; else { - if (!Options.PlayerCanSetName.GetBool() && !IsPlayerVIP(player.FriendCode)) return; + if (!Options.PlayerCanSetName.GetBool() && !IsPlayerVIP(player.FriendCode) && !player.FriendCode.GetDevUser().up) + { + Utils.SendMessage(GetString("Message.OnlyVIPCanUse"), player.PlayerId, sendOption: SendOption.None); + return; + } if (GameStates.IsInGame) { diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index 8646ca8f8..e97fa842a 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -1107,7 +1107,7 @@ public static class GameSettingMenuPatch Vector3 gameSettingsLabelPos = gameSettingsLabel.transform.localPosition; - CustomGameMode[] gms = Enum.GetValues().SkipLast(1).ToArray(); + CustomGameMode[] gms = Enum.GetValues().SkipLast(2).ToArray(); int totalCols = Mathf.Max(1, Mathf.CeilToInt(gms.Length / 5f)); System.Collections.Generic.Dictionary gmColors = new() diff --git a/Patches/IntroPatch.cs b/Patches/IntroPatch.cs index af80e1951..a62f2a4fa 100644 --- a/Patches/IntroPatch.cs +++ b/Patches/IntroPatch.cs @@ -1077,6 +1077,7 @@ internal static class IntroCutsceneDestroyPatch foreach (PlayerControl pc in aapc) { if (pc.Is(CustomRoles.GM)) continue; + if (pc.CurrentOutfit.PetId != "") continue; string petId = PetsHelper.GetPetId(); PetsHelper.SetPet(pc, petId, sender); diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 6dcda75c8..a2e41fc95 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -2324,6 +2324,7 @@ "Message.SetColor": "Your color is set to: {0}", "Message.AllowLevelRange": "The game level can be set in the range: 0-100", "Message.AllowNameLength": "Nickname can be set length: 1-10", + "Message.OnlyVIPCanUse": "According to the host's settings, only VIP players can use this command", "Message.OnlyCanUseInLobby": "Sorry, this command can only be used in the lobby", "Message.CanNotUseInLobby": "Sorry, this command cannot be used in the lobby", "Message.CanNotUseByHost": "Sorry, Host can't use this command", @@ -7208,11 +7209,11 @@ "Quiz.Questions.Medium.81.Answer.E": "7", "Quiz.Questions.Medium.81.CorrectAnswer": "B", "Quiz.Questions.Medium.82": "Which of the following is a correct chemical reaction for the formation of water?", - "Quiz.Questions.Medium.82.Answer.A": "2H₂ + O₂ → 2H₂O", - "Quiz.Questions.Medium.82.Answer.B": "H₂ + O₂ → H₂O", - "Quiz.Questions.Medium.82.Answer.C": "2H₂ + O₂ → H₂O₂", - "Quiz.Questions.Medium.82.Answer.D": "H₂ + O₂ → 2H₂O", - "Quiz.Questions.Medium.82.Answer.E": "2H₂ + O₂ → H₂O₂", + "Quiz.Questions.Medium.82.Answer.A": "2H2 + O2 → 2H2O", + "Quiz.Questions.Medium.82.Answer.B": "H2 + O2 → H2O", + "Quiz.Questions.Medium.82.Answer.C": "2H2 + O2 → H2O2", + "Quiz.Questions.Medium.82.Answer.D": "H2 + O2 → 2H2O", + "Quiz.Questions.Medium.82.Answer.E": "2H2 + O2 → H2O2", "Quiz.Questions.Medium.82.CorrectAnswer": "A", "Quiz.Questions.Medium.83": "If the sum of three consecutive integers is 57, what is the middle integer?", "Quiz.Questions.Medium.83.Answer.A": "18", diff --git a/Roles/AddOns/Crewmate/Stressed.cs b/Roles/AddOns/Crewmate/Stressed.cs index 583502d99..b0a903e52 100644 --- a/Roles/AddOns/Crewmate/Stressed.cs +++ b/Roles/AddOns/Crewmate/Stressed.cs @@ -143,7 +143,7 @@ public class Stressed : IAddon Achievements.Type.OutOfTime.Complete(); } - if (pc.IsNonHostModClient()) SendRPC(pc.PlayerId, Timers[pc.PlayerId], LastUpdates[pc.PlayerId]); + if (pc.IsNonHostModdedClient()) SendRPC(pc.PlayerId, Timers[pc.PlayerId], LastUpdates[pc.PlayerId]); if (!pc.IsModdedClient()) Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc); } diff --git a/Roles/AddOns/Impostor/Damocles.cs b/Roles/AddOns/Impostor/Damocles.cs index 00a693d4b..a71d9b831 100644 --- a/Roles/AddOns/Impostor/Damocles.cs +++ b/Roles/AddOns/Impostor/Damocles.cs @@ -82,7 +82,7 @@ public class Damocles : IAddon Achievements.Type.OutOfTime.Complete(); } - if (pc.IsNonHostModClient()) SendRPC(id); + if (pc.IsNonHostModdedClient()) SendRPC(id); if (!pc.IsModdedClient()) Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc); } diff --git a/Roles/Crewmate/Medic.cs b/Roles/Crewmate/Medic.cs index 68d735267..134afa125 100644 --- a/Roles/Crewmate/Medic.cs +++ b/Roles/Crewmate/Medic.cs @@ -115,13 +115,21 @@ public class Medic : RoleBase if (!Utils.DoRPC) return; MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetMedicalerProtectList, SendOption.Reliable); + writer.Write(1); writer.Write(ProtectList.Count); - ProtectList.Do(x => writer.Write(x)); + ProtectList.ForEach(x => writer.Write(x)); AmongUsClient.Instance.FinishRpcImmediately(writer); } public static void ReceiveRPCForProtectList(MessageReader reader) { + if (reader.ReadInt32() != 1) + { + byte id = reader.ReadByte(); + Main.PlayerStates[id].InitTask(id.GetPlayer()); + return; + } + int count = reader.ReadInt32(); ProtectList = []; for (var i = 0; i < count; i++) ProtectList.Add(reader.ReadByte()); @@ -156,9 +164,6 @@ public class Medic : RoleBase public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { if (killer == null || target == null) return false; - - if (!CanUseKillButton(killer)) return false; - if (ProtectList.Contains(target.PlayerId)) return false; killer.RpcRemoveAbilityUse(); @@ -192,6 +197,20 @@ public class Medic : RoleBase else Achievements.Type.ImUnstoppable.Complete(); } + if (killer.GetAbilityUseLimit() < 1f) + { + killer.RpcChangeRoleBasis(CustomRoles.CrewmateEHR); + killer.RpcResetTasks(); + + if (killer.IsNonHostModdedClient()) + { + MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetMedicalerProtectList, SendOption.Reliable); + writer.Write(2); + writer.Write(killer.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + } + return false; } @@ -230,6 +249,7 @@ public class Medic : RoleBase if (Utils.DoRPC) { sender.AutoStartRpc(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetMedicalerProtectList); + sender.Write(1); sender.Write(ProtectList.Count); ProtectList.ForEach(x => sender.Write(x)); sender.EndRpc(); @@ -311,7 +331,7 @@ public class Medic : RoleBase { TempMarkProtectedList = []; - foreach (byte pc in ProtectList) Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(pc), SpecifyTarget: target); + foreach (byte id in ProtectList) Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(id), SpecifyTarget: target); } } diff --git a/Roles/Crewmate/SwordsMan.cs b/Roles/Crewmate/SwordsMan.cs index 6932a5548..bde226f56 100644 --- a/Roles/Crewmate/SwordsMan.cs +++ b/Roles/Crewmate/SwordsMan.cs @@ -104,6 +104,7 @@ public class SwordsMan : RoleBase Killed.Add(killer.PlayerId); SetKillCooldown(killer.PlayerId); killer.RpcChangeRoleBasis(CustomRoles.CrewmateEHR); + killer.RpcResetTasks(); Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: killer); } } \ No newline at end of file diff --git a/Roles/Impostor/Mafioso.cs b/Roles/Impostor/Mafioso.cs index 5c4e06017..30be60756 100644 --- a/Roles/Impostor/Mafioso.cs +++ b/Roles/Impostor/Mafioso.cs @@ -196,7 +196,7 @@ public class Mafioso : RoleBase if (before1CD != Pistol1CD || before2CD != Pistol2CD) { NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc); - if (pc.IsNonHostModClient()) SendRPCSyncPistolCD(); + if (pc.IsNonHostModdedClient()) SendRPCSyncPistolCD(); } } diff --git a/Roles/Neutral/Glitch.cs b/Roles/Neutral/Glitch.cs index 834912de8..cee3d2a4d 100644 --- a/Roles/Neutral/Glitch.cs +++ b/Roles/Neutral/Glitch.cs @@ -262,7 +262,7 @@ public class Glitch : RoleBase if (MimicCDTimer is > 180 or < 0) MimicCDTimer = 0; - if (player.IsNonHostModClient()) + if (player.IsNonHostModdedClient()) SendRPCSyncTimers(); if (!player.IsModdedClient()) Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player); diff --git a/Roles/Neutral/Vulture.cs b/Roles/Neutral/Vulture.cs index 69a64ce36..0aefc87d5 100644 --- a/Roles/Neutral/Vulture.cs +++ b/Roles/Neutral/Vulture.cs @@ -37,6 +37,7 @@ public class Vulture : RoleBase CustomRoles.Jester ]; + private long LastNotifyTS; private long CooldownFinishTS; private int TotalEaten; private byte VultureId; @@ -58,11 +59,11 @@ public class Vulture : RoleBase CanVent = new BooleanOptionItem(Id + 12, "CanVent", true, TabGroup.NeutralRoles, true) .SetParent(CustomRoleSpawnChances[CustomRoles.Vulture]); - VentCooldown = new FloatOptionItem(Id + 18, "VultureVentCooldown", new(0f, 60f, 0.5f), 15f, TabGroup.NeutralRoles) + VentCooldown = new FloatOptionItem(Id + 18, "VentCooldown", new(0f, 60f, 0.5f), 15f, TabGroup.NeutralRoles) .SetParent(CanVent) .SetValueFormat(OptionFormat.Seconds); - MaxInVentTime = new FloatOptionItem(Id + 19, "VultureMaxInVentTime", new(0f, 300f, 0.5f), 5f, TabGroup.NeutralRoles) + MaxInVentTime = new FloatOptionItem(Id + 19, "MaxInVentTime", new(0f, 300f, 0.5f), 5f, TabGroup.NeutralRoles) .SetParent(CanVent) .SetValueFormat(OptionFormat.Seconds); @@ -96,6 +97,7 @@ public class Vulture : RoleBase TotalEaten = 0; playerId.SetAbilityUseLimit(MaxEaten.GetInt()); CooldownFinishTS = Utils.TimeStamp; + LastNotifyTS = Utils.TimeStamp; VultureId = playerId; } @@ -152,6 +154,7 @@ public class Vulture : RoleBase } pc.RpcRemoveAbilityUse(); + CooldownFinishTS = Utils.TimeStamp + VultureReportCD.GetInt(); Vector2 bodyPos = Object.FindObjectsOfType().First(x => x.ParentId == target.PlayerId).TruePosition; foreach (byte seerId in Main.PlayerStates.Keys) LocateArrow.Remove(seerId, bodyPos); @@ -180,6 +183,16 @@ public class Vulture : RoleBase { CustomRoles role = ChangeRoles[ChangeRole.GetValue()]; pc.RpcSetCustomRole(role); + pc.RpcChangeRoleBasis(role); + return; + } + + long now = Utils.TimeStamp; + + if (now != LastNotifyTS) + { + Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc); + LastNotifyTS = now; } }