Add functionalty to identify items via a scroll
This commit is contained in:
parent
5b8d127af0
commit
66e58733f7
@ -1,8 +1,9 @@
|
||||
use crate::map::{Map, MasterDungeonMap};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use ::specs::prelude::*;
|
||||
use ::specs_derive::*;
|
||||
|
||||
use crate::map::{Map, MasterDungeonMap};
|
||||
|
||||
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
|
||||
// Entity.
|
||||
|
||||
|
@ -54,6 +54,7 @@ pub enum EffectType {
|
||||
}
|
||||
|
||||
/// Who, or what the effect should affect.
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone)]
|
||||
pub enum Targets {
|
||||
Single { target: Entity },
|
||||
|
109
src/gui/menu.rs
109
src/gui/menu.rs
@ -1,9 +1,9 @@
|
||||
use ::rltk::{Rltk, VirtualKeyCode, RGB};
|
||||
use ::rltk::{FontCharType, Rltk, VirtualKeyCode, RGB};
|
||||
use ::specs::prelude::*;
|
||||
|
||||
use super::enums::*;
|
||||
use super::{get_item_color, get_item_display_name};
|
||||
use crate::components::{CursedItem, Equipped, InBackpack, Item, Name, Vendor};
|
||||
use crate::components::{CursedItem, Equipped, InBackpack, Item, Name, ObfuscatedName, Vendor};
|
||||
use crate::rex_assets::RexAssets;
|
||||
use crate::{colors, MasterDungeonMap, RunState, State, VendorMode};
|
||||
|
||||
@ -707,3 +707,108 @@ pub fn remove_curse_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opt
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identify_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option<Entity>) {
|
||||
use ::rltk::to_cp437;
|
||||
|
||||
let player_entity = gs.ecs.fetch::<Entity>();
|
||||
let equipped = gs.ecs.read_storage::<Equipped>();
|
||||
let backpack = gs.ecs.read_storage::<InBackpack>();
|
||||
let entities = gs.ecs.entities();
|
||||
let items = gs.ecs.read_storage::<Item>();
|
||||
let names = gs.ecs.read_storage::<Name>();
|
||||
let dm = gs.ecs.fetch::<MasterDungeonMap>();
|
||||
let obfuscated = gs.ecs.read_storage::<ObfuscatedName>();
|
||||
|
||||
let build_cursed_iterator = || {
|
||||
(&entities, &items).join().filter(|(item_entity, _item)| {
|
||||
let mut keep = false;
|
||||
if let Some(bp) = backpack.get(*item_entity) {
|
||||
if bp.owner == *player_entity {
|
||||
if let Some(name) = names.get(*item_entity) {
|
||||
if obfuscated.get(*item_entity).is_some()
|
||||
&& !dm.identified_items.contains(&name.name)
|
||||
{
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It's equipped, so we know it's cursed
|
||||
if let Some(equip) = equipped.get(*item_entity) {
|
||||
if equip.owner == *player_entity {
|
||||
if let Some(name) = names.get(*item_entity) {
|
||||
if obfuscated.get(*item_entity).is_some()
|
||||
&& !dm.identified_items.contains(&name.name)
|
||||
{
|
||||
keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep
|
||||
})
|
||||
};
|
||||
|
||||
let count = build_cursed_iterator().count();
|
||||
|
||||
let mut y = (25 - (count / 2)) as i32;
|
||||
ctx.draw_box(
|
||||
15,
|
||||
y - 2,
|
||||
31,
|
||||
(count + 3) as i32,
|
||||
colors::WHITE,
|
||||
colors::BLACK,
|
||||
);
|
||||
ctx.print_color(
|
||||
18,
|
||||
y - 2,
|
||||
colors::YELLOW,
|
||||
colors::BLACK,
|
||||
"Identify Which Item?",
|
||||
);
|
||||
ctx.print_color(
|
||||
18,
|
||||
y + count as i32 + 1,
|
||||
colors::YELLOW,
|
||||
colors::BLACK,
|
||||
"ESCAPE to cancel",
|
||||
);
|
||||
|
||||
let mut equippable: Vec<Entity> = Vec::new();
|
||||
for (j, (entity, _item)) in build_cursed_iterator().enumerate() {
|
||||
ctx.set(17, y, colors::WHITE, colors::BLACK, to_cp437('('));
|
||||
ctx.set(18, y, colors::YELLOW, colors::BLACK, 97 + j as FontCharType);
|
||||
ctx.set(19, y, colors::WHITE, colors::BLACK, to_cp437(')'));
|
||||
|
||||
ctx.print_color(
|
||||
21,
|
||||
y,
|
||||
get_item_color(&gs.ecs, entity),
|
||||
colors::BLACK,
|
||||
&get_item_display_name(&gs.ecs, entity),
|
||||
);
|
||||
equippable.push(entity);
|
||||
y += 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)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
18
src/state.rs
18
src/state.rs
@ -54,6 +54,7 @@ pub enum RunState {
|
||||
ShowVendor { vendor: Entity, mode: VendorMode },
|
||||
TeleportingToOtherLevel { x: i32, y: i32, depth: i32 },
|
||||
ShowRemoveCurse,
|
||||
ShowIdentify,
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
@ -267,6 +268,7 @@ impl GameState for State {
|
||||
RunState::TeleportingToOtherLevel { x, y, depth }
|
||||
}
|
||||
RunState::ShowRemoveCurse => RunState::ShowRemoveCurse,
|
||||
RunState::ShowIdentify => RunState::ShowIdentify,
|
||||
_ => RunState::Ticking,
|
||||
};
|
||||
}
|
||||
@ -551,6 +553,22 @@ impl GameState for State {
|
||||
let item_entity = result.1.unwrap();
|
||||
self.ecs.write_storage::<CursedItem>().remove(item_entity);
|
||||
|
||||
newrunstate = RunState::Ticking;
|
||||
}
|
||||
}
|
||||
}
|
||||
RunState::ShowIdentify => {
|
||||
let result = gui::identify_menu(self, ctx);
|
||||
match result.0 {
|
||||
gui::ItemMenuResult::Cancel => newrunstate = RunState::AwaitingInput,
|
||||
gui::ItemMenuResult::NoResponse => {}
|
||||
gui::ItemMenuResult::Selected => {
|
||||
let item_entity = result.1.unwrap();
|
||||
if let Some(name) = self.ecs.read_storage::<Name>().get(item_entity) {
|
||||
let mut dm = self.ecs.fetch_mut::<MasterDungeonMap>();
|
||||
dm.identified_items.insert(name.name.clone());
|
||||
}
|
||||
|
||||
newrunstate = RunState::Ticking;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user