generated from GarandPLG/rust-flake-template
Update formatting to use 4‑space indentation
- Adjust rustfmt.toml to set tab_spaces = 4. - Reformat imports, struct definitions, function bodies, and match arms across the project to match the new style (aligned fields, added spacing, etc.). - Ensure all code complies with the updated rustfmt settings.
This commit is contained in:
1 parent
a981663152
commit
73f544d5d6
66 files changed
+5378
-5373
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -1,53 +1,53 @@
|
||||
pub enum MoveFocusedCell {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FocusedCell {
|
||||
row: usize,
|
||||
col: usize,
|
||||
max_row: usize,
|
||||
max_col: usize,
|
||||
row: usize,
|
||||
col: usize,
|
||||
max_row: usize,
|
||||
max_col: usize,
|
||||
}
|
||||
|
||||
impl FocusedCell {
|
||||
pub fn new(row: usize, col: usize, max_row: usize, max_col: usize) -> Self {
|
||||
Self {
|
||||
row,
|
||||
col,
|
||||
max_row,
|
||||
max_col,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_coords(&self) -> (usize, usize) {
|
||||
(self.row, self.col)
|
||||
}
|
||||
|
||||
pub fn move_focused_cell(&mut self, direction: MoveFocusedCell) -> (usize, usize) {
|
||||
match direction {
|
||||
MoveFocusedCell::Up => {
|
||||
self.row = self.row.saturating_sub(1).max(0);
|
||||
}
|
||||
MoveFocusedCell::Down => {
|
||||
self.row = self.row.saturating_add(1).min(self.max_row - 1);
|
||||
}
|
||||
MoveFocusedCell::Left => {
|
||||
self.col = self.col.saturating_sub(1).max(0);
|
||||
}
|
||||
MoveFocusedCell::Right => {
|
||||
self.col = self.col.saturating_add(1).min(self.max_col - 1);
|
||||
}
|
||||
pub fn new(row: usize, col: usize, max_row: usize, max_col: usize) -> Self {
|
||||
Self {
|
||||
row,
|
||||
col,
|
||||
max_row,
|
||||
max_col,
|
||||
}
|
||||
}
|
||||
|
||||
(self.row, self.col)
|
||||
}
|
||||
pub fn get_coords(&self) -> (usize, usize) {
|
||||
(self.row, self.col)
|
||||
}
|
||||
|
||||
pub fn set_focused_cell(&mut self, cell: (usize, usize)) {
|
||||
self.row = cell.0.max(0).min(self.max_row - 1);
|
||||
self.col = cell.1.max(0).min(self.max_col - 1);
|
||||
}
|
||||
pub fn move_focused_cell(&mut self, direction: MoveFocusedCell) -> (usize, usize) {
|
||||
match direction {
|
||||
MoveFocusedCell::Up => {
|
||||
self.row = self.row.saturating_sub(1).max(0);
|
||||
}
|
||||
MoveFocusedCell::Down => {
|
||||
self.row = self.row.saturating_add(1).min(self.max_row - 1);
|
||||
}
|
||||
MoveFocusedCell::Left => {
|
||||
self.col = self.col.saturating_sub(1).max(0);
|
||||
}
|
||||
MoveFocusedCell::Right => {
|
||||
self.col = self.col.saturating_add(1).min(self.max_col - 1);
|
||||
}
|
||||
}
|
||||
|
||||
(self.row, self.col)
|
||||
}
|
||||
|
||||
pub fn set_focused_cell(&mut self, cell: (usize, usize)) {
|
||||
self.row = cell.0.max(0).min(self.max_row - 1);
|
||||
self.col = cell.1.max(0).min(self.max_col - 1);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@ use clap::ValueEnum;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||
pub enum GameMode {
|
||||
LastManStanding,
|
||||
FrontLines,
|
||||
LastManStanding,
|
||||
FrontLines,
|
||||
}
|
||||
@@ -3,17 +3,17 @@ use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct MarkedCells {
|
||||
pub marking_cells: bool,
|
||||
pub marked_cells: VecDeque<(usize, usize)>,
|
||||
pub selected_unit: Option<Units>,
|
||||
pub marking_cells: bool,
|
||||
pub marked_cells: VecDeque<(usize, usize)>,
|
||||
pub selected_unit: Option<Units>,
|
||||
}
|
||||
|
||||
impl MarkedCells {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
marking_cells: false,
|
||||
marked_cells: VecDeque::new(),
|
||||
selected_unit: None,
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
marking_cells: false,
|
||||
marked_cells: VecDeque::new(),
|
||||
selected_unit: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,35 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Offset {
|
||||
value: usize,
|
||||
max: usize,
|
||||
value: usize,
|
||||
max: usize,
|
||||
}
|
||||
|
||||
impl Offset {
|
||||
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
|
||||
Self {
|
||||
value: initial_value.unwrap_or(0).min(initial_max.unwrap_or(0)),
|
||||
max: initial_max.unwrap_or(0),
|
||||
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
|
||||
Self {
|
||||
value: initial_value.unwrap_or(0).min(initial_max.unwrap_or(0)),
|
||||
max: initial_max.unwrap_or(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> usize {
|
||||
self.value
|
||||
}
|
||||
pub fn get_value(&self) -> usize {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn set_value(&mut self, value: usize) {
|
||||
self.value = value.min(self.max);
|
||||
}
|
||||
pub fn set_value(&mut self, value: usize) {
|
||||
self.value = value.min(self.max);
|
||||
}
|
||||
|
||||
pub fn set_max(&mut self, max: usize) {
|
||||
self.max = max;
|
||||
self.value = self.value.min(max);
|
||||
}
|
||||
pub fn set_max(&mut self, max: usize) {
|
||||
self.max = max;
|
||||
self.value = self.value.min(max);
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
self.value = self.value.saturating_add(1).min(self.max);
|
||||
}
|
||||
pub fn next(&mut self) {
|
||||
self.value = self.value.saturating_add(1).min(self.max);
|
||||
}
|
||||
|
||||
pub fn prev(&mut self) {
|
||||
self.value = self.value.saturating_sub(1).max(0)
|
||||
}
|
||||
pub fn prev(&mut self) {
|
||||
self.value = self.value.saturating_sub(1).max(0)
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,37 @@
|
||||
use ratatui::{
|
||||
style::{Color, Stylize},
|
||||
text::Span,
|
||||
style::{Color, Stylize},
|
||||
text::Span,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Players {
|
||||
Player,
|
||||
Enemy,
|
||||
Unclaimed,
|
||||
Player,
|
||||
Enemy,
|
||||
Unclaimed,
|
||||
}
|
||||
|
||||
impl Players {
|
||||
pub fn get_text(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Player => "Player",
|
||||
Self::Enemy => "Enemy",
|
||||
Self::Unclaimed => "Unclaimed",
|
||||
pub fn get_text(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Player => "Player",
|
||||
Self::Enemy => "Enemy",
|
||||
Self::Unclaimed => "Unclaimed",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_color(&self) -> Color {
|
||||
match self {
|
||||
Self::Player => Color::LightBlue,
|
||||
Self::Enemy => Color::LightRed,
|
||||
Self::Unclaimed => Color::White,
|
||||
pub fn get_color(&self) -> Color {
|
||||
match self {
|
||||
Self::Player => Color::LightBlue,
|
||||
Self::Enemy => Color::LightRed,
|
||||
Self::Unclaimed => Color::White,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_span(&self) -> Span<'static> {
|
||||
match self {
|
||||
Self::Player => self.get_text().fg(self.get_color()),
|
||||
Self::Enemy => self.get_text().fg(self.get_color()),
|
||||
Self::Unclaimed => self.get_text().fg(self.get_color()),
|
||||
pub fn get_span(&self) -> Span<'static> {
|
||||
match self {
|
||||
Self::Player => self.get_text().fg(self.get_color()),
|
||||
Self::Enemy => self.get_text().fg(self.get_color()),
|
||||
Self::Unclaimed => self.get_text().fg(self.get_color()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,35 +7,35 @@ pub const MINE_PRODUCTION_TICKS: u64 = 1000_u64.div_ceil(TICK_MS as u64);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Resources {
|
||||
pub wood: u32,
|
||||
pub metal: u32,
|
||||
pub wood: u32,
|
||||
pub metal: u32,
|
||||
}
|
||||
|
||||
impl Resources {
|
||||
pub fn can_afford(&self, cost: Self) -> bool {
|
||||
self.wood >= cost.wood && self.metal >= cost.metal
|
||||
}
|
||||
|
||||
pub fn spend(&mut self, cost: Self) -> bool {
|
||||
if !self.can_afford(cost) {
|
||||
return false;
|
||||
pub fn can_afford(&self, cost: Self) -> bool {
|
||||
self.wood >= cost.wood && self.metal >= cost.metal
|
||||
}
|
||||
self.wood -= cost.wood;
|
||||
self.metal -= cost.metal;
|
||||
true
|
||||
}
|
||||
pub fn new(wood: u16, metal: u16) -> Self {
|
||||
Self {
|
||||
wood: u32::from(wood),
|
||||
metal: u32::from(metal),
|
||||
|
||||
pub fn spend(&mut self, cost: Self) -> bool {
|
||||
if !self.can_afford(cost) {
|
||||
return false;
|
||||
}
|
||||
self.wood -= cost.wood;
|
||||
self.metal -= cost.metal;
|
||||
true
|
||||
}
|
||||
pub fn new(wood: u16, metal: u16) -> Self {
|
||||
Self {
|
||||
wood: u32::from(wood),
|
||||
metal: u32::from(metal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_wood(&mut self, amount: u32) -> () {
|
||||
self.wood = self.wood.saturating_add(amount);
|
||||
}
|
||||
pub fn add_wood(&mut self, amount: u32) -> () {
|
||||
self.wood = self.wood.saturating_add(amount);
|
||||
}
|
||||
|
||||
pub fn add_metal(&mut self, amount: u32) -> () {
|
||||
self.metal = self.metal.saturating_add(amount);
|
||||
}
|
||||
pub fn add_metal(&mut self, amount: u32) -> () {
|
||||
self.metal = self.metal.saturating_add(amount);
|
||||
}
|
||||
}
|
||||
@@ -4,135 +4,135 @@ use ratatui::{style::Color, text::Line};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct BaseBuilding {
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
owner: Players,
|
||||
level: u8,
|
||||
queued_miners: u32,
|
||||
recruitment_ticks: u16,
|
||||
waiting_for_departure: bool,
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
owner: Players,
|
||||
level: u8,
|
||||
queued_miners: u32,
|
||||
recruitment_ticks: u16,
|
||||
waiting_for_departure: bool,
|
||||
}
|
||||
|
||||
impl BaseBuilding {
|
||||
pub const RECRUITMENT_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
|
||||
pub const RECRUITMENT_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
|
||||
|
||||
pub fn queued_miners(&self) -> u32 {
|
||||
self.queued_miners
|
||||
}
|
||||
|
||||
pub fn recruitment_progress(&self) -> u16 {
|
||||
(u32::from(self.recruitment_ticks) * 100 / u32::from(Self::RECRUITMENT_TICKS)) as u16
|
||||
}
|
||||
|
||||
pub fn can_queue_miner(&self) -> bool {
|
||||
self.owner != Players::Unclaimed && self.queued_miners < u32::MAX
|
||||
}
|
||||
|
||||
pub fn queue_miner(&mut self) -> bool {
|
||||
if !self.can_queue_miner() {
|
||||
return false;
|
||||
pub fn queued_miners(&self) -> u32 {
|
||||
self.queued_miners
|
||||
}
|
||||
self.queued_miners += 1;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn advance_recruitment(&mut self, occupied: bool) -> bool {
|
||||
if self.waiting_for_departure {
|
||||
if occupied {
|
||||
return false;
|
||||
}
|
||||
self.waiting_for_departure = false;
|
||||
pub fn recruitment_progress(&self) -> u16 {
|
||||
(u32::from(self.recruitment_ticks) * 100 / u32::from(Self::RECRUITMENT_TICKS)) as u16
|
||||
}
|
||||
if self.queued_miners == 0 {
|
||||
return false;
|
||||
}
|
||||
self.recruitment_ticks = self
|
||||
.recruitment_ticks
|
||||
.saturating_add(1)
|
||||
.min(Self::RECRUITMENT_TICKS);
|
||||
if self.recruitment_ticks < Self::RECRUITMENT_TICKS || occupied {
|
||||
return false;
|
||||
}
|
||||
self.queued_miners -= 1;
|
||||
self.recruitment_ticks = 0;
|
||||
self.waiting_for_departure = true;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn recruitment_status(&self, occupied: bool) -> &'static str {
|
||||
if self.queued_miners == 0 {
|
||||
"Queue empty"
|
||||
} else if self.waiting_for_departure && occupied {
|
||||
"Paused: waiting for Miner to leave base"
|
||||
} else if self.recruitment_ticks == Self::RECRUITMENT_TICKS && occupied {
|
||||
"Ready: waiting for free base cell"
|
||||
} else {
|
||||
"Recruiting"
|
||||
pub fn can_queue_miner(&self) -> bool {
|
||||
self.owner != Players::Unclaimed && self.queued_miners < u32::MAX
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(owner: Players) -> Self {
|
||||
Self {
|
||||
durability: 1500,
|
||||
stress: 0,
|
||||
owner,
|
||||
level: 1,
|
||||
queued_miners: 0,
|
||||
recruitment_ticks: 0,
|
||||
waiting_for_departure: false,
|
||||
pub fn queue_miner(&mut self) -> bool {
|
||||
if !self.can_queue_miner() {
|
||||
return false;
|
||||
}
|
||||
self.queued_miners += 1;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn advance_recruitment(&mut self, occupied: bool) -> bool {
|
||||
if self.waiting_for_departure {
|
||||
if occupied {
|
||||
return false;
|
||||
}
|
||||
self.waiting_for_departure = false;
|
||||
}
|
||||
if self.queued_miners == 0 {
|
||||
return false;
|
||||
}
|
||||
self.recruitment_ticks = self
|
||||
.recruitment_ticks
|
||||
.saturating_add(1)
|
||||
.min(Self::RECRUITMENT_TICKS);
|
||||
if self.recruitment_ticks < Self::RECRUITMENT_TICKS || occupied {
|
||||
return false;
|
||||
}
|
||||
self.queued_miners -= 1;
|
||||
self.recruitment_ticks = 0;
|
||||
self.waiting_for_departure = true;
|
||||
true
|
||||
}
|
||||
|
||||
pub fn recruitment_status(&self, occupied: bool) -> &'static str {
|
||||
if self.queued_miners == 0 {
|
||||
"Queue empty"
|
||||
} else if self.waiting_for_departure && occupied {
|
||||
"Paused: waiting for Miner to leave base"
|
||||
} else if self.recruitment_ticks == Self::RECRUITMENT_TICKS && occupied {
|
||||
"Ready: waiting for free base cell"
|
||||
} else {
|
||||
"Recruiting"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(owner: Players) -> Self {
|
||||
Self {
|
||||
durability: 1500,
|
||||
stress: 0,
|
||||
owner,
|
||||
level: 1,
|
||||
queued_miners: 0,
|
||||
recruitment_ticks: 0,
|
||||
waiting_for_departure: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for BaseBuilding {
|
||||
fn get_tag(&self) -> char {
|
||||
'B'
|
||||
}
|
||||
|
||||
fn get_color(&self) -> Color {
|
||||
match self.owner {
|
||||
Players::Player => Color::LightBlue,
|
||||
Players::Enemy => Color::LightRed,
|
||||
Players::Unclaimed => Color::LightGreen,
|
||||
fn get_tag(&self) -> char {
|
||||
'B'
|
||||
}
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
(self.level + b'0') as char
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
match self.owner {
|
||||
Players::Player => Color::LightBlue,
|
||||
Players::Enemy => Color::LightRed,
|
||||
Players::Unclaimed => Color::LightGreen,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
(self.level + b'0') as char
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1500
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1500
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Base"
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Base"
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = self.base_text();
|
||||
lines.push(Line::from(format!(
|
||||
"Recruitment queue: {}",
|
||||
self.queued_miners
|
||||
)));
|
||||
if self.queued_miners > 0 {
|
||||
lines.push(Line::from(format!(
|
||||
"Miner progress: {}%",
|
||||
self.recruitment_progress()
|
||||
)));
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = self.base_text();
|
||||
lines.push(Line::from(format!(
|
||||
"Recruitment queue: {}",
|
||||
self.queued_miners
|
||||
)));
|
||||
if self.queued_miners > 0 {
|
||||
lines.push(Line::from(format!(
|
||||
"Miner progress: {}%",
|
||||
self.recruitment_progress()
|
||||
)));
|
||||
}
|
||||
lines
|
||||
}
|
||||
lines
|
||||
}
|
||||
}
|
||||
@@ -1,96 +1,96 @@
|
||||
use crate::app::states::skirmish_states::{
|
||||
Players, Resources,
|
||||
structures::{Ore, Structure},
|
||||
units::{Unit, Units},
|
||||
Players, Resources,
|
||||
structures::{Ore, Structure},
|
||||
units::{Unit, Units},
|
||||
};
|
||||
use ratatui::{
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Mine {
|
||||
owner: Players,
|
||||
ore: Ore,
|
||||
owner: Players,
|
||||
ore: Ore,
|
||||
}
|
||||
|
||||
impl Mine {
|
||||
pub const COST: Resources = Resources {
|
||||
wood: 20,
|
||||
metal: 10,
|
||||
};
|
||||
pub const METAL_PER_CYCLE: u16 = 1;
|
||||
pub const STAFFED_METAL_PER_CYCLE: u16 = 2;
|
||||
|
||||
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
|
||||
if owner == Players::Unclaimed || ore.get_owner() != Players::Unclaimed {
|
||||
return None;
|
||||
}
|
||||
Some(Self { owner, ore })
|
||||
}
|
||||
|
||||
pub fn get_ore_amount(&self) -> u16 {
|
||||
self.ore.get_ore_amount()
|
||||
}
|
||||
|
||||
pub fn into_ore(self) -> Ore {
|
||||
self.ore
|
||||
}
|
||||
|
||||
pub fn produce(&mut self) -> u16 {
|
||||
self.produce_with_miner(false)
|
||||
}
|
||||
|
||||
pub fn accepts_unit(&self, unit: &Units) -> bool {
|
||||
matches!(unit, Units::Miner(_)) && unit.get_owner() == self.owner
|
||||
}
|
||||
|
||||
pub fn production_per_cycle(&self, staffed: bool) -> u16 {
|
||||
let rate: u16 = if staffed {
|
||||
Self::STAFFED_METAL_PER_CYCLE
|
||||
} else {
|
||||
Self::METAL_PER_CYCLE
|
||||
pub const COST: Resources = Resources {
|
||||
wood: 20,
|
||||
metal: 10,
|
||||
};
|
||||
rate.min(self.get_ore_amount())
|
||||
}
|
||||
pub const METAL_PER_CYCLE: u16 = 1;
|
||||
pub const STAFFED_METAL_PER_CYCLE: u16 = 2;
|
||||
|
||||
pub fn produce_with_miner(&mut self, staffed: bool) -> u16 {
|
||||
self.ore.extract(self.production_per_cycle(staffed))
|
||||
}
|
||||
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
|
||||
if owner == Players::Unclaimed || ore.get_owner() != Players::Unclaimed {
|
||||
return None;
|
||||
}
|
||||
Some(Self { owner, ore })
|
||||
}
|
||||
|
||||
pub fn get_ore_amount(&self) -> u16 {
|
||||
self.ore.get_ore_amount()
|
||||
}
|
||||
|
||||
pub fn into_ore(self) -> Ore {
|
||||
self.ore
|
||||
}
|
||||
|
||||
pub fn produce(&mut self) -> u16 {
|
||||
self.produce_with_miner(false)
|
||||
}
|
||||
|
||||
pub fn accepts_unit(&self, unit: &Units) -> bool {
|
||||
matches!(unit, Units::Miner(_)) && unit.get_owner() == self.owner
|
||||
}
|
||||
|
||||
pub fn production_per_cycle(&self, staffed: bool) -> u16 {
|
||||
let rate: u16 = if staffed {
|
||||
Self::STAFFED_METAL_PER_CYCLE
|
||||
} else {
|
||||
Self::METAL_PER_CYCLE
|
||||
};
|
||||
rate.min(self.get_ore_amount())
|
||||
}
|
||||
|
||||
pub fn produce_with_miner(&mut self, staffed: bool) -> u16 {
|
||||
self.ore.extract(self.production_per_cycle(staffed))
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Mine {
|
||||
fn get_tag(&self) -> char {
|
||||
'M'
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
self.owner.get_color()
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
self.ore.get_level()
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.ore.get_stress()
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.ore.get_durability()
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.ore.get_max_durability()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Mine"
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = self.base_text();
|
||||
lines.push(Line::from_iter([
|
||||
"Ore: ".gray(),
|
||||
self.get_ore_amount().to_string().cyan(),
|
||||
format!("/{}", self.ore.get_max_ore_amount()).gray(),
|
||||
]));
|
||||
lines
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
'M'
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
self.owner.get_color()
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
self.ore.get_level()
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.ore.get_stress()
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.ore.get_durability()
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.ore.get_max_durability()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Mine"
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = self.base_text();
|
||||
lines.push(Line::from_iter([
|
||||
"Ore: ".gray(),
|
||||
self.get_ore_amount().to_string().cyan(),
|
||||
format!("/{}", self.ore.get_max_ore_amount()).gray(),
|
||||
]));
|
||||
lines
|
||||
}
|
||||
}
|
||||
@@ -1,75 +1,75 @@
|
||||
use crate::app::{
|
||||
states::skirmish_states::{
|
||||
Players,
|
||||
structures::{Mine, Ore, Structure},
|
||||
},
|
||||
threads::TICK_MS,
|
||||
states::skirmish_states::{
|
||||
Players,
|
||||
structures::{Mine, Ore, Structure},
|
||||
},
|
||||
threads::TICK_MS,
|
||||
};
|
||||
use ratatui::{style::Color, text::Line};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct MineConstruction {
|
||||
mine: Mine,
|
||||
ticks: u16,
|
||||
mine: Mine,
|
||||
ticks: u16,
|
||||
}
|
||||
|
||||
impl MineConstruction {
|
||||
pub const BUILD_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
|
||||
pub const BUILD_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
|
||||
|
||||
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
|
||||
Mine::new(owner, ore).map(|mine: Mine| -> Self { Self { mine, ticks: 0 } })
|
||||
}
|
||||
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
|
||||
Mine::new(owner, ore).map(|mine: Mine| -> Self { Self { mine, ticks: 0 } })
|
||||
}
|
||||
|
||||
pub fn advance(&mut self) -> () {
|
||||
self.ticks = self.ticks.saturating_add(1).min(Self::BUILD_TICKS);
|
||||
}
|
||||
pub fn advance(&mut self) -> () {
|
||||
self.ticks = self.ticks.saturating_add(1).min(Self::BUILD_TICKS);
|
||||
}
|
||||
|
||||
pub fn is_finished(&self) -> bool {
|
||||
self.ticks == Self::BUILD_TICKS
|
||||
}
|
||||
pub fn is_finished(&self) -> bool {
|
||||
self.ticks == Self::BUILD_TICKS
|
||||
}
|
||||
|
||||
pub fn progress_percent(&self) -> u16 {
|
||||
(u32::from(self.ticks) * 100 / u32::from(Self::BUILD_TICKS)) as u16
|
||||
}
|
||||
pub fn progress_percent(&self) -> u16 {
|
||||
(u32::from(self.ticks) * 100 / u32::from(Self::BUILD_TICKS)) as u16
|
||||
}
|
||||
|
||||
pub fn into_mine(self) -> Option<Mine> {
|
||||
self.is_finished().then_some(self.mine)
|
||||
}
|
||||
pub fn into_mine(self) -> Option<Mine> {
|
||||
self.is_finished().then_some(self.mine)
|
||||
}
|
||||
|
||||
pub fn cancel(self) -> Ore {
|
||||
self.mine.into_ore()
|
||||
}
|
||||
pub fn cancel(self) -> Ore {
|
||||
self.mine.into_ore()
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for MineConstruction {
|
||||
fn get_tag(&self) -> char {
|
||||
'C'
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
self.mine.get_color()
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
self.mine.get_level()
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.mine.get_stress()
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.mine.get_durability()
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.mine.get_max_durability()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Mine construction"
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.mine.get_owner()
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
vec![
|
||||
Line::from(format!("Construction: {}%", self.progress_percent())),
|
||||
Line::from(format!("Ore: {}", self.mine.get_ore_amount())),
|
||||
]
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
'C'
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
self.mine.get_color()
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
self.mine.get_level()
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.mine.get_stress()
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.mine.get_durability()
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.mine.get_max_durability()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Mine construction"
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.mine.get_owner()
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
vec![
|
||||
Line::from(format!("Construction: {}%", self.progress_percent())),
|
||||
Line::from(format!("Ore: {}", self.mine.get_ore_amount())),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,6 @@ pub use tunnel::Tunnel;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BuildingTerrain {
|
||||
Stone,
|
||||
Ore,
|
||||
Stone,
|
||||
Ore,
|
||||
}
|
||||
@@ -1,100 +1,100 @@
|
||||
use crate::app::states::skirmish_states::{Players, structures::Structure};
|
||||
use ratatui::{
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Ore {
|
||||
owner: Players,
|
||||
ore_amount: u16,
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
level: u8,
|
||||
owner: Players,
|
||||
ore_amount: u16,
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
level: u8,
|
||||
}
|
||||
|
||||
impl Ore {
|
||||
pub fn new(owner: Players, level: u8) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
ore_amount: 5000,
|
||||
durability: 1000,
|
||||
stress: 0,
|
||||
level,
|
||||
pub fn new(owner: Players, level: u8) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
ore_amount: 5000,
|
||||
durability: 1000,
|
||||
stress: 0,
|
||||
level,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_ore_amount(&self) -> u16 {
|
||||
self.ore_amount
|
||||
}
|
||||
pub fn get_ore_amount(&self) -> u16 {
|
||||
self.ore_amount
|
||||
}
|
||||
|
||||
pub fn get_max_ore_amount(&self) -> u16 {
|
||||
5000
|
||||
}
|
||||
pub fn get_max_ore_amount(&self) -> u16 {
|
||||
5000
|
||||
}
|
||||
|
||||
pub fn extract(&mut self, amount: u16) -> u16 {
|
||||
let extracted: u16 = amount.min(self.ore_amount);
|
||||
self.ore_amount -= extracted;
|
||||
extracted
|
||||
}
|
||||
pub fn extract(&mut self, amount: u16) -> u16 {
|
||||
let extracted: u16 = amount.min(self.ore_amount);
|
||||
self.ore_amount -= extracted;
|
||||
extracted
|
||||
}
|
||||
|
||||
pub fn set_owner(&mut self, new_owner: Players) -> &mut Self {
|
||||
self.owner = new_owner;
|
||||
self
|
||||
}
|
||||
pub fn set_owner(&mut self, new_owner: Players) -> &mut Self {
|
||||
self.owner = new_owner;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Ore {
|
||||
fn get_tag(&self) -> char {
|
||||
'O'
|
||||
}
|
||||
|
||||
fn get_color(&self) -> Color {
|
||||
match self.owner {
|
||||
Players::Player => self.owner.get_color(),
|
||||
Players::Enemy => self.owner.get_color(),
|
||||
Players::Unclaimed => Color::Indexed(217),
|
||||
fn get_tag(&self) -> char {
|
||||
'O'
|
||||
}
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
if self.level != 0 {
|
||||
(self.level + b'0') as char
|
||||
} else {
|
||||
' '
|
||||
fn get_color(&self) -> Color {
|
||||
match self.owner {
|
||||
Players::Player => self.owner.get_color(),
|
||||
Players::Enemy => self.owner.get_color(),
|
||||
Players::Unclaimed => Color::Indexed(217),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1000
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Ore"
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
if self.level != 0 {
|
||||
(self.level + b'0') as char
|
||||
} else {
|
||||
' '
|
||||
}
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1000
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Ore"
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = Structure::base_text(self);
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
|
||||
lines.push(Line::from_iter([
|
||||
"Ore: ".gray(),
|
||||
self.get_ore_amount().to_string().cyan(),
|
||||
"/".gray(),
|
||||
self.get_max_ore_amount().to_string().cyan(),
|
||||
]));
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
let mut lines: Vec<Line<'_>> = Structure::base_text(self);
|
||||
|
||||
lines.push(Line::from_iter([
|
||||
"Ore: ".gray(),
|
||||
self.get_ore_amount().to_string().cyan(),
|
||||
"/".gray(),
|
||||
self.get_max_ore_amount().to_string().cyan(),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
}
|
||||
@@ -3,53 +3,53 @@ use ratatui::style::Color;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Stone {
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
}
|
||||
|
||||
impl Stone {
|
||||
pub fn take_damage(&mut self, damage: u16) {
|
||||
self.durability = self.durability.saturating_sub(damage);
|
||||
}
|
||||
pub fn take_damage(&mut self, damage: u16) {
|
||||
self.durability = self.durability.saturating_sub(damage);
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
durability: 1000,
|
||||
stress: 0,
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
durability: 1000,
|
||||
stress: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Stone {
|
||||
fn get_tag(&self) -> char {
|
||||
' '
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
' '
|
||||
}
|
||||
|
||||
fn get_color(&self) -> Color {
|
||||
Color::White
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
Color::White
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
' '
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
' '
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1000
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
1000
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Stone"
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Stone"
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
Players::Unclaimed
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
Players::Unclaimed
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,57 @@
|
||||
use crate::app::states::skirmish_states::Players;
|
||||
use ratatui::{
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
};
|
||||
|
||||
pub trait Structure {
|
||||
fn get_tag(&self) -> char;
|
||||
fn get_tag(&self) -> char;
|
||||
|
||||
fn get_color(&self) -> Color;
|
||||
fn get_color(&self) -> Color;
|
||||
|
||||
fn get_level(&self) -> char;
|
||||
fn get_level(&self) -> char;
|
||||
|
||||
fn get_stress(&self) -> u8;
|
||||
fn get_stress(&self) -> u8;
|
||||
|
||||
fn get_durability(&self) -> u16;
|
||||
fn get_durability(&self) -> u16;
|
||||
|
||||
fn get_max_durability(&self) -> u16;
|
||||
fn get_max_durability(&self) -> u16;
|
||||
|
||||
fn get_name(&self) -> &'static str;
|
||||
fn get_name(&self) -> &'static str;
|
||||
|
||||
fn get_owner(&self) -> Players;
|
||||
fn get_owner(&self) -> Players;
|
||||
|
||||
fn base_text(&self) -> Vec<Line<'_>> {
|
||||
let durability: u16 = self.get_durability();
|
||||
let max_durability: u16 = self.get_max_durability();
|
||||
let durability_percent: u32 = durability as u32 * 100 / max_durability as u32;
|
||||
let stress: u8 = self.get_stress();
|
||||
let level: char = self.get_level();
|
||||
fn base_text(&self) -> Vec<Line<'_>> {
|
||||
let durability: u16 = self.get_durability();
|
||||
let max_durability: u16 = self.get_max_durability();
|
||||
let durability_percent: u32 = durability as u32 * 100 / max_durability as u32;
|
||||
let stress: u8 = self.get_stress();
|
||||
let level: char = self.get_level();
|
||||
|
||||
let mut lines: Vec<Line<'_>> = vec![
|
||||
Line::from_iter([
|
||||
"Durability: ".gray(),
|
||||
durability.to_string().cyan(),
|
||||
"/".gray(),
|
||||
max_durability.to_string().cyan(),
|
||||
" ( ".gray(),
|
||||
durability_percent.to_string().cyan(),
|
||||
"% )".gray(),
|
||||
]),
|
||||
Line::from_iter(["Stress: ".gray(), stress.to_string().cyan(), "%".gray()]),
|
||||
];
|
||||
let mut lines: Vec<Line<'_>> = vec![
|
||||
Line::from_iter([
|
||||
"Durability: ".gray(),
|
||||
durability.to_string().cyan(),
|
||||
"/".gray(),
|
||||
max_durability.to_string().cyan(),
|
||||
" ( ".gray(),
|
||||
durability_percent.to_string().cyan(),
|
||||
"% )".gray(),
|
||||
]),
|
||||
Line::from_iter(["Stress: ".gray(), stress.to_string().cyan(), "%".gray()]),
|
||||
];
|
||||
|
||||
if level != ' ' {
|
||||
lines.push(Line::from_iter([
|
||||
"Level: ".gray(),
|
||||
level.to_string().cyan(),
|
||||
]));
|
||||
if level != ' ' {
|
||||
lines.push(Line::from_iter([
|
||||
"Level: ".gray(),
|
||||
level.to_string().cyan(),
|
||||
]));
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
self.base_text()
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
self.base_text()
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,100 @@
|
||||
use crate::app::states::skirmish_states::{
|
||||
Players,
|
||||
structures::{BaseBuilding, Mine, MineConstruction, Ore, Stone, Structure, Tunnel},
|
||||
units::Units,
|
||||
Players,
|
||||
structures::{BaseBuilding, Mine, MineConstruction, Ore, Stone, Structure, Tunnel},
|
||||
units::Units,
|
||||
};
|
||||
use ratatui::{
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Structures {
|
||||
Base(BaseBuilding),
|
||||
Tunnel(Tunnel),
|
||||
Stone(Stone),
|
||||
Ore(Ore),
|
||||
Mine(Mine),
|
||||
MineConstruction(MineConstruction),
|
||||
Base(BaseBuilding),
|
||||
Tunnel(Tunnel),
|
||||
Stone(Stone),
|
||||
Ore(Ore),
|
||||
Mine(Mine),
|
||||
MineConstruction(MineConstruction),
|
||||
}
|
||||
|
||||
impl Structures {
|
||||
pub fn can_enter(&self, unit: &Units) -> bool {
|
||||
match self {
|
||||
Self::Base(_) | Self::Tunnel(_) => true,
|
||||
Self::Mine(mine) => mine.accepts_unit(unit),
|
||||
_ => false,
|
||||
pub fn can_enter(&self, unit: &Units) -> bool {
|
||||
match self {
|
||||
Self::Base(_) | Self::Tunnel(_) => true,
|
||||
Self::Mine(mine) => mine.accepts_unit(unit),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn build_mine(&mut self, owner: Players) -> bool {
|
||||
if let Self::Ore(ore) = *self
|
||||
&& let Some(mine) = Mine::new(owner, ore)
|
||||
{
|
||||
*self = Self::Mine(mine);
|
||||
return true;
|
||||
pub fn build_mine(&mut self, owner: Players) -> bool {
|
||||
if let Self::Ore(ore) = *self
|
||||
&& let Some(mine) = Mine::new(owner, ore)
|
||||
{
|
||||
*self = Self::Mine(mine);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn s(&self) -> &dyn Structure {
|
||||
match self {
|
||||
Self::Base(b) => b,
|
||||
Self::Tunnel(t) => t,
|
||||
Self::Stone(s) => s,
|
||||
Self::Ore(o) => o,
|
||||
Self::Mine(mine) => mine,
|
||||
Self::MineConstruction(site) => site,
|
||||
#[inline]
|
||||
fn s(&self) -> &dyn Structure {
|
||||
match self {
|
||||
Self::Base(b) => b,
|
||||
Self::Tunnel(t) => t,
|
||||
Self::Stone(s) => s,
|
||||
Self::Ore(o) => o,
|
||||
Self::Mine(mine) => mine,
|
||||
Self::MineConstruction(site) => site,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Structures {
|
||||
fn get_color(&self) -> Color {
|
||||
self.s().get_color()
|
||||
}
|
||||
|
||||
fn get_tag(&self) -> char {
|
||||
self.s().get_tag()
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
self.s().get_level()
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.s().get_name()
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.s().get_durability()
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.s().get_max_durability()
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.s().get_stress()
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.s().get_owner()
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
match self.s().get_owner() {
|
||||
Players::Unclaimed => self.s().text(),
|
||||
Players::Player | Players::Enemy => {
|
||||
let mut lines: Vec<Line<'_>> = self.s().text();
|
||||
|
||||
lines.push(Line::from_iter([
|
||||
"Owner: ".gray(),
|
||||
self.s().get_owner().get_span(),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
self.s().get_color()
|
||||
}
|
||||
|
||||
fn get_tag(&self) -> char {
|
||||
self.s().get_tag()
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
self.s().get_level()
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.s().get_name()
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.s().get_durability()
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
self.s().get_max_durability()
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.s().get_stress()
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.s().get_owner()
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
match self.s().get_owner() {
|
||||
Players::Unclaimed => self.s().text(),
|
||||
Players::Player | Players::Enemy => {
|
||||
let mut lines: Vec<Line<'_>> = self.s().text();
|
||||
|
||||
lines.push(Line::from_iter([
|
||||
"Owner: ".gray(),
|
||||
self.s().get_owner().get_span(),
|
||||
]));
|
||||
|
||||
lines
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,55 +3,55 @@ use ratatui::style::Color;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Tunnel {
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
roof_support: bool,
|
||||
rail: bool,
|
||||
lamp: bool,
|
||||
durability: u16,
|
||||
stress: u8,
|
||||
roof_support: bool,
|
||||
rail: bool,
|
||||
lamp: bool,
|
||||
}
|
||||
|
||||
impl Tunnel {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
durability: 500,
|
||||
stress: 25,
|
||||
roof_support: false,
|
||||
rail: false,
|
||||
lamp: false,
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
durability: 500,
|
||||
stress: 25,
|
||||
roof_support: false,
|
||||
rail: false,
|
||||
lamp: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Tunnel {
|
||||
fn get_tag(&self) -> char {
|
||||
'T'
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
'T'
|
||||
}
|
||||
|
||||
fn get_color(&self) -> Color {
|
||||
Color::Gray
|
||||
}
|
||||
fn get_color(&self) -> Color {
|
||||
Color::Gray
|
||||
}
|
||||
|
||||
fn get_level(&self) -> char {
|
||||
' '
|
||||
}
|
||||
fn get_level(&self) -> char {
|
||||
' '
|
||||
}
|
||||
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
fn get_durability(&self) -> u16 {
|
||||
self.durability
|
||||
}
|
||||
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
500
|
||||
}
|
||||
fn get_max_durability(&self) -> u16 {
|
||||
500
|
||||
}
|
||||
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
fn get_stress(&self) -> u8 {
|
||||
self.stress
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Tunnel"
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Tunnel"
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
Players::Unclaimed
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
Players::Unclaimed
|
||||
}
|
||||
}
|
||||
@@ -3,71 +3,71 @@ use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct DiggingTask {
|
||||
path: VecDeque<(usize, usize)>,
|
||||
progress: f32,
|
||||
tick_increase: f32,
|
||||
total_steps: usize,
|
||||
path: VecDeque<(usize, usize)>,
|
||||
progress: f32,
|
||||
tick_increase: f32,
|
||||
total_steps: usize,
|
||||
}
|
||||
|
||||
impl DiggingTask {
|
||||
pub fn new(path: VecDeque<(usize, usize)>, tick_increase: f32) -> Self {
|
||||
Self {
|
||||
total_steps: path.len(),
|
||||
path,
|
||||
progress: 0.0,
|
||||
tick_increase,
|
||||
pub fn new(path: VecDeque<(usize, usize)>, tick_increase: f32) -> Self {
|
||||
Self {
|
||||
total_steps: path.len(),
|
||||
path,
|
||||
progress: 0.0,
|
||||
tick_increase,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_front(&mut self) {
|
||||
self.path.pop_front();
|
||||
self.progress = 0.0;
|
||||
}
|
||||
|
||||
pub fn from_moving(task: MovingTask, tick_increase: f32) -> Self {
|
||||
Self {
|
||||
path: task.get_path().clone(),
|
||||
progress: 0.0,
|
||||
tick_increase,
|
||||
total_steps: task.get_total_steps(),
|
||||
pub fn pop_front(&mut self) {
|
||||
self.path.pop_front();
|
||||
self.progress = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_target(&self) -> Option<(usize, usize)> {
|
||||
self.path.front().copied()
|
||||
}
|
||||
pub fn from_moving(task: MovingTask, tick_increase: f32) -> Self {
|
||||
Self {
|
||||
path: task.get_path().clone(),
|
||||
progress: 0.0,
|
||||
tick_increase,
|
||||
total_steps: task.get_total_steps(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_target(&self) -> Option<(usize, usize)> {
|
||||
self.path.front().copied()
|
||||
}
|
||||
}
|
||||
|
||||
impl Task for DiggingTask {
|
||||
fn get_icon(&self) -> char {
|
||||
'⛏'
|
||||
}
|
||||
fn get_icon(&self) -> char {
|
||||
'⛏'
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
&self.path
|
||||
}
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.path.front().map_or(&(0, 0), |c| c)
|
||||
}
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.path.front().map_or(&(0, 0), |c| c)
|
||||
}
|
||||
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.path.back().map_or(&(0, 0), |c| c)
|
||||
}
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.path.back().map_or(&(0, 0), |c| c)
|
||||
}
|
||||
|
||||
fn get_progress(&self) -> f32 {
|
||||
self.progress
|
||||
}
|
||||
fn get_progress(&self) -> f32 {
|
||||
self.progress
|
||||
}
|
||||
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.total_steps
|
||||
}
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.total_steps
|
||||
}
|
||||
|
||||
fn progress(&mut self) {
|
||||
self.progress = (self.progress + self.tick_increase).clamp(0.0, 100.0);
|
||||
}
|
||||
fn progress(&mut self) {
|
||||
self.progress = (self.progress + self.tick_increase).clamp(0.0, 100.0);
|
||||
}
|
||||
|
||||
fn is_finished(&self) -> bool {
|
||||
self.progress >= 100.0
|
||||
}
|
||||
fn is_finished(&self) -> bool {
|
||||
self.progress >= 100.0
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::app::{
|
||||
states::skirmish_states::tasks::{DiggingTask, Task},
|
||||
threads::TICK_MS,
|
||||
states::skirmish_states::tasks::{DiggingTask, Task},
|
||||
threads::TICK_MS,
|
||||
};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
@@ -8,68 +8,68 @@ const MOVEMENT_TICKS: u16 = 3000_u16.div_ceil(TICK_MS as u16);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct MovingTask {
|
||||
path: VecDeque<(usize, usize)>,
|
||||
ticks: u16,
|
||||
total_steps: usize,
|
||||
path: VecDeque<(usize, usize)>,
|
||||
ticks: u16,
|
||||
total_steps: usize,
|
||||
}
|
||||
|
||||
impl MovingTask {
|
||||
pub fn new(path: VecDeque<(usize, usize)>) -> Self {
|
||||
Self {
|
||||
total_steps: path.len(),
|
||||
path,
|
||||
ticks: 0,
|
||||
pub fn new(path: VecDeque<(usize, usize)>) -> Self {
|
||||
Self {
|
||||
total_steps: path.len(),
|
||||
path,
|
||||
ticks: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_digging(task: DiggingTask) -> Self {
|
||||
Self {
|
||||
total_steps: task.get_total_steps(),
|
||||
path: task.get_path().clone(),
|
||||
ticks: 0,
|
||||
pub fn from_digging(task: DiggingTask) -> Self {
|
||||
Self {
|
||||
total_steps: task.get_total_steps(),
|
||||
path: task.get_path().clone(),
|
||||
ticks: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_front(&mut self) {
|
||||
self.path.pop_front();
|
||||
self.ticks = 0;
|
||||
}
|
||||
pub fn pop_front(&mut self) {
|
||||
self.path.pop_front();
|
||||
self.ticks = 0;
|
||||
}
|
||||
|
||||
pub fn get_movement_progress(&self) -> Option<u16> {
|
||||
(self.ticks > 0).then(|| self.ticks * 100 / MOVEMENT_TICKS)
|
||||
}
|
||||
pub fn get_movement_progress(&self) -> Option<u16> {
|
||||
(self.ticks > 0).then(|| self.ticks * 100 / MOVEMENT_TICKS)
|
||||
}
|
||||
}
|
||||
|
||||
impl Task for MovingTask {
|
||||
fn get_icon(&self) -> char {
|
||||
'→'
|
||||
}
|
||||
fn get_icon(&self) -> char {
|
||||
'→'
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
&self.path
|
||||
}
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.path.front().unwrap_or(&(0, 0))
|
||||
}
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.path.front().unwrap_or(&(0, 0))
|
||||
}
|
||||
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.path.back().unwrap_or(&(0, 0))
|
||||
}
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.path.back().unwrap_or(&(0, 0))
|
||||
}
|
||||
|
||||
fn get_progress(&self) -> f32 {
|
||||
f32::from(self.ticks) * 100.0 / f32::from(MOVEMENT_TICKS)
|
||||
}
|
||||
fn get_progress(&self) -> f32 {
|
||||
f32::from(self.ticks) * 100.0 / f32::from(MOVEMENT_TICKS)
|
||||
}
|
||||
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.total_steps
|
||||
}
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.total_steps
|
||||
}
|
||||
|
||||
fn progress(&mut self) {
|
||||
self.ticks = (self.ticks + 1).min(MOVEMENT_TICKS);
|
||||
}
|
||||
fn progress(&mut self) {
|
||||
self.ticks = (self.ticks + 1).min(MOVEMENT_TICKS);
|
||||
}
|
||||
|
||||
fn is_finished(&self) -> bool {
|
||||
self.ticks == MOVEMENT_TICKS
|
||||
}
|
||||
fn is_finished(&self) -> bool {
|
||||
self.ticks == MOVEMENT_TICKS
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub trait Task {
|
||||
fn get_icon(&self) -> char;
|
||||
fn get_icon(&self) -> char;
|
||||
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)>;
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)>;
|
||||
|
||||
fn get_path_front_coords(&self) -> &(usize, usize);
|
||||
fn get_path_front_coords(&self) -> &(usize, usize);
|
||||
|
||||
fn get_path_back_coords(&self) -> &(usize, usize);
|
||||
fn get_path_back_coords(&self) -> &(usize, usize);
|
||||
|
||||
fn get_progress(&self) -> f32;
|
||||
fn get_progress(&self) -> f32;
|
||||
|
||||
fn get_total_steps(&self) -> usize;
|
||||
fn get_total_steps(&self) -> usize;
|
||||
|
||||
fn get_total_progress(&self) -> f32 {
|
||||
let total: usize = self.get_total_steps();
|
||||
if total == 0 {
|
||||
return 100.0;
|
||||
fn get_total_progress(&self) -> f32 {
|
||||
let total: usize = self.get_total_steps();
|
||||
if total == 0 {
|
||||
return 100.0;
|
||||
}
|
||||
let completed: usize = total.saturating_sub(self.get_path().len());
|
||||
((completed as f32 * 100.0 + self.get_progress()) / total as f32).clamp(0.0, 100.0)
|
||||
}
|
||||
let completed: usize = total.saturating_sub(self.get_path().len());
|
||||
((completed as f32 * 100.0 + self.get_progress()) / total as f32).clamp(0.0, 100.0)
|
||||
}
|
||||
|
||||
fn progress(&mut self);
|
||||
fn progress(&mut self);
|
||||
|
||||
fn is_finished(&self) -> bool;
|
||||
fn is_finished(&self) -> bool;
|
||||
}
|
||||
@@ -3,58 +3,58 @@ use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Tasks {
|
||||
Digging(DiggingTask),
|
||||
Moving(MovingTask),
|
||||
Digging(DiggingTask),
|
||||
Moving(MovingTask),
|
||||
}
|
||||
|
||||
impl Tasks {
|
||||
#[inline]
|
||||
fn t(&self) -> &dyn Task {
|
||||
match self {
|
||||
Self::Digging(d) => d,
|
||||
Self::Moving(m) => m,
|
||||
#[inline]
|
||||
fn t(&self) -> &dyn Task {
|
||||
match self {
|
||||
Self::Digging(d) => d,
|
||||
Self::Moving(m) => m,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn t_mut(&mut self) -> &mut dyn Task {
|
||||
match self {
|
||||
Self::Digging(d) => d,
|
||||
Self::Moving(m) => m,
|
||||
#[inline]
|
||||
fn t_mut(&mut self) -> &mut dyn Task {
|
||||
match self {
|
||||
Self::Digging(d) => d,
|
||||
Self::Moving(m) => m,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Task for Tasks {
|
||||
fn get_icon(&self) -> char {
|
||||
self.t().get_icon()
|
||||
}
|
||||
fn get_icon(&self) -> char {
|
||||
self.t().get_icon()
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
self.t().get_path()
|
||||
}
|
||||
fn get_path(&self) -> &VecDeque<(usize, usize)> {
|
||||
self.t().get_path()
|
||||
}
|
||||
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.t().get_path_front_coords()
|
||||
}
|
||||
fn get_path_front_coords(&self) -> &(usize, usize) {
|
||||
self.t().get_path_front_coords()
|
||||
}
|
||||
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.t().get_path_back_coords()
|
||||
}
|
||||
fn get_path_back_coords(&self) -> &(usize, usize) {
|
||||
self.t().get_path_back_coords()
|
||||
}
|
||||
|
||||
fn get_progress(&self) -> f32 {
|
||||
self.t().get_progress()
|
||||
}
|
||||
fn get_progress(&self) -> f32 {
|
||||
self.t().get_progress()
|
||||
}
|
||||
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.t().get_total_steps()
|
||||
}
|
||||
fn get_total_steps(&self) -> usize {
|
||||
self.t().get_total_steps()
|
||||
}
|
||||
|
||||
fn is_finished(&self) -> bool {
|
||||
self.t().is_finished()
|
||||
}
|
||||
fn is_finished(&self) -> bool {
|
||||
self.t().is_finished()
|
||||
}
|
||||
|
||||
fn progress(&mut self) {
|
||||
self.t_mut().progress();
|
||||
}
|
||||
fn progress(&mut self) {
|
||||
self.t_mut().progress();
|
||||
}
|
||||
}
|
||||
@@ -1,133 +1,132 @@
|
||||
use ratatui::{style::Stylize, text::Line};
|
||||
|
||||
use crate::app::states::skirmish_states::{
|
||||
Players, Resources,
|
||||
tasks::{Task, Tasks},
|
||||
units::Unit,
|
||||
Players, Resources,
|
||||
tasks::{Task, Tasks},
|
||||
units::Unit,
|
||||
};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct MinerUnit {
|
||||
owner: Players,
|
||||
hp: u16,
|
||||
can_dig: bool,
|
||||
digging_power: f32,
|
||||
coords: (usize, usize),
|
||||
tasks: VecDeque<Tasks>,
|
||||
owner: Players,
|
||||
hp: u16,
|
||||
can_dig: bool,
|
||||
digging_power: f32,
|
||||
coords: (usize, usize),
|
||||
tasks: VecDeque<Tasks>,
|
||||
}
|
||||
|
||||
impl MinerUnit {
|
||||
pub const RECRUIT_COST: Resources = Resources {
|
||||
wood: 10,
|
||||
metal: 15,
|
||||
};
|
||||
pub fn new(owner: Players, coords: (usize, usize)) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
hp: 100,
|
||||
can_dig: true,
|
||||
digging_power: 0.55,
|
||||
coords,
|
||||
tasks: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn col_to_letters(&self, col: usize) -> String {
|
||||
let mut col: usize = col + 1;
|
||||
let mut letters: Vec<char> = Vec::new();
|
||||
|
||||
while col > 0 {
|
||||
letters.push((b'A' + ((col - 1) % 26) as u8) as char);
|
||||
col = (col - 1) / 26;
|
||||
pub const RECRUIT_COST: Resources = Resources {
|
||||
wood: 10,
|
||||
metal: 15,
|
||||
};
|
||||
pub fn new(owner: Players, coords: (usize, usize)) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
hp: 100,
|
||||
can_dig: true,
|
||||
digging_power: 0.55,
|
||||
coords,
|
||||
tasks: VecDeque::new(),
|
||||
}
|
||||
}
|
||||
|
||||
letters.iter().rev().collect()
|
||||
}
|
||||
fn col_to_letters(&self, col: usize) -> String {
|
||||
let mut col: usize = col + 1;
|
||||
let mut letters: Vec<char> = Vec::new();
|
||||
|
||||
fn display_coords(&self, coords: &(usize, usize)) -> String {
|
||||
format!("{}{}", self.col_to_letters(coords.0), coords.1)
|
||||
}
|
||||
while col > 0 {
|
||||
letters.push((b'A' + ((col - 1) % 26) as u8) as char);
|
||||
col = (col - 1) / 26;
|
||||
}
|
||||
|
||||
letters.iter().rev().collect()
|
||||
}
|
||||
|
||||
fn display_coords(&self, coords: &(usize, usize)) -> String {
|
||||
format!("{}{}", self.col_to_letters(coords.0), coords.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Unit for MinerUnit {
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.owner
|
||||
}
|
||||
|
||||
fn get_tag(&self) -> char {
|
||||
'M'
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
'M'
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Miner"
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Miner"
|
||||
}
|
||||
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.hp
|
||||
}
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.hp
|
||||
}
|
||||
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
100
|
||||
}
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
100
|
||||
}
|
||||
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.can_dig
|
||||
}
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.can_dig
|
||||
}
|
||||
|
||||
fn get_can_build(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn get_can_build(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.digging_power
|
||||
}
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.digging_power
|
||||
}
|
||||
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.coords
|
||||
}
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.coords
|
||||
}
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
self.coords = coords;
|
||||
}
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
self.coords = coords;
|
||||
}
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
&self.tasks
|
||||
}
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
&self.tasks
|
||||
}
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
&mut self.tasks
|
||||
}
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
&mut self.tasks
|
||||
}
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
Vec::from(
|
||||
self
|
||||
.tasks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, task): (usize, &Tasks)| -> [Line<'_>; 2] {
|
||||
[
|
||||
Line::from_iter([
|
||||
format!("{}. ", i + 1).gray(),
|
||||
task.get_icon().gray(),
|
||||
" ".gray(),
|
||||
self.display_coords(task.get_path_front_coords()).green(),
|
||||
" -> ".gray(),
|
||||
self.display_coords(task.get_path_back_coords()).yellow(),
|
||||
]),
|
||||
Line::from(format!(
|
||||
" Step: {}% | Total: {}%",
|
||||
task.get_progress() as u16,
|
||||
task.get_total_progress() as u16,
|
||||
))
|
||||
.cyan(),
|
||||
]
|
||||
})
|
||||
.collect::<Vec<Line<'_>>>(),
|
||||
)
|
||||
}
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
Vec::from(
|
||||
self.tasks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, task): (usize, &Tasks)| -> [Line<'_>; 2] {
|
||||
[
|
||||
Line::from_iter([
|
||||
format!("{}. ", i + 1).gray(),
|
||||
task.get_icon().gray(),
|
||||
" ".gray(),
|
||||
self.display_coords(task.get_path_front_coords()).green(),
|
||||
" -> ".gray(),
|
||||
self.display_coords(task.get_path_back_coords()).yellow(),
|
||||
]),
|
||||
Line::from(format!(
|
||||
" Step: {}% | Total: {}%",
|
||||
task.get_progress() as u16,
|
||||
task.get_total_progress() as u16,
|
||||
))
|
||||
.cyan(),
|
||||
]
|
||||
})
|
||||
.collect::<Vec<Line<'_>>>(),
|
||||
)
|
||||
}
|
||||
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.tasks.push_back(task);
|
||||
}
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.tasks.push_back(task);
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,90 @@
|
||||
use crate::app::states::skirmish_states::{Players, tasks::Tasks};
|
||||
use ratatui::{
|
||||
style::Stylize,
|
||||
text::{Line, Span},
|
||||
style::Stylize,
|
||||
text::{Line, Span},
|
||||
};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub trait Unit {
|
||||
fn is_unit(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players;
|
||||
|
||||
fn get_tag(&self) -> char;
|
||||
|
||||
fn get_name(&self) -> &'static str;
|
||||
|
||||
fn get_hp(&self) -> u16;
|
||||
|
||||
fn get_max_hp(&self) -> u16;
|
||||
|
||||
fn get_can_dig(&self) -> bool;
|
||||
|
||||
fn get_can_build(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn get_digging_power(&self) -> f32;
|
||||
|
||||
fn get_coords(&self) -> (usize, usize);
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize));
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks>;
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks>;
|
||||
|
||||
fn set_task(&mut self, task: Tasks);
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>>;
|
||||
|
||||
fn base_text(&self) -> Vec<Line<'_>> {
|
||||
let owner: Span<'_> = self.get_owner().get_span();
|
||||
let hp: u16 = self.get_hp();
|
||||
let max_hp: u16 = self.get_max_hp();
|
||||
let hp_percent: u16 = hp * 100 / max_hp;
|
||||
let can_dig: bool = self.get_can_dig();
|
||||
let digging_power: f32 = self.get_digging_power();
|
||||
let have_any_tasks: bool = self.get_ref_tasks().is_empty();
|
||||
let tasks: Vec<Line<'_>> = self.get_tasks_formatted();
|
||||
|
||||
let mut lines: Vec<Line<'_>> = Vec::from([
|
||||
Line::from_iter(["Owner: ".gray(), owner]),
|
||||
Line::from_iter([
|
||||
"HP: ".gray(),
|
||||
hp.green(),
|
||||
"/".gray(),
|
||||
max_hp.green(),
|
||||
" ( ".gray(),
|
||||
hp_percent.green(),
|
||||
"% )".gray(),
|
||||
]),
|
||||
]);
|
||||
|
||||
if can_dig {
|
||||
lines.push(Line::from_iter([
|
||||
"Digging power: ".gray(),
|
||||
digging_power.green(),
|
||||
]));
|
||||
fn is_unit(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
if self.get_can_build() {
|
||||
lines.push(Line::from("Can build: Yes").green());
|
||||
fn get_owner(&self) -> Players;
|
||||
|
||||
fn get_tag(&self) -> char;
|
||||
|
||||
fn get_name(&self) -> &'static str;
|
||||
|
||||
fn get_hp(&self) -> u16;
|
||||
|
||||
fn get_max_hp(&self) -> u16;
|
||||
|
||||
fn get_can_dig(&self) -> bool;
|
||||
|
||||
fn get_can_build(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
if !have_any_tasks {
|
||||
lines.push(Line::from("Tasks Queue: ".gray()));
|
||||
for task in tasks {
|
||||
lines.push(task);
|
||||
}
|
||||
fn get_digging_power(&self) -> f32;
|
||||
|
||||
fn get_coords(&self) -> (usize, usize);
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize));
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks>;
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks>;
|
||||
|
||||
fn set_task(&mut self, task: Tasks);
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>>;
|
||||
|
||||
fn base_text(&self) -> Vec<Line<'_>> {
|
||||
let owner: Span<'_> = self.get_owner().get_span();
|
||||
let hp: u16 = self.get_hp();
|
||||
let max_hp: u16 = self.get_max_hp();
|
||||
let hp_percent: u16 = hp * 100 / max_hp;
|
||||
let can_dig: bool = self.get_can_dig();
|
||||
let digging_power: f32 = self.get_digging_power();
|
||||
let have_any_tasks: bool = self.get_ref_tasks().is_empty();
|
||||
let tasks: Vec<Line<'_>> = self.get_tasks_formatted();
|
||||
|
||||
let mut lines: Vec<Line<'_>> = Vec::from([
|
||||
Line::from_iter(["Owner: ".gray(), owner]),
|
||||
Line::from_iter([
|
||||
"HP: ".gray(),
|
||||
hp.green(),
|
||||
"/".gray(),
|
||||
max_hp.green(),
|
||||
" ( ".gray(),
|
||||
hp_percent.green(),
|
||||
"% )".gray(),
|
||||
]),
|
||||
]);
|
||||
|
||||
if can_dig {
|
||||
lines.push(Line::from_iter([
|
||||
"Digging power: ".gray(),
|
||||
digging_power.green(),
|
||||
]));
|
||||
}
|
||||
|
||||
if self.get_can_build() {
|
||||
lines.push(Line::from("Can build: Yes").green());
|
||||
}
|
||||
|
||||
if !have_any_tasks {
|
||||
lines.push(Line::from("Tasks Queue: ".gray()));
|
||||
for task in tasks {
|
||||
lines.push(task);
|
||||
}
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
self.base_text()
|
||||
}
|
||||
fn text(&self) -> Vec<Line<'_>> {
|
||||
self.base_text()
|
||||
}
|
||||
}
|
||||
@@ -1,158 +1,154 @@
|
||||
use crate::app::states::skirmish_states::{
|
||||
Players,
|
||||
tasks::Tasks,
|
||||
units::{MinerUnit, Unit},
|
||||
Players,
|
||||
tasks::Tasks,
|
||||
units::{MinerUnit, Unit},
|
||||
};
|
||||
use ratatui::text::Line;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Units {
|
||||
Miner(MinerUnit),
|
||||
Miner(MinerUnit),
|
||||
}
|
||||
|
||||
impl Units {
|
||||
#[inline]
|
||||
pub fn u(&self) -> &dyn Unit {
|
||||
match self {
|
||||
Self::Miner(m) => m,
|
||||
#[inline]
|
||||
pub fn u(&self) -> &dyn Unit {
|
||||
match self {
|
||||
Self::Miner(m) => m,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn u_mut(&mut self) -> &mut dyn Unit {
|
||||
match self {
|
||||
Self::Miner(m) => m,
|
||||
#[inline]
|
||||
pub fn u_mut(&mut self) -> &mut dyn Unit {
|
||||
match self {
|
||||
Self::Miner(m) => m,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Unit for Units {
|
||||
fn get_can_build(&self) -> bool {
|
||||
self.u().get_can_build()
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
self.u().get_tag()
|
||||
}
|
||||
fn get_can_build(&self) -> bool {
|
||||
self.u().get_can_build()
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
self.u().get_tag()
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.u().get_name()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.u().get_name()
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.u().get_owner()
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.u().get_owner()
|
||||
}
|
||||
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.u().get_hp()
|
||||
}
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.u().get_hp()
|
||||
}
|
||||
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
self.u().get_max_hp()
|
||||
}
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
self.u().get_max_hp()
|
||||
}
|
||||
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.u().get_can_dig()
|
||||
}
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.u().get_can_dig()
|
||||
}
|
||||
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.u().get_digging_power()
|
||||
}
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.u().get_digging_power()
|
||||
}
|
||||
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.u().get_coords()
|
||||
}
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.u().get_coords()
|
||||
}
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
self.u_mut().set_coords(coords);
|
||||
}
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
self.u_mut().set_coords(coords);
|
||||
}
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
self.u().get_ref_tasks()
|
||||
}
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
self.u().get_ref_tasks()
|
||||
}
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
self.u_mut().get_mut_tasks()
|
||||
}
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
self.u_mut().get_mut_tasks()
|
||||
}
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
self.u().get_tasks_formatted()
|
||||
}
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
self.u().get_tasks_formatted()
|
||||
}
|
||||
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.u_mut().set_task(task);
|
||||
}
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.u_mut().set_task(task);
|
||||
}
|
||||
}
|
||||
|
||||
impl Unit for Option<Units> {
|
||||
fn get_can_build(&self) -> bool {
|
||||
self
|
||||
.as_ref()
|
||||
.is_some_and(|unit: &Units| -> bool { unit.get_can_build() })
|
||||
}
|
||||
fn is_unit(&self) -> bool {
|
||||
self.as_ref().map_or(false, |u| u.is_unit())
|
||||
}
|
||||
|
||||
fn get_tag(&self) -> char {
|
||||
self.as_ref().map_or(' ', |u| u.get_tag())
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.as_ref().map_or("", |u| u.get_name())
|
||||
}
|
||||
|
||||
fn get_owner(&self) -> Players {
|
||||
self.as_ref().map_or(Players::Unclaimed, |u| u.get_owner())
|
||||
}
|
||||
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.as_ref().map_or(0, |u| u.get_hp())
|
||||
}
|
||||
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
self.as_ref().map_or(0, |u| u.get_max_hp())
|
||||
}
|
||||
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.as_ref().map_or(false, |u| u.get_can_dig())
|
||||
}
|
||||
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.as_ref().map_or(0.0, |u| u.get_digging_power())
|
||||
}
|
||||
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.as_ref().map_or((0, 0), |u| u.get_coords())
|
||||
}
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
if let Some(unit) = self.as_mut() {
|
||||
unit.set_coords(coords);
|
||||
fn get_can_build(&self) -> bool {
|
||||
self.as_ref()
|
||||
.is_some_and(|unit: &Units| -> bool { unit.get_can_build() })
|
||||
}
|
||||
fn is_unit(&self) -> bool {
|
||||
self.as_ref().map_or(false, |u| u.is_unit())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
self
|
||||
.as_ref()
|
||||
.expect("attempted to get referenced tasks from `None`")
|
||||
.get_ref_tasks()
|
||||
}
|
||||
fn get_tag(&self) -> char {
|
||||
self.as_ref().map_or(' ', |u| u.get_tag())
|
||||
}
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
self
|
||||
.as_mut()
|
||||
.expect("attempted to get mutable tasks from `None`")
|
||||
.get_mut_tasks()
|
||||
}
|
||||
fn get_name(&self) -> &'static str {
|
||||
self.as_ref().map_or("", |u| u.get_name())
|
||||
}
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
self
|
||||
.as_ref()
|
||||
.map_or(Vec::new(), |u| u.get_tasks_formatted())
|
||||
}
|
||||
fn get_owner(&self) -> Players {
|
||||
self.as_ref().map_or(Players::Unclaimed, |u| u.get_owner())
|
||||
}
|
||||
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.as_mut().map_or((), |u| u.set_task(task))
|
||||
}
|
||||
fn get_hp(&self) -> u16 {
|
||||
self.as_ref().map_or(0, |u| u.get_hp())
|
||||
}
|
||||
|
||||
fn get_max_hp(&self) -> u16 {
|
||||
self.as_ref().map_or(0, |u| u.get_max_hp())
|
||||
}
|
||||
|
||||
fn get_can_dig(&self) -> bool {
|
||||
self.as_ref().map_or(false, |u| u.get_can_dig())
|
||||
}
|
||||
|
||||
fn get_digging_power(&self) -> f32 {
|
||||
self.as_ref().map_or(0.0, |u| u.get_digging_power())
|
||||
}
|
||||
|
||||
fn get_coords(&self) -> (usize, usize) {
|
||||
self.as_ref().map_or((0, 0), |u| u.get_coords())
|
||||
}
|
||||
|
||||
fn set_coords(&mut self, coords: (usize, usize)) {
|
||||
if let Some(unit) = self.as_mut() {
|
||||
unit.set_coords(coords);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
|
||||
self.as_ref()
|
||||
.expect("attempted to get referenced tasks from `None`")
|
||||
.get_ref_tasks()
|
||||
}
|
||||
|
||||
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
|
||||
self.as_mut()
|
||||
.expect("attempted to get mutable tasks from `None`")
|
||||
.get_mut_tasks()
|
||||
}
|
||||
|
||||
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
|
||||
self.as_ref()
|
||||
.map_or(Vec::new(), |u| u.get_tasks_formatted())
|
||||
}
|
||||
|
||||
fn set_task(&mut self, task: Tasks) {
|
||||
self.as_mut().map_or((), |u| u.set_task(task))
|
||||
}
|
||||
}
|
||||
@@ -3,56 +3,56 @@ use ratatui::text::{Line, Span};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
|
||||
pub enum ZoomLevel {
|
||||
ZoomedIn,
|
||||
Default,
|
||||
ZoomedOut,
|
||||
ZoomedIn,
|
||||
Default,
|
||||
ZoomedOut,
|
||||
}
|
||||
|
||||
pub enum CellSizes {
|
||||
Width,
|
||||
Height,
|
||||
Width,
|
||||
Height,
|
||||
}
|
||||
|
||||
impl ZoomLevel {
|
||||
pub fn get_cell_size(&self, cell_size: CellSizes) -> usize {
|
||||
match (cell_size, self) {
|
||||
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
|
||||
(CellSizes::Width, ZoomLevel::Default) => 9,
|
||||
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
|
||||
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
|
||||
(CellSizes::Height, ZoomLevel::Default) => 5,
|
||||
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
|
||||
pub fn get_cell_size(&self, cell_size: CellSizes) -> usize {
|
||||
match (cell_size, self) {
|
||||
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
|
||||
(CellSizes::Width, ZoomLevel::Default) => 9,
|
||||
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
|
||||
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
|
||||
(CellSizes::Height, ZoomLevel::Default) => 5,
|
||||
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cell_text_area<'a>(
|
||||
&self,
|
||||
tag: char,
|
||||
structure_level: char,
|
||||
unit: Span<'a>,
|
||||
) -> Vec<Line<'a>> {
|
||||
match self {
|
||||
ZoomLevel::ZoomedIn => vec![
|
||||
Line::from(vec![
|
||||
Span::raw(format!(" {} ", structure_level)),
|
||||
unit,
|
||||
Span::raw(" "),
|
||||
]),
|
||||
Line::from(format!(" ")),
|
||||
Line::from(format!(" {} ", tag)),
|
||||
Line::from(format!(" ")),
|
||||
Line::from(format!(" ")),
|
||||
],
|
||||
ZoomLevel::Default => vec![
|
||||
Line::from(vec![
|
||||
Span::raw(format!(" {} ", structure_level)),
|
||||
unit,
|
||||
Span::raw(" "),
|
||||
]),
|
||||
Line::from(format!(" {} ", tag)),
|
||||
Line::from(format!(" ")),
|
||||
],
|
||||
ZoomLevel::ZoomedOut => vec![Line::from(format!(" {} ", tag))],
|
||||
pub fn get_cell_text_area<'a>(
|
||||
&self,
|
||||
tag: char,
|
||||
structure_level: char,
|
||||
unit: Span<'a>,
|
||||
) -> Vec<Line<'a>> {
|
||||
match self {
|
||||
ZoomLevel::ZoomedIn => vec![
|
||||
Line::from(vec![
|
||||
Span::raw(format!(" {} ", structure_level)),
|
||||
unit,
|
||||
Span::raw(" "),
|
||||
]),
|
||||
Line::from(format!(" ")),
|
||||
Line::from(format!(" {} ", tag)),
|
||||
Line::from(format!(" ")),
|
||||
Line::from(format!(" ")),
|
||||
],
|
||||
ZoomLevel::Default => vec![
|
||||
Line::from(vec![
|
||||
Span::raw(format!(" {} ", structure_level)),
|
||||
unit,
|
||||
Span::raw(" "),
|
||||
]),
|
||||
Line::from(format!(" {} ", tag)),
|
||||
Line::from(format!(" ")),
|
||||
],
|
||||
ZoomLevel::ZoomedOut => vec![Line::from(format!(" {} ", tag))],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user