lappy sync

This commit is contained in:
Benjamyn Love 2022-11-14 22:48:23 +11:00
parent 95101b2c30
commit 9b9077fa01
5 changed files with 138 additions and 8 deletions

View File

@ -39,6 +39,7 @@ pub enum RunState {
PreRun, PreRun,
PlayerTurn, PlayerTurn,
MonsterTurn, MonsterTurn,
ShowInventory
} }
#[derive(Component, Debug)] #[derive(Component, Debug)]

View File

@ -1,6 +1,8 @@
use rltk::{RGB, Rltk, Console, Point}; use rltk::{RGB, Rltk, Point, VirtualKeyCode};
use specs::prelude::*; 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) { fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
let map = ecs.fetch::<Map>(); let map = ecs.fetch::<Map>();
@ -79,3 +81,52 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::MAGENTA)); ctx.set_bg(mouse_pos.0, mouse_pos.1, RGB::named(rltk::MAGENTA));
draw_tooltips(ecs, ctx); 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<Entity>) {
let player_entity = gs.ecs.fetch::<Entity>();
let names = gs.ecs.read_storage::<Name>();
let backpack = gs.ecs.read_storage::<InBackpack>();
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<Entity> = 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)
}
}
}
}
}

30
src/inventory_system.rs Normal file
View File

@ -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();
}
}

View File

@ -37,6 +37,9 @@ pub use gamelog::*;
mod spawner; mod spawner;
use spawner::*; use spawner::*;
mod inventory_system;
use inventory_system::*;
pub struct State { pub struct State {
pub ecs: World, pub ecs: World,
} }
@ -53,6 +56,8 @@ impl State {
melee_combat_system.run_now(&self.ecs); melee_combat_system.run_now(&self.ecs);
let mut damage_system = DamageSystem {}; let mut damage_system = DamageSystem {};
damage_system.run_now(&self.ecs); damage_system.run_now(&self.ecs);
let mut pickup = ItemCollectionSystem{};
pickup.run_now(&self.ecs);
self.ecs.maintain(); self.ecs.maintain();
} }
} }
@ -60,6 +65,10 @@ impl State {
impl GameState for State { impl GameState for State {
fn tick(&mut self, ctx: &mut Rltk) { fn tick(&mut self, ctx: &mut Rltk) {
ctx.cls(); ctx.cls();
damage_system::delete_the_dead(&mut self.ecs);
draw_map(&self.ecs, ctx);
let mut newrunstate; let mut newrunstate;
{ {
let runstate = self.ecs.fetch::<RunState>(); let runstate = self.ecs.fetch::<RunState>();
@ -82,6 +91,20 @@ impl GameState for State {
self.run_systems(); self.run_systems();
newrunstate = RunState::AwaitingInput; 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::<Name>();
let mut gamelog = self.ecs.fetch_mut::<gamelog::GameLog>();
gamelog.entries.push(format!("You try to use {} but it isn't written yet", names.get(item_entity).unwrap().name));
newrunstate = RunState::AwaitingInput;
}
}
}
} }
{ {
@ -89,8 +112,6 @@ impl GameState for State {
*runwriter = newrunstate; *runwriter = newrunstate;
} }
damage_system::delete_the_dead(&mut self.ecs);
draw_map(&self.ecs, ctx);
let positions = self.ecs.read_storage::<Position>(); let positions = self.ecs.read_storage::<Position>();
let renderables = self.ecs.read_storage::<Renderable>(); let renderables = self.ecs.read_storage::<Renderable>();
@ -125,6 +146,8 @@ fn main() -> rltk::BError {
gs.ecs.register::<SufferDamage>(); gs.ecs.register::<SufferDamage>();
gs.ecs.register::<Item>(); gs.ecs.register::<Item>();
gs.ecs.register::<Potion>(); gs.ecs.register::<Potion>();
gs.ecs.register::<InBackpack>();
gs.ecs.register::<WantsToPickupItem>();
let map = Map::new_map_rooms_and_corridors(); let map = Map::new_map_rooms_and_corridors();
let (player_x, player_y) = map.rooms[0].center(); let (player_x, player_y) = map.rooms[0].center();

View File

@ -1,6 +1,4 @@
use crate::WantsToMelee; use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats, WantsToMelee, Item, GameLog, WantsToPickupItem};
use super::{Map, Player, Position, RunState, State, Viewshed, CombatStats};
use rltk::{Point, Rltk, VirtualKeyCode}; use rltk::{Point, Rltk, VirtualKeyCode};
use specs::prelude::*; use specs::prelude::*;
use std::cmp::{max, min}; 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::<Point>();
let player_entity = ecs.fetch::<Entity>();
let entities = ecs.entities();
let items = ecs.read_storage::<Item>();
let positions = ecs.read_storage::<Position>();
let mut gamelog = ecs.fetch_mut::<GameLog>();
let mut target_item : Option<Entity> = 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::<WantsToPickupItem>();
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 { pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
match ctx.key { match ctx.key {
None => return RunState::AwaitingInput, 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::Numpad7 | VirtualKeyCode::U => {try_move_player(-1, -1, &mut gs.ecs)}
VirtualKeyCode::Numpad3 | VirtualKeyCode::N => {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::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, _ => return RunState::AwaitingInput,
}, },
} }