diff --git a/GameMode/RoomRush.cs b/GameMode/RoomRush.cs index b2a547e18..e3f6486b0 100644 --- a/GameMode/RoomRush.cs +++ b/GameMode/RoomRush.cs @@ -15,6 +15,8 @@ namespace EHR private static OptionItem GlobalTimeMultiplier; private static OptionItem TimeWhenFirstPlayerEntersRoom; private static OptionItem VentTimes; + private static OptionItem DisplayRoomName; + private static OptionItem DisplayArrowToRoom; public static readonly HashSet HasPlayedFriendCodes = []; @@ -125,10 +127,18 @@ namespace EHR .SetGameMode(gameMode) .SetValueFormat(OptionFormat.Seconds); - VentTimes = new IntegerOptionItem(id, "RR_VentTimes", new(0, 90, 1), 1, TabGroup.GameSettings) + VentTimes = new IntegerOptionItem(id++, "RR_VentTimes", new(0, 90, 1), 1, TabGroup.GameSettings) .SetColor(color) .SetGameMode(gameMode) .SetValueFormat(OptionFormat.Times); + + DisplayRoomName = new BooleanOptionItem(id++, "RR_DisplayRoomName", true, TabGroup.GameSettings) + .SetColor(color) + .SetGameMode(gameMode); + + DisplayArrowToRoom = new BooleanOptionItem(id, "RR_DisplayArrowToRoom", false, TabGroup.GameSettings) + .SetColor(color) + .SetGameMode(gameMode); } public static int GetSurvivalTime(byte id) @@ -257,6 +267,8 @@ namespace EHR TimeLeft = (int)Math.Round(time * GlobalTimeMultiplier.GetFloat()); Logger.Info($"Starting a new round - Goal = from: {Translator.GetString(previous.ToString())}, to: {Translator.GetString(RoomGoal.ToString())} - Time: {TimeLeft}", "RoomRush"); + Main.AllPlayerControls.Do(x => LocateArrow.RemoveAllTarget(x.PlayerId)); + if (DisplayArrowToRoom.GetBool()) Main.AllAlivePlayerControls.Do(x => LocateArrow.Add(x.PlayerId, goalPos)); Utils.NotifyRoles(); } @@ -269,10 +281,13 @@ namespace EHR var sb = new StringBuilder(); var done = DonePlayers.Contains(seer.PlayerId); var color = done ? Color.green : Color.yellow; - sb.AppendLine(Utils.ColorString(color, Translator.GetString(RoomGoal.ToString()))); + if (DisplayRoomName.GetBool()) sb.AppendLine(Utils.ColorString(color, Translator.GetString(RoomGoal.ToString()))); + if (DisplayArrowToRoom.GetBool()) sb.AppendLine(Utils.ColorString(color, LocateArrow.GetArrows(seer))); color = done ? Color.white : Color.yellow; sb.AppendLine(Utils.ColorString(color, TimeLeft.ToString())); + if (VentTimes.GetInt() == 0) return sb.ToString(); + sb.AppendLine(); int vents = VentLimit.GetValueOrDefault(seer.PlayerId); diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs index b74ef0dbc..dead9aca9 100644 --- a/Modules/OptionHolder.cs +++ b/Modules/OptionHolder.cs @@ -2220,13 +2220,13 @@ public static class Options CustomRoleCounts.Add(role, countOption); } - public static void SetupAdtRoleOptions(int id, CustomRoles role, CustomGameMode customGameMode = CustomGameMode.Standard, bool canSetNum = false, TabGroup tab = TabGroup.Addons, bool canSetChance = true, bool teamSpawnOptions = false) + public static void SetupAdtRoleOptions(int id, CustomRoles role, CustomGameMode customGameMode = CustomGameMode.Standard, bool canSetNum = false, TabGroup tab = TabGroup.Addons, bool canSetChance = true, bool teamSpawnOptions = false, bool allowZeroCount = false) { var spawnOption = new StringOptionItem(id, role.ToString(), RatesZeroOne, 0, tab).SetColor(Utils.GetRoleColor(role)) .SetHeader(true) .SetGameMode(customGameMode) as StringOptionItem; - var countOption = new IntegerOptionItem(id + 1, "Maximum", new(1, canSetNum ? 15 : 1, 1), 1, tab) + var countOption = new IntegerOptionItem(id + 1, "Maximum", new(allowZeroCount ? 0 : 1, canSetNum ? 15 : 1, 1), 1, tab) .SetParent(spawnOption) .SetValueFormat(OptionFormat.Players) .SetHidden(!canSetNum) diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index f9031c71e..00e0fdf9e 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -2101,12 +2101,6 @@ static class PlayerControlCompleteTaskPatch NameColorManager.Add(impostor.PlayerId, __instance.PlayerId, "#ff1919"); NotifyRoles(SpecifySeer: __instance, ForceLoop: true); } - - if (isTaskFinish && __instance.GetCustomRole() is CustomRoles.Doctor or CustomRoles.Sunnyboy or CustomRoles.SpeedBooster) - { - // Execute CustomSyncAllSettings at the end of the task only for matches with sunnyboy, speed booster, or doctor. - MarkEveryoneDirtySettings(); - } } } diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 4f826142b..1aa40d64f 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -4133,6 +4133,8 @@ "RR_GlobalTimeMultiplier": "Global Time Multiplier (for adjusting the difficulty)", "RR_TimeWhenTwoPlayersEntersRoom": "When the first two players enter the correct room, the time limit is set to", "RR_VentTimes": "Times each player can vent", + "RR_DisplayRoomName": "Display the Name of the Room to Get to", + "RR_DisplayArrowToRoom": "Display an Arrow to the Room to Get to", "RR_Tutorial_1": "<#ffab1b>Tutorial\\nHello! Welcome to Room Rush!\\n", "RR_Tutorial_2": "The goal of this gamemode is to get to the room you see under your name as fast as possible.", "RR_Tutorial_3": "When the first two players enter the correct room, the time limit is set to a few seconds.", diff --git a/Roles/AddOns/Impostor/Madmate.cs b/Roles/AddOns/Impostor/Madmate.cs index 8b2797a09..7680dce2c 100644 --- a/Roles/AddOns/Impostor/Madmate.cs +++ b/Roles/AddOns/Impostor/Madmate.cs @@ -8,7 +8,7 @@ namespace EHR.AddOns.Impostor public void SetupCustomOption() { - SetupAdtRoleOptions(15800, CustomRoles.Madmate, canSetNum: true, canSetChance: false); + SetupAdtRoleOptions(15800, CustomRoles.Madmate, canSetNum: true, canSetChance: false, allowZeroCount: true); MadmateSpawnMode = new StringOptionItem(15810, "MadmateSpawnMode", MadmateSpawnModeStrings, 0, TabGroup.Addons) .SetParent(CustomRoleSpawnChances[CustomRoles.Madmate]); MadmateCountMode = new StringOptionItem(15811, "MadmateCountMode", MadmateCountModeStrings, 0, TabGroup.Addons) diff --git a/Roles/Crewmate/Bane.cs b/Roles/Crewmate/Bane.cs index 5aeba7476..38c37168d 100644 --- a/Roles/Crewmate/Bane.cs +++ b/Roles/Crewmate/Bane.cs @@ -21,10 +21,11 @@ namespace EHR.Crewmate public static void OnKilled(PlayerControl killer) { - if (killer == null) return; - if (!killer.GetCustomRole().IsImpostor()) return; + if (killer == null || killer.Is(CustomRoles.Bloodlust)) return; - killer.RpcSetCustomRole(killer.Is(RoleTypes.Shapeshifter) ? CustomRoles.ShapeshifterEHR : killer.IsImpostor() ? CustomRoles.ImpostorEHR : CustomRoles.Amnesiac); + var erasedRole = killer.IsImpostor() ? CustomRoles.ImpostorEHR : killer.IsCrewmate() ? CustomRoles.CrewmateEHR : CustomRoles.Amnesiac; + killer.RpcSetCustomRole(erasedRole); + killer.RpcChangeRoleBasis(erasedRole); } } } \ No newline at end of file diff --git a/Roles/Crewmate/NiceHacker.cs b/Roles/Crewmate/NiceHacker.cs index b1d01e6aa..f21ffe3b3 100644 --- a/Roles/Crewmate/NiceHacker.cs +++ b/Roles/Crewmate/NiceHacker.cs @@ -157,12 +157,12 @@ namespace EHR.Crewmate } else { - opts.Mode = MapOptions.Modes.Normal; + opts.Mode = pc.IsMadmate() ? MapOptions.Modes.Sabotage : MapOptions.Modes.Normal; pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); } } - public static void MapCountdown(PlayerControl pc, MapBehaviour map, MapOptions opts, int seconds) + private static void MapCountdown(PlayerControl pc, MapBehaviour map, MapOptions opts, int seconds) { if (!map.IsOpen) { @@ -173,7 +173,7 @@ namespace EHR.Crewmate { map.Close(); pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); - opts.Mode = MapOptions.Modes.Normal; + opts.Mode = pc.IsMadmate() ? MapOptions.Modes.Sabotage : MapOptions.Modes.Normal; return; } diff --git a/Roles/Crewmate/Randomizer.cs b/Roles/Crewmate/Randomizer.cs index 2917bd769..300455efe 100644 --- a/Roles/Crewmate/Randomizer.cs +++ b/Roles/Crewmate/Randomizer.cs @@ -381,7 +381,6 @@ namespace EHR.Crewmate } catch (Exception ex) { - Logger.CurrentMethod(); Logger.Exception(ex, "Randomizer"); } } @@ -439,7 +438,7 @@ namespace EHR.Crewmate public static int MaximumEffectDuration; private static bool Notify; - public static Dictionary> CurrentEffects = []; + private static Dictionary> CurrentEffects = []; public static Dictionary AllPlayerDefaultSpeed = []; public static Dictionary Rifts = []; @@ -452,7 +451,6 @@ namespace EHR.Crewmate public static bool Exists; - byte RandomizerId; private static int Id => 643490; private static string RNGString => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Randomizer), Translator.GetString("RNGHasSpoken")); @@ -516,7 +514,6 @@ namespace EHR.Crewmate Exists = true; PlayerIdList.Add(playerId); AllPlayerDefaultSpeed = Main.AllPlayerSpeed.ToDictionary(x => x.Key, x => x.Value); - RandomizerId = playerId; } public static PlayerControl PickRandomPlayer() @@ -570,7 +567,6 @@ namespace EHR.Crewmate } catch (Exception e) { - Logger.CurrentMethod(); Logger.Exception(e, "Randomizer"); } } @@ -589,7 +585,6 @@ namespace EHR.Crewmate } catch (Exception e) { - Logger.CurrentMethod(); Logger.Exception(e, "Randomizer"); } } @@ -608,7 +603,6 @@ namespace EHR.Crewmate } catch (Exception e) { - Logger.CurrentMethod(); Logger.Exception(e, "Randomizer"); } } @@ -620,7 +614,7 @@ namespace EHR.Crewmate LastDeathEffect = Utils.TimeStamp; Rifts.Clear(); Bombs.Clear(); - Utils.SendRPC(CustomRPC.SyncRoleData, PlayerIdList.First(), 3); + Utils.SendRPC(CustomRPC.SyncRoleData, PlayerIdList[0], 3); foreach (var pc in Main.AllPlayerControls) { RevertSpeedChangesForPlayer(pc, false); @@ -639,7 +633,7 @@ namespace EHR.Crewmate { try { - if (lowLoad || !Exists || !GameStates.IsInTask || Bombs.Count == 0) return; + if (lowLoad || !Exists || !GameStates.IsInTask || Bombs.Count == 0 || Main.HasJustStarted) return; var now = Utils.TimeStamp; var randomizer = Utils.GetPlayerById(PlayerIdList.FirstOrDefault()); @@ -661,7 +655,6 @@ namespace EHR.Crewmate } catch (Exception ex) { - Logger.CurrentMethod(); Logger.Exception(ex, "Randomizer"); } } @@ -694,7 +687,7 @@ namespace EHR.Crewmate { try { - if (!IsEnable || !GameStates.IsInTask) return; + if (!IsEnable || !GameStates.IsInTask || Main.HasJustStarted) return; TimeSinceLastMeeting += Time.fixedDeltaTime; @@ -711,7 +704,6 @@ namespace EHR.Crewmate } catch (Exception ex) { - Logger.CurrentMethod(); Logger.Exception(ex, "Randomizer"); } } @@ -720,7 +712,7 @@ namespace EHR.Crewmate { try { - if (!IsEnable || !GameStates.IsInTask) return; + if (!IsEnable || !GameStates.IsInTask || Main.HasJustStarted) return; var now = Utils.TimeStamp; if (LastTP[pc.PlayerId] + 5 > now) return; @@ -746,7 +738,6 @@ namespace EHR.Crewmate } catch (Exception ex) { - Logger.CurrentMethod(); Logger.Exception(ex, "Randomizer"); } } @@ -755,13 +746,13 @@ namespace EHR.Crewmate { try { - if (!Exists || pc == null || !pc.IsAlive() || !GameStates.IsInTask) return; + if (!Exists || pc == null || !pc.IsAlive() || !GameStates.IsInTask || Main.HasJustStarted) return; if (CurrentEffects.TryGetValue(pc.PlayerId, out var effects)) { var now = Utils.TimeStamp; - foreach (var item in effects) + foreach (var item in effects.ToArray()) { if (item.Value.StartTimeStamp + item.Value.Duration < now) { @@ -782,7 +773,6 @@ namespace EHR.Crewmate } catch (Exception ex) { - Logger.CurrentMethod(); Logger.Exception(ex, "Randomizer"); } } diff --git a/Roles/Crewmate/Spy.cs b/Roles/Crewmate/Spy.cs index d0e0d9e6c..86b6af704 100644 --- a/Roles/Crewmate/Spy.cs +++ b/Roles/Crewmate/Spy.cs @@ -11,7 +11,6 @@ namespace EHR.Crewmate { private const int Id = 640400; private static List PlayerIdList = []; - private static bool Change; public static Dictionary SpyRedNameList = []; private static OptionItem SpyRedNameDur; @@ -42,14 +41,13 @@ namespace EHR.Crewmate { PlayerIdList = []; SpyRedNameList = []; - Change = false; } public override void Add(byte playerId) { + LastUpdate = TimeStamp; PlayerIdList.Add(playerId); playerId.SetAbilityUseLimit(UseLimitOpt.GetInt()); - Change = false; } private static void SendRPC(int operate, byte id = byte.MaxValue, bool changeColor = false) @@ -84,7 +82,7 @@ namespace EHR.Crewmate return; case 3: SpyRedNameList.Remove(reader.ReadByte()); - Change = reader.ReadBoolean(); + reader.ReadBoolean(); return; } } @@ -101,25 +99,25 @@ namespace EHR.Crewmate return false; } + private long LastUpdate; + public override void OnFixedUpdate(PlayerControl pc) { if (pc == null || !pc.Is(CustomRoles.Spy) || SpyRedNameList.Count == 0) return; + long now = TimeStamp; + if (now == LastUpdate) return; + LastUpdate = now; + foreach (var x in SpyRedNameList) { - if (x.Value + SpyRedNameDur.GetInt() < TimeStamp || !GameStates.IsInTask) + if (x.Value + SpyRedNameDur.GetInt() < now || !GameStates.IsInTask) { SpyRedNameList.Remove(x.Key); - Change = true; SendRPC(3, id: x.Key, changeColor: true); + NotifyRoles(SpecifySeer: pc, SpecifyTarget: x.Key.GetPlayer()); } } - - if (Change && GameStates.IsInTask) - { - NotifyRoles(SpecifySeer: pc); - Change = false; - } } } } \ No newline at end of file diff --git a/Roles/Impostor/Eraser.cs b/Roles/Impostor/Eraser.cs index 569e2edd7..ecbc90865 100644 --- a/Roles/Impostor/Eraser.cs +++ b/Roles/Impostor/Eraser.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using AmongUs.GameOptions; using static EHR.Translator; namespace EHR.Impostor; @@ -126,15 +128,17 @@ internal class Eraser : RoleBase public override void AfterMeetingTasks() { - foreach (byte pc in PlayerToErase) + foreach (byte id in PlayerToErase) { - var player = Utils.GetPlayerById(pc); - if (player == null) continue; - player.RpcSetCustomRole(player.GetCustomRole().GetErasedRole()); - player.Notify(GetString("LostRoleByEraser")); - Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} lost their role", "Eraser"); - player.MarkDirtySettings(); - ErasedPlayers.Add(pc); + var pc = Utils.GetPlayerById(id); + if (pc == null || !pc.IsAlive() || pc.Is(CustomRoles.Bloodlust)) continue; + var erasedRole = pc.GetRoleTypes() is RoleTypes.Crewmate or RoleTypes.Engineer or RoleTypes.Noisemaker or RoleTypes.Scientist or RoleTypes.Tracker ? CustomRoles.CrewmateEHR : CustomRoles.ImpostorEHR; + pc.RpcSetCustomRole(erasedRole); + pc.RpcChangeRoleBasis(erasedRole); + pc.Notify(GetString("LostRoleByEraser")); + Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} lost their role", "Eraser"); + pc.MarkDirtySettings(); + ErasedPlayers.Add(id); } PlayerToErase = []; diff --git a/Roles/Neutral/Necromancer.cs b/Roles/Neutral/Necromancer.cs index 1006f6cff..6ba8e1d1e 100644 --- a/Roles/Neutral/Necromancer.cs +++ b/Roles/Neutral/Necromancer.cs @@ -74,7 +74,7 @@ namespace EHR.Neutral public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { - if (Deathknight.DeathknightId == byte.MaxValue) + if (Deathknight.DeathknightId == byte.MaxValue && !target.Is(CustomRoles.Loyal) && !target.IsConverted()) { target.RpcChangeRoleBasis(CustomRoles.Deathknight); target.RpcSetCustomRole(CustomRoles.Deathknight); @@ -136,7 +136,7 @@ namespace EHR.Neutral return player.Is(CustomRoles.Necromancer) && target.Is(CustomRoles.Deathknight); } - public static bool CanBeUndead(PlayerControl pc) => pc != null && !pc.Is(CustomRoles.Deathknight) && !pc.Is(CustomRoles.Necromancer) && !pc.Is(CustomRoles.Undead) && !pc.Is(CustomRoles.Loyal); + public static bool CanBeUndead(PlayerControl pc) => pc != null && !pc.Is(CustomRoles.Deathknight) && !pc.Is(CustomRoles.Necromancer) && !pc.Is(CustomRoles.Undead) && !pc.Is(CustomRoles.Loyal) && !pc.IsConverted(); } internal class Deathknight : RoleBase