From 64aeb189c9ddb0a1d9b89aa3449d69c986d358a3 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 20 Jan 2022 16:24:12 -0500 Subject: [PATCH] Cleanup code now handled by effects module --- src/components.rs | 23 --------- src/damage_system.rs | 105 ++-------------------------------------- src/effects/triggers.rs | 39 ++++++++++++--- src/hunger_system.rs | 12 +++-- src/raws/rawmaster.rs | 97 ++++++++++++++++++------------------- src/state.rs | 6 +-- 6 files changed, 90 insertions(+), 192 deletions(-) diff --git a/src/components.rs b/src/components.rs index d296b3e..114e02f 100644 --- a/src/components.rs +++ b/src/components.rs @@ -88,29 +88,6 @@ pub struct Item { pub base_value: f32, } -#[derive(Component, Debug, ConvertSaveload, Clone)] -pub struct SufferDamage { - pub amount: Vec<(i32, bool)>, -} - -impl SufferDamage { - pub fn new_damage( - store: &mut WriteStorage, - victim: Entity, - amount: i32, - from_player: bool, - ) { - if let Some(suffering) = store.get_mut(victim) { - suffering.amount.push((amount, from_player)); - } else { - let dmg = SufferDamage { - amount: vec![(amount, from_player)], - }; - store.insert(victim, dmg).expect("Unable to insert damage"); - } - } -} - #[derive(Component, Debug, ConvertSaveload, Clone)] pub struct Ranged { pub range: i32, diff --git a/src/damage_system.rs b/src/damage_system.rs index 3d4883f..72f481c 100644 --- a/src/damage_system.rs +++ b/src/damage_system.rs @@ -1,109 +1,10 @@ -use ::rltk::{Point, RandomNumberGenerator}; +use ::rltk::RandomNumberGenerator; use ::specs::prelude::*; -use crate::components::{ - Attributes, Equipped, InBackpack, LootTable, Name, Player, Pools, Position, SufferDamage, -}; +use crate::components::{Equipped, InBackpack, LootTable, Name, Player, Pools, Position}; use crate::game_log::GameLog; -use crate::gamesystem::{mana_at_level, player_hp_at_level}; -use crate::particle_system::ParticleBuilder; use crate::raws::{self, SpawnType, RAWS}; -use crate::{colors, Map, RunState}; - -pub struct DamageSystem {} - -impl<'a> System<'a> for DamageSystem { - #[allow(clippy::type_complexity)] - type SystemData = ( - WriteStorage<'a, Pools>, - WriteStorage<'a, SufferDamage>, - ReadStorage<'a, Position>, - WriteExpect<'a, Map>, - Entities<'a>, - ReadExpect<'a, Entity>, - ReadStorage<'a, Attributes>, - WriteExpect<'a, GameLog>, - WriteExpect<'a, ParticleBuilder>, - ReadExpect<'a, Point>, - ); - - fn run(&mut self, data: Self::SystemData) { - let ( - mut stats, - mut damage, - positions, - mut map, - entities, - player, - attributes, - mut log, - mut particles, - player_pos, - ) = data; - let mut xp_gain = 0; - let mut gold_gain = 0.0_f32; - - for (entity, mut stats, damage) in (&entities, &mut stats, &damage).join() { - gold_gain += stats.gold; - for dmg in damage.amount.iter() { - if !stats.god_mode { - stats.hit_points.current -= dmg.0; - } - - if let Some(pos) = positions.get(entity) { - let idx = map.xy_idx(pos.x, pos.y); - map.bloodstains.insert(idx); - } - - if stats.hit_points.current < 1 && dmg.1 { - xp_gain += stats.level * 100; - } - } - } - - if xp_gain != 0 || gold_gain != 0.0 { - let mut player_stats = stats.get_mut(*player).unwrap(); - let player_attributes = attributes.get(*player).unwrap(); - - player_stats.xp += xp_gain; - player_stats.gold += gold_gain; - - 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 - )); - player_stats.hit_points.max = player_hp_at_level( - player_attributes.fitness.base + player_attributes.fitness.modifiers, - player_stats.level, - ); - player_stats.hit_points.current = player_stats.hit_points.max; - player_stats.mana.max = mana_at_level( - player_attributes.intelligence.base + player_attributes.intelligence.modifiers, - player_stats.level, - ); - player_stats.mana.current = player_stats.mana.max; - - for i in 0..10 { - if player_pos.y - i > 1 { - particles.request( - player_pos.x, - player_pos.y - i, - colors::GOLD, - colors::BLACK, - rltk::to_cp437('░'), - 400.0, - ); - } - } - } - } - - damage.clear(); - } -} +use crate::RunState; pub fn delete_the_dead(ecs: &mut World) { let mut dead: Vec = Vec::new(); diff --git a/src/effects/triggers.rs b/src/effects/triggers.rs index 2dc908c..5b50525 100644 --- a/src/effects/triggers.rs +++ b/src/effects/triggers.rs @@ -9,10 +9,10 @@ use crate::{GameLog, Map, RunState}; pub fn item_trigger(creator: Option, item: Entity, targets: &Targets, ecs: &mut World) { // Use the item via the generic system - event_trigger(creator, item, targets, ecs); + let did_something = event_trigger(creator, item, targets, ecs); // If it was a consumable, then it gets deleted - if ecs.read_storage::().get(item).is_some() { + if did_something && ecs.read_storage::().get(item).is_some() { ecs.entities() .delete(item) .expect("Failed to delete consumable item"); @@ -24,13 +24,14 @@ pub fn trigger(creator: Option, trigger: Entity, targets: &Targets, ecs: ecs.write_storage::().remove(trigger); // Use the item via the generic system - event_trigger(creator, trigger, targets, ecs); + let did_something = event_trigger(creator, trigger, targets, ecs); // If it was a single activation, then it gets deleted - if ecs - .read_storage::() - .get(trigger) - .is_some() + if did_something + && ecs + .read_storage::() + .get(trigger) + .is_some() { ecs.entities() .delete(trigger) @@ -38,7 +39,13 @@ pub fn trigger(creator: Option, trigger: Entity, targets: &Targets, ecs: } } -fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs: &mut World) { +fn event_trigger( + creator: Option, + entity: Entity, + targets: &Targets, + ecs: &mut World, +) -> bool { + let mut did_something = false; let mut gamelog = ecs.fetch_mut::(); // Providing food @@ -46,6 +53,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs add_effect(creator, EffectType::WellFed, targets.clone()); let names = ecs.read_storage::(); gamelog.append(format!("You eat the {}.", names.get(entity).unwrap().name)); + + did_something = true; } // Magic mapper @@ -53,6 +62,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs let mut runstate = ecs.fetch_mut::(); gamelog.append("The map is revealed to you!"); *runstate = RunState::MagicMapReveal { row: 0 }; + + did_something = true; } // Town Portal @@ -64,6 +75,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs gamelog.append("You are teleported back to town!"); let mut runstate = ecs.fetch_mut::(); *runstate = RunState::TownPortal; + + did_something = true; } } @@ -76,6 +89,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs }, targets.clone(), ); + + did_something = true; } // Damage @@ -87,6 +102,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs }, targets.clone(), ); + + did_something = true; } // Confusion @@ -98,6 +115,8 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs }, targets.clone(), ); + + did_something = true; } // Teleport @@ -112,5 +131,9 @@ fn event_trigger(creator: Option, entity: Entity, targets: &Targets, ecs }, targets.clone(), ); + + did_something = true; } + + did_something } diff --git a/src/hunger_system.rs b/src/hunger_system.rs index bd6b363..a4d5331 100644 --- a/src/hunger_system.rs +++ b/src/hunger_system.rs @@ -1,6 +1,7 @@ use ::specs::prelude::*; -use crate::components::{HungerClock, HungerState, MyTurn, SufferDamage}; +use crate::components::{HungerClock, HungerState, MyTurn}; +use crate::effects::{add_effect, EffectType, Targets}; use crate::game_log::GameLog; pub struct HungerSystem {} @@ -11,13 +12,12 @@ impl<'a> System<'a> for HungerSystem { Entities<'a>, WriteStorage<'a, HungerClock>, ReadExpect<'a, Entity>, // The player - WriteStorage<'a, SufferDamage>, WriteExpect<'a, GameLog>, ReadStorage<'a, MyTurn>, ); fn run(&mut self, data: Self::SystemData) { - let (entities, mut hunger_clock, player_entity, mut inflict_damage, mut log, turns) = data; + let (entities, mut hunger_clock, player_entity, mut log, turns) = data; for (entity, mut clock, _myturn) in (&entities, &mut hunger_clock, &turns).join() { clock.duration -= 1; @@ -54,7 +54,11 @@ impl<'a> System<'a> for HungerSystem { log.append("Your hunger pangs are getting painful!"); } - SufferDamage::new_damage(&mut inflict_damage, entity, 1, false); + add_effect( + None, + EffectType::Damage { amount: 1 }, + Targets::Single { target: entity }, + ); } } } diff --git a/src/raws/rawmaster.rs b/src/raws/rawmaster.rs index 528ef7a..f422386 100644 --- a/src/raws/rawmaster.rs +++ b/src/raws/rawmaster.rs @@ -268,6 +268,51 @@ pub fn string_to_slot(slot: &str) -> EquipmentSlot { } } +macro_rules! apply_effects { + ($effects:expr, $eb:expr) => { + for effect in $effects.iter() { + let effect_name = effect.0.as_str(); + match effect_name { + "provides_healing" => { + $eb = $eb.with(ProvidesHealing { + heal_amount: effect.1.parse::().unwrap(), + }) + } + "ranged" => { + $eb = $eb.with(Ranged { + range: effect.1.parse::().unwrap(), + }) + } + "damage" => { + $eb = $eb.with(InflictsDamage { + damage: effect.1.parse::().unwrap(), + }) + } + "area_of_effect" => { + $eb = $eb.with(AreaOfEffect { + radius: effect.1.parse::().unwrap(), + }) + } + "confusion" => { + $eb = $eb.with(Confusion { + turns: effect.1.parse::().unwrap(), + }) + } + "magic_mapping" => $eb = $eb.with(MagicMapper {}), + "town_portal" => $eb = $eb.with(TownPortal {}), + "food" => $eb = $eb.with(ProvidesFood {}), + "single_activation" => $eb = $eb.with(SingleActivation {}), + _ => { + ::rltk::console::log(format!( + "Warning: consumable effect {} not implemented.", + effect_name + )); + } + } + } + }; +} + pub fn spawn_named_item( raws: &RawMaster, ecs: &mut World, @@ -303,45 +348,7 @@ pub fn spawn_named_item( if let Some(consumable) = &item_template.consumable { eb = eb.with(Consumable {}); - for effect in consumable.effects.iter() { - let effect_name = effect.0.as_str(); - match effect_name { - "provides_healing" => { - eb = eb.with(ProvidesHealing { - heal_amount: effect.1.parse::().unwrap(), - }) - } - "ranged" => { - eb = eb.with(Ranged { - range: effect.1.parse::().unwrap(), - }) - } - "damage" => { - eb = eb.with(InflictsDamage { - damage: effect.1.parse::().unwrap(), - }) - } - "area_of_effect" => { - eb = eb.with(AreaOfEffect { - radius: effect.1.parse::().unwrap(), - }) - } - "confusion" => { - eb = eb.with(Confusion { - turns: effect.1.parse::().unwrap(), - }) - } - "magic_mapping" => eb = eb.with(MagicMapper {}), - "town_portal" => eb = eb.with(TownPortal {}), - "food" => eb = eb.with(ProvidesFood {}), - _ => { - rltk::console::log(format!( - "Warning: consumable effect {} not implemented.", - effect_name - )); - } - } - } + apply_effects!(consumable.effects, eb); } if let Some(weapon) = &item_template.weapon { @@ -636,17 +643,7 @@ pub fn spawn_named_prop( } if let Some(entry_trigger) = &prop_template.entry_trigger { eb = eb.with(EntryTrigger {}); - for effect in entry_trigger.effects.iter() { - match effect.0.as_str() { - "damage" => { - eb = eb.with(InflictsDamage { - damage: effect.1.parse::().unwrap(), - }); - } - "single_activation" => eb = eb.with(SingleActivation {}), - _ => {} - } - } + apply_effects!(entry_trigger.effects, eb); } if let Some(light) = &prop_template.light { eb = eb diff --git a/src/state.rs b/src/state.rs index ef6d31d..19ad58d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -2,7 +2,6 @@ use ::rltk::{GameState, Point, Rltk}; use ::specs::prelude::*; use crate::components::*; -use crate::damage_system::{self, DamageSystem}; use crate::game_log::GameLog; use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection}; use crate::hunger_system::HungerSystem; @@ -20,7 +19,7 @@ use crate::player::*; use crate::raws::*; use crate::trigger_system::TriggerSystem; use crate::visibility_system::VisibilitySystem; -use crate::{ai, camera, effects, saveload_system, spawner}; +use crate::{ai, camera, damage_system, effects, saveload_system, spawner}; pub const SHOW_MAPGEN_VISUALIZER: bool = false; @@ -119,9 +118,6 @@ impl State { let mut melee = MeleeCombatSystem {}; melee.run_now(&self.ecs); - let mut damage = DamageSystem {}; - damage.run_now(&self.ecs); - let mut pickup = ItemCollectionSystem {}; pickup.run_now(&self.ecs);