mod achievements;
pub(crate) mod announce;
mod art;
mod audio;
mod binds;
mod board_render;
mod boot;
mod campaign;
mod clock;
mod codes;
mod controls;
mod creatures;
mod cursor;
mod cycle;
mod daily;
mod dev;
mod editor;
mod effects;
mod embedded;
mod gamepad;
mod hint;
mod hud;
pub(crate) mod i18n;
mod language;
pub mod layout;
mod lobby;
mod match_setup;
mod menu_scene;
mod menu_ui;
pub mod net;
pub mod palette;
mod paths;
mod pause;
mod progress;
mod replays;
mod results;
mod schedule;
mod session;
mod settings;
mod side_panels;
mod sim_events;
mod stage_select;
mod suspend;
mod teams;
mod tournament;
mod update;
pub use campaign::{Campaign, CampaignKind};
pub use daily::Daily;
pub use schedule::run;
use crate::app::i18n::fill;
use crate::sim::{
Board, BotLevel, Level, MAX_PLAYERS, PlayerAction, PuzzleOutcome, Replay, bot_action,
castle_spots, classic_arena, classic_arena_seeded, generate_arena,
};
use bevy::prelude::*;
use bevy::render::RenderPlugin;
use bevy::render::settings::{InstanceFlags, RenderCreation, WgpuSettings};
pub fn replay_path() -> std::path::PathBuf {
replays::library_dir().join("last.txt")
}
pub fn highlight_path() -> std::path::PathBuf {
replays::library_dir().join("highlight.gif")
}
#[derive(Resource, Default)]
pub struct Highlight(pub Option<String>);
#[derive(Resource)]
pub struct Sim(pub Board);
#[derive(Resource, Default)]
pub struct PendingActions(pub [PlayerAction; MAX_PLAYERS]);
#[derive(Resource, Default)]
pub struct Paused(pub bool);
#[derive(Resource, Default)]
pub struct Recorder(pub Option<Replay>);
#[derive(Resource, Default)]
pub struct Bots(pub [Option<BotLevel>; MAX_PLAYERS]);
#[derive(Resource, Default)]
pub struct Playback(pub Option<(Replay, usize)>);
#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Screen {
#[default]
Menu,
Puzzle,
Versus,
Editor,
Lobby,
Settings,
Controls,
MatchSetup,
Achievements,
StageSelect,
Replays,
Interlude,
Language,
NewVersion,
}
#[derive(Clone, Copy)]
pub struct Chrome {
pub width: f32,
pub top: f32,
pub bottom: f32,
}
impl Chrome {
const fn of(width: f32, top: f32, bottom: f32) -> Chrome {
Chrome { width, top, bottom }
}
}
impl Screen {
pub const ALL: [Screen; 14] = [
Screen::Menu,
Screen::Puzzle,
Screen::Versus,
Screen::Editor,
Screen::Lobby,
Screen::Settings,
Screen::Controls,
Screen::MatchSetup,
Screen::Achievements,
Screen::StageSelect,
Screen::Replays,
Screen::Interlude,
Screen::Language,
Screen::NewVersion,
];
fn chrome(self) -> Chrome {
match self {
Screen::Menu => Chrome::of(0.0, 0.0, 0.0),
Screen::Versus => Chrome::of(2.0 * side_panels::SIDEBAR_W + 60.0, 60.0, 104.0),
Screen::Puzzle
| Screen::Editor
| Screen::Lobby
| Screen::Settings
| Screen::Controls
| Screen::MatchSetup
| Screen::Achievements
| Screen::StageSelect
| Screen::Replays
| Screen::Interlude
| Screen::Language
| Screen::NewVersion => Chrome::of(40.0, 60.0, 104.0),
}
}
}
#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Phase {
#[default]
Setup,
Running,
Won,
Lost,
}
#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum VersusPhase {
#[default]
Running,
Over,
}
#[derive(Resource)]
pub struct Sandbox(pub bool);
#[derive(Message)]
pub struct LoadLevel {
pub keep_posts: bool,
}
#[derive(Message)]
pub struct PlacementDenied {
pub player: u8,
}
#[derive(Message)]
pub struct LevelSaved;
#[derive(Resource, Default)]
pub struct Seats(pub u8);
#[derive(Resource, Default)]
pub struct SeatNames(pub [String; MAX_PLAYERS]);
impl SeatNames {
pub fn label(&self, tr: &i18n::Tr, seat: u8) -> String {
match self.0.get(usize::from(seat)) {
Some(name) if !name.is_empty() => name.clone(),
_ => seat_label(tr, seat),
}
}
}
pub fn seat_label(tr: &i18n::Tr, seat: u8) -> String {
fill(tr.player_label, &[("p", &(seat + 1).to_string())])
}
#[derive(Resource, Default)]
pub struct Resuming(pub Option<suspend::Suspended>);
#[derive(Resource, Default)]
pub struct RoundNotice(pub String);