161 lines
5.3 KiB
Rust
161 lines
5.3 KiB
Rust
use crate::border_panel::{INNER_BORDER, draw_border_panel};
|
|
use crate::{Currency, bar::Bar, game::State, row::Row};
|
|
use servicepoint::{Bitmap, CharGrid, CharGridMutExt, TILE_SIZE, WindowMut};
|
|
use std::{
|
|
collections::VecDeque,
|
|
fmt::{Debug, Formatter},
|
|
ops::Mul,
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct UnlockSystem {
|
|
bought: usize,
|
|
last_unlock: Option<String>,
|
|
unlock_queue: VecDeque<Unlock>,
|
|
all_unlocks_bar: Bar,
|
|
next_unlock_bar: Bar,
|
|
total_unlock_count: usize,
|
|
}
|
|
|
|
pub struct Unlock {
|
|
pub name: String,
|
|
pub cost: Currency,
|
|
pub apply: Box<dyn Fn(&mut State)>,
|
|
}
|
|
|
|
impl Debug for Unlock {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(format_args!(
|
|
"Upgrade {{ name: {:?}, cost: {:?} }}",
|
|
self.name, self.cost
|
|
))
|
|
}
|
|
}
|
|
|
|
impl UnlockSystem {
|
|
pub fn new(start_state: &State) -> Self {
|
|
let mut upgrades = Self::gen_bar_enable_unlocks(&start_state.rows)
|
|
.chain(Self::gen_global_speed_unlocks())
|
|
.chain(Self::gen_global_productivity_unlocks())
|
|
.chain(Self::gen_bar_speed_unlocks(&start_state.rows))
|
|
.chain(Self::gen_bar_productivity_unlocks(&start_state.rows))
|
|
.collect::<Vec<_>>();
|
|
upgrades.sort_by(|l, r| l.cost.total_cmp(&r.cost));
|
|
|
|
Self {
|
|
total_unlock_count: upgrades.len(),
|
|
unlock_queue: upgrades.into(),
|
|
bought: 0,
|
|
last_unlock: None,
|
|
all_unlocks_bar: Bar::new(),
|
|
next_unlock_bar: Bar::new(),
|
|
}
|
|
}
|
|
|
|
pub fn peek_next(&self) -> Option<&Unlock> {
|
|
self.unlock_queue.front()
|
|
}
|
|
|
|
pub fn progress(&mut self, state: &mut State) {
|
|
if let Some(next_upgrade) = self.peek_next() {
|
|
if next_upgrade.cost <= state.currency {
|
|
self.buy_next(state);
|
|
self.next_unlock_bar.progress = 0.0;
|
|
} else {
|
|
self.next_unlock_bar.progress = state.currency / next_upgrade.cost;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn draw(
|
|
&self,
|
|
chars: &mut WindowMut<char, CharGrid>,
|
|
bitmap: &mut WindowMut<bool, Bitmap>,
|
|
) {
|
|
let title = format!(" Stage {}/{} ", self.bought, self.total_unlock_count);
|
|
|
|
let (mut chars, mut bitmap) = draw_border_panel(chars, bitmap, &title, INNER_BORDER);
|
|
|
|
let (all_unlocks_pixels, mut bitmap) = bitmap.split_vertical_mut(TILE_SIZE).unwrap();
|
|
self.all_unlocks_bar.draw(all_unlocks_pixels);
|
|
|
|
let (next_unlocks_pixels, _) = bitmap.split_vertical_mut(TILE_SIZE).unwrap();
|
|
self.next_unlock_bar.draw(next_unlocks_pixels);
|
|
|
|
if let Some(next) = self.peek_next() {
|
|
let (_, mut next_unlock_chars) = chars.split_vertical_mut(2).unwrap();
|
|
next_unlock_chars
|
|
.set_row_str(0, &format!("Loading: {}", next.name))
|
|
.unwrap();
|
|
}
|
|
}
|
|
|
|
fn buy_next(&mut self, state: &mut State) {
|
|
let next_upgrade = self.unlock_queue.pop_front().unwrap();
|
|
log::info!("Applying upgrade {:?}", &next_upgrade);
|
|
|
|
state.currency -= next_upgrade.cost;
|
|
(next_upgrade.apply)(state);
|
|
|
|
self.last_unlock = Some(next_upgrade.name);
|
|
self.bought += 1;
|
|
|
|
self.all_unlocks_bar.progress = self.bought as f64 / self.total_unlock_count as f64;
|
|
}
|
|
|
|
fn gen_bar_enable_unlocks(bars: &[Row]) -> impl Iterator<Item = Unlock> {
|
|
bars.iter().enumerate().map(|(index, bar)| Unlock {
|
|
name: format!("Start {}", bar.name()),
|
|
cost: 10f64.powi(index as i32),
|
|
apply: Box::new(move |game| {
|
|
game.rows[index].enabled = true;
|
|
}),
|
|
})
|
|
}
|
|
|
|
fn gen_global_speed_unlocks() -> impl Iterator<Item = Unlock> {
|
|
(1..32).map_while(|level| {
|
|
Some(Unlock {
|
|
name: format!("The answer {}", level),
|
|
cost: 42f64.mul(2f64.powi(level)),
|
|
apply: Box::new(move |game| {
|
|
game.speed *= 1.15;
|
|
}),
|
|
})
|
|
})
|
|
}
|
|
|
|
fn gen_global_productivity_unlocks() -> impl Iterator<Item = Unlock> {
|
|
(1..32).map(|level| Unlock {
|
|
name: format!("??? {}", level),
|
|
cost: 23f64.mul(2f64.powi(level)),
|
|
apply: Box::new(move |game| {
|
|
game.productivity *= 1.15;
|
|
}),
|
|
})
|
|
}
|
|
|
|
fn gen_bar_productivity_unlocks(bars: &[Row]) -> impl Iterator<Item = Unlock> {
|
|
bars.iter().enumerate().flat_map(|(index, bar)| {
|
|
(1..=20).map(move |level| Unlock {
|
|
name: format!("{} productivity {level}", bar.name()),
|
|
cost: 10f64.powi(index as i32).mul(3f64.powi(level)),
|
|
apply: Box::new(move |game| {
|
|
game.rows[index].productivity *= 1.5;
|
|
}),
|
|
})
|
|
})
|
|
}
|
|
|
|
fn gen_bar_speed_unlocks(bars: &[Row]) -> impl Iterator<Item = Unlock> {
|
|
bars.iter().enumerate().flat_map(|(index, bar)| {
|
|
(1..=15).map(move |level| Unlock {
|
|
name: format!("{} speed {level}", bar.name()),
|
|
cost: 10f64.powi(index as i32).mul(5f64.powi(level)),
|
|
apply: Box::new(move |game| {
|
|
game.rows[index].speed *= 1.5;
|
|
}),
|
|
})
|
|
})
|
|
}
|
|
}
|