Implement obfuscated names for magic scrolls
This commit is contained in:
parent
ec0f13dcdd
commit
dd8a3b4f6f
@ -379,6 +379,11 @@ pub struct MagicItem {
|
||||
pub class: MagicItemClass,
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ObfuscatedName {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
|
||||
// Entity.
|
||||
|
||||
|
47
src/gui.rs
47
src/gui.rs
@ -9,7 +9,10 @@ use crate::components::{
|
||||
};
|
||||
use crate::game_log::GameLog;
|
||||
use crate::rex_assets::RexAssets;
|
||||
use crate::{camera, colors, Equipped, Hidden, MagicItem, Map, RunState, State, VendorMode};
|
||||
use crate::{
|
||||
camera, colors, Equipped, Hidden, MagicItem, Map, MasterDungeonMap, ObfuscatedName, RunState,
|
||||
State, VendorMode,
|
||||
};
|
||||
|
||||
pub fn get_item_color(ecs: &World, item: Entity) -> RGB {
|
||||
if let Some(magic) = ecs.read_storage::<MagicItem>().get(item) {
|
||||
@ -23,6 +26,25 @@ pub fn get_item_color(ecs: &World, item: Entity) -> RGB {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item_display_name(ecs: &World, item: Entity) -> String {
|
||||
if let Some(name) = ecs.read_storage::<Name>().get(item) {
|
||||
if ecs.read_storage::<MagicItem>().get(item).is_some() {
|
||||
let dm = ecs.fetch::<MasterDungeonMap>();
|
||||
if dm.identified_items.contains(&name.name) {
|
||||
name.name.clone()
|
||||
} else if let Some(obfuscated) = ecs.read_storage::<ObfuscatedName>().get(item) {
|
||||
obfuscated.name.clone()
|
||||
} else {
|
||||
"Unidentified magic item".to_string()
|
||||
}
|
||||
} else {
|
||||
name.name.clone()
|
||||
}
|
||||
} else {
|
||||
"Nameless item (bug)".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_hollow_box(
|
||||
console: &mut Rltk,
|
||||
sx: i32,
|
||||
@ -166,15 +188,14 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||
let mut y = 13;
|
||||
let entities = ecs.entities();
|
||||
let equipped = ecs.read_storage::<Equipped>();
|
||||
let name = ecs.read_storage::<Name>();
|
||||
for (entity, equipped_by, item_name) in (&entities, &equipped, &name).join() {
|
||||
for (entity, equipped_by) in (&entities, &equipped).join() {
|
||||
if equipped_by.owner == *player_entity {
|
||||
ctx.print_color(
|
||||
50,
|
||||
y,
|
||||
get_item_color(ecs, entity),
|
||||
colors::BLACK,
|
||||
&item_name.name,
|
||||
&get_item_display_name(ecs, entity),
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
@ -185,9 +206,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||
let consumables = ecs.read_storage::<Consumable>();
|
||||
let backpack = ecs.read_storage::<InBackpack>();
|
||||
let mut index = 1;
|
||||
for (entity, carried_by, _consumable, item_name) in
|
||||
(&entities, &backpack, &consumables, &name).join()
|
||||
{
|
||||
for (entity, carried_by, _consumable) in (&entities, &backpack, &consumables).join() {
|
||||
if carried_by.owner == *player_entity && index < 10 {
|
||||
ctx.print_color(50, y, colors::YELLOW, colors::BLACK, &format!("↑{}", index));
|
||||
ctx.print_color(
|
||||
@ -195,7 +214,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
||||
y,
|
||||
get_item_color(ecs, entity),
|
||||
colors::BLACK,
|
||||
&item_name.name,
|
||||
&get_item_display_name(ecs, entity),
|
||||
);
|
||||
y += 1;
|
||||
index += 1;
|
||||
@ -452,7 +471,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||
let mut equippable: Vec<Entity> = Vec::new();
|
||||
let mut j = 0;
|
||||
#[allow(clippy::explicit_counter_loop)]
|
||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
||||
for (entity, _pack) in (&entities, &backpack)
|
||||
.join()
|
||||
.filter(|item| item.1.owner == *player_entity)
|
||||
{
|
||||
@ -471,7 +490,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||
y,
|
||||
get_item_color(&gs.ecs, entity),
|
||||
colors::BLACK,
|
||||
&name.name.to_string(),
|
||||
&get_item_display_name(&gs.ecs, entity),
|
||||
);
|
||||
equippable.push(entity);
|
||||
y += 1;
|
||||
@ -528,7 +547,7 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||
let mut equippable: Vec<Entity> = Vec::new();
|
||||
let mut j = 0;
|
||||
#[allow(clippy::explicit_counter_loop)]
|
||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
||||
for (entity, _pack) in (&entities, &backpack)
|
||||
.join()
|
||||
.filter(|item| item.1.owner == *player_entity)
|
||||
{
|
||||
@ -547,7 +566,7 @@ pub fn drop_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
||||
y,
|
||||
get_item_color(&gs.ecs, entity),
|
||||
colors::BLACK,
|
||||
&name.name.to_string(),
|
||||
&get_item_display_name(&gs.ecs, entity),
|
||||
);
|
||||
equippable.push(entity);
|
||||
y += 1;
|
||||
@ -610,7 +629,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||
let mut equippable: Vec<Entity> = Vec::new();
|
||||
let mut j = 0;
|
||||
#[allow(clippy::explicit_counter_loop)]
|
||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
||||
for (entity, _pack) in (&entities, &backpack)
|
||||
.join()
|
||||
.filter(|item| item.1.owner == *player_entity)
|
||||
{
|
||||
@ -629,7 +648,7 @@ pub fn remove_item_menu(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Opti
|
||||
y,
|
||||
get_item_color(&gs.ecs, entity),
|
||||
colors::BLACK,
|
||||
&name.name.to_string(),
|
||||
&get_item_display_name(&gs.ecs, entity),
|
||||
);
|
||||
|
||||
equippable.push(entity);
|
||||
|
@ -91,6 +91,7 @@ fn main() -> ::rltk::BError {
|
||||
MyTurn,
|
||||
Name,
|
||||
NaturalAttackDefense,
|
||||
ObfuscatedName,
|
||||
OtherLevelPosition,
|
||||
ParticleLifetime,
|
||||
Player,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use ::rltk::{Point, RandomNumberGenerator};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
@ -11,13 +11,26 @@ use crate::map_builders::level_builder;
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
pub struct MasterDungeonMap {
|
||||
maps: HashMap<i32, Map>,
|
||||
pub identified_items: HashSet<String>,
|
||||
pub scroll_mappings: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl MasterDungeonMap {
|
||||
pub fn new() -> MasterDungeonMap {
|
||||
MasterDungeonMap {
|
||||
let mut dm = MasterDungeonMap {
|
||||
maps: HashMap::new(),
|
||||
identified_items: HashSet::new(),
|
||||
scroll_mappings: HashMap::new(),
|
||||
};
|
||||
|
||||
let mut rng = RandomNumberGenerator::new();
|
||||
for scroll_tag in crate::raws::get_scroll_tags().iter() {
|
||||
let masked_name = make_scroll_name(&mut rng);
|
||||
dm.scroll_mappings
|
||||
.insert(scroll_tag.to_string(), masked_name);
|
||||
}
|
||||
|
||||
dm
|
||||
}
|
||||
|
||||
pub fn store_map(&mut self, map: &Map) {
|
||||
@ -33,6 +46,49 @@ impl MasterDungeonMap {
|
||||
}
|
||||
}
|
||||
|
||||
fn make_scroll_name(rng: &mut rltk::RandomNumberGenerator) -> String {
|
||||
let length = 4 + rng.roll_dice(1, 4);
|
||||
let mut name = "Scroll of ".to_string();
|
||||
|
||||
for i in 0..length {
|
||||
if i % 2 == 0 {
|
||||
name += match rng.roll_dice(1, 5) {
|
||||
1 => "a",
|
||||
2 => "e",
|
||||
3 => "i",
|
||||
4 => "o",
|
||||
_ => "u",
|
||||
}
|
||||
} else {
|
||||
name += match rng.roll_dice(1, 21) {
|
||||
1 => "b",
|
||||
2 => "c",
|
||||
3 => "d",
|
||||
4 => "f",
|
||||
5 => "g",
|
||||
6 => "h",
|
||||
7 => "j",
|
||||
8 => "k",
|
||||
9 => "l",
|
||||
10 => "m",
|
||||
11 => "n",
|
||||
12 => "p",
|
||||
13 => "q",
|
||||
14 => "r",
|
||||
15 => "s",
|
||||
16 => "t",
|
||||
17 => "v",
|
||||
18 => "w",
|
||||
19 => "x",
|
||||
20 => "y",
|
||||
_ => "z",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
name
|
||||
}
|
||||
|
||||
pub fn level_transition(ecs: &mut World, new_depth: i32, offset: i32) -> Option<Vec<Map>> {
|
||||
// Obtain the master dungeon map
|
||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||
|
@ -46,4 +46,5 @@ pub struct Wearable {
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct MagicItem {
|
||||
pub class: String,
|
||||
pub naming: String,
|
||||
}
|
||||
|
@ -7,8 +7,9 @@ use ::specs::saveload::{MarkedBuilder, SimpleMarker};
|
||||
|
||||
use crate::components::*;
|
||||
use crate::gamesystem::{mana_at_level, npc_hp};
|
||||
use crate::map::MasterDungeonMap;
|
||||
use crate::random_table::RandomTable;
|
||||
use crate::raws::{Raws, Reaction};
|
||||
use crate::raws::{Raws, Reaction, RAWS};
|
||||
|
||||
pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
|
||||
lazy_static! {
|
||||
@ -180,6 +181,21 @@ pub fn get_vendor_items(categories: &[String], raws: &RawMaster) -> Vec<(String,
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_scroll_tags() -> Vec<String> {
|
||||
let raws = &RAWS.lock().unwrap();
|
||||
let mut result = Vec::new();
|
||||
|
||||
for item in raws.raws.items.iter() {
|
||||
if let Some(magic) = &item.magic {
|
||||
if &magic.naming == "scroll" {
|
||||
result.push(item.name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn spawn_position<'a>(
|
||||
pos: SpawnType,
|
||||
new_entity: EntityBuilder<'a>,
|
||||
@ -235,7 +251,7 @@ pub fn spawn_named_item(
|
||||
) -> Option<Entity> {
|
||||
if raws.item_index.contains_key(key) {
|
||||
let item_template = &raws.raws.items[raws.item_index[key]];
|
||||
|
||||
let scroll_names = ecs.fetch::<MasterDungeonMap>().scroll_mappings.clone();
|
||||
let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
||||
|
||||
// Spawn in the specified location
|
||||
@ -333,7 +349,17 @@ pub fn spawn_named_item(
|
||||
"legendary" => MagicItemClass::Legendary,
|
||||
_ => MagicItemClass::Common,
|
||||
};
|
||||
eb = eb.with(MagicItem { class })
|
||||
eb = eb.with(MagicItem { class });
|
||||
|
||||
#[allow(clippy::single_match)]
|
||||
match magic.naming.as_str() {
|
||||
"scroll" => {
|
||||
eb = eb.with(ObfuscatedName {
|
||||
name: scroll_names[&item_template.name].clone(),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
return Some(eb.build());
|
||||
|
@ -93,6 +93,7 @@ pub fn save_game(ecs: &mut World) {
|
||||
MyTurn,
|
||||
Name,
|
||||
NaturalAttackDefense,
|
||||
ObfuscatedName,
|
||||
OtherLevelPosition,
|
||||
ParticleLifetime,
|
||||
Player,
|
||||
@ -207,6 +208,7 @@ pub fn load_game(ecs: &mut World) {
|
||||
MyTurn,
|
||||
Name,
|
||||
NaturalAttackDefense,
|
||||
ObfuscatedName,
|
||||
OtherLevelPosition,
|
||||
ParticleLifetime,
|
||||
Player,
|
||||
|
@ -95,12 +95,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
||||
"Old Boots",
|
||||
SpawnType::Equipped { by: player },
|
||||
);
|
||||
spawn_named_entity(
|
||||
&RAWS.lock().unwrap(),
|
||||
ecs,
|
||||
"Town Portal Scroll",
|
||||
SpawnType::Carried { by: player },
|
||||
);
|
||||
|
||||
player
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user