cleanup and bugfixes, standardising log colours

This commit is contained in:
Llywelwyn 2023-08-17 04:44:40 +01:00
parent dd4e0aaee4
commit ff1afed92c
10 changed files with 153 additions and 73 deletions

View file

@ -34,7 +34,7 @@
"name": { "name": "scroll of fireball", "plural": "scrolls of fireball" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"weight": 0.5,
"value": 150,
"value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "ranged": "10", "damage": "8d6", "aoe": "3" },
"magic": { "class": "rare", "naming": "scroll" }
@ -44,7 +44,7 @@
"name": { "name": "cursed scroll of fireball", "plural": "cursed scrolls of fireball" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"weight": 0.5,
"value": 150,
"value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE", "CURSED"],
"effects": { "ranged": "10", "damage": "8d6", "aoe": "3" },
"magic": { "class": "rare", "naming": "scroll" }
@ -59,6 +59,16 @@
"effects": { "ranged": "10", "confusion": "4" },
"magic": { "class": "uncommon", "naming": "scroll" }
},
{
"id": "scroll_mass_confusion",
"name": { "name": "scroll of mass confusion", "plural": "scrolls of mass confusion" },
"renderable": { "glyph": "?", "fg": "#00FFFF", "bg": "#000000", "order": 2 },
"weight": 0.5,
"value": 200,
"flags": ["CONSUMABLE", "DESTRUCTIBLE"],
"effects": { "ranged": "10", "aoe": "4", "confusion": "3" },
"magic": { "class": "veryrare", "naming": "scroll" }
},
{
"id": "scroll_magicmap",
"name": { "name": "scroll of magic mapping", "plural": "scrolls of magic mapping" },

View file

@ -1,4 +1,4 @@
use crate::{gamelog, Clock, Player, Pools, Position, RunState, TakingTurn};
use crate::{gamelog, Clock, Player, Pools, Position, TakingTurn};
use specs::prelude::*;
pub struct RegenSystem {}
@ -11,7 +11,6 @@ impl<'a> System<'a> for RegenSystem {
type SystemData = (
ReadStorage<'a, Clock>,
Entities<'a>,
ReadExpect<'a, RunState>,
ReadStorage<'a, Position>,
WriteStorage<'a, Pools>,
ReadStorage<'a, TakingTurn>,
@ -19,22 +18,24 @@ impl<'a> System<'a> for RegenSystem {
);
fn run(&mut self, data: Self::SystemData) {
let (clock, entities, runstate, positions, mut pools, turns, player) = data;
if *runstate != RunState::Ticking {
let (clock, entities, positions, mut pools, turns, player) = data;
let mut clock_turn = false;
for (_e, _c, _t) in (&entities, &clock, &turns).join() {
clock_turn = true;
}
if !clock_turn {
return;
}
for (_e, _c, _t) in (&entities, &clock, &turns).join() {
let current_turn = gamelog::get_event_count("turns") + 1;
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);
}
let current_turn = gamelog::get_event_count("turns");
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);
}
let level = gamelog::get_event_count("player_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));
}
}
let level = gamelog::get_event_count("player_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));
}
}
}

View file

@ -1,4 +1,9 @@
use crate::{gamelog, Confusion, Name, ParticleBuilder, Position, RunState, TakingTurn};
use crate::{
effects::{add_effect, EffectType, Targets},
gamelog,
gui::renderable_colour,
Clock, Confusion, Name, Renderable, TakingTurn,
};
use rltk::prelude::*;
use specs::prelude::*;
@ -8,37 +13,93 @@ impl<'a> System<'a> for TurnStatusSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
WriteStorage<'a, TakingTurn>,
ReadStorage<'a, Clock>,
WriteStorage<'a, Confusion>,
Entities<'a>,
ReadExpect<'a, RunState>,
ReadStorage<'a, Name>,
ReadStorage<'a, Position>,
WriteExpect<'a, ParticleBuilder>,
ReadExpect<'a, Entity>,
ReadStorage<'a, Renderable>,
);
fn run(&mut self, data: Self::SystemData) {
let (mut turns, mut confusion, entities, runstate, names, positions, mut particle_builder) = data;
if *runstate != RunState::Ticking {
let (mut turns, clock, mut confusion, entities, names, player_entity, renderables) = data;
let mut clock_tick = false;
for (_e, _c, _t) in (&entities, &clock, &turns).join() {
clock_tick = true;
}
if !clock_tick {
return;
}
let mut remove_turn: Vec<Entity> = Vec::new();
let mut remove_confusion: Vec<Entity> = Vec::new();
for (entity, _turn, confused, name, pos) in (&entities, &mut turns, &mut confusion, &names, &positions).join() {
let mut logger = gamelog::Logger::new();
let mut log = false;
let mut not_my_turn: Vec<Entity> = Vec::new();
let mut not_confused: Vec<Entity> = Vec::new();
for (entity, _turn, confused, name) in (&entities, &mut turns, &mut confusion, &names).join() {
log = true;
confused.turns -= 1;
if confused.turns < 1 {
remove_confusion.push(entity);
gamelog::Logger::new().npc_name(&name.name).colour(WHITE).append("snaps out of it.").log();
particle_builder.request(pos.x, pos.y, RGB::named(LIGHT_BLUE), RGB::named(BLACK), to_cp437('!'), 200.0);
not_confused.push(entity);
if entity == *player_entity {
logger = logger
.colour(renderable_colour(&renderables, entity))
.append(&name.name)
.colour(WHITE)
.append("snap out of it.");
} else {
logger = logger
.append("The")
.colour(renderable_colour(&renderables, entity))
.append(&name.name)
.colour(WHITE)
.append("snaps out of it.");
}
add_effect(
None,
EffectType::Particle {
glyph: to_cp437('!'),
fg: RGB::named(LIGHT_BLUE),
bg: RGB::named(BLACK),
lifespan: 200.0,
delay: 0.0,
},
Targets::Entity { target: entity },
);
} else {
remove_turn.push(entity);
gamelog::Logger::new().npc_name(&name.name).colour(WHITE).append("is confused.").log();
particle_builder.request(pos.x, pos.y, RGB::named(MAGENTA), RGB::named(BLACK), to_cp437('?'), 200.0);
not_my_turn.push(entity);
if entity == *player_entity {
logger = logger
.colour(renderable_colour(&renderables, entity))
.append(&name.name)
.colour(WHITE)
.append("are confused!");
} else {
logger = logger
.append("The")
.colour(renderable_colour(&renderables, entity))
.append(&name.name)
.colour(WHITE)
.append("is confused!");
}
add_effect(
None,
EffectType::Particle {
glyph: to_cp437('?'),
fg: RGB::named(MAGENTA),
bg: RGB::named(BLACK),
lifespan: 200.0,
delay: 0.0,
},
Targets::Entity { target: entity },
);
}
}
for e in remove_turn {
if log {
logger.log();
}
for e in not_my_turn {
turns.remove(e);
}
for e in remove_confusion {
for e in not_confused {
confusion.remove(e);
}
}

View file

@ -2,7 +2,7 @@ use super::{add_effect, targeting, EffectSpawner, EffectType, Entity, Targets, W
use crate::{
gamelog,
gamesystem::{hp_per_level, mana_per_level},
Attributes, GrantsXP, Map, Player, Pools, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME,
Attributes, Confusion, GrantsXP, Map, Player, Pools, DEFAULT_PARTICLE_LIFETIME, LONG_PARTICLE_LIFETIME,
};
use rltk::prelude::*;
use specs::prelude::*;
@ -53,6 +53,14 @@ pub fn heal_damage(ecs: &mut World, heal: &EffectSpawner, target: Entity) {
}
}
pub fn add_confusion(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
if let EffectType::Confusion { turns } = &effect.effect_type {
ecs.write_storage::<Confusion>()
.insert(target, Confusion { turns: *turns })
.expect("Unable to insert Confusion");
}
}
pub fn bloodstain(ecs: &mut World, target: usize) {
let mut map = ecs.fetch_mut::<Map>();
// If the current tile isn't bloody, bloody it.

View file

@ -20,6 +20,7 @@ lazy_static! {
pub enum EffectType {
Damage { amount: i32 },
Healing { amount: i32 },
Confusion { turns: i32 },
Bloodstain,
Particle { glyph: FontCharType, fg: RGB, bg: RGB, lifespan: f32, delay: f32 },
EntityDeath,
@ -98,6 +99,7 @@ fn tile_effect_hits_entities(effect: &EffectType) -> bool {
EffectType::Damage { .. } => true,
EffectType::Healing { .. } => true,
EffectType::RestoreNutrition { .. } => true,
EffectType::Confusion { .. } => true,
_ => false,
}
}
@ -107,6 +109,7 @@ fn affect_entity(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
match &effect.effect_type {
EffectType::Damage { .. } => damage::inflict_damage(ecs, effect, target),
EffectType::Healing { .. } => damage::heal_damage(ecs, effect, target),
EffectType::Confusion { .. } => damage::add_confusion(ecs, effect, target),
EffectType::Bloodstain { .. } => {
if let Some(pos) = targeting::entity_position(ecs, target) {
damage::bloodstain(ecs, pos)

View file

@ -1,7 +1,7 @@
use super::{add_effect, spatial, EffectType, Entity, Targets, World};
use crate::{
gamelog, gui::item_colour_ecs, gui::obfuscate_name_ecs, Consumable, Cursed, InflictsDamage, MagicMapper, Prop,
ProvidesHealing, ProvidesNutrition, RandomNumberGenerator, Renderable, RunState,
gamelog, gui::item_colour_ecs, gui::obfuscate_name_ecs, Confusion, Consumable, Cursed, InflictsDamage, MagicMapper,
Prop, ProvidesHealing, ProvidesNutrition, RandomNumberGenerator, Renderable, RunState,
};
use rltk::prelude::*;
use specs::prelude::*;
@ -43,6 +43,8 @@ fn event_trigger(source: Option<Entity>, entity: Entity, target: &Targets, ecs:
logger = handle_healing(ecs, &mut event, logger);
// DOES DAMAGE
logger = handle_damage(ecs, &mut event, logger);
// APPLIES CONFUSION
logger = handle_confusion(ecs, &mut event, logger);
if event.log {
logger.log();
}
@ -83,7 +85,7 @@ fn handle_healing(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::L
let mut rng = ecs.write_resource::<RandomNumberGenerator>();
let roll = rng.roll_dice(healing_item.n_dice, healing_item.sides) + healing_item.modifier;
add_effect(event.source, EffectType::Healing { amount: roll }, event.target.clone());
logger = logger.append("You recover some vigour.");
logger = logger.append("You recover some vigour.").buc(event.buc, None, Some("You feel great!"));
event.log = true;
}
return logger;
@ -115,8 +117,14 @@ fn handle_damage(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Lo
return logger;
}
fn handle_confusion(ecs: &mut World, event: &mut EventInfo, mut logger: gamelog::Logger) -> gamelog::Logger {
if let Some(confusion) = ecs.read_storage::<Confusion>().get(event.entity) {
add_effect(event.source, EffectType::Confusion { turns: confusion.turns }, event.target.clone());
}
return logger;
}
fn get_entity_targets(target: &Targets) -> Vec<Entity> {
rltk::console::log("ayo");
let mut entities: Vec<Entity> = Vec::new();
match target {
Targets::Entity { target } => entities.push(*target),

View file

@ -449,6 +449,15 @@ pub fn obfuscate_name_ecs(ecs: &World, item: Entity) -> (String, String) {
return (singular, plural);
}
/// Gets renderable colour as tuple of u8
pub fn renderable_colour(renderables: &ReadStorage<Renderable>, entity: Entity) -> (u8, u8, u8) {
return if let Some(renderable) = renderables.get(entity) {
((renderable.fg.r * 255.0) as u8, (renderable.fg.g * 255.0) as u8, (renderable.fg.b * 255.0) as u8)
} else {
WHITE
};
}
pub fn item_colour_ecs(ecs: &World, item: Entity) -> (u8, u8, u8) {
let dm = ecs.fetch::<MasterDungeonMap>();
if let Some(name) = ecs.read_storage::<Name>().get(item) {

View file

@ -1,4 +1,4 @@
use super::{camera::get_screen_bounds, Attributes, Hidden, Map, Pools, Position, Renderable, Rltk, World, RGB};
use super::{camera::get_screen_bounds, Attributes, Hidden, Map, Name, Pools, Position, Renderable, Rltk, World, RGB};
use rltk::prelude::*;
use specs::prelude::*;
@ -43,6 +43,7 @@ impl Tooltip {
pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
let (min_x, _max_x, min_y, _max_y, x_offset, y_offset) = get_screen_bounds(ecs, ctx);
let map = ecs.fetch::<Map>();
let names = ecs.read_storage::<Name>();
let positions = ecs.read_storage::<Position>();
let renderables = ecs.read_storage::<Renderable>();
let hidden = ecs.read_storage::<Hidden>();
@ -69,7 +70,7 @@ pub fn draw_tooltips(ecs: &World, ctx: &mut Rltk) {
}
let mut tooltips: Vec<Tooltip> = Vec::new();
for (entity, position, renderable, _hidden) in (&entities, &positions, &renderables, !&hidden).join() {
for (entity, position, renderable, _name, _hidden) in (&entities, &positions, &renderables, &names, !&hidden).join() {
if position.x == mouse_pos_adjusted.0 && position.y == mouse_pos_adjusted.1 {
let mut tip = Tooltip::new();
tip.add(crate::gui::obfuscate_name_ecs(ecs, entity).0, renderable.fg);

View file

@ -90,11 +90,6 @@ impl State {
fn run_systems(&mut self) {
let mut mapindex = spatial::MapIndexingSystem {};
let mut vis = VisibilitySystem {};
let mut regen_system = ai::RegenSystem {};
let mut energy = ai::EnergySystem {};
let mut encumbrance_system = ai::EncumbranceSystem {};
let mut turn_status_system = ai::TurnStatusSystem {};
let mut quip_system = ai::QuipSystem {};
let mut trigger_system = trigger_system::TriggerSystem {};
let mut melee_system = MeleeCombatSystem {};
let mut damage_system = DamageSystem {};
@ -109,11 +104,6 @@ impl State {
mapindex.run_now(&self.ecs);
vis.run_now(&self.ecs);
regen_system.run_now(&self.ecs);
encumbrance_system.run_now(&self.ecs);
energy.run_now(&self.ecs);
quip_system.run_now(&self.ecs);
turn_status_system.run_now(&self.ecs);
self.run_ai();
trigger_system.run_now(&self.ecs);
inventory_system.run_now(&self.ecs);
@ -132,12 +122,22 @@ impl State {
}
fn run_ai(&mut self) {
let mut adjacent_ai = ai::AdjacentAI {};
let mut encumbrance_system = ai::EncumbranceSystem {}; // Must run first, as it affects energy regen.
let mut energy = ai::EnergySystem {}; // Figures out who deserves a turn.
let mut regen_system = ai::RegenSystem {}; // Restores HP on appropriate clock ticks.
let mut turn_status_system = ai::TurnStatusSystem {}; // Ticks stasuses. Should anyone now lose their turn? i.e. confusion
let mut quip_system = ai::QuipSystem {}; // Quipping is "free". It doesn't use up a turn.
let mut adjacent_ai = ai::AdjacentAI {}; // AdjacentAI -> DefaultAI are all exclusive. If one acts, the entity's turn is over.
let mut visible_ai = ai::VisibleAI {};
let mut approach_ai = ai::ApproachAI {};
let mut flee_ai = ai::FleeAI {};
let mut chase_ai = ai::ChaseAI {};
let mut default_move_ai = ai::DefaultAI {};
encumbrance_system.run_now(&self.ecs);
energy.run_now(&self.ecs);
regen_system.run_now(&self.ecs);
turn_status_system.run_now(&self.ecs);
quip_system.run_now(&self.ecs);
adjacent_ai.run_now(&self.ecs);
visible_ai.run_now(&self.ecs);
approach_ai.run_now(&self.ecs);

View file

@ -91,27 +91,6 @@ pub fn player(ecs: &mut World, player_x: i32, player_y: i32) -> Entity {
raws::SpawnType::Carried { by: player },
0,
);
raws::spawn_named_entity(
&raws::RAWS.lock().unwrap(),
ecs,
"scroll_confusion",
raws::SpawnType::Carried { by: player },
0,
);
raws::spawn_named_entity(
&raws::RAWS.lock().unwrap(),
ecs,
"scroll_confusion",
raws::SpawnType::Carried { by: player },
0,
);
raws::spawn_named_entity(
&raws::RAWS.lock().unwrap(),
ecs,
"scroll_fireball",
raws::SpawnType::Carried { by: player },
0,
);
return player;
}