Refactor all game log useage to use the new system

This commit is contained in:
Timothy Warren 2022-02-01 10:39:46 -05:00
parent 88fc0dbcea
commit a3f6c7b9d0
22 changed files with 163 additions and 164 deletions

View File

@ -6,8 +6,8 @@ use crate::components::{
AttributeBonus, Attributes, EquipmentChanged, Equipped, InBackpack, Item, Pools, Slow,
StatusEffect,
};
use crate::game_log::GameLog;
use crate::gamesystem::attr_bonus;
use crate::{colors, gamelog};
pub struct EncumbranceSystem {}
@ -22,7 +22,6 @@ impl<'a> System<'a> for EncumbranceSystem {
WriteStorage<'a, Pools>,
WriteStorage<'a, Attributes>,
ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>,
ReadStorage<'a, AttributeBonus>,
ReadStorage<'a, StatusEffect>,
ReadStorage<'a, Slow>,
@ -38,7 +37,6 @@ impl<'a> System<'a> for EncumbranceSystem {
mut pools,
mut attributes,
player,
mut gamelog,
attrbonus,
statuses,
slowed,
@ -133,7 +131,8 @@ impl<'a> System<'a> for EncumbranceSystem {
// Overburdened
pool.total_initiative_penalty += 4.0;
if *entity == *player {
gamelog.append(
gamelog::log_color_line(
colors::ORANGE,
"You are overburdened, and suffering an initiative penalty.",
);
}

View File

@ -2,14 +2,13 @@ use ::rltk::{Point, RandomNumberGenerator};
use ::specs::prelude::*;
use crate::components::{MyTurn, Name, Quips, Viewshed};
use crate::game_log::GameLog;
use crate::{colors, gamelog};
pub struct QuipSystem {}
impl<'a> System<'a> for QuipSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
WriteExpect<'a, GameLog>,
WriteStorage<'a, Quips>,
ReadStorage<'a, Name>,
ReadStorage<'a, MyTurn>,
@ -19,7 +18,7 @@ impl<'a> System<'a> for QuipSystem {
);
fn run(&mut self, data: Self::SystemData) {
let (mut gamelog, mut quips, names, turns, player_pos, viewsheds, mut rng) = data;
let (mut quips, names, turns, player_pos, viewsheds, mut rng) = data;
for (quip, name, viewshed, _turn) in (&mut quips, &names, &viewsheds, &turns).join() {
if !quip.available.is_empty()
@ -32,10 +31,10 @@ impl<'a> System<'a> for QuipSystem {
(rng.roll_dice(1, quip.available.len() as i32) - 1) as usize
};
gamelog.append(format!(
"{} says \"{}\"",
name.name, quip.available[quip_index]
));
gamelog::color_line(colors::YELLOW, &name.name)
.append_white("says")
.append_color(colors::CYAN, &quip.available[quip_index])
.log();
quip.available.remove(quip_index);
}

View File

@ -5,9 +5,8 @@ use crate::components::{
AreaOfEffect, Equipped, InBackpack, LootTable, Name, OnDeath, Player, Pools, Position,
};
use crate::effects::*;
use crate::game_log::GameLog;
use crate::raws::{self, SpawnType, RAWS};
use crate::{Map, RunState};
use crate::{colors, gamelog, Map, RunState};
pub fn delete_the_dead(ecs: &mut World) {
let mut dead: Vec<Entity> = Vec::new();
@ -18,14 +17,15 @@ pub fn delete_the_dead(ecs: &mut World) {
let players = ecs.read_storage::<Player>();
let names = ecs.read_storage::<Name>();
let entities = ecs.entities();
let mut log = ecs.write_resource::<GameLog>();
for (entity, stats) in (&entities, &combat_stats).join() {
if stats.hit_points.current < 1 {
match players.get(entity) {
None => {
if let Some(victim_name) = names.get(entity) {
log.append(format!("{} is dead", &victim_name.name));
gamelog::color_line(colors::RED, &victim_name.name)
.append("is dead!")
.log();
}
dead.push(entity)

View File

@ -7,7 +7,7 @@ use crate::components::{
Attributes, Confusion, DamageOverTime, Duration, Name, Player, Pools, SerializeMe, Skills, Slow,
};
use crate::gamesystem::{mana_at_level, player_hp_at_level};
use crate::{colors, EquipmentChanged, GameLog, Map, StatusEffect};
use crate::{colors, gamelog, EquipmentChanged, Map, StatusEffect};
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
let mut pools = ecs.write_storage::<Pools>();
@ -69,7 +69,6 @@ pub fn death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
}
if xp_gain != 0 || gold_gain != 0.0 {
let mut log = ecs.fetch_mut::<GameLog>();
let mut player_stats = pools.get_mut(source).unwrap();
let mut player_attributes = attributes.get_mut(source).unwrap();
player_stats.xp += xp_gain;
@ -77,29 +76,28 @@ pub fn death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
if player_stats.xp >= player_stats.level * 1000 {
// We've gone up a level!
player_stats.level += 1;
log.append(format!(
"Congratulations, you are now level {}",
player_stats.level
));
gamelog::color_line(colors::MAGENTA, "Congratulations, you are now level")
.append(format!("{}", player_stats.level))
.log();
// Improve a random attribute
let mut rng = ecs.fetch_mut::<RandomNumberGenerator>();
match rng.roll_dice(1, 4) {
1 => {
player_attributes.might.base += 1;
log.append("You feel stronger!");
gamelog::log_color_line(colors::GREEN, "You feel stronger!");
}
2 => {
player_attributes.fitness.base += 1;
log.append("You feel healthier!");
gamelog::log_color_line(colors::GREEN, "You feel healthier!");
}
3 => {
player_attributes.quickness.base += 1;
log.append("You feel quicker!");
gamelog::log_color_line(colors::GREEN, "You feel quicker!");
}
_ => {
player_attributes.intelligence.base += 1;
log.append("You feel smarter!");
gamelog::log_color_line(colors::GREEN, "You feel smarter!");
}
}

View File

@ -11,18 +11,19 @@ use crate::components::{
};
use crate::effects::{aoe_tiles, entity_position, targeting};
use crate::raws::find_spell_entity;
use crate::{colors, GameLog, Map, RunState};
use crate::{colors, gamelog, Map, RunState};
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
// Check charges
if let Some(c) = ecs.write_storage::<Consumable>().get_mut(item) {
if c.charges < 1 {
// Cancel
let mut gamelog = ecs.fetch_mut::<GameLog>();
gamelog.append(format!(
"{} is out of charges!",
ecs.read_storage::<Name>().get(item).unwrap().name
));
gamelog::color_line(
colors::CYAN,
&ecs.read_storage::<Name>().get(item).unwrap().name,
)
.append_white("is out of charges!")
.log();
return;
} else {
@ -114,7 +115,6 @@ fn event_trigger(
ecs: &mut World,
) -> bool {
let mut did_something = false;
let mut gamelog = ecs.fetch_mut::<GameLog>();
// Simple particle spawn
if let Some(part) = ecs.read_storage::<SpawnParticleBurst>().get(entity) {
@ -158,7 +158,9 @@ fn event_trigger(
if ecs.read_storage::<ProvidesFood>().get(entity).is_some() {
add_effect(creator, EffectType::WellFed, targets.clone());
let names = ecs.read_storage::<Name>();
gamelog.append(format!("You eat the {}.", names.get(entity).unwrap().name));
gamelog::line("You eat the")
.append_color(colors::CYAN, &names.get(entity).unwrap().name)
.log();
did_something = true;
}
@ -166,7 +168,7 @@ fn event_trigger(
// Magic mapper
if ecs.read_storage::<MagicMapper>().get(entity).is_some() {
let mut runstate = ecs.fetch_mut::<RunState>();
gamelog.append("The map is revealed to you!");
gamelog::log_line("The map is revealed to you!");
*runstate = RunState::MagicMapReveal { row: 0 };
did_something = true;
@ -200,9 +202,9 @@ fn event_trigger(
if ecs.read_storage::<TownPortal>().get(entity).is_some() {
let map = ecs.fetch::<Map>();
if map.depth == 1 {
gamelog.append("You are already in town, so the scroll does nothing.");
gamelog::log_line("You are already in town, so the scroll does nothing.");
} else {
gamelog.append("You are teleported back to town!");
gamelog::log_line("You are teleported back to town!");
let mut runstate = ecs.fetch_mut::<RunState>();
*runstate = RunState::TownPortal;

View File

@ -15,6 +15,22 @@ pub fn line<T: ToString>(text: T) -> Logger {
Logger::new().append(text)
}
/// Convenience method to create a new [`Logger`] and
/// immediately append text of the given color
pub fn color_line<T: ToString>(color: RGB, text: T) -> Logger {
Logger::new().append_color(color, text)
}
/// Convenience function to log a simple line of white text
pub fn log_line<T: ToString>(text: T) {
line(text).log();
}
/// Convenience function to log a line of one color
pub fn log_color_line<T: ToString>(color: RGB, text: T) {
color_line(color, text).log();
}
impl Logger {
pub fn new() -> Self {
Logger {
@ -52,10 +68,15 @@ impl Logger {
}
/// Convenience method to append text with a new color
pub fn append_color<T: ToString>(mut self, color: RGB, text: T) -> Self {
pub fn append_color<T: ToString>(self, color: RGB, text: T) -> Self {
self.color(color).append(text)
}
/// Convenience method to append white text after the text has had a different color
pub fn append_white<T: ToString>(self, text: T) -> Self {
self.append_color(colors::WHITE, text)
}
/// Append the current line to the log output
pub fn log(self) {
append_entry(self.fragments);

View File

@ -8,6 +8,7 @@ lazy_static! {
static ref LOG: Mutex<Vec<Vec<LogFragment>>> = Mutex::new(Vec::new());
}
#[allow(dead_code)]
pub fn append_fragment(fragment: LogFragment) {
LOG.lock().unwrap().push(vec![fragment]);
}

View File

@ -16,7 +16,7 @@ use crate::components::{
InBackpack, KnownSpells, MagicItem, MagicItemClass, Name, ObfuscatedName, Pools, StatusEffect,
Viewshed, Weapon,
};
use crate::{camera, colors, game_log, Map, MasterDungeonMap, State};
use crate::{camera, colors, gamelog, Map, MasterDungeonMap, State};
pub fn get_item_color(ecs: &World, item: Entity) -> RGB {
let dm = ecs.fetch::<crate::map::MasterDungeonMap>();
@ -326,7 +326,9 @@ pub fn draw_ui(ecs: &World, ctx: &mut Rltk) {
// Draw the log
let mut block = TextBlock::new(1, 46, 79, 58);
block.print(&game_log::log_display());
block
.print(&gamelog::log_display())
.expect("Failed to print game log.");
block.render(&mut ::rltk::BACKEND_INTERNAL.lock().consoles[0].console);
draw_tooltips(ecs, ctx);

View File

@ -1,8 +1,9 @@
use ::specs::prelude::*;
use crate::colors;
use crate::components::{HungerClock, HungerState, MyTurn};
use crate::effects::{add_effect, EffectType, Targets};
use crate::game_log::GameLog;
use crate::gamelog::log_color_line;
pub struct HungerSystem {}
@ -12,12 +13,11 @@ impl<'a> System<'a> for HungerSystem {
Entities<'a>,
WriteStorage<'a, HungerClock>,
ReadExpect<'a, Entity>, // The player
WriteExpect<'a, GameLog>,
ReadStorage<'a, MyTurn>,
);
fn run(&mut self, data: Self::SystemData) {
let (entities, mut hunger_clock, player_entity, mut log, turns) = data;
let (entities, mut hunger_clock, player_entity, turns) = data;
for (entity, mut clock, _myturn) in (&entities, &mut hunger_clock, &turns).join() {
clock.duration -= 1;
@ -29,7 +29,7 @@ impl<'a> System<'a> for HungerSystem {
clock.duration = 200;
if entity == *player_entity {
log.append("You are no longer well fed.");
log_color_line(colors::ORANGE, "You are no longer well fed");
}
}
HungerState::Normal => {
@ -37,7 +37,7 @@ impl<'a> System<'a> for HungerSystem {
clock.duration = 200;
if entity == *player_entity {
log.append("You are hungry.");
log_color_line(colors::ORANGE, "You are hungry.");
}
}
HungerState::Hungry => {
@ -45,13 +45,13 @@ impl<'a> System<'a> for HungerSystem {
clock.duration = 200;
if entity == *player_entity {
log.append("You are starving!");
log_color_line(colors::RED, "You are starving!");
}
}
HungerState::Starving => {
// Inflict damage from hunger
if entity == *player_entity {
log.append("Your hunger pangs are getting painful!");
log_color_line(colors::RED, "Your hunger pangs are getting painful!");
}
add_effect(

View File

@ -1,16 +1,16 @@
mod collection_system;
mod drop_system;
mod equip_use;
mod identification_system;
mod remove_system;
mod use_equip;
mod use_system;
use ::specs::prelude::*;
pub use collection_system::ItemCollectionSystem;
pub use drop_system::ItemDropSystem;
pub use equip_use::ItemEquipOnUse;
pub use identification_system::ItemIdentificationSystem;
pub use remove_system::ItemRemoveSystem;
pub use use_equip::ItemEquipOnUse;
pub use use_system::{ItemUseSystem, SpellUseSystem};
use crate::components::{MagicItem, Name, ObfuscatedName};

View File

@ -4,8 +4,7 @@ use super::obfuscate_name;
use crate::components::{
EquipmentChanged, InBackpack, MagicItem, Name, ObfuscatedName, Position, WantsToPickupItem,
};
use crate::game_log::GameLog;
use crate::MasterDungeonMap;
use crate::{colors, gamelog, MasterDungeonMap};
pub struct ItemCollectionSystem {}
@ -13,7 +12,6 @@ impl<'a> System<'a> for ItemCollectionSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>,
WriteStorage<'a, WantsToPickupItem>,
WriteStorage<'a, Position>,
ReadStorage<'a, Name>,
@ -27,7 +25,6 @@ impl<'a> System<'a> for ItemCollectionSystem {
fn run(&mut self, data: Self::SystemData) {
let (
player_entity,
mut gamelog,
mut wants_pickup,
mut positions,
names,
@ -53,10 +50,12 @@ impl<'a> System<'a> for ItemCollectionSystem {
.expect("Unable to insert equipment change");
if pickup.collected_by == *player_entity {
gamelog.append(format!(
"You pick up the {}.",
obfuscate_name(pickup.item, &names, &magic_items, &obfuscated_names, &dm)
));
gamelog::line("You pick up the")
.append_color(
colors::CYAN,
obfuscate_name(pickup.item, &names, &magic_items, &obfuscated_names, &dm),
)
.log();
}
}

View File

@ -4,8 +4,7 @@ use super::obfuscate_name;
use crate::components::{
EquipmentChanged, InBackpack, MagicItem, Name, ObfuscatedName, Position, WantsToDropItem,
};
use crate::game_log::GameLog;
use crate::MasterDungeonMap;
use crate::{colors, gamelog, MasterDungeonMap};
pub struct ItemDropSystem {}
@ -13,7 +12,6 @@ impl<'a> System<'a> for ItemDropSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>,
Entities<'a>,
WriteStorage<'a, WantsToDropItem>,
ReadStorage<'a, Name>,
@ -28,7 +26,6 @@ impl<'a> System<'a> for ItemDropSystem {
fn run(&mut self, data: Self::SystemData) {
let (
player_entity,
mut gamelog,
entities,
mut wants_drop,
names,
@ -65,10 +62,12 @@ impl<'a> System<'a> for ItemDropSystem {
.expect("Unable to insert equipment change");
if entity == *player_entity {
gamelog.append(format!(
"You drop the {}.",
obfuscate_name(to_drop.item, &names, &magic_items, &obfuscated_names, &dm)
));
gamelog::line("You drop the")
.append_color(
colors::CYAN,
obfuscate_name(to_drop.item, &names, &magic_items, &obfuscated_names, &dm),
)
.log();
}
}

View File

@ -4,7 +4,7 @@ use crate::components::{
CursedItem, EquipmentChanged, Equippable, Equipped, IdentifiedItem, InBackpack, Name,
WantsToUseItem,
};
use crate::GameLog;
use crate::{colors, gamelog};
pub struct ItemEquipOnUse {}
@ -12,7 +12,6 @@ impl<'a> System<'a> for ItemEquipOnUse {
#[allow(clippy::type_complexity)]
type SystemData = (
ReadExpect<'a, Entity>,
WriteExpect<'a, GameLog>,
Entities<'a>,
WriteStorage<'a, WantsToUseItem>,
ReadStorage<'a, Name>,
@ -27,7 +26,6 @@ impl<'a> System<'a> for ItemEquipOnUse {
fn run(&mut self, data: Self::SystemData) {
let (
player_entity,
mut gamelog,
entities,
mut wants_use,
names,
@ -48,18 +46,19 @@ impl<'a> System<'a> for ItemEquipOnUse {
// Remove any items the target has in the item's slot
let mut can_equip = true;
let mut log_entries: Vec<String> = Vec::new();
let mut to_unequip = Vec::new();
for (item_entity, already_equipped, name) in (&entities, &equipped, &names).join() {
if already_equipped.owner == target && already_equipped.slot == target_slot {
if cursed.get(item_entity).is_some() {
gamelog::line("You cannot un-equip")
.append_color(colors::CYAN, &name.name)
.append_white("- it is cursed!")
.log();
can_equip = false;
gamelog
.append(format!("You cannot un-equip {}, it is cursed.", name.name))
} else {
to_unequip.push(item_entity);
if target == *player_entity {
log_entries.push(format!("You un-equip {}.", name.name));
gamelog::log_line(format!("You un-equip {}.", name.name));
}
}
}
@ -85,10 +84,6 @@ impl<'a> System<'a> for ItemEquipOnUse {
.expect("Unable to move equipped item to backpack.");
}
for entry in log_entries.iter() {
gamelog.append(entry);
}
// Wield the item
equipped
.insert(
@ -101,7 +96,7 @@ impl<'a> System<'a> for ItemEquipOnUse {
.expect("Unable to equip item");
backpack.remove(useitem.item);
if target == *player_entity {
gamelog.append(format!(
gamelog::log_line(format!(
"You equip {}.",
names.get(useitem.item).unwrap().name
));

View File

@ -1,7 +1,7 @@
use ::specs::prelude::*;
use crate::components::{CursedItem, Equipped, InBackpack, Name, WantsToRemoveItem};
use crate::GameLog;
use crate::{colors, gamelog};
pub struct ItemRemoveSystem {}
@ -13,20 +13,18 @@ impl<'a> System<'a> for ItemRemoveSystem {
WriteStorage<'a, Equipped>,
WriteStorage<'a, InBackpack>,
ReadStorage<'a, CursedItem>,
WriteExpect<'a, GameLog>,
ReadStorage<'a, Name>,
);
fn run(&mut self, data: Self::SystemData) {
let (entities, mut wants_remove, mut equipped, mut backpack, cursed, mut gamelog, names) =
data;
let (entities, mut wants_remove, mut equipped, mut backpack, cursed, names) = data;
for (entity, to_remove) in (&entities, &wants_remove).join() {
if cursed.get(to_remove.item).is_some() {
gamelog.append(format!(
"You cannot remove {}, it is cursed",
names.get(to_remove.item).unwrap().name
));
gamelog::line("You cannot remove")
.append_color(colors::CYAN, &names.get(to_remove.item).unwrap().name)
.append_white(" - it is cursed.")
.log();
continue;
}

View File

@ -10,7 +10,7 @@ mod colors;
mod components;
mod damage_system;
mod effects;
mod game_log;
mod gamelog;
mod gamesystem;
mod gui;
mod hunger_system;

View File

@ -1,14 +1,13 @@
use ::rltk::RandomNumberGenerator;
use ::specs::prelude::*;
use crate::colors;
use crate::components::{
Attributes, EquipmentSlot, Equipped, HungerClock, HungerState, Name, NaturalAttackDefense,
Pools, Skill, Skills, WantsToMelee, Weapon, WeaponAttribute, Wearable,
};
use crate::effects::{add_effect, EffectType, Targets};
use crate::game_log::GameLog;
use crate::gamesystem::skill_bonus;
use crate::{colors, gamelog};
pub struct MeleeCombatSystem {}
@ -16,7 +15,6 @@ impl<'a> System<'a> for MeleeCombatSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
Entities<'a>,
WriteExpect<'a, GameLog>,
WriteStorage<'a, WantsToMelee>,
ReadStorage<'a, Name>,
ReadStorage<'a, Attributes>,
@ -33,7 +31,6 @@ impl<'a> System<'a> for MeleeCombatSystem {
fn run(&mut self, data: Self::SystemData) {
let (
entities,
mut log,
mut wants_melee,
names,
attributes,
@ -163,10 +160,13 @@ impl<'a> System<'a> for MeleeCombatSystem {
target: wants_melee.target,
},
);
log.append(format!(
"{} hits {} for {} hp.",
&name.name, &target_name.name, damage
));
gamelog::color_line(colors::YELLOW, &name.name)
.append_white("hits")
.append_color(colors::YELLOW, &target_name.name)
.append_white("for")
.append_color(colors::RED, format!("{}", damage))
.append_white("hp.")
.log();
// Proc effects
if let Some(chance) = &weapon_info.proc_chance {
@ -189,10 +189,11 @@ impl<'a> System<'a> for MeleeCombatSystem {
}
} else if natural_roll == 1 {
// Natural 1 miss
log.append(format!(
"{} considers attacking {}, but misjudges the timing.",
name.name, target_name.name
));
gamelog::color_line(colors::CYAN, &name.name)
.append_white("considers attacking")
.append_color(colors::CYAN, &target_name.name)
.append_white("but misjudges the timing!")
.log();
add_effect(
None,
EffectType::Particle {
@ -207,10 +208,11 @@ impl<'a> System<'a> for MeleeCombatSystem {
);
} else {
// Miss
log.append(format!(
"{} attacks {}, but can't connect",
name.name, target_name.name
));
gamelog::color_line(colors::CYAN, &name.name)
.append_white("attacks")
.append_color(colors::CYAN, &target_name.name)
.append_white("but can't connect.")
.log();
add_effect(
None,
EffectType::Particle {

View File

@ -1,6 +1,6 @@
use std::cmp::{max, min};
use rltk::{DistanceAlg, Point, Rltk, VirtualKeyCode};
use rltk::{DistanceAlg, Point, RandomNumberGenerator, Rltk, VirtualKeyCode};
use specs::prelude::*;
use crate::components::{
@ -8,9 +8,10 @@ use crate::components::{
HungerState, Item, Name, Player, Pools, Position, Renderable, Target, Vendor, Viewshed,
WantsToMelee, WantsToPickupItem, WantsToShoot,
};
use crate::game_log::GameLog;
use crate::raws::{self, Reaction, RAWS};
use crate::{spatial, Map, RunState, State, TileType, VendorMode, WantsToCastSpell, Weapon};
use crate::{
colors, gamelog, spatial, Map, RunState, State, TileType, VendorMode, WantsToCastSpell, Weapon,
};
fn get_player_target_list(ecs: &mut World) -> Vec<(f32, Entity)> {
let mut possible_targets = Vec::new();
@ -68,7 +69,6 @@ fn fire_on_target(ecs: &mut World) -> RunState {
let targets = ecs.write_storage::<Target>();
let entities = ecs.entities();
let mut current_target: Option<Entity> = None;
let mut log = ecs.fetch_mut::<GameLog>();
for (e, _t) in (&entities, &targets).join() {
current_target = Some(e);
@ -79,7 +79,9 @@ fn fire_on_target(ecs: &mut World) -> RunState {
let mut shoot_store = ecs.write_storage::<WantsToShoot>();
let names = ecs.read_storage::<Name>();
if let Some(name) = names.get(target) {
log.entries.push(format!("You fire at {}", name.name));
gamelog::line("You fire at")
.append_color(colors::CYAN, &name.name)
.log();
}
shoot_store
.insert(*player_entity, WantsToShoot { target })
@ -87,8 +89,7 @@ fn fire_on_target(ecs: &mut World) -> RunState {
RunState::Ticking
} else {
log.entries
.push("You don't have a target selected!".to_string());
gamelog::log_line("You don't have a target selected!");
RunState::AwaitingInput
}
}
@ -269,10 +270,7 @@ pub fn try_next_level(ecs: &mut World) -> bool {
if map.tiles[player_idx] == TileType::DownStairs {
true
} else {
let mut gamelog = ecs.fetch_mut::<GameLog>();
gamelog
.entries
.push("There is no way down from here.".to_string());
gamelog::log_line("There is no way down from here.");
false
}
}
@ -285,10 +283,7 @@ pub fn try_previous_level(ecs: &mut World) -> bool {
if map.tiles[player_idx] == TileType::UpStairs {
true
} else {
let mut gamelog = ecs.fetch_mut::<GameLog>();
gamelog
.entries
.push("There is no way up from here.".to_string());
gamelog::log_line("There is no way up from here.");
false
}
}
@ -299,7 +294,6 @@ fn get_item(ecs: &mut World) {
let entities = ecs.entities();
let items = ecs.read_storage::<Item>();
let positions = ecs.read_storage::<Position>();
let mut gamelog = ecs.fetch_mut::<GameLog>();
let mut target_item: Option<Entity> = None;
for (item_entity, _item, position) in (&entities, &items, &positions).join() {
@ -309,9 +303,7 @@ fn get_item(ecs: &mut World) {
}
match target_item {
None => gamelog
.entries
.push("There is nothing here to pick up.".to_string()),
None => gamelog::log_line("There is nothing here to pick up."),
Some(item) => {
let mut pickup = ecs.write_storage::<WantsToPickupItem>();
pickup
@ -365,7 +357,7 @@ fn skip_turn(ecs: &mut World) -> RunState {
let pools = health_components.get_mut(*player_entity).unwrap();
pools.hit_points.current = i32::min(pools.hit_points.current + 1, pools.hit_points.max);
let mut rng = ecs.fetch_mut::<::rltk::RandomNumberGenerator>();
let mut rng = ecs.fetch_mut::<RandomNumberGenerator>();
if rng.roll_dice(1, 6) == 1 {
pools.mana.current = i32::min(pools.mana.current + 1, pools.mana.max);
}
@ -454,8 +446,7 @@ fn use_spell_hotkey(gs: &mut State, key: i32) -> RunState {
return RunState::Ticking;
}
} else {
let mut gamelog = gs.ecs.fetch_mut::<GameLog>();
gamelog.append("You don't have enough mana to cast that!");
gamelog::log_line("You don't have enough mana to cast that!");
}
}

View File

@ -6,9 +6,8 @@ use crate::components::{
Pools, Position, Skill, Skills, WantsToShoot, Weapon, WeaponAttribute, Wearable,
};
use crate::effects::{add_effect, EffectType, Targets};
use crate::game_log::GameLog;
use crate::gamesystem::skill_bonus;
use crate::{colors, Map};
use crate::{colors, gamelog, Map};
pub struct RangedCombatSystem {}
@ -16,7 +15,6 @@ impl<'a> System<'a> for RangedCombatSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
Entities<'a>,
WriteExpect<'a, GameLog>,
WriteStorage<'a, WantsToShoot>,
ReadStorage<'a, Name>,
ReadStorage<'a, Attributes>,
@ -35,7 +33,6 @@ impl<'a> System<'a> for RangedCombatSystem {
fn run(&mut self, data: Self::SystemData) {
let (
entities,
mut log,
mut wants_shoot,
names,
attributes,
@ -188,11 +185,13 @@ impl<'a> System<'a> for RangedCombatSystem {
target: wants_shoot.target,
},
);
log.append(format!(
"{} hits {} for {} hp.",
&name.name, &target_name.name, damage
));
gamelog::color_line(colors::YELLOW, &name.name)
.append_white("hits")
.append_color(colors::YELLOW, &target_name.name)
.append_white("for")
.append_color(colors::RED, format!("{}", damage))
.append_white("hp.")
.log();
// Proc effects
if let Some(chance) = &weapon_info.proc_chance {
if rng.roll_dice(1, 100) <= (chance * 100.0) as i32 {
@ -214,10 +213,11 @@ impl<'a> System<'a> for RangedCombatSystem {
}
} else if natural_roll == 1 {
// Natural 1 miss
log.append(format!(
"{} considers attacking {}, but misjudges the timing.",
name.name, target_name.name
));
gamelog::color_line(colors::CYAN, &name.name)
.append_white("considers attacking")
.append_color(colors::CYAN, &target_name.name)
.append_white("but misjudges the timing!")
.log();
add_effect(
None,
EffectType::Particle {
@ -232,10 +232,11 @@ impl<'a> System<'a> for RangedCombatSystem {
);
} else {
// Miss
log.append(format!(
"{} attacks {}, but can't connect",
name.name, target_name.name
));
gamelog::color_line(colors::CYAN, &name.name)
.append_white("attacks")
.append_color(colors::CYAN, &target_name.name)
.append_white("but can't connect.")
.log();
add_effect(
None,
EffectType::Particle {

View File

@ -20,7 +20,9 @@ use crate::ranged_combat_system::RangedCombatSystem;
use crate::raws::*;
use crate::trigger_system::TriggerSystem;
use crate::visibility_system::VisibilitySystem;
use crate::{ai, camera, damage_system, effects, game_log, player, saveload_system, spawner};
use crate::{
ai, camera, colors, damage_system, effects, gamelog, player, saveload_system, spawner,
};
/// Whether to show a visual representation of map generation
pub const SHOW_MAPGEN_VISUALIZER: bool = false;
@ -122,8 +124,7 @@ impl State {
self.generate_world_map(current_depth + offset, offset);
// Notify the player
let mut gamelog = self.ecs.fetch_mut::<GameLog>();
gamelog.append("You change level.");
gamelog::log_line("You change level.");
}
fn game_over_cleanup(&mut self) {
@ -164,8 +165,8 @@ impl State {
}
// Set up the game log
game_log::clear_log();
game_log::line("Welcome to")
gamelog::clear_log();
gamelog::line("Welcome to")
.append_color(colors::CYAN, "Rusty Roguelike")
.log();
}

View File

@ -2,8 +2,7 @@ use ::specs::prelude::*;
use crate::components::{AreaOfEffect, EntityMoved, EntryTrigger, Name, Position};
use crate::effects::{add_effect, aoe_tiles, EffectType, Targets};
use crate::game_log::GameLog;
use crate::{spatial, Map};
use crate::{colors, gamelog, spatial, Map};
pub struct TriggerSystem {}
@ -16,21 +15,12 @@ impl<'a> System<'a> for TriggerSystem {
ReadStorage<'a, EntryTrigger>,
ReadStorage<'a, Name>,
Entities<'a>,
WriteExpect<'a, GameLog>,
ReadStorage<'a, AreaOfEffect>,
);
fn run(&mut self, data: Self::SystemData) {
let (
map,
mut entity_moved,
position,
entry_trigger,
names,
entities,
mut log,
area_of_effect,
) = data;
let (map, mut entity_moved, position, entry_trigger, names, entities, area_of_effect) =
data;
// Iterate the entities that moved and their final position
for (entity, mut _entity_moved, pos) in (&entities, &mut entity_moved, &position).join() {
@ -44,7 +34,9 @@ impl<'a> System<'a> for TriggerSystem {
Some(_trigger) => {
// We triggered it
if let Some(name) = names.get(entity_id) {
log.append(format!("{} triggers!", &name.name));
gamelog::color_line(colors::RED, &name.name)
.append_white("triggers!")
.log();
}
// Call the effects system

View File

@ -2,8 +2,7 @@ use ::rltk::{field_of_view, Point, RandomNumberGenerator};
use ::specs::prelude::*;
use crate::components::{BlocksVisibility, Hidden, Name};
use crate::game_log::GameLog;
use crate::{spatial, Map, Player, Position, Viewshed};
use crate::{colors, gamelog, spatial, Map, Player, Position, Viewshed};
pub struct VisibilitySystem {}
@ -17,7 +16,6 @@ impl<'a> System<'a> for VisibilitySystem {
ReadStorage<'a, Player>,
WriteStorage<'a, Hidden>,
WriteExpect<'a, RandomNumberGenerator>,
WriteExpect<'a, GameLog>,
ReadStorage<'a, Name>,
ReadStorage<'a, BlocksVisibility>,
);
@ -31,7 +29,6 @@ impl<'a> System<'a> for VisibilitySystem {
player,
mut hidden,
mut rng,
mut log,
names,
blocks_visibility,
) = data;
@ -70,7 +67,9 @@ impl<'a> System<'a> for VisibilitySystem {
if rng.roll_dice(1, 24) == 1 {
let name = names.get(e);
if let Some(name) = name {
log.entries.push(format!("You spotted a {}.", &name.name));
gamelog::line("You spotted:")
.append_color(colors::RED, &name.name)
.log();
}
hidden.remove(e);
}