Try to fix Loop Wanted issue (#632)

* Add new Gamemode and fix SettingMenu button order issue

* back path

* Fix

* Try to ban Crewmate Kill

* Rename LoopWanted to DoomTag & fix double suffix

* Rename

* Fix gurge said
This commit is contained in:
Christina authored and GitHub committed 2026-06-27 14:57:26 +02:00
1 parent 0cde09fcb6
commit 6a4d5cb4d5
22 files changed
+139 -143

No files matched your search

@@ -8,7 +8,7 @@ using static EHR.Translator;
namespace EHR.Gamemodes;
internal static class LoopWanted
internal static class DoomTag
{
private static Dictionary<byte, byte> TargetMap = [];
private static Dictionary<byte, long> LowerVisionList = [];
@@ -23,47 +23,47 @@ internal static class LoopWanted
private static OptionItem CarnivalSpeedMultiplier;
private static OptionItem ShowTargetArrow;
private static readonly string[] PunishmentModeOptions = ["LoopWanted.PunishSuicide", "LoopWanted.PunishLowerVision"];
private static readonly string[] PunishmentModeOptions = ["DoomTag.PunishSuicide", "DoomTag.PunishLowerVision"];
public static void SetupCustomOption()
{
var id = 69_226_001;
Color color = Utils.GetRoleColor(CustomRoles.LoopHunter);
const CustomGameMode gameMode = CustomGameMode.LoopWanted;
Color color = Utils.GetRoleColor(CustomRoles.Tagger);
const CustomGameMode gameMode = CustomGameMode.DoomTag;
const TabGroup tab = TabGroup.GameSettings;
BaseKillCooldown = new FloatOptionItem(id++, "LoopWanted.BaseKillCooldown", new(2.5f, 60f, 2.5f), 15f, tab)
BaseKillCooldown = new FloatOptionItem(id++, "DoomTag.BaseKillCooldown", new(2.5f, 60f, 2.5f), 15f, tab)
.SetHeader(true)
.SetGameMode(gameMode)
.SetColor(color)
.SetValueFormat(OptionFormat.Seconds);
PunishmentMode = new StringOptionItem(id++, "LoopWanted.PunishmentMode", PunishmentModeOptions, 0, tab)
PunishmentMode = new StringOptionItem(id++, "DoomTag.PunishmentMode", PunishmentModeOptions, 0, tab)
.SetGameMode(gameMode)
.SetColor(color);
LowerVisionMultiplier = new FloatOptionItem(id++, "LoopWanted.LowerVisionMultiplier", new(0f, 10f, 0.5f), 0.5f, tab)
LowerVisionMultiplier = new FloatOptionItem(id++, "DoomTag.LowerVisionMultiplier", new(0f, 10f, 0.5f), 0.5f, tab)
.SetParent(PunishmentMode)
.SetGameMode(gameMode)
.SetColor(color)
.SetValueFormat(OptionFormat.Multiplier);
CarnivalPlayerCount = new IntegerOptionItem(id++, "LoopWanted.CarnivalPlayerCount", new(1, 127, 1), 3, tab)
CarnivalPlayerCount = new IntegerOptionItem(id++, "DoomTag.CarnivalPlayerCount", new(1, 127, 1), 3, tab)
.SetGameMode(gameMode)
.SetColor(color)
.SetValueFormat(OptionFormat.Players);
CarnivalKillCooldown = new FloatOptionItem(id++, "LoopWanted.CarnivalKillCooldown", new(2.5f, 60f, 2.5f), 5f, tab)
CarnivalKillCooldown = new FloatOptionItem(id++, "DoomTag.CarnivalKillCooldown", new(2.5f, 60f, 2.5f), 5f, tab)
.SetGameMode(gameMode)
.SetColor(color)
.SetValueFormat(OptionFormat.Seconds);
CarnivalSpeedMultiplier = new FloatOptionItem(id++, "LoopWanted.CarnivalSpeedMultiplier", new(0.25f, 10f, 0.25f), 2.0f, tab)
CarnivalSpeedMultiplier = new FloatOptionItem(id++, "DoomTag.CarnivalSpeedMultiplier", new(0.25f, 10f, 0.25f), 2.0f, tab)
.SetGameMode(gameMode)
.SetColor(color)
.SetValueFormat(OptionFormat.Multiplier);
ShowTargetArrow = new BooleanOptionItem(id, "LoopWanted.ShowTargetArrow", false, tab)
ShowTargetArrow = new BooleanOptionItem(id, "DoomTag.ShowTargetArrow", false, tab)
.SetGameMode(gameMode)
.SetColor(color);
}
@@ -75,16 +75,16 @@ internal static class LoopWanted
LowerVisionList = [];
CarnivalMode = false;
if (Options.CurrentGameMode != CustomGameMode.LoopWanted) return;
if (Options.CurrentGameMode != CustomGameMode.DoomTag) return;
DefaultSpeed = Main.RealOptionsData.GetFloat(FloatOptionNames.PlayerSpeedMod);
Utils.SendRPC(CustomRPC.LoopWantedSync, 1, false);
Utils.SendRPC(CustomRPC.DoomTagSync, 1, false);
}
public static void OnGameStart()
{
if (Options.CurrentGameMode != CustomGameMode.LoopWanted) return;
if (Options.CurrentGameMode != CustomGameMode.DoomTag) return;
AssignTargets();
}
@@ -102,7 +102,7 @@ internal static class LoopWanted
if (playerIds.Count < 2)
{
Logger.Warn("Not enough players for LoopWanted", "LoopWanted");
Logger.Warn("Not enough players for DoomTag", "DoomTag");
return;
}
@@ -115,7 +115,7 @@ internal static class LoopWanted
TargetMap.Remove(TargetMap.GetKeyByValue(targetId));
TargetMap[hunterId] = targetId;
if (ShowTargetArrow.GetBool()) TargetArrow.Add(hunterId, targetId);
Logger.Info($"{hunterId.ColoredPlayerName()} 2 targets 2 {targetId.ColoredPlayerName()}", "LoopWanted");
Logger.Info($"{hunterId.ColoredPlayerName()} 2 targets 2 {targetId.ColoredPlayerName()}", "DoomTag");
}
SyncTargetMapRPC();
@@ -138,7 +138,7 @@ internal static class LoopWanted
if (expectedTarget == targetId)
{
Logger.Info($"{killer.GetRealName()} correctly killed their target {target.GetRealName()}", "LoopWanted");
Logger.Info($"{killer.GetRealName()} correctly killed their target {target.GetRealName()}", "DoomTag");
byte nextTarget = GetTarget(targetId);
@@ -151,7 +151,7 @@ internal static class LoopWanted
TargetMap.Remove(TargetMap.GetKeyByValue(nextTarget));
TargetMap[killerId] = nextTarget;
if (ShowTargetArrow.GetBool()) TargetArrow.Add(killerId, nextTarget);
Logger.Info($"{killer.GetRealName()}'s new target is {nextTarget.ColoredPlayerName()}", "LoopWanted");
Logger.Info($"{killer.GetRealName()}'s new target is {nextTarget.ColoredPlayerName()}", "DoomTag");
}
else
{
@@ -165,13 +165,13 @@ internal static class LoopWanted
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: killer);
SyncTargetMapRPC();
Utils.SendRPC(CustomRPC.LoopWantedSync, 1, CarnivalMode);
Utils.SendRPC(CustomRPC.DoomTagSync, 1, CarnivalMode);
killer.Kill(target);
}
else
{
Logger.Info($"{killer.GetRealName()} killed wrong target {target.GetRealName()} (expected: {expectedTarget.ColoredPlayerName()})", "LoopWanted");
Logger.Info($"{killer.GetRealName()} killed wrong target {target.GetRealName()} (expected: {expectedTarget.ColoredPlayerName()})", "DoomTag");
if (PunishmentMode.GetInt() == 0)
killer.Kill(target);
@@ -194,21 +194,21 @@ internal static class LoopWanted
switch (PunishmentMode.GetInt())
{
case 0:
Logger.Info($"{killer.GetRealName()} is committing suicide for wrong kill", "LoopWanted");
killer.Notify(GetString("LoopWanted.WrongKillSuicide"));
Logger.Info($"{killer.GetRealName()} is committing suicide for wrong kill", "DoomTag");
killer.Notify(GetString("DoomTag.WrongKillSuicide"));
LateTask.New(() =>
{
if (!killer || !killer.IsAlive() || GameStates.IsEnded) return;
killer.Suicide();
HandleDeadPlayer(killer.PlayerId);
}, 0.5f, "LoopWanted Suicide Punishment");
}, 0.5f, "DoomTag Suicide Punishment");
break;
case 1:
float visionMultiplier = LowerVisionMultiplier.GetFloat();
LowerVisionList[killer.PlayerId] = Utils.TimeStamp;
killer.MarkDirtySettings();
killer.Notify(string.Format(GetString("LoopWanted.WrongKillLowerVision"), visionMultiplier));
killer.Notify(string.Format(GetString("DoomTag.WrongKillLowerVision"), visionMultiplier));
break;
}
}
@@ -232,11 +232,8 @@ internal static class LoopWanted
TargetMap[hunterId] = nextTarget;
if (ShowTargetArrow.GetBool()) TargetArrow.Add(hunterId, nextTarget);
LateTask.New(() =>
{
PlayerControl hunter = Utils.GetPlayerById(hunterId);
if (hunter) Utils.NotifyRoles(SpecifySeer: hunter, SpecifyTarget: hunter);
}, 0.2f);
PlayerControl hunter = Utils.GetPlayerById(hunterId);
if (hunter) Utils.NotifyRoles(SpecifySeer: hunter, SpecifyTarget: hunter);
}
else if (hunterId != byte.MaxValue)
{
@@ -256,7 +253,7 @@ internal static class LoopWanted
if (!CarnivalMode && aliveCount <= threshold && aliveCount > 1)
{
CarnivalMode = true;
Utils.SendRPC(CustomRPC.LoopWantedSync, 1, true);
Utils.SendRPC(CustomRPC.DoomTagSync, 1, true);
foreach (PlayerControl pc in Main.CachedAlivePlayerControls())
{
@@ -264,12 +261,12 @@ internal static class LoopWanted
Main.AllPlayerKillCooldown[pc.PlayerId] = CarnivalKillCooldown.GetFloat();
if (!pc.AmOwner) pc.ReactorFlash();
pc.MarkDirtySettings();
pc.Notify(GetString("LoopWanted.CarnivalModeActivated"));
pc.Notify(GetString("DoomTag.CarnivalModeActivated"));
}
SoundManager.Instance.PlaySound(HudManager.Instance.LobbyTimerExtensionUI.lobbyTimerPopUpSound, false);
Utils.FlashColor(new(1f, 0.5f, 0f, 0.4f), 1.4f);
Logger.Info($"Carnival Mode activated! {aliveCount} players remaining.", "LoopWanted");
Logger.Info($"Carnival Mode activated! {aliveCount} players remaining.", "DoomTag");
}
}
@@ -286,11 +283,11 @@ internal static class LoopWanted
case 1:
PlayerControl winner = alivePlayers[0];
CustomWinnerHolder.WinnerIds = [winner.PlayerId];
Logger.Info($"LoopWanted Winner: {winner.GetRealName()}", "LoopWanted");
Logger.Info($"DoomTag Winner: {winner.GetRealName()}", "DoomTag");
return true;
case 0:
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.None);
Logger.Info("No players alive, force ending the game", "LoopWanted");
Logger.Info("No players alive, force ending the game", "DoomTag");
return true;
default:
return false;
@@ -301,7 +298,7 @@ internal static class LoopWanted
public static string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false)
{
if (seer.PlayerId != target.PlayerId || GameStates.IsMeeting || (seer.IsModdedClient() && !hud)) return string.Empty;
if (seer.PlayerId != target.PlayerId || GameStates.IsMeeting) return string.Empty;
byte targetId = GetTarget(seer.PlayerId);
if (targetId == byte.MaxValue) return string.Empty;
@@ -309,7 +306,7 @@ internal static class LoopWanted
Suffix.Clear();
Suffix.Append("<#D9BAA5>");
Suffix.Append(hud ? GetString("LoopWanted.CurrentTarget") : GetString("Target"));
Suffix.Append(hud ? GetString("DoomTag.CurrentTarget") : GetString("Target"));
Suffix.Append(": <b>");
Suffix.Append(targetId.ColoredPlayerName());
Suffix.Append("</b>");
@@ -325,7 +322,7 @@ internal static class LoopWanted
if (CarnivalMode)
{
Suffix.Append("\n<#ff6600>");
Suffix.Append(GetString("LoopWanted.CarnivalModeHUD"));
Suffix.Append(GetString("DoomTag.CarnivalModeHUD"));
Suffix.Append("</color>");
}
@@ -336,8 +333,8 @@ internal static class LoopWanted
{
if (!AmongUsClient.Instance.AmHost) return;
var writer = Utils.CreateRPC(CustomRPC.LoopWantedSync);
writer.WritePacked(2);
var writer = Utils.CreateRPC(CustomRPC.DoomTagSync);
writer.Write(2);
writer.Write(TargetMap.Count);
foreach (var kvp in TargetMap)
{
@@ -391,7 +388,7 @@ internal static class LoopWanted
public static void Postfix()
{
if (!Main.IntroDestroyed || !GameStates.IsInTask || ExileController.Instance || Options.CurrentGameMode != CustomGameMode.LoopWanted || !AmongUsClient.Instance.AmHost) return;
if (!Main.IntroDestroyed || !GameStates.IsInTask || ExileController.Instance || Options.CurrentGameMode != CustomGameMode.DoomTag || !AmongUsClient.Instance.AmHost) return;
long now = Utils.TimeStamp;
if (IntroCutsceneDestroyPatch.IntroDestroyTS + 10 > now || LastFixedUpdate == now) return;