From 489e4cd61e11b1d9e697d4fe2573cba4c02b9036 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Tue, 20 Jan 2026 11:05:01 +0100 Subject: [PATCH] Add Accumulator --- CustomRoles.cs | 1 + Main.cs | 2 + Modules/CustomRolesHelper.cs | 3 + Modules/Utils.cs | 1 + Resources/Lang/en_US.json | 8 ++ Roles/Standard/Neutral/Killing/Accumulator.cs | 110 ++++++++++++++++++ 6 files changed, 125 insertions(+) create mode 100644 Roles/Standard/Neutral/Killing/Accumulator.cs diff --git a/CustomRoles.cs b/CustomRoles.cs index e6a4597ad..7b6b327cc 100644 --- a/CustomRoles.cs +++ b/CustomRoles.cs @@ -289,6 +289,7 @@ public enum CustomRoles // Neutrals + Accumulator, Agitator, Amnesiac, Amogus, diff --git a/Main.cs b/Main.cs index 1c15705ad..9061882de 100644 --- a/Main.cs +++ b/Main.cs @@ -561,6 +561,7 @@ public class Main : BasePlugin { CustomRoles.Thanos, "#F9D401" }, { CustomRoles.Berserker, "#50538F" }, { CustomRoles.SerialKiller, "#233fcc" }, + { CustomRoles.Accumulator, "#2bfbae" }, { CustomRoles.Spider, "#C9E44C" }, { CustomRoles.SoulCollector, "#6021A0" }, { CustomRoles.Sharpshooter, "#5901D4" }, @@ -1066,6 +1067,7 @@ public enum CustomWinner Necromancer = CustomRoles.Necromancer, Wraith = CustomRoles.Wraith, SerialKiller = CustomRoles.SerialKiller, + Accumulator = CustomRoles.Accumulator, Spider = CustomRoles.Spider, SoulCollector = CustomRoles.SoulCollector, Berserker = CustomRoles.Berserker, diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index c4f1b11ed..d455ecb57 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -377,6 +377,7 @@ internal static class CustomRolesHelper CustomRoles.Clerk => CustomRoles.Crewmate, CustomRoles.CovenMember => CustomRoles.Crewmate, CustomRoles.Augur => Augur.CanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate, + CustomRoles.Accumulator => Accumulator.CanVentBeforeKilling.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate, // Vanilla roles (just in case) CustomRoles.ImpostorEHR => CustomRoles.Impostor, @@ -654,6 +655,7 @@ internal static class CustomRolesHelper CustomRoles.Parasite or CustomRoles.Berserker or CustomRoles.SerialKiller or + CustomRoles.Accumulator or CustomRoles.Spider or CustomRoles.SoulCollector or CustomRoles.Sharpshooter or @@ -1964,6 +1966,7 @@ public enum CountTypes HexMaster, Wraith, SerialKiller, + Accumulator, Spider, SoulCollector, Berserker, diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 5cd41ecd2..cd74d3b00 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -960,6 +960,7 @@ public static class Utils case CustomRoles.Cherokious: case CustomRoles.Crewpostor: case CustomRoles.Hypocrite: + case CustomRoles.Accumulator: if (forRecompute && !p.IsDead) hasTasks = false; if (p.IsDead) hasTasks = false; break; diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index c2b7e6202..814f42fc3 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -9517,6 +9517,14 @@ "ImmuneToAttacksWhenTasksDone": "Immune to attacks on task completion", "TwisterCooldown": "Twist Cooldown", "TwisterButtonText": "Twist", + "Accumulator": "Accumulator", + "AccumulatorInfo": "Do Tasks For Low Kill Cooldown", + "AccumulatorInfoLong": "(Neutrals):\\nAs the Accumulator, you start with a crewmate basis, and you can do tasks. Each task you complete lowers your kill cooldown (that you'll eventually have). You can pet or finish all tasks to turn into a killing neutral with the kill cooldown you accumulated.\\nKill everyone to win!", + "Accumulator.KillCooldownDecrementWithEachTask": "Kill Cooldown Decrement With Each Task", + "Accumulator.CanVentBeforeKilling": "Can Vent Before Killing", + "Accumulator.CanVentAfterKilling": "Can Vent After Killing", + "Accumulator.ImpostorVisionBeforeKilling": "Has Impostor Vision Before Killing", + "Accumulator.ImpostorVisionAfterKilling": "Has Impostor Vision After Killing", "MainMenu.SettingsButton": "Settings", "MainMenu.InventoryButton": "Inventory", "MainMenu.CreditsButton": "Credits", diff --git a/Roles/Standard/Neutral/Killing/Accumulator.cs b/Roles/Standard/Neutral/Killing/Accumulator.cs new file mode 100644 index 000000000..d7829886b --- /dev/null +++ b/Roles/Standard/Neutral/Killing/Accumulator.cs @@ -0,0 +1,110 @@ +using System; +using AmongUs.GameOptions; +using EHR.Modules; +using Hazel; + +namespace EHR.Roles; + +public class Accumulator : RoleBase +{ + public static bool On; + + private static OptionItem StartingKillCooldown; + private static OptionItem KillCooldownDecrementWithEachTask; + public static OptionItem CanVentBeforeKilling; + private static OptionItem VentCooldown; + private static OptionItem MaxInVentTime; + private static OptionItem CanVentAfterKilling; + private static OptionItem ImpostorVisionBeforeKilling; + private static OptionItem ImpostorVisionAfterKilling; + + public override bool IsEnable => On; + + private bool Killing; + private float KCD; + private byte AccumulatorId; + + public override void SetupCustomOption() + { + StartSetup(657700) + .AutoSetupOption(ref StartingKillCooldown, 30f, new FloatValueRule(0f, 180f, 0.5f), OptionFormat.Seconds) + .AutoSetupOption(ref KillCooldownDecrementWithEachTask, 3f, new FloatValueRule(0f, 30f, 0.5f), OptionFormat.Seconds) + .AutoSetupOption(ref CanVentBeforeKilling, false) + .AutoSetupOption(ref VentCooldown, 0f, new FloatValueRule(0f, 120f, 0.5f), OptionFormat.Seconds, overrideParent: CanVentBeforeKilling) + .AutoSetupOption(ref MaxInVentTime, 0f, new FloatValueRule(0f, 120f, 0.5f), OptionFormat.Seconds, overrideParent: CanVentBeforeKilling) + .AutoSetupOption(ref CanVentAfterKilling, true) + .AutoSetupOption(ref ImpostorVisionBeforeKilling, false) + .AutoSetupOption(ref ImpostorVisionAfterKilling, true) + .CreateOverrideTasksData(); + } + + public override void Init() + { + On = false; + } + + public override void Add(byte playerId) + { + On = true; + Killing = false; + KCD = StartingKillCooldown.GetFloat(); + AccumulatorId = playerId; + } + + public override void SetKillCooldown(byte id) + { + Main.AllPlayerKillCooldown[id] = KCD; + } + + public override bool CanUseKillButton(PlayerControl pc) + { + return Killing; + } + + public override void ApplyGameOptions(IGameOptions opt, byte id) + { + opt.SetVision(Killing ? ImpostorVisionAfterKilling.GetBool() : ImpostorVisionBeforeKilling.GetBool()); + + if (!Killing && CanVentBeforeKilling.GetBool()) + { + AURoleOptions.EngineerCooldown = VentCooldown.GetFloat(); + AURoleOptions.EngineerInVentMaxTime = MaxInVentTime.GetFloat(); + } + } + + public override bool CanUseImpostorVentButton(PlayerControl pc) + { + return Killing && CanVentAfterKilling.GetBool(); + } + + public override void OnTaskComplete(PlayerControl pc, int completedTaskCount, int totalTaskCount) + { + KCD -= KillCooldownDecrementWithEachTask.GetFloat(); + Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, KCD, Killing); + + if (completedTaskCount + 1 >= totalTaskCount) + OnPet(pc); + } + + public override void OnPet(PlayerControl pc) + { + if (Killing) return; + Killing = true; + pc.RpcSetRoleDesync(RoleTypes.Impostor, pc.OwnerId, setRoleMap: true); + LateTask.New(() => pc.SetKillCooldown(KCD), 0.2f); + Utils.SendRPC(CustomRPC.SyncRoleData, pc.PlayerId, KCD, Killing); + Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc); + } + + public void ReceiveRPC(MessageReader reader) + { + KCD = reader.ReadSingle(); + Killing = reader.ReadBoolean(); + } + + public override string GetSuffix(PlayerControl seer, PlayerControl target, bool hud = false, bool meeting = false) + { + if (seer.PlayerId != AccumulatorId || seer.PlayerId != target.PlayerId || (seer.IsModdedClient() && !hud) || meeting || Killing) return string.Empty; + return string.Format(Translator.GetString("KCD"), Math.Round(Math.Max(0, KCD), 1)); + } +} \ No newline at end of file