beholder target roleblocked sees nothing
slightly nicer game end screen
This commit is contained in:
parent
a2013adea9
commit
ad29c3d59c
|
|
@ -282,6 +282,15 @@ pub enum GameOver {
|
|||
WolvesWin,
|
||||
}
|
||||
|
||||
impl Display for GameOver {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GameOver::VillageWins => f.write_str("village wins"),
|
||||
GameOver::WolvesWin => f.write_str("wolves win"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Pool<T>
|
||||
where
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ impl Night {
|
|||
NightState::Active {
|
||||
current_result: CurrentResult::Result(current_result),
|
||||
..
|
||||
} => Some(¤t_result),
|
||||
} => Some(current_result),
|
||||
NightState::Active {
|
||||
current_result: CurrentResult::GoBackToSleepAfterShown { .. },
|
||||
..
|
||||
|
|
|
|||
|
|
@ -395,10 +395,13 @@ impl Night {
|
|||
if let Some(result) = self.used_actions.iter().find_map(|(prompt, result, _)| {
|
||||
prompt.matches_beholding(*marked).then_some(result)
|
||||
}) && self.dies_tonight(*marked)?
|
||||
&& !matches!(result, ActionResult::RoleBlocked)
|
||||
{
|
||||
Ok(ActionComplete {
|
||||
result: result.clone(),
|
||||
result: if matches!(result, ActionResult::RoleBlocked) {
|
||||
ActionResult::BeholderSawNothing
|
||||
} else {
|
||||
result.clone()
|
||||
},
|
||||
change: None,
|
||||
}
|
||||
.into())
|
||||
|
|
|
|||
|
|
@ -83,11 +83,13 @@ pub enum StoryActionResult {
|
|||
Mortician(DiedToTitle),
|
||||
Insomniac { visits: Box<[CharacterId]> },
|
||||
Empath { scapegoat: bool },
|
||||
BeholderSawNothing,
|
||||
}
|
||||
|
||||
impl StoryActionResult {
|
||||
pub fn new(result: ActionResult) -> Option<Self> {
|
||||
Some(match result {
|
||||
ActionResult::BeholderSawNothing => Self::BeholderSawNothing,
|
||||
ActionResult::RoleBlocked => Self::RoleBlocked,
|
||||
ActionResult::Seer(alignment) => Self::Seer(alignment),
|
||||
ActionResult::PowerSeer { powerful } => Self::PowerSeer { powerful },
|
||||
|
|
|
|||
|
|
@ -484,6 +484,7 @@ pub enum ActionResult {
|
|||
Mortician(DiedToTitle),
|
||||
Insomniac(Visits),
|
||||
Empath { scapegoat: bool },
|
||||
BeholderSawNothing,
|
||||
GoBackToSleep,
|
||||
Continue,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1306,7 +1306,10 @@ input {
|
|||
margin-top: 2%;
|
||||
font-size: 1.5vw;
|
||||
|
||||
height: 100vh;
|
||||
|
||||
.setup {
|
||||
height: 85%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
|
@ -1322,6 +1325,7 @@ input {
|
|||
|
||||
&.final {
|
||||
margin-top: 1cm;
|
||||
margin-bottom: 1cm;
|
||||
}
|
||||
|
||||
& .title {
|
||||
|
|
@ -1870,3 +1874,26 @@ input {
|
|||
font-size: 3rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.victory {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 3vw;
|
||||
height: max-content;
|
||||
gap: 1cm;
|
||||
padding: 1cm;
|
||||
}
|
||||
|
||||
|
||||
.end-screen {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ use yew::{html::Scope, prelude::*};
|
|||
use crate::{
|
||||
callback,
|
||||
components::{
|
||||
Button, CoverOfDarkness, Lobby, LobbyPlayerAction, RoleReveal, Settings, Story,
|
||||
Button, CoverOfDarkness, Lobby, LobbyPlayerAction, RoleReveal, Settings, Story, Victory,
|
||||
action::{ActionResultView, Prompt},
|
||||
host::{DaytimePlayerList, Setup},
|
||||
},
|
||||
|
|
@ -312,6 +312,16 @@ impl Component for Host {
|
|||
log::trace!("state: {:?}", self.state);
|
||||
let content = match self.state.clone() {
|
||||
HostState::Story { story, page } => {
|
||||
if let Some(outcome) = story
|
||||
.final_village()
|
||||
.ok()
|
||||
.and_then(|village| village.is_game_over())
|
||||
&& self.big_screen
|
||||
{
|
||||
html! {
|
||||
<Victory outcome={outcome}/>
|
||||
}
|
||||
} else {
|
||||
let new_lobby_click = crate::callback::send_message(
|
||||
HostMessage::PostGame(PostGameMessage::NewLobby),
|
||||
self.send.clone(),
|
||||
|
|
@ -323,6 +333,7 @@ impl Component for Host {
|
|||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
HostState::GameOver { result } => {
|
||||
let cont = self.big_screen.not().then(|| {
|
||||
crate::callback::send_message(
|
||||
|
|
@ -332,15 +343,7 @@ impl Component for Host {
|
|||
});
|
||||
|
||||
html! {
|
||||
<CoverOfDarkness
|
||||
message={match result {
|
||||
GameOver::VillageWins => "village wins",
|
||||
GameOver::WolvesWin => "wolves win",
|
||||
}}
|
||||
next={cont}
|
||||
>
|
||||
{"continue"}
|
||||
</CoverOfDarkness>
|
||||
<Victory outcome={result} cont={cont}/>
|
||||
}
|
||||
}
|
||||
HostState::Disconnected => html! {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ use yew::prelude::*;
|
|||
use crate::{
|
||||
components::{Button, CoverOfDarkness, Icon, IconSource, Identity},
|
||||
pages::{
|
||||
AdjudicatorResult, ArcanistResult, EmpathResult, GravediggerResultPage, InsomniacResult,
|
||||
MorticianResultPage, PowerSeerResult, RoleblockPage, SeerResult,
|
||||
AdjudicatorResult, ArcanistResult, BeholderSawNothing, EmpathResult, GravediggerResultPage,
|
||||
InsomniacResult, MorticianResultPage, PowerSeerResult, RoleblockPage, SeerResult,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -58,6 +58,9 @@ pub fn ActionResultView(props: &ActionResultProps) -> Html {
|
|||
.not()
|
||||
.then(|| html! {<Button on_click={on_continue}>{"continue"}</Button>});
|
||||
let body = match &props.result {
|
||||
ActionResult::BeholderSawNothing => html! {
|
||||
<BeholderSawNothing />
|
||||
},
|
||||
ActionResult::PowerSeer { powerful } => {
|
||||
html! {
|
||||
<PowerSeerResult powerful={*powerful}/>
|
||||
|
|
|
|||
|
|
@ -274,6 +274,9 @@ struct StoryNightResultProps {
|
|||
#[function_component]
|
||||
fn StoryNightResult(StoryNightResultProps { result, characters }: &StoryNightResultProps) -> Html {
|
||||
match result {
|
||||
StoryActionResult::BeholderSawNothing => html!{
|
||||
<span>{"but saw nothing"}</span>
|
||||
},
|
||||
StoryActionResult::RoleBlocked => html! {
|
||||
<span>{"but was role blocked"}</span>
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
use werewolves_proto::game::GameOver;
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::{Button, Icon, IconSource, IconType};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Properties)]
|
||||
pub struct VictoryProps {
|
||||
pub outcome: GameOver,
|
||||
#[prop_or_default]
|
||||
pub cont: Option<Callback<()>>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn Victory(VictoryProps { outcome, cont }: &VictoryProps) -> Html {
|
||||
let cont_btn = cont.clone().map(|cont| {
|
||||
html! {
|
||||
<Button on_click={cont}>{"continue"}</Button>
|
||||
}
|
||||
});
|
||||
match outcome {
|
||||
GameOver::WolvesWin => html! {
|
||||
<div class="end-screen">
|
||||
<div class="victory wolves faint">
|
||||
<Icon source={IconSource::Wolves} icon_type={IconType::Informational}/>
|
||||
<h1>{"Wolves Win"}</h1>
|
||||
<Icon source={IconSource::Wolves} icon_type={IconType::Informational}/>
|
||||
</div>
|
||||
{cont_btn}
|
||||
</div>
|
||||
},
|
||||
GameOver::VillageWins => html! {
|
||||
<div class="end-screen">
|
||||
<div class="victory village faint">
|
||||
<Icon source={IconSource::Village} icon_type={IconType::Informational}/>
|
||||
<h1>{"Village Wins"}</h1>
|
||||
<Icon source={IconSource::Village} icon_type={IconType::Informational}/>
|
||||
</div>
|
||||
{cont_btn}
|
||||
</div>
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::{Icon, IconSource, IconType};
|
||||
|
||||
#[function_component]
|
||||
pub fn BeholderPage1() -> Html {
|
||||
html! {
|
||||
|
|
@ -27,3 +29,17 @@ pub fn BeholderPage1() -> Html {
|
|||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
pub fn BeholderSawNothing() -> Html {
|
||||
html! {
|
||||
<div class="role-page">
|
||||
<h1 class="intel">{"BEHOLDER"}</h1>
|
||||
<div class="information intel faint">
|
||||
<h1>{"YOUR TARGET HAS DIED"}</h1>
|
||||
<h1><Icon source={IconSource::RedX} icon_type={IconType::Informational}/></h1>
|
||||
<h1>{"BUT SAW NOTHING"}</h1>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue