From 0169a88091e5befcd78ab35119e3267f06aadea2 Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Tue, 1 Aug 2023 01:44:02 +0100 Subject: [PATCH] RegenSystem{} for health regen (mana NYI) --- src/ai/energy_system.rs | 9 ++++-- src/ai/mod.rs | 2 ++ src/ai/regen_system.rs | 61 +++++++++++++++++++++++++++++++++++++++++ src/camera.rs | 7 ++++- src/damage_system.rs | 1 + src/main.rs | 8 ++++-- src/player.rs | 8 +----- src/spawner.rs | 6 ++-- 8 files changed, 86 insertions(+), 16 deletions(-) create mode 100644 src/ai/regen_system.rs diff --git a/src/ai/energy_system.rs b/src/ai/energy_system.rs index 6b50bf9..0703aea 100644 --- a/src/ai/energy_system.rs +++ b/src/ai/energy_system.rs @@ -27,9 +27,13 @@ impl<'a> System<'a> for EnergySystem { if *runstate != RunState::Ticking { return; } - for (_entity, _clock, energy) in (&entities, &clock, &mut energies).join() { + // Clear TakingTurn{} from every entity. + turns.clear(); + // TURN COUNTER + for (entity, _clock, energy) in (&entities, &clock, &mut energies).join() { energy.current += NORMAL_SPEED; if energy.current >= TURN_COST { + turns.insert(entity, TakingTurn {}).expect("Unable to insert turn for turn counter."); energy.current -= TURN_COST; crate::gamelog::record_event("turns", 1); // Handle spawning mobs each turn @@ -38,8 +42,7 @@ impl<'a> System<'a> for EnergySystem { } } } - // Clear TakingTurn{} from every entity. - turns.clear(); + // EVERYTHING ELSE for (entity, energy, _pos) in (&entities, &mut energies, &positions).join() { // Every entity has a POTENTIAL equal to their speed. let mut energy_potential: i32 = energy.speed; diff --git a/src/ai/mod.rs b/src/ai/mod.rs index 6e480cf..b51dec3 100644 --- a/src/ai/mod.rs +++ b/src/ai/mod.rs @@ -4,3 +4,5 @@ mod turn_status_system; pub use turn_status_system::TurnStatusSystem; mod quip_system; pub use quip_system::QuipSystem; +mod regen_system; +pub use regen_system::RegenSystem; diff --git a/src/ai/regen_system.rs b/src/ai/regen_system.rs new file mode 100644 index 0000000..8e17e3d --- /dev/null +++ b/src/ai/regen_system.rs @@ -0,0 +1,61 @@ +use crate::{gamelog, Clock, Player, Pools, Position, RunState, TakingTurn}; +use specs::prelude::*; + +pub struct RegenSystem {} + +const MONSTER_HP_REGEN_TURN: i32 = 20; +const MONSTER_HP_REGEN_PER_TICK: i32 = 1; + +impl<'a> System<'a> for RegenSystem { + #[allow(clippy::type_complexity)] + type SystemData = ( + ReadStorage<'a, Clock>, + Entities<'a>, + ReadExpect<'a, RunState>, + ReadStorage<'a, Position>, + WriteStorage<'a, Pools>, + ReadStorage<'a, TakingTurn>, + ReadStorage<'a, Player>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (clock, entities, runstate, positions, mut pools, turns, player) = data; + if *runstate != RunState::Ticking { + return; + } + for (_e, _c, _t) in (&entities, &clock, &turns).join() { + let current_turn = gamelog::get_event_count("turns") + 1; + if current_turn % MONSTER_HP_REGEN_TURN == 0 { + for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, !&player).join() { + try_hp_regen_tick(pool, MONSTER_HP_REGEN_PER_TICK); + } + } + let level = gamelog::get_event_count("player_level"); + if current_turn % get_player_hp_regen_turn(level) == 0 { + for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, &player).join() { + try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level)); + } + } + } + } +} + +fn get_player_hp_regen_turn(level: i32) -> i32 { + if level < 10 { + return (42 / (level + 2)) + 1; + } else { + return 3; + } +} + +fn get_player_hp_regen_per_tick(level: i32) -> i32 { + if level < 10 { + return 1; + } else { + return 2; + } +} + +fn try_hp_regen_tick(pool: &mut Pools, amount: i32) { + pool.hit_points.current = i32::min(pool.hit_points.current + amount, pool.hit_points.max); +} diff --git a/src/camera.rs b/src/camera.rs index 1444d56..e5393ca 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -63,12 +63,17 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { if pos.x < max_x && pos.y < max_y && pos.x >= min_x && pos.y >= min_y { let mut draw = false; let mut fg = render.fg; - let (_glyph, _fg, bg) = crate::map::themes::get_tile_renderables_for_id(idx, &*map); + let mut bg = if render.bg == (RGB { r: 0.0, g: 0.0, b: 0.0 }) { + crate::map::themes::get_tile_renderables_for_id(idx, &*map).2 + } else { + render.bg + }; // Draw entities on visible tiles if map.visible_tiles[idx] { draw = true; } else { fg = fg.mul(0.75); + bg = bg.mul(0.75); } // Draw entities with minds within telepath range if map.telepath_tiles[idx] { diff --git a/src/damage_system.rs b/src/damage_system.rs index e81c556..90e33ae 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -73,6 +73,7 @@ impl<'a> System<'a> for DamageSystem { if next_level_requirement != -1 && player_stats.xp >= next_level_requirement { // We've gone up a level! player_stats.level += 1; + gamelog::record_event("player_level", 1); gamelog::Logger::new() .append("Welcome to experience level") .append(player_stats.level) diff --git a/src/main.rs b/src/main.rs index 264e95b..897616f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,8 +45,8 @@ extern crate lazy_static; //Consts pub const SHOW_MAPGEN: bool = false; -pub const LOG_SPAWNING: bool = true; -pub const LOG_TICKS: bool = true; +pub const LOG_SPAWNING: bool = false; +pub const LOG_TICKS: bool = false; #[derive(PartialEq, Copy, Clone)] pub enum RunState { @@ -132,6 +132,7 @@ impl State { let mut mapindex = MapIndexingSystem {}; let mut vis = VisibilitySystem {}; let mut energy = ai::EnergySystem {}; + let mut regen_system = ai::RegenSystem {}; let mut turn_status_system = ai::TurnStatusSystem {}; let mut quip_system = ai::QuipSystem {}; let mut mob = MonsterAI {}; @@ -148,6 +149,7 @@ impl State { mapindex.run_now(&self.ecs); vis.run_now(&self.ecs); + regen_system.run_now(&self.ecs); energy.run_now(&self.ecs); turn_status_system.run_now(&self.ecs); quip_system.run_now(&self.ecs); @@ -260,6 +262,7 @@ impl State { self.generate_world_map(1); gamelog::setup_log(); + gamelog::record_event("player_level", 1); } } @@ -614,6 +617,7 @@ fn main() -> rltk::BError { gs.ecs.insert(rex_assets::RexAssets::new()); gamelog::setup_log(); + gamelog::record_event("player_level", 1); gs.generate_world_map(1); rltk::main_loop(context, gs) diff --git a/src/player.rs b/src/player.rs index 5116f72..b46e4fd 100644 --- a/src/player.rs +++ b/src/player.rs @@ -539,7 +539,6 @@ fn skip_turn(ecs: &mut World) -> bool { } } - let mut did_heal = false; if can_heal { let mut health_components = ecs.write_storage::(); let pools = health_components.get_mut(*player_entity).unwrap(); @@ -547,15 +546,10 @@ fn skip_turn(ecs: &mut World) -> bool { let roll = rng.roll_dice(1, 6); if (roll == 6) && pools.hit_points.current < pools.hit_points.max { pools.hit_points.current += 1; - did_heal = true; } } - if did_heal { - gamelog::Logger::new().append("You wait a turn, and").colour(rltk::GREEN).append("recover a hit point.").log(); - } else { - gamelog::Logger::new().append("You wait a turn.").log(); - } + gamelog::Logger::new().append("You wait a turn.").log(); return true; } diff --git a/src/spawner.rs b/src/spawner.rs index 033bad8..63b8c1a 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -1,7 +1,7 @@ use super::{ - ai::NORMAL_SPEED, gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, Attributes, - Clock, Energy, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect, Renderable, SerializeMe, - Skill, Skills, TileType, Viewshed, + ai::NORMAL_SPEED, gamelog, gamesystem, gamesystem::attr_bonus, random_table::RandomTable, raws, Attribute, + Attributes, Clock, Energy, HungerClock, HungerState, Map, Name, Player, Pool, Pools, Position, Rect, Renderable, + SerializeMe, Skill, Skills, TileType, Viewshed, }; use rltk::{RandomNumberGenerator, RGB}; use specs::prelude::*;