From 80c34a72b59af9d0d851b9299cf9a085684ae76f Mon Sep 17 00:00:00 2001 From: Llywelwyn Date: Mon, 14 Aug 2023 20:21:53 +0100 Subject: [PATCH] in-system name obfuscation (picking up, dropping items, etc.) --- src/ai/encumbrance_system.rs | 1 - src/gui/mod.rs | 43 ++++++++++++++++++++++++-- src/gui/tooltip.rs | 7 ++--- src/inventory_system.rs | 59 +++++++++++++++++++++++++++++------- src/player.rs | 12 ++++---- 5 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/ai/encumbrance_system.rs b/src/ai/encumbrance_system.rs index ea2d77a..ceb2815 100644 --- a/src/ai/encumbrance_system.rs +++ b/src/ai/encumbrance_system.rs @@ -1,5 +1,4 @@ use crate::{gamelog, Attributes, Burden, EquipmentChanged, Equipped, InBackpack, Item, Pools}; -use rltk::prelude::*; use specs::prelude::*; use std::collections::HashMap; diff --git a/src/gui/mod.rs b/src/gui/mod.rs index ca05dfd..e3b6b82 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,7 +1,7 @@ use super::{ ai::CARRY_CAPACITY_PER_STRENGTH, camera, gamelog, gamesystem, rex_assets::RexAssets, ArmourClassBonus, Attributes, - Burden, Equipped, Hidden, HungerClock, HungerState, InBackpack, MagicItem, Map, Name, ObfuscatedName, Player, - Point, Pools, Position, Prop, Renderable, RunState, Skill, Skills, State, Viewshed, + Burden, Equipped, Hidden, HungerClock, HungerState, InBackpack, MagicItem, Map, MasterDungeonMap, Name, + ObfuscatedName, Player, Point, Pools, Position, Prop, Renderable, RunState, Skill, Skills, State, Viewshed, Wand, }; use rltk::{Rltk, VirtualKeyCode, RGB}; use specs::prelude::*; @@ -365,6 +365,43 @@ pub fn get_max_inventory_width(inventory: &BTreeMap) - return width; } +// Inside the ECS +pub fn obfuscate_name( + item: Entity, + names: &ReadStorage, + magic_items: &ReadStorage, + obfuscated_names: &ReadStorage, + dm: &MasterDungeonMap, + wand: Option<&ReadStorage>, +) -> (String, String) { + let (mut singular, mut plural) = ("nameless item (bug)".to_string(), "nameless items (bug)".to_string()); + if let Some(name) = names.get(item) { + if magic_items.get(item).is_some() { + if dm.identified_items.contains(&name.name) { + (singular, plural) = (name.name.clone(), name.plural.clone()); + } else if let Some(obfuscated) = obfuscated_names.get(item) { + (singular, plural) = (obfuscated.name.clone(), obfuscated.plural.clone()); + } else { + (singular, plural) = ("unid magic item".to_string(), "unid magic items".to_string()); + } + } else { + (singular, plural) = (name.name.clone(), name.plural.clone()); + } + } + if wand.is_some() { + let wands = wand.unwrap(); + if let Some(wand) = wands.get(item) { + let used = wand.max_uses - wand.uses; + for _i in 0..used { + singular.push_str("*"); + plural.push_str("*"); + } + } + } + return (singular, plural); +} + +// Outside the ECS pub fn get_item_display_name(ecs: &World, item: Entity) -> (String, String) { let (mut singular, mut plural) = ("nameless item (bug)".to_string(), "nameless items (bug)".to_string()); if let Some(name) = ecs.read_storage::().get(item) { @@ -381,7 +418,7 @@ pub fn get_item_display_name(ecs: &World, item: Entity) -> (String, String) { (singular, plural) = (name.name.clone(), name.plural.clone()); } } - if let Some(wand) = ecs.read_storage::().get(item) { + if let Some(wand) = ecs.read_storage::().get(item) { let used = wand.max_uses - wand.uses; for _i in 0..used { singular.push_str("*"); diff --git a/src/gui/tooltip.rs b/src/gui/tooltip.rs index 37cee9d..6304e63 100644 --- a/src/gui/tooltip.rs +++ b/src/gui/tooltip.rs @@ -1,4 +1,4 @@ -use super::{camera::get_screen_bounds, Attributes, Hidden, Map, Name, Pools, Position, Renderable, Rltk, World, RGB}; +use super::{camera::get_screen_bounds, Attributes, Hidden, Map, Pools, Position, Renderable, Rltk, World, RGB}; use rltk::prelude::*; use specs::prelude::*; @@ -43,7 +43,6 @@ impl Tooltip { pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk) { let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx); let map = ecs.fetch::(); - let names = ecs.read_storage::(); let positions = ecs.read_storage::(); let renderables = ecs.read_storage::(); let hidden = ecs.read_storage::(); @@ -70,10 +69,10 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk) { } let mut tooltips: Vec = Vec::new(); - for (entity, name, position, renderable, _hidden) in (&entities, &names, &positions, &renderables, !&hidden).join() { + for (entity, position, renderable, _hidden) in (&entities, &positions, &renderables, !&hidden).join() { if position.x == mouse_pos_adjusted.0 && position.y == mouse_pos_adjusted.1 { let mut tip = Tooltip::new(); - tip.add(name.name.to_string(), renderable.fg); + tip.add(crate::gui::get_item_display_name(ecs, entity).0, renderable.fg); // Attributes let attr = attributes.get(entity); if let Some(a) = attr { diff --git a/src/inventory_system.rs b/src/inventory_system.rs index c415bdb..adb555d 100644 --- a/src/inventory_system.rs +++ b/src/inventory_system.rs @@ -1,9 +1,9 @@ use super::{ - gamelog, Confusion, Consumable, Cursed, Destructible, Digger, EquipmentChanged, Equippable, Equipped, HungerClock, - 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, + gamelog, gui::obfuscate_name, Confusion, Consumable, Cursed, Destructible, Digger, EquipmentChanged, Equippable, + Equipped, HungerClock, HungerState, IdentifiedItem, InBackpack, InflictsDamage, MagicItem, MagicMapper, Map, + MasterDungeonMap, Name, ObfuscatedName, 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::*; @@ -18,10 +18,25 @@ impl<'a> System<'a> for ItemCollectionSystem { ReadStorage<'a, Name>, WriteStorage<'a, InBackpack>, WriteStorage<'a, EquipmentChanged>, + ReadStorage<'a, MagicItem>, + ReadStorage<'a, ObfuscatedName>, + ReadExpect<'a, MasterDungeonMap>, + ReadStorage<'a, Wand>, ); fn run(&mut self, data: Self::SystemData) { - let (player_entity, mut wants_pickup, mut positions, names, mut backpack, mut equipment_changed) = data; + let ( + player_entity, + mut wants_pickup, + mut positions, + names, + mut backpack, + mut equipment_changed, + magic_items, + obfuscated_names, + dm, + wands, + ) = data; for pickup in wants_pickup.join() { positions.remove(pickup.item); @@ -33,7 +48,10 @@ impl<'a> System<'a> for ItemCollectionSystem { if pickup.collected_by == *player_entity { gamelog::Logger::new() .append("You pick up the") - .item_name_n(format!("{}", &names.get(pickup.item).unwrap().name)) + .item_name_n(format!( + "{}", + obfuscate_name(pickup.item, &names, &magic_items, &obfuscated_names, &dm, Some(&wands)).0 + )) .period() .log(); } @@ -48,7 +66,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>); +type NameComponents<'a> = (ReadStorage<'a, Name>, WriteStorage<'a, IdentifiedItem>); pub struct ItemUseSystem {} impl<'a> System<'a> for ItemUseSystem { @@ -89,7 +107,7 @@ impl<'a> System<'a> for ItemUseSystem { mut rng, entities, mut wants_to_use, - (mut names, mut identified_items), + (names, mut identified_items), mut consumables, mut wands, destructibles, @@ -461,10 +479,26 @@ impl<'a> System<'a> for ItemDropSystem { WriteStorage<'a, Position>, WriteStorage<'a, InBackpack>, WriteStorage<'a, EquipmentChanged>, + ReadStorage<'a, MagicItem>, + ReadStorage<'a, ObfuscatedName>, + ReadExpect<'a, MasterDungeonMap>, + ReadStorage<'a, Wand>, ); fn run(&mut self, data: Self::SystemData) { - let (player_entity, entities, mut wants_drop, names, mut positions, mut backpack, mut equipment_changed) = data; + let ( + player_entity, + entities, + mut wants_drop, + names, + mut positions, + mut backpack, + mut equipment_changed, + magic_items, + obfuscated_names, + dm, + wands, + ) = data; for (entity, to_drop) in (&entities, &wants_drop).join() { equipment_changed.insert(entity, EquipmentChanged {}).expect("Unable to insert EquipmentChanged."); @@ -482,7 +516,10 @@ impl<'a> System<'a> for ItemDropSystem { if entity == *player_entity { gamelog::Logger::new() .append("You drop the") - .item_name_n(format!("{}", &names.get(to_drop.item).unwrap().name)) + .item_name_n(format!( + "{}", + obfuscate_name(to_drop.item, &names, &magic_items, &obfuscated_names, &dm, Some(&wands)).0 + )) .period() .log(); } diff --git a/src/player.rs b/src/player.rs index da6b37a..085508a 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,7 +1,7 @@ use super::{ - gamelog, Attributes, BlocksTile, BlocksVisibility, Bystander, Door, EntityMoved, Hidden, HungerClock, HungerState, - Item, Map, Monster, Name, ParticleBuilder, Player, Pools, Position, Renderable, RunState, State, SufferDamage, - Telepath, TileType, Viewshed, WantsToMelee, WantsToPickupItem, + gamelog, gui::get_item_display_name, Attributes, BlocksTile, BlocksVisibility, Bystander, Door, EntityMoved, + Hidden, HungerClock, HungerState, Item, Map, Monster, Name, ParticleBuilder, Player, Pools, Position, Renderable, + RunState, State, SufferDamage, Telepath, TileType, Viewshed, WantsToMelee, WantsToPickupItem, }; use rltk::{Point, RandomNumberGenerator, Rltk, VirtualKeyCode}; use specs::prelude::*; @@ -351,9 +351,9 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) -> bool { for entity in map.tile_content[destination_idx].iter() { if let Some(_hidden) = hidden.get(*entity) { } else { - if let Some(name) = names.get(*entity) { - let item_name = &name.name; - item_names.push(item_name.to_string()); + if let Some(_) = names.get(*entity) { + let item_name = get_item_display_name(ecs, *entity).0; + item_names.push(item_name); some = true; } }