This commit is contained in:
Gurge44 committed 2025-02-26 13:22:37 +01:00
1 parent 580879524b
commit 2ae4a775bf
11 files changed
+76 -55

No files matched your search

+16 -16
View File
@@ -7,30 +7,30 @@ namespace EHR;
internal class LateTask
{
private static readonly List<LateTask> Tasks = [];
private readonly Action action;
private readonly string callerData;
private readonly bool log;
private readonly string name;
private float timer;
private readonly Action Action;
private readonly string CallerData;
private readonly bool LOG;
private readonly string Name;
private float Timer;
private LateTask(Action action, float time, string name, bool log, string callerData)
{
this.action = action;
timer = time;
this.name = name;
this.log = log;
this.callerData = callerData;
this.Action = action;
Timer = time;
this.Name = name;
this.LOG = log;
this.CallerData = callerData;
Tasks.Add(this);
if (log && name is not "" and not "No Name Task") Logger.Info("\"" + name + "\" is created", "LateTask");
}
private bool Run(float deltaTime)
{
timer -= deltaTime;
Timer -= deltaTime;
if (timer <= 0)
if (Timer <= 0)
{
action();
Action();
return true;
}
@@ -57,15 +57,15 @@ internal class LateTask
{
if (task.Run(deltaTime))
{
if (task.name is not "" and not "No Name Task" && task.log)
Logger.Info($"\"{task.name}\" is finished", "LateTask");
if (task.Name is not "" and not "No Name Task" && task.LOG)
Logger.Info($"\"{task.Name}\" is finished", "LateTask");
Tasks.Remove(task);
}
}
catch (Exception ex)
{
Logger.Error($"{ex.GetType()}: {ex.Message} in \"{task.name}\" ({task.callerData})\n{ex.StackTrace}", "LateTask.Error", false);
Logger.Error($"{ex.GetType()}: {ex.Message} in \"{task.Name}\" ({task.CallerData})\n{ex.StackTrace}", "LateTask.Error", false);
Tasks.Remove(task);
}
}
+4
View File
@@ -194,6 +194,7 @@ public static class Options
public static OptionItem DisableWhisperCommand;
public static OptionItem DisableSpectateCommand;
public static OptionItem Disable8ballCommand;
public static OptionItem DisableReactorOnSkeldAndMira;
public static OptionItem DisableReactorOnPolus;
@@ -1889,6 +1890,9 @@ public static class Options
DisableSpectateCommand = new BooleanOptionItem(22812, "DisableSpectateCommand", false, TabGroup.GameSettings)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
Disable8ballCommand = new BooleanOptionItem(22813, "Disable8ballCommand", false, TabGroup.GameSettings)
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
LoadingPercentage = 75;
DisableDevices = new BooleanOptionItem(22900, "DisableDevices", false, TabGroup.GameSettings)
+13 -7
View File
@@ -194,7 +194,7 @@ internal static class ChatCommands
new(["addtag", "добавитьтег", "添加标签", "adicionartag"], "{id} {color} {tag}", GetString("CommandDescription.AddTag"), Command.UsageLevels.Host, Command.UsageTimes.InLobby, AddTagCommand, true, false, [GetString("CommandArgs.AddTag.Id"), GetString("CommandArgs.AddTag.Color"), GetString("CommandArgs.AddTag.Tag")]),
new(["deletetag", "удалитьтег", "删除标签"], "{id}", GetString("CommandDescription.DeleteTag"), Command.UsageLevels.Host, Command.UsageTimes.InLobby, DeleteTagCommand, true, false, [GetString("CommandArgs.DeleteTag.Id")]),
new(["daybreak", "db", "дейбрейк", "破晓"], "", GetString("CommandDescription.DayBreak"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, DayBreakCommand, true, true),
// Commands with action handled elsewhere
new(["shoot", "guess", "bet", "bt", "st", "угадать", "бт", "猜测", "赌", "adivinhar"], "{id} {role}", GetString("CommandDescription.Guess"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, (_, _, _) => { }, true, false, [GetString("CommandArgs.Guess.Id"), GetString("CommandArgs.Guess.Role")]),
new(["tl", "sp", "jj", "trial", "суд", "засудить", "审判", "判", "julgar"], "{id}", GetString("CommandDescription.Trial"), Command.UsageLevels.Everyone, Command.UsageTimes.InMeeting, (_, _, _) => { }, true, false, [GetString("CommandArgs.Trial.Id")]),
@@ -370,17 +370,17 @@ internal static class ChatCommands
RequestCommandProcessingFromHost(nameof(DayBreakCommand), text);
return;
}
if (!player.IsAlive() || Main.PlayerStates[player.PlayerId].Role is not Starspawn sp || sp.HasUsedDayBreak) return;
if (!player.IsLocalPlayer()) ChatManager.SendPreviousMessagesToAll();
Starspawn.IsDayBreak = true;
sp.HasUsedDayBreak = true;
Utils.SendMessage("\n", title: string.Format(GetString("StarspawnUsedDayBreak"), CustomRoles.Starspawn.ToColoredString()));
}
private static void AddTagCommand(PlayerControl player, string text, string[] args)
{
if (!AmongUsClient.Instance.AmHost)
@@ -420,6 +420,12 @@ internal static class ChatCommands
private static void EightBallCommand(PlayerControl player, string text, string[] args)
{
if (Options.Disable8ballCommand.GetBool())
{
Utils.SendMessage("\n", player.PlayerId, GetString("EightBallDisabled"));
return;
}
if (!AmongUsClient.Instance.AmHost)
{
RequestCommandProcessingFromHost(nameof(EightBallCommand), text);
@@ -640,7 +646,7 @@ internal static class ChatCommands
private static void DeathNoteCommand(PlayerControl player, string text, string[] args)
{
if (Starspawn.IsDayBreak) return;
if (!AmongUsClient.Instance.AmHost)
{
RequestCommandProcessingFromHost(nameof(DeathNoteCommand), text);
+1 -1
View File
@@ -952,8 +952,8 @@ internal static class GameEndChecker
reason = GameOverReason.ImpostorByKill;
if (Options.DisableTaskWin.GetBool() || TaskState.InitialTotalTasks == 0) return false;
if ((GameData.Instance.TotalTasks == 0 && GameData.Instance.CompletedTasks == 0) || !Main.PlayerStates.Values.Any(x => x.TaskState.HasTasks)) return false;
if (Options.DisableTaskWinIfAllCrewsAreDead.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.Is(CustomRoleTypes.Crewmate))) return false;
if (Options.DisableTaskWinIfAllCrewsAreConverted.GetBool() && Main.AllAlivePlayerControls.Where(x => x.Is(Team.Crewmate) && x.GetRoleTypes() is RoleTypes.Crewmate or RoleTypes.Engineer or RoleTypes.Scientist or RoleTypes.Noisemaker or RoleTypes.Tracker or RoleTypes.CrewmateGhost or RoleTypes.GuardianAngel).All(x => x.IsConverted())) return false;
if (GameData.Instance.TotalTasks <= GameData.Instance.CompletedTasks)
+16 -1
View File
@@ -153,7 +153,7 @@ internal static class Crowded
}
[HarmonyPatch(typeof(ServerManager), nameof(ServerManager.SetRegion))]
public static class ServerManager_SetRegion
public static class ServerManagerSetRegion
{
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public static void Postfix()
@@ -244,6 +244,21 @@ internal static class Crowded
}
}
[HarmonyPatch(typeof(CreateOptionsPicker), nameof(CreateOptionsPicker.Refresh))]
public static class CreateOptionsPickerRefresh
{
public static bool Prefix(CreateOptionsPicker __instance)
{
IGameOptions targetOptions = __instance.GetTargetOptions();
__instance.UpdateImpostorsButtons(targetOptions.NumImpostors);
__instance.UpdateMaxPlayersButtons(targetOptions);
__instance.UpdateLanguageButton((uint)targetOptions.Keywords);
__instance.MapMenu.UpdateMapButtons(targetOptions.MapId);
__instance.GameModeText.text = DestroyableSingleton<TranslationController>.Instance.GetString(GameModesHelpers.ModeToName[GameOptionsManager.Instance.CurrentGameOptions.GameMode]);
return false;
}
}
[HarmonyPatch(typeof(GameOptionsData), nameof(GameOptionsData.AreInvalid))]
public static class InvalidOptionsPatches
{
+2 -2
View File
@@ -369,7 +369,7 @@ internal static class ShipStatusSpawnPlayerPatch
Vector2 direction = Vector2.up.Rotate((player.PlayerId - 1) * (360f / numPlayers));
Vector2 position = __instance.MeetingSpawnCenter + (direction * __instance.SpawnRadius) + new Vector2(0.0f, 0.3636f);
player.TP(position, true, false);
LateTask.New(() => player.TP(position, true, false), 1.5f, log: false);
return false;
}
}
@@ -392,7 +392,7 @@ internal static class PolusShipStatusSpawnPlayerPatch
? __instance.MeetingSpawnCenter2 + (Vector2.right * (num2 - num1) * 0.6f)
: __instance.MeetingSpawnCenter + (Vector2.right * num2 * 0.6f);
player.TP(position, true, false);
LateTask.New(() => player.TP(position, true, false), 1.5f, log: false);
return false;
}
}
+10 -6
View File
@@ -2521,8 +2521,10 @@
"JailTalkTitle": "JAIL",
"DisableWhisperCommand": "Disable /whisper command",
"DisableSpectateCommand": "Disable /spectate command",
"Disable8ballCommand": "Disable /8ball command",
"SpectateDisabled": "<#ff0000>X</color> The /spectate command is disabled in this lobby.",
"WhisperDisabled": "<#ff0000>X</color> The /whisper command is disabled in this lobby.",
"EightBallDisabled": "<#ff0000>X</color> The /8ball command is disabled in this lobby.",
"Anagram.CorrectGuess": "<#00ffa5>✓</color> {0} has guessed the anagram correctly (<b>{1}</b>)!",
"Anagram": "The scrambled word is <b>{0}</b>! Guess the original word!",
"AnagramTitle": "<#888888>➡ ANAGRAM ⬅</color>",
@@ -3262,25 +3264,25 @@
"CanWinAfterDeath": "Can win after death",
"Starspawn": "Starspawn",
"StarspawnInfo": "Isolate Players & Call Daybreak",
"StarspawnInfoLong": "(Impostors):\\nAs the Starspawn, you can isolate players by using your kill button on them. Only evil players can interact with isolated players.\\nOnce in a game, you can call daybreak in a meeting by typing <b>/daybreak</b> in the chat. This will prevent ALL meeting abilities from being used in that meeting. This includes guessing, judging, and all other meeting abilities that are role-specific.",
"StarspawnInfoLong": "(Impostors):\\nAs the Starspawn, you can isolate players by using your kill button on them. Only evil players can interact with isolated players.\\nOnce in a game, you can call daybreak in a meeting by typing <b>/daybreak</b> in the chat. This will prevent ALL meeting abilities from being used in that meeting. This includes guessing, judging, and all other meeting abilities that are role-specific.\\n\\nYou win if crewmates lose.",
"StarspawnUsedDayBreak": "<#ff0000>⚠</color> <#ffff00>Daybreak has been called by the {0}!</color> <#ff0000>⚠</color>\\nThis means that NO meeting abilities can be used in this meeting anymore.",
"Spirit": "Spirit",
"SpiritInfo": "Place Candles to Swap Interactions",
"SpiritInfoLong": "(Neutrals):\\nAs the Spirit, you can place candles on players to swap interactions between them using your shapeshift menu. If an interaction were to happen on one of the players, it will instead happen to the other. This includes normal kills. If one of them die or disconnect, the swap will break and you gain back a candle, which you can reuse. Swapped players know they are swapped with someone, but not who.",
"SpiritInfoLong": "(Neutrals):\\nAs the Spirit, you can place candles on players to swap interactions between them using your shapeshift menu. If an interaction were to happen on one of the players, it will instead happen to the other. This includes normal kills. If one of them die or disconnect, the swap will break and you gain back a candle, which you can reuse. Swapped players know they are swapped with someone, but not who.\\n\\nYou win if crewmates lose.",
"SpiritTarget": "<#ffff44>You were swapped with someone by the {0}!</color>",
"Seamstress": "Seamstress",
"SeamstressInfo": "Sew Players Together",
"SeamstressInfoLong": "(Neutrals):\\nAs the Seamstress, you can sew 2 players together using your shapeshift menu. If an interaction happens on one of the players, it will happen to both of them. If one of them die or disconnect, or a meeting is called, the sew will break. Sewed players know they are sewed together with someone, but not who.",
"SeamstressInfoLong": "(Neutrals):\\nAs the Seamstress, you can sew 2 players together using your shapeshift menu. If an interaction happens on one of the players, it will happen to both of them. If one of them die or disconnect, or a meeting is called, the sew will break. Sewed players know they are sewed together with someone, but not who.\\n\\nYou win if crewmates lose.",
"SewedBySeamstress": "<#ffff44>You were sewed together with someone by the {0}!</color>",
"Magistrate": "Magistrate",
"MagistrateInfo": "Call Court to Coordinate With Evils",
"MagistrateInfoLong": "(Neutrals):\\nAs the Magistrate, you can call court once in the game. The next meeting will look like this:\\n-Everyone will be gray\\n-You will have the name COURT, others will have the name JURY\\n-You will have extra votes",
"MagistrateInfoLong": "(Neutrals):\\nAs the Magistrate, you can call court once in the game. The next meeting will look like this:\\n-Everyone will be gray\\n-You will have the name COURT, others will have the name JURY\\n-You will have extra votes\\n\\nYou win if crewmates lose.",
"Magistrate.ExtraVotes": "Extra Votes",
"Magistrate.CourtName": "COURT",
"Magistrate.JuryName": "JURY",
"Auditor": "Auditor",
"AuditorInfo": "Check Players",
"AuditorInfoLong": "(Neutrals):\\nAs the Auditor, you can check players by using your kill button on them. You will see their role and:\\n- Steal 1 or all ability uses from them (depending on the settings) if you're in auditing mode\\n- Lower their vision temporarily if you're in smokebombing mode",
"AuditorInfoLong": "(Neutrals):\\nAs the Auditor, you can check players by using your kill button on them. You will see their role and:\\n- Steal 1 or all ability uses from them (depending on the settings) if you're in auditing mode\\n- Lower their vision temporarily if you're in smokebombing mode\\n\\nYou win if crewmates lose.",
"Auditor.LoweredVision": "Lowered Vision",
"Auditor.LoweredVisionDuration": "Lowered Vision Duration",
"Auditor.StealAllChargesInsteadOfOne": "Steal All Charges Instead Of 1",
@@ -3669,6 +3671,7 @@
"SchrodingersCatInfo": "Get Attacked to Get a Role",
"SchrodingersCatInfoLong": "(Neutrals):\\nAs Schrödinger's Cat, if you get attacked, you turn into the same role as your killer. If you don't get attacked, you lose, or you can win with crewmates, depending on the settings.",
"SchrodingersCat.WinsWithCrewIfNotAttacked": "Wins with crewmates if not attacked",
"SchrodingersCat.StealsExactImpostorRole": "Steals the exact impostor role instead of <#ff1919>Renegade</color>",
"SchrodingersCat.Notify.KillerRecruited": "You have recruited the {1}! {0} now has the same role as you.",
"SchrodingersCat.Notify.RecruitedByKiller": "You have been recruited by the {1}! You now have the same role as {0}.",
"Socialite": "Socialite",
@@ -5163,6 +5166,7 @@
"AgitaterCanGetBombed": "<color=#F4A460>Agitator</color> can get bomb",
"AgitaterAutoReportBait": "<color=#F4A460>Agitator</color> Auto Report Bait",
"Cleansed": "Cleansed",
"CleansedInfo": "Your add-ons were cleansed",
"Prefix.Cleansed": "Cleansed",
"Cleansed-": "Cleansed ",
"MaxCleanserUses": "Max cleanses",
@@ -5170,7 +5174,7 @@
"CleanserTitle": "CLEANSER",
"CleanserRemoveSelf": "You can not cleanse yourself",
"CleanserRemovedRole": "<b>{0}</b> has been cleansed. All their Addons will be removed after the meeting.",
"LostAddonByCleanser": "All your Addons were removed by the cleanser",
"LostAddonByCleanser": "All your Addons were removed by the {0}",
"Cleanser": "Cleanser",
"CleanserInfo": "Erase All Addons of your vote target",
"CleanserInfoLong": "(Crewmates):\\nCleanser can vote for any target at the meeting to erase the target's Add-ons, and the erasure will take effect after the meeting ends. Depending on the settings cleansed player may never get add on in future",
+1 -1
View File
@@ -127,6 +127,6 @@ public class Cleanser : RoleBase
Logger.Info($"Removed all the add ons of {targetPc.GetNameWithRole().RemoveHtmlTags()}", "Cleanser");
CleanserTarget = byte.MaxValue;
targetPc.MarkDirtySettings();
targetPc.Notify(GetString("LostAddonByCleanser"));
targetPc.Notify(string.Format(GetString("LostAddonByCleanser"), CustomRoles.Cleanser.ToColoredString()));
}
}
+7 -17
View File
@@ -12,7 +12,6 @@ public class Amnesiac : RoleBase
{
private const int Id = 35000;
private static List<Amnesiac> Instances = [];
public static HashSet<byte> WasAmnesiac = [];
private static OptionItem RememberCooldown;
private static OptionItem CanRememberCrewPower;
@@ -74,7 +73,6 @@ public class Amnesiac : RoleBase
public override void Init()
{
Instances = [];
WasAmnesiac = [];
}
public override void Add(byte playerId)
@@ -174,25 +172,20 @@ public class Amnesiac : RoleBase
switch (target.GetTeam())
{
case Team.Impostor:
RememberedRole = CustomRoles.Refugee;
RememberedRole = SingleRoles.Contains(targetRole) ? CustomRoles.Refugee : targetRole;
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("RememberedImpostor"));
break;
case Team.Crewmate:
RememberedRole = CanRememberCrewPower.GetBool() || targetRole.GetCrewmateRoleCategory() != RoleOptionType.Crewmate_Power ? targetRole : CustomRoles.Sheriff;
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("RememberedCrewmate"));
break;
case Team.Neutral when !SingleRoles.Contains(targetRole):
RememberedRole = targetRole;
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("RememberedNeutralKiller"));
break;
case Team.Neutral:
if (!SingleRoles.Contains(targetRole))
{
RememberedRole = targetRole;
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString("RememberedNeutralKiller"));
}
else
{
RememberedRole = AmnesiacIncompatibleNeutralMode[IncompatibleNeutralMode.GetValue()];
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString($"Remembered{RememberedRole}"));
}
RememberedRole = AmnesiacIncompatibleNeutralMode[IncompatibleNeutralMode.GetValue()];
amneNotifyString = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Amnesiac), GetString($"Remembered{RememberedRole}"));
break;
case Team.Coven:
RememberedRole = targetRole == CustomRoles.CovenLeader ? Enum.GetValues<CustomRoles>().FindFirst(x => x.IsCoven() && !x.RoleExist(true), out var unusedCovenRole) ? unusedCovenRole : null : targetRole;
@@ -225,9 +218,6 @@ public class Amnesiac : RoleBase
if (role.IsRecruitingRole()) amnesiac.SetAbilityUseLimit(0);
if (role.GetRoleTypes() == RoleTypes.Engineer)
WasAmnesiac.Add(amnesiac.PlayerId);
if (!amnesiac.IsLocalPlayer()) return;
switch (role)
+5 -2
View File
@@ -5,6 +5,7 @@ internal class SchrodingersCat : RoleBase
public static bool On;
public static OptionItem WinsWithCrewIfNotAttacked;
public static OptionItem StealsExactImpostorRole;
public override bool IsEnable => On;
public override void SetupCustomOption()
@@ -14,6 +15,9 @@ internal class SchrodingersCat : RoleBase
WinsWithCrewIfNotAttacked = new BooleanOptionItem(id + 2, "SchrodingersCat.WinsWithCrewIfNotAttacked", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SchrodingersCat]);
StealsExactImpostorRole = new BooleanOptionItem(id + 3, "SchrodingersCat.StealsExactImpostorRole", true, TabGroup.NeutralRoles)
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SchrodingersCat]);
}
public override void Add(byte playerId)
@@ -29,10 +33,9 @@ internal class SchrodingersCat : RoleBase
public override bool OnCheckMurderAsTarget(PlayerControl killer, PlayerControl target)
{
CustomRoles killerRole = killer.GetCustomRole();
if (killerRole.IsImpostor() || killerRole.IsMadmate()) killerRole = CustomRoles.Refugee;
if (!StealsExactImpostorRole.GetBool() && (killerRole.IsImpostor() || killerRole.IsMadmate())) killerRole = CustomRoles.Refugee;
if (killerRole == CustomRoles.Jackal) killerRole = CustomRoles.Sidekick;
if (Options.SingleRoles.Contains(killerRole)) killerRole = CustomRoles.Amnesiac;
target.RpcSetCustomRole(killerRole);
+1 -2
View File
@@ -9,7 +9,6 @@ using System.Runtime.CompilerServices;
using AmongUs.GameOptions;
using EHR.AddOns.Crewmate;
using EHR.AddOns.Impostor;
using EHR.Neutral;
namespace EHR;
@@ -53,7 +52,7 @@ public abstract class RoleBase : IComparable<RoleBase>
public virtual bool CanUseImpostorVentButton(PlayerControl pc)
{
return pc.IsAlive() && (pc.Is(CustomRoleTypes.Impostor) || Amnesiac.WasAmnesiac.Contains(pc.PlayerId) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.CanVent.GetBool())) && Circumvent.CanUseImpostorVentButton(pc);
return pc.IsAlive() && (pc.Is(CustomRoleTypes.Impostor) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.CanVent.GetBool())) && Circumvent.CanUseImpostorVentButton(pc);
}
public virtual bool CanUseVent(PlayerControl pc, int ventId)