roguelike-game/src/effects/damage.rs

138 lines
5.2 KiB
Rust

use ::rltk::Point;
use ::specs::prelude::*;
use super::{add_effect, entity_position, EffectSpawner, EffectType, Targets};
use crate::components::{Attributes, Confusion, Player, Pools};
use crate::gamesystem::{mana_at_level, player_hp_at_level};
use crate::{colors, GameLog, Map};
pub fn inflict_damage(ecs: &mut World, damage: &EffectSpawner, target: Entity) {
let mut pools = ecs.write_storage::<Pools>();
if let Some(pool) = pools.get_mut(target) {
if !pool.god_mode {
if let EffectType::Damage { amount } = damage.effect_type {
pool.hit_points.current -= amount;
add_effect(None, EffectType::Bloodstain, Targets::Single { target });
add_effect(
None,
EffectType::Particle {
glyph: rltk::to_cp437('‼'),
fg: colors::ORANGE,
bg: colors::BLACK,
lifespan: 200.0,
},
Targets::Single { target },
);
if pool.hit_points.current < 1 {
add_effect(
damage.creator,
EffectType::EntityDeath,
Targets::Single { target },
);
}
}
}
}
}
pub fn bloodstain(ecs: &mut World, tile_idx: i32) {
let mut map = ecs.fetch_mut::<Map>();
map.bloodstains.insert(tile_idx as usize);
}
pub fn death(ecs: &mut World, effect: &EffectSpawner, target: Entity) {
let mut xp_gain = 0;
let mut gold_gain = 0.0f32;
let mut pools = ecs.write_storage::<Pools>();
let attributes = ecs.read_storage::<Attributes>();
let map = ecs.fetch_mut::<Map>();
if let Some(pos) = entity_position(ecs, target) {
crate::spatial::remove_entity(target, pos as usize);
}
if let Some(source) = effect.creator {
if ecs.read_storage::<Player>().get(source).is_some() {
if let Some(stats) = pools.get(target) {
xp_gain += stats.level * 100;
gold_gain += stats.gold;
}
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 player_attributes = attributes.get(source).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;
let player_pos = ecs.fetch::<Point>();
for i in 0..10 {
if player_pos.y - i > 1 {
add_effect(
None,
EffectType::Particle {
glyph: ::rltk::to_cp437('░'),
fg: colors::GOLD,
bg: colors::BLACK,
lifespan: 400.0,
},
Targets::Tile {
tile_idx: map.xy_idx(player_pos.x, player_pos.y - i) as i32,
},
);
}
}
}
}
}
}
}
pub fn heal_damage(ecs: &mut World, heal: &EffectSpawner, target: Entity) {
let mut pools = ecs.write_storage::<Pools>();
if let Some(pool) = pools.get_mut(target) {
if let EffectType::Healing { amount } = heal.effect_type {
pool.hit_points.current =
i32::min(pool.hit_points.max, pool.hit_points.current + amount);
add_effect(
None,
EffectType::Particle {
glyph: ::rltk::to_cp437('‼'),
fg: colors::GREEN,
bg: colors::BLACK,
lifespan: 200.0,
},
Targets::Single { target },
);
}
}
}
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 make target confused");
}
}