diff --git a/src/ai/encumbrance_system.rs b/src/ai/encumbrance_system.rs index 0514eec..0244597 100644 --- a/src/ai/encumbrance_system.rs +++ b/src/ai/encumbrance_system.rs @@ -1,7 +1,7 @@ use crate::{ gamelog, Attributes, Burden, EquipmentChanged, Equipped, InBackpack, Item, Pools }; use specs::prelude::*; use std::collections::HashMap; -use crate::config::entity::CARRY_CAPACITY_PER_STRENGTH; +use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH; pub struct EncumbranceSystem {} diff --git a/src/ai/energy_system.rs b/src/ai/energy_system.rs index b09c6fe..f01c612 100644 --- a/src/ai/energy_system.rs +++ b/src/ai/energy_system.rs @@ -1,8 +1,9 @@ -use crate::config::entity::*; +use crate::data::entity::*; use crate::{ Burden, BurdenLevel, Clock, Energy, Name, Position, RunState, TakingTurn }; use rltk::prelude::*; use specs::prelude::*; use crate::config::CONFIG; +use crate::data::events::*; pub struct EnergySystem {} @@ -50,10 +51,10 @@ impl<'a> System<'a> for EnergySystem { if energy.current >= TURN_COST { turns.insert(entity, TakingTurn {}).expect("Unable to insert turn for turn counter."); energy.current -= TURN_COST; - crate::gamelog::record_event("turns", 1); + crate::gamelog::record_event(EVENT::TURN(1)); // Handle spawning mobs each turn if CONFIG.logging.log_ticks { - console::log(format!("===== TURN {} =====", crate::gamelog::get_event_count("turns"))); + console::log(format!("===== TURN {} =====", crate::gamelog::get_event_count(EVENT::COUNT_TURN))); } } } diff --git a/src/ai/regen_system.rs b/src/ai/regen_system.rs index 8ac4437..b74f857 100644 --- a/src/ai/regen_system.rs +++ b/src/ai/regen_system.rs @@ -11,6 +11,7 @@ use crate::{ TakingTurn, }; use specs::prelude::*; +use crate::data::events::*; pub struct RegenSystem {} @@ -47,14 +48,14 @@ impl<'a> System<'a> for RegenSystem { return; } // Monster HP regen - let current_turn = gamelog::get_event_count("turns"); + let current_turn = gamelog::get_event_count(EVENT::COUNT_TURN); if current_turn % MONSTER_HP_REGEN_TURN == 0 { for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, !&player).join() { try_hp_regen_tick(pool, MONSTER_HP_REGEN_PER_TICK); } } // Player HP regen - let level = gamelog::get_event_count("player_level"); + let level = gamelog::get_event_count(EVENT::COUNT_LEVEL); if current_turn % get_player_hp_regen_turn(level) == 0 { for (_e, _p, pool, _player) in (&entities, &positions, &mut pools, &player).join() { try_hp_regen_tick(pool, get_player_hp_regen_per_tick(level)); diff --git a/src/ai/turn_status_system.rs b/src/ai/turn_status_system.rs index 17f2db6..45b67c1 100644 --- a/src/ai/turn_status_system.rs +++ b/src/ai/turn_status_system.rs @@ -10,6 +10,7 @@ use crate::{ }; use rltk::prelude::*; use specs::prelude::*; +use crate::data::events::*; pub struct TurnStatusSystem {} @@ -78,7 +79,7 @@ impl<'a> System<'a> for TurnStatusSystem { .colour(WHITE) .append("are confused!"); log = true; - gamelog::record_event("player_confused", 1); + gamelog::record_event(EVENT::PLAYER_CONFUSED(1)); } else { logger = logger .append("The") diff --git a/src/camera.rs b/src/camera.rs index 94148b9..76923ae 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -71,7 +71,7 @@ pub fn render_camera(ecs: &World, ctx: &mut Rltk) { if map.visible_tiles[idx] { draw = true; } else { - fg = fg.mul(crate::config::visuals::NON_VISIBLE_MULTIPLIER); + fg = fg.mul(crate::data::visuals::NON_VISIBLE_MULTIPLIER); // We don't darken BG, because get_tile_renderables_for_id handles this. } diff --git a/src/components.rs b/src/components.rs index 3ab3c10..b08b5e1 100644 --- a/src/components.rs +++ b/src/components.rs @@ -21,7 +21,8 @@ pub struct SerializationHelper { pub struct DMSerializationHelper { pub map: super::map::MasterDungeonMap, pub log: Vec>, - pub events: HashMap, + pub event_counts: HashMap, + pub events: HashMap>, } #[derive(Component, ConvertSaveload, Clone)] diff --git a/src/config/glyphs.rs b/src/config/glyphs.rs deleted file mode 100644 index ba9ae67..0000000 --- a/src/config/glyphs.rs +++ /dev/null @@ -1,21 +0,0 @@ -// DEFAULT THEME -#[allow(dead_code)] -pub const WALL_GLYPH: char = '#'; -pub const FLOOR_GLYPH: char = '.'; -pub const DOWN_STAIR_GLYPH: char = '>'; -pub const UP_STAIR_GLYPH: char = '<'; -pub const WOOD_FLOOR_GLYPH: char = '.'; -pub const FENCE_GLYPH: char = '='; -pub const BRIDGE_GLYPH: char = '.'; -pub const GRAVEL_GLYPH: char = ';'; -pub const ROAD_GLYPH: char = '.'; -pub const GRASS_GLYPH: char = '"'; -pub const FOLIAGE_GLYPH: char = ':'; -pub const HEAVY_FOLIAGE_GLYPH: char = ';'; -pub const SAND_GLYPH: char = '.'; -pub const SHALLOW_WATER_GLYPH: char = '~'; -pub const DEEP_WATER_GLYPH: char = '≈'; -pub const BARS_GLYPH: char = '#'; - -// FOREST THEME -pub const FOREST_WALL_GLYPH: char = '♣'; diff --git a/src/config/load.rs b/src/config/load.rs deleted file mode 100644 index b86a5d2..0000000 --- a/src/config/load.rs +++ /dev/null @@ -1,2 +0,0 @@ -use std::error::Error; -use super::Config; diff --git a/src/config/mod.rs b/src/config/mod.rs index 0ca8d03..1143362 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,10 +1,3 @@ -pub mod entity; -pub mod visuals; -pub mod glyphs; -pub mod messages; -pub mod char_create; -mod load; - use rltk::prelude::*; use toml::Value; use serde::{ Serialize, Deserialize }; diff --git a/src/damage_system.rs b/src/damage_system.rs index 25ebaec..ee59e88 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -14,6 +14,7 @@ use super::{ }; use rltk::prelude::*; use specs::prelude::*; +use crate::data::events; pub fn delete_the_dead(ecs: &mut World) { let mut dead: Vec = Vec::new(); @@ -80,7 +81,7 @@ pub fn delete_the_dead(ecs: &mut World) { } // For everything that died, increment the event log, and delete. for victim in dead { - gamelog::record_event("death_count", 1); + gamelog::record_event(events::EVENT::TURN(1)); ecs.delete_entity(victim).expect("Unable to delete."); } } diff --git a/src/config/char_create.rs b/src/data/char_create.rs similarity index 100% rename from src/config/char_create.rs rename to src/data/char_create.rs diff --git a/src/config/entity.rs b/src/data/entity.rs similarity index 100% rename from src/config/entity.rs rename to src/data/entity.rs diff --git a/src/data/events.rs b/src/data/events.rs new file mode 100644 index 0000000..d8e97c8 --- /dev/null +++ b/src/data/events.rs @@ -0,0 +1,26 @@ +use serde::{ Deserialize, Serialize }; + +#[derive(Serialize, Deserialize, Clone)] +pub enum EVENT { + TURN(i32), + LEVEL(i32), + CHANGED_FLOOR(i32), + PLAYER_CONFUSED(i32), + KICKED_SOMETHING(i32), + BROKE_DOOR(i32), + LOOKED_FOR_HELP(i32), + KILLED(String), + DISCOVERED(String), + IDENTIFIED(String), +} + +impl EVENT { + pub const COUNT_TURN: &str = "turns"; + pub const COUNT_DEATH: &str = "deaths"; + pub const COUNT_LEVEL: &str = "level"; + pub const COUNT_CHANGED_FLOOR: &str = "changed_floor"; + pub const COUNT_BROKE_DOOR: &str = "broke_door"; + pub const COUNT_PLAYER_CONFUSED: &str = "player_confused"; + pub const COUNT_KICK: &str = "kick"; + pub const COUNT_LOOKED_FOR_HELP: &str = "looked_for_help"; +} diff --git a/src/config/messages.rs b/src/data/messages.rs similarity index 100% rename from src/config/messages.rs rename to src/data/messages.rs diff --git a/src/data/mod.rs b/src/data/mod.rs new file mode 100644 index 0000000..590c92a --- /dev/null +++ b/src/data/mod.rs @@ -0,0 +1,5 @@ +pub mod entity; +pub mod visuals; +pub mod messages; +pub mod char_create; +pub mod events; diff --git a/src/config/visuals.rs b/src/data/visuals.rs similarity index 76% rename from src/config/visuals.rs rename to src/data/visuals.rs index 5b41f3a..1afd15d 100644 --- a/src/config/visuals.rs +++ b/src/data/visuals.rs @@ -37,3 +37,25 @@ pub const DEEP_WATER_COLOUR: (u8, u8, u8) = (18, 33, 63); pub const BARS_COLOUR: (u8, u8, u8) = (100, 100, 100); // FOREST THEME pub const FOREST_WALL_COLOUR: (u8, u8, u8) = (0, 153, 0); + +// DEFAULT THEME +#[allow(dead_code)] +pub const WALL_GLYPH: char = '#'; +pub const FLOOR_GLYPH: char = '.'; +pub const DOWN_STAIR_GLYPH: char = '>'; +pub const UP_STAIR_GLYPH: char = '<'; +pub const WOOD_FLOOR_GLYPH: char = '.'; +pub const FENCE_GLYPH: char = '='; +pub const BRIDGE_GLYPH: char = '.'; +pub const GRAVEL_GLYPH: char = ';'; +pub const ROAD_GLYPH: char = '.'; +pub const GRASS_GLYPH: char = '"'; +pub const FOLIAGE_GLYPH: char = ':'; +pub const HEAVY_FOLIAGE_GLYPH: char = ';'; +pub const SAND_GLYPH: char = '.'; +pub const SHALLOW_WATER_GLYPH: char = '~'; +pub const DEEP_WATER_GLYPH: char = '≈'; +pub const BARS_GLYPH: char = '#'; + +// FOREST THEME +pub const FOREST_WALL_GLYPH: char = '♣'; diff --git a/src/effects/damage.rs b/src/effects/damage.rs index bb9eeeb..7230a3a 100644 --- a/src/effects/damage.rs +++ b/src/effects/damage.rs @@ -10,8 +10,9 @@ use crate::{ Player, Pools, }; -use crate::config::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME }; -use crate::config::messages::LEVELUP_PLAYER; +use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME }; +use crate::data::messages::LEVELUP_PLAYER; +use crate::data::events::*; use rltk::prelude::*; use specs::prelude::*; @@ -161,7 +162,7 @@ pub fn entity_death(ecs: &mut World, effect: &EffectSpawner, target: Entity) { source_pools.level += 1; // If it was the PLAYER that levelled up: if ecs.read_storage::().get(source).is_some() { - gamelog::record_event("player_level", 1); + gamelog::record_event(EVENT::LEVEL(1)); gamelog::Logger::new().append(LEVELUP_PLAYER).append_n(source_pools.level).append("!").log(); let player_pos = ecs.fetch::(); let map = ecs.fetch_mut::(); diff --git a/src/effects/triggers.rs b/src/effects/triggers.rs index 3b65ffe..3a079fd 100644 --- a/src/effects/triggers.rs +++ b/src/effects/triggers.rs @@ -33,7 +33,7 @@ use crate::{ KnownSpell, KnownSpells, }; -use crate::config::messages::*; +use crate::data::messages::*; use rltk::prelude::*; use specs::prelude::*; pub fn item_trigger(source: Option, item: Entity, target: &Targets, ecs: &mut World) { diff --git a/src/gamelog/events.rs b/src/gamelog/events.rs index 7781fa1..c2ffa30 100644 --- a/src/gamelog/events.rs +++ b/src/gamelog/events.rs @@ -1,18 +1,48 @@ -use std::collections::HashMap; +use std::collections::{ HashSet, HashMap }; use std::sync::Mutex; +use crate::data::events::EVENT; lazy_static! { - static ref EVENTS: Mutex> = Mutex::new(HashMap::new()); + /// A count of each event that has happened over the run. i.e. "turns", "descended", "ascended" + static ref EVENT_COUNTER: Mutex> = Mutex::new(HashMap::new()); + // A record of events that happened on a given turn. i.e. "Advanced to level 2". + pub static ref EVENTS: Mutex>> = Mutex::new(HashMap::new()); + static ref VISITED: Mutex> = Mutex::new(HashSet::new()); } +/// Makes a copy of event counts (FOR SERIALIZATION) +pub fn clone_event_counts() -> HashMap { + EVENT_COUNTER.lock().unwrap().clone() +} +/// Makes a copy of events (FOR SERIALIZATION) +pub fn clone_events() -> HashMap> { + EVENTS.lock().unwrap().clone() +} +/// Fetches event counter into mutex (FOR DESERIALIZATION) +pub fn restore_event_counter(events: HashMap) { + EVENT_COUNTER.lock().unwrap().clear(); + events.iter().for_each(|(k, v)| { + EVENT_COUNTER.lock().unwrap().insert(k.to_string(), *v); + }); +} +/// Fetches events into mutex (FOR DESERIALIZATION) +pub fn restore_events(events: HashMap>) { + EVENTS.lock().unwrap().clear(); + events.iter().for_each(|(k, v)| { + EVENTS.lock().unwrap().insert(*k, v.to_vec()); + }); +} +/// Wipes all events - for starting a new game. pub fn clear_events() { + EVENT_COUNTER.lock().unwrap().clear(); EVENTS.lock().unwrap().clear(); } #[allow(unused_mut)] -pub fn record_event(event: T, n: i32) { +/// Increments the event counter by n for a given event. +fn modify_event_count(event: T, n: i32) { let event_name = event.to_string(); - let mut events_lock = EVENTS.lock(); + let mut events_lock = EVENT_COUNTER.lock(); let mut events = events_lock.as_mut().unwrap(); if let Some(e) = events.get_mut(&event_name) { *e += n; @@ -20,10 +50,10 @@ pub fn record_event(event: T, n: i32) { events.insert(event_name, n); } } - +/// Returns how many times an event has taken place. pub fn get_event_count(event: T) -> i32 { let event_name = event.to_string(); - let events_lock = EVENTS.lock(); + let events_lock = EVENT_COUNTER.lock(); let events = events_lock.unwrap(); if let Some(e) = events.get(&event_name) { *e @@ -31,14 +61,61 @@ pub fn get_event_count(event: T) -> i32 { 0 } } +/// Records an event on the current turn. +pub fn record_event(event: EVENT) { + let mut new_event: String = "unknown event".to_string(); + let mut significant_event = true; + match event { + EVENT::TURN(n) => { + modify_event_count(EVENT::COUNT_TURN, n); + significant_event = false; + } + EVENT::LEVEL(n) => { + modify_event_count(EVENT::COUNT_LEVEL, n); + new_event = format!("Advanced to level {}", n); + } + EVENT::CHANGED_FLOOR(n) => { + modify_event_count(EVENT::COUNT_CHANGED_FLOOR, 1); + if VISITED.lock().unwrap().contains(&n) { + significant_event = false; + } else { + VISITED.lock().unwrap().insert(n); + new_event = format!("Visited level {} for the first time", n); + } + } + EVENT::KICKED_SOMETHING(n) => { + modify_event_count(EVENT::COUNT_KICK, n); + significant_event = false; + } + EVENT::BROKE_DOOR(n) => { + modify_event_count(EVENT::COUNT_BROKE_DOOR, n); + significant_event = false; + } + EVENT::PLAYER_CONFUSED(n) => { + modify_event_count(EVENT::COUNT_PLAYER_CONFUSED, n); + significant_event = false; + } + EVENT::LOOKED_FOR_HELP(n) => { + modify_event_count(EVENT::COUNT_LOOKED_FOR_HELP, n); + significant_event = false; + } + EVENT::KILLED(name) => { + new_event = format!("Killed {}", name); + } + EVENT::DISCOVERED(name) => { + new_event = format!("Discovered {}", name); + } + EVENT::IDENTIFIED(name) => { + new_event = format!("Identified {}", name); + } + } -pub fn clone_events() -> HashMap { - EVENTS.lock().unwrap().clone() -} - -pub fn load_events(events: HashMap) { - EVENTS.lock().unwrap().clear(); - events.iter().for_each(|(k, v)| { - EVENTS.lock().unwrap().insert(k.to_string(), *v); - }); + if significant_event { + EVENTS.lock() + .as_mut() + .unwrap() + .entry(get_event_count(EVENT::COUNT_TURN) as u32) + .or_insert_with(Vec::new) + .push(new_event); + } } diff --git a/src/gamelog/mod.rs b/src/gamelog/mod.rs index 621482c..f67b436 100644 --- a/src/gamelog/mod.rs +++ b/src/gamelog/mod.rs @@ -1,5 +1,3 @@ -use rltk::prelude::*; - mod builder; pub use builder::*; mod logstore; @@ -9,6 +7,7 @@ mod events; pub use events::*; use serde::{ Deserialize, Serialize }; +use rltk::prelude::*; #[derive(Serialize, Deserialize, Clone)] pub struct LogFragment { pub colour: RGB, diff --git a/src/gamesystem.rs b/src/gamesystem.rs index c9c109f..130a02c 100644 --- a/src/gamesystem.rs +++ b/src/gamesystem.rs @@ -1,7 +1,7 @@ use super::{ Skill, Skills }; use crate::gui::{ Ancestry, Class }; -use crate::config::entity; -use crate::config::char_create::*; +use crate::data::entity; +use crate::data::char_create::*; use rltk::prelude::*; use std::cmp::max; diff --git a/src/gui/character_creation.rs b/src/gui/character_creation.rs index d53b238..c60d839 100644 --- a/src/gui/character_creation.rs +++ b/src/gui/character_creation.rs @@ -1,6 +1,6 @@ use super::{ gamesystem::attr_bonus, gamesystem::get_attribute_rolls, Attributes, Pools, Renderable, RunState, State }; -use crate::config::entity; -use crate::config::char_create::*; +use crate::data::entity; +use crate::data::char_create::*; use crate::{ raws, Attribute, diff --git a/src/gui/mod.rs b/src/gui/mod.rs index e7b157a..b470f7b 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -33,7 +33,7 @@ use super::{ Viewshed, BUC, }; -use crate::config::entity::CARRY_CAPACITY_PER_STRENGTH; +use crate::data::entity::CARRY_CAPACITY_PER_STRENGTH; use rltk::prelude::*; use specs::prelude::*; use std::collections::BTreeMap; @@ -47,6 +47,7 @@ mod identify_menu; pub use identify_menu::*; mod tooltip; pub use cheat_menu::*; +use crate::data::events::*; /// Gives a popup box with a message and a title, and waits for a keypress. #[allow(unused)] @@ -329,7 +330,7 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) { 54, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), - &format!("T{}", crate::gamelog::get_event_count("turns")) + &format!("T{}", crate::gamelog::get_event_count(EVENT::COUNT_TURN)) ); // Boxes and tooltips last, so they draw over everything else. @@ -1135,22 +1136,22 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult { y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), - format!("You survived for {} turns.", crate::gamelog::get_event_count("turns")) + format!("You survived for {} turns.", crate::gamelog::get_event_count(EVENT::COUNT_TURN)) ); y += 2; ctx.print_color(x, y, RGB::named(rltk::GREEN), RGB::named(rltk::BLACK), format!("And in the process, you")); y += 1; - if crate::gamelog::get_event_count("descended") > 0 { + if crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR) > 0 { ctx.print_color( x + 1, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), - format!("- descended {} floor(s)", crate::gamelog::get_event_count("descended")) + format!("- changed floor {} times", crate::gamelog::get_event_count(EVENT::COUNT_CHANGED_FLOOR)) ); y += 1; } - if crate::gamelog::get_event_count("kick_count") > 0 { + if crate::gamelog::get_event_count(EVENT::COUNT_KICK) > 0 { ctx.print_color( x + 1, y, @@ -1158,29 +1159,29 @@ pub fn game_over(ctx: &mut Rltk) -> YesNoResult { RGB::named(rltk::BLACK), format!( "- kicked {} time(s), breaking {} object(s)", - crate::gamelog::get_event_count("kick_count"), - crate::gamelog::get_event_count("broken_doors") + crate::gamelog::get_event_count(EVENT::COUNT_KICK), + crate::gamelog::get_event_count(EVENT::COUNT_BROKE_DOOR) ) ); y += 1; } - if crate::gamelog::get_event_count("death_count") > 0 { + if crate::gamelog::get_event_count(EVENT::COUNT_DEATH) > 0 { ctx.print_color( x + 1, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), - format!("- slew {} other creature(s)", crate::gamelog::get_event_count("death_count")) + format!("- slew {} other creature(s)", crate::gamelog::get_event_count(EVENT::COUNT_DEATH)) ); y += 1; } - if crate::gamelog::get_event_count("looked_for_help") > 0 { + if crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP) > 0 { ctx.print_color( x + 1, y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), - format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count("looked_for_help")) + format!("- forgot the controls {} time(s)", crate::gamelog::get_event_count(EVENT::COUNT_LOOKED_FOR_HELP)) ); } diff --git a/src/inventory/collection_system.rs b/src/inventory/collection_system.rs index b1500f3..3bb4945 100644 --- a/src/inventory/collection_system.rs +++ b/src/inventory/collection_system.rs @@ -13,7 +13,7 @@ use crate::{ WantsToPickupItem, }; use specs::prelude::*; -use crate::config::messages; +use crate::data::messages; pub struct ItemCollectionSystem {} diff --git a/src/inventory/drop_system.rs b/src/inventory/drop_system.rs index 39a8a0f..dd9659e 100644 --- a/src/inventory/drop_system.rs +++ b/src/inventory/drop_system.rs @@ -13,7 +13,7 @@ use crate::{ WantsToDropItem, }; use specs::prelude::*; -use crate::config::messages; +use crate::data::messages; pub struct ItemDropSystem {} diff --git a/src/inventory/equip_system.rs b/src/inventory/equip_system.rs index 7d04e1c..1d52c1d 100644 --- a/src/inventory/equip_system.rs +++ b/src/inventory/equip_system.rs @@ -16,7 +16,7 @@ use crate::{ BUC, }; use specs::prelude::*; -use crate::config::messages; +use crate::data::messages; pub struct ItemEquipSystem {} diff --git a/src/inventory/identification_system.rs b/src/inventory/identification_system.rs index e1d49f4..3fbe579 100644 --- a/src/inventory/identification_system.rs +++ b/src/inventory/identification_system.rs @@ -1,5 +1,7 @@ use crate::{ Beatitude, IdentifiedBeatitude, IdentifiedItem, Item, MasterDungeonMap, Name, ObfuscatedName, Player }; use specs::prelude::*; +use crate::data::events::*; +use crate::gamelog; pub struct ItemIdentificationSystem {} @@ -32,6 +34,9 @@ impl<'a> System<'a> for ItemIdentificationSystem { 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) { + if gamelog::get_event_count(EVENT::COUNT_TURN) != 1 { + gamelog::record_event(EVENT::IDENTIFIED(id.name.clone())); + } dm.identified_items.insert(id.name.clone()); for (entity, _item, name) in (&entities, &items, &names).join() { if name.name == id.name { diff --git a/src/inventory/remove_system.rs b/src/inventory/remove_system.rs index f093820..cbe498d 100644 --- a/src/inventory/remove_system.rs +++ b/src/inventory/remove_system.rs @@ -13,7 +13,7 @@ use crate::{ }; use rltk::prelude::*; use specs::prelude::*; -use crate::config::messages; +use crate::data::messages; pub struct ItemRemoveSystem {} diff --git a/src/main.rs b/src/main.rs index dd1dc88..14a41a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,7 @@ mod inventory; mod particle_system; use particle_system::ParticleBuilder; mod ai; +mod data; mod config; mod effects; mod gamesystem; @@ -36,6 +37,7 @@ mod random_table; mod rex_assets; mod spatial; mod morgue; +use data::events::*; #[macro_use] extern crate lazy_static; @@ -177,13 +179,11 @@ impl State { current_id = worldmap_resource.id; } // Record the correct type of event - if offset > 0 { - gamelog::record_event("descended", 1); - } else if current_id == 1 { + if offset < 0 && current_id == 1 { gamelog::Logger::new().append("CHEAT MENU: YOU CAN'T DO THAT.").colour((255, 0, 0)).log(); return; } else { - gamelog::record_event("ascended", 1); + gamelog::record_event(EVENT::CHANGED_FLOOR(current_id + offset)); } // Freeze the current level map::dungeon::freeze_entities(&mut self.ecs); @@ -213,7 +213,7 @@ impl State { self.generate_world_map(1, 0); gamelog::setup_log(); - gamelog::record_event("player_level", 1); + gamelog::record_event(EVENT::LEVEL(1)); } } @@ -537,7 +537,7 @@ impl GameState for State { let result = gui::show_help(ctx); match result { gui::YesNoResult::Yes => { - gamelog::record_event("looked_for_help", 1); + gamelog::record_event(EVENT::LOOKED_FOR_HELP(1)); new_runstate = RunState::AwaitingInput; } _ => {} @@ -628,7 +628,7 @@ fn main() -> rltk::BError { .with_simple_console(DISPLAYWIDTH, DISPLAYHEIGHT, "curses14x16.png") .build()?; if config::CONFIG.visuals.with_scanlines { - context.with_post_scanlines(config::visuals::WITH_SCREEN_BURN); + context.with_post_scanlines(data::visuals::WITH_SCREEN_BURN); } let mut gs = State { @@ -733,7 +733,7 @@ fn main() -> rltk::BError { gs.ecs.insert(rex_assets::RexAssets::new()); gamelog::setup_log(); - gamelog::record_event("player_level", 1); + gamelog::record_event(EVENT::LEVEL(1)); gs.generate_world_map(1, 0); rltk::main_loop(context, gs) diff --git a/src/map/dungeon.rs b/src/map/dungeon.rs index 5da701c..c7b5ebc 100644 --- a/src/map/dungeon.rs +++ b/src/map/dungeon.rs @@ -4,6 +4,7 @@ use rltk::prelude::*; use serde::{ Deserialize, Serialize }; use specs::prelude::*; use std::collections::{ HashMap, HashSet }; +use crate::data::events::*; #[derive(Default, Serialize, Deserialize, Clone)] pub struct MasterDungeonMap { @@ -241,7 +242,7 @@ fn transition_to_new_map(ecs: &mut World, new_id: i32) -> Vec { // Might need this to fallback to 1, but if player // level isn't found at all, there's a bigger concern // concern than just this function not working. - let player_level = gamelog::get_event_count("player_level"); + let player_level = gamelog::get_event_count(EVENT::COUNT_LEVEL); let mut builder = map_builders::level_builder(new_id, &mut rng, 100, 50, player_level); builder.build_map(&mut rng); std::mem::drop(rng); diff --git a/src/map/interval_spawning_system.rs b/src/map/interval_spawning_system.rs index 72e59ad..838c27d 100644 --- a/src/map/interval_spawning_system.rs +++ b/src/map/interval_spawning_system.rs @@ -1,5 +1,6 @@ use crate::{ config::CONFIG, gamelog, raws, spawner, Clock, Map, RandomNumberGenerator, TakingTurn }; use specs::prelude::*; +use crate::data::events::*; const TRY_SPAWN_CHANCE: i32 = 70; @@ -32,7 +33,7 @@ pub fn try_spawn_interval(ecs: &mut World) { fn spawn_random_mob_in_free_nonvisible_tile(ecs: &mut World) { let map = ecs.fetch::(); let mut available_tiles = populate_unblocked_nonvisible(&map); - let player_level = gamelog::get_event_count("player_level"); + let player_level = gamelog::get_event_count(EVENT::COUNT_LEVEL); rltk::console::log(player_level); let difficulty = (map.difficulty + player_level) / 2; if available_tiles.len() == 0 { diff --git a/src/map/mod.rs b/src/map/mod.rs index f4972af..7ea2b95 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -8,7 +8,7 @@ pub use interval_spawning_system::try_spawn_interval; pub mod dungeon; pub use dungeon::{ level_transition, MasterDungeonMap }; pub mod themes; -use crate::config::visuals::MAX_COLOUR_OFFSET_PERCENT; +use crate::data::visuals::MAX_COLOUR_OFFSET_PERCENT; // FIXME: If the map size gets too small, entities stop being rendered starting from the right. // i.e. on a map size of 40*40, only entities to the left of the player are rendered. diff --git a/src/map/themes.rs b/src/map/themes.rs index 87a7d18..7a7dd4e 100644 --- a/src/map/themes.rs +++ b/src/map/themes.rs @@ -1,6 +1,5 @@ use super::{ Map, Point, TileType }; -use crate::config::glyphs::*; -use crate::config::visuals::*; +use crate::data::visuals::*; use crate::config::CONFIG; use rltk::prelude::*; use std::ops::{ Add, Mul }; @@ -269,7 +268,7 @@ fn darken_by_distance(pos: Point, other_pos: Point) -> f32 { let distance = DistanceAlg::Pythagoras.distance2d(pos, other_pos) as f32; // Get distance in tiles. let interp_factor = (distance - START_DARKEN_AT_N_TILES) / - ((crate::config::entity::DEFAULT_VIEWSHED_STANDARD as f32) - START_DARKEN_AT_N_TILES); + ((crate::data::entity::DEFAULT_VIEWSHED_STANDARD as f32) - START_DARKEN_AT_N_TILES); let interp_factor = interp_factor.max(0.0).min(1.0); // Clamp [0-1] return ( 1.0 - diff --git a/src/morgue.rs b/src/morgue.rs index 373f4a4..f3d2011 100644 --- a/src/morgue.rs +++ b/src/morgue.rs @@ -9,6 +9,7 @@ use specs::prelude::*; use rltk::prelude::*; use rltk::to_char; use std::collections::HashMap; +use crate::data::events::*; #[cfg(target_arch = "wasm32")] pub fn create_morgue_file(ecs: &World) { @@ -25,7 +26,7 @@ pub fn create_morgue_file(ecs: &World) { } let morgue_info = create_morgue_string(ecs); let file_name = create_file_name(ecs, morgue_dir); - if let Err(err) = write_morgue_file(morgue_info.as_str(), file_name.as_str()) { + if let Err(err) = write_morgue_file(file_name.as_str(), morgue_info.as_str()) { console::log(format!("Unable to write the morgue file: {}", err)); }; } @@ -75,10 +76,13 @@ fn create_morgue_string(ecs: &World) -> String { morgue_info.push_str(&create_boxed_text(header.as_str(), None)); morgue_info.push_str(&draw_tombstone(ecs, header.len())); morgue_info.push_str(&draw_map(ecs)); + morgue_info.push_str("\n"); morgue_info.push_str(&create_boxed_text("Equipment", None)); morgue_info.push_str(&draw_equipment(ecs)); morgue_info.push_str(&create_boxed_text("Backpack", None)); morgue_info.push_str(&draw_backpack(ecs)); + morgue_info.push_str(&create_boxed_text("Significant Events", None)); + morgue_info.push_str(&draw_events_list()); return morgue_info; } @@ -133,7 +137,7 @@ fn draw_tombstone(ecs: &World, len: usize) -> String { "", map.name, map.id, - gamelog::get_event_count("turns"), + gamelog::get_event_count(EVENT::COUNT_TURN), "", "", p = pad @@ -229,3 +233,28 @@ fn draw_backpack(ecs: &World) -> String { result.push_str("\n"); return result; } + +fn draw_events_list() -> String { + // Initialise default (empty) string + let mut result: String = Default::default(); + // Get lock on events mutex + let lock = gamelog::EVENTS.lock().unwrap(); + // Collect all keys, and sort in ascending value (by turn count) + let mut sorted_keys: Vec = lock + .keys() + .map(|k| *k) + .collect(); + sorted_keys.sort(); + // Iterate through sorted keys, looking for corresponding values, and append on newline + for key in sorted_keys { + if let Some(value) = lock.get(&key) { + result.push_str(&format!("{:<4} | ", key)); + for event in value.iter() { + result.push_str(&format!("{}", event)); + } + result.push_str("\n"); + } + } + + return result; +} diff --git a/src/particle_system.rs b/src/particle_system.rs index d83b9e6..249f232 100644 --- a/src/particle_system.rs +++ b/src/particle_system.rs @@ -1,7 +1,7 @@ use super::{ ParticleLifetime, Position, Renderable, Rltk }; use rltk::RGB; use specs::prelude::*; -use crate::config::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME }; +use crate::data::visuals::{ DEFAULT_PARTICLE_LIFETIME, SHORT_PARTICLE_LIFETIME }; /// Runs each tick, deleting particles who are past their expiry. // Should make an addition to this to also spawn delayed particles, diff --git a/src/player.rs b/src/player.rs index ddc0250..1c71bd7 100644 --- a/src/player.rs +++ b/src/player.rs @@ -34,6 +34,7 @@ use rltk::prelude::*; use rltk::{ Point, RandomNumberGenerator, Rltk, VirtualKeyCode }; use specs::prelude::*; use std::cmp::{ max, min }; +use crate::data::events::*; pub fn try_door(i: i32, j: i32, ecs: &mut World) -> RunState { let mut positions = ecs.write_storage::(); @@ -263,7 +264,7 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState { .log(); something_was_destroyed = Some(potential_target); destroyed_pos = Some(Point::new(pos.x + delta_x, pos.y + delta_y)); - gamelog::record_event("broken_doors", 1); + gamelog::record_event(EVENT::BROKE_DOOR(1)); return false; // 66% chance of just kicking it. } else { @@ -308,7 +309,7 @@ pub fn kick(i: i32, j: i32, ecs: &mut World) -> RunState { ecs.delete_entity(destroyed_thing).expect("Unable to delete."); } - gamelog::record_event("kick_count", 1); + gamelog::record_event(EVENT::KICKED_SOMETHING(1)); return RunState::Ticking; } diff --git a/src/saveload_system.rs b/src/saveload_system.rs index 81bd33a..bb7eb43 100644 --- a/src/saveload_system.rs +++ b/src/saveload_system.rs @@ -38,6 +38,7 @@ pub fn save_game(ecs: &mut World) { .with(DMSerializationHelper { map: dungeon_master, log: crate::gamelog::clone_log(), + event_counts: crate::gamelog::clone_event_counts(), events: crate::gamelog::clone_events(), }) .marked::>() @@ -280,7 +281,8 @@ pub fn load_game(ecs: &mut World) { *dungeonmaster = h.map.clone(); deleteme2 = Some(e); crate::gamelog::restore_log(&mut h.log.clone()); - crate::gamelog::load_events(h.events.clone()); + crate::gamelog::restore_event_counter(h.event_counts.clone()); + crate::gamelog::restore_events(h.events.clone()); } for (e, _p, pos) in (&entities, &player, &position).join() { let mut ppos = ecs.write_resource::(); diff --git a/src/spawner.rs b/src/spawner.rs index 9a63c8b..b9c1994 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -24,7 +24,7 @@ use super::{ TileType, Viewshed, }; -use crate::config::entity; +use crate::data::entity; use crate::gamesystem::*; use rltk::{ RandomNumberGenerator, RGB }; use specs::prelude::*;