From e536edfc287161f17da205ba52e2ff442beec250 Mon Sep 17 00:00:00 2001 From: emilis Date: Sun, 1 Feb 2026 21:49:59 +0000 Subject: [PATCH] show targets for intel results --- werewolves-proto/src/game/night/process.rs | 61 +++++++++++-------- werewolves-proto/src/game/story.rs | 56 ++++++++++++----- werewolves-proto/src/game_test/mod.rs | 14 ++--- werewolves-proto/src/game_test/role/empath.rs | 32 ++++++++-- werewolves-proto/src/message/night.rs | 51 +++++++++++----- werewolves/index.scss | 50 +++++++++++++-- werewolves/src/components/action/prompt.rs | 40 +++--------- werewolves/src/components/action/result.rs | 28 ++++----- werewolves/src/components/story/character.rs | 22 ++++--- werewolves/src/components/story/gamegen.rs | 14 ++--- werewolves/src/pages/drunk_page.rs | 10 ++- werewolves/src/pages/role_change.rs | 14 ++--- werewolves/src/pages/role_page.rs | 56 +++++++++++++---- werewolves/src/pages/role_page/adjudicator.rs | 23 +++---- werewolves/src/pages/role_page/alpha_wolf.rs | 9 +-- werewolves/src/pages/role_page/arcanist.rs | 53 +++++++++------- werewolves/src/pages/role_page/beholder.rs | 27 ++++---- werewolves/src/pages/role_page/bloodletter.rs | 15 +++-- werewolves/src/pages/role_page/direwolf.rs | 6 +- werewolves/src/pages/role_page/elder.rs | 23 ++++--- werewolves/src/pages/role_page/empath.rs | 30 ++++----- werewolves/src/pages/role_page/gravedigger.rs | 35 +++++------ werewolves/src/pages/role_page/guardian.rs | 38 +++++------- werewolves/src/pages/role_page/hunter.rs | 12 ++-- werewolves/src/pages/role_page/insomniac.rs | 14 ++--- werewolves/src/pages/role_page/lone_wolf.rs | 10 +-- werewolves/src/pages/role_page/maple_wolf.rs | 20 +++--- werewolves/src/pages/role_page/mason.rs | 26 +++++--- werewolves/src/pages/role_page/militia.rs | 16 +++-- werewolves/src/pages/role_page/mortician.rs | 32 ++++------ werewolves/src/pages/role_page/power_seer.rs | 21 +++---- werewolves/src/pages/role_page/protector.rs | 10 ++- werewolves/src/pages/role_page/pyremaster.rs | 12 ++-- werewolves/src/pages/role_page/seer.rs | 45 +++++++------- werewolves/src/pages/role_page/vindicator.rs | 11 ++-- werewolves/src/pages/roleblock.rs | 10 ++- werewolves/src/pages/shift_failed.rs | 12 ++-- werewolves/src/pages/traitor.rs | 32 ++++++---- werewolves/src/test_util/mod.rs | 24 +++++--- werewolves/src/test_util/result.rs | 50 ++++++++++----- 40 files changed, 607 insertions(+), 457 deletions(-) diff --git a/werewolves-proto/src/game/night/process.rs b/werewolves-proto/src/game/night/process.rs index 3e7b965..b0e4c38 100644 --- a/werewolves-proto/src/game/night/process.rs +++ b/werewolves-proto/src/game/night/process.rs @@ -192,9 +192,10 @@ impl Night { marked: Some(marked), .. } => { - let alignment = self.character_with_current_auras(*marked)?.alignment(); + let target = self.character_with_current_auras(*marked)?; + let alignment = target.alignment(); Ok(ResponseOutcome::ActionComplete(ActionComplete { - result: ActionResult::Seer(alignment), + result: ActionResult::Seer(target.identity(), alignment), change: None, secondary_changes: vec![], })) @@ -217,11 +218,15 @@ impl Night { marked: (Some(marked1), Some(marked2)), .. } => { - let same = self.character_with_current_auras(*marked1)?.alignment() - == self.character_with_current_auras(*marked2)?.alignment(); + let target1 = self.character_with_current_auras(*marked1)?; + let target2 = self.character_with_current_auras(*marked2)?; + let same = target1.alignment() == target2.alignment(); Ok(ResponseOutcome::ActionComplete(ActionComplete { - result: ActionResult::Arcanist(AlignmentEq::new(same)), + result: ActionResult::Arcanist( + (target1.identity(), target2.identity()), + AlignmentEq::new(same), + ), change: None, secondary_changes: vec![], })) @@ -234,7 +239,10 @@ impl Night { .character_with_current_auras(*marked)? .gravedigger_dig(); Ok(ResponseOutcome::ActionComplete(ActionComplete { - result: ActionResult::GraveDigger(dig_role), + result: ActionResult::GraveDigger( + self.village.character_by_id(*marked)?.identity(), + dig_role, + ), change: None, secondary_changes: vec![], })) @@ -423,6 +431,7 @@ impl Night { .. } => Ok(ActionComplete { result: ActionResult::Adjudicator { + target: self.village.character_by_id(*marked)?.identity(), killer: self.character_with_current_auras(*marked)?.killer(), }, change: None, @@ -434,6 +443,7 @@ impl Night { .. } => Ok(ActionComplete { result: ActionResult::PowerSeer { + target: self.village.character_by_id(*marked)?.identity(), powerful: self.character_with_current_auras(*marked)?.powerful(), }, change: None, @@ -445,6 +455,7 @@ impl Night { .. } => Ok(ActionComplete { result: ActionResult::Mortician( + self.village.character_by_id(*marked)?.identity(), self.village .character_by_id(*marked)? .died_to() @@ -507,7 +518,10 @@ impl Night { let scapegoat = marked.role_title() == RoleTitle::Scapegoat || is_scapegoat_aura; Ok(ActionComplete { - result: ActionResult::Empath { scapegoat }, + result: ActionResult::Empath { + target: marked.identity(), + scapegoat, + }, change: scapegoat.then(|| NightChange::EmpathFoundScapegoat { empath: character_id.character_id, scapegoat: marked.character_id(), @@ -658,36 +672,35 @@ impl Night { } Aura::InevitableScapegoat => { match &act.result { - ActionResult::Adjudicator { .. } => { + ActionResult::Adjudicator { target, .. } => { act.result = ActionResult::Adjudicator { + target: target.clone(), killer: Killer::Killer, }; } - ActionResult::PowerSeer { .. } => { + ActionResult::PowerSeer { target, .. } => { act.result = ActionResult::PowerSeer { + target: target.clone(), powerful: Powerful::Powerful, } } - ActionResult::Arcanist(_) => { - let (_, target2) = self - .current_prompt() - .ok_or(GameError::NoCurrentPromptForAura)? - .0 - .marked() - .ok_or(GameError::MustSelectTarget)?; - let target2_align = self - .village - .character_by_id(target2.ok_or(GameError::MustSelectTarget)?)? - .alignment(); + ActionResult::Arcanist((t1, t2), _) => { + let target2 = self.village.character_by_id(t2.character_id)?; + + let target2_align = target2.alignment(); let target1_align = Alignment::Wolves; - act.result = - ActionResult::Arcanist(if target1_align == target2_align { + act.result = ActionResult::Arcanist( + (t1.clone(), t2.clone()), + if target1_align == target2_align { AlignmentEq::Same } else { AlignmentEq::Different - }); + }, + ); + } + ActionResult::Seer(target, _) => { + act.result = ActionResult::Seer(target.clone(), Alignment::Wolves) } - ActionResult::Seer(_) => act.result = ActionResult::Seer(Alignment::Wolves), _ => {} } if let Some((marked, _)) = self diff --git a/werewolves-proto/src/game/story.rs b/werewolves-proto/src/game/story.rs index 472b14e..f386bee 100644 --- a/werewolves-proto/src/game/story.rs +++ b/werewolves-proto/src/game/story.rs @@ -79,14 +79,25 @@ impl NightChoice { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum StoryActionResult { RoleBlocked, - Seer(Alignment), - PowerSeer { powerful: Powerful }, - Adjudicator { killer: Killer }, - Arcanist(AlignmentEq), - GraveDigger(Option), - Mortician(DiedToTitle), - Insomniac { visits: Box<[CharacterId]> }, - Empath { scapegoat: bool }, + Seer(CharacterId, Alignment), + PowerSeer { + target: CharacterId, + powerful: Powerful, + }, + Adjudicator { + target: CharacterId, + killer: Killer, + }, + Arcanist((CharacterId, CharacterId), AlignmentEq), + GraveDigger(CharacterId, Option), + Mortician(CharacterId, DiedToTitle), + Insomniac { + visits: Box<[CharacterId]>, + }, + Empath { + target: CharacterId, + scapegoat: bool, + }, BeholderSawNothing, BeholderSawEverything, Drunk, @@ -101,16 +112,31 @@ impl StoryActionResult { ActionResult::BeholderSawEverything => Self::BeholderSawEverything, ActionResult::Drunk => Self::Drunk, ActionResult::RoleBlocked => Self::RoleBlocked, - ActionResult::Seer(alignment) => Self::Seer(alignment), - ActionResult::PowerSeer { powerful } => Self::PowerSeer { powerful }, - ActionResult::Adjudicator { killer } => Self::Adjudicator { killer }, - ActionResult::Arcanist(same) => Self::Arcanist(same), - ActionResult::GraveDigger(role_title) => Self::GraveDigger(role_title), - ActionResult::Mortician(died_to) => Self::Mortician(died_to), + ActionResult::Seer(target, alignment) => Self::Seer(target.character_id, alignment), + ActionResult::PowerSeer { target, powerful } => Self::PowerSeer { + powerful, + target: target.character_id, + }, + ActionResult::Adjudicator { target, killer } => Self::Adjudicator { + killer, + target: target.character_id, + }, + ActionResult::Arcanist((target1, target2), same) => { + Self::Arcanist((target1.character_id, target2.character_id), same) + } + ActionResult::GraveDigger(target, role_title) => { + Self::GraveDigger(target.character_id, role_title) + } + ActionResult::Mortician(target, died_to) => { + Self::Mortician(target.character_id, died_to) + } ActionResult::Insomniac(visits) => Self::Insomniac { visits: visits.iter().map(|c| c.character_id).collect(), }, - ActionResult::Empath { scapegoat } => Self::Empath { scapegoat }, + ActionResult::Empath { target, scapegoat } => Self::Empath { + scapegoat, + target: target.character_id, + }, ActionResult::GoBackToSleep | ActionResult::Continue => return None, }) diff --git a/werewolves-proto/src/game_test/mod.rs b/werewolves-proto/src/game_test/mod.rs index cfe10b8..ab4b42a 100644 --- a/werewolves-proto/src/game_test/mod.rs +++ b/werewolves-proto/src/game_test/mod.rs @@ -206,19 +206,19 @@ impl ActionResultExt for ActionResult { } fn empath(&self) -> bool { match self { - Self::Empath { scapegoat } => *scapegoat, + Self::Empath { scapegoat, .. } => *scapegoat, resp => panic!("expected empath, got {resp:?}"), } } fn mortician(&self) -> DiedToTitle { match self { - Self::Mortician(role) => *role, + Self::Mortician(_, role) => *role, resp => panic!("expected mortician, got {resp:?}"), } } fn gravedigger(&self) -> Option { match self { - Self::GraveDigger(role) => *role, + Self::GraveDigger(_, role) => *role, resp => panic!("expected gravedigger, got {resp:?}"), } } @@ -227,13 +227,13 @@ impl ActionResultExt for ActionResult { } fn adjudicator(&self) -> Killer { match self { - Self::Adjudicator { killer } => *killer, + Self::Adjudicator { killer, .. } => *killer, resp => panic!("expected adjudicator, got {resp:?}"), } } fn power_seer(&self) -> Powerful { match self { - Self::PowerSeer { powerful } => *powerful, + Self::PowerSeer { powerful, .. } => *powerful, resp => panic!("expected power seer, got {resp:?}"), } } @@ -247,14 +247,14 @@ impl ActionResultExt for ActionResult { fn seer(&self) -> Alignment { match self { - ActionResult::Seer(a) => a.clone(), + ActionResult::Seer(_, a) => a.clone(), _ => panic!("expected a seer result"), } } fn arcanist(&self) -> AlignmentEq { match self { - ActionResult::Arcanist(same) => same.clone(), + ActionResult::Arcanist(_, same) => same.clone(), resp => panic!("expected an arcanist result, got {resp:?}"), } } diff --git a/werewolves-proto/src/game_test/role/empath.rs b/werewolves-proto/src/game_test/role/empath.rs index fa74c3c..c4361a5 100644 --- a/werewolves-proto/src/game_test/role/empath.rs +++ b/werewolves-proto/src/game_test/role/empath.rs @@ -45,7 +45,13 @@ fn nothing_on_wolf() { game.next().title().empath(); game.mark(game.character_by_player_id(wolf_player_id).character_id()); - assert_eq!(game.r#continue(), ActionResult::Empath { scapegoat: false }); + assert_eq!( + game.r#continue(), + ActionResult::Empath { + scapegoat: false, + target: game.character_by_player_id(wolf_player_id).identity() + } + ); game.r#continue().sleep(); game.next_expect_day(); @@ -105,7 +111,13 @@ fn takes_on_scapegoats_curse() { game.character_by_player_id(scapegoat_player_id) .character_id(), ); - assert_eq!(game.r#continue(), ActionResult::Empath { scapegoat: true }); + assert_eq!( + game.r#continue(), + ActionResult::Empath { + scapegoat: true, + target: game.character_by_player_id(scapegoat_player_id).identity() + } + ); game.r#continue().sleep(); game.next().title().seer(); @@ -181,7 +193,13 @@ fn takes_on_scapegoat_aura_curse() { game.next().title().empath(); game.mark(game.character_by_player_id(scapegoat).character_id()); - assert_eq!(game.r#continue(), ActionResult::Empath { scapegoat: true }); + assert_eq!( + game.r#continue(), + ActionResult::Empath { + scapegoat: true, + target: game.character_by_player_id(scapegoat).identity() + } + ); game.r#continue().sleep(); game.next_expect_day(); @@ -222,7 +240,13 @@ fn takes_on_scapegoat_aura_curse_no_role_change() { game.next().title().empath(); game.mark(game.character_by_player_id(scapegoat).character_id()); - assert_eq!(game.r#continue(), ActionResult::Empath { scapegoat: true }); + assert_eq!( + game.r#continue(), + ActionResult::Empath { + scapegoat: true, + target: game.character_by_player_id(scapegoat).identity() + } + ); game.r#continue().sleep(); game.next_expect_day(); diff --git a/werewolves-proto/src/message/night.rs b/werewolves-proto/src/message/night.rs index 5277da9..a78f2c3 100644 --- a/werewolves-proto/src/message/night.rs +++ b/werewolves-proto/src/message/night.rs @@ -601,14 +601,23 @@ pub enum ActionResponse { pub enum ActionResult { RoleBlocked, Drunk, - Seer(Alignment), - PowerSeer { powerful: Powerful }, - Adjudicator { killer: Killer }, - Arcanist(AlignmentEq), - GraveDigger(Option), - Mortician(DiedToTitle), + Seer(CharacterIdentity, Alignment), + PowerSeer { + target: CharacterIdentity, + powerful: Powerful, + }, + Adjudicator { + target: CharacterIdentity, + killer: Killer, + }, + Arcanist((CharacterIdentity, CharacterIdentity), AlignmentEq), + GraveDigger(CharacterIdentity, Option), + Mortician(CharacterIdentity, DiedToTitle), Insomniac(Visits), - Empath { scapegoat: bool }, + Empath { + target: CharacterIdentity, + scapegoat: bool, + }, BeholderSawNothing, BeholderSawEverything, GoBackToSleep, @@ -619,16 +628,26 @@ pub enum ActionResult { impl ActionResult { pub fn insane(&self) -> Option { Some(match self { - ActionResult::Seer(Alignment::Village) => ActionResult::Seer(Alignment::Wolves), - ActionResult::Seer(Alignment::Traitor) | ActionResult::Seer(Alignment::Wolves) => { - ActionResult::Seer(Alignment::Village) + ActionResult::Seer(c, Alignment::Village) => { + ActionResult::Seer(c.clone(), Alignment::Wolves) } - ActionResult::PowerSeer { powerful } => ActionResult::PowerSeer { + ActionResult::Seer(c, Alignment::Traitor) + | ActionResult::Seer(c, Alignment::Wolves) => { + ActionResult::Seer(c.clone(), Alignment::Village) + } + ActionResult::PowerSeer { target, powerful } => ActionResult::PowerSeer { + target: target.clone(), powerful: !*powerful, }, - ActionResult::Adjudicator { killer } => ActionResult::Adjudicator { killer: !*killer }, - ActionResult::Arcanist(alignment_eq) => ActionResult::Arcanist(!*alignment_eq), - ActionResult::Empath { scapegoat } => ActionResult::Empath { + ActionResult::Adjudicator { target, killer } => ActionResult::Adjudicator { + target: target.clone(), + killer: !*killer, + }, + ActionResult::Arcanist(targets, alignment_eq) => { + ActionResult::Arcanist(targets.clone(), !*alignment_eq) + } + ActionResult::Empath { target, scapegoat } => ActionResult::Empath { + target: target.clone(), scapegoat: !*scapegoat, }, ActionResult::BeholderSawNothing => ActionResult::BeholderSawEverything, @@ -637,8 +656,8 @@ impl ActionResult { ActionResult::ShiftFailed | ActionResult::RoleBlocked | ActionResult::Drunk - | ActionResult::GraveDigger(_) - | ActionResult::Mortician(_) + | ActionResult::GraveDigger(_, _) + | ActionResult::Mortician(_, _) | ActionResult::Insomniac(_) | ActionResult::GoBackToSleep | ActionResult::Continue => return None, diff --git a/werewolves/index.scss b/werewolves/index.scss index 42d682e..5f397fc 100644 --- a/werewolves/index.scss +++ b/werewolves/index.scss @@ -156,7 +156,7 @@ nav.host-nav { &:hover { background-color: white; - color: invert(#cccccc); + color: color.invert(#cccccc); } } @@ -952,7 +952,7 @@ error { flex-direction: row; flex-wrap: wrap; gap: 2px; - font-size: 1rem; + font-size: 1em; margin: 0px; padding: 0px; align-items: center; @@ -2159,6 +2159,18 @@ li.choice { justify-content: center; align-items: center; gap: 30px; + max-height: 40%; + + @media only screen and (min-width : 1600px) { + width: 100%; + } + + flex-shrink: 1; + + img { + max-height: 100%; + flex-shrink: 1; + } } .icon-info { @@ -2248,6 +2260,7 @@ li.choice { flex-direction: column; flex-wrap: nowrap; height: 100%; + align-items: center; justify-content: space-around; } @@ -2287,6 +2300,7 @@ li.choice { flex-direction: column; flex-wrap: nowrap; font-weight: bold; + font-size: 0.5em; gap: 10px; } @@ -2368,9 +2382,13 @@ li.choice { } .information { - font-size: 1.0rem; + font-size: 2.0rem; + font-stretch: condensed; padding-left: 5%; padding-right: 5%; + text-align: center; + + display: flex; flex-direction: column; @@ -2397,6 +2415,30 @@ li.choice { padding-bottom: 10px; } } + + img { + flex-shrink: 1; + flex-grow: 1; + } + + .subtext { + font-size: 1.5rem; + } + + .arcanist-targets { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1ch; + font-size: 1.5rem; + align-items: center; + + .and { + font-style: italic; + opacity: 50%; + font-size: 0.7em; + } + } } .setup-aura { @@ -2594,7 +2636,7 @@ dialog::backdrop { font-size: 2em; } - button { + button:not(:hover) { color: white; } diff --git a/werewolves/src/components/action/prompt.rs b/werewolves/src/components/action/prompt.rs index 0dd8134..0648fd3 100644 --- a/werewolves/src/components/action/prompt.rs +++ b/werewolves/src/components/action/prompt.rs @@ -25,12 +25,9 @@ use werewolves_proto::{ }; use yew::prelude::*; -use crate::{ - components::{ - Button, CoverOfDarkness, Identity, - action::{BinaryChoice, TargetPicker, WolvesIntro}, - }, - pages::TraitorIntroPage, +use crate::components::{ + Button, CoverOfDarkness, Identity, + action::{BinaryChoice, TargetPicker, WolvesIntro}, }; #[derive(Debug, Clone, PartialEq, Properties)] @@ -111,24 +108,8 @@ pub fn Prompt(props: &ActionPromptProps) -> Html { }) }); - let cont = continue_callback.clone().map(|continue_callback| { - html! { - - } - }); let (character_id, targets, marked, role_info) = match &props.prompt { - ActionPrompt::BeholderWakes { .. } => return html! {}, - ActionPrompt::TraitorIntro { character_id } => { - return html! { -
- {identity_html(props, Some(character_id))} - - {cont} -
- }; - } + ActionPrompt::BeholderWakes { .. } | ActionPrompt::TraitorIntro { .. } => return html! {}, ActionPrompt::CoverOfDarkness => { return html! { @@ -415,16 +396,15 @@ pub fn Prompt(props: &ActionPromptProps) -> Html { {identity_html(props, Some(character_id))}

{"SHAPESHIFTER"}

-

+ {"WOULD YOU LIKE TO USE YOUR "} {"ONCE PER GAME"} {" SHAPESHIFT ABILITY?"} -

-

- {"YOU WILL DIE"}{", AND THE "} - {"TARGET OF THE WOLFPACK KILL"} - {" SHALL INSTEAD BECOME A WOLF"} -

+ + + {"YOU WILL DIE"} + {", BUT THE TARGET OF THE WOLFPACK KILL SHALL INSTEAD BECOME A WOLF"} +
{choice} diff --git a/werewolves/src/components/action/result.rs b/werewolves/src/components/action/result.rs index 5123f6e..f1d2946 100644 --- a/werewolves/src/components/action/result.rs +++ b/werewolves/src/components/action/result.rs @@ -70,21 +70,21 @@ pub fn ActionResultView(props: &ActionResultProps) -> Html { ActionResult::BeholderSawNothing => html! { }, - ActionResult::PowerSeer { powerful } => { + ActionResult::PowerSeer { target, powerful } => { html! { - + } } - ActionResult::Adjudicator { killer } => { + ActionResult::Adjudicator { killer, target } => { html! { - + } } - ActionResult::Mortician(died_to) => html! { - + ActionResult::Mortician(target, died_to) => html! { + }, - ActionResult::Empath { scapegoat } => html! { - + ActionResult::Empath { target, scapegoat } => html! { + }, ActionResult::Insomniac(visits) => { html! { @@ -96,17 +96,17 @@ pub fn ActionResultView(props: &ActionResultProps) -> Html { } } - ActionResult::Seer(alignment) => html! { - + ActionResult::Seer(target, alignment) => html! { + }, - ActionResult::Arcanist(same) => { + ActionResult::Arcanist((t1, t2), same) => { html! { - + } } - ActionResult::GraveDigger(role_title) => { + ActionResult::GraveDigger(target, role_title) => { html! { - + } } ActionResult::GoBackToSleep => { diff --git a/werewolves/src/components/story/character.rs b/werewolves/src/components/story/character.rs index 5f4bb31..2732b01 100644 --- a/werewolves/src/components/story/character.rs +++ b/werewolves/src/components/story/character.rs @@ -327,40 +327,40 @@ fn Choice( {"Roleblocked"} }, - StoryActionResult::Seer(alignment) => html! { + StoryActionResult::Seer(_, alignment) => html! { <> {"and saw"} }, - StoryActionResult::PowerSeer { powerful } => html! { + StoryActionResult::PowerSeer { powerful, .. } => html! { <> {"and saw"} }, - StoryActionResult::Adjudicator { killer } => html! { + StoryActionResult::Adjudicator { killer, .. } => html! { <> {"and saw"} }, - StoryActionResult::Arcanist(alignment_eq) => html! { + StoryActionResult::Arcanist(_, alignment_eq) => html! { <> {"and saw them as"} }, - StoryActionResult::GraveDigger(None) => html! { + StoryActionResult::GraveDigger(_, None) => html! { {"but found an empty grave"} }, - StoryActionResult::GraveDigger(Some(role_title)) => html! { + StoryActionResult::GraveDigger(_, Some(role_title)) => html! { <> {"as"} }, - StoryActionResult::Mortician(died_to_title) => html! { + StoryActionResult::Mortician(_, died_to_title) => html! { <> {"and found"} @@ -390,10 +390,14 @@ fn Choice( }) .collect::() } - StoryActionResult::Empath { scapegoat: true } => { + StoryActionResult::Empath { + scapegoat: true, .. + } => { html! {{"and found their scapegoat"}} } - StoryActionResult::Empath { scapegoat: false } => { + StoryActionResult::Empath { + scapegoat: false, .. + } => { html! {{"who was not a scapegoat"}} } StoryActionResult::BeholderSawNothing => html! { diff --git a/werewolves/src/components/story/gamegen.rs b/werewolves/src/components/story/gamegen.rs index b3128ae..7825abe 100644 --- a/werewolves/src/components/story/gamegen.rs +++ b/werewolves/src/components/story/gamegen.rs @@ -652,19 +652,19 @@ impl ActionResultExt for ActionResult { } fn empath(&self) -> bool { match self { - Self::Empath { scapegoat } => *scapegoat, + Self::Empath { scapegoat, .. } => *scapegoat, resp => panic!("expected empath, got {resp:?}"), } } fn mortician(&self) -> DiedToTitle { match self { - Self::Mortician(role) => *role, + Self::Mortician(_, role) => *role, resp => panic!("expected mortician, got {resp:?}"), } } fn gravedigger(&self) -> Option { match self { - Self::GraveDigger(role) => *role, + Self::GraveDigger(_, role) => *role, resp => panic!("expected gravedigger, got {resp:?}"), } } @@ -673,13 +673,13 @@ impl ActionResultExt for ActionResult { } fn adjudicator(&self) -> Killer { match self { - Self::Adjudicator { killer } => *killer, + Self::Adjudicator { killer, .. } => *killer, resp => panic!("expected adjudicator, got {resp:?}"), } } fn power_seer(&self) -> Powerful { match self { - Self::PowerSeer { powerful } => *powerful, + Self::PowerSeer { powerful, .. } => *powerful, resp => panic!("expected power seer, got {resp:?}"), } } @@ -693,14 +693,14 @@ impl ActionResultExt for ActionResult { fn seer(&self) -> Alignment { match self { - ActionResult::Seer(a) => a.clone(), + ActionResult::Seer(_, a) => a.clone(), _ => panic!("expected a seer result"), } } fn arcanist(&self) -> AlignmentEq { match self { - ActionResult::Arcanist(same) => same.clone(), + ActionResult::Arcanist(_, same) => same.clone(), resp => panic!("expected an arcanist result, got {resp:?}"), } } diff --git a/werewolves/src/pages/drunk_page.rs b/werewolves/src/pages/drunk_page.rs index 92476c0..36c510d 100644 --- a/werewolves/src/pages/drunk_page.rs +++ b/werewolves/src/pages/drunk_page.rs @@ -1,7 +1,7 @@ use werewolves_proto::aura::AuraTitle; use yew::prelude::*; -use crate::components::{Icon, IconSource, PartialAssociatedIcon}; +use crate::components::{Icon, IconSource, IconType, PartialAssociatedIcon}; #[function_component] pub fn DrunkPage() -> Html { @@ -10,11 +10,9 @@ pub fn DrunkPage() -> Html {

{"DRUNK"}

-

{"YOU GOT DRUNK INSTEAD"}

-
- -
-

{"YOUR NIGHT ACTION DID NOT TAKE PLACE"}

+ {"YOU GOT DRUNK INSTEAD"} + + {"YOUR NIGHT ACTION DID NOT TAKE PLACE"}
} diff --git a/werewolves/src/pages/role_change.rs b/werewolves/src/pages/role_change.rs index 375b5d7..c5678ec 100644 --- a/werewolves/src/pages/role_change.rs +++ b/werewolves/src/pages/role_change.rs @@ -16,7 +16,7 @@ use convert_case::{Case, Casing}; use werewolves_proto::{game::SetupRole, role::RoleTitle}; use yew::prelude::*; -use crate::components::{Icon, PartialAssociatedIcon}; +use crate::components::{Icon, IconType, PartialAssociatedIcon}; #[derive(Debug, Clone, Copy, PartialEq, Properties)] pub struct RoleChangePageProps { @@ -28,21 +28,19 @@ pub fn RoleChangePage(RoleChangePageProps { role }: &RoleChangePageProps) -> Htm let class = Into::::into(*role).category().class(); let icon = role.icon().map(|icon| { html! { -
- -
+ } }); html! {

{"ROLE CHANGE"}

-

{"YOUR ROLE HAS CHANGED"}

+ {"YOUR ROLE HAS CHANGED"} {icon} -

- {"YOUR NEW ROLE IS "} + + {"YOUR NEW ROLE IS "} {role.to_string().to_case(Case::Upper)} -

+
} diff --git a/werewolves/src/pages/role_page.rs b/werewolves/src/pages/role_page.rs index bea4ee0..6145a12 100644 --- a/werewolves/src/pages/role_page.rs +++ b/werewolves/src/pages/role_page.rs @@ -23,7 +23,7 @@ use yew::prelude::*; use crate::{ components::Identity, - pages::{RoleChangePage, WolfpackKillPage}, + pages::{RoleChangePage, TraitorIntroPage1, TraitorIntroPage2, WolfpackKillPage}, }; werewolves_macros::include_path!("werewolves/src/pages/role_page"); @@ -123,12 +123,20 @@ impl RolePage for ActionPrompt { character_id, recruits_left, .. - } => Rc::new([html! { - <> - {ident(character_id)} - - - }]), + } => Rc::new([ + html! { + <> + {ident(character_id)} + + + }, + html! { + <> + {ident(character_id)} + + + }, + ]), ActionPrompt::MasonsWake { leader, masons } => Rc::new([html! { <> {ident(leader)} @@ -147,12 +155,20 @@ impl RolePage for ActionPrompt { }]), - ActionPrompt::ElderReveal { character_id, .. } => Rc::new([html! { - <> - {ident(character_id)} - - - }]), + ActionPrompt::ElderReveal { character_id, .. } => Rc::new([ + html! { + <> + {ident(character_id)} + + + }, + html! { + <> + {ident(character_id)} + + + }, + ]), ActionPrompt::Guardian { character_id, previous: None, @@ -253,6 +269,20 @@ impl RolePage for ActionPrompt { }]), + ActionPrompt::TraitorIntro { character_id } => Rc::new([ + html! { + <> + {ident(character_id)} + + + }, + html! { + <> + {ident(character_id)} + + + }, + ]), _ => Rc::new([]), } } diff --git a/werewolves/src/pages/role_page/adjudicator.rs b/werewolves/src/pages/role_page/adjudicator.rs index 720a0fb..a70c404 100644 --- a/werewolves/src/pages/role_page/adjudicator.rs +++ b/werewolves/src/pages/role_page/adjudicator.rs @@ -12,10 +12,10 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use werewolves_proto::role::Killer; +use werewolves_proto::{message::PublicIdentity, role::Killer}; use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IdentitySpan}; #[function_component] pub fn AdjudicatorPage1() -> Html { @@ -23,23 +23,24 @@ pub fn AdjudicatorPage1() -> Html {

{"ADJUDICATOR"}

-

{"PICK A PLAYER"}

-
- -
-

{"YOU WILL CHECK IF THEY APPEAR AS A KILLER"}

+

{"PICK A PLAYER"}

+ +

{"YOU WILL CHECK IF THEY APPEAR AS A KILLER"}

} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct AdjudicatorResultProps { pub killer: Killer, + pub target: PublicIdentity, } #[function_component] -pub fn AdjudicatorResult(AdjudicatorResultProps { killer }: &AdjudicatorResultProps) -> Html { +pub fn AdjudicatorResult( + AdjudicatorResultProps { killer, target }: &AdjudicatorResultProps, +) -> Html { let text = match killer { Killer::Killer => "IS A KILLER", Killer::NotKiller => "IS NOT A KILLER", @@ -60,8 +61,8 @@ pub fn AdjudicatorResult(AdjudicatorResultProps { killer }: &AdjudicatorResultPr

{"ADJUDICATOR"}

-

{"YOUR TARGET"}

-
{icon}
+ + {icon}

{text}

diff --git a/werewolves/src/pages/role_page/alpha_wolf.rs b/werewolves/src/pages/role_page/alpha_wolf.rs index 9e6c0a0..6fbfa98 100644 --- a/werewolves/src/pages/role_page/alpha_wolf.rs +++ b/werewolves/src/pages/role_page/alpha_wolf.rs @@ -20,15 +20,12 @@ pub fn AlphaWolfPage1() -> Html {

{"ALPHA WOLF"}

-

+ {"IF YOU WISH TO USE YOUR "} {"ONCE PER GAME"} {" KILL ABILITY"} -

-

- {"POINT AT YOUR TARGET "} - {"OR GO BACK TO SLEEP"} -

+ + {"POINT AT YOUR TARGET OR GO BACK TO SLEEP"}
} diff --git a/werewolves/src/pages/role_page/arcanist.rs b/werewolves/src/pages/role_page/arcanist.rs index 857fdb7..eb8c265 100644 --- a/werewolves/src/pages/role_page/arcanist.rs +++ b/werewolves/src/pages/role_page/arcanist.rs @@ -12,10 +12,10 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use werewolves_proto::role::AlignmentEq; +use werewolves_proto::{message::PublicIdentity, role::AlignmentEq}; use yew::prelude::*; -use crate::components::{Icon, IconSource, IconType}; +use crate::components::{Icon, IconSource, IconType, IdentitySpan}; #[function_component] pub fn ArcanistPage1() -> Html { @@ -23,50 +23,59 @@ pub fn ArcanistPage1() -> Html {

{"ARCANIST"}

-

{"PICK TWO PLAYERS"}

-

- - // - // - -

-

{"YOU WILL CHECK IF THEIR ALIGNMENTS ARE THE SAME OR DIFFERENT"}

+ {"PICK TWO PLAYERS"} +
+ + +
+ {"YOU WILL COMPARE THEIR ALIGNMENTS"}
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct ArcanistResultProps { pub alignment_eq: AlignmentEq, + pub targets: (PublicIdentity, PublicIdentity), } #[function_component] -pub fn ArcanistResult(ArcanistResultProps { alignment_eq }: &ArcanistResultProps) -> Html { +pub fn ArcanistResult( + ArcanistResultProps { + alignment_eq, + targets: (t1, t2), + }: &ArcanistResultProps, +) -> Html { let text = match alignment_eq { - AlignmentEq::Same => "THE SAME", - AlignmentEq::Different => "DIFFERENT", + AlignmentEq::Same => "ARE THE SAME", + AlignmentEq::Different => "ARE DIFFERENT", }; let icons = match alignment_eq { AlignmentEq::Same => html! { - + }, AlignmentEq::Different => html! { - <> - - - + }, }; html! {

{"ARCANIST"}

-

{"YOUR TARGETS APPEAR AS"}

-
+
+ + {"AND"} + +
+
{icons}
-

{text}

+ {text}
} diff --git a/werewolves/src/pages/role_page/beholder.rs b/werewolves/src/pages/role_page/beholder.rs index 0312c51..0db1f2e 100644 --- a/werewolves/src/pages/role_page/beholder.rs +++ b/werewolves/src/pages/role_page/beholder.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn BeholderPage1() -> Html { @@ -22,9 +22,10 @@ pub fn BeholderPage1() -> Html {

{"BEHOLDER"}

-

{"PICK A PLAYER"}

-

{"YOU WILL SEE WHAT INFORMATION THEY MAY HAVE GATHERED"}

-

{"SHOULD THEY DIE TONIGHT"}

+ {"PICK A PLAYER"} + + {"YOU WILL SEE WHAT INFORMATION THEY MAY HAVE GATHERED"} + {"SHOULD THEY DIE TONIGHT"}
} @@ -36,11 +37,9 @@ pub fn BeholderWakePage1() -> Html {

{"BEHOLDER"}

-

{"YOUR TARGET HAS DIED"}

-
- -
-

{"THIS IS THE LAST PIECE OF INFORMATION THEY SAW"}

+ {"YOUR TARGET HAS DIED"} + + {"THIS IS THE LAST PIECE OF INFORMATION THEY SAW"}
} @@ -68,16 +67,14 @@ pub fn BeholderSawEverything() -> Html {

{"BEHOLDER"}

-

{"YOUR TARGET HAS DIED"}

-
- -
-

+ {"YOUR TARGET HAS DIED"} + + {"BUT SAW "} {"EVERYTHING"} -

+
} diff --git a/werewolves/src/pages/role_page/bloodletter.rs b/werewolves/src/pages/role_page/bloodletter.rs index cedb5af..f47d7d1 100644 --- a/werewolves/src/pages/role_page/bloodletter.rs +++ b/werewolves/src/pages/role_page/bloodletter.rs @@ -22,17 +22,16 @@ pub fn BloodletterPage1() -> Html {

{"BLOODLETTER"}

-

{"PICK A PLAYER"}

-

{"THEY WILL BE COVERED IN WOLF BLOOD"}

-

- {"AND APPEAR AS A WOLF "} + {"PICK A PLAYER"} + + {"THEY'LL APPEAR AS A WOLF "} - {" KILLER "} + {"KILLER"} - {" AND POWERFUL "} + {"AND POWERFUL"} - {" IN CHECKS"} -

+ {"IN CHECKS FOR 2 NIGHTS"} +
} diff --git a/werewolves/src/pages/role_page/direwolf.rs b/werewolves/src/pages/role_page/direwolf.rs index e06252e..0828f66 100644 --- a/werewolves/src/pages/role_page/direwolf.rs +++ b/werewolves/src/pages/role_page/direwolf.rs @@ -20,9 +20,9 @@ pub fn DirewolfPage1() -> Html {

{"DIREWOLF"}

-

{"CHOOSE A TARGET"}

-

{"ANY VISITORS TO THIS TARGET WILL BE ROLE BLOCKED"}

-

{"YOU CANNOT CHOOSE YOURSELF OR THE SAME TARGET AS LAST NIGHT"}

+ {"CHOOSE A TARGET"} + {"ANY VISITORS TO THIS TARGET WILL BE ROLE BLOCKED"} + {"YOU CANNOT CHOOSE YOURSELF OR THE SAME TARGET AS LAST NIGHT"}
} diff --git a/werewolves/src/pages/role_page/elder.rs b/werewolves/src/pages/role_page/elder.rs index e6b9063..2285a0b 100644 --- a/werewolves/src/pages/role_page/elder.rs +++ b/werewolves/src/pages/role_page/elder.rs @@ -20,15 +20,24 @@ pub fn ElderPage1() -> Html {

{"ELDER"}

-

{"YOU ARE THE ELDER"}

-

+ {"YOU ARE THE ELDER"} + {"IF YOU ARE EXECUTED BY THE VILLAGE FROM NOW ON "} {"ALL POWER ROLES WILL BE LOST"} -

-

- {"YOU STARTED THE GAME WITH PROTECTION FROM A NIGHT "} - {"DEATH — THIS MAY OR MAY NOT STILL BE INTACT"} -

+ +
+
+ } +} + +#[function_component] +pub fn ElderPage2() -> Html { + html! { +
+

{"ELDER"}

+
+ {"YOU STARTED THE GAME WITH PROTECTION FROM A NIGHT "} + {"DEATH — THIS MAY OR MAY NOT STILL BE INTACT"}
} diff --git a/werewolves/src/pages/role_page/empath.rs b/werewolves/src/pages/role_page/empath.rs index 3d0cd61..f82d775 100644 --- a/werewolves/src/pages/role_page/empath.rs +++ b/werewolves/src/pages/role_page/empath.rs @@ -13,9 +13,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +use werewolves_proto::message::PublicIdentity; use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType, IdentitySpan}; #[function_component] pub fn EmpathPage1() -> Html { @@ -23,34 +24,35 @@ pub fn EmpathPage1() -> Html {

{"EMPATH"}

-

{"PICK A PLAYER"}

-

{"YOU WILL CHECK IF THEY ARE THE SCAPEGOAT"}

-

{"IF THEY ARE, YOU WILL TAKE ON THEIR CURSE"}

+ {"PICK A PLAYER"} + {"YOU WILL CHECK IF THEY ARE THE SCAPEGOAT"} + {"IF THEY ARE, YOU WILL TAKE ON THEIR CURSE"}
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct EmpathResultProps { pub scapegoat: bool, + pub target: PublicIdentity, } #[function_component] -pub fn EmpathResult(EmpathResultProps { scapegoat }: &EmpathResultProps) -> Html { +pub fn EmpathResult(EmpathResultProps { scapegoat, target }: &EmpathResultProps) -> Html { let text = match scapegoat { - true => "THE SCAPEGOAT", - false => "NOT THE SCAPEGOAT", + true => "IS THE SCAPEGOAT", + false => "IS NOT THE SCAPEGOAT", }; let icon = match scapegoat { true => html! { }, false => html! { }, }; @@ -58,11 +60,9 @@ pub fn EmpathResult(EmpathResultProps { scapegoat }: &EmpathResultProps) -> Html

{"EMPATH"}

-

{"YOUR TARGET IS"}

-
- {icon} -
-

{text}

+ + {icon} + {text}
} diff --git a/werewolves/src/pages/role_page/gravedigger.rs b/werewolves/src/pages/role_page/gravedigger.rs index a706bec..eb46e59 100644 --- a/werewolves/src/pages/role_page/gravedigger.rs +++ b/werewolves/src/pages/role_page/gravedigger.rs @@ -13,10 +13,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use convert_case::{Case, Casing}; -use werewolves_proto::role::RoleTitle; +use werewolves_proto::{message::PublicIdentity, role::RoleTitle}; use yew::prelude::*; -use crate::components::{Icon, IconSource, PartialAssociatedIcon}; +use crate::components::{Icon, IconSource, IconType, IdentitySpan, PartialAssociatedIcon}; #[function_component] pub fn GravediggerPage1() -> Html { @@ -24,46 +24,45 @@ pub fn GravediggerPage1() -> Html {

{"GRAVEDIGGER"}

-

+ {"PICK A "} {"DEAD"} {" PLAYER"} -

-
- -
-

+ + + {"YOU WILL LEARN THEIR ROLE"} -

+
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct GravediggerResultPageProps { pub role: Option, + pub target: PublicIdentity, } #[function_component] pub fn GravediggerResultPage( - GravediggerResultPageProps { role }: &GravediggerResultPageProps, + GravediggerResultPageProps { role, target }: &GravediggerResultPageProps, ) -> Html { let text = role .as_ref() .map(|r| { html! { -

- {"AND FIND A "} + <> + {"WAS A "} {r.to_string().to_case(Case::Upper)} -

+ } }) .unwrap_or_else(|| { html! { -

{"BUT INSTEAD YOU FIND AN EMPTY GRAVE"}

+ {"YOU FIND AN EMPTY GRAVE"} } }); let icon = role @@ -74,10 +73,8 @@ pub fn GravediggerResultPage(

{"GRAVEDIGGER"}

-

{"YOU CHECK THE ROLE OF YOUR TARGET"}

-
- -
+ + {text}
diff --git a/werewolves/src/pages/role_page/guardian.rs b/werewolves/src/pages/role_page/guardian.rs index 2955771..07ddbbe 100644 --- a/werewolves/src/pages/role_page/guardian.rs +++ b/werewolves/src/pages/role_page/guardian.rs @@ -15,7 +15,7 @@ use werewolves_proto::message::CharacterIdentity; use yew::prelude::*; -use crate::components::{CharacterTargetCard, Icon, IconSource}; +use crate::components::{CharacterTargetCard, Icon, IconSource, IconType}; #[derive(Debug, Clone, PartialEq, Properties)] pub struct GuardianPageProps { @@ -28,11 +28,9 @@ pub fn GuardianPageNoPrevProtect() -> Html {

{"GUARDIAN"}

-

{"PICK A PLAYER"}

-
- -
-

{"CHOOSE SOMEONE TO PROTECT FROM DEATH"}

+ {"PICK A PLAYER"} + + {"CHOOSE SOMEONE TO PROTECT FROM DEATH"}
} @@ -44,8 +42,8 @@ pub fn GuardianPagePreviousProtectSelf() -> Html {

{"GUARDIAN"}

-

{"LAST TIME YOU PROTECTED YOURSELF"}

-

{"YOU CANNOT PROTECT YOURSELF AGAIN TONIGHT"}

+ {"LAST TIME YOU PROTECTED YOURSELF"} + {"YOU CANNOT PROTECT YOURSELF AGAIN TONIGHT"}
} @@ -57,14 +55,12 @@ pub fn GuardianPagePreviousProtect1(GuardianPageProps { previous }: &GuardianPag

{"GUARDIAN"}

-

{"LAST TIME YOU PROTECTED"}

-
- -
+ {"LAST TIME YOU PROTECTED"} +
-

{"IF YOU PROTECT THEM AGAIN, YOU WILL INSTEAD GUARD THEM"}

+ {"IF YOU PROTECT THEM AGAIN, YOU WILL INSTEAD GUARD THEM"}
} @@ -76,14 +72,12 @@ pub fn GuardianPagePreviousProtect2(GuardianPageProps { previous }: &GuardianPag

{"GUARDIAN"}

-

{"LAST TIME YOU PROTECTED"}

-
- -
+ {"LAST TIME YOU PROTECTED"} +
-

{"IF ATTACKED WHILE GUARDED, YOU AND THEIR ATTACKER WILL INSTEAD DIE"}

+ {"IF ATTACKED WHILE GUARDED, YOU AND THEIR ATTACKER WILL INSTEAD DIE"}
} @@ -95,14 +89,12 @@ pub fn GuardianPagePreviousGuard(GuardianPageProps { previous }: &GuardianPagePr

{"GUARDIAN"}

-

{"LAST TIME YOU GUARDED"}

-
- -
+ {"LAST TIME YOU GUARDED"} +
-

{"YOU CANNOT PROTECT THEM TONIGHT"}

+ {"YOU CANNOT PROTECT THEM TONIGHT"}
} diff --git a/werewolves/src/pages/role_page/hunter.rs b/werewolves/src/pages/role_page/hunter.rs index c339be3..c06c221 100644 --- a/werewolves/src/pages/role_page/hunter.rs +++ b/werewolves/src/pages/role_page/hunter.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn HunterPage1() -> Html { @@ -22,14 +22,12 @@ pub fn HunterPage1() -> Html {

{"HUNTER"}

-

{"SET A HUNTER'S TRAP ON A PLAYER"}

-
- -
-

+ {"SET A HUNTER'S TRAP ON A PLAYER"} + + {"IF YOU DIE TONIGHT, OR ARE EXECUTED TOMORROW "} {"THIS PLAYER WILL DIE AT NIGHT"} -

+
} diff --git a/werewolves/src/pages/role_page/insomniac.rs b/werewolves/src/pages/role_page/insomniac.rs index bddd87e..f345b49 100644 --- a/werewolves/src/pages/role_page/insomniac.rs +++ b/werewolves/src/pages/role_page/insomniac.rs @@ -15,7 +15,7 @@ use werewolves_proto::message::night::Visits; use yew::prelude::*; -use crate::components::{CharacterTargetCard, Icon, IconSource, Identity}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn InsomniacPage1() -> Html { @@ -23,13 +23,9 @@ pub fn InsomniacPage1() -> Html {

{"INSOMNIAC"}

-

{"YOUR SLEEP IS INTERRUPTED"}

-
- -
-

- {"THE FOLLOWING PEOPLE VISITED YOU TONIGHT"} -

+ {"YOUR SLEEP IS INTERRUPTED"} + + {"YOU'VE NOTICED VISITORS IN THE NIGHT"}
} @@ -57,7 +53,7 @@ pub fn InsomniacResult(InsomniacResultProps { visits }: &InsomniacResultProps) -

{"INSOMNIAC"}

-

{"YOU WERE VISITED IN THE NIGHT BY:"}

+ {"YOU WERE VISITED IN THE NIGHT BY:"}
{visitors}
diff --git a/werewolves/src/pages/role_page/lone_wolf.rs b/werewolves/src/pages/role_page/lone_wolf.rs index 11ad31f..fca5920 100644 --- a/werewolves/src/pages/role_page/lone_wolf.rs +++ b/werewolves/src/pages/role_page/lone_wolf.rs @@ -20,13 +20,13 @@ pub fn LoneWolfPage1() -> Html {

{"LONE WOLF"}

-

+ {"YOU MUST KILL TONIGHT IN ANGER OVER A FELLOW "} {"WOLF HAVING BEEN SLAIN"} -

-

- {"POINT AT YOUR TARGET "} -

+ + + {"PICK A PLAYER"} +
} diff --git a/werewolves/src/pages/role_page/maple_wolf.rs b/werewolves/src/pages/role_page/maple_wolf.rs index 8d23264..63d3021 100644 --- a/werewolves/src/pages/role_page/maple_wolf.rs +++ b/werewolves/src/pages/role_page/maple_wolf.rs @@ -29,10 +29,10 @@ pub fn MapleWolfPage1( ) -> Html { let food_state = if *nights_til_starvation == 0 { html! { -
-

{"YOU ARE STARVING"}

-

{"IF YOU FAIL TO EAT TONIGHT, YOU WILL DIE"}

-
+ <> + {"YOU ARE STARVING"} + {"IF YOU FAIL TO EAT TONIGHT, YOU WILL DIE"} + } } else { let nights = if *nights_til_starvation == 1 { @@ -49,23 +49,19 @@ pub fn MapleWolfPage1( } }; html! { -

+ {"IF YOU FAIL TO EAT "} {nights} {"YOU WILL "}{"STARVE"} -

+ } }; html! {

{"MAPLE WOLF"}

-

- {"YOU CAN CHOOSE TO EAT A PLAYER TONIGHT"} -

-
- -
+ {"YOU CAN CHOOSE TO EAT A PLAYER TONIGHT"} + {food_state}
diff --git a/werewolves/src/pages/role_page/mason.rs b/werewolves/src/pages/role_page/mason.rs index 00dcc5d..b07ae07 100644 --- a/werewolves/src/pages/role_page/mason.rs +++ b/werewolves/src/pages/role_page/mason.rs @@ -47,13 +47,23 @@ pub fn MasonRecruitPage1(

{"MASON LEADER"}

-

{"YOU HAVE "}{recruitments}{" LEFT"}

-

- {"ANYONE YOU RECRUIT INTO THE MASONS WILL WAKE WITH YOU "} - {"EVERY NIGHT"} - {", AS LONG AS THEY ARE ALIVE AND REMAIN VILLAGE ALIGNED"} -

-

{"WOULD YOU LIKE TO RECRUIT TONIGHT?"}

+ {"YOU HAVE "}{recruitments}{" LEFT"} + + {"RECRUITS WILL WAKE WITH YOU EVERY NIGHT"} + {" WHILE THEY ARE ALIVE AND REMAIN VILLAGE ALIGNED"} + +
+
+ } +} + +#[function_component] +pub fn MasonRecruitPage2() -> Html { + html! { +
+

{"MASON LEADER"}

+
+ {"WOULD YOU LIKE TO RECRUIT TONIGHT?"}
} @@ -85,7 +95,7 @@ pub fn MasonsWake(MasonsWakeProps { leader, masons }: &MasonsWakeProps) -> Html

{title}

-

{"YOU ARE ALL MEMBERS "}

+ {"THE MASONS CONVENE AT NIGHT"}
{masons}
diff --git a/werewolves/src/pages/role_page/militia.rs b/werewolves/src/pages/role_page/militia.rs index 181f1d5..85a9eb2 100644 --- a/werewolves/src/pages/role_page/militia.rs +++ b/werewolves/src/pages/role_page/militia.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn MilitiaPage1() -> Html { @@ -22,18 +22,16 @@ pub fn MilitiaPage1() -> Html {

{"MILITIA"}

-

+ {"IF YOU WISH TO USE YOUR "} {"ONCE PER GAME"} {" KILL ABILITY"} -

-
- -
-

- {"POINT AT YOUR TARGET "} + + + + {"PICK A PLAYER "} {"OR GO BACK TO SLEEP"} -

+
} diff --git a/werewolves/src/pages/role_page/mortician.rs b/werewolves/src/pages/role_page/mortician.rs index 3008846..801d3b1 100644 --- a/werewolves/src/pages/role_page/mortician.rs +++ b/werewolves/src/pages/role_page/mortician.rs @@ -12,10 +12,10 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use werewolves_proto::diedto::DiedToTitle; +use werewolves_proto::{diedto::DiedToTitle, message::PublicIdentity}; use yew::prelude::*; -use crate::components::{Icon, IconSource, IconType, PartialAssociatedIcon}; +use crate::components::{Icon, IconSource, IconType, IdentitySpan, PartialAssociatedIcon}; #[function_component] pub fn MorticianPage1() -> Html { @@ -23,31 +23,26 @@ pub fn MorticianPage1() -> Html {

{"MORTICIAN"}

-

- {"PICK A "} - {"DEAD"} - {" PLAYER"} -

-
- -
-

+ {"PICK A "}{"DEAD"}{" PLAYER"} + + {"YOU WILL LEARN THE CAUSE "} {"OF THEIR DEATH"} -

+
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct MorticianResultPageProps { pub died_to: DiedToTitle, + pub target: PublicIdentity, } #[function_component] pub fn MorticianResultPage( - MorticianResultPageProps { died_to }: &MorticianResultPageProps, + MorticianResultPageProps { died_to, target }: &MorticianResultPageProps, ) -> Html { let text = match died_to { DiedToTitle::Execution => "Execution", @@ -69,11 +64,10 @@ pub fn MorticianResultPage(

{"MORTICIAN"}

-

{"YOUR TARGET DIED TO"}

-
- -
-

{text}

+ + {"DIED TO"} + + {text}
} diff --git a/werewolves/src/pages/role_page/power_seer.rs b/werewolves/src/pages/role_page/power_seer.rs index 101f882..10ae7c2 100644 --- a/werewolves/src/pages/role_page/power_seer.rs +++ b/werewolves/src/pages/role_page/power_seer.rs @@ -13,10 +13,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use werewolves_proto::role::Powerful; +use werewolves_proto::{message::PublicIdentity, role::Powerful}; use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IdentitySpan}; #[function_component] pub fn PowerSeerPage1() -> Html { @@ -24,38 +24,37 @@ pub fn PowerSeerPage1() -> Html {

{"POWER SEER"}

-

{"PICK A PLAYER"}

+ {"PICK A PLAYER"}
-

{"YOU WILL CHECK IF THEY ARE POWERFUL"}

+ {"YOU WILL CHECK IF THEY ARE POWERFUL"}
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct PowerSeerResultProps { pub powerful: Powerful, + pub target: PublicIdentity, } #[function_component] -pub fn PowerSeerResult(PowerSeerResultProps { powerful }: &PowerSeerResultProps) -> Html { +pub fn PowerSeerResult(PowerSeerResultProps { powerful, target }: &PowerSeerResultProps) -> Html { let text = match powerful { - Powerful::Powerful => "POWERFUL", - Powerful::NotPowerful => "NOT POWERFUL", + Powerful::Powerful => "IS POWERFUL", + Powerful::NotPowerful => "IS NOT POWERFUL", }; let icon = match powerful { Powerful::Powerful => html! { }, Powerful::NotPowerful => html! { }, }; @@ -63,7 +62,7 @@ pub fn PowerSeerResult(PowerSeerResultProps { powerful }: &PowerSeerResultProps)

{"POWER SEER"}

-

{"YOUR TARGET APPEARS AS"}

+
{icon}

{text}

diff --git a/werewolves/src/pages/role_page/protector.rs b/werewolves/src/pages/role_page/protector.rs index 1f2f2f8..e880ff3 100644 --- a/werewolves/src/pages/role_page/protector.rs +++ b/werewolves/src/pages/role_page/protector.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn ProtectorPage1() -> Html { @@ -22,11 +22,9 @@ pub fn ProtectorPage1() -> Html {

{"PROTECTOR"}

-

{"PICK A PLAYER"}

-
- -
-

{"YOU WILL PROTECT THEM FROM A DEATH TONIGHT"}

+ {"PICK A PLAYER"} + + {"YOU WILL PROTECT THEM FROM A DEATH TONIGHT"}
} diff --git a/werewolves/src/pages/role_page/pyremaster.rs b/werewolves/src/pages/role_page/pyremaster.rs index 289b71b..7381537 100644 --- a/werewolves/src/pages/role_page/pyremaster.rs +++ b/werewolves/src/pages/role_page/pyremaster.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn PyremasterPage1() -> Html { @@ -22,16 +22,14 @@ pub fn PyremasterPage1() -> Html {

{"PYREMASTER"}

-

{"YOU CAN CHOOSE TO THROW A PLAYER ON THE PYRE"}

-
- -
-

+ {"YOU CAN CHOOSE TO THROW A PLAYER ON THE PYRE"} + + {"IF YOU KILL "} {"TWO"} {" GOOD VILLAGERS LIKE THIS "} {"YOU WILL DIE AS WELL"} -

+
} diff --git a/werewolves/src/pages/role_page/seer.rs b/werewolves/src/pages/role_page/seer.rs index 1655624..db7b3b5 100644 --- a/werewolves/src/pages/role_page/seer.rs +++ b/werewolves/src/pages/role_page/seer.rs @@ -12,10 +12,15 @@ // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use werewolves_proto::role::{Alignment, RoleTitle}; +use werewolves_proto::{ + message::PublicIdentity, + role::{Alignment, RoleTitle}, +}; use yew::prelude::*; -use crate::components::{AssociatedIcon, Icon, IconSource, IconType, attributes::RoleTitleSpan}; +use crate::components::{ + AssociatedIcon, Icon, IconSource, IconType, IdentitySpan, attributes::RoleTitleSpan, +}; #[function_component] pub fn SeerPage1() -> Html { @@ -23,24 +28,25 @@ pub fn SeerPage1() -> Html {

{"SEER"}

-

{"PICK A PLAYER"}

-
- - + {"PICK A PLAYER"} +
+ +
-

{"YOU WILL CHECK IF THEY APPEAR AS A VILLAGER OR PART OF THE WOLFPACK"}

+ {"YOU WILL CHECK THEIR ALIGNMENT"}
} } -#[derive(Debug, Clone, Copy, PartialEq, Properties)] +#[derive(Debug, Clone, PartialEq, Properties)] pub struct SeerResultProps { pub alignment: Alignment, + pub target: PublicIdentity, } #[function_component] -pub fn SeerResult(SeerResultProps { alignment }: &SeerResultProps) -> Html { +pub fn SeerResult(SeerResultProps { alignment, target }: &SeerResultProps) -> Html { let text = match alignment { Alignment::Village => "VILLAGE", Alignment::Wolves => "WOLFPACK", @@ -61,11 +67,9 @@ pub fn SeerResult(SeerResultProps { alignment }: &SeerResultProps) -> Html { }, Alignment::Traitor => html! {
-

- {"THIS PERSON IS A "} - {"TRAITOR"} -

-

{"THEY WIN ALONGSIDE EVIL"}

+ {"THIS PERSON IS A "} + {"TRAITOR"} + {"THEY WIN ALONGSIDE EVIL"}
}, }; @@ -75,11 +79,9 @@ pub fn SeerResult(SeerResultProps { alignment }: &SeerResultProps) -> Html {
-

{"YOUR TARGET APPEARS AS"}

- -

{text}

+ + + {text}
{additional_info}
@@ -106,16 +108,15 @@ fn FalselyAppearsAs( .copied() .map(|role| { html! { - + } }) .collect::(); html! {
-
{"ROLES THAT FALSELY APPEAR AS "} {*alignment_text} -
{false_positives}
diff --git a/werewolves/src/pages/role_page/vindicator.rs b/werewolves/src/pages/role_page/vindicator.rs index c07526f..d6e777c 100644 --- a/werewolves/src/pages/role_page/vindicator.rs +++ b/werewolves/src/pages/role_page/vindicator.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn VindicatorPage1() -> Html { @@ -22,12 +22,9 @@ pub fn VindicatorPage1() -> Html {

{"VINDICATOR"}

-

{"A VILLAGER WAS EXECUTED"}

-

{"PICK A PLAYER"}

-
- -
-

{"YOU WILL PROTECT THEM FROM A DEATH TONIGHT"}

+ {"A VILLAGER WAS EXECUTED"} + + {"PICK A PLAYER TO PROTECT FROM A DEATH TONIGHT"}
} diff --git a/werewolves/src/pages/roleblock.rs b/werewolves/src/pages/roleblock.rs index b6aef2f..abecd4d 100644 --- a/werewolves/src/pages/roleblock.rs +++ b/werewolves/src/pages/roleblock.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn RoleblockPage() -> Html { @@ -22,11 +22,9 @@ pub fn RoleblockPage() -> Html {

{"ROLE BLOCKED"}

-

{"YOU WERE ROLE BLOCKED"}

-
- -
-

{"YOUR NIGHT ACTION DID NOT TAKE PLACE"}

+ {"YOU WERE ROLE BLOCKED"} + + {"YOUR NIGHT ACTION DID NOT TAKE PLACE"}
} diff --git a/werewolves/src/pages/shift_failed.rs b/werewolves/src/pages/shift_failed.rs index 6ff7102..0e24cc9 100644 --- a/werewolves/src/pages/shift_failed.rs +++ b/werewolves/src/pages/shift_failed.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] pub fn ShiftFailed() -> Html { @@ -22,13 +22,9 @@ pub fn ShiftFailed() -> Html {

{"SHIFT FAILED"}

-

{"YOUR SHIFT HAS FAILED"}

-
- -
-

- {"YOU RETAIN YOUR SHAPESHIFT ABILITY"} -

+ {"YOUR SHIFT HAS FAILED"} + + {"YOU RETAIN YOUR SHAPESHIFT ABILITY"}
} diff --git a/werewolves/src/pages/traitor.rs b/werewolves/src/pages/traitor.rs index 942b68b..3492a92 100644 --- a/werewolves/src/pages/traitor.rs +++ b/werewolves/src/pages/traitor.rs @@ -1,22 +1,30 @@ use yew::prelude::*; -use crate::components::{Icon, IconSource}; +use crate::components::{Icon, IconSource, IconType}; #[function_component] -pub fn TraitorIntroPage() -> Html { +pub fn TraitorIntroPage1() -> Html { html! {
-

{"TRAITOR"}

+

{"DAMNED"}

-

{"YOU ARE A TRAITOR"}

-

{"YOU RETAIN YOUR ROLE AND WIN IF EVIL WINS"}

-
- -
-

{"HOWEVER"}

-

- {"YOU CONTRIBUTE TO VILLAGE PARITY"} -

+ {"YOU ARE DAMNED"} + +
+
+ } +} + +#[function_component] +pub fn TraitorIntroPage2() -> Html { + html! { +
+

{"DAMNED"}

+
+ {"YOU RETAIN YOUR ROLE AND WIN IF EVIL WINS"} + + {"HOWEVER, YOU CONTRIBUTE TO VILLAGE PARITY"} +
} diff --git a/werewolves/src/test_util/mod.rs b/werewolves/src/test_util/mod.rs index 5823201..b8fb882 100644 --- a/werewolves/src/test_util/mod.rs +++ b/werewolves/src/test_util/mod.rs @@ -136,7 +136,7 @@ pub fn TestScreenSelector( let class = prompt_class(&prompt); html! {
  • -
  • @@ -172,7 +172,7 @@ pub fn TestScreenSelector( let class = result_class(&result); html! {
  • -
  • @@ -225,18 +225,28 @@ impl From for TestScreen { TestScreen::Result(match value { ActionResultTitle::RoleBlocked => ActionResult::RoleBlocked, ActionResultTitle::Drunk => ActionResult::Drunk, - ActionResultTitle::Seer => ActionResult::Seer(Alignment::Village), + ActionResultTitle::Seer => ActionResult::Seer(identity(), Alignment::Village), ActionResultTitle::PowerSeer => ActionResult::PowerSeer { + target: identity(), powerful: Powerful::Powerful, }, ActionResultTitle::Adjudicator => ActionResult::Adjudicator { + target: identity(), killer: Killer::Killer, }, - ActionResultTitle::Arcanist => ActionResult::Arcanist(AlignmentEq::Same), - ActionResultTitle::GraveDigger => ActionResult::GraveDigger(None), - ActionResultTitle::Mortician => ActionResult::Mortician(DiedToTitle::Execution), + ActionResultTitle::Arcanist => ActionResult::Arcanist( + (identity(), identities(2).last().cloned().unwrap()), + AlignmentEq::Same, + ), + ActionResultTitle::GraveDigger => ActionResult::GraveDigger(identity(), None), + ActionResultTitle::Mortician => { + ActionResult::Mortician(identity(), DiedToTitle::Execution) + } ActionResultTitle::Insomniac => ActionResult::Insomniac(Visits::new(identities(2))), - ActionResultTitle::Empath => ActionResult::Empath { scapegoat: true }, + ActionResultTitle::Empath => ActionResult::Empath { + target: identity(), + scapegoat: true, + }, ActionResultTitle::BeholderSawNothing => ActionResult::BeholderSawNothing, ActionResultTitle::BeholderSawEverything => ActionResult::BeholderSawEverything, ActionResultTitle::GoBackToSleep => ActionResult::GoBackToSleep, diff --git a/werewolves/src/test_util/result.rs b/werewolves/src/test_util/result.rs index 17146d5..3c4c53f 100644 --- a/werewolves/src/test_util/result.rs +++ b/werewolves/src/test_util/result.rs @@ -49,16 +49,17 @@ pub fn ResultScreenTest( | ActionResult::Continue | ActionResult::Drunk | ActionResult::RoleBlocked => html! {}, - ActionResult::Seer(alignment) => { + ActionResult::Seer(target, alignment) => { let all = Alignment::ALL .into_iter() .map(|align| { let on_click = { + let target= target.clone(); let send = send.clone(); Callback::from(move |_| { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Seer(align), + ActionResult::Seer(target.clone(), align), )); }) }; @@ -76,14 +77,18 @@ pub fn ResultScreenTest(
    } } - ActionResult::PowerSeer { powerful } => { + ActionResult::PowerSeer { target, powerful } => { let on_toggle = { let set = !*powerful; let send = send.clone(); + let target = target.clone(); Callback::from(move |_| { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::PowerSeer { powerful: set }, + ActionResult::PowerSeer { + target: target.clone(), + powerful: set, + }, )); }) }; @@ -98,14 +103,18 @@ pub fn ResultScreenTest(
    } } - ActionResult::Adjudicator { killer } => { + ActionResult::Adjudicator { target, killer } => { let on_toggle = { let set = !*killer; let send = send.clone(); + let target = target.clone(); Callback::from(move |_| { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Adjudicator { killer: set }, + ActionResult::Adjudicator { + target: target.clone(), + killer: set, + }, )); }) }; @@ -120,14 +129,15 @@ pub fn ResultScreenTest(
    } } - ActionResult::Arcanist(alignment_eq) => { + ActionResult::Arcanist(targets, alignment_eq) => { let on_toggle = { let set = !*alignment_eq; let send = send.clone(); + let targets = targets.clone(); Callback::from(move |_| { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Arcanist(set), + ActionResult::Arcanist(targets.clone(), set), )); }) }; @@ -142,7 +152,7 @@ pub fn ResultScreenTest(
    } } - ActionResult::GraveDigger(role_title) => { + ActionResult::GraveDigger(target, role_title) => { let possibilities = [None] .into_iter() .chain(RoleTitle::ALL.into_iter().map(Some)) @@ -162,6 +172,7 @@ pub fn ResultScreenTest( let on_change_cb = { let send = send.clone(); let possibilities = possibilities.clone(); + let target = target.clone(); Callback::from(move |ev: Event| { if let Some(select) = ev.target_dyn_into::() { let selected = select.selected_index(); @@ -171,7 +182,7 @@ pub fn ResultScreenTest( if let Some(new_role) = possibilities.get(selected as usize) { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::GraveDigger(*new_role), + ActionResult::GraveDigger(target.clone(), *new_role), )); } } @@ -179,6 +190,7 @@ pub fn ResultScreenTest( }; let on_wheel = { let send = send.clone(); + let res_target = target.clone(); let possibilities = possibilities.clone(); Callback::from(move |ev: WheelEvent| { let Some(target) = ev.target_dyn_into::() else { @@ -206,7 +218,7 @@ pub fn ResultScreenTest( if let Some(new_role) = possibilities.get(new_index as usize) { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::GraveDigger(*new_role), + ActionResult::GraveDigger(res_target.clone(), *new_role), )); } }) @@ -220,7 +232,7 @@ pub fn ResultScreenTest(
    } } - ActionResult::Mortician(died_to_title) => { + ActionResult::Mortician(target, died_to_title) => { let roles = DiedToTitle::ALL .into_iter() .map(|died_to| { @@ -231,6 +243,7 @@ pub fn ResultScreenTest( .collect::(); let on_change_cb = { let send = send.clone(); + let target = target.clone(); Callback::from(move |ev: Event| { if let Some(select) = ev.target_dyn_into::() { let selected = select.selected_index(); @@ -240,7 +253,7 @@ pub fn ResultScreenTest( if let Some(died_to) = DiedToTitle::ALL.into_iter().nth(selected as _) { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Mortician(died_to), + ActionResult::Mortician(target.clone(), died_to), )); } } @@ -248,6 +261,7 @@ pub fn ResultScreenTest( }; let on_wheel = { let send = send.clone(); + let res_target = target.clone(); Callback::from(move |ev: WheelEvent| { let Some(target) = ev.target_dyn_into::() else { return; @@ -274,7 +288,7 @@ pub fn ResultScreenTest( if let Some(died_to) = DiedToTitle::ALL.into_iter().nth(new_index as _) { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Mortician(died_to), + ActionResult::Mortician(res_target.clone(), died_to), )); } }) @@ -335,14 +349,18 @@ pub fn ResultScreenTest(
    } } - ActionResult::Empath { scapegoat } => { + ActionResult::Empath { target, scapegoat } => { let on_toggle = { let set = !*scapegoat; let send = send.clone(); + let target = target.clone(); Callback::from(move |_| { send.emit(ServerToHostMessage::ActionResult( None, - ActionResult::Empath { scapegoat: set }, + ActionResult::Empath { + scapegoat: set, + target: target.clone(), + }, )); }) };