Drop items

This commit is contained in:
Benjamyn Love 2022-11-20 16:10:11 +11:00
parent 458b90a184
commit 433d5c00f3
5 changed files with 116 additions and 2 deletions

View File

@ -1,4 +1,4 @@
use rltk::RGB;
use rltk::{RGB};
use specs::prelude::*;
use specs_derive::*;
@ -40,6 +40,7 @@ pub enum RunState {
PlayerTurn,
MonsterTurn,
ShowInventory,
ShowDropItem
}
#[derive(Component, Debug)]
@ -99,3 +100,7 @@ pub struct WantsToPickupItem {
pub struct WantsToDrinkPotion {
pub potion: Entity,
}
#[derive(Component, Debug, Clone)]
pub struct WantsToDropItem {
pub item : Entity
}

View File

@ -130,3 +130,48 @@ pub fn show_inventory(gs : &mut State, ctx : &mut Rltk) -> (ItemMenuResult, Opti
}
}
pub fn drop_item_menu(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), "Drop which item?");
ctx.print_color(18, y + count as i32 + 1, RGB::named(rltk::YELLOW), 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]));
}
(ItemMenuResult::NoResponse, None)
}
}
}
}
}

View File

@ -2,7 +2,7 @@ use specs::prelude::*;
use super::{
gamelog::GameLog, CombatStats, InBackpack, Name, Position, Potion, WantsToDrinkPotion,
WantsToPickupItem,
WantsToPickupItem,WantsToDropItem
};
pub struct ItemCollectionSystem {}
@ -91,3 +91,37 @@ impl<'a> System<'a> for PotionUseSystem {
wants_drink.clear();
}
}
pub struct ItemDropSystem {}
impl<'a> System<'a> for ItemDropSystem {
#[allow(clippy::type_complexity)]
type SystemData = ( ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>,
Entities<'a>,
WriteStorage<'a, WantsToDropItem>,
ReadStorage<'a, Name>,
WriteStorage<'a, Position>,
WriteStorage<'a, InBackpack>
);
fn run(&mut self, data : Self::SystemData) {
let (player_entity, mut gamelog, entities, mut wants_drop, names, mut positions, mut backpack) = data;
for (entity, to_drop) in (&entities, &wants_drop).join() {
let mut dropper_pos : Position = Position{x:0, y:0};
{
let dropped_pos = positions.get(entity).unwrap();
dropper_pos.x = dropped_pos.x;
dropper_pos.y = dropped_pos.y;
}
positions.insert(to_drop.item, Position{ x : dropper_pos.x, y : dropper_pos.y}).expect("Unable to insert position");
backpack.remove(to_drop.item);
if entity == *player_entity {
gamelog.entries.push(format!("You drop the {}", names.get(to_drop.item).unwrap().name));
}
}
wants_drop.clear();
}
}

View File

@ -58,6 +58,8 @@ impl State {
damage_system.run_now(&self.ecs);
let mut pickup = ItemCollectionSystem {};
pickup.run_now(&self.ecs);
let mut drop_items = ItemDropSystem{};
drop_items.run_now(&self.ecs);
let mut potions = PotionUseSystem {};
potions.run_now(&self.ecs);
self.ecs.maintain();
@ -128,6 +130,32 @@ impl GameState for State {
}
}
}
RunState::ShowDropItem => {
let result = gui::drop_item_menu(self, ctx);
match result.0 {
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
gui::ItemMenuResult::NoResponse => {},
gui::ItemMenuResult::Selected => {
let item_entity = result.1.unwrap();
let mut intent = self.ecs.write_storage::<WantsToDropItem>();
intent.insert(*self.ecs.fetch::<Entity>(), WantsToDropItem { item: item_entity }).expect("Unable to insert intent");
newrunstate = RunState::PlayerTurn;
}
}
}
RunState::ShowDropItem => {
let result = gui::drop_item_menu(self, ctx);
match result.0 {
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
gui::ItemMenuResult::NoResponse => {},
gui::ItemMenuResult::Selected => {
let item_entity = result.1.unwrap();
let mut intent = self.ecs.write_storage::<WantsToDropItem>();
intent.insert(*self.ecs.fetch::<Entity>(), WantsToDropItem { item: item_entity }).expect("Unable to insert intent");
newrunstate = RunState::PlayerTurn;
}
}
}
}
{
@ -160,6 +188,7 @@ fn main() -> rltk::BError {
gs.ecs.register::<Potion>();
gs.ecs.register::<InBackpack>();
gs.ecs.register::<WantsToPickupItem>();
gs.ecs.register::<WantsToDropItem>();
gs.ecs.register::<WantsToDrinkPotion>();
let map = Map::new_map_rooms_and_corridors();

View File

@ -86,6 +86,7 @@ pub fn player_input(gs: &mut State, ctx: &mut Rltk) -> RunState {
VirtualKeyCode::Numpad1 | VirtualKeyCode::B => {try_move_player(-1, 1, &mut gs.ecs)}
VirtualKeyCode::G => get_item(&mut gs.ecs),
VirtualKeyCode::I => return RunState::ShowInventory,
VirtualKeyCode::D => return RunState::ShowDropItem,
_ => return RunState::AwaitingInput,
},
}