diff --git a/src/components.rs b/src/components.rs index f824eed..10116cf 100644 --- a/src/components.rs +++ b/src/components.rs @@ -39,7 +39,7 @@ pub enum RunState { PreRun, PlayerTurn, MonsterTurn, - ShowInventory + ShowInventory, } #[derive(Component, Debug)] @@ -95,5 +95,7 @@ pub struct WantsToPickupItem { pub item: Entity, } -// UPTO https://bfnightly.bracketproductions.com/chapter_9.html -// / Next, we'll put together a system to process WantsToPickupItem notices. We'll make a new file +#[derive(Component, Debug)] +pub struct WantsToDrinkPotion { + pub potion: Entity, +} diff --git a/src/inventory_system.rs b/src/inventory_system.rs index 1d8fbdd..5d06f0f 100644 --- a/src/inventory_system.rs +++ b/src/inventory_system.rs @@ -1,30 +1,93 @@ use specs::prelude::*; -use super::{WantsToPickupItem, Name, InBackpack, Position, gamelog::GameLog}; + +use super::{ + gamelog::GameLog, CombatStats, InBackpack, Name, Position, Potion, WantsToDrinkPotion, + WantsToPickupItem, +}; pub struct ItemCollectionSystem {} impl<'a> System<'a> for ItemCollectionSystem { #[allow(clippy::type_complexity)] - type SystemData = ( ReadExpect<'a, Entity>, - WriteExpect<'a, GameLog>, - WriteStorage<'a, WantsToPickupItem>, - WriteStorage<'a, Position>, - ReadStorage<'a, Name>, - WriteStorage<'a, InBackpack> - ); + type SystemData = ( + ReadExpect<'a, Entity>, + WriteExpect<'a, GameLog>, + WriteStorage<'a, WantsToPickupItem>, + WriteStorage<'a, Position>, + ReadStorage<'a, Name>, + WriteStorage<'a, InBackpack>, + ); - fn run (&mut self, data : Self::SystemData) { + fn run(&mut self, data: Self::SystemData) { let (player_entity, mut log, mut wants_pickup, mut positions, names, mut backpack) = data; for pickup in wants_pickup.join() { positions.remove(pickup.item); - backpack.insert(pickup.item, InBackpack{ owner: pickup.collected_by }).expect("Unable to insert item"); + backpack + .insert( + pickup.item, + InBackpack { + owner: pickup.collected_by, + }, + ) + .expect("Unable to insert item"); if pickup.collected_by == *player_entity { - log.entries.push(format!("You pick up the {}.", names.get(pickup.item).unwrap().name)); + log.entries.push(format!( + "You pick up the {}.", + names.get(pickup.item).unwrap().name + )); } } wants_pickup.clear(); } -} \ No newline at end of file +} + +pub struct PotionUseSystem {} + +impl<'a> System<'a> for PotionUseSystem { + #[allow(clippy::type_complexity)] + type SystemData = ( + ReadExpect<'a, Entity>, + WriteExpect<'a, GameLog>, + Entities<'a>, + WriteStorage<'a, WantsToDrinkPotion>, + ReadStorage<'a, Name>, + ReadStorage<'a, Potion>, + WriteStorage<'a, CombatStats>, + ); + + fn run(&mut self, data: Self::SystemData) { + let ( + player_entity, + mut gamelog, + entities, + mut wants_drink, + names, + potions, + mut combat_stats, + ) = data; + + for (entity, drink, stats) in (&entities, &wants_drink, &mut combat_stats).join() { + let potion = potions.get(drink.potion); + + match potion { + None => {} + Some(potion) => { + stats.hp = i32::min(stats.max_hp, stats.hp + potion.heal_amount); + gamelog.entries.push(format!("{}", stats.hp)); + if entity == *player_entity { + gamelog.entries.push(format!( + "You drink the {}, healing {} hp.", + names.get(drink.potion).unwrap().name, + potion.heal_amount + )); + entities.delete(drink.potion).expect("Delete failed") + } + } + } + } + wants_drink.clear(); + } +} diff --git a/src/main.rs b/src/main.rs index 5a29489..59a9486 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,8 +56,10 @@ impl State { melee_combat_system.run_now(&self.ecs); let mut damage_system = DamageSystem {}; damage_system.run_now(&self.ecs); - let mut pickup = ItemCollectionSystem{}; + let mut pickup = ItemCollectionSystem {}; pickup.run_now(&self.ecs); + let mut potions = PotionUseSystem {}; + potions.run_now(&self.ecs); self.ecs.maintain(); } } @@ -65,9 +67,21 @@ impl State { impl GameState for State { fn tick(&mut self, ctx: &mut Rltk) { ctx.cls(); - damage_system::delete_the_dead(&mut self.ecs); draw_map(&self.ecs, ctx); + { + let positions = self.ecs.read_storage::(); + let renderables = self.ecs.read_storage::(); + let map = self.ecs.fetch::(); + for (pos, render) in (&positions, &renderables).join() { + let idx = map.xy_idx(pos.x, pos.y); + if map.visible_tiles[idx] { + ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph) + } + } + + gui::draw_ui(&self.ecs, ctx); + } let mut newrunstate; { @@ -78,6 +92,7 @@ impl GameState for State { match newrunstate { RunState::PreRun => { self.run_systems(); + self.ecs.maintain(); newrunstate = RunState::AwaitingInput; } RunState::AwaitingInput => { @@ -85,23 +100,31 @@ impl GameState for State { } RunState::PlayerTurn => { self.run_systems(); + self.ecs.maintain(); newrunstate = RunState::MonsterTurn; } RunState::MonsterTurn => { self.run_systems(); + self.ecs.maintain(); newrunstate = RunState::AwaitingInput; } RunState::ShowInventory => { let result = gui::show_inventory(self, ctx); match result.0 { gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput, - gui::ItemMenuResult::NoResponse => {}, + gui::ItemMenuResult::NoResponse => {} gui::ItemMenuResult::Selected => { let item_entity = result.1.unwrap(); - let names = self.ecs.read_storage::(); - let mut gamelog = self.ecs.fetch_mut::(); - gamelog.entries.push(format!("You try to use {} but it isn't written yet", names.get(item_entity).unwrap().name)); - newrunstate = RunState::AwaitingInput; + let mut intent = self.ecs.write_storage::(); + intent + .insert( + *self.ecs.fetch::(), + WantsToDrinkPotion { + potion: item_entity, + }, + ) + .expect("Failed to insert intent"); + newrunstate = RunState::PlayerTurn; } } } @@ -112,18 +135,7 @@ impl GameState for State { *runwriter = newrunstate; } - - let positions = self.ecs.read_storage::(); - let renderables = self.ecs.read_storage::(); - let map = self.ecs.fetch::(); - - for (pos, render) in (&positions, &renderables).join() { - let idx = map.xy_idx(pos.x, pos.y); - if map.visible_tiles[idx] { - ctx.set(pos.x, pos.y, render.fg, render.bg, render.glyph) - } - } - gui::draw_ui(&self.ecs, ctx); + damage_system::delete_the_dead(&mut self.ecs); } } @@ -148,6 +160,7 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); let map = Map::new_map_rooms_and_corridors(); let (player_x, player_y) = map.rooms[0].center();