wolf kill prompt fix + traitor -> damned

This commit is contained in:
emilis 2026-02-01 23:11:04 +00:00
parent 060180579d
commit 67d345646d
No known key found for this signature in database
23 changed files with 79 additions and 160 deletions

View File

@ -28,7 +28,7 @@ const BLOODLET_DURATION_DAYS: u8 = 2;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChecksAs, Titles)]
pub enum Aura {
#[checks("assignable")]
Traitor,
Damned,
#[checks("assignable")]
#[checks("cleansible")]
Drunk(DrunkBag),
@ -58,7 +58,7 @@ pub enum Aura {
impl Display for Aura {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Aura::Traitor => "Traitor",
Aura::Damned => "Damned",
Aura::Drunk(_) => "Drunk",
Aura::Insane => "Insane",
Aura::Bloodlet { .. } => "Bloodlet",
@ -79,7 +79,7 @@ impl Aura {
| Aura::VindictiveScapegoat
| Aura::SpitefulScapegoat
| Aura::InevitableScapegoat
| Aura::Traitor
| Aura::Damned
| Aura::Drunk(_)
| Aura::Insane => false,
Aura::Bloodlet {
@ -156,7 +156,7 @@ impl Auras {
/// returns [Some] if the auras override the player's [Team]
pub fn overrides_team(&self) -> Option<Team> {
if self.0.iter().any(|a| matches!(a, Aura::Traitor)) {
if self.0.iter().any(|a| matches!(a, Aura::Damned)) {
return Some(Team::AnyEvil);
}
None
@ -166,7 +166,7 @@ impl Auras {
pub fn overrides_alignment(&self) -> Option<Alignment> {
for aura in self.0.iter() {
match aura {
Aura::Traitor => return Some(Alignment::Traitor),
Aura::Damned => return Some(Alignment::Damned),
Aura::RedeemableScapegoat
| Aura::VindictiveScapegoat
| Aura::SpitefulScapegoat
@ -198,7 +198,7 @@ impl Auras {
impl AuraTitle {
pub fn into_aura(self) -> Aura {
match self {
AuraTitle::Traitor => Aura::Traitor,
AuraTitle::Damned => Aura::Damned,
AuraTitle::Drunk => Aura::Drunk(DrunkBag::default()),
AuraTitle::Insane => Aura::Insane,
AuraTitle::Bloodlet => Aura::Bloodlet { night: 0 },
@ -225,9 +225,7 @@ impl AuraTitle {
/// this aura
pub fn incompatible_with(&self, other: Self) -> bool {
match self {
AuraTitle::Bloodlet | AuraTitle::Insane | AuraTitle::Drunk | AuraTitle::Traitor => {
false
}
AuraTitle::Bloodlet | AuraTitle::Insane | AuraTitle::Drunk | AuraTitle::Damned => false,
AuraTitle::VindictiveScapegoat
| AuraTitle::RedeemableScapegoat
| AuraTitle::SpitefulScapegoat

View File

@ -244,7 +244,7 @@ impl Character {
}
pub fn team(&self) -> Team {
if let Alignment::Traitor = self.alignment() {
if let Alignment::Damned = self.alignment() {
return Team::AnyEvil;
}
if self.is_wolf() {
@ -387,9 +387,9 @@ impl Character {
GameTime::Day { number: _ } => return Err(GameError::NotNight),
GameTime::Night { number } => number,
};
if night == 0 && self.auras.list().contains(&Aura::Traitor) {
log::info!("adding traitor prompt for {}", self.identity());
prompts.push(ActionPrompt::TraitorIntro {
if night == 0 && self.auras.list().contains(&Aura::Damned) {
log::info!("adding damned prompt for {}", self.identity());
prompts.push(ActionPrompt::DamnedIntro {
character_id: self.identity(),
});
}

View File

@ -65,7 +65,7 @@ impl ActionPrompt {
fn unless(&self) -> Option<Unless> {
match &self {
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::MasonsWake { .. }
| ActionPrompt::WolvesIntro { .. }
@ -1511,7 +1511,7 @@ impl Night {
} => (*marked == visit_char).then(|| character_id.clone()),
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Bloodletter { .. }
| ActionPrompt::WolfPackKill { marked: None, .. }
| ActionPrompt::Arcanist { marked: _, .. }

View File

@ -134,7 +134,7 @@ impl Night {
secondary_changes: vec![],
}
.into()),
ActionPrompt::TraitorIntro { .. } => Ok(ActionComplete {
ActionPrompt::DamnedIntro { .. } => Ok(ActionComplete {
result: ActionResult::GoBackToSleep,
change: None,
secondary_changes: vec![],
@ -627,7 +627,7 @@ impl Night {
let outcome = self.process(resp)?;
if matches!(
self.current_prompt(),
Some((ActionPrompt::TraitorIntro { .. }, _))
Some((ActionPrompt::DamnedIntro { .. }, _))
| Some((ActionPrompt::RoleChange { .. }, _))
| Some((ActionPrompt::ElderReveal { .. }, _))
) {
@ -656,7 +656,7 @@ impl Night {
| Aura::VindictiveScapegoat
| Aura::SpitefulScapegoat
| Aura::Scapegoat
| Aura::Traitor
| Aura::Damned
| Aura::Bloodlet { .. } => continue,
Aura::Drunk(bag) => {
if bag.peek() == DrunkRoll::Drunk {

View File

@ -165,14 +165,14 @@ impl SetupRoleTitle {
| AuraTitle::VindictiveScapegoat
| AuraTitle::SpitefulScapegoat
| AuraTitle::InevitableScapegoat
| AuraTitle::Traitor
| AuraTitle::Damned
| AuraTitle::Bloodlet
| AuraTitle::Insane => false,
AuraTitle::Drunk => !matches!(self, SetupRoleTitle::Werewolf),
};
}
match aura {
AuraTitle::Traitor => true,
AuraTitle::Damned => true,
AuraTitle::Drunk => {
matches!(
self.category(),

View File

@ -437,7 +437,7 @@ impl StoryActionPrompt {
character_id: character_id.character_id,
},
ActionPrompt::TraitorIntro { .. }
ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Bloodletter { .. }
| ActionPrompt::Protector { .. }
| ActionPrompt::Gravedigger { .. }

View File

@ -441,7 +441,7 @@ impl GameExt for Game {
let prompt = self.mark(mark);
match prompt {
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::MasonsWake { .. }
| ActionPrompt::ElderReveal { .. }

View File

@ -32,7 +32,7 @@ pub enum ActionType {
Cover,
#[checks("is_wolfy")]
WolvesIntro,
TraitorIntro,
DamnedIntro,
RoleChange,
Protect,
#[checks("is_wolfy")]
@ -210,8 +210,8 @@ pub enum ActionPrompt {
living_players: Box<[CharacterIdentity]>,
marked: Option<CharacterId>,
},
#[checks(ActionType::TraitorIntro)]
TraitorIntro { character_id: CharacterIdentity },
#[checks(ActionType::DamnedIntro)]
DamnedIntro { character_id: CharacterIdentity },
#[checks(ActionType::BeholderWakes)]
BeholderWakes { character_id: CharacterIdentity },
}
@ -238,7 +238,7 @@ impl ActionPrompt {
| ActionPrompt::DireWolf { .. }
| ActionPrompt::LoneWolfKill { .. }
| ActionPrompt::Bloodletter { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::CoverOfDarkness => false,
ActionPrompt::BeholderWakes { .. }
@ -302,13 +302,13 @@ impl ActionPrompt {
| ActionPrompt::MasonsWake { .. }
| ActionPrompt::Shapeshifter { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::TraitorIntro { .. } => None,
| ActionPrompt::DamnedIntro { .. } => None,
}
}
pub(crate) const fn character_id(&self) -> Option<CharacterId> {
match self {
ActionPrompt::BeholderWakes { character_id }
| ActionPrompt::TraitorIntro { character_id }
| ActionPrompt::DamnedIntro { character_id }
| ActionPrompt::Insomniac { character_id, .. }
| ActionPrompt::LoneWolfKill { character_id, .. }
| ActionPrompt::ElderReveal { character_id }
@ -353,7 +353,7 @@ impl ActionPrompt {
| ActionPrompt::Vindicator { character_id, .. } => character_id.character_id == target,
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::BeholderChooses { .. }
| ActionPrompt::CoverOfDarkness
| ActionPrompt::WolvesIntro { .. }
@ -390,7 +390,7 @@ impl ActionPrompt {
let mut prompt = self.clone();
match &mut prompt {
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::MasonsWake { .. }
| ActionPrompt::ElderReveal { .. }
@ -632,8 +632,7 @@ impl ActionResult {
ActionResult::Seer(c, Alignment::Village) => {
ActionResult::Seer(c.clone(), Alignment::Wolves)
}
ActionResult::Seer(c, Alignment::Traitor)
| ActionResult::Seer(c, Alignment::Wolves) => {
ActionResult::Seer(c, Alignment::Damned) | ActionResult::Seer(c, Alignment::Wolves) => {
ActionResult::Seer(c.clone(), Alignment::Village)
}
ActionResult::PowerSeer { target, powerful } => ActionResult::PowerSeer {

View File

@ -460,7 +460,7 @@ impl RoleTitle {
pub enum Alignment {
Village,
Wolves,
Traitor,
Damned,
}
impl Alignment {
@ -478,7 +478,7 @@ impl Display for Alignment {
match self {
Alignment::Village => f.write_str("Village"),
Alignment::Wolves => f.write_str("Wolves"),
Alignment::Traitor => f.write_str("Traitor"),
Alignment::Damned => f.write_str("Damned"),
}
}
}

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -17,8 +17,8 @@ $offensive_color: color.adjust($village_color, $hue: 30deg);
$offensive_border: color.change($offensive_color, $alpha: 1.0);
$starts_as_villager_color: color.adjust($village_color, $hue: 60deg);
$starts_as_villager_border: color.change($starts_as_villager_color, $alpha: 1.0);
$traitor_color: color.adjust($village_color, $hue: 45deg);
$traitor_border: color.change($traitor_color, $alpha: 1.0);
$damned_color: color.adjust($village_color, $hue: 45deg);
$damned_border: color.change($damned_color, $alpha: 1.0);
$drunk_color: color.adjust($village_color, $hue: 150deg);
$drunk_border: color.change($drunk_color, $alpha: 1.0);
@ -28,7 +28,7 @@ $offensive_border_faint: color.change($offensive_border, $alpha: 0.3);
$defensive_border_faint: color.change($defensive_border, $alpha: 0.3);
$intel_border_faint: color.change($intel_border, $alpha: 0.3);
$starts_as_villager_border_faint: color.change($starts_as_villager_border, $alpha: 0.3);
$traitor_border_faint: color.change($traitor_border, $alpha: 0.3);
$damned_border_faint: color.change($damned_border, $alpha: 0.3);
$drunk_border_faint: color.change($drunk_border, $alpha: 0.3);
$wolves_color_faint: color.change($wolves_color, $alpha: 0.1);
@ -37,7 +37,7 @@ $offensive_color_faint: color.change($offensive_color, $alpha: 0.1);
$defensive_color_faint: color.change($defensive_color, $alpha: 0.1);
$intel_color_faint: color.change($intel_color, $alpha: 0.1);
$starts_as_villager_color_faint: color.change($starts_as_villager_color, $alpha: 0.1);
$traitor_color_faint: color.change($traitor_color, $alpha: 0.1);
$damned_color_faint: color.change($damned_color, $alpha: 0.1);
$drunk_color_faint: color.change($drunk_color, $alpha: 0.1);
@mixin flexbox() {
@ -1485,26 +1485,26 @@ select {
}
}
.traitor {
--faction-color: $traitor_color;
--faction-border: $traitor_border;
--faction-color-faint: $traitor_color_faint;
--faction-border-faint: $traitor_border_faint;
.damned {
--faction-color: $damned_color;
--faction-border: $damned_border;
--faction-color-faint: $damned_color_faint;
--faction-border-faint: $damned_border_faint;
background-color: $traitor_color;
border: 1px solid $traitor_border;
background-color: $damned_color;
border: 1px solid $damned_border;
&.hover:hover {
color: white;
background-color: $traitor_border;
background-color: $damned_border;
}
&.faint {
border: 1px solid $traitor_border_faint;
background-color: $traitor_color_faint;
border: 1px solid $damned_border_faint;
background-color: $damned_color_faint;
&.hover:hover {
background-color: $traitor_border_faint;
background-color: $damned_border_faint;
}
}
}
@ -1593,8 +1593,6 @@ select {
background-color: color.change($defensive_color, $lightness: 30%);
border: 1px solid color.change($defensive_border, $lightness: 40%);
}
}
@ -1746,18 +1744,14 @@ li.choice {
.details {
font-size: 5vw;
// height: 100%;
// width: 100%;
border: 1px solid $village_border;
background-color: color.change($village_color, $alpha: 0.3);
text-align: center;
// width: fit-content;
&>* {
margin-top: 0.5cm;
margin-bottom: 0.5cm;
// padding: 0;
}
}
}
@ -1791,7 +1785,6 @@ li.choice {
.check-icon {
width: 40vw;
height: 40vh;
// margin-top: 10%;
align-self: center;
}
@ -1816,7 +1809,6 @@ li.choice {
gap: 10px;
img {
// flex-shrink: 1 !important;
width: max-content !important;
height: max-content !important;
}
@ -1856,8 +1848,6 @@ li.choice {
flex-wrap: nowrap;
align-items: center;
gap: 3px;
// justify-content: center;
// text-align: center;
.field {
display: flex;
@ -1873,13 +1863,10 @@ li.choice {
& input {
height: 2em;
// max-width: 80%;
width: 70%;
&#number {
text-align: center;
// font-size: 2rem;
// width: 20%;
width: 3ch;
}
}
@ -1899,69 +1886,6 @@ li.choice {
}
}
// .story {
// .cast {
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
// gap: 10px;
// justify-content: center;
// }
// .time-period {
// user-select: text;
// .day {
// display: flex;
// flex-direction: column;
// flex-wrap: wrap;
// align-items: center;
// .executed {
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
// gap: 10px;
// }
// }
// .night {
// &>label {
// margin-left: 10vw;
// font-size: 2rem;
// font-weight: lighter;
// }
// ul.changes,
// ul.choices {
// display: flex;
// flex-direction: column;
// flex-wrap: nowrap;
// gap: 10px;
// &>li {
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
// align-items: center;
// gap: 10px;
// }
// & span {
// display: flex;
// flex-direction: row;
// flex-wrap: wrap;
// align-items: center;
// gap: 10px;
// }
// }
// }
// }
// }
.attribute-span {
display: flex;
flex-direction: row;
@ -3000,10 +2924,10 @@ dialog {
}
}
.traitor-highlight {
color: $traitor_color;
.damned-highlight {
color: $damned_color;
.number {
color: $traitor_color;
color: $damned_color;
}
}

View File

@ -22,7 +22,7 @@ pub trait Class {
impl Class for Character {
fn class(&self) -> Option<&'static str> {
if let Team::AnyEvil = self.team() {
return Some("traitor");
return Some("damned");
}
Some(
Into::<SetupRole>::into(self.role_title())

View File

@ -109,7 +109,7 @@ pub fn Prompt(props: &ActionPromptProps) -> Html {
});
let (character_id, targets, marked, role_info) = match &props.prompt {
ActionPrompt::BeholderWakes { .. } | ActionPrompt::TraitorIntro { .. } => return html! {},
ActionPrompt::BeholderWakes { .. } | ActionPrompt::DamnedIntro { .. } => return html! {},
ActionPrompt::CoverOfDarkness => {
return html! {
<CoverOfDarkness next={continue_callback}/>

View File

@ -31,7 +31,7 @@ pub fn AlignmentSpan(AlignmentSpanProps { alignment }: &AlignmentSpanProps) -> H
let class = match alignment {
role::Alignment::Village => "village-highlight",
role::Alignment::Wolves => "wolves-highlight",
role::Alignment::Traitor => "traitor-highlight",
role::Alignment::Damned => "damned-highlight",
};
html! {
<span class={classes!("attribute-span", class)}>

View File

@ -23,7 +23,7 @@ use crate::{
impl Class for AuraTitle {
fn class(&self) -> Option<&'static str> {
Some(match self {
AuraTitle::Traitor => "traitor",
AuraTitle::Damned => "damned",
AuraTitle::Drunk => "drunk",
AuraTitle::Insane => "insane",
AuraTitle::Bloodlet => "wolves",

View File

@ -77,7 +77,7 @@ decl_icon!(
NotEqual: "/img/not-equal.svg",
Equal: "/img/equal.svg",
RedX: "/img/red-x.svg",
Traitor: "/img/traitor.svg",
Damned: "/img/damned.svg",
Bloodlet: "/img/bloodlet.svg",
Drunk: "/img/drunk.svg",
Insane: "/img/insane.svg",
@ -157,7 +157,7 @@ impl AssociatedIcon for Alignment {
match self {
Alignment::Village => IconSource::Village,
Alignment::Wolves => IconSource::Wolves,
Alignment::Traitor => IconSource::Traitor,
Alignment::Damned => IconSource::Damned,
}
}
}
@ -233,7 +233,7 @@ impl PartialAssociatedIcon for DiedToTitle {
impl PartialAssociatedIcon for AuraTitle {
fn icon(&self) -> Option<IconSource> {
match self {
AuraTitle::Traitor => Some(IconSource::Traitor),
AuraTitle::Damned => Some(IconSource::Damned),
AuraTitle::Drunk => Some(IconSource::Drunk),
AuraTitle::Insane => Some(IconSource::Insane),
AuraTitle::Bloodlet => Some(IconSource::Bloodlet),

View File

@ -863,7 +863,7 @@ impl GameExt for Game {
let prompt = self.mark(mark);
match prompt {
ActionPrompt::BeholderWakes { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::MasonsWake { .. }
| ActionPrompt::ElderReveal { .. }

View File

@ -3,24 +3,24 @@ use yew::prelude::*;
use crate::components::{Icon, IconSource, IconType};
#[function_component]
pub fn TraitorIntroPage1() -> Html {
pub fn DamnedIntroPage1() -> Html {
html! {
<div class="role-page">
<h1 class="traitor">{"DAMNED"}</h1>
<div class="information traitor faint">
<h1 class="damned">{"DAMNED"}</h1>
<div class="information damned faint">
<span class="yellow">{"YOU ARE DAMNED"}</span>
<Icon source={IconSource::Traitor} icon_type={IconType::Informational}/>
<Icon source={IconSource::Damned} icon_type={IconType::Informational}/>
</div>
</div>
}
}
#[function_component]
pub fn TraitorIntroPage2() -> Html {
pub fn DamnedIntroPage2() -> Html {
html! {
<div class="role-page">
<h1 class="traitor">{"DAMNED"}</h1>
<div class="information traitor faint">
<h1 class="damned">{"DAMNED"}</h1>
<div class="information damned faint">
{"YOU RETAIN YOUR ROLE AND WIN IF EVIL WINS"}
<span class="yellow">
{"HOWEVER, YOU CONTRIBUTE TO VILLAGE PARITY"}

View File

@ -23,7 +23,7 @@ use yew::prelude::*;
use crate::{
components::Identity,
pages::{RoleChangePage, TraitorIntroPage1, TraitorIntroPage2, WolfpackKillPage},
pages::{DamnedIntroPage1, DamnedIntroPage2, RoleChangePage, WolfpackKillPage},
};
werewolves_macros::include_path!("werewolves/src/pages/role_page");
@ -269,17 +269,17 @@ impl RolePage for ActionPrompt {
<BeholderWakePage1 />
</>
}]),
ActionPrompt::TraitorIntro { character_id } => Rc::new([
ActionPrompt::DamnedIntro { character_id } => Rc::new([
html! {
<>
{ident(character_id)}
<TraitorIntroPage1 />
<DamnedIntroPage1 />
</>
},
html! {
<>
{ident(character_id)}
<TraitorIntroPage2 />
<DamnedIntroPage2 />
</>
},
]),

View File

@ -50,7 +50,7 @@ pub fn SeerResult(SeerResultProps { alignment, target }: &SeerResultProps) -> Ht
let text = match alignment {
Alignment::Village => "VILLAGE",
Alignment::Wolves => "WOLFPACK",
Alignment::Traitor => "TRAITOR",
Alignment::Damned => "DAMNED",
};
let additional_info = match alignment {
Alignment::Village => html! {
@ -65,10 +65,10 @@ pub fn SeerResult(SeerResultProps { alignment, target }: &SeerResultProps) -> Ht
alignment_text={text}
/>
},
Alignment::Traitor => html! {
Alignment::Damned => html! {
<div class="bottom-bound">
{"THIS PERSON IS A "}
<span class="yellow">{"TRAITOR"}</span>
{"THIS PERSON IS "}
<span class="yellow">{"DAMNED"}</span>
{"THEY WIN ALONGSIDE EVIL"}
</div>
},

View File

@ -15,7 +15,7 @@
use yew::prelude::*;
use crate::components::{Icon, IconSource};
use crate::components::{Icon, IconSource, IconType};
#[function_component]
pub fn WolfpackKillPage() -> Html {
@ -23,11 +23,9 @@ pub fn WolfpackKillPage() -> Html {
<div class="role-page">
<h1 class="wolves">{"WOLF PACK KILL"}</h1>
<div class="information wolves faint">
<h2>{"CHOOSE A TARGET TO EAT TONIGHT"}</h2>
<div class="info-icon-grow">
<Icon source={IconSource::Wolves} />
</div>
<h3 class="yellow">{"WOLVES MUST BE UNANIMOUS"}</h3>
{"CHOOSE A TARGET TO EAT TONIGHT"}
<Icon source={IconSource::Wolves} icon_type={IconType::Fit}/>
<span class="yellow">{"WOLVES MUST BE UNANIMOUS"}</span>
</div>
</div>
}

View File

@ -401,7 +401,7 @@ impl From<ActionPromptTitle> for TestScreen {
living_players: identities(20),
marked: None,
},
ActionPromptTitle::TraitorIntro => ActionPrompt::TraitorIntro {
ActionPromptTitle::DamnedIntro => ActionPrompt::DamnedIntro {
character_id: identities(1).into_iter().next().unwrap(),
},
})
@ -459,6 +459,6 @@ fn prompt_class(prompt: &ActionPrompt) -> Option<&'static str> {
| ActionPrompt::LoneWolfKill { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::Bloodletter { .. } => Some("wolves"),
ActionPrompt::TraitorIntro { .. } => Some("traitor"),
ActionPrompt::DamnedIntro { .. } => Some("damned"),
}
}

View File

@ -323,7 +323,7 @@ pub fn PromptScreenTest(
| ActionPrompt::Bloodletter { .. }
| ActionPrompt::Seer { .. }
| ActionPrompt::ElderReveal { .. }
| ActionPrompt::TraitorIntro { .. }
| ActionPrompt::DamnedIntro { .. }
| ActionPrompt::Insomniac { .. }
| ActionPrompt::Shapeshifter { .. }
| ActionPrompt::CoverOfDarkness => html! {},