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,
|
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
|
// Serialization helper code. We need to implement ConvertSaveLoad for each type that contains an
|
||||||
// Entity.
|
// Entity.
|
||||||
|
|
||||||
|
47
src/gui.rs
47
src/gui.rs
@ -9,7 +9,10 @@ use crate::components::{
|
|||||||
};
|
};
|
||||||
use crate::game_log::GameLog;
|
use crate::game_log::GameLog;
|
||||||
use crate::rex_assets::RexAssets;
|
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 {
|
pub fn get_item_color(ecs: &World, item: Entity) -> RGB {
|
||||||
if let Some(magic) = ecs.read_storage::<MagicItem>().get(item) {
|
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(
|
pub fn draw_hollow_box(
|
||||||
console: &mut Rltk,
|
console: &mut Rltk,
|
||||||
sx: i32,
|
sx: i32,
|
||||||
@ -166,15 +188,14 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||||||
let mut y = 13;
|
let mut y = 13;
|
||||||
let entities = ecs.entities();
|
let entities = ecs.entities();
|
||||||
let equipped = ecs.read_storage::<Equipped>();
|
let equipped = ecs.read_storage::<Equipped>();
|
||||||
let name = ecs.read_storage::<Name>();
|
for (entity, equipped_by) in (&entities, &equipped).join() {
|
||||||
for (entity, equipped_by, item_name) in (&entities, &equipped, &name).join() {
|
|
||||||
if equipped_by.owner == *player_entity {
|
if equipped_by.owner == *player_entity {
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
50,
|
50,
|
||||||
y,
|
y,
|
||||||
get_item_color(ecs, entity),
|
get_item_color(ecs, entity),
|
||||||
colors::BLACK,
|
colors::BLACK,
|
||||||
&item_name.name,
|
&get_item_display_name(ecs, entity),
|
||||||
);
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
@ -185,9 +206,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||||||
let consumables = ecs.read_storage::<Consumable>();
|
let consumables = ecs.read_storage::<Consumable>();
|
||||||
let backpack = ecs.read_storage::<InBackpack>();
|
let backpack = ecs.read_storage::<InBackpack>();
|
||||||
let mut index = 1;
|
let mut index = 1;
|
||||||
for (entity, carried_by, _consumable, item_name) in
|
for (entity, carried_by, _consumable) in (&entities, &backpack, &consumables).join() {
|
||||||
(&entities, &backpack, &consumables, &name).join()
|
|
||||||
{
|
|
||||||
if carried_by.owner == *player_entity && index < 10 {
|
if carried_by.owner == *player_entity && index < 10 {
|
||||||
ctx.print_color(50, y, colors::YELLOW, colors::BLACK, &format!("↑{}", index));
|
ctx.print_color(50, y, colors::YELLOW, colors::BLACK, &format!("↑{}", index));
|
||||||
ctx.print_color(
|
ctx.print_color(
|
||||||
@ -195,7 +214,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
|
|||||||
y,
|
y,
|
||||||
get_item_color(ecs, entity),
|
get_item_color(ecs, entity),
|
||||||
colors::BLACK,
|
colors::BLACK,
|
||||||
&item_name.name,
|
&get_item_display_name(ecs, entity),
|
||||||
);
|
);
|
||||||
y += 1;
|
y += 1;
|
||||||
index += 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 equippable: Vec<Entity> = Vec::new();
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
#[allow(clippy::explicit_counter_loop)]
|
#[allow(clippy::explicit_counter_loop)]
|
||||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
for (entity, _pack) in (&entities, &backpack)
|
||||||
.join()
|
.join()
|
||||||
.filter(|item| item.1.owner == *player_entity)
|
.filter(|item| item.1.owner == *player_entity)
|
||||||
{
|
{
|
||||||
@ -471,7 +490,7 @@ pub fn show_inventory(gs: &mut State, ctx: &mut Rltk) -> (ItemMenuResult, Option
|
|||||||
y,
|
y,
|
||||||
get_item_color(&gs.ecs, entity),
|
get_item_color(&gs.ecs, entity),
|
||||||
colors::BLACK,
|
colors::BLACK,
|
||||||
&name.name.to_string(),
|
&get_item_display_name(&gs.ecs, entity),
|
||||||
);
|
);
|
||||||
equippable.push(entity);
|
equippable.push(entity);
|
||||||
y += 1;
|
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 equippable: Vec<Entity> = Vec::new();
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
#[allow(clippy::explicit_counter_loop)]
|
#[allow(clippy::explicit_counter_loop)]
|
||||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
for (entity, _pack) in (&entities, &backpack)
|
||||||
.join()
|
.join()
|
||||||
.filter(|item| item.1.owner == *player_entity)
|
.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,
|
y,
|
||||||
get_item_color(&gs.ecs, entity),
|
get_item_color(&gs.ecs, entity),
|
||||||
colors::BLACK,
|
colors::BLACK,
|
||||||
&name.name.to_string(),
|
&get_item_display_name(&gs.ecs, entity),
|
||||||
);
|
);
|
||||||
equippable.push(entity);
|
equippable.push(entity);
|
||||||
y += 1;
|
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 equippable: Vec<Entity> = Vec::new();
|
||||||
let mut j = 0;
|
let mut j = 0;
|
||||||
#[allow(clippy::explicit_counter_loop)]
|
#[allow(clippy::explicit_counter_loop)]
|
||||||
for (entity, _pack, name) in (&entities, &backpack, &names)
|
for (entity, _pack) in (&entities, &backpack)
|
||||||
.join()
|
.join()
|
||||||
.filter(|item| item.1.owner == *player_entity)
|
.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,
|
y,
|
||||||
get_item_color(&gs.ecs, entity),
|
get_item_color(&gs.ecs, entity),
|
||||||
colors::BLACK,
|
colors::BLACK,
|
||||||
&name.name.to_string(),
|
&get_item_display_name(&gs.ecs, entity),
|
||||||
);
|
);
|
||||||
|
|
||||||
equippable.push(entity);
|
equippable.push(entity);
|
||||||
|
@ -91,6 +91,7 @@ fn main() -> ::rltk::BError {
|
|||||||
MyTurn,
|
MyTurn,
|
||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
|
ObfuscatedName,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use ::rltk::{Point, RandomNumberGenerator};
|
use ::rltk::{Point, RandomNumberGenerator};
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
@ -11,13 +11,26 @@ use crate::map_builders::level_builder;
|
|||||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct MasterDungeonMap {
|
pub struct MasterDungeonMap {
|
||||||
maps: HashMap<i32, Map>,
|
maps: HashMap<i32, Map>,
|
||||||
|
pub identified_items: HashSet<String>,
|
||||||
|
pub scroll_mappings: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MasterDungeonMap {
|
impl MasterDungeonMap {
|
||||||
pub fn new() -> MasterDungeonMap {
|
pub fn new() -> MasterDungeonMap {
|
||||||
MasterDungeonMap {
|
let mut dm = MasterDungeonMap {
|
||||||
maps: HashMap::new(),
|
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) {
|
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>> {
|
pub fn level_transition(ecs: &mut World, new_depth: i32, offset: i32) -> Option<Vec<Map>> {
|
||||||
// Obtain the master dungeon map
|
// Obtain the master dungeon map
|
||||||
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
let dungeon_master = ecs.read_resource::<MasterDungeonMap>();
|
||||||
|
@ -46,4 +46,5 @@ pub struct Wearable {
|
|||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct MagicItem {
|
pub struct MagicItem {
|
||||||
pub class: String,
|
pub class: String,
|
||||||
|
pub naming: String,
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ use ::specs::saveload::{MarkedBuilder, SimpleMarker};
|
|||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::gamesystem::{mana_at_level, npc_hp};
|
use crate::gamesystem::{mana_at_level, npc_hp};
|
||||||
|
use crate::map::MasterDungeonMap;
|
||||||
use crate::random_table::RandomTable;
|
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) {
|
pub fn parse_dice_string(dice: &str) -> (i32, i32, i32) {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -180,6 +181,21 @@ pub fn get_vendor_items(categories: &[String], raws: &RawMaster) -> Vec<(String,
|
|||||||
result
|
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>(
|
fn spawn_position<'a>(
|
||||||
pos: SpawnType,
|
pos: SpawnType,
|
||||||
new_entity: EntityBuilder<'a>,
|
new_entity: EntityBuilder<'a>,
|
||||||
@ -235,7 +251,7 @@ pub fn spawn_named_item(
|
|||||||
) -> Option<Entity> {
|
) -> Option<Entity> {
|
||||||
if raws.item_index.contains_key(key) {
|
if raws.item_index.contains_key(key) {
|
||||||
let item_template = &raws.raws.items[raws.item_index[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>>();
|
let mut eb = ecs.create_entity().marked::<SimpleMarker<SerializeMe>>();
|
||||||
|
|
||||||
// Spawn in the specified location
|
// Spawn in the specified location
|
||||||
@ -333,7 +349,17 @@ pub fn spawn_named_item(
|
|||||||
"legendary" => MagicItemClass::Legendary,
|
"legendary" => MagicItemClass::Legendary,
|
||||||
_ => MagicItemClass::Common,
|
_ => 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());
|
return Some(eb.build());
|
||||||
|
@ -93,6 +93,7 @@ pub fn save_game(ecs: &mut World) {
|
|||||||
MyTurn,
|
MyTurn,
|
||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
|
ObfuscatedName,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
@ -207,6 +208,7 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
MyTurn,
|
MyTurn,
|
||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
|
ObfuscatedName,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
|
@ -95,12 +95,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
|
|||||||
"Old Boots",
|
"Old Boots",
|
||||||
SpawnType::Equipped { by: player },
|
SpawnType::Equipped { by: player },
|
||||||
);
|
);
|
||||||
spawn_named_entity(
|
|
||||||
&RAWS.lock().unwrap(),
|
|
||||||
ecs,
|
|
||||||
"Town Portal Scroll",
|
|
||||||
SpawnType::Carried { by: player },
|
|
||||||
);
|
|
||||||
|
|
||||||
player
|
player
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user