initial
This commit is contained in:
parent
85881db62f
commit
4f899d329e
9 changed files with 121 additions and 67 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use super::{gamelog::GameLog, CombatStats, Entities, Item, Map, Name, Player, Position, SufferDamage};
|
||||
use super::{gamelog, CombatStats, Entities, Item, Map, Name, Player, Position, SufferDamage};
|
||||
use specs::prelude::*;
|
||||
|
||||
pub struct DamageSystem {}
|
||||
|
|
@ -37,7 +37,6 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
let names = ecs.read_storage::<Name>();
|
||||
let items = ecs.read_storage::<Item>();
|
||||
let entities = ecs.entities();
|
||||
let mut log = ecs.write_resource::<GameLog>();
|
||||
for (entity, stats) in (&entities, &combat_stats).join() {
|
||||
if stats.hp < 1 {
|
||||
let player = players.get(entity);
|
||||
|
|
@ -47,9 +46,19 @@ pub fn delete_the_dead(ecs: &mut World) {
|
|||
if let Some(victim_name) = victim_name {
|
||||
let item = items.get(entity);
|
||||
if let Some(_item) = item {
|
||||
log.entries.push(format!("{} was destroyed!", &victim_name.name));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.npc_name(&victim_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("was destroyed.")
|
||||
.log();
|
||||
} else {
|
||||
log.entries.push(format!("The {} died!", &victim_name.name));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.npc_name(&victim_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("died.")
|
||||
.log();
|
||||
}
|
||||
}
|
||||
dead.push(entity)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,21 @@ impl Logger {
|
|||
}
|
||||
|
||||
pub fn log(self) {
|
||||
append_entry(self.fragments)
|
||||
return append_entry(self.fragments);
|
||||
}
|
||||
|
||||
pub fn npc_name<T: ToString>(mut self, text: T) -> Self {
|
||||
self.fragments.push(LogFragment { colour: RGB::named(rltk::YELLOW), text: text.to_string() });
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn item_name<T: ToString>(mut self, text: T) -> Self {
|
||||
self.fragments.push(LogFragment { colour: RGB::named(rltk::CYAN), text: text.to_string() });
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn damage(mut self, damage: i32) -> Self {
|
||||
self.fragments.push(LogFragment { colour: RGB::named(rltk::RED), text: format!("{}", damage).to_string() });
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,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]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@ mod logstore;
|
|||
use logstore::*;
|
||||
pub use logstore::{clear_log, log_display};
|
||||
|
||||
pub struct GameLog {
|
||||
pub entries: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct LogFragment {
|
||||
pub colour: RGB,
|
||||
pub text: String,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use super::{
|
||||
gamelog::GameLog, CombatStats, Confusion, Consumable, Cursed, Destructible, InBackpack, InflictsDamage,
|
||||
MagicMapper, Map, Name, ParticleBuilder, Point, Position, ProvidesHealing, RunState, SufferDamage, WantsToDropItem,
|
||||
gamelog, CombatStats, Confusion, Consumable, Cursed, Destructible, InBackpack, InflictsDamage, MagicMapper, Map,
|
||||
Name, ParticleBuilder, Point, Position, ProvidesHealing, RunState, SufferDamage, WantsToDropItem,
|
||||
WantsToPickupItem, WantsToUseItem, AOE, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME,
|
||||
};
|
||||
use specs::prelude::*;
|
||||
|
|
@ -11,7 +11,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>,
|
||||
|
|
@ -19,14 +18,17 @@ impl<'a> System<'a> for ItemCollectionSystem {
|
|||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (player_entity, mut gamelog, mut wants_pickup, mut positions, names, mut backpack) = data;
|
||||
let (player_entity, mut wants_pickup, mut positions, names, mut backpack) = data;
|
||||
|
||||
for pickup in wants_pickup.join() {
|
||||
positions.remove(pickup.item);
|
||||
backpack.insert(pickup.item, InBackpack { owner: pickup.collected_by }).expect("Unable to pickup item.");
|
||||
|
||||
if pickup.collected_by == *player_entity {
|
||||
gamelog.entries.push(format!("You pick up the {}.", names.get(pickup.item).unwrap().name));
|
||||
gamelog::Logger::new()
|
||||
.append("You pick up the")
|
||||
.item_name(format!("{}.", &names.get(pickup.item).unwrap().name))
|
||||
.log();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +41,6 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
ReadExpect<'a, Entity>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
ReadExpect<'a, Map>,
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, WantsToUseItem>,
|
||||
|
|
@ -62,7 +63,6 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
player_entity,
|
||||
mut gamelog,
|
||||
map,
|
||||
entities,
|
||||
mut wants_to_use,
|
||||
|
|
@ -89,7 +89,7 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
|
||||
let is_cursed = cursed_items.get(wants_to_use.item);
|
||||
|
||||
gamelog.entries.push(format!("You use the {}.", item_being_used.name));
|
||||
gamelog::Logger::new().append("You use the").item_name(format!("{}.", &item_being_used.name)).log();
|
||||
|
||||
// TARGETING
|
||||
let mut targets: Vec<Entity> = Vec::new();
|
||||
|
|
@ -117,7 +117,12 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
if let Some(pos) = pos {
|
||||
target = Point::new(pos.x, pos.y);
|
||||
}
|
||||
gamelog.entries.push(format!("The {} disobeys!", item_being_used.name));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.item_name(&item_being_used.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("disobeys!")
|
||||
.log();
|
||||
}
|
||||
}
|
||||
// AOE
|
||||
|
|
@ -153,7 +158,13 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
if let Some(stats) = stats {
|
||||
stats.hp = i32::min(stats.max_hp, stats.hp + heal.amount);
|
||||
if entity == *player_entity {
|
||||
gamelog.entries.push(format!("Quaffing, you heal {} hp.", heal.amount));
|
||||
gamelog::Logger::new()
|
||||
.append("Quaffing, you heal")
|
||||
.colour(rltk::GREEN)
|
||||
.append(heal.amount)
|
||||
.colour(rltk::WHITE)
|
||||
.append("hit points.")
|
||||
.log();
|
||||
}
|
||||
let pos = positions.get(entity);
|
||||
if let Some(pos) = pos {
|
||||
|
|
@ -194,14 +205,25 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
None => {
|
||||
SufferDamage::new_damage(&mut suffer_damage, *mob, damage.amount);
|
||||
if entity == *player_entity {
|
||||
gamelog.entries.push(format!(
|
||||
"{} takes {} damage from the {}!",
|
||||
entity_name.name, damage.amount, item_being_used.name
|
||||
));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.npc_name(&entity_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("takes")
|
||||
.damage(damage.amount)
|
||||
.colour(rltk::WHITE)
|
||||
.append("damage from the")
|
||||
.item_name(format!("{}.", &item_being_used.name))
|
||||
.log();
|
||||
}
|
||||
}
|
||||
Some(_destructible) => {
|
||||
gamelog.entries.push(format!("{} is destroyed!", entity_name.name));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.item_name(&entity_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("is destroyed!")
|
||||
.log();
|
||||
entities.delete(*mob).expect("Delete failed");
|
||||
}
|
||||
}
|
||||
|
|
@ -237,11 +259,19 @@ impl<'a> System<'a> for ItemUseSystem {
|
|||
used_item = true;
|
||||
match is_cursed {
|
||||
None => {
|
||||
gamelog.entries.push("You feel a sense of acuity to your surroundings.".to_string());
|
||||
gamelog::Logger::new()
|
||||
.append("You feel")
|
||||
.colour(rltk::GREEN)
|
||||
.append("a sense of acuity towards your surroundings.")
|
||||
.log();
|
||||
*runstate = RunState::MagicMapReveal { row: 0, cursed: false };
|
||||
}
|
||||
Some(_) => {
|
||||
gamelog.entries.push("You forget where you just were!".to_string());
|
||||
gamelog::Logger::new()
|
||||
.append("You")
|
||||
.colour(rltk::RED)
|
||||
.append("forget where you last were.")
|
||||
.log();
|
||||
*runstate = RunState::MagicMapReveal { row: 0, cursed: true };
|
||||
}
|
||||
}
|
||||
|
|
@ -269,7 +299,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>,
|
||||
|
|
@ -278,7 +307,7 @@ impl<'a> System<'a> for ItemDropSystem {
|
|||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (player_entity, mut gamelog, entities, mut wants_drop, names, mut positions, mut backpack) = data;
|
||||
let (player_entity, entities, mut wants_drop, names, mut positions, mut backpack) = data;
|
||||
|
||||
for (entity, to_drop) in (&entities, &wants_drop).join() {
|
||||
let mut dropper_pos: Position = Position { x: 0, y: 0 };
|
||||
|
|
@ -293,7 +322,10 @@ impl<'a> System<'a> for ItemDropSystem {
|
|||
backpack.remove(to_drop.item);
|
||||
|
||||
if entity == *player_entity {
|
||||
gamelog.entries.push(format!("You drop the {}.", names.get(to_drop.item).unwrap().name));
|
||||
gamelog::Logger::new()
|
||||
.append("You drop the")
|
||||
.item_name(format!("{}.", &names.get(to_drop.item).unwrap().name))
|
||||
.log();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,8 +157,7 @@ impl State {
|
|||
}
|
||||
|
||||
// Notify player, restore health up to a point.
|
||||
let mut gamelog = self.ecs.fetch_mut::<gamelog::GameLog>();
|
||||
gamelog.entries.push("You descend the stairwell, and take a moment to recover your strength.".to_string());
|
||||
gamelog::Logger::new().append("You descend the stairwell, and take a moment to gather your strength.").log();
|
||||
let mut player_health_store = self.ecs.write_storage::<CombatStats>();
|
||||
let player_health = player_health_store.get_mut(*player_entity);
|
||||
if let Some(player_health) = player_health {
|
||||
|
|
@ -431,9 +430,7 @@ fn main() -> rltk::BError {
|
|||
gs.ecs.insert(map);
|
||||
gs.ecs.insert(Point::new(player_x, player_y));
|
||||
gs.ecs.insert(player_entity);
|
||||
gs.ecs.insert(gamelog::GameLog {
|
||||
entries: vec!["<pretend i wrote a paragraph explaining why you're here>".to_string()],
|
||||
});
|
||||
|
||||
gamelog::clear_log();
|
||||
gamelog::Logger::new()
|
||||
.append("Welcome!")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::{gamelog::GameLog, CombatStats, Name, ParticleBuilder, Position, SufferDamage, WantsToMelee};
|
||||
use super::{gamelog, CombatStats, Name, ParticleBuilder, Position, SufferDamage, WantsToMelee};
|
||||
use specs::prelude::*;
|
||||
|
||||
pub struct MeleeCombatSystem {}
|
||||
|
|
@ -6,7 +6,6 @@ pub struct MeleeCombatSystem {}
|
|||
impl<'a> System<'a> for MeleeCombatSystem {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
WriteStorage<'a, WantsToMelee>,
|
||||
ReadStorage<'a, Name>,
|
||||
ReadStorage<'a, CombatStats>,
|
||||
|
|
@ -16,16 +15,8 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
);
|
||||
|
||||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
entities,
|
||||
mut log,
|
||||
mut wants_melee,
|
||||
names,
|
||||
combat_stats,
|
||||
mut inflict_damage,
|
||||
mut particle_builder,
|
||||
positions,
|
||||
) = data;
|
||||
let (entities, mut wants_melee, names, combat_stats, mut inflict_damage, mut particle_builder, positions) =
|
||||
data;
|
||||
|
||||
for (_entity, wants_melee, name, stats) in (&entities, &wants_melee, &names, &combat_stats).join() {
|
||||
if stats.hp <= 0 {
|
||||
|
|
@ -51,9 +42,23 @@ impl<'a> System<'a> for MeleeCombatSystem {
|
|||
let damage = i32::max(0, stats.power - target_stats.defence);
|
||||
|
||||
if damage == 0 {
|
||||
log.entries.push(format!("{} is unable to hurt {}.", &name.name, &target_name.name));
|
||||
gamelog::Logger::new()
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("attempts to strike")
|
||||
.npc_name(&target_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("- but fails.")
|
||||
.log();
|
||||
} else {
|
||||
log.entries.push(format!("{} hits {} for {} damage.", &name.name, &target_name.name, damage));
|
||||
gamelog::Logger::new() // <name> hits the <name>!
|
||||
.append("The")
|
||||
.npc_name(&name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("hits the")
|
||||
.npc_name(format!("{}.", &target_name.name))
|
||||
.log();
|
||||
SufferDamage::new_damage(&mut inflict_damage, wants_melee.target, damage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
use super::{
|
||||
gamelog::GameLog, Confusion, Map, Monster, Name, ParticleBuilder, Position, RunState, Viewshed, WantsToMelee,
|
||||
};
|
||||
use super::{gamelog, Confusion, Map, Monster, Name, ParticleBuilder, Position, RunState, Viewshed, WantsToMelee};
|
||||
use rltk::Point;
|
||||
use specs::prelude::*;
|
||||
|
||||
|
|
@ -10,7 +8,6 @@ impl<'a> System<'a> for MonsterAI {
|
|||
#[allow(clippy::type_complexity)]
|
||||
type SystemData = (
|
||||
WriteExpect<'a, Map>,
|
||||
WriteExpect<'a, GameLog>,
|
||||
ReadExpect<'a, Point>,
|
||||
ReadExpect<'a, Entity>,
|
||||
ReadExpect<'a, RunState>,
|
||||
|
|
@ -27,7 +24,6 @@ impl<'a> System<'a> for MonsterAI {
|
|||
fn run(&mut self, data: Self::SystemData) {
|
||||
let (
|
||||
mut map,
|
||||
mut gamelog,
|
||||
player_pos,
|
||||
player_entity,
|
||||
runstate,
|
||||
|
|
@ -57,11 +53,15 @@ impl<'a> System<'a> for MonsterAI {
|
|||
let mut glyph = rltk::to_cp437('?');
|
||||
if i_am_confused.turns < 1 {
|
||||
confused.remove(entity);
|
||||
gamelog.entries.push(format!("{} snaps out of its confusion!", entity_name.name));
|
||||
gamelog::Logger::new()
|
||||
.npc_name(&entity_name.name)
|
||||
.colour(rltk::WHITE)
|
||||
.append("snaps out of it.")
|
||||
.log();
|
||||
fg = rltk::RGB::named(rltk::MEDIUMSLATEBLUE);
|
||||
glyph = rltk::to_cp437('!');
|
||||
} else {
|
||||
gamelog.entries.push(format!("{} is confused.", entity_name.name));
|
||||
gamelog::Logger::new().npc_name(&entity_name.name).colour(rltk::WHITE).append("is confused.").log();
|
||||
}
|
||||
particle_builder.request(pos.x, pos.y, fg, rltk::RGB::named(rltk::BLACK), glyph, 200.0);
|
||||
can_act = false;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::{
|
||||
gamelog::GameLog, CombatStats, Item, Map, Monster, Name, Player, Position, RunState, State, TileType, Viewshed,
|
||||
gamelog, CombatStats, Item, Map, Monster, Name, Player, Position, RunState, State, TileType, Viewshed,
|
||||
WantsToMelee, WantsToPickupItem, MAPHEIGHT, MAPWIDTH,
|
||||
};
|
||||
use rltk::{Point, RandomNumberGenerator, Rltk, VirtualKeyCode};
|
||||
|
|
@ -48,8 +48,7 @@ pub fn try_move_player(delta_x: i32, delta_y: i32, ecs: &mut World) {
|
|||
}
|
||||
if tile_content != "You see " {
|
||||
tile_content.push_str(".");
|
||||
let mut gamelog = ecs.write_resource::<GameLog>();
|
||||
gamelog.entries.push(tile_content);
|
||||
gamelog::Logger::new().append(tile_content).log()
|
||||
}
|
||||
pos.x = min((MAPWIDTH as i32) - 1, max(0, pos.x + delta_x));
|
||||
pos.y = min((MAPHEIGHT as i32) - 1, max(0, pos.y + delta_y));
|
||||
|
|
@ -67,7 +66,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() {
|
||||
|
|
@ -77,7 +75,7 @@ fn get_item(ecs: &mut World) {
|
|||
}
|
||||
|
||||
match target_item {
|
||||
None => gamelog.entries.push("There is nothing to pick up.".to_string()),
|
||||
None => gamelog::Logger::new().append("There is nothing to pick up.").log(),
|
||||
Some(item) => {
|
||||
let mut pickup = ecs.write_storage::<WantsToPickupItem>();
|
||||
pickup
|
||||
|
|
@ -142,8 +140,7 @@ pub fn try_next_level(ecs: &mut World) -> bool {
|
|||
if map.tiles[player_idx] == TileType::DownStair {
|
||||
return true;
|
||||
} else {
|
||||
let mut gamelog = ecs.fetch_mut::<GameLog>();
|
||||
gamelog.entries.push("You don't see a way down.".to_string());
|
||||
gamelog::Logger::new().append("You don't see a way down.").log();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -152,8 +149,6 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
let player_entity = ecs.fetch::<Entity>();
|
||||
let viewshed_components = ecs.read_storage::<Viewshed>();
|
||||
let monsters = ecs.read_storage::<Monster>();
|
||||
let mut wait_message = "You wait a turn.";
|
||||
|
||||
let worldmap_resource = ecs.fetch::<Map>();
|
||||
|
||||
let mut can_heal = true;
|
||||
|
|
@ -171,6 +166,7 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
}
|
||||
}
|
||||
|
||||
let mut did_heal = false;
|
||||
if can_heal {
|
||||
let mut health_components = ecs.write_storage::<CombatStats>();
|
||||
let player_hp = health_components.get_mut(*player_entity).unwrap();
|
||||
|
|
@ -178,12 +174,15 @@ fn skip_turn(ecs: &mut World) -> RunState {
|
|||
let roll = rng.roll_dice(1, 6);
|
||||
if (roll == 6) && player_hp.hp < player_hp.max_hp {
|
||||
player_hp.hp += 1;
|
||||
wait_message = "You wait a turn, and recover a hit point.";
|
||||
did_heal = true;
|
||||
}
|
||||
}
|
||||
|
||||
let mut gamelog = ecs.fetch_mut::<GameLog>();
|
||||
gamelog.entries.push(wait_message.to_string());
|
||||
if did_heal {
|
||||
gamelog::Logger::new().append("You wait a turn, and").colour(rltk::GREEN).append("recover a hit point.").log();
|
||||
} else {
|
||||
gamelog::Logger::new().append("You wait a turn.").log();
|
||||
}
|
||||
return RunState::PlayerTurn;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue