Add event counting to game log, completing section 5.29
This commit is contained in:
parent
21c0601ebd
commit
83cab40c13
@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
use ::specs_derive::*;
|
use ::specs_derive::*;
|
||||||
@ -19,4 +21,5 @@ pub struct SerializationHelper {
|
|||||||
pub struct DMSerializationHelper {
|
pub struct DMSerializationHelper {
|
||||||
pub map: MasterDungeonMap,
|
pub map: MasterDungeonMap,
|
||||||
pub log: Vec<Vec<crate::gamelog::LogFragment>>,
|
pub log: Vec<Vec<crate::gamelog::LogFragment>>,
|
||||||
|
pub events: HashMap<String, i32>,
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use crate::{colors, gamelog, EquipmentChanged, Map, StatusEffect};
|
|||||||
|
|
||||||
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
||||||
let mut pools = ecs.write_storage::<Pools>();
|
let mut pools = ecs.write_storage::<Pools>();
|
||||||
|
let player_entity = ecs.fetch::<Entity>();
|
||||||
if let Some(pool) = pools.get_mut(target) {
|
if let Some(pool) = pools.get_mut(target) {
|
||||||
if !pool.god_mode {
|
if !pool.god_mode {
|
||||||
if let Some(creator) = damage.creator {
|
if let Some(creator) = damage.creator {
|
||||||
@ -31,6 +32,14 @@ pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
|
|||||||
},
|
},
|
||||||
Targets::Single { target },
|
Targets::Single { target },
|
||||||
);
|
);
|
||||||
|
if target == *player_entity {
|
||||||
|
gamelog::record_event("Damage Taken", amount);
|
||||||
|
}
|
||||||
|
if let Some(creator) = damage.creator {
|
||||||
|
if creator == *player_entity {
|
||||||
|
gamelog::record_event("Damage Inflicted", amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if pool.hit_points.current < 1 {
|
if pool.hit_points.current < 1 {
|
||||||
add_effect(
|
add_effect(
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
//!
|
//!
|
||||||
//! Where the exploits of the current game are recorded
|
//! Where the exploits of the current game are recorded
|
||||||
mod builder;
|
mod builder;
|
||||||
|
mod events;
|
||||||
mod logstore;
|
mod logstore;
|
||||||
|
|
||||||
use ::rltk::RGB;
|
use ::rltk::RGB;
|
||||||
use ::serde::{Deserialize, Serialize};
|
use ::serde::{Deserialize, Serialize};
|
||||||
pub use builder::*;
|
pub use builder::*;
|
||||||
|
pub use events::*;
|
||||||
use logstore::*;
|
use logstore::*;
|
||||||
pub use logstore::{clear_log, clone_log, log_display, restore_log};
|
pub use logstore::{clear_log, clone_log, log_display, restore_log};
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ impl Logger {
|
|||||||
pub fn damage(mut self, damage: i32) -> Self {
|
pub fn damage(mut self, damage: i32) -> Self {
|
||||||
self.fragments.push(LogFragment {
|
self.fragments.push(LogFragment {
|
||||||
color: colors::RED,
|
color: colors::RED,
|
||||||
text: format!("{}", damage).to_string(),
|
text: format!("{}", damage),
|
||||||
});
|
});
|
||||||
|
|
||||||
self
|
self
|
||||||
|
43
src/gamelog/events.rs
Normal file
43
src/gamelog/events.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref EVENTS: Mutex<HashMap<String, i32>> = Mutex::new(HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_events() {
|
||||||
|
EVENTS.lock().unwrap().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn record_event<T: ToString>(event: T, n: i32) {
|
||||||
|
let event_name = event.to_string();
|
||||||
|
let mut events_lock = EVENTS.lock();
|
||||||
|
let events = events_lock.as_mut().unwrap();
|
||||||
|
if let Some(e) = events.get_mut(&event_name) {
|
||||||
|
*e += n;
|
||||||
|
} else {
|
||||||
|
events.insert(event_name, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_event_count<T: ToString>(event: T) -> i32 {
|
||||||
|
let event_name = event.to_string();
|
||||||
|
let events_lock = EVENTS.lock();
|
||||||
|
let events = events_lock.unwrap();
|
||||||
|
if let Some(e) = events.get(&event_name) {
|
||||||
|
*e
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_events() -> HashMap<String, i32> {
|
||||||
|
EVENTS.lock().unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_events(events: HashMap<String, i32>) {
|
||||||
|
clear_events();
|
||||||
|
events.iter().for_each(|(k, v)| {
|
||||||
|
EVENTS.lock().unwrap().insert(k.to_string(), *v);
|
||||||
|
});
|
||||||
|
}
|
53
src/gui.rs
53
src/gui.rs
@ -421,3 +421,56 @@ pub fn ranged_target(
|
|||||||
|
|
||||||
(ItemMenuResult::NoResponse, None)
|
(ItemMenuResult::NoResponse, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn game_over(ctx: &mut Rltk) -> GameOverResult {
|
||||||
|
ctx.print_color_centered(15, colors::YELLOW, colors::BLACK, "Your journey has ended!");
|
||||||
|
ctx.print_color_centered(
|
||||||
|
17,
|
||||||
|
colors::WHITE,
|
||||||
|
colors::BLACK,
|
||||||
|
"One day, we'll tell you all about how you did.",
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
18,
|
||||||
|
colors::WHITE,
|
||||||
|
colors::BLACK,
|
||||||
|
"That day, sadly, is not in this chapter...",
|
||||||
|
);
|
||||||
|
|
||||||
|
ctx.print_color_centered(
|
||||||
|
19,
|
||||||
|
colors::WHITE,
|
||||||
|
colors::BLACK,
|
||||||
|
format!("You lived for {} turns.", gamelog::get_event_count("Turn")),
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
20,
|
||||||
|
colors::RED,
|
||||||
|
colors::BLACK,
|
||||||
|
&format!(
|
||||||
|
"You suffered {} points of damage.",
|
||||||
|
gamelog::get_event_count("Damage Taken")
|
||||||
|
),
|
||||||
|
);
|
||||||
|
ctx.print_color_centered(
|
||||||
|
21,
|
||||||
|
colors::RED,
|
||||||
|
colors::BLACK,
|
||||||
|
&format!(
|
||||||
|
"You inflicted {} points of damage.",
|
||||||
|
gamelog::get_event_count("Damage Inflicted")
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
ctx.print_color_centered(
|
||||||
|
23,
|
||||||
|
colors::MAGENTA,
|
||||||
|
colors::BLACK,
|
||||||
|
"Press any key to return to the menu.",
|
||||||
|
);
|
||||||
|
|
||||||
|
match ctx.key {
|
||||||
|
None => GameOverResult::NoSelection,
|
||||||
|
Some(_) => GameOverResult::QuitToMenu,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -336,34 +336,6 @@ pub fn main_menu(gs: &mut State, ctx: &mut Rltk) -> MainMenuResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn game_over(ctx: &mut Rltk) -> GameOverResult {
|
|
||||||
ctx.print_color_centered(15, colors::YELLOW, colors::BLACK, "Your journey has ended!");
|
|
||||||
ctx.print_color_centered(
|
|
||||||
17,
|
|
||||||
colors::WHITE,
|
|
||||||
colors::BLACK,
|
|
||||||
"One day, we'll tell you all about how you did.",
|
|
||||||
);
|
|
||||||
ctx.print_color_centered(
|
|
||||||
18,
|
|
||||||
colors::WHITE,
|
|
||||||
colors::BLACK,
|
|
||||||
"That day, sadly, is not in this chapter...",
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.print_color_centered(
|
|
||||||
20,
|
|
||||||
colors::MAGENTA,
|
|
||||||
colors::BLACK,
|
|
||||||
"Press any key to return to the menu.",
|
|
||||||
);
|
|
||||||
|
|
||||||
match ctx.key {
|
|
||||||
None => GameOverResult::NoSelection,
|
|
||||||
Some(_) => GameOverResult::QuitToMenu,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_cheat_mode(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
pub fn show_cheat_mode(_gs: &mut State, ctx: &mut Rltk) -> CheatMenuResult {
|
||||||
let count = 4;
|
let count = 4;
|
||||||
let mut y = (25 - (count / 2)) as i32;
|
let mut y = (25 - (count / 2)) as i32;
|
||||||
|
12
src/main.rs
12
src/main.rs
@ -164,6 +164,8 @@ fn register_components(state: &mut State) {
|
|||||||
/// * Creates the [`Player`](crate::spawner::player)
|
/// * Creates the [`Player`](crate::spawner::player)
|
||||||
/// * Generates the first [`map`](crate::state::State::generate_world_map)
|
/// * Generates the first [`map`](crate::state::State::generate_world_map)
|
||||||
fn init_state() -> State {
|
fn init_state() -> State {
|
||||||
|
use ::rltk::{Point, RandomNumberGenerator};
|
||||||
|
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
|
|
||||||
register_components(&mut state);
|
register_components(&mut state);
|
||||||
@ -176,8 +178,8 @@ fn init_state() -> State {
|
|||||||
|
|
||||||
state.ecs.insert(MasterDungeonMap::new());
|
state.ecs.insert(MasterDungeonMap::new());
|
||||||
state.ecs.insert(Map::new(1, 64, 64, "New Map"));
|
state.ecs.insert(Map::new(1, 64, 64, "New Map"));
|
||||||
state.ecs.insert(::rltk::Point::zero());
|
state.ecs.insert(Point::zero());
|
||||||
state.ecs.insert(::rltk::RandomNumberGenerator::new());
|
state.ecs.insert(RandomNumberGenerator::new());
|
||||||
|
|
||||||
let player_entity = spawner::player(&mut state.ecs, 0, 0);
|
let player_entity = spawner::player(&mut state.ecs, 0, 0);
|
||||||
state.ecs.insert(player_entity);
|
state.ecs.insert(player_entity);
|
||||||
@ -193,10 +195,12 @@ fn init_state() -> State {
|
|||||||
|
|
||||||
/// The entry point
|
/// The entry point
|
||||||
fn main() -> ::rltk::BError {
|
fn main() -> ::rltk::BError {
|
||||||
let context = ::rltk::RltkBuilder::simple(80, 60)
|
use ::rltk::{main_loop, RltkBuilder};
|
||||||
|
|
||||||
|
let context = RltkBuilder::simple(80, 60)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_title("Roguelike Tutorial")
|
.with_title("Roguelike Tutorial")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
::rltk::main_loop(context, init_state())
|
main_loop(context, init_state())
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ pub fn save_game(ecs: &mut World) {
|
|||||||
.with(DMSerializationHelper {
|
.with(DMSerializationHelper {
|
||||||
map: dungeon_master,
|
map: dungeon_master,
|
||||||
log: crate::gamelog::clone_log(),
|
log: crate::gamelog::clone_log(),
|
||||||
|
events: crate::gamelog::clone_events(),
|
||||||
})
|
})
|
||||||
.marked::<SimpleMarker<SerializeMe>>()
|
.marked::<SimpleMarker<SerializeMe>>()
|
||||||
.build();
|
.build();
|
||||||
@ -300,6 +301,7 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
*dungeon_master = h.map.clone();
|
*dungeon_master = h.map.clone();
|
||||||
deleteme2 = Some(e);
|
deleteme2 = Some(e);
|
||||||
crate::gamelog::restore_log(&mut h.log.clone());
|
crate::gamelog::restore_log(&mut h.log.clone());
|
||||||
|
crate::gamelog::load_events(h.events.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (e, _p, pos) in (&entities, &player, &position).join() {
|
for (e, _p, pos) in (&entities, &player, &position).join() {
|
||||||
|
@ -169,6 +169,8 @@ impl State {
|
|||||||
gamelog::line("Welcome to")
|
gamelog::line("Welcome to")
|
||||||
.append_color(colors::CYAN, "Rusty Roguelike")
|
.append_color(colors::CYAN, "Rusty Roguelike")
|
||||||
.log();
|
.log();
|
||||||
|
|
||||||
|
gamelog::clear_events();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,6 +221,9 @@ impl GameState for State {
|
|||||||
}
|
}
|
||||||
RunState::AwaitingInput => {
|
RunState::AwaitingInput => {
|
||||||
newrunstate = player_input(self, ctx);
|
newrunstate = player_input(self, ctx);
|
||||||
|
if newrunstate != RunState::AwaitingInput {
|
||||||
|
crate::gamelog::record_event("Turn", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RunState::Ticking => {
|
RunState::Ticking => {
|
||||||
let mut should_change_target = false;
|
let mut should_change_target = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user