diff --git a/src/components.rs b/src/components.rs index c70a557..d229f14 100644 --- a/src/components.rs +++ b/src/components.rs @@ -228,6 +228,11 @@ pub struct ObfuscatedName { pub plural: String, } +#[derive(Component, Debug, Serialize, Deserialize, Clone)] +pub struct IdentifiedItem { + pub name: String, +} + #[derive(Component, Debug, Serialize, Deserialize, Clone)] pub struct EquipmentChanged {} diff --git a/src/gui/mod.rs b/src/gui/mod.rs index ebf88aa..3247912 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -185,6 +185,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { // Draw entities seen on screen let viewsheds = ecs.read_storage::(); let renderables = ecs.read_storage::(); + let names = ecs.read_storage::(); let hidden = ecs.read_storage::(); let props = ecs.read_storage::(); let map = ecs.fetch::(); @@ -193,7 +194,10 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { for tile in viewshed.visible_tiles.iter() { let idx = map.xy_idx(tile.x, tile.y); for entity in map.tile_content[idx].iter() { - let mut draw = true; + let mut draw = false; + if let Some(_) = names.get(*entity) { + draw = true; + } let prop = props.get(*entity); if let Some(_) = prop { draw = false; diff --git a/src/inventory_system.rs b/src/inventory_system.rs index 1d34fc6..88e378d 100644 --- a/src/inventory_system.rs +++ b/src/inventory_system.rs @@ -1,8 +1,8 @@ use super::{ gamelog, Confusion, Consumable, Cursed, Destructible, Digger, EquipmentChanged, Equippable, Equipped, HungerClock, - HungerState, InBackpack, InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Pools, Position, - ProvidesHealing, ProvidesNutrition, RandomNumberGenerator, RunState, SufferDamage, TileType, Viewshed, Wand, - WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME, + HungerState, IdentifiedItem, InBackpack, InflictsDamage, MagicMapper, Map, Name, ParticleBuilder, Point, Pools, + Position, ProvidesHealing, ProvidesNutrition, RandomNumberGenerator, RunState, SufferDamage, TileType, Viewshed, + Wand, WantsToDropItem, WantsToPickupItem, WantsToRemoveItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME, }; use specs::prelude::*; @@ -48,6 +48,7 @@ impl<'a> System<'a> for ItemCollectionSystem { // systems. type EquipComponents<'a> = (ReadStorage<'a, Equippable>, WriteStorage<'a, Equipped>, WriteStorage<'a, EquipmentChanged>); +type NameComponents<'a> = (WriteStorage<'a, Name>, WriteStorage<'a, IdentifiedItem>); pub struct ItemUseSystem {} impl<'a> System<'a> for ItemUseSystem { @@ -58,7 +59,7 @@ impl<'a> System<'a> for ItemUseSystem { WriteExpect<'a, RandomNumberGenerator>, Entities<'a>, WriteStorage<'a, WantsToUseItem>, - WriteStorage<'a, Name>, + NameComponents<'a>, WriteStorage<'a, Consumable>, WriteStorage<'a, Wand>, ReadStorage<'a, Destructible>, @@ -88,7 +89,7 @@ impl<'a> System<'a> for ItemUseSystem { mut rng, entities, mut wants_to_use, - mut names, + (mut names, mut identified_items), mut consumables, mut wands, destructibles, @@ -393,6 +394,12 @@ impl<'a> System<'a> for ItemUseSystem { // ITEM DELETION AFTER USE if used_item { + // Identify + if entity == *player_entity { + identified_items + .insert(entity, IdentifiedItem { name: item_being_used.name.clone() }) + .expect("Unable to insert"); + } let consumable = consumables.get(wants_to_use.item); match consumable { None => {} @@ -411,6 +418,39 @@ impl<'a> System<'a> for ItemUseSystem { } } +pub struct ItemIdentificationSystem {} + +impl<'a> System<'a> for ItemIdentificationSystem { + #[allow(clippy::type_complexity)] + type SystemData = ( + ReadStorage<'a, crate::components::Player>, + WriteStorage<'a, IdentifiedItem>, + WriteExpect<'a, crate::map::MasterDungeonMap>, + ReadStorage<'a, crate::Item>, + ReadStorage<'a, Name>, + WriteStorage<'a, crate::ObfuscatedName>, + Entities<'a>, + ); + + fn run(&mut self, data: Self::SystemData) { + let (player, mut identified, mut dm, items, names, mut obfuscated_names, entities) = data; + for (_p, id) in (&player, &identified).join() { + let tag = crate::raws::get_id_from_name(id.name.clone()); + if !dm.identified_items.contains(&id.name) && crate::raws::is_tag_magic(&tag) { + dm.identified_items.insert(id.name.clone()); + + for (entity, _item, name) in (&entities, &items, &names).join() { + if name.name == id.name { + obfuscated_names.remove(entity); + } + } + } + } + // Clean up + identified.clear(); + } +} + pub struct ItemDropSystem {} impl<'a> System<'a> for ItemDropSystem { diff --git a/src/main.rs b/src/main.rs index 28f251c..f76df06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -108,6 +108,7 @@ impl State { let mut item_use_system = ItemUseSystem {}; let mut item_drop_system = ItemDropSystem {}; let mut item_remove_system = ItemRemoveSystem {}; + let mut item_id_system = ItemIdentificationSystem {}; let mut hunger_clock = hunger_system::HungerSystem {}; let mut particle_system = particle_system::ParticleSpawnSystem {}; @@ -125,6 +126,7 @@ impl State { item_use_system.run_now(&self.ecs); item_drop_system.run_now(&self.ecs); item_remove_system.run_now(&self.ecs); + item_id_system.run_now(&self.ecs); melee_system.run_now(&self.ecs); damage_system.run_now(&self.ecs); hunger_clock.run_now(&self.ecs); @@ -537,6 +539,7 @@ fn main() -> rltk::BError { gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); + gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); gs.ecs.register::(); diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index 7e6362f..8ec3f33 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -111,7 +111,10 @@ pub fn spawn_named_entity( pub fn spawn_named_item(raws: &RawMaster, ecs: &mut World, key: &str, pos: SpawnType) -> Option { if raws.item_index.contains_key(key) { let item_template = &raws.raws.items[raws.item_index[key]]; - let scroll_names = ecs.fetch::().scroll_map.clone(); + let dm = ecs.fetch::(); + let scroll_names = dm.scroll_map.clone(); + let identified_items = dm.identified_items.clone(); + std::mem::drop(dm); let mut eb = ecs.create_entity().marked::>(); eb = eb.with(Name { name: item_template.name.name.clone(), plural: item_template.name.plural.clone() }); @@ -178,15 +181,17 @@ pub fn spawn_named_item(raws: &RawMaster, ecs: &mut World, key: &str, pos: Spawn }; eb = eb.with(MagicItem { class: item_class }); - #[allow(clippy::single_match)] - match magic_item.naming.as_str() { - "scroll" => { - eb = eb.with(ObfuscatedName { - name: scroll_names[&item_template.name.name].0.clone(), - plural: scroll_names[&item_template.name.name].1.clone(), - }) + if !identified_items.contains(&item_template.name.name) { + #[allow(clippy::single_match)] + match magic_item.naming.as_str() { + "scroll" => { + eb = eb.with(ObfuscatedName { + name: scroll_names[&item_template.name.name].0.clone(), + plural: scroll_names[&item_template.name.name].1.clone(), + }) + } + _ => {} } - _ => {} } } @@ -655,3 +660,23 @@ pub fn get_scroll_tags() -> Vec { } return result; } + +pub fn get_id_from_name(name: String) -> String { + let raws = &super::RAWS.lock().unwrap(); + for item in &raws.raws.items { + if item.name.name == name { + return item.id.clone(); + } + } + return "null".to_string(); +} + +pub fn is_tag_magic(tag: &str) -> bool { + let raws = &super::RAWS.lock().unwrap(); + if raws.item_index.contains_key(tag) { + let item_template = &raws.raws.items[raws.item_index[tag]]; + return item_template.magic.is_some(); + } else { + return false; + } +} diff --git a/src/saveload_system.rs b/src/saveload_system.rs index e452689..a0506f0 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -73,6 +73,7 @@ pub fn save_game(ecs: &mut World) { GrantsXP, Hidden, HungerClock, + IdentifiedItem, InBackpack, InflictsDamage, Item, @@ -187,6 +188,7 @@ pub fn load_game(ecs: &mut World) { GrantsXP, Hidden, HungerClock, + IdentifiedItem, InBackpack, InflictsDamage, Item, diff --git a/src/spawner.rs b/src/spawner.rs index 8bbf765..e71ead0 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -72,8 +72,22 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity { raws::spawn_named_entity( &raws::RAWS.lock().unwrap(), ecs, - "equip_dagger", - raws::SpawnType::Equipped { by: player }, + "scroll_fireball", + raws::SpawnType::Carried { by: player }, + 0, + ); + raws::spawn_named_entity( + &raws::RAWS.lock().unwrap(), + ecs, + "scroll_fireball", + raws::SpawnType::Carried { by: player }, + 0, + ); + raws::spawn_named_entity( + &raws::RAWS.lock().unwrap(), + ecs, + "scroll_fireball", + raws::SpawnType::Carried { by: player }, 0, ); raws::spawn_named_entity(