diff --git a/CTA/CustomTeamAssigner/CustomRoles.cs b/CTA/CustomTeamAssigner/CustomRoles.cs index d85a22d65..c7f029308 100644 --- a/CTA/CustomTeamAssigner/CustomRoles.cs +++ b/CTA/CustomTeamAssigner/CustomRoles.cs @@ -94,6 +94,7 @@ public enum CustomRoles Overheat, Parasite, Penguin, + Perplexer, Postponer, Psychopath, Puppeteer, diff --git a/CustomRoles.cs b/CustomRoles.cs index d85a22d65..c7f029308 100644 --- a/CustomRoles.cs +++ b/CustomRoles.cs @@ -94,6 +94,7 @@ public enum CustomRoles Overheat, Parasite, Penguin, + Perplexer, Postponer, Psychopath, Puppeteer, diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 8915f993f..63c7af094 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -368,6 +368,7 @@ internal static class CustomRolesHelper CustomRoles.Unshifter => CustomRoles.Impostor, CustomRoles.Scanner => CustomRoles.Phantom, CustomRoles.Fakeshifter => CustomRoles.Shapeshifter, + CustomRoles.Perplexer => CustomRoles.Shapeshifter, CustomRoles.Silencer => Silencer.SilenceMode.GetValue() switch { 0 => CustomRoles.Impostor, @@ -831,7 +832,8 @@ internal static class CustomRolesHelper CustomRoles.Camouflager or CustomRoles.Twister or CustomRoles.Lurker or - CustomRoles.Fakeshifter; + CustomRoles.Fakeshifter or + CustomRoles.Perplexer; } public static bool IsNeutral(this CustomRoles role, bool check = false) @@ -1694,6 +1696,7 @@ internal static class CustomRolesHelper CustomRoles.Librarian => RoleOptionType.Impostor_Support, CustomRoles.Nullifier => RoleOptionType.Impostor_Support, CustomRoles.Occultist => RoleOptionType.Impostor_Support, + CustomRoles.Perplexer => RoleOptionType.Impostor_Support, CustomRoles.Silencer => RoleOptionType.Impostor_Support, CustomRoles.Swapster => RoleOptionType.Impostor_Support, CustomRoles.TimeThief => RoleOptionType.Impostor_Support, diff --git a/Resources/Lang/en_US.jsonc b/Resources/Lang/en_US.jsonc index 94a926290..dc44062d2 100644 --- a/Resources/Lang/en_US.jsonc +++ b/Resources/Lang/en_US.jsonc @@ -2099,6 +2099,9 @@ "PenguinTimerText": "Drag Timer", "PenguinVictimCanUseAbilities": "Victim Can Use Their Abilities While Being Dragged", "PenguinVictimKill": "As the victim of the Penguin/Goose, you cannot interact with others", + "Perplexer": "Perplexer", + "PerplexerInfo": "Invert a player's movement controls", + "PerplexerInfoLong": "(Impostors):\nAs the Perplexer, use your shapeshift menu to select a player. That player will get their movement controls inverted for a certain amout of time.", "PhantomEHR": "Phantom", "PhantomEHRInfo": "Go invisible temporarily", "PhantomEHRInfoLong": "(Impostors):\\nAs the Phantom, you can go invisible for a short period. During this time, you can't be seen by Crewmates.", diff --git a/Roles/Standard/Impostor/Concealing/Fakeshifter.cs b/Roles/Standard/Impostor/Concealing/Fakeshifter.cs index 6f6b391bf..6744cd7c5 100644 --- a/Roles/Standard/Impostor/Concealing/Fakeshifter.cs +++ b/Roles/Standard/Impostor/Concealing/Fakeshifter.cs @@ -39,7 +39,7 @@ public class Fakeshifter : RoleBase public override void ApplyGameOptions(IGameOptions opt, byte playerId) { AURoleOptions.ShapeshifterCooldown = AbilityCooldown.GetInt(); - opt.SetVision(false); + opt.SetVision(true); } public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting) diff --git a/Roles/Standard/Impostor/Support/Perplexer.cs b/Roles/Standard/Impostor/Support/Perplexer.cs new file mode 100644 index 000000000..6f3a1a197 --- /dev/null +++ b/Roles/Standard/Impostor/Support/Perplexer.cs @@ -0,0 +1,71 @@ +using AmongUs.GameOptions; +using EHR.Modules; +using System.Linq; + +namespace EHR.Roles; + +public class Perplexer : RoleBase +{ + public static bool On; + private const int Id = 698000; + + public override bool IsEnable => On; + + private static OptionItem KillCooldown; + private static OptionItem AbilityCooldown; + private static OptionItem AbilityDuration; + private static OptionItem AbilityUseLimit; + private static OptionItem AbilityUseGainWithEachKill; + + private byte MarkedId; + + public override void SetupCustomOption() + { + StartSetup(Id) + .AutoSetupOption(ref KillCooldown, 30f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityCooldown, 30f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityDuration, 10f, new FloatValueRule(1, 120, 1), OptionFormat.Seconds) + .AutoSetupOption(ref AbilityUseLimit, 3f, new FloatValueRule(0, 20, 0.05f), OptionFormat.None) + .AutoSetupOption(ref AbilityUseGainWithEachKill, 0.5f, new FloatValueRule(0f, 5f, 0.25f), OptionFormat.Times); + } + + public override void Init() + { + On = false; + } + + public override void Add(byte playerId) + { + On = true; + MarkedId = byte.MaxValue; + playerId.SetAbilityUseLimit(AbilityUseLimit.GetFloat()); + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + AURoleOptions.ShapeshifterCooldown = AbilityCooldown.GetInt(); + opt.SetVision(true); + } + public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting) + { + bool animated = !Options.DisableShapeshiftAnimations.GetBool(); + + if (MarkedId == byte.MaxValue && target.IsAlive()) + { + MarkedId = target.PlayerId; + Main.AllPlayerSpeed[target.PlayerId] *= -1; + Utils.MarkEveryoneDirtySettings(); + LateTask.New(() => shapeshifter.RpcShapeshift(shapeshifter, animated), animated ? 1.2f : 0.5f); + LateTask.New(() => + { + if (target != null && target.IsAlive()) + { + Main.AllPlayerSpeed[target.PlayerId] *= -1; + MarkedId = byte.MaxValue; + Utils.MarkEveryoneDirtySettings(); + } + }, AbilityDuration.GetFloat(), "Perplexer Revert Control Invert"); + } + return false; + } +} \ No newline at end of file