traitor prompt appears for non-wakers

also the traitor, elder reveal, role change prompts
can no longer get drunk (lol)
This commit is contained in:
emilis 2025-11-13 23:22:41 +00:00
parent 1c3980d700
commit 99a2fa31c4
No known key found for this signature in database
6 changed files with 37 additions and 14 deletions

View File

@ -14,11 +14,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use rand::{SeedableRng, rngs::SmallRng, seq::SliceRandom}; use rand::{SeedableRng, rngs::SmallRng, seq::SliceRandom};
// #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
// pub enum BagItem<T, V> {
// Left(T),
// Right(V),
// }
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Bag<T>(Vec<T>); pub struct Bag<T>(Vec<T>);

View File

@ -248,9 +248,9 @@ impl Character {
) )
} }
fn mason_prompts(&self, village: &Village) -> Result<Box<[ActionPrompt]>> { fn mason_prompts(&self, village: &Village) -> Result<Vec<ActionPrompt>> {
if !self.role.wakes(village) { if !self.role.wakes(village) {
return Ok(Box::new([])); return Ok(Vec::new());
} }
let (recruits, recruits_available) = match &self.role { let (recruits, recruits_available) = match &self.role {
Role::MasonLeader { Role::MasonLeader {
@ -313,22 +313,25 @@ impl Character {
} }
pub fn night_action_prompts(&self, village: &Village) -> Result<Box<[ActionPrompt]>> { pub fn night_action_prompts(&self, village: &Village) -> Result<Box<[ActionPrompt]>> {
let mut prompts = Vec::new();
if self.mason_leader().is_ok() { if self.mason_leader().is_ok() {
return self.mason_prompts(village); // add them here so masons wake up even with a dead leader
} prompts.append(&mut self.mason_prompts(village)?);
if !self.alive() || !self.role.wakes(village) {
return Ok(Box::new([]));
} }
let night = match village.time() { let night = match village.time() {
GameTime::Day { number: _ } => return Err(GameError::NotNight), GameTime::Day { number: _ } => return Err(GameError::NotNight),
GameTime::Night { number } => number, GameTime::Night { number } => number,
}; };
let mut prompts = Vec::new();
if night == 0 && self.auras.list().contains(&Aura::Traitor) { if night == 0 && self.auras.list().contains(&Aura::Traitor) {
log::info!("adding traitor prompt for {}", self.identity());
prompts.push(ActionPrompt::TraitorIntro { prompts.push(ActionPrompt::TraitorIntro {
character_id: self.identity(), character_id: self.identity(),
}); });
} }
if !self.alive() || !self.role.wakes(village) {
return Ok(prompts.into_boxed_slice());
}
match &self.role { match &self.role {
Role::Empath { cursed: true } Role::Empath { cursed: true }
| Role::Diseased | Role::Diseased

View File

@ -1064,6 +1064,9 @@ impl Night {
Visits::new( Visits::new(
self.used_actions self.used_actions
.iter() .iter()
.filter(|(_, result, _)| {
!matches!(result, ActionResult::Drunk | ActionResult::RoleBlocked)
})
.filter_map(|(prompt, _, _)| match prompt { .filter_map(|(prompt, _, _)| match prompt {
ActionPrompt::Arcanist { ActionPrompt::Arcanist {
character_id, character_id,

View File

@ -547,10 +547,26 @@ impl Night {
resp: ActionResponse, resp: ActionResponse,
) -> Result<ResponseOutcome> { ) -> Result<ResponseOutcome> {
let outcome = self.process(resp)?; let outcome = self.process(resp)?;
if matches!(
self.current_prompt(),
Some((ActionPrompt::TraitorIntro { .. }, _))
| Some((ActionPrompt::RoleChange { .. }, _))
| Some((ActionPrompt::ElderReveal { .. }, _))
) {
return Ok(outcome);
}
let mut act = match outcome { let mut act = match outcome {
ResponseOutcome::PromptUpdate(prompt) => { ResponseOutcome::PromptUpdate(prompt) => {
return Ok(ResponseOutcome::PromptUpdate(prompt)); return Ok(ResponseOutcome::PromptUpdate(prompt));
} }
ResponseOutcome::ActionComplete(ActionComplete {
result: ActionResult::Drunk,
..
})
| ResponseOutcome::ActionComplete(ActionComplete {
result: ActionResult::RoleBlocked,
..
}) => return Ok(outcome),
ResponseOutcome::ActionComplete(act) => act, ResponseOutcome::ActionComplete(act) => act,
}; };
let Some(char) = self.current_character() else { let Some(char) = self.current_character() else {

View File

@ -15,7 +15,7 @@
use core::{num::NonZeroU8, ops::Not}; use core::{num::NonZeroU8, ops::Not};
use crate::{ use crate::{
aura::{Aura, AuraTitle}, aura::Aura,
diedto::DiedTo, diedto::DiedTo,
error::GameError, error::GameError,
game::{ game::{

View File

@ -1,5 +1,7 @@
use yew::prelude::*; use yew::prelude::*;
use crate::components::{Icon, IconSource};
#[function_component] #[function_component]
pub fn TraitorIntroPage() -> Html { pub fn TraitorIntroPage() -> Html {
html! { html! {
@ -8,8 +10,11 @@ pub fn TraitorIntroPage() -> Html {
<div class="information traitor faint"> <div class="information traitor faint">
<h2>{"YOU ARE A TRAITOR"}</h2> <h2>{"YOU ARE A TRAITOR"}</h2>
<h3>{"YOU RETAIN YOUR ROLE AND WIN IF EVIL WINS"}</h3> <h3>{"YOU RETAIN YOUR ROLE AND WIN IF EVIL WINS"}</h3>
<div class="info-icon-grow">
<Icon source={IconSource::Traitor}/>
</div>
<h4>{"HOWEVER"}</h4> <h4>{"HOWEVER"}</h4>
<h2 class="yellow inline-icons"> <h2 class="yellow">
{"YOU CONTRIBUTE TO VILLAGE PARITY"} {"YOU CONTRIBUTE TO VILLAGE PARITY"}
</h2> </h2>
</div> </div>