Cleanup code now handled by effects module
This commit is contained in:
parent
64cc39eba1
commit
64aeb189c9
@ -88,29 +88,6 @@ pub struct Item {
|
|||||||
pub base_value: f32,
|
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<SufferDamage>,
|
|
||||||
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)]
|
#[derive(Component, Debug, ConvertSaveload, Clone)]
|
||||||
pub struct Ranged {
|
pub struct Ranged {
|
||||||
pub range: i32,
|
pub range: i32,
|
||||||
|
@ -1,109 +1,10 @@
|
|||||||
use ::rltk::{Point, RandomNumberGenerator};
|
use ::rltk::RandomNumberGenerator;
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
use crate::components::{
|
use crate::components::{Equipped, InBackpack, LootTable, Name, Player, Pools, Position};
|
||||||
Attributes, Equipped, InBackpack, LootTable, Name, Player, Pools, Position, SufferDamage,
|
|
||||||
};
|
|
||||||
use crate::game_log::GameLog;
|
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::raws::{self, SpawnType, RAWS};
|
||||||
use crate::{colors, Map, RunState};
|
use crate::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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_the_dead(ecs: &mut World) {
|
pub fn delete_the_dead(ecs: &mut World) {
|
||||||
let mut dead: Vec<Entity> = Vec::new();
|
let mut dead: Vec<Entity> = Vec::new();
|
||||||
|
@ -9,10 +9,10 @@ use crate::{GameLog, Map, RunState};
|
|||||||
|
|
||||||
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
|
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
|
||||||
// Use the item via the generic system
|
// 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 it was a consumable, then it gets deleted
|
||||||
if ecs.read_storage::<Consumable>().get(item).is_some() {
|
if did_something && ecs.read_storage::<Consumable>().get(item).is_some() {
|
||||||
ecs.entities()
|
ecs.entities()
|
||||||
.delete(item)
|
.delete(item)
|
||||||
.expect("Failed to delete consumable item");
|
.expect("Failed to delete consumable item");
|
||||||
@ -24,13 +24,14 @@ pub fn trigger(creator: Option<Entity>, trigger: Entity, targets: &Targets, ecs:
|
|||||||
ecs.write_storage::<Hidden>().remove(trigger);
|
ecs.write_storage::<Hidden>().remove(trigger);
|
||||||
|
|
||||||
// Use the item via the generic system
|
// 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 it was a single activation, then it gets deleted
|
||||||
if ecs
|
if did_something
|
||||||
.read_storage::<SingleActivation>()
|
&& ecs
|
||||||
.get(trigger)
|
.read_storage::<SingleActivation>()
|
||||||
.is_some()
|
.get(trigger)
|
||||||
|
.is_some()
|
||||||
{
|
{
|
||||||
ecs.entities()
|
ecs.entities()
|
||||||
.delete(trigger)
|
.delete(trigger)
|
||||||
@ -38,7 +39,13 @@ pub fn trigger(creator: Option<Entity>, trigger: Entity, targets: &Targets, ecs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs: &mut World) {
|
fn event_trigger(
|
||||||
|
creator: Option<Entity>,
|
||||||
|
entity: Entity,
|
||||||
|
targets: &Targets,
|
||||||
|
ecs: &mut World,
|
||||||
|
) -> bool {
|
||||||
|
let mut did_something = false;
|
||||||
let mut gamelog = ecs.fetch_mut::<GameLog>();
|
let mut gamelog = ecs.fetch_mut::<GameLog>();
|
||||||
|
|
||||||
// Providing food
|
// Providing food
|
||||||
@ -46,6 +53,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
add_effect(creator, EffectType::WellFed, targets.clone());
|
add_effect(creator, EffectType::WellFed, targets.clone());
|
||||||
let names = ecs.read_storage::<Name>();
|
let names = ecs.read_storage::<Name>();
|
||||||
gamelog.append(format!("You eat the {}.", names.get(entity).unwrap().name));
|
gamelog.append(format!("You eat the {}.", names.get(entity).unwrap().name));
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Magic mapper
|
// Magic mapper
|
||||||
@ -53,6 +62,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
let mut runstate = ecs.fetch_mut::<RunState>();
|
let mut runstate = ecs.fetch_mut::<RunState>();
|
||||||
gamelog.append("The map is revealed to you!");
|
gamelog.append("The map is revealed to you!");
|
||||||
*runstate = RunState::MagicMapReveal { row: 0 };
|
*runstate = RunState::MagicMapReveal { row: 0 };
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Town Portal
|
// Town Portal
|
||||||
@ -64,6 +75,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
gamelog.append("You are teleported back to town!");
|
gamelog.append("You are teleported back to town!");
|
||||||
let mut runstate = ecs.fetch_mut::<RunState>();
|
let mut runstate = ecs.fetch_mut::<RunState>();
|
||||||
*runstate = RunState::TownPortal;
|
*runstate = RunState::TownPortal;
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +89,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
},
|
},
|
||||||
targets.clone(),
|
targets.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Damage
|
// Damage
|
||||||
@ -87,6 +102,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
},
|
},
|
||||||
targets.clone(),
|
targets.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confusion
|
// Confusion
|
||||||
@ -98,6 +115,8 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
},
|
},
|
||||||
targets.clone(),
|
targets.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Teleport
|
// Teleport
|
||||||
@ -112,5 +131,9 @@ fn event_trigger(creator: Option<Entity>, entity: Entity, targets: &Targets, ecs
|
|||||||
},
|
},
|
||||||
targets.clone(),
|
targets.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
did_something
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use ::specs::prelude::*;
|
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;
|
use crate::game_log::GameLog;
|
||||||
|
|
||||||
pub struct HungerSystem {}
|
pub struct HungerSystem {}
|
||||||
@ -11,13 +12,12 @@ impl<'a> System<'a> for HungerSystem {
|
|||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
WriteStorage<'a, HungerClock>,
|
WriteStorage<'a, HungerClock>,
|
||||||
ReadExpect<'a, Entity>, // The player
|
ReadExpect<'a, Entity>, // The player
|
||||||
WriteStorage<'a, SufferDamage>,
|
|
||||||
WriteExpect<'a, GameLog>,
|
WriteExpect<'a, GameLog>,
|
||||||
ReadStorage<'a, MyTurn>,
|
ReadStorage<'a, MyTurn>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn run(&mut self, data: Self::SystemData) {
|
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() {
|
for (entity, mut clock, _myturn) in (&entities, &mut hunger_clock, &turns).join() {
|
||||||
clock.duration -= 1;
|
clock.duration -= 1;
|
||||||
@ -54,7 +54,11 @@ impl<'a> System<'a> for HungerSystem {
|
|||||||
log.append("Your hunger pangs are getting painful!");
|
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 },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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::<i32>().unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"ranged" => {
|
||||||
|
$eb = $eb.with(Ranged {
|
||||||
|
range: effect.1.parse::<i32>().unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"damage" => {
|
||||||
|
$eb = $eb.with(InflictsDamage {
|
||||||
|
damage: effect.1.parse::<i32>().unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"area_of_effect" => {
|
||||||
|
$eb = $eb.with(AreaOfEffect {
|
||||||
|
radius: effect.1.parse::<i32>().unwrap(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"confusion" => {
|
||||||
|
$eb = $eb.with(Confusion {
|
||||||
|
turns: effect.1.parse::<i32>().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(
|
pub fn spawn_named_item(
|
||||||
raws: &RawMaster,
|
raws: &RawMaster,
|
||||||
ecs: &mut World,
|
ecs: &mut World,
|
||||||
@ -303,45 +348,7 @@ pub fn spawn_named_item(
|
|||||||
|
|
||||||
if let Some(consumable) = &item_template.consumable {
|
if let Some(consumable) = &item_template.consumable {
|
||||||
eb = eb.with(Consumable {});
|
eb = eb.with(Consumable {});
|
||||||
for effect in consumable.effects.iter() {
|
apply_effects!(consumable.effects, eb);
|
||||||
let effect_name = effect.0.as_str();
|
|
||||||
match effect_name {
|
|
||||||
"provides_healing" => {
|
|
||||||
eb = eb.with(ProvidesHealing {
|
|
||||||
heal_amount: effect.1.parse::<i32>().unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"ranged" => {
|
|
||||||
eb = eb.with(Ranged {
|
|
||||||
range: effect.1.parse::<i32>().unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"damage" => {
|
|
||||||
eb = eb.with(InflictsDamage {
|
|
||||||
damage: effect.1.parse::<i32>().unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"area_of_effect" => {
|
|
||||||
eb = eb.with(AreaOfEffect {
|
|
||||||
radius: effect.1.parse::<i32>().unwrap(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
"confusion" => {
|
|
||||||
eb = eb.with(Confusion {
|
|
||||||
turns: effect.1.parse::<i32>().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
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(weapon) = &item_template.weapon {
|
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 {
|
if let Some(entry_trigger) = &prop_template.entry_trigger {
|
||||||
eb = eb.with(EntryTrigger {});
|
eb = eb.with(EntryTrigger {});
|
||||||
for effect in entry_trigger.effects.iter() {
|
apply_effects!(entry_trigger.effects, eb);
|
||||||
match effect.0.as_str() {
|
|
||||||
"damage" => {
|
|
||||||
eb = eb.with(InflictsDamage {
|
|
||||||
damage: effect.1.parse::<i32>().unwrap(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
"single_activation" => eb = eb.with(SingleActivation {}),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Some(light) = &prop_template.light {
|
if let Some(light) = &prop_template.light {
|
||||||
eb = eb
|
eb = eb
|
||||||
|
@ -2,7 +2,6 @@ use ::rltk::{GameState, Point, Rltk};
|
|||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
use crate::components::*;
|
use crate::components::*;
|
||||||
use crate::damage_system::{self, DamageSystem};
|
|
||||||
use crate::game_log::GameLog;
|
use crate::game_log::GameLog;
|
||||||
use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection};
|
use crate::gui::{self, show_cheat_mode, CheatMenuResult, MainMenuSelection};
|
||||||
use crate::hunger_system::HungerSystem;
|
use crate::hunger_system::HungerSystem;
|
||||||
@ -20,7 +19,7 @@ use crate::player::*;
|
|||||||
use crate::raws::*;
|
use crate::raws::*;
|
||||||
use crate::trigger_system::TriggerSystem;
|
use crate::trigger_system::TriggerSystem;
|
||||||
use crate::visibility_system::VisibilitySystem;
|
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;
|
pub const SHOW_MAPGEN_VISUALIZER: bool = false;
|
||||||
|
|
||||||
@ -119,9 +118,6 @@ impl State {
|
|||||||
let mut melee = MeleeCombatSystem {};
|
let mut melee = MeleeCombatSystem {};
|
||||||
melee.run_now(&self.ecs);
|
melee.run_now(&self.ecs);
|
||||||
|
|
||||||
let mut damage = DamageSystem {};
|
|
||||||
damage.run_now(&self.ecs);
|
|
||||||
|
|
||||||
let mut pickup = ItemCollectionSystem {};
|
let mut pickup = ItemCollectionSystem {};
|
||||||
pickup.run_now(&self.ecs);
|
pickup.run_now(&self.ecs);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user