From 425a6fe696f1432d2548913a240c4b7968e07ddf Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Sat, 8 Feb 2025 19:41:09 -0500
Subject: [PATCH 1/8] all the work in one commit
---
Resources/Lang/en_US.json | 25 ++
Roles/Neutral/Doomsayer.cs | 573 ++++++++++++++++++++++++++++++++++++-
2 files changed, 587 insertions(+), 11 deletions(-)
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json
index 17c0d34d5b..574e2e059b 100644
--- a/Resources/Lang/en_US.json
+++ b/Resources/Lang/en_US.json
@@ -3730,6 +3730,9 @@
"DCanGuessCoven": "Can Guess Coven",
"DCanGuessAdt": "Can Guess Add-Ons",
"DoomsayerAdvancedSettings": "Advanced Settings",
+ "DoomsayerEasyMode": "Easy Mode (Can Get Hints)",
+ "DoomsayerObserveCooldown": "Observe Cooldown",
+ "DoomsayerEvenEasierMode": "Even Easier Mode (Hints Show Possible Roles)",
"DoomsayerMaxNumberOfGuessesPerMeeting": "Maximum number of guesses per meeting",
"DoomsayerKillCorrectlyGuessedPlayers": "Kill correctly guessed players",
"DoomsayerDoesNotSuicideWhenMisguessing": "Doomsayer does not suicide when misguessing",
@@ -3741,6 +3744,28 @@
"DoomsayerGuessCountMsg": "You correctly guessed {0} Roles",
"DoomsayerGuessCountTitle": "DOOMSAYER",
"DoomsayerGuessSameRoleAgainMsg": "You tried to guess the same Role or Add-on that you guessed before",
+ "DoomsayerObserveTitle": "OBSERVATION RESULTS",
+
+ "DoomsayerObserve.Basic": "Your observation of {0} shows that they live an ordinary life.",
+ "DoomsayerRoles.Basic": "(Impostor, Shapeshifter, Phantom, Crewmate, Scientist, Engineer, Tracker, Noisemaker)",
+ "DoomsayerObserve.Fear": "Your observation of {0} shows that they are feared by many.",
+ "DoomsayerRoles.Fear": "(Arrogance, Berserker, Blackmailer, Bomber, Captain, Councillor, Coven Leader, Death, Demon, Dictator, God, Godfather, Famine, Infectious, Instigator, Jailer, Judge, Mayor, Marshall, Monarch, Parasite, Pestilence, Pitfall, Poisoner, President, Serial Killer, Sheriff, Twister, Vampire, Vindicator, Virus, War)",
+ "DoomsayerObserve.Magic": "Your observation of {0} shows that they posses some sort of magical power.",
+ "DoomsayerRoles.Magic": "(Chameleon, Chronomancer, Conjurer, Deathpact, Eraser, Guardian, Fortune Teller, Hex Master, Lightning, Medusa, Moon Dancer, Observer, Oracle, Overseer, Pixie, Psychic, Rift Maker, Shapemaster, Soul Catcher, Specter, Swooper, Time Master, Transporter, Warlock, Wildling, Witch, Wraith, YinYanger)",
+ "DoomsayerObserve.Skilled": "Your observation of {0} shows that they are very skilled in their craft.",
+ "DoomsayerRoles.Skilled": "(Alchemist, Baker, Camouflager, Celebrity, Cleanser, Consigliere, Copycat, Dazzler, Deputy, Doomsayer, Evil Guesser, Evil Hacker, Evil Tracker, Inspector, Investigator, Keeper, Knight, Lookout, Mechanic, Medic, Merchant, Nice Guesser, Pickpocket, Plague Scientist, Plaguebearer, Potion Master, Quick Shooter, Ritualist, Sniper, Stealth, Task Manager, Telecommunication, Time Thief, Veteran, Visionary)",
+ "DoomsayerObserve.Dedicated": "Your observation of {0} shows that they are very dedicated to their job.",
+ "DoomsayerRoles.Dedicated": "(Agitator, Anti Adminer, Bandit, Benefactor, Bodyguard, Bounty Hunter, Disperser, Double Agent, Escapist, Fireworker, Huntsman, Imitator, Jackal, Killing Machine, Lawyer, Lighter, Maverick, Miner, Ninja, Opportunist, Quizmaster, Seeker, Time Manager, Vector, Ventguard, Workaholic)",
+ "DoomsayerObserve.Shunned": "Your observation of {0} shows that they are shunned by society.",
+ "DoomsayerRoles.Shunned": "(Addict, Cultist, Deceiver, Devourer, Doppelganger, Follower, Gangster, Greedy, Hangman, Hater, Inhibitor, Jinx, Kamikaze, Lazy Guy, Ludopath, Lurker, Mini, Mole, Nemesis, Pacifist, Provocatuer, Punching Bag, Puppeteer, Pyromaniac, Revolutionist, Saboteur, Sacrifist, Snitch, Spy, Stalker, Swapper, Taskinator, Terrorist, Traitor, Troller, Vigilante)",
+ "DoomsayerObserve.Bodies": "Your observation of {0} shows that they have some sort of obsession with dead people...",
+ "DoomsayerRoles.Bodies": "(Altruist, Amnesiac, Anonymous, Butcher, Cleaner, Coroner, Cursed Soul, Detective, Doctor, Medium, Mortician, Necromancer, Pelican, Scavenger, Soul Collector, Spiritcaller, Spiritualist, Tracefinder, Trapster, Undertaker, Vulture, Witness, Zombie)",
+ "DoomsayerObserve.Dead": "Your observation of {0} shows that they are dead...",
+ "DoomsayerRoles.Dead": "(Any Ghost Role)",
+ "DoomsayerObserve.Misunderstood": "Your observation of {0} shows that they are misunderstood.",
+ "DoomsayerRoles.Misunderstood": "(Admirer, Bard, Bastion, Collector, Crewpostor, Crusader, Cursed Wolf, Doll Master, Enigma, Grenadier, Innocent, Jester, Mastermind, Mercenary, Penguin, Pursuer, Randomizer, Refugee, Retributionist, Reverie, Romantic, Ruthless Romantic, Shaman, Underdog, Vengeful Romantic, Voodoo Master, Werewolf)",
+ "DoomsayerObserve.Unknown": "You are unable to comprehend your observation of {0}...",
+ "DoomsayerObserve.Obvious": "Good job, you wasted your observation on {0}, considering anyone can see it with their own two eyes...",
"EveryoneCanKnowMini": "Everyone can see the Mini",
"CanBeEvil": "Mini can be an Impostor",
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index 5c88a1f854..03c297122b 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -2,7 +2,10 @@
using Hazel;
using InnerNet;
using TOHE.Roles.Core;
+using TOHE.Roles.Crewmate;
using UnityEngine;
+using static TOHE.MeetingHudStartPatch;
+using static TOHE.Options;
using static TOHE.Translator;
using static TOHE.Utils;
@@ -14,12 +17,14 @@ internal class Doomsayer : RoleBase
public override CustomRoles Role => CustomRoles.Doomsayer;
private const int Id = 14100;
public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Doomsayer);
- public override CustomRoles ThisRoleBase => CustomRoles.Crewmate;
+ public override CustomRoles ThisRoleBase => EasyMode.GetBool() ? CustomRoles.Impostor : CustomRoles.Crewmate;
public override Custom_RoleType ThisRoleType => Custom_RoleType.NeutralEvil;
//==================================================================\\
private readonly HashSet GuessedRoles = [];
private readonly Dictionary GuessingToWin = [];
+ private static readonly Dictionary> MsgToSend = [];
+ private static readonly Dictionary> ObserveList = [];
private int GuessesCount = 0;
private int GuessesCountPerMeeting = 0;
@@ -38,26 +43,36 @@ internal class Doomsayer : RoleBase
private static OptionItem MisguessRolePrevGuessRoleUntilNextMeeting;
private static OptionItem DoomsayerTryHideMsg;
private static OptionItem ImpostorVision;
+ private static OptionItem EasyMode;
+ private static OptionItem EvenEasierMode;
+ private static OptionItem ObserveCooldown;
public override void SetupCustomOption()
{
- Options.SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Doomsayer);
+ SetupSingleRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Doomsayer);
DoomsayerAmountOfGuessesToWin = IntegerOptionItem.Create(Id + 10, "DoomsayerAmountOfGuessesToWin", new(1, 10, 1), 3, TabGroup.NeutralRoles, false)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer])
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer])
.SetValueFormat(OptionFormat.Times);
DCanGuessImpostors = BooleanOptionItem.Create(Id + 12, "DCanGuessImpostors", true, TabGroup.NeutralRoles, true)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
DCanGuessCrewmates = BooleanOptionItem.Create(Id + 13, "DCanGuessCrewmates", true, TabGroup.NeutralRoles, true)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
DCanGuessNeutrals = BooleanOptionItem.Create(Id + 14, "DCanGuessNeutrals", true, TabGroup.NeutralRoles, true)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
DCanGuessCoven = BooleanOptionItem.Create(Id + 26, "DCanGuessCoven", true, TabGroup.NeutralRoles, true)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
DCanGuessAdt = BooleanOptionItem.Create(Id + 15, "DCanGuessAdt", false, TabGroup.NeutralRoles, false)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+
+ EasyMode = BooleanOptionItem.Create(Id + 27, "DoomsayerEasyMode", false, TabGroup.NeutralRoles, true)
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ ObserveCooldown = FloatOptionItem.Create(Id + 29, "DoomsayerObserveCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false).SetParent(EasyMode)
+ .SetValueFormat(OptionFormat.Seconds);
+ EvenEasierMode = BooleanOptionItem.Create(Id + 28, "DoomsayerEvenEasierMode", false, TabGroup.NeutralRoles, true)
+ .SetParent(EasyMode);
AdvancedSettings = BooleanOptionItem.Create(Id + 16, "DoomsayerAdvancedSettings", true, TabGroup.NeutralRoles, true)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
MaxNumberOfGuessesPerMeeting = IntegerOptionItem.Create(Id + 23, "DoomsayerMaxNumberOfGuessesPerMeeting", new(1, 10, 1), 3, TabGroup.NeutralRoles, false)
.SetParent(AdvancedSettings);
KillCorrectlyGuessedPlayers = BooleanOptionItem.Create(Id + 18, "DoomsayerKillCorrectlyGuessedPlayers", true, TabGroup.NeutralRoles, true)
@@ -68,18 +83,22 @@ public override void SetupCustomOption()
.SetParent(DoesNotSuicideWhenMisguessing);
ImpostorVision = BooleanOptionItem.Create(Id + 25, GeneralOption.ImpostorVision, true, TabGroup.NeutralRoles, false)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
DoomsayerTryHideMsg = BooleanOptionItem.Create(Id + 21, "DoomsayerTryHideMsg", true, TabGroup.NeutralRoles, true)
.SetColor(Color.green)
- .SetParent(Options.CustomRoleSpawnChances[CustomRoles.Doomsayer]);
+ .SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
}
public override void Init()
{
CantGuess = false;
+ MsgToSend.Clear();
+ ObserveList.Clear();
}
public override void Add(byte playerId)
{
GuessingToWin.TryAdd(playerId, GuessesCount);
+ ObserveList[playerId] = [];
+ MsgToSend[playerId] = [];
}
public void SendRPC(PlayerControl player)
{
@@ -268,4 +287,536 @@ public void SendMessageAboutGuess(PlayerControl guesser, PlayerControl playerMis
}, 0.7f, "Doomsayer Guess Msg 2");
}
}
+ public override bool CanUseKillButton(PlayerControl pc) => EasyMode.GetBool();
+ public override void SetKillCooldown(byte id) => ObserveCooldown.GetFloat();
+
+ public override bool ForcedCheckMurderAsKiller(PlayerControl killer, PlayerControl target)
+ {
+ if (killer == null || target == null) return false;
+ if (!EasyMode.GetBool()) return false;
+ if (!EvenEasierMode.GetBool()) MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()));
+ else MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()) + " " + ObserveRolesMsg(target));
+ return false;
+ }
+
+ // i hate this code so much no wonder why we reworked fortune teller, oh well, here we go again
+ public static string ObserveRiddleMsg(PlayerControl player)
+ {
+ string result = "DoomsayerRoles.";
+ var role = player.GetCustomRole();
+ if (role.IsGhostRole())
+ {
+ return GetString(result + "Dead");
+ }
+ if (Main.PlayerStates[player.PlayerId].IsNecromancer)
+ {
+ return GetString(result + "Bodies");
+ }
+ if (role.IsVanilla())
+ {
+ return GetString(result + "Basic");
+ }
+ if (role.IsRevealingRole(player))
+ {
+ return GetString(result + "Obvious");
+ }
+ switch (role)
+ {
+ case CustomRoles.Arrogance:
+ case CustomRoles.Berserker:
+ case CustomRoles.Blackmailer:
+ case CustomRoles.Bomber:
+ case CustomRoles.Captain:
+ case CustomRoles.ChiefOfPolice:
+ case CustomRoles.Councillor:
+ case CustomRoles.CovenLeader:
+ case CustomRoles.Death:
+ case CustomRoles.Demon:
+ case CustomRoles.Dictator:
+ case CustomRoles.God:
+ case CustomRoles.Godfather:
+ case CustomRoles.Famine:
+ case CustomRoles.Infectious:
+ case CustomRoles.Instigator:
+ case CustomRoles.Jailer:
+ case CustomRoles.Judge:
+ case CustomRoles.Mayor:
+ case CustomRoles.Marshall:
+ case CustomRoles.Monarch:
+ case CustomRoles.Parasite:
+ case CustomRoles.Pestilence:
+ case CustomRoles.Pitfall:
+ case CustomRoles.Poisoner:
+ case CustomRoles.President:
+ case CustomRoles.SerialKiller:
+ case CustomRoles.Shocker:
+ case CustomRoles.Sheriff:
+ case CustomRoles.Twister:
+ case CustomRoles.Vampire:
+ case CustomRoles.Vindicator:
+ case CustomRoles.Virus:
+ case CustomRoles.War:
+ result += "Fear";
+ break;
+ case CustomRoles.Abyssbringer:
+ case CustomRoles.Chameleon:
+ case CustomRoles.Chronomancer:
+ case CustomRoles.Conjurer:
+ case CustomRoles.Deathpact:
+ case CustomRoles.Eraser:
+ case CustomRoles.Guardian:
+ case CustomRoles.FortuneTeller:
+ case CustomRoles.HexMaster:
+ case CustomRoles.Lightning:
+ case CustomRoles.Medusa:
+ case CustomRoles.MoonDancer:
+ case CustomRoles.Observer:
+ case CustomRoles.Oracle:
+ case CustomRoles.Overseer:
+ case CustomRoles.Pixie:
+ case CustomRoles.Psychic:
+ case CustomRoles.RiftMaker:
+ case CustomRoles.ShapeMaster:
+ case CustomRoles.SoulCatcher:
+ case CustomRoles.Specter:
+ case CustomRoles.Swooper:
+ case CustomRoles.TimeMaster:
+ case CustomRoles.Transporter:
+ case CustomRoles.Warlock:
+ case CustomRoles.Wildling:
+ case CustomRoles.Witch:
+ case CustomRoles.Wraith:
+ case CustomRoles.YinYanger:
+ result += "Magic";
+ break;
+ case CustomRoles.Alchemist:
+ case CustomRoles.Baker:
+ case CustomRoles.Camouflager:
+ case CustomRoles.Celebrity:
+ case CustomRoles.Cleanser:
+ case CustomRoles.Consigliere:
+ case CustomRoles.CopyCat:
+ case CustomRoles.Dazzler:
+ case CustomRoles.Deputy:
+ case CustomRoles.Doomsayer:
+ case CustomRoles.EvilGuesser:
+ case CustomRoles.EvilHacker:
+ case CustomRoles.EvilTracker:
+ case CustomRoles.Inspector:
+ case CustomRoles.Investigator:
+ case CustomRoles.Keeper:
+ case CustomRoles.Knight:
+ case CustomRoles.Lookout:
+ case CustomRoles.Mechanic:
+ case CustomRoles.Medic:
+ case CustomRoles.Merchant:
+ case CustomRoles.NiceGuesser:
+ case CustomRoles.Pickpocket:
+ case CustomRoles.PlagueDoctor:
+ case CustomRoles.PlagueBearer:
+ case CustomRoles.PotionMaster:
+ case CustomRoles.QuickShooter:
+ case CustomRoles.Ritualist:
+ case CustomRoles.Sniper:
+ case CustomRoles.Stealth:
+ case CustomRoles.TaskManager:
+ case CustomRoles.Telecommunication:
+ case CustomRoles.TimeThief:
+ case CustomRoles.Veteran:
+ case CustomRoles.Visionary:
+ result += "Skilled";
+ break;
+ case CustomRoles.Agitater:
+ case CustomRoles.AntiAdminer:
+ case CustomRoles.Bandit:
+ case CustomRoles.Benefactor:
+ case CustomRoles.Bodyguard:
+ case CustomRoles.BountyHunter:
+ case CustomRoles.Disperser:
+ case CustomRoles.DoubleAgent:
+ case CustomRoles.Escapist:
+ case CustomRoles.Fireworker:
+ case CustomRoles.Huntsman:
+ case CustomRoles.Imitator:
+ case CustomRoles.Jackal:
+ case CustomRoles.KillingMachine:
+ case CustomRoles.Lawyer:
+ case CustomRoles.Lighter:
+ case CustomRoles.Maverick:
+ case CustomRoles.Miner:
+ case CustomRoles.Ninja:
+ case CustomRoles.Opportunist:
+ case CustomRoles.Quizmaster:
+ case CustomRoles.Seeker:
+ case CustomRoles.TimeManager:
+ case CustomRoles.Vector:
+ case CustomRoles.Ventguard:
+ case CustomRoles.Workaholic:
+ result += "Dedicated";
+ break;
+ case CustomRoles.Addict:
+ case CustomRoles.Cultist:
+ case CustomRoles.Deceiver:
+ case CustomRoles.Devourer:
+ case CustomRoles.Doppelganger:
+ case CustomRoles.Follower:
+ case CustomRoles.Gangster:
+ case CustomRoles.Greedy:
+ case CustomRoles.Hangman:
+ case CustomRoles.Hater:
+ case CustomRoles.Inhibitor:
+ case CustomRoles.Jinx:
+ case CustomRoles.Kamikaze:
+ case CustomRoles.LazyGuy:
+ case CustomRoles.Ludopath:
+ case CustomRoles.Lurker:
+ case CustomRoles.Mini:
+ case CustomRoles.Mole:
+ case CustomRoles.Nemesis:
+ case CustomRoles.Pacifist:
+ case CustomRoles.Provocateur:
+ case CustomRoles.PunchingBag:
+ case CustomRoles.Puppeteer:
+ case CustomRoles.Pyromaniac:
+ case CustomRoles.Revolutionist:
+ case CustomRoles.Saboteur:
+ case CustomRoles.Sacrifist:
+ case CustomRoles.Snitch:
+ case CustomRoles.Spy:
+ case CustomRoles.Stalker:
+ case CustomRoles.Swapper:
+ case CustomRoles.Taskinator:
+ case CustomRoles.Terrorist:
+ case CustomRoles.Traitor:
+ case CustomRoles.Troller:
+ case CustomRoles.Vigilante:
+ result += "Shunned";
+ break;
+ case CustomRoles.Altruist:
+ case CustomRoles.Amnesiac:
+ case CustomRoles.Anonymous:
+ case CustomRoles.Butcher:
+ case CustomRoles.Cleaner:
+ case CustomRoles.Coroner:
+ case CustomRoles.CursedSoul:
+ case CustomRoles.Detective:
+ case CustomRoles.Doctor:
+ case CustomRoles.Medium:
+ case CustomRoles.Mortician:
+ case CustomRoles.Necromancer:
+ case CustomRoles.Pelican:
+ case CustomRoles.Scavenger:
+ case CustomRoles.SoulCollector:
+ case CustomRoles.Spiritcaller:
+ case CustomRoles.Spiritualist:
+ case CustomRoles.Tracefinder:
+ case CustomRoles.Trapster:
+ case CustomRoles.Undertaker:
+ case CustomRoles.Vulture:
+ case CustomRoles.Witness:
+ case CustomRoles.Zombie:
+ result += "Bodies";
+ break;
+ case CustomRoles.Admirer:
+ case CustomRoles.Bard:
+ case CustomRoles.Bastion:
+ case CustomRoles.Collector:
+ case CustomRoles.Crewpostor:
+ case CustomRoles.Crusader:
+ case CustomRoles.CursedWolf:
+ case CustomRoles.DollMaster:
+ case CustomRoles.Enigma:
+ case CustomRoles.Grenadier:
+ case CustomRoles.Innocent:
+ case CustomRoles.Jester:
+ case CustomRoles.Mastermind:
+ case CustomRoles.Mercenary:
+ case CustomRoles.Penguin:
+ case CustomRoles.Pursuer:
+ case CustomRoles.Randomizer:
+ case CustomRoles.Refugee:
+ case CustomRoles.Retributionist:
+ case CustomRoles.Revenant:
+ case CustomRoles.Reverie:
+ case CustomRoles.Romantic:
+ case CustomRoles.RuthlessRomantic:
+ case CustomRoles.VengefulRomantic:
+ case CustomRoles.Shaman:
+ case CustomRoles.Underdog:
+ case CustomRoles.VoodooMaster:
+ case CustomRoles.Werewolf:
+ result += "Misunderstood";
+ break;
+ case CustomRoles.Solsticer:
+ result += "Obvious";
+ break;
+ default:
+ result += "Unknown";
+ break;
+ }
+ return GetString(result);
+ }
+ public static string ObserveRolesMsg(PlayerControl player) {
+ string result = "DoomsayerRoles.";
+ var role = player.GetCustomRole();
+ if (role.IsRevealingRole(player))
+ {
+ return string.Empty;
+ }
+ if (role.IsGhostRole())
+ {
+ return GetString(result + "Dead");
+ }
+ if (Main.PlayerStates[player.PlayerId].IsNecromancer)
+ {
+ return GetString(result + "Bodies");
+ }
+ if (role.IsVanilla())
+ {
+ return GetString(result + "Basic");
+ }
+ switch (role)
+ {
+ case CustomRoles.Arrogance:
+ case CustomRoles.Berserker:
+ case CustomRoles.Blackmailer:
+ case CustomRoles.Bomber:
+ case CustomRoles.Captain:
+ case CustomRoles.ChiefOfPolice:
+ case CustomRoles.Councillor:
+ case CustomRoles.CovenLeader:
+ case CustomRoles.Death:
+ case CustomRoles.Demon:
+ case CustomRoles.Dictator:
+ case CustomRoles.God:
+ case CustomRoles.Godfather:
+ case CustomRoles.Famine:
+ case CustomRoles.Infectious:
+ case CustomRoles.Instigator:
+ case CustomRoles.Jailer:
+ case CustomRoles.Judge:
+ case CustomRoles.Mayor:
+ case CustomRoles.Marshall:
+ case CustomRoles.Monarch:
+ case CustomRoles.Parasite:
+ case CustomRoles.Pestilence:
+ case CustomRoles.Pitfall:
+ case CustomRoles.Poisoner:
+ case CustomRoles.President:
+ case CustomRoles.SerialKiller:
+ case CustomRoles.Shocker:
+ case CustomRoles.Sheriff:
+ case CustomRoles.Twister:
+ case CustomRoles.Vampire:
+ case CustomRoles.Vindicator:
+ case CustomRoles.Virus:
+ case CustomRoles.War:
+ result += "Fear";
+ break;
+ case CustomRoles.Abyssbringer:
+ case CustomRoles.Chameleon:
+ case CustomRoles.Chronomancer:
+ case CustomRoles.Conjurer:
+ case CustomRoles.Deathpact:
+ case CustomRoles.Eraser:
+ case CustomRoles.Guardian:
+ case CustomRoles.FortuneTeller:
+ case CustomRoles.HexMaster:
+ case CustomRoles.Lightning:
+ case CustomRoles.Medusa:
+ case CustomRoles.MoonDancer:
+ case CustomRoles.Observer:
+ case CustomRoles.Oracle:
+ case CustomRoles.Overseer:
+ case CustomRoles.Pixie:
+ case CustomRoles.Psychic:
+ case CustomRoles.RiftMaker:
+ case CustomRoles.ShapeMaster:
+ case CustomRoles.SoulCatcher:
+ case CustomRoles.Specter:
+ case CustomRoles.Swooper:
+ case CustomRoles.TimeMaster:
+ case CustomRoles.Transporter:
+ case CustomRoles.Warlock:
+ case CustomRoles.Wildling:
+ case CustomRoles.Witch:
+ case CustomRoles.Wraith:
+ case CustomRoles.YinYanger:
+ result += "Magic";
+ break;
+ case CustomRoles.Alchemist:
+ case CustomRoles.Baker:
+ case CustomRoles.Camouflager:
+ case CustomRoles.Celebrity:
+ case CustomRoles.Cleanser:
+ case CustomRoles.Consigliere:
+ case CustomRoles.CopyCat:
+ case CustomRoles.Dazzler:
+ case CustomRoles.Deputy:
+ case CustomRoles.Doomsayer:
+ case CustomRoles.EvilGuesser:
+ case CustomRoles.EvilHacker:
+ case CustomRoles.EvilTracker:
+ case CustomRoles.Inspector:
+ case CustomRoles.Investigator:
+ case CustomRoles.Keeper:
+ case CustomRoles.Knight:
+ case CustomRoles.Lookout:
+ case CustomRoles.Mechanic:
+ case CustomRoles.Medic:
+ case CustomRoles.Merchant:
+ case CustomRoles.NiceGuesser:
+ case CustomRoles.Pickpocket:
+ case CustomRoles.PlagueDoctor:
+ case CustomRoles.PlagueBearer:
+ case CustomRoles.PotionMaster:
+ case CustomRoles.QuickShooter:
+ case CustomRoles.Ritualist:
+ case CustomRoles.Sniper:
+ case CustomRoles.Stealth:
+ case CustomRoles.TaskManager:
+ case CustomRoles.Telecommunication:
+ case CustomRoles.TimeThief:
+ case CustomRoles.Veteran:
+ case CustomRoles.Visionary:
+ result += "Skilled";
+ break;
+ case CustomRoles.Agitater:
+ case CustomRoles.AntiAdminer:
+ case CustomRoles.Bandit:
+ case CustomRoles.Benefactor:
+ case CustomRoles.Bodyguard:
+ case CustomRoles.BountyHunter:
+ case CustomRoles.Disperser:
+ case CustomRoles.DoubleAgent:
+ case CustomRoles.Escapist:
+ case CustomRoles.Fireworker:
+ case CustomRoles.Huntsman:
+ case CustomRoles.Imitator:
+ case CustomRoles.Jackal:
+ case CustomRoles.KillingMachine:
+ case CustomRoles.Lawyer:
+ case CustomRoles.Lighter:
+ case CustomRoles.Maverick:
+ case CustomRoles.Miner:
+ case CustomRoles.Ninja:
+ case CustomRoles.Opportunist:
+ case CustomRoles.Quizmaster:
+ case CustomRoles.Seeker:
+ case CustomRoles.TimeManager:
+ case CustomRoles.Vector:
+ case CustomRoles.Ventguard:
+ case CustomRoles.Workaholic:
+ result += "Dedicated";
+ break;
+ case CustomRoles.Addict:
+ case CustomRoles.Cultist:
+ case CustomRoles.Deceiver:
+ case CustomRoles.Devourer:
+ case CustomRoles.Doppelganger:
+ case CustomRoles.Follower:
+ case CustomRoles.Gangster:
+ case CustomRoles.Greedy:
+ case CustomRoles.Hangman:
+ case CustomRoles.Hater:
+ case CustomRoles.Inhibitor:
+ case CustomRoles.Jinx:
+ case CustomRoles.Kamikaze:
+ case CustomRoles.LazyGuy:
+ case CustomRoles.Ludopath:
+ case CustomRoles.Lurker:
+ case CustomRoles.Mini:
+ case CustomRoles.Mole:
+ case CustomRoles.Nemesis:
+ case CustomRoles.Pacifist:
+ case CustomRoles.Provocateur:
+ case CustomRoles.PunchingBag:
+ case CustomRoles.Puppeteer:
+ case CustomRoles.Pyromaniac:
+ case CustomRoles.Revolutionist:
+ case CustomRoles.Saboteur:
+ case CustomRoles.Sacrifist:
+ case CustomRoles.Snitch:
+ case CustomRoles.Spy:
+ case CustomRoles.Stalker:
+ case CustomRoles.Swapper:
+ case CustomRoles.Taskinator:
+ case CustomRoles.Terrorist:
+ case CustomRoles.Traitor:
+ case CustomRoles.Troller:
+ case CustomRoles.Vigilante:
+ result += "Shunned";
+ break;
+ case CustomRoles.Altruist:
+ case CustomRoles.Amnesiac:
+ case CustomRoles.Anonymous:
+ case CustomRoles.Butcher:
+ case CustomRoles.Cleaner:
+ case CustomRoles.Coroner:
+ case CustomRoles.CursedSoul:
+ case CustomRoles.Detective:
+ case CustomRoles.Doctor:
+ case CustomRoles.Medium:
+ case CustomRoles.Mortician:
+ case CustomRoles.Necromancer:
+ case CustomRoles.Pelican:
+ case CustomRoles.Scavenger:
+ case CustomRoles.SoulCollector:
+ case CustomRoles.Spiritcaller:
+ case CustomRoles.Spiritualist:
+ case CustomRoles.Tracefinder:
+ case CustomRoles.Trapster:
+ case CustomRoles.Undertaker:
+ case CustomRoles.Vulture:
+ case CustomRoles.Witness:
+ case CustomRoles.Zombie:
+ result += "Bodies";
+ break;
+ case CustomRoles.Admirer:
+ case CustomRoles.Bard:
+ case CustomRoles.Bastion:
+ case CustomRoles.Collector:
+ case CustomRoles.Crewpostor:
+ case CustomRoles.Crusader:
+ case CustomRoles.CursedWolf:
+ case CustomRoles.DollMaster:
+ case CustomRoles.Enigma:
+ case CustomRoles.Grenadier:
+ case CustomRoles.Innocent:
+ case CustomRoles.Jester:
+ case CustomRoles.Mastermind:
+ case CustomRoles.Mercenary:
+ case CustomRoles.Penguin:
+ case CustomRoles.Pursuer:
+ case CustomRoles.Randomizer:
+ case CustomRoles.Refugee:
+ case CustomRoles.Retributionist:
+ case CustomRoles.Revenant:
+ case CustomRoles.Reverie:
+ case CustomRoles.Romantic:
+ case CustomRoles.RuthlessRomantic:
+ case CustomRoles.VengefulRomantic:
+ case CustomRoles.Shaman:
+ case CustomRoles.Underdog:
+ case CustomRoles.VoodooMaster:
+ case CustomRoles.Werewolf:
+ result += "Misunderstood";
+ break;
+ default: // also includes schrodinger's cat, glitch, illusionist, and trickster
+ result += "Unknown";
+ break;
+ }
+ if (result.Contains("Unknown")) return string.Empty;
+ return GetString(result);
+ }
+ public override void OnMeetingHudStart(PlayerControl pc)
+ {
+ if (MsgToSend.ContainsKey(pc.PlayerId))
+ {
+ foreach (var msg in MsgToSend[pc.PlayerId])
+ {
+ AddMsg(msg, pc.PlayerId, ColorString(GetRoleColor(CustomRoles.Doomsayer), GetString("DoomsayerObserveTitle")));
+ }
+ }
+ }
}
From ed43d8597b0fa28533603cb6969111b508d82fa9 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Wed, 12 Feb 2025 17:49:42 -0500
Subject: [PATCH 2/8] add kill button text
---
Resources/Lang/en_US.json | 2 ++
Roles/Neutral/Doomsayer.cs | 13 ++++++++++---
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json
index 574e2e059b..5f2693469d 100644
--- a/Resources/Lang/en_US.json
+++ b/Resources/Lang/en_US.json
@@ -3745,6 +3745,8 @@
"DoomsayerGuessCountTitle": "DOOMSAYER",
"DoomsayerGuessSameRoleAgainMsg": "You tried to guess the same Role or Add-on that you guessed before",
"DoomsayerObserveTitle": "OBSERVATION RESULTS",
+ "DoomsayerKillButtonText": "Observe",
+ "DoomsayerObserveNotif": "{0} observed",
"DoomsayerObserve.Basic": "Your observation of {0} shows that they live an ordinary life.",
"DoomsayerRoles.Basic": "(Impostor, Shapeshifter, Phantom, Crewmate, Scientist, Engineer, Tracker, Noisemaker)",
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index 03c297122b..d5c0583c8f 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -69,7 +69,7 @@ public override void SetupCustomOption()
ObserveCooldown = FloatOptionItem.Create(Id + 29, "DoomsayerObserveCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false).SetParent(EasyMode)
.SetValueFormat(OptionFormat.Seconds);
EvenEasierMode = BooleanOptionItem.Create(Id + 28, "DoomsayerEvenEasierMode", false, TabGroup.NeutralRoles, true)
- .SetParent(EasyMode);
+ .SetParent(EasyMode).SetHidden(true);
AdvancedSettings = BooleanOptionItem.Create(Id + 16, "DoomsayerAdvancedSettings", true, TabGroup.NeutralRoles, true)
.SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
@@ -295,14 +295,21 @@ public override bool ForcedCheckMurderAsKiller(PlayerControl killer, PlayerContr
if (killer == null || target == null) return false;
if (!EasyMode.GetBool()) return false;
if (!EvenEasierMode.GetBool()) MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()));
- else MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()) + " " + ObserveRolesMsg(target));
+ else MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()) + "
" + ObserveRolesMsg(target) + "");
+ killer.Notify(string.Format(GetString("DoomsayerObserveNotif"), target.GetRealName()));
+ killer.ResetKillCooldown();
+ killer.SetKillCooldown();
return false;
}
+ public override void SetAbilityButtonText(HudManager hud, byte playerId)
+ {
+ hud.KillButton?.OverrideText(GetString("DoomsayerKillButtonText"));
+ }
// i hate this code so much no wonder why we reworked fortune teller, oh well, here we go again
public static string ObserveRiddleMsg(PlayerControl player)
{
- string result = "DoomsayerRoles.";
+ string result = "DoomsayerObserve.";
var role = player.GetCustomRole();
if (role.IsGhostRole())
{
From c45c3213c9e0f1a709b9ba2807d557944d259470 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Sun, 16 Feb 2025 17:25:20 -0500
Subject: [PATCH 3/8] kill cooldown fix
---
Roles/Neutral/Doomsayer.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index d5c0583c8f..0fab6e9144 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -288,7 +288,7 @@ public void SendMessageAboutGuess(PlayerControl guesser, PlayerControl playerMis
}
}
public override bool CanUseKillButton(PlayerControl pc) => EasyMode.GetBool();
- public override void SetKillCooldown(byte id) => ObserveCooldown.GetFloat();
+ public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = ObserveCooldown.GetFloat();
public override bool ForcedCheckMurderAsKiller(PlayerControl killer, PlayerControl target)
{
From e9de869eb45ee82a5301f51fba1452f983e30488 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Wed, 19 Mar 2025 17:10:11 -0400
Subject: [PATCH 4/8] changed it to use Custom_RoleTypes with a few exceptions
---
Resources/Lang/en_US.json | 18 +-
Roles/Neutral/Doomsayer.cs | 523 +++----------------------------------
2 files changed, 44 insertions(+), 497 deletions(-)
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json
index 8de19667d4..c3bd902185 100644
--- a/Resources/Lang/en_US.json
+++ b/Resources/Lang/en_US.json
@@ -3763,7 +3763,6 @@
"DoomsayerAdvancedSettings": "Advanced Settings",
"DoomsayerEasyMode": "Easy Mode (Can Get Hints)",
"DoomsayerObserveCooldown": "Observe Cooldown",
- "DoomsayerEvenEasierMode": "Even Easier Mode (Hints Show Possible Roles)",
"DoomsayerMaxNumberOfGuessesPerMeeting": "Maximum number of guesses per meeting",
"DoomsayerKillCorrectlyGuessedPlayers": "Kill correctly guessed players",
"DoomsayerDoesNotSuicideWhenMisguessing": "Doomsayer does not suicide when misguessing",
@@ -3779,25 +3778,14 @@
"DoomsayerKillButtonText": "Observe",
"DoomsayerObserveNotif": "{0} observed",
- "DoomsayerObserve.Basic": "Your observation of {0} shows that they live an ordinary life.",
- "DoomsayerRoles.Basic": "(Impostor, Shapeshifter, Phantom, Crewmate, Scientist, Engineer, Tracker, Noisemaker)",
+ "DoomsayerObserve.Basic": "Your observation of {0} shows that they live a mostly ordinary life.",
"DoomsayerObserve.Fear": "Your observation of {0} shows that they are feared by many.",
- "DoomsayerRoles.Fear": "(Arrogance, Berserker, Blackmailer, Bomber, Captain, Councillor, Coven Leader, Death, Demon, Dictator, God, Godfather, Famine, Infectious, Instigator, Jailer, Judge, Mayor, Marshall, Monarch, Parasite, Pestilence, Pitfall, Poisoner, President, Serial Killer, Sheriff, Twister, Vampire, Vindicator, Virus, War)",
- "DoomsayerObserve.Magic": "Your observation of {0} shows that they posses some sort of magical power.",
- "DoomsayerRoles.Magic": "(Chameleon, Chronomancer, Conjurer, Deathpact, Eraser, Guardian, Fortune Teller, Hex Master, Lightning, Medusa, Moon Dancer, Observer, Oracle, Overseer, Pixie, Psychic, Rift Maker, Shapemaster, Soul Catcher, Specter, Swooper, Time Master, Transporter, Warlock, Wildling, Witch, Wraith, YinYanger)",
"DoomsayerObserve.Skilled": "Your observation of {0} shows that they are very skilled in their craft.",
- "DoomsayerRoles.Skilled": "(Alchemist, Baker, Camouflager, Celebrity, Cleanser, Consigliere, Copycat, Dazzler, Deputy, Doomsayer, Evil Guesser, Evil Hacker, Evil Tracker, Inspector, Investigator, Keeper, Knight, Lookout, Mechanic, Medic, Merchant, Nice Guesser, Pickpocket, Plague Scientist, Plaguebearer, Potion Master, Quick Shooter, Ritualist, Sniper, Stealth, Task Manager, Telecommunication, Time Thief, Veteran, Visionary)",
"DoomsayerObserve.Dedicated": "Your observation of {0} shows that they are very dedicated to their job.",
- "DoomsayerRoles.Dedicated": "(Agitator, Anti Adminer, Bandit, Benefactor, Bodyguard, Bounty Hunter, Disperser, Double Agent, Escapist, Fireworker, Huntsman, Imitator, Jackal, Killing Machine, Lawyer, Lighter, Maverick, Miner, Ninja, Opportunist, Quizmaster, Seeker, Time Manager, Vector, Ventguard, Workaholic)",
- "DoomsayerObserve.Shunned": "Your observation of {0} shows that they are shunned by society.",
- "DoomsayerRoles.Shunned": "(Addict, Cultist, Deceiver, Devourer, Doppelganger, Follower, Gangster, Greedy, Hangman, Hater, Inhibitor, Jinx, Kamikaze, Lazy Guy, Ludopath, Lurker, Mini, Mole, Nemesis, Pacifist, Provocatuer, Punching Bag, Puppeteer, Pyromaniac, Revolutionist, Saboteur, Sacrifist, Snitch, Spy, Stalker, Swapper, Taskinator, Terrorist, Traitor, Troller, Vigilante)",
- "DoomsayerObserve.Bodies": "Your observation of {0} shows that they have some sort of obsession with dead people...",
- "DoomsayerRoles.Bodies": "(Altruist, Amnesiac, Anonymous, Butcher, Cleaner, Coroner, Cursed Soul, Detective, Doctor, Medium, Mortician, Necromancer, Pelican, Scavenger, Soul Collector, Spiritcaller, Spiritualist, Tracefinder, Trapster, Undertaker, Vulture, Witness, Zombie)",
+ "DoomsayerObserve.Secret": "Your observation of {0} shows that they are hiding a secret.",
"DoomsayerObserve.Dead": "Your observation of {0} shows that they are dead...",
- "DoomsayerRoles.Dead": "(Any Ghost Role)",
- "DoomsayerObserve.Misunderstood": "Your observation of {0} shows that they are misunderstood.",
- "DoomsayerRoles.Misunderstood": "(Admirer, Bard, Bastion, Collector, Crewpostor, Crusader, Cursed Wolf, Doll Master, Enigma, Grenadier, Innocent, Jester, Mastermind, Mercenary, Penguin, Pursuer, Randomizer, Refugee, Retributionist, Reverie, Romantic, Ruthless Romantic, Shaman, Underdog, Vengeful Romantic, Voodoo Master, Werewolf)",
"DoomsayerObserve.Unknown": "You are unable to comprehend your observation of {0}...",
+ "DoomsayerObserve.GM": "It should not be possible to be able to Observe the Game Master. If you somehow got this string, screenshot it and ping Marg so she can laugh about it.",
"DoomsayerObserve.Obvious": "Good job, you wasted your observation on {0}, considering anyone can see it with their own two eyes...",
"EveryoneCanKnowMini": "Everyone can see the Mini",
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index 789ebc18b0..e13778f8a6 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -2,6 +2,7 @@
using System.Text;
using TOHE.Modules;
using TOHE.Roles.Core;
+using TOHE.Roles.Coven;
using TOHE.Roles.Crewmate;
using UnityEngine;
using static TOHE.MeetingHudStartPatch;
@@ -35,7 +36,6 @@ internal class Doomsayer : RoleBase
private static OptionItem DoomsayerTryHideMsg;
private static OptionItem ImpostorVision;
private static OptionItem EasyMode;
- private static OptionItem EvenEasierMode;
private static OptionItem ObserveCooldown;
private readonly HashSet GuessedRoles = [];
@@ -68,8 +68,7 @@ public override void SetupCustomOption()
.SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
ObserveCooldown = FloatOptionItem.Create(Id + 29, "DoomsayerObserveCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false).SetParent(EasyMode)
.SetValueFormat(OptionFormat.Seconds);
- EvenEasierMode = BooleanOptionItem.Create(Id + 28, "DoomsayerEvenEasierMode", false, TabGroup.NeutralRoles, true)
- .SetParent(EasyMode).SetHidden(true);
+
AdvancedSettings = BooleanOptionItem.Create(Id + 16, "DoomsayerAdvancedSettings", true, TabGroup.NeutralRoles, true)
.SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
@@ -274,8 +273,7 @@ public override bool ForcedCheckMurderAsKiller(PlayerControl killer, PlayerContr
{
if (killer == null || target == null) return false;
if (!EasyMode.GetBool()) return false;
- if (!EvenEasierMode.GetBool()) MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()));
- else MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()) + "
" + ObserveRolesMsg(target) + "");
+ MsgToSend[killer.PlayerId].Add(string.Format(ObserveRiddleMsg(target), target.GetRealName()));
killer.Notify(string.Format(GetString("DoomsayerObserveNotif"), target.GetRealName()));
killer.ResetKillCooldown();
killer.SetKillCooldown();
@@ -291,509 +289,70 @@ public static string ObserveRiddleMsg(PlayerControl player)
{
string result = "DoomsayerObserve.";
var role = player.GetCustomRole();
+ if (role == CustomRoles.GM)
+ {
+ return GetString(result + "GM");
+ }
if (role.IsGhostRole())
{
return GetString(result + "Dead");
}
- if (Main.PlayerStates[player.PlayerId].IsNecromancer)
+ if (Main.PlayerStates[player.PlayerId].IsNecromancer || Illusionist.IsNonCovIllusioned(player.PlayerId)|| role is CustomRoles.SchrodingersCat or CustomRoles.Glitch)
{
- return GetString(result + "Bodies");
+ return GetString(result + "Unknown");
}
- if (role.IsVanilla())
+ if (role.IsVanilla() || Illusionist.IsCovIllusioned(player.PlayerId) || role == CustomRoles.Trickster)
{
return GetString(result + "Basic");
}
- if (role.IsRevealingRole(player))
+ if (role.IsRevealingRole(player) || role == CustomRoles.Solsticer)
{
return GetString(result + "Obvious");
}
- switch (role)
+ if (DCanGuessAdt.GetBool() && player.IsAnySubRole(sub => sub.IsConverted()))
{
- case CustomRoles.Arrogance:
- case CustomRoles.Berserker:
- case CustomRoles.Blackmailer:
- case CustomRoles.Bomber:
- case CustomRoles.Captain:
- case CustomRoles.ChiefOfPolice:
- case CustomRoles.Councillor:
- case CustomRoles.CovenLeader:
- case CustomRoles.Death:
- case CustomRoles.Demon:
- case CustomRoles.Dictator:
- case CustomRoles.God:
- case CustomRoles.Godfather:
- case CustomRoles.Famine:
- case CustomRoles.Infectious:
- case CustomRoles.Instigator:
- case CustomRoles.Jailer:
- case CustomRoles.Judge:
- case CustomRoles.Mayor:
- case CustomRoles.Marshall:
- case CustomRoles.Monarch:
- case CustomRoles.Parasite:
- case CustomRoles.Pestilence:
- case CustomRoles.Pitfall:
- case CustomRoles.Poisoner:
- case CustomRoles.President:
- case CustomRoles.SerialKiller:
- case CustomRoles.Shocker:
- case CustomRoles.Sheriff:
- case CustomRoles.Twister:
- case CustomRoles.Vampire:
- case CustomRoles.Vindicator:
- case CustomRoles.Virus:
- case CustomRoles.War:
- result += "Fear";
- break;
- case CustomRoles.Abyssbringer:
- case CustomRoles.Chameleon:
- case CustomRoles.Chronomancer:
- case CustomRoles.Conjurer:
- case CustomRoles.Deathpact:
- case CustomRoles.Eraser:
- case CustomRoles.Guardian:
- case CustomRoles.FortuneTeller:
- case CustomRoles.HexMaster:
- case CustomRoles.Lightning:
- case CustomRoles.Medusa:
- case CustomRoles.MoonDancer:
- case CustomRoles.Observer:
- case CustomRoles.Oracle:
- case CustomRoles.Overseer:
- case CustomRoles.Pixie:
- case CustomRoles.Psychic:
- case CustomRoles.RiftMaker:
- case CustomRoles.ShapeMaster:
- case CustomRoles.SoulCatcher:
- case CustomRoles.Specter:
- case CustomRoles.Swooper:
- case CustomRoles.TimeMaster:
- case CustomRoles.Transporter:
- case CustomRoles.Warlock:
- case CustomRoles.Wildling:
- case CustomRoles.Witch:
- case CustomRoles.Wraith:
- case CustomRoles.YinYanger:
- result += "Magic";
- break;
- case CustomRoles.Alchemist:
- case CustomRoles.Baker:
- case CustomRoles.Camouflager:
- case CustomRoles.Celebrity:
- case CustomRoles.Cleanser:
- case CustomRoles.Consigliere:
- case CustomRoles.CopyCat:
- case CustomRoles.Dazzler:
- case CustomRoles.Deputy:
- case CustomRoles.Doomsayer:
- case CustomRoles.EvilGuesser:
- case CustomRoles.EvilHacker:
- case CustomRoles.EvilTracker:
- case CustomRoles.Inspector:
- case CustomRoles.Investigator:
- case CustomRoles.Keeper:
- case CustomRoles.Knight:
- case CustomRoles.Lookout:
- case CustomRoles.Mechanic:
- case CustomRoles.Medic:
- case CustomRoles.Merchant:
- case CustomRoles.NiceGuesser:
- case CustomRoles.Pickpocket:
- case CustomRoles.PlagueDoctor:
- case CustomRoles.PlagueBearer:
- case CustomRoles.PotionMaster:
- case CustomRoles.QuickShooter:
- case CustomRoles.Ritualist:
- case CustomRoles.Sniper:
- case CustomRoles.Stealth:
- case CustomRoles.TaskManager:
- case CustomRoles.Telecommunication:
- case CustomRoles.TimeThief:
- case CustomRoles.Veteran:
- case CustomRoles.Visionary:
- result += "Skilled";
- break;
- case CustomRoles.Agitater:
- case CustomRoles.AntiAdminer:
- case CustomRoles.Bandit:
- case CustomRoles.Benefactor:
- case CustomRoles.Bodyguard:
- case CustomRoles.BountyHunter:
- case CustomRoles.Disperser:
- case CustomRoles.DoubleAgent:
- case CustomRoles.Escapist:
- case CustomRoles.Fireworker:
- case CustomRoles.Huntsman:
- case CustomRoles.Imitator:
- case CustomRoles.Jackal:
- case CustomRoles.KillingMachine:
- case CustomRoles.Lawyer:
- case CustomRoles.Lighter:
- case CustomRoles.Maverick:
- case CustomRoles.Miner:
- case CustomRoles.Ninja:
- case CustomRoles.Opportunist:
- case CustomRoles.Quizmaster:
- case CustomRoles.Seeker:
- case CustomRoles.TimeManager:
- case CustomRoles.Vector:
- case CustomRoles.Ventguard:
- case CustomRoles.Workaholic:
- result += "Dedicated";
- break;
- case CustomRoles.Addict:
- case CustomRoles.Cultist:
- case CustomRoles.Deceiver:
- case CustomRoles.Devourer:
- case CustomRoles.Doppelganger:
- case CustomRoles.Follower:
- case CustomRoles.Gangster:
- case CustomRoles.Greedy:
- case CustomRoles.Hangman:
- case CustomRoles.Hater:
- case CustomRoles.Inhibitor:
- case CustomRoles.Jinx:
- case CustomRoles.Kamikaze:
- case CustomRoles.LazyGuy:
- case CustomRoles.Ludopath:
- case CustomRoles.Lurker:
- case CustomRoles.Mini:
- case CustomRoles.Mole:
- case CustomRoles.Nemesis:
- case CustomRoles.Pacifist:
- case CustomRoles.Provocateur:
- case CustomRoles.PunchingBag:
- case CustomRoles.Puppeteer:
- case CustomRoles.Pyromaniac:
- case CustomRoles.Revolutionist:
- case CustomRoles.Saboteur:
- case CustomRoles.Sacrifist:
- case CustomRoles.Snitch:
- case CustomRoles.Spy:
- case CustomRoles.Stalker:
- case CustomRoles.Swapper:
- case CustomRoles.Taskinator:
- case CustomRoles.Terrorist:
- case CustomRoles.Traitor:
- case CustomRoles.Troller:
- case CustomRoles.Vigilante:
- result += "Shunned";
- break;
- case CustomRoles.Altruist:
- case CustomRoles.Amnesiac:
- case CustomRoles.Anonymous:
- case CustomRoles.Butcher:
- case CustomRoles.Cleaner:
- case CustomRoles.Coroner:
- case CustomRoles.CursedSoul:
- case CustomRoles.Detective:
- case CustomRoles.Doctor:
- case CustomRoles.Medium:
- case CustomRoles.Mortician:
- case CustomRoles.Necromancer:
- case CustomRoles.Pelican:
- case CustomRoles.Scavenger:
- case CustomRoles.SoulCollector:
- case CustomRoles.Spiritcaller:
- case CustomRoles.Spiritualist:
- case CustomRoles.Tracefinder:
- case CustomRoles.Trapster:
- case CustomRoles.Undertaker:
- case CustomRoles.Vulture:
- case CustomRoles.Witness:
- case CustomRoles.Zombie:
- result += "Bodies";
- break;
- case CustomRoles.Admirer:
- case CustomRoles.Bard:
- case CustomRoles.Bastion:
- case CustomRoles.Collector:
- case CustomRoles.Crewpostor:
- case CustomRoles.Crusader:
- case CustomRoles.CursedWolf:
- case CustomRoles.DollMaster:
- case CustomRoles.Enigma:
- case CustomRoles.Grenadier:
- case CustomRoles.Innocent:
- case CustomRoles.Jester:
- case CustomRoles.Mastermind:
- case CustomRoles.Mercenary:
- case CustomRoles.Penguin:
- case CustomRoles.Pursuer:
- case CustomRoles.Randomizer:
- case CustomRoles.Refugee:
- case CustomRoles.Retributionist:
- case CustomRoles.Revenant:
- case CustomRoles.Reverie:
- case CustomRoles.Romantic:
- case CustomRoles.RuthlessRomantic:
- case CustomRoles.VengefulRomantic:
- case CustomRoles.Shaman:
- case CustomRoles.Underdog:
- case CustomRoles.VoodooMaster:
- case CustomRoles.Werewolf:
- result += "Misunderstood";
- break;
- case CustomRoles.Solsticer:
- result += "Obvious";
- break;
- default:
- result += "Unknown";
- break;
+ return GetString(result + "Secret");
}
- return GetString(result);
- }
- public static string ObserveRolesMsg(PlayerControl player) {
- string result = "DoomsayerRoles.";
- var role = player.GetCustomRole();
- if (role.IsRevealingRole(player))
+ if (role == CustomRoles.God)
{
- return string.Empty;
- }
- if (role.IsGhostRole())
- {
- return GetString(result + "Dead");
+ return GetString(result + "Fear");
}
- if (Main.PlayerStates[player.PlayerId].IsNecromancer)
+ switch (role.GetCustomRoleType())
{
- return GetString(result + "Bodies");
- }
- if (role.IsVanilla())
- {
- return GetString(result + "Basic");
- }
- switch (role)
- {
- case CustomRoles.Arrogance:
- case CustomRoles.Berserker:
- case CustomRoles.Blackmailer:
- case CustomRoles.Bomber:
- case CustomRoles.Captain:
- case CustomRoles.ChiefOfPolice:
- case CustomRoles.Councillor:
- case CustomRoles.CovenLeader:
- case CustomRoles.Death:
- case CustomRoles.Demon:
- case CustomRoles.Dictator:
- case CustomRoles.God:
- case CustomRoles.Godfather:
- case CustomRoles.Famine:
- case CustomRoles.Infectious:
- case CustomRoles.Instigator:
- case CustomRoles.Jailer:
- case CustomRoles.Judge:
- case CustomRoles.Mayor:
- case CustomRoles.Marshall:
- case CustomRoles.Monarch:
- case CustomRoles.Parasite:
- case CustomRoles.Pestilence:
- case CustomRoles.Pitfall:
- case CustomRoles.Poisoner:
- case CustomRoles.President:
- case CustomRoles.SerialKiller:
- case CustomRoles.Shocker:
- case CustomRoles.Sheriff:
- case CustomRoles.Twister:
- case CustomRoles.Vampire:
- case CustomRoles.Vindicator:
- case CustomRoles.Virus:
- case CustomRoles.War:
- result += "Fear";
+ case Custom_RoleType.CrewmateVanilla:
+ case Custom_RoleType.CrewmateBasic:
+ case Custom_RoleType.NeutralBenign:
+ case Custom_RoleType.ImpostorVanilla:
+ result += "Basic";
break;
- case CustomRoles.Abyssbringer:
- case CustomRoles.Chameleon:
- case CustomRoles.Chronomancer:
- case CustomRoles.Conjurer:
- case CustomRoles.Deathpact:
- case CustomRoles.Eraser:
- case CustomRoles.Guardian:
- case CustomRoles.FortuneTeller:
- case CustomRoles.HexMaster:
- case CustomRoles.Lightning:
- case CustomRoles.Medusa:
- case CustomRoles.MoonDancer:
- case CustomRoles.Observer:
- case CustomRoles.Oracle:
- case CustomRoles.Overseer:
- case CustomRoles.Pixie:
- case CustomRoles.Psychic:
- case CustomRoles.RiftMaker:
- case CustomRoles.ShapeMaster:
- case CustomRoles.SoulCatcher:
- case CustomRoles.Specter:
- case CustomRoles.Swooper:
- case CustomRoles.TimeMaster:
- case CustomRoles.Transporter:
- case CustomRoles.Warlock:
- case CustomRoles.Wildling:
- case CustomRoles.Witch:
- case CustomRoles.Wraith:
- case CustomRoles.YinYanger:
- result += "Magic";
- break;
- case CustomRoles.Alchemist:
- case CustomRoles.Baker:
- case CustomRoles.Camouflager:
- case CustomRoles.Celebrity:
- case CustomRoles.Cleanser:
- case CustomRoles.Consigliere:
- case CustomRoles.CopyCat:
- case CustomRoles.Dazzler:
- case CustomRoles.Deputy:
- case CustomRoles.Doomsayer:
- case CustomRoles.EvilGuesser:
- case CustomRoles.EvilHacker:
- case CustomRoles.EvilTracker:
- case CustomRoles.Inspector:
- case CustomRoles.Investigator:
- case CustomRoles.Keeper:
- case CustomRoles.Knight:
- case CustomRoles.Lookout:
- case CustomRoles.Mechanic:
- case CustomRoles.Medic:
- case CustomRoles.Merchant:
- case CustomRoles.NiceGuesser:
- case CustomRoles.Pickpocket:
- case CustomRoles.PlagueDoctor:
- case CustomRoles.PlagueBearer:
- case CustomRoles.PotionMaster:
- case CustomRoles.QuickShooter:
- case CustomRoles.Ritualist:
- case CustomRoles.Sniper:
- case CustomRoles.Stealth:
- case CustomRoles.TaskManager:
- case CustomRoles.Telecommunication:
- case CustomRoles.TimeThief:
- case CustomRoles.Veteran:
- case CustomRoles.Visionary:
- result += "Skilled";
+ case Custom_RoleType.CrewmatePower:
+ case Custom_RoleType.CovenPower:
+ case Custom_RoleType.NeutralApocalypse:
+ result += "Fear";
break;
- case CustomRoles.Agitater:
- case CustomRoles.AntiAdminer:
- case CustomRoles.Bandit:
- case CustomRoles.Benefactor:
- case CustomRoles.Bodyguard:
- case CustomRoles.BountyHunter:
- case CustomRoles.Disperser:
- case CustomRoles.DoubleAgent:
- case CustomRoles.Escapist:
- case CustomRoles.Fireworker:
- case CustomRoles.Huntsman:
- case CustomRoles.Imitator:
- case CustomRoles.Jackal:
- case CustomRoles.KillingMachine:
- case CustomRoles.Lawyer:
- case CustomRoles.Lighter:
- case CustomRoles.Maverick:
- case CustomRoles.Miner:
- case CustomRoles.Ninja:
- case CustomRoles.Opportunist:
- case CustomRoles.Quizmaster:
- case CustomRoles.Seeker:
- case CustomRoles.TimeManager:
- case CustomRoles.Vector:
- case CustomRoles.Ventguard:
- case CustomRoles.Workaholic:
+ case Custom_RoleType.CrewmateSupport:
+ case Custom_RoleType.CovenUtility:
+ case Custom_RoleType.ImpostorSupport:
+ case Custom_RoleType.NeutralEvil:
+ case Custom_RoleType.NeutralChaos:
result += "Dedicated";
break;
- case CustomRoles.Addict:
- case CustomRoles.Cultist:
- case CustomRoles.Deceiver:
- case CustomRoles.Devourer:
- case CustomRoles.Doppelganger:
- case CustomRoles.Follower:
- case CustomRoles.Gangster:
- case CustomRoles.Greedy:
- case CustomRoles.Hangman:
- case CustomRoles.Hater:
- case CustomRoles.Inhibitor:
- case CustomRoles.Jinx:
- case CustomRoles.Kamikaze:
- case CustomRoles.LazyGuy:
- case CustomRoles.Ludopath:
- case CustomRoles.Lurker:
- case CustomRoles.Mini:
- case CustomRoles.Mole:
- case CustomRoles.Nemesis:
- case CustomRoles.Pacifist:
- case CustomRoles.Provocateur:
- case CustomRoles.PunchingBag:
- case CustomRoles.Puppeteer:
- case CustomRoles.Pyromaniac:
- case CustomRoles.Revolutionist:
- case CustomRoles.Saboteur:
- case CustomRoles.Sacrifist:
- case CustomRoles.Snitch:
- case CustomRoles.Spy:
- case CustomRoles.Stalker:
- case CustomRoles.Swapper:
- case CustomRoles.Taskinator:
- case CustomRoles.Terrorist:
- case CustomRoles.Traitor:
- case CustomRoles.Troller:
- case CustomRoles.Vigilante:
- result += "Shunned";
- break;
- case CustomRoles.Altruist:
- case CustomRoles.Amnesiac:
- case CustomRoles.Anonymous:
- case CustomRoles.Butcher:
- case CustomRoles.Cleaner:
- case CustomRoles.Coroner:
- case CustomRoles.CursedSoul:
- case CustomRoles.Detective:
- case CustomRoles.Doctor:
- case CustomRoles.Medium:
- case CustomRoles.Mortician:
- case CustomRoles.Necromancer:
- case CustomRoles.Pelican:
- case CustomRoles.Scavenger:
- case CustomRoles.SoulCollector:
- case CustomRoles.Spiritcaller:
- case CustomRoles.Spiritualist:
- case CustomRoles.Tracefinder:
- case CustomRoles.Trapster:
- case CustomRoles.Undertaker:
- case CustomRoles.Vulture:
- case CustomRoles.Witness:
- case CustomRoles.Zombie:
- result += "Bodies";
+ case Custom_RoleType.Madmate:
+ case Custom_RoleType.CovenTrickery:
+ case Custom_RoleType.ImpostorHindering:
+ case Custom_RoleType.ImpostorConcealing:
+ result += "Secret";
break;
- case CustomRoles.Admirer:
- case CustomRoles.Bard:
- case CustomRoles.Bastion:
- case CustomRoles.Collector:
- case CustomRoles.Crewpostor:
- case CustomRoles.Crusader:
- case CustomRoles.CursedWolf:
- case CustomRoles.DollMaster:
- case CustomRoles.Enigma:
- case CustomRoles.Grenadier:
- case CustomRoles.Innocent:
- case CustomRoles.Jester:
- case CustomRoles.Mastermind:
- case CustomRoles.Mercenary:
- case CustomRoles.Penguin:
- case CustomRoles.Pursuer:
- case CustomRoles.Randomizer:
- case CustomRoles.Refugee:
- case CustomRoles.Retributionist:
- case CustomRoles.Revenant:
- case CustomRoles.Reverie:
- case CustomRoles.Romantic:
- case CustomRoles.RuthlessRomantic:
- case CustomRoles.VengefulRomantic:
- case CustomRoles.Shaman:
- case CustomRoles.Underdog:
- case CustomRoles.VoodooMaster:
- case CustomRoles.Werewolf:
- result += "Misunderstood";
+ case Custom_RoleType.NeutralKilling:
+ case Custom_RoleType.CovenKilling:
+ case Custom_RoleType.ImpostorKilling:
+ case Custom_RoleType.CrewmateKilling:
+ result += "Skilled";
break;
- default: // also includes schrodinger's cat, glitch, illusionist, and trickster
+ default:
result += "Unknown";
break;
}
- if (result.Contains("Unknown")) return string.Empty;
return GetString(result);
}
public override void OnMeetingHudStart(PlayerControl pc)
From aed7175791ff0aa4045e3a4c3a3bdff054b612c0 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Sat, 22 Mar 2025 14:28:08 -0400
Subject: [PATCH 5/8] add IsDesyncRole
---
Roles/Neutral/Doomsayer.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index e13778f8a6..dca748a8a3 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -18,6 +18,7 @@ internal class Doomsayer : RoleBase
public override CustomRoles Role => CustomRoles.Doomsayer;
private const int Id = 14100;
public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Doomsayer);
+ public override bool IsDesyncRole => EasyMode.GetBool();
public override CustomRoles ThisRoleBase => EasyMode.GetBool() ? CustomRoles.Impostor : CustomRoles.Crewmate;
public override Custom_RoleType ThisRoleType => Custom_RoleType.NeutralEvil;
//==================================================================\\
From f2b1e6f6b4a0c549a43b090706651e57240cf458 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Sun, 13 Apr 2025 13:29:40 -0400
Subject: [PATCH 6/8] code cleanup
---
Roles/Neutral/Doomsayer.cs | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index 6238223c52..42d0f10168 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -3,7 +3,6 @@
using TOHE.Modules;
using TOHE.Roles.Core;
using TOHE.Roles.Coven;
-using TOHE.Roles.Crewmate;
using UnityEngine;
using static TOHE.MeetingHudStartPatch;
using static TOHE.Options;
@@ -69,7 +68,7 @@ public override void SetupCustomOption()
.SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
ObserveCooldown = FloatOptionItem.Create(Id + 29, "DoomsayerObserveCooldown", new(0f, 180f, 2.5f), 30f, TabGroup.NeutralRoles, false).SetParent(EasyMode)
.SetValueFormat(OptionFormat.Seconds);
-
+
AdvancedSettings = BooleanOptionItem.Create(Id + 16, "DoomsayerAdvancedSettings", true, TabGroup.NeutralRoles, true)
.SetParent(CustomRoleSpawnChances[CustomRoles.Doomsayer]);
@@ -285,7 +284,6 @@ public override void SetAbilityButtonText(HudManager hud, byte playerId)
hud.KillButton?.OverrideText(GetString("DoomsayerKillButtonText"));
}
- // i hate this code so much no wonder why we reworked fortune teller, oh well, here we go again
public static string ObserveRiddleMsg(PlayerControl player)
{
string result = "DoomsayerObserve.";
@@ -298,7 +296,7 @@ public static string ObserveRiddleMsg(PlayerControl player)
{
return GetString(result + "Dead");
}
- if (Main.PlayerStates[player.PlayerId].IsNecromancer || Illusionist.IsNonCovIllusioned(player.PlayerId)|| role is CustomRoles.SchrodingersCat or CustomRoles.Glitch)
+ if (Main.PlayerStates[player.PlayerId].IsNecromancer || Illusionist.IsNonCovIllusioned(player.PlayerId) || role is CustomRoles.SchrodingersCat or CustomRoles.Glitch)
{
return GetString(result + "Unknown");
}
@@ -320,10 +318,10 @@ public static string ObserveRiddleMsg(PlayerControl player)
}
switch (role.GetCustomRoleType())
{
- case Custom_RoleType.CrewmateVanilla:
- case Custom_RoleType.CrewmateBasic:
- case Custom_RoleType.NeutralBenign:
- case Custom_RoleType.ImpostorVanilla:
+ case Custom_RoleType.CrewmateVanilla:
+ case Custom_RoleType.CrewmateBasic:
+ case Custom_RoleType.NeutralBenign:
+ case Custom_RoleType.ImpostorVanilla:
result += "Basic";
break;
case Custom_RoleType.CrewmatePower:
From 4f6fb54be6f4ca573b8bc6f6b38b627b4ae96f19 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Tue, 15 Apr 2025 14:45:03 -0400
Subject: [PATCH 7/8] fix observes not clearing
---
Roles/Neutral/Doomsayer.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Roles/Neutral/Doomsayer.cs b/Roles/Neutral/Doomsayer.cs
index 42d0f10168..a13321aab9 100644
--- a/Roles/Neutral/Doomsayer.cs
+++ b/Roles/Neutral/Doomsayer.cs
@@ -364,4 +364,8 @@ public override void OnMeetingHudStart(PlayerControl pc)
}
}
}
+ public override void AfterMeetingTasks()
+ {
+ MsgToSend.Clear();
+ }
}
From bb18724f6dc1428a9290b6129d8a8ce2e54d7377 Mon Sep 17 00:00:00 2001
From: Marg <51059123+MargaretTheFool@users.noreply.github.com>
Date: Tue, 15 Apr 2025 15:48:57 -0400
Subject: [PATCH 8/8] edit InfoLong
---
Resources/Lang/en_US.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Resources/Lang/en_US.json b/Resources/Lang/en_US.json
index fd63aadbc6..00ab26faed 100644
--- a/Resources/Lang/en_US.json
+++ b/Resources/Lang/en_US.json
@@ -965,7 +965,7 @@
"BanditInfoLong": "(Neutrals):\nAs the Bandit, you can click your Kill button one time to steal a player's Add-on and twice to kill. Depending on the settings, you may instantly steal the Add-on or after the meeting starts. After the maximum number of steals is reached, you will kill normally. Additionally, if there are no stealable Add-ons on the target or the target is Stubborn, you will kill the target.\n\nKill everyone to win.\n\nNote: Cleansed, Last Impostor, and Lovers cannot be stolen.\nNote: If Bandit can Vent is on, Nimble will become unstealable.",
"DoppelgangerInfoLong": "(Neutrals):\nAs the Doppelganger, use your Kill button to steal a player's identity (their name and skin) and then kill your target.\n\nKill everyone to win.\n\nNote: You cannot steal the target's identity when Camouflage is active.",
"PunchingBagInfoLong": "(Neutrals):\nAs the Punching Bag, your goal is to get attacked a few times to win.\n\nYou cannot be guessed, as that adds to your attack count.",
- "DoomsayerInfoLong": "(Neutrals):\nThe Doomsayer can guess the role of a certain player during the meeting.\nIf the Doomsayer guesses a certain number of roles (the number depends on the Host settings), then he wins.\nThe guessing command is: /bt [player id] [role]\nYou can see the player's id before the player's name, or use the /id command to view the id of all players.",
+ "DoomsayerInfoLong": "(Neutrals):\nThe Doomsayer can guess the role of a certain player during the meeting.\nIf the Doomsayer guesses a certain number of roles (the number depends on the Host settings), then he wins.\nThe guessing command is: /bt [player id] [role]\nYou can see the player's id before the player's name, or use the /id command to view the id of all players.\nIf \"Easy Mode\" is on, the Doomsayer can use their kill button to Observe a player and get a riddle based on that player's role type at the next meeting.",
"ShroudInfoLong": "(Neutrals):\nAs the Shroud, you do not kill normally.\nInstead, use your Kill button to shroud a player.\nShrouded players kill others.\nIf the shrouded player doesn't make a kill, they'll kill themselves after a meeting.\n\nShroud sees shrouded players with a 「◈」mark next to their name.\nShrouded players who did not make a kill will also have the 「◈」mark in meetings, where they'll die if the Shroud is alive by the end of the meeting.",
"WerewolfInfoLong": "(Neutrals):\nAs the Werewolf, you can kill much like any killer.\nHowever, when you kill, any nearby players also die.\nAny player who dies to this will have their death reason as Mauled.\n\nTo balance this, you have a higher Kill Cooldown than anyone else.",
"ShamanInfoLong": "(Neutrals):\nAs the Shaman, you can use your Kill button to select a Voodoo Doll once per round. If the Kill button is used on you, the effect will be deflected onto the Voodoo Doll.\nIf you survive until the end, you win with the winning team.\nNote: If the killer cannot kill the chosen target, murder is canceled, but if the killer rechecks the Shaman, the killer will kill the Shaman.",