From 9b9077fa018c7ed863603b25bd95f979fd7b19b6 Mon Sep 17 00:00:00 2001 From: Benjamyn Love Date: Mon, 14 Nov 2022 22:48:23 +1100 Subject: [PATCH] lappy sync --- src/components.rs | 1 + src/gui.rs | 55 +++++++++++++++++++++++++++++++++++++++-- src/inventory_system.rs | 30 ++++++++++++++++++++++ src/main.rs | 29 +++++++++++++++++++--- src/player.rs | 31 ++++++++++++++++++++--- 5 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 src/inventory_system.rs diff --git a/src/components.rs b/src/components.rs index c3f928f..f824eed 100644 --- a/src/components.rs +++ b/src/components.rs @@ -39,6 +39,7 @@ pub enum RunState { PreRun, PlayerTurn, MonsterTurn, + ShowInventory } #[derive(Component, Debug)] diff --git a/src/gui.rs b/src/gui.rs index fbd7040..7a1945f 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,6 +1,8 @@ -use rltk::{RGB, Rltk, Console, Point}; +use rltk::{RGB, Rltk, Point, VirtualKeyCode}; use specs::prelude::*; -use super::{CombatStats, Player, GameLog, Map, Name, Position}; +use crate::{InBackpack, player}; + +use super::{CombatStats, Player, GameLog, Map, Name, Position, State}; fn draw_tooltips(ecs: &World, ctx: &mut Rltk) { let map = ecs.fetch::(); @@ -78,4 +80,53 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { let mouse_pos = ctx.mouse_pos(); ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::MAGENTA)); draw_tooltips(ecs, ctx); +} + +#[derive(PartialEq, Copy, Clone)] +pub enum ItemMenuResult { Cancel, NoResponse, Selected } + +pub fn show_inventory(gs : &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Option) { + let player_entity = gs.ecs.fetch::(); + let names = gs.ecs.read_storage::(); + let backpack = gs.ecs.read_storage::(); + let entities = gs.ecs.entities(); + + + let inventory = (&backpack, &names).join().filter(|item| item.0.owner == *player_entity); + let count = inventory.count(); + + let mut y = (25 - (count / 2)) as i32; + ctx.draw_box(15, y - 2, 31, (count+3) as i32, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK)); + ctx.print_color(18, y - 2, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Inventory".to_string()); + ctx.print_color(18, y+count as i32 + 1, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Escape to cancel"); + + let mut equippable : Vec = Vec::new(); + let mut j = 0; + for (entity, _pack, name) in (&entities, &backpack, &names).join().filter(|item| item.1.owner == *player_entity) { + ctx.set(17, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), rltk::to_cp437('(')); + ctx.set(18, y, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), 97+j as rltk::FontCharType); + ctx.set(19, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), rltk::to_cp437(')')); + + ctx.print(21, y, &name.name.to_string()); + equippable.push(entity); + y += 1; + j += 1; + } + + match ctx.key { + None => (ItemMenuResult::NoResponse, None), + Some(key) => { + match key { + VirtualKeyCode::Escape => { (ItemMenuResult::Cancel, None) }, + _ => { + let selection = rltk::letter_to_option(key); + if selection > -1 && selection < count as i32 { + return (ItemMenuResult::Selected, Some(equippable[selection as usize])); + } + return (ItemMenuResult::NoResponse, None) + } + } + } + } + } \ No newline at end of file diff --git a/src/inventory_system.rs b/src/inventory_system.rs new file mode 100644 index 0000000..1d8fbdd --- /dev/null +++ b/src/inventory_system.rs @@ -0,0 +1,30 @@ +use specs::prelude::*; +use super::{WantsToPickupItem, Name, InBackpack, Position, gamelog::GameLog}; + +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> + ); + + 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"); + + if pickup.collected_by == *player_entity { + log.entries.push(format!("You pick up the {}.", names.get(pickup.item).unwrap().name)); + } + } + + wants_pickup.clear(); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 88f2ed2..5a29489 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,9 @@ pub use gamelog::*; mod spawner; use spawner::*; +mod inventory_system; +use inventory_system::*; + pub struct State { pub ecs: World, } @@ -53,6 +56,8 @@ impl State { melee_combat_system.run_now(&self.ecs); let mut damage_system = DamageSystem {}; damage_system.run_now(&self.ecs); + let mut pickup = ItemCollectionSystem{}; + pickup.run_now(&self.ecs); self.ecs.maintain(); } } @@ -60,6 +65,10 @@ 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 mut newrunstate; { let runstate = self.ecs.fetch::(); @@ -82,6 +91,20 @@ impl GameState for State { self.run_systems(); 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::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; + } + } + } } { @@ -89,9 +112,7 @@ impl GameState for State { *runwriter = newrunstate; } - 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::(); @@ -125,6 +146,8 @@ fn main() -> rltk::BError { gs.ecs.register::(); 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(); diff --git a/src/player.rs b/src/player.rs index 3f98a95..096a00b 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,6 +1,4 @@ -use crate::WantsToMelee; - -use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats}; +use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats, WantsToMelee, Item, GameLog, WantsToPickupItem}; use rltk::{Point, Rltk, VirtualKeyCode}; use specs::prelude::*; use std::cmp::{max, min}; @@ -37,6 +35,31 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) { } } +fn get_item(ecs: &mut World) { + let player_pos = ecs.fetch::(); + let player_entity = ecs.fetch::(); + let entities = ecs.entities(); + let items = ecs.read_storage::(); + let positions = ecs.read_storage::(); + let mut gamelog = ecs.fetch_mut::(); + + let mut target_item : Option = None; + for (item_entity, _item, position) in (&entities, &items, &positions).join() { + if position.x == player_pos.x && position.y == player_pos.y { + target_item = Some(item_entity); + } + } + + match target_item { + None => gamelog.entries.push("There is nothing to pick up.".to_string()), + Some(item) => { + let mut pickup = ecs.write_storage::(); + pickup.insert(*player_entity, WantsToPickupItem{ collected_by: *player_entity, item}).expect("Unable to insert want to pickup"); + } + } + +} + pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState { match ctx.key { None => return RunState::AwaitingInput, @@ -61,6 +84,8 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState { VirtualKeyCode::Numpad7 | VirtualKeyCode::U => {try_move_player(-1, -1, &mut gs.ecs)} VirtualKeyCode::Numpad3 | VirtualKeyCode::N => {try_move_player(1, 1, &mut gs.ecs)} VirtualKeyCode::Numpad1 | VirtualKeyCode::B => {try_move_player(-1, 1, &mut gs.ecs)} + VirtualKeyCode::G => get_item(&mut gs.ecs), + VirtualKeyCode::I => return RunState::ShowInventory, _ => return RunState::AwaitingInput, }, }