From 4379ca840933a454f33808965738bd79885ccaec Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Mon, 20 Apr 2026 10:50:08 +0200 Subject: [PATCH] Add Blockade --- CustomRoles.cs | 1 + Main.cs | 2 + Modules/CustomRolesHelper.cs | 3 + Modules/Utils.cs | 2 + Resources/Lang/en_US.jsonc | 4 + Roles/Standard/Neutral/Killing/Blockade.cs | 116 +++++++++++++++++++++ 6 files changed, 128 insertions(+) create mode 100644 Roles/Standard/Neutral/Killing/Blockade.cs diff --git a/CustomRoles.cs b/CustomRoles.cs index 8c072d294..a46c3bb6d 100644 --- a/CustomRoles.cs +++ b/CustomRoles.cs @@ -306,6 +306,7 @@ public enum CustomRoles Bargainer, Beehive, Berserker, + Blockade, BloodKnight, Bubble, Chemist, diff --git a/Main.cs b/Main.cs index 634d11895..b4f3608d2 100644 --- a/Main.cs +++ b/Main.cs @@ -571,6 +571,7 @@ public class Main : BasePlugin { CustomRoles.Thanos, "#F9D401" }, { CustomRoles.Berserker, "#50538F" }, { CustomRoles.SerialKiller, "#233fcc" }, + { CustomRoles.Blockade, "#d6fa34" }, { CustomRoles.Quarry, "#c1fb2b" }, { CustomRoles.Accumulator, "#2bfbae" }, { CustomRoles.Spider, "#C9E44C" }, @@ -1090,6 +1091,7 @@ public enum CustomWinner Necromancer = CustomRoles.Necromancer, Wraith = CustomRoles.Wraith, SerialKiller = CustomRoles.SerialKiller, + Blockade = CustomRoles.Blockade, Quarry = CustomRoles.Quarry, Accumulator = CustomRoles.Accumulator, Spider = CustomRoles.Spider, diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index add69c826..9ac5f322e 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -529,6 +529,7 @@ internal static class CustomRolesHelper CustomRoles.Duality => RoleTypes.Impostor, CustomRoles.Berserker => RoleTypes.Impostor, CustomRoles.SerialKiller => RoleTypes.Impostor, + CustomRoles.Blockade => RoleTypes.Shapeshifter, CustomRoles.Quarry => RoleTypes.Shapeshifter, CustomRoles.SoulCollector => RoleTypes.Impostor, CustomRoles.Spider => UsePets ? RoleTypes.Impostor : RoleTypes.Shapeshifter, @@ -668,6 +669,7 @@ internal static class CustomRolesHelper CustomRoles.Parasite or CustomRoles.Berserker or CustomRoles.SerialKiller or + CustomRoles.Blockade or CustomRoles.Quarry or CustomRoles.Accumulator or CustomRoles.Spider or @@ -1994,6 +1996,7 @@ public enum CountTypes HexMaster, Wraith, SerialKiller, + Blockade, Quarry, Accumulator, Spider, diff --git a/Modules/Utils.cs b/Modules/Utils.cs index b8f027856..39e324038 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -817,6 +817,7 @@ public static class Utils case CustomRoles.Eclipse: case CustomRoles.Pyromaniac: case CustomRoles.SerialKiller: + case CustomRoles.Blockade: case CustomRoles.Quarry: case CustomRoles.Spider: case CustomRoles.SoulCollector: @@ -3676,6 +3677,7 @@ public static class Utils { CustomRoles.Farmer => 2, CustomRoles.Thanos => 5, + CustomRoles.Blockade => 5, CustomRoles.Mole => Mole.CD.GetInt(), CustomRoles.PortalMaker => PortalMaker.AbilityCooldown.GetInt(), CustomRoles.Telecommunication => Telecommunication.VentCooldown.GetInt(), diff --git a/Resources/Lang/en_US.jsonc b/Resources/Lang/en_US.jsonc index d440320ac..52da4563d 100644 --- a/Resources/Lang/en_US.jsonc +++ b/Resources/Lang/en_US.jsonc @@ -2474,6 +2474,10 @@ "BerserkerInfo": "Go Berserk If Others Kill More Than You", "BerserkerInfoLong": "(Neutrals):\\nAs the Berserker, you get stronger each time someone other than you kills:\\n1: Long kill range\\n2: Lower kill cooldown\\n3: Impostor vision\\n4: Immunity\\n5: Suicide\\nIf you kill, your strength goes down a level. Kill everyone to win!", "Berserker.LowerKillCooldown": "Lower Kill Cooldown", + "Blockade": "Blockade", + "BlockadeInfo": "Place Blockades", + "BlockadeInfoLong": "(Neutrals):\\nAs the Blockade, you can vanish/pet/shapeshift to place blockades. No one other than you can go through them. All blockades disappear when a meeting starts.", + "Blockade.BlockadeRadius": "Blockade Radius", "BloodKnight": "Blood Knight", "BloodKnightInfo": "Killing gives you a temporary shield", "BloodKnightInfoLong": "(Neutrals):\\nBlood Knights win if they're the last killing role alive and crewmates are equal or less than them. They gain temporary shields after every kill, making them immortal for a few seconds.", diff --git a/Roles/Standard/Neutral/Killing/Blockade.cs b/Roles/Standard/Neutral/Killing/Blockade.cs new file mode 100644 index 000000000..b90c932cb --- /dev/null +++ b/Roles/Standard/Neutral/Killing/Blockade.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using AmongUs.GameOptions; + +namespace EHR.Roles; + +public class Blockade : RoleBase +{ + public static bool On; + + private static OptionItem BlockadeRadius; + private static OptionItem KillCooldown; + private static OptionItem CanVent; + private static OptionItem ImpostorVision; + private static OptionItem AbilityUseLimit; + private static OptionItem AbilityUseGainWithEachKill; + + public override bool IsEnable => On; + + private List Blockades; + private Dictionary LastPosition; + + public override void SetupCustomOption() + { + StartSetup(658300) + .AutoSetupOption(ref BlockadeRadius, 1.5f, new FloatValueRule(0.1f, 10f, 0.1f), OptionFormat.Multiplier) + .AutoSetupOption(ref KillCooldown, 22.5f, new FloatValueRule(0f, 180f, 0.5f), OptionFormat.Seconds) + .AutoSetupOption(ref CanVent, true) + .AutoSetupOption(ref ImpostorVision, true) + .AutoSetupOption(ref AbilityUseLimit, 1f, new FloatValueRule(0, 20, 0.05f), OptionFormat.Times) + .AutoSetupOption(ref AbilityUseGainWithEachKill, 0.5f, new FloatValueRule(0f, 5f, 0.1f), OptionFormat.Times); + } + + public override void Init() + { + On = false; + } + + public override void Add(byte playerId) + { + On = true; + Blockades = []; + LastPosition = []; + playerId.SetAbilityUseLimit(AbilityUseLimit.GetFloat()); + } + + public override void SetKillCooldown(byte id) + { + Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat(); + } + + public override void ApplyGameOptions(IGameOptions opt, byte id) + { + opt.SetVision(ImpostorVision.GetBool()); + + if (Options.UsePhantomBasis.GetBool()) + { + AURoleOptions.PhantomCooldown = 5f; + AURoleOptions.PhantomDuration = 1f; + } + else if (!Options.UsePets.GetBool()) + { + AURoleOptions.ShapeshifterCooldown = 5f; + AURoleOptions.ShapeshifterDuration = 1f; + } + } + + public override bool CanUseImpostorVentButton(PlayerControl pc) + { + return CanVent.GetBool(); + } + + public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting) + { + if (shapeshifting) PlaceBlockade(shapeshifter); + return false; + } + + public override bool OnVanish(PlayerControl pc) + { + PlaceBlockade(pc); + return false; + } + + public override void OnPet(PlayerControl pc) + { + PlaceBlockade(pc); + } + + void PlaceBlockade(PlayerControl pc) + { + if (pc.GetAbilityUseLimit() < 1f) return; + pc.RpcRemoveAbilityUse(); + + Blockades.Add(pc.Pos()); + pc.Notify(Translator.GetString("MarkDone")); + } + + public override void OnCheckPlayerPosition(PlayerControl pc) + { + if (pc.Is(CustomRoles.Blockade)) return; + + Vector2 pos = pc.Pos(); + float radius = BlockadeRadius.GetFloat(); + + if (Blockades.Exists(x => FastVector2.DistanceWithinRange(pos, x, radius))) + pc.TP(LastPosition.GetValueOrDefault(pc.PlayerId, pc.transform.position)); + else + LastPosition[pc.PlayerId] = pc.transform.position; + } + + public override void OnReportDeadBody() + { + Blockades = []; + LastPosition = []; + } +} \ No newline at end of file