Add functionalty to identify items via a scroll

This commit is contained in:
Timothy Warren 2022-01-21 16:16:48 -05:00
parent 5b8d127af0
commit 66e58733f7
4 changed files with 128 additions and 3 deletions

View File

@ -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.

View File

@ -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 },

View File

@ -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)
}
},
}
}

View File

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