diff --git a/EHR.sln.DotSettings b/EHR.sln.DotSettings
index cc0424b77..da2aab289 100644
--- a/EHR.sln.DotSettings
+++ b/EHR.sln.DotSettings
@@ -46,6 +46,8 @@
TS
UI
VN
+ <Policy><Descriptor Staticness="Any" AccessRightKinds="Private, Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="non_field_members_should_be_pascal_case"><ElementKinds><Kind Name="PROPERTY" /><Kind Name="EVENT" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="False" Prefix="Get" Suffix="" Style="AaBb" /></Policy>
True
True
True
diff --git a/GameMode/MoveAndStopManager.cs b/GameMode/MoveAndStop.cs
similarity index 60%
rename from GameMode/MoveAndStopManager.cs
rename to GameMode/MoveAndStop.cs
index 0912fb22a..f886928dc 100644
--- a/GameMode/MoveAndStopManager.cs
+++ b/GameMode/MoveAndStop.cs
@@ -1,60 +1,34 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
-using EHR.AddOns.Common;
using HarmonyLib;
using UnityEngine;
using static EHR.Translator;
namespace EHR
{
- public class Counter(int totalGreenTime, int totalRedTime, long startTimeStamp, char symbol, bool isRed, bool isYellow = false, bool moveAndStop = true)
+ public class Counter(int totalGreenTime, int totalRedTime, long startTimeStamp, char symbol, bool isRed, Func randomRedTimeFunc, Func randomGreenTimeFunc, bool isYellow = false)
{
- public int TotalGreenTime
- {
- get => totalGreenTime;
- set => totalGreenTime = value;
- }
+ private int TotalGreenTime { get; set; } = totalGreenTime;
- public int TotalRedTime
- {
- get => totalRedTime;
- set => totalRedTime = value;
- }
+ private int TotalRedTime { get; set; } = totalRedTime;
- public long StartTimeStamp
- {
- get => startTimeStamp;
- set => startTimeStamp = value;
- }
+ private long StartTimeStamp { get; set; } = startTimeStamp;
- public char Symbol
- {
- get => symbol;
- set => symbol = value;
- }
+ private char Symbol { get; } = symbol;
- public bool IsRed
- {
- get => isRed;
- set => isRed = value;
- }
+ public bool IsRed { get; private set; } = isRed;
- public bool IsYellow
- {
- get => isYellow;
- set => isYellow = value;
- }
+ private Func RandomRedTime { get; } = randomRedTimeFunc;
- public bool MoveAndStop
- {
- get => moveAndStop;
- set => moveAndStop = value;
- }
+ private Func RandomGreenTime { get; } = randomGreenTimeFunc;
+
+ private bool IsYellow { get; set; } = isYellow;
private static int TotalYellowTime => 3;
- public int Timer => (IsRed ? TotalRedTime : IsYellow ? TotalYellowTime : TotalGreenTime) - (int)Math.Round((double)(Utils.TimeStamp - StartTimeStamp));
+ private int Timer => (IsRed ? TotalRedTime : IsYellow ? TotalYellowTime : TotalGreenTime) - (int)Math.Round((double)(Utils.TimeStamp - StartTimeStamp));
public string ColoredTimerString
{
@@ -84,17 +58,14 @@ namespace EHR
break;
// Change from red to green
case true when !IsYellow:
- TotalGreenTime = MoveAndStop ? MoveAndStopManager.RandomGreenTime(Symbol) : Asthmatic.RandomGreenTime();
+ TotalGreenTime = RandomGreenTime(Symbol);
IsRed = false;
break;
- default:
- if (IsYellow && !IsRed) // Change from yellow to red
- {
- TotalRedTime = MoveAndStop ? MoveAndStopManager.RandomRedTime(Symbol) : Asthmatic.RandomRedTime();
- IsYellow = false;
- IsRed = true;
- }
-
+ // Change from yellow to red
+ case false when IsYellow:
+ TotalRedTime = RandomRedTime(Symbol);
+ IsYellow = false;
+ IsRed = true;
break;
}
@@ -103,37 +74,21 @@ namespace EHR
}
}
- internal class MoveAndStopPlayerData(Counter leftCounter, Counter middleCounter, Counter rightCounter, float positionX, float positionY)
+ internal class MoveAndStopPlayerData(Counter leftCounter, Counter middleCounter, Counter rightCounter, float positionX, float positionY, int lives)
{
- public Counter LeftCounter
- {
- get => leftCounter;
- set => leftCounter = value;
- }
+ public Counter LeftCounter { get; } = leftCounter;
- public Counter MiddleCounter
- {
- get => middleCounter;
- set => middleCounter = value;
- }
+ public Counter MiddleCounter { get; } = middleCounter;
- public Counter RightCounter
- {
- get => rightCounter;
- set => rightCounter = value;
- }
+ public Counter RightCounter { get; } = rightCounter;
- public float PositionX
- {
- get => positionX;
- set => positionX = value;
- }
+ public float PositionX { get; set; } = positionX;
- public float PositionY
- {
- get => positionY;
- set => positionY = value;
- }
+ public float PositionY { get; set; } = positionY;
+
+ public int Lives { get; set; } = lives;
+
+ private float LostLifeCooldownTimer { get; set; } = 0f;
public override string ToString()
{
@@ -152,29 +107,51 @@ namespace EHR
LeftCounter.Update();
MiddleCounter.Update();
RightCounter.Update();
+
+ if (LostLifeCooldownTimer > 0f) LostLifeCooldownTimer -= Time.deltaTime;
+ }
+
+ public bool RemoveLife(PlayerControl pc)
+ {
+ if (LostLifeCooldownTimer > 0f) return false;
+
+ Lives--;
+ LostLifeCooldownTimer = 1f;
+
+ if (Lives <= 0)
+ {
+ pc.Suicide();
+ return true;
+ }
+
+ pc.KillFlash();
+ pc.Notify(string.Format(GetString("MoveAndStop_LivesRemainingNotify"), Lives));
+
+ return false;
}
}
- internal class MoveAndStopManager
+ internal static class MoveAndStop
{
private static Dictionary AllPlayerTimers = [];
- private static OptionItem MoveAndStop_GameTime;
- private static OptionItem MoveAndStop_RightCounterGreenMin;
- private static OptionItem MoveAndStop_RightCounterRedMin;
- private static OptionItem MoveAndStop_RightCounterGreenMax;
- private static OptionItem MoveAndStop_RightCounterRedMax;
- private static OptionItem MoveAndStop_LeftCounterGreenMin;
- private static OptionItem MoveAndStop_LeftCounterRedMin;
- private static OptionItem MoveAndStop_LeftCounterGreenMax;
- private static OptionItem MoveAndStop_LeftCounterRedMax;
- private static OptionItem MoveAndStop_MiddleCounterGreenMin;
- private static OptionItem MoveAndStop_MiddleCounterRedMin;
- private static OptionItem MoveAndStop_MiddleCounterGreenMax;
- private static OptionItem MoveAndStop_MiddleCounterRedMax;
- private static OptionItem MoveAndStop_ExtraGreenTimeOnAirhip;
- private static OptionItem MoveAndStop_ExtraGreenTimeOnFungle;
- private static OptionItem MoveAndStop_EnableTutorial;
+ private static OptionItem GameTime;
+ private static OptionItem PlayerLives;
+ private static OptionItem RightCounterGreenMin;
+ private static OptionItem RightCounterRedMin;
+ private static OptionItem RightCounterGreenMax;
+ private static OptionItem RightCounterRedMax;
+ private static OptionItem LeftCounterGreenMin;
+ private static OptionItem LeftCounterRedMin;
+ private static OptionItem LeftCounterGreenMax;
+ private static OptionItem LeftCounterRedMax;
+ private static OptionItem MiddleCounterGreenMin;
+ private static OptionItem MiddleCounterRedMin;
+ private static OptionItem MiddleCounterGreenMax;
+ private static OptionItem MiddleCounterRedMax;
+ private static OptionItem ExtraGreenTimeOnAirhip;
+ private static OptionItem ExtraGreenTimeOnFungle;
+ private static OptionItem EnableTutorial;
public static readonly HashSet HasPlayed = [];
@@ -182,14 +159,12 @@ namespace EHR
public static int RoundTime { get; set; }
- public static bool HasJustStarted => MoveAndStop_GameTime.GetInt() - RoundTime < 30;
-
- public static bool Tutorial => MoveAndStop_EnableTutorial.GetBool();
+ private static bool HasJustStarted => GameTime.GetInt() - RoundTime < 25;
private static int ExtraGreenTime => (MapNames)Main.NormalOptions.MapId switch
{
- MapNames.Airship => MoveAndStop_ExtraGreenTimeOnAirhip.GetInt(),
- MapNames.Fungle => MoveAndStop_ExtraGreenTimeOnFungle.GetInt(),
+ MapNames.Airship => ExtraGreenTimeOnAirhip.GetInt(),
+ MapNames.Fungle => ExtraGreenTimeOnFungle.GetInt(),
_ => 0
};
@@ -202,28 +177,28 @@ namespace EHR
private static int StartingGreenTime(PlayerControl pc)
{
- return (MapNames)Main.NormalOptions.MapId == MapNames.Airship ? Tutorial && !HasPlayed.Contains(pc.FriendCode) ? 70 : 50 : Tutorial && !HasPlayed.Contains(pc.FriendCode) ? 60 : 40;
+ return (MapNames)Main.NormalOptions.MapId == MapNames.Airship ? EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode) ? 70 : 50 : EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode) ? 60 : 40;
}
- public static int RandomRedTime(char direction)
+ private static int RandomRedTime(char direction)
{
return direction switch
{
- '→' => Random.Next(MoveAndStop_RightCounterRedMin.GetInt(), MoveAndStop_RightCounterRedMax.GetInt()),
- '●' => Random.Next(MoveAndStop_MiddleCounterRedMin.GetInt(), MoveAndStop_MiddleCounterRedMax.GetInt()),
- '←' => Random.Next(MoveAndStop_LeftCounterRedMin.GetInt(), MoveAndStop_LeftCounterRedMax.GetInt()),
- _ => throw new NotImplementedException()
+ '➡' => Random.Next(RightCounterRedMin.GetInt(), RightCounterRedMax.GetInt()),
+ '⇅' => Random.Next(MiddleCounterRedMin.GetInt(), MiddleCounterRedMax.GetInt()),
+ '⬅' => Random.Next(LeftCounterRedMin.GetInt(), LeftCounterRedMax.GetInt()),
+ _ => throw new ArgumentException("Invalid symbol representing the direction (RandomRedTime method in MoveAndStop.cs)", nameof(direction))
};
}
- public static int RandomGreenTime(char direction)
+ private static int RandomGreenTime(char direction)
{
return ExtraGreenTime + direction switch
{
- '→' => Random.Next(MoveAndStop_RightCounterGreenMin.GetInt(), MoveAndStop_RightCounterGreenMax.GetInt()),
- '●' => Random.Next(MoveAndStop_MiddleCounterGreenMin.GetInt(), MoveAndStop_MiddleCounterGreenMax.GetInt()),
- '←' => Random.Next(MoveAndStop_LeftCounterGreenMin.GetInt(), MoveAndStop_LeftCounterGreenMax.GetInt()),
- _ => throw new NotImplementedException()
+ '➡' => Random.Next(RightCounterGreenMin.GetInt(), RightCounterGreenMax.GetInt()),
+ '⇅' => Random.Next(MiddleCounterGreenMin.GetInt(), MiddleCounterGreenMax.GetInt()),
+ '⬅' => Random.Next(LeftCounterGreenMin.GetInt(), LeftCounterGreenMax.GetInt()),
+ _ => throw new ArgumentException("Invalid symbol representing the direction (RandomGreenTime method in MoveAndStop.cs)", nameof(direction))
};
}
@@ -258,28 +233,34 @@ namespace EHR
public static void SetupCustomOption()
{
- MoveAndStop_GameTime = new IntegerOptionItem(68_213_001, "FFA_GameTime", new(30, 1200, 10), 900, TabGroup.GameSettings)
+ GameTime = new IntegerOptionItem(68_213_001, "FFA_GameTime", new(30, 1200, 10), 900, TabGroup.GameSettings)
.SetGameMode(CustomGameMode.MoveAndStop)
.SetColor(new Color32(0, 255, 255, byte.MaxValue))
.SetValueFormat(OptionFormat.Seconds)
.SetHeader(true);
- MoveAndStop_RightCounterGreenMin = CreateSetting(68_213_002, "Right", false, true);
- MoveAndStop_RightCounterRedMin = CreateSetting(68_213_003, "Right", true, true);
- MoveAndStop_RightCounterGreenMax = CreateSetting(68_213_004, "Right", false, false);
- MoveAndStop_RightCounterRedMax = CreateSetting(68_213_005, "Right", true, false);
- MoveAndStop_LeftCounterGreenMin = CreateSetting(68_213_006, "Left", false, true);
- MoveAndStop_LeftCounterRedMin = CreateSetting(68_213_007, "Left", true, true);
- MoveAndStop_LeftCounterGreenMax = CreateSetting(68_213_008, "Left", false, false);
- MoveAndStop_LeftCounterRedMax = CreateSetting(68_213_009, "Left", true, false);
- MoveAndStop_MiddleCounterGreenMin = CreateSetting(68_213_010, "Middle", false, true);
- MoveAndStop_MiddleCounterRedMin = CreateSetting(68_213_011, "Middle", true, true);
- MoveAndStop_MiddleCounterGreenMax = CreateSetting(68_213_012, "Middle", false, false);
- MoveAndStop_MiddleCounterRedMax = CreateSetting(68_213_013, "Middle", true, false);
- MoveAndStop_ExtraGreenTimeOnAirhip = CreateExtraTimeSetting(68_213_014, "Airship", 20);
- MoveAndStop_ExtraGreenTimeOnFungle = CreateExtraTimeSetting(68_213_015, "Fungle", 10);
+ PlayerLives = new IntegerOptionItem(68_213_017, "MoveAndStop_PlayerLives", new(1, 10, 1), 3, TabGroup.GameSettings)
+ .SetGameMode(CustomGameMode.MoveAndStop)
+ .SetColor(new Color32(0, 255, 255, byte.MaxValue))
+ .SetValueFormat(OptionFormat.Health)
+ .SetHeader(true);
- MoveAndStop_EnableTutorial = new BooleanOptionItem(68_213_016, "MoveAndStop_EnableTutorial", true, TabGroup.GameSettings)
+ RightCounterGreenMin = CreateSetting(68_213_002, "Right", false, true).SetHeader(true);
+ RightCounterRedMin = CreateSetting(68_213_003, "Right", true, true);
+ RightCounterGreenMax = CreateSetting(68_213_004, "Right", false, false);
+ RightCounterRedMax = CreateSetting(68_213_005, "Right", true, false);
+ LeftCounterGreenMin = CreateSetting(68_213_006, "Left", false, true);
+ LeftCounterRedMin = CreateSetting(68_213_007, "Left", true, true);
+ LeftCounterGreenMax = CreateSetting(68_213_008, "Left", false, false);
+ LeftCounterRedMax = CreateSetting(68_213_009, "Left", true, false);
+ MiddleCounterGreenMin = CreateSetting(68_213_010, "Middle", false, true);
+ MiddleCounterRedMin = CreateSetting(68_213_011, "Middle", true, true);
+ MiddleCounterGreenMax = CreateSetting(68_213_012, "Middle", false, false);
+ MiddleCounterRedMax = CreateSetting(68_213_013, "Middle", true, false);
+ ExtraGreenTimeOnAirhip = CreateExtraTimeSetting(68_213_014, "Airship", 20);
+ ExtraGreenTimeOnFungle = CreateExtraTimeSetting(68_213_015, "Fungle", 10);
+
+ EnableTutorial = new BooleanOptionItem(68_213_016, "MoveAndStop_EnableTutorial", true, TabGroup.GameSettings)
.SetGameMode(CustomGameMode.MoveAndStop)
.SetHeader(true)
.SetColor(new Color32(0, 255, 255, byte.MaxValue));
@@ -292,7 +273,7 @@ namespace EHR
FixedUpdatePatch.LastSuffix = [];
FixedUpdatePatch.Limit = [];
AllPlayerTimers = [];
- RoundTime = MoveAndStop_GameTime.GetInt() + 8;
+ RoundTime = GameTime.GetInt() + 8;
FixedUpdatePatch.DoChecks = false;
LateTask.New(() => { FixedUpdatePatch.DoChecks = true; }, 10f, log: false);
@@ -301,11 +282,14 @@ namespace EHR
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
{
+ int startingGreenTime = StartingGreenTime(pc);
+ Vector2 pos = pc.Pos();
+
AllPlayerTimers.TryAdd(pc.PlayerId, new(
- new(StartingGreenTime(pc), RandomRedTime('←'), now, '←', false),
- new(StartingGreenTime(pc), RandomRedTime('●'), now, '●', false),
- new(StartingGreenTime(pc), RandomRedTime('→'), now, '→', false),
- pc.Pos().x, pc.Pos().y));
+ new(startingGreenTime, RandomRedTime('⬅'), now, '⬅', false, RandomRedTime, RandomGreenTime),
+ new(startingGreenTime, RandomRedTime('⇅'), now, '⇅', false, RandomRedTime, RandomGreenTime),
+ new(startingGreenTime, RandomRedTime('➡'), now, '➡', false, RandomRedTime, RandomGreenTime),
+ pos.x, pos.y, PlayerLives.GetInt()));
float limit;
@@ -324,7 +308,7 @@ namespace EHR
}
}
- public static int GetRankOfScore(byte playerId)
+ public static int GetRankFromScore(byte playerId)
{
try
{
@@ -345,19 +329,23 @@ namespace EHR
var text = timers.ToString();
- if (HasJustStarted && Tutorial && !HasPlayed.Contains(pc.FriendCode)) text += $"\n\n{GetString("MoveAndStop_Tutorial")}";
+ if (HasJustStarted && EnableTutorial.GetBool() && !HasPlayed.Contains(pc.FriendCode))
+ text += $"\n\n{GetString("MoveAndStop_Tutorial")}";
return text;
}
+ public static int GetLivesRemaining(byte id) => AllPlayerTimers.TryGetValue(id, out MoveAndStopPlayerData data) ? data.Lives : 0;
+
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))]
- private class FixedUpdatePatch
+ private static class FixedUpdatePatch
{
public static bool DoChecks;
private static long LastFixedUpdate;
public static Dictionary LastSuffix = [];
public static Dictionary Limit = [];
+ [SuppressMessage("ReSharper", "UnusedMember.Local")]
public static void Postfix(PlayerControl __instance)
{
if (!GameStates.IsInTask || Options.CurrentGameMode != CustomGameMode.MoveAndStop || !__instance.IsAlive() || !AmongUsClient.Instance.AmHost || !DoChecks) return;
@@ -395,9 +383,12 @@ namespace EHR
{
// If: Right counter is red && player moved more than their limit
case true when distanceX > limit:
- pc.Suicide(); // Player suicides
- goto End; // Skip the upcoming checks, the player is already dead
- // Else If: Right counter is yellow or green
+ if (data.RemoveLife(pc)) // Remove a life from the player
+ goto End; // If no lives left, kill them and skip the rest of the code
+
+ // If the player has lives left, update their position
+ goto case false;
+ // Else If: the Right counter is yellow or green
case false:
data.PositionX = currentPosition.x; // Update the player's last position regardless of the distance
break;
@@ -412,8 +403,8 @@ namespace EHR
{
// The distance is negative here because it's the opposite direction as right
case true when distanceX < -limit:
- pc.Suicide();
- goto End;
+ if (data.RemoveLife(pc)) goto End;
+ goto case false;
case false:
data.PositionX = currentPosition.x;
break;
@@ -429,8 +420,8 @@ namespace EHR
{
// The player dies if either they moved up OR down too far
case true when distanceY > limit || distanceY < -limit:
- pc.Suicide();
- goto End;
+ if (data.RemoveLife(pc)) goto End;
+ goto case false;
case false:
data.PositionY = currentPosition.y;
break;
@@ -445,7 +436,8 @@ namespace EHR
string suffix = GetSuffixText(pc);
- if (!LastSuffix.TryGetValue(pc.PlayerId, out string beforeSuffix) || beforeSuffix != suffix) Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
+ if (!LastSuffix.TryGetValue(pc.PlayerId, out string beforeSuffix) || beforeSuffix != suffix)
+ Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
LastSuffix[pc.PlayerId] = suffix;
}
diff --git a/Modules/OptionHolder.cs b/Modules/OptionHolder.cs
index b8ddde276..3d5a38cfd 100644
--- a/Modules/OptionHolder.cs
+++ b/Modules/OptionHolder.cs
@@ -808,44 +808,47 @@ namespace EHR
Achievements.LoadAllData();
#if DEBUG
- // Used for generating the table of roles for the README
- try
- {
- var sb = new StringBuilder();
- var grouped = Enum.GetValues().GroupBy(x =>
+ // Used for generating the table of roles for the README
+ try
{
- if (x is CustomRoles.GM or CustomRoles.Philantropist or CustomRoles.Konan or CustomRoles.NotAssigned or CustomRoles.LovingCrewmate or CustomRoles.LovingImpostor or CustomRoles.Convict || x.IsForOtherGameMode() || x.IsVanilla() || x.ToString().Contains("EHR") || HnSManager.AllHnSRoles.Contains(x)) return 4;
- if (x.IsAdditionRole()) return 3;
- if (x.IsImpostor() || x.IsMadmate()) return 0;
- if (x.IsNeutral()) return 1;
- if (x.IsCrewmate()) return 2;
- return 4;
- }).ToDictionary(x => x.Key, x => x.ToArray());
- var max = grouped.Max(x => x.Value.Length);
- for (int i = 0; i < max; i++)
- {
- var cr = grouped[2].ElementAtOrDefault(i);
- var crew = Translator.GetString(cr.ToString());
- var ir = grouped[0].ElementAtOrDefault(i);
- var imp = Translator.GetString(ir.ToString());
- if (ir == default) imp = string.Empty;
- var nr = grouped[1].ElementAtOrDefault(i);
- var neu = Translator.GetString(nr.ToString());
- if (nr == default) neu = string.Empty;
- var a = grouped[3].ElementAtOrDefault(i);
- var add = Translator.GetString(a.ToString());
- if (a == default) add = string.Empty;
- sb.AppendLine($"| {crew,17} | {imp,17} | {neu,17} | {add,17} |");
- }
+ var sb = new StringBuilder();
- const string path = "./roles.txt";
- if (!File.Exists(path)) File.Create(path).Close();
- File.WriteAllText(path, sb.ToString());
- }
- catch (Exception e)
- {
- Utils.ThrowException(e);
- }
+ var grouped = Enum.GetValues().GroupBy(x =>
+ {
+ if (x is CustomRoles.GM or CustomRoles.Philantropist or CustomRoles.Konan or CustomRoles.NotAssigned or CustomRoles.LovingCrewmate or CustomRoles.LovingImpostor or CustomRoles.Convict || x.IsForOtherGameMode() || x.IsVanilla() || x.ToString().Contains("EHR") || HnSManager.AllHnSRoles.Contains(x)) return 4;
+ if (x.IsAdditionRole()) return 3;
+ if (x.IsImpostor() || x.IsMadmate()) return 0;
+ if (x.IsNeutral()) return 1;
+ if (x.IsCrewmate()) return 2;
+ return 4;
+ }).ToDictionary(x => x.Key, x => x.ToArray());
+
+ var max = grouped.Max(x => x.Value.Length);
+
+ for (int i = 0; i < max; i++)
+ {
+ var cr = grouped[2].ElementAtOrDefault(i);
+ var crew = Translator.GetString(cr.ToString());
+ var ir = grouped[0].ElementAtOrDefault(i);
+ var imp = Translator.GetString(ir.ToString());
+ if (ir == default) imp = string.Empty;
+ var nr = grouped[1].ElementAtOrDefault(i);
+ var neu = Translator.GetString(nr.ToString());
+ if (nr == default) neu = string.Empty;
+ var a = grouped[3].ElementAtOrDefault(i);
+ var add = Translator.GetString(a.ToString());
+ if (a == default) add = string.Empty;
+ sb.AppendLine($"| {crew,17} | {imp,17} | {neu,17} | {add,17} |");
+ }
+
+ const string path = "./roles.txt";
+ if (!File.Exists(path)) File.Create(path).Close();
+ File.WriteAllText(path, sb.ToString());
+ }
+ catch (Exception e)
+ {
+ Utils.ThrowException(e);
+ }
#endif
}
@@ -1337,7 +1340,7 @@ namespace EHR
// FFA
FFAManager.SetupCustomOption();
// Move And Stop
- MoveAndStopManager.SetupCustomOption();
+ MoveAndStop.SetupCustomOption();
// Hot Potato
HotPotatoManager.SetupCustomOption();
// Speedrun
diff --git a/Modules/Utils.cs b/Modules/Utils.cs
index af4a87a0e..1852147ee 100644
--- a/Modules/Utils.cs
+++ b/Modules/Utils.cs
@@ -25,7 +25,6 @@ using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using InnerNet;
using Newtonsoft.Json;
-using TMPro;
using UnityEngine;
using static EHR.Translator;
@@ -42,7 +41,7 @@ List of symbols that work in game
6- random: ‰ § ¶ © ™ ¥ $ ¢ € ƒ £ Æ
other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢ ╖ ╕ ╣ ║ ╗ ╝ ╜ ╛ ┐ └ ┴ ┬ ─ ┼ ╞ ╟ ╚ ╔ ╩ ╦ ╠ ═ ╬ ╧ ╨ ╤ ╥ ╙ ╘ ╒ ╓ ╫ ╪ ┘ ┌ Θ ∩ ¿
-*/
+ */
public static class Utils
{
@@ -1052,9 +1051,7 @@ other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢
}
if (pc.Is(CustomRoles.Damocles)) ProgressText.Append($" {Damocles.GetProgressText(playerId)}");
-
if (pc.Is(CustomRoles.Stressed)) ProgressText.Append($" {Stressed.GetProgressText(playerId)}");
-
if (pc.Is(CustomRoles.Circumvent)) ProgressText.Append($" {Circumvent.GetProgressText(playerId)}");
if (pc.Is(CustomRoles.Taskcounter))
@@ -1121,7 +1118,7 @@ other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢
Color TextColor = comms ? Color.gray : NormalColor;
string Completed = comms ? "?" : $"{taskState.CompletedTasksCount}";
- return ColorString(TextColor, $" {(moveAndStop ? "" : string.Empty)}{Completed}/{taskState.AllTasksCount}{(moveAndStop ? "" : string.Empty)}");
+ return ColorString(TextColor, $" {(moveAndStop ? "" : string.Empty)}{Completed}/{taskState.AllTasksCount}{(moveAndStop ? $" <#ffffff>({MoveAndStop.GetLivesRemaining(playerId)})" : string.Empty)}");
}
catch
{
@@ -1471,7 +1468,7 @@ other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢
break;
case CustomGameMode.MoveAndStop:
List<(int, byte)> list3 = [];
- list3.AddRange(cloneRoles.Select(id => (MoveAndStopManager.GetRankOfScore(id), id)));
+ list3.AddRange(cloneRoles.Select(id => (MoveAndStop.GetRankFromScore(id), id)));
list3.Sort();
@@ -2163,7 +2160,7 @@ other: ∟ ⌠ ⌡ ╬ ╨ ▓ ▒ ░ « » █ ▄ ▌▀▐│ ┤ ╡ ╢
SelfSuffix.Append(SoloKombatManager.GetDisplayHealth(seer));
break;
case CustomGameMode.MoveAndStop:
- SelfSuffix.Append(MoveAndStopManager.GetSuffixText(seer));
+ SelfSuffix.Append(MoveAndStop.GetSuffixText(seer));
break;
case CustomGameMode.HotPotato when seer.IsAlive():
SelfSuffix.Append(HotPotatoManager.GetSuffixText(seer.PlayerId));
diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs
index f702c9a2c..bf5fb6425 100644
--- a/Patches/CheckGameEndPatch.cs
+++ b/Patches/CheckGameEndPatch.cs
@@ -710,10 +710,10 @@ namespace EHR
{
reason = GameOverReason.ImpostorByKill;
- if (MoveAndStopManager.RoundTime <= 0)
+ if (MoveAndStop.RoundTime <= 0)
{
PlayerControl[] apc = Main.AllPlayerControls;
- SetWinner(Main.GM.Value && apc.Length == 1 ? PlayerControl.LocalPlayer : apc.Where(x => !x.Is(CustomRoles.GM) && x != null).OrderBy(x => MoveAndStopManager.GetRankOfScore(x.PlayerId)).ThenByDescending(x => x.IsAlive()).First());
+ SetWinner(Main.GM.Value && apc.Length == 1 ? PlayerControl.LocalPlayer : apc.Where(x => !x.Is(CustomRoles.GM) && x != null).OrderBy(x => MoveAndStop.GetRankFromScore(x.PlayerId)).ThenByDescending(x => x.IsAlive()).First());
return true;
}
@@ -731,7 +731,7 @@ namespace EHR
SetWinner(aapc[0]);
return true;
case 0:
- MoveAndStopManager.RoundTime = 0;
+ MoveAndStop.RoundTime = 0;
Logger.Warn("No players alive. Force ending the game", "MoveAndStop");
return false;
}
diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs
index e50996193..2c195e297 100644
--- a/Patches/HudPatch.cs
+++ b/Patches/HudPatch.cs
@@ -244,7 +244,7 @@ namespace EHR.Patches
{
CustomGameMode.SoloKombat => SoloKombatManager.GetHudText(),
CustomGameMode.FFA when player.IsHost() => FFAManager.GetHudText(),
- CustomGameMode.MoveAndStop when player.IsHost() => MoveAndStopManager.HUDText,
+ CustomGameMode.MoveAndStop when player.IsHost() => MoveAndStop.HUDText,
CustomGameMode.HotPotato when player.IsHost() => HotPotatoManager.GetSuffixText(player.PlayerId),
CustomGameMode.HideAndSeek when player.IsHost() => HnSManager.GetSuffixText(player, player, true),
CustomGameMode.NaturalDisasters => NaturalDisasters.SuffixText(),
@@ -738,7 +738,7 @@ namespace EHR.Patches
}
List<(int, byte)> list3 = [];
- foreach (byte id in Main.PlayerStates.Keys) list3.Add((MoveAndStopManager.GetRankOfScore(id), id));
+ foreach (byte id in Main.PlayerStates.Keys) list3.Add((MoveAndStop.GetRankFromScore(id), id));
list3.Sort();
list3 = [.. list3.OrderBy(x => !Utils.GetPlayerById(x.Item2).IsAlive())];
@@ -746,7 +746,7 @@ namespace EHR.Patches
foreach ((int, byte) id in list3.Where(x => SummaryText3.ContainsKey(x.Item2)).ToArray())
{
bool alive = Utils.GetPlayerById(id.Item2).IsAlive();
- finalText += $"{(!alive ? "<#777777>" : string.Empty)}\r\n{(alive ? SummaryText3[id.Item2] : SummaryText3[id.Item2].RemoveHtmlTags())}{(!alive ? $" <#ff0000>{GetString("Dead")}" : string.Empty)}";
+ finalText += $"{(!alive ? "<#777777>" : string.Empty)}\r\n{(alive ? SummaryText3[id.Item2].Replace("", "") : SummaryText3[id.Item2].RemoveHtmlTags())}{(!alive ? $" <#ff0000>{GetString("Dead")}" : string.Empty)}";
}
break;
diff --git a/Patches/OnGameStartedPatch.cs b/Patches/OnGameStartedPatch.cs
index 9eef42541..d92b51a5c 100644
--- a/Patches/OnGameStartedPatch.cs
+++ b/Patches/OnGameStartedPatch.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using AmongUs.Data;
using AmongUs.GameOptions;
using Assets.CoreScripts;
@@ -340,7 +339,7 @@ namespace EHR
{
SoloKombatManager.Init();
FFAManager.Init();
- MoveAndStopManager.Init();
+ MoveAndStop.Init();
HotPotatoManager.Init();
HnSManager.Init();
SpeedrunManager.Init();
diff --git a/Patches/OutroPatch.cs b/Patches/OutroPatch.cs
index 83da06ed1..26d37114c 100644
--- a/Patches/OutroPatch.cs
+++ b/Patches/OutroPatch.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using EHR.AddOns.GhostRoles;
using EHR.Crewmate;
using EHR.Modules;
@@ -116,7 +115,7 @@ namespace EHR
switch (Options.CurrentGameMode)
{
case CustomGameMode.MoveAndStop:
- Main.AllPlayerControls.Do(x => MoveAndStopManager.HasPlayed.Add(x.FriendCode));
+ Main.AllPlayerControls.Do(x => MoveAndStop.HasPlayed.Add(x.FriendCode));
break;
case CustomGameMode.RoomRush:
Main.AllPlayerControls.Do(x => RoomRush.HasPlayedFriendCodes.Add(x.FriendCode));
@@ -436,7 +435,7 @@ namespace EHR
case CustomGameMode.MoveAndStop:
{
List<(int, byte)> list = [];
- list.AddRange(cloneRoles.Select(id => (MoveAndStopManager.GetRankOfScore(id), id)));
+ list.AddRange(cloneRoles.Select(id => (MoveAndStop.GetRankFromScore(id), id)));
list.Sort();
foreach ((int, byte) id in list.Where(x => EndGamePatch.SummaryText.ContainsKey(x.Item2))) sb.Append('\n').Append(EndGamePatch.SummaryText[id.Item2]);
diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs
index a66026431..25e2ce2bf 100644
--- a/Patches/PlayerControlPatch.cs
+++ b/Patches/PlayerControlPatch.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
using AmongUs.GameOptions;
using EHR.AddOns.Common;
using EHR.AddOns.Crewmate;
@@ -1280,10 +1279,7 @@ namespace EHR
HudManager.Instance.KillButton.SetTarget(closest);
}
}
- catch
- {
-
- }
+ catch { }
if (localPlayer)
{
@@ -1521,7 +1517,11 @@ namespace EHR
progressText = $"\n{progressText}";
}
- if (Main.VisibleTasksCount) RoleText.text += progressText;
+ if (Main.VisibleTasksCount)
+ {
+ if (Options.CurrentGameMode == CustomGameMode.MoveAndStop) RoleText.text = RoleText.text.Insert(0, progressText);
+ else RoleText.text += progressText;
+ }
PlayerControl seer = PlayerControl.LocalPlayer;
PlayerControl target = __instance;
@@ -1707,7 +1707,7 @@ namespace EHR
Suffix.Append(FFAManager.GetPlayerArrow(seer, target));
break;
case CustomGameMode.MoveAndStop when self:
- Suffix.Append(MoveAndStopManager.GetSuffixText(seer));
+ Suffix.Append(MoveAndStop.GetSuffixText(seer));
break;
case CustomGameMode.Speedrun when self:
Suffix.Append(SpeedrunManager.GetSuffixText(seer));
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json
index c2d87f146..d7b301227 100644
--- a/Resources/Lang/en_US.json
+++ b/Resources/Lang/en_US.json
@@ -4290,8 +4290,10 @@
"MoveAndStop_MiddleCounterRedMax": "Middle Counter Maximum Red Time",
"MoveAndStop_ExtraGreenTimeOnAirship": "Extra Green Time On AirShip",
"MoveAndStop_ExtraGreenTimeOnFungle": "Extra Green Time On Fungle",
+ "MoveAndStop_PlayerLives": "Player Lives",
"MoveAndStop_EnableTutorial": "Enable Tutorial",
- "MoveAndStop_Tutorial": "<#ffffff>Stop on red lights\\nOnly move in directions where you see a green arrow\\n● indicates up and down\\nThe timers indicate when the color changes\\nYellow means the light will turn red, so stop moving\\nOrange means the light will turn green, but do not move yet\\nFinish your tasks to win",
+ "MoveAndStop_Tutorial": "<#ffffff>Stop on red lights\\nOnly move in directions where you see a green arrow\\nThe timers indicate when the color changes\\nYellow means the light will turn red, so stop moving\\nOrange means the light will turn green, but do not move yet\\nFinish your tasks to win",
+ "MoveAndStop_LivesRemainingNotify": "<#ffff00>⚠ YOU LOST A LIFE | <#ffff44>{0} REMAINING ⚠",
"Tasker": "Tasker",
"TaskerInfo": "FINISH TASKS FIRST TO WIN",
"TaskerInfoLong": "FINISH TASKS FIRST TO WIN",
diff --git a/Resources/Lang/fr_FR.json b/Resources/Lang/fr_FR.json
index c53010dde..e4055e101 100644
--- a/Resources/Lang/fr_FR.json
+++ b/Resources/Lang/fr_FR.json
@@ -1,5 +1,5 @@
{
- "LanguageID": "0",
+ "LanguageID": "8",
"TextBelowVersionText": "",
"HostText": "EHR",
"IconColor": "#902efd",
diff --git a/Roles/AddOns/Common/Asthmatic.cs b/Roles/AddOns/Common/Asthmatic.cs
index df47ee4a5..a78c4ae73 100644
--- a/Roles/AddOns/Common/Asthmatic.cs
+++ b/Roles/AddOns/Common/Asthmatic.cs
@@ -39,15 +39,8 @@ namespace EHR.AddOns.Common
.SetValueFormat(OptionFormat.Seconds);
}
- public static int RandomRedTime()
- {
- return IRandom.Instance.Next(MinRedTime, MaxRedTime);
- }
-
- public static int RandomGreenTime()
- {
- return IRandom.Instance.Next(MinGreenTime, MaxGreenTime);
- }
+ private static int RandomRedTime(char _) => IRandom.Instance.Next(MinRedTime, MaxRedTime);
+ private static int RandomGreenTime(char _) => IRandom.Instance.Next(MinGreenTime, MaxGreenTime);
public static void Init()
{
@@ -70,7 +63,7 @@ namespace EHR.AddOns.Common
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
if (pc.Is(CustomRoles.Asthmatic))
- Timers[pc.PlayerId] = new(30, r.Next(MinRedTime, MaxRedTime), now, '●', false, moveAndStop: false);
+ Timers[pc.PlayerId] = new(30, r.Next(MinRedTime, MaxRedTime), now, '●', false, RandomRedTime, RandomGreenTime);
}, 8f, "Add Asthmatic Timers");
}