diff --git a/CustomRoles.cs b/CustomRoles.cs index d1c8b9050..e3f45b50f 100644 --- a/CustomRoles.cs +++ b/CustomRoles.cs @@ -381,10 +381,11 @@ public enum CustomRoles Starspawn, Cultist, Sunnyboy, - Technician, Tank, + Technician, Terrorist, Thanos, + Thief, Tiger, Traitor, Tremor, @@ -541,6 +542,7 @@ public enum CustomRoles LastImpostor, Lazy, Listener, + Looter, Lovers, Loyal, Lucky, diff --git a/Main.cs b/Main.cs index d026ba7e3..751422efe 100644 --- a/Main.cs +++ b/Main.cs @@ -583,6 +583,7 @@ public class Main : BasePlugin { CustomRoles.PlagueDoctor, "#ff6633" }, { CustomRoles.Curser, "#510c91" }, { CustomRoles.Postman, "#00b893" }, + { CustomRoles.Thief, "#44AF84" }, { CustomRoles.Auditor, "#6BB626" }, { CustomRoles.Magistrate, "#E44CB8" }, { CustomRoles.Seamstress, "#BFE44C" }, @@ -658,6 +659,7 @@ public class Main : BasePlugin { CustomRoles.Listener, "#060270" }, { CustomRoles.Unbound, "#DFC57B" }, { CustomRoles.AntiTP, "#fcba03" }, + { CustomRoles.Looter, "#F5D866" }, { CustomRoles.Tired, "#ff1919" }, { CustomRoles.Concealer, "#ff1919" }, { CustomRoles.Composter, "#8D6F64" }, diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index f0527683d..f3d39a086 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -539,6 +539,7 @@ internal static class CustomRolesHelper CustomRoles.PlagueDoctor => RoleTypes.Impostor, CustomRoles.Curser => RoleTypes.Impostor, CustomRoles.Postman => RoleTypes.Impostor, + CustomRoles.Thief => RoleTypes.Impostor, CustomRoles.Dealer => RoleTypes.Impostor, CustomRoles.Auditor => RoleTypes.Impostor, CustomRoles.Seamstress => RoleTypes.Shapeshifter, @@ -1593,6 +1594,7 @@ internal static class CustomRolesHelper CustomRoles.Doomsayer => RoleOptionType.Neutral_Evil, CustomRoles.Mario => RoleOptionType.Neutral_Evil, CustomRoles.Terrorist => RoleOptionType.Neutral_Evil, + CustomRoles.Thief => RoleOptionType.Neutral_Evil, CustomRoles.Collector => RoleOptionType.Neutral_Evil, CustomRoles.Vulture => RoleOptionType.Neutral_Evil, CustomRoles.Workaholic => RoleOptionType.Neutral_Evil, diff --git a/Modules/Utils.cs b/Modules/Utils.cs index f6a570484..a67cffeb0 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -879,6 +879,7 @@ public static class Utils case CustomRoles.Doppelganger: case CustomRoles.NecroGuesser: case CustomRoles.PlagueDoctor: + case CustomRoles.Thief: case CustomRoles.Postman: case CustomRoles.Dealer: case CustomRoles.Auditor: diff --git a/Patches/PlayerControlPatch.cs b/Patches/PlayerControlPatch.cs index 7a0e0f370..4f2dfdbf8 100644 --- a/Patches/PlayerControlPatch.cs +++ b/Patches/PlayerControlPatch.cs @@ -1265,6 +1265,9 @@ internal static class ReportDeadBodyPatch QuizMaster.Data.LastReportedPlayer = (Palette.GetColorName(target.DefaultOutfit.ColorId), target.Object); if (MeetingStates.FirstMeeting) QuizMaster.Data.FirstReportedBodyPlayerName = target.Object.GetRealName(); } + + if (player.Is(CustomRoles.Looter)) + tpc.GetCustomSubRoles().FindAll(x => !player.Is(x) && !x.IsGhostRole()).ForEach(x => player.RpcSetCustomRole(x)); } if (QuizMaster.On) @@ -1359,7 +1362,7 @@ internal static class ReportDeadBodyPatch { if (pc.IsAlive()) { - if (Camouflage.IsCamouflage && !Magistrate.CallCourtNextMeeting) + if (Camouflage.IsCamouflage && !Magistrate.CallCourtNextMeeting && !Doppelganger.DoppelVictim.ContainsKey(pc.PlayerId)) Camouflage.RpcSetSkin(pc, revertToDefault: true, forceRevert: true); if (Magistrate.CallCourtNextMeeting) diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json index 7bebaa524..6ea913417 100644 --- a/Resources/Lang/en_US.json +++ b/Resources/Lang/en_US.json @@ -9764,6 +9764,14 @@ "HelperInfo": "Complete Tasks For Others", "HelperInfoLong": "(Crewmates):\\nAs the Helper, whenever you complete a task, a random crewmate will also have one of their tasks completed.", "HelperCompletedTaskForYou": "The {0} completed a task for you!", + "Thief": "Thief", + "ThiefInfo": "Steal a Killing Role", + "ThiefInfoLong": "(Neutrals):\\nAs the Thief, you must kill someone to become their role:\\n- Impostor / Neutral Killing roles => become the same role as them\\n- Trickster => become Double Agent\\n- Maverick => become Serial Killer\\n- Madmate roles => become Renegade\\n- Coven roles (if enabled) => become Coven Member\\nIf you kill any other role, you suicide.", + "Thief.CanStealCovenRoles": "Can Steal <#7b3fbb>Coven Roles", + "Looter": "Looter", + "LooterInfo": "Loot Players' Add-ons", + "LooterInfoLong": "(Add-ons):\\nAs a Looter, when you report a body, you take all of the target's add-ons.", + "Prefix.Looter": "Looter", "ChameleonCanVent": "Vent to disguise", "ChameleonInvisState": "You are disguising!", "ChameleonInvisStateOut": "Your disguise ended", diff --git a/Roles/AddOns/Common/Looter.cs b/Roles/AddOns/Common/Looter.cs new file mode 100644 index 000000000..a564604bc --- /dev/null +++ b/Roles/AddOns/Common/Looter.cs @@ -0,0 +1,11 @@ +namespace EHR.AddOns.Common; + +public class Looter : IAddon +{ + public AddonTypes Type => AddonTypes.Mixed; + + public void SetupCustomOption() + { + Options.SetupAdtRoleOptions(656500, CustomRoles.Looter, canSetNum: true, teamSpawnOptions: true); + } +} \ No newline at end of file diff --git a/Roles/Neutral/Thief.cs b/Roles/Neutral/Thief.cs new file mode 100644 index 000000000..792875dca --- /dev/null +++ b/Roles/Neutral/Thief.cs @@ -0,0 +1,60 @@ +namespace EHR.Neutral; + +public class Thief : RoleBase +{ + public static bool On; + + private static OptionItem CanStealCovenRoles; + + public override bool IsEnable => On; + + public override void SetupCustomOption() + { + StartSetup(656400) + .AutoSetupOption(ref CanStealCovenRoles, false); + } + + public override void Init() + { + On = false; + } + + public override void Add(byte playerId) + { + On = true; + } + + public override bool CanUseKillButton(PlayerControl pc) + { + return pc.IsAlive(); + } + + public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) + { + bool success = target.IsImpostor() || target.Is(CustomRoles.Trickster) || target.IsMadmate() || target.Is(CustomRoles.Maverick) || target.IsNeutralKiller() || (target.Is(CustomRoleTypes.Coven) && CanStealCovenRoles.GetBool()); + if (!success) killer.Suicide(); + return success; + } + + public override void OnMurder(PlayerControl killer, PlayerControl target) + { + CustomRoles? role = null; + + if (target.Is(CustomRoles.Trickster)) role = CustomRoles.DoubleAgent; + else if (target.Is(CustomRoles.Maverick)) role = CustomRoles.SerialKiller; + else if (target.IsMadmate()) role = CustomRoles.Refugee; + else if (target.IsImpostor() || target.IsNeutralKiller()) role = target.GetCustomRole(); + else if (CanStealCovenRoles.GetBool() && target.Is(CustomRoleTypes.Coven)) role = CustomRoles.CovenMember; + + if (!role.HasValue) + { + if (killer.IsAlive()) killer.Suicide(); + return; + } + + killer.RpcChangeRoleBasis(role.Value); + killer.RpcSetCustomRole(role.Value); + killer.ResetKillCooldown(); + killer.SetKillCooldown(); + } +} \ No newline at end of file