diff --git a/changelog.txt b/changelog.txt index a9ce8c2..7669294 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,11 +1,15 @@ 30-August-2023 -- overmap: bare, but exists. player now starts on the overworld, and can move to local maps (like the old starting town) via >. can leave local maps back to the overmap by walking out of the map boundaries. +- added dungeon features: grassy forest room, and barracks variants (bunks, squads of mobtypes) +- added support for map messages: i.e. notifications for present dungeon features logged to chat every now and again + +Pre-29-August-2023 +- added overmap: bare, but exists. player now starts on the overworld, and can move to local maps (like the old starting town) via >. can leave local maps back to the overmap by walking out of the map boundaries. - mouse begone: support still there if wanted, but targeting/e(x)amining can now be done via keyboard only -- config.toml: non-wasm builds read from config.toml at runtime, or generate a new copy if not present in the exe dir. includes options for logging various details to the console, and visual choices like post-processing effects, all-black bgs vs. full-coloured, etc. -- morgue files: y/n prompt to write a morgue file on death (or write to console in the case of wasm), containing a map of the floor the player died on, class/race/attribute/etc. details, a fully identified backpack, and a list of significant events that took place this run w/ turn number +- added config.toml: non-wasm builds read from config.toml at runtime, or generate a new copy if not present in the exe dir. includes options for logging various details to the console, and visual choices like post-processing effects, all-black bgs vs. full-coloured, etc. +- improved morgue files: y/n prompt to write a morgue file on death (or write to console in the case of wasm), containing a map of the floor the player died on, class/race/attribute/etc. details, a fully identified backpack, and a list of significant events that took place this run w/ turn number - refactored colour offsets: now per-tile (and per-theme), instead of global. now can include varying fg/bg offset for every type of tile. - consistent chatlog colours: renderables for mobs, beatitude for items -- rooms themes: grassy room theme proof-of-concept, propagates grass/foliage/etc. out from a room if rolled, and spawns themed mobs +- dungeon features: framework - map identifiers (instead of displaying an incorrect depth) on ui: e.g. D1, D2, Town, Woods, etc. - bugfixes: - map params are saved on map transition, instead of only at creation. now bloodstains, vision, etc. will persist when changing between floors diff --git a/src/data/messages.rs b/src/data/messages.rs index ddd31e4..5847c14 100644 --- a/src/data/messages.rs +++ b/src/data/messages.rs @@ -43,3 +43,9 @@ pub const PLAYER_DIED_ADDENDUM_LAST: &str = ", and "; pub const STATUS_CONFUSED_STRING: &str = "confused"; pub const STATUS_BLIND_STRING: &str = "blinded"; // Results in something like: "You died! You were killed by a kobold captain, whilst confused." + +// Dungeon features +pub const FEATURE_TREANTS: &str = "You feel an unusual freshness in the air."; +pub const FEATURE_BARRACKS_GOBLIN: &str = "You hear an order being barked, and ignored."; +pub const FEATURE_BARRACKS_KOBOLD: &str = "You hear someone being reprimanded for disobedience."; +pub const FEATURE_BARRACKS_ORC: &str = "You hear someone barking orders."; diff --git a/src/main.rs b/src/main.rs index df00bdb..b99a7a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -273,6 +273,7 @@ impl GameState for State { self.run_systems(); self.ecs.maintain(); try_spawn_interval(&mut self.ecs); + maybe_map_message(&mut self.ecs); match *self.ecs.fetch::() { RunState::AwaitingInput => { new_runstate = RunState::AwaitingInput; diff --git a/src/map/interval_spawning_system.rs b/src/map/interval_spawning_system.rs index 838c27d..80e910e 100644 --- a/src/map/interval_spawning_system.rs +++ b/src/map/interval_spawning_system.rs @@ -3,6 +3,33 @@ use specs::prelude::*; use crate::data::events::*; const TRY_SPAWN_CHANCE: i32 = 70; +const FEATURE_MESSAGE_CHANCE: i32 = 110; + +pub fn maybe_map_message(ecs: &mut World) { + let mut maybe_message = false; + let map = ecs.fetch::(); + if map.messages.is_empty() { + return; + } + // Scope for borrow checker (ECS) + { + let clock = ecs.read_storage::(); + let turns = ecs.read_storage::(); + let mut rng = ecs.write_resource::(); + for (_c, _t) in (&clock, &turns).join() { + if rng.roll_dice(1, FEATURE_MESSAGE_CHANCE) == 1 { + maybe_message = true; + } + } + } + if maybe_message { + let mut logger = gamelog::Logger::new(); + for message in map.messages.clone() { + logger = logger.append(message); + } + logger.log(); + } +} pub fn try_spawn_interval(ecs: &mut World) { let mut try_spawn = false; diff --git a/src/map/mod.rs b/src/map/mod.rs index 0fcd0b4..0b31dc9 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -4,7 +4,7 @@ use std::collections::{ HashSet, HashMap }; mod tiletype; pub use tiletype::{ tile_cost, tile_opaque, tile_walkable, TileType, get_dest, Destination }; mod interval_spawning_system; -pub use interval_spawning_system::try_spawn_interval; +pub use interval_spawning_system::{ maybe_map_message, try_spawn_interval }; pub mod dungeon; pub use dungeon::{ level_transition, MasterDungeonMap }; pub mod themes; @@ -30,6 +30,7 @@ pub struct Map { pub name: String, pub short_name: String, pub depth: i32, + pub messages: HashSet, pub difficulty: i32, pub bloodstains: HashMap, pub view_blocked: HashSet, @@ -70,6 +71,7 @@ impl Map { id: new_id, name: name.to_string(), short_name: short_name.to_string(), + messages: HashSet::new(), depth: depth, difficulty: difficulty, bloodstains: HashMap::new(), diff --git a/src/map_builders/room_themer.rs b/src/map_builders/room_themer.rs index 157edca..04720bb 100644 --- a/src/map_builders/room_themer.rs +++ b/src/map_builders/room_themer.rs @@ -1,5 +1,6 @@ use super::{ BuilderMap, MetaMapBuilder, Rect, TileType }; use crate::tile_walkable; +use crate::data::messages::{ FEATURE_TREANTS, FEATURE_BARRACKS_GOBLIN, FEATURE_BARRACKS_KOBOLD, FEATURE_BARRACKS_ORC }; use crate::raws; use rltk::RandomNumberGenerator; @@ -59,6 +60,7 @@ impl ThemeRooms { } } } + build_data.map.messages.insert(FEATURE_TREANTS.to_string()); } fn place_barracks(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap, room: &Rect) { @@ -75,9 +77,18 @@ impl ThemeRooms { let mut needs_captain = if rng.roll_dice(1, 3) == 1 { false } else { true }; let (captain, squad) = match rng.roll_dice(1, 4) { - 1 => ("goblin_chieftain", "squad_goblin"), - 2 => ("kobold_captain", "squad_kobold"), - _ => ("orc_captain", "squad_orc"), + 1 => { + build_data.map.messages.insert(FEATURE_BARRACKS_GOBLIN.to_string()); + ("goblin_chieftain", "squad_goblin") + } + 2 => { + build_data.map.messages.insert(FEATURE_BARRACKS_KOBOLD.to_string()); + ("kobold_captain", "squad_kobold") + } + _ => { + build_data.map.messages.insert(FEATURE_BARRACKS_ORC.to_string()); + ("orc_captain", "squad_orc") + } }; for idx in possible { if idx % 2 == 0 && rng.roll_dice(1, 2) == 1 {