Complete section 5.26

This commit is contained in:
Timothy Warren 2022-01-28 13:47:16 -05:00
parent 051be94bc9
commit a40f43b839
8 changed files with 107 additions and 11 deletions

View File

@ -521,3 +521,8 @@ pub struct TileSize {
pub x: i32,
pub y: i32,
}
#[derive(Component, Debug, Default, Serialize, Deserialize, Clone)]
pub struct OnDeath {
pub abilities: Vec<SpecialAbility>,
}

View File

@ -51,3 +51,6 @@ pub struct ProvidesIdentification {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Confusion {}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct AlwaysTargetsSelf {}

View File

@ -1,10 +1,13 @@
use ::rltk::RandomNumberGenerator;
use ::specs::prelude::*;
use crate::components::{Equipped, InBackpack, LootTable, Name, Player, Pools, Position};
use crate::components::{
AreaOfEffect, Equipped, InBackpack, LootTable, Name, OnDeath, Player, Pools, Position,
};
use crate::effects::*;
use crate::game_log::GameLog;
use crate::raws::{self, SpawnType, RAWS};
use crate::RunState;
use crate::{Map, RunState};
pub fn delete_the_dead(ecs: &mut World) {
let mut dead: Vec<Entity> = Vec::new();
@ -101,6 +104,42 @@ pub fn delete_the_dead(ecs: &mut World) {
}
}
// Fire death events
for victim in dead.iter() {
let death_effects = ecs.read_storage::<OnDeath>();
if let Some(death_effect) = death_effects.get(*victim) {
let mut rng = ecs.fetch_mut::<RandomNumberGenerator>();
for effect in death_effect.abilities.iter() {
if rng.roll_dice(1, 100) <= (effect.chance * 100.0) as i32 {
let map = ecs.fetch::<Map>();
if let Some(pos) = ecs.read_storage::<Position>().get(*victim) {
let spell_entity =
crate::raws::find_spell_entity(ecs, &effect.spell).unwrap();
let tile_idx = map.xy_idx(pos.x, pos.y);
let target = if let Some(aoe) =
ecs.read_storage::<AreaOfEffect>().get(spell_entity)
{
Targets::Tiles {
tiles: aoe_tiles(&map, rltk::Point::new(pos.x, pos.y), aoe.radius),
}
} else {
Targets::Tile {
tile_idx: tile_idx as i32,
}
};
add_effect(
None,
EffectType::SpellUse {
spell: crate::raws::find_spell_entity(ecs, &effect.spell).unwrap(),
},
target,
);
}
}
}
}
}
for victim in dead {
ecs.delete_entity(victim)
.expect("Unable to delete the dead");

View File

@ -1,15 +1,17 @@
use ::rltk::Point;
use ::specs::prelude::*;
use super::{add_effect, EffectType, Targets};
use crate::components::{
AttributeBonus, Confusion, Consumable, DamageOverTime, Duration, Hidden, InflictsDamage,
MagicMapper, Name, Pools, ProvidesFood, ProvidesHealing, ProvidesIdentification, ProvidesMana,
ProvidesRemoveCurse, SingleActivation, Slow, SpawnParticleBurst, SpawnParticleLine,
SpellTemplate, TeachesSpell, TeleportTo, TownPortal,
AlwaysTargetsSelf, AreaOfEffect, AttributeBonus, Confusion, Consumable, DamageOverTime,
Duration, Hidden, InflictsDamage, KnownSpell, KnownSpells, MagicMapper, Name, Pools, Position,
ProvidesFood, ProvidesHealing, ProvidesIdentification, ProvidesMana, ProvidesRemoveCurse,
SingleActivation, Slow, SpawnParticleBurst, SpawnParticleLine, SpellTemplate, TeachesSpell,
TeleportTo, TownPortal,
};
use crate::effects::{entity_position, targeting};
use crate::effects::{aoe_tiles, entity_position, targeting};
use crate::raws::find_spell_entity;
use crate::{colors, GameLog, KnownSpell, KnownSpells, Map, RunState};
use crate::{colors, GameLog, Map, RunState};
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
// Check charges
@ -44,6 +46,8 @@ pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ec
}
pub fn spell_trigger(creator: Option<Entity>, spell: Entity, targets: &Targets, ecs: &mut World) {
let mut targeting = targets.clone();
let mut self_destruct = false;
if let Some(template) = ecs.read_storage::<SpellTemplate>().get(spell) {
let mut pools = ecs.write_storage::<Pools>();
if let Some(caster) = creator {
@ -52,10 +56,33 @@ pub fn spell_trigger(creator: Option<Entity>, spell: Entity, targets: &Targets,
pool.mana.current -= template.mana_cost;
}
}
}
}
event_trigger(creator, spell, targets, ecs);
// Handle self-targeting override
if ecs.read_storage::<AlwaysTargetsSelf>().get(spell).is_some() {
if let Some(pos) = ecs.read_storage::<Position>().get(caster) {
let map = ecs.fetch::<Map>();
targeting = if let Some(aoe) = ecs.read_storage::<AreaOfEffect>().get(spell) {
Targets::Tiles {
tiles: aoe_tiles(&map, Point::new(pos.x, pos.y), aoe.radius),
}
} else {
Targets::Tile {
tile_idx: map.xy_idx(pos.x, pos.y) as i32,
}
}
}
}
}
if let Some(_destruct) = ecs.read_storage::<SingleActivation>().get(spell) {
self_destruct = true;
}
}
event_trigger(creator, spell, &targeting, ecs);
if self_destruct && creator.is_some() {
ecs.entities()
.delete(creator.unwrap())
.expect("Unable to delete owner");
}
}
pub fn trigger(creator: Option<Entity>, trigger: Entity, targets: &Targets, ecs: &mut World) {
@ -320,7 +347,7 @@ fn event_trigger(
}
fn spawn_line_particles(ecs: &World, start: i32, end: i32, part: &SpawnParticleLine) {
use ::rltk::{LineAlg, Point};
use ::rltk::LineAlg;
let map = ecs.fetch::<Map>();
let start_pt = Point::new(start % map.width, end / map.width);

View File

@ -81,6 +81,7 @@ fn init_state() -> State {
register!(
state <-
AlwaysTargetsSelf,
ApplyMove,
ApplyTeleport,
AreaOfEffect,
@ -120,6 +121,7 @@ fn init_state() -> State {
Name,
NaturalAttackDefense,
ObfuscatedName,
OnDeath,
OtherLevelPosition,
ParticleLifetime,
Player,

View File

@ -25,6 +25,7 @@ pub struct Mob {
pub gold: Option<String>,
pub vendor: Option<Vec<String>>,
pub abilities: Option<Vec<MobAbility>>,
pub on_death: Option<Vec<MobAbility>>,
}
#[derive(Deserialize, Debug)]

View File

@ -337,6 +337,7 @@ macro_rules! apply_effects {
damage: effect.1.parse::<i32>().unwrap(),
})
}
"target_self" => $eb = $eb.with(AlwaysTargetsSelf {}),
_ => {
console::log(format!(
"WARNING: consumable effect '{}' not implemented.",
@ -667,6 +668,20 @@ pub fn spawn_named_mob(
eb = eb.with(a);
}
if let Some(ability_list) = &mob_template.on_death {
let mut a = OnDeath::default();
for ability in ability_list.iter() {
a.abilities.push(SpecialAbility {
chance: ability.chance,
spell: ability.spell.clone(),
range: ability.range,
min_range: ability.min_range,
});
}
eb = eb.with(a);
}
let new_mob = eb.build();
// Are they wielding anything?

View File

@ -60,6 +60,7 @@ pub fn save_game(ecs: &mut World) {
ecs,
serializer,
data,
AlwaysTargetsSelf,
ApplyMove,
ApplyTeleport,
AreaOfEffect,
@ -99,6 +100,7 @@ pub fn save_game(ecs: &mut World) {
Name,
NaturalAttackDefense,
ObfuscatedName,
OnDeath,
OtherLevelPosition,
ParticleLifetime,
Player,
@ -192,6 +194,7 @@ pub fn load_game(ecs: &mut World) {
ecs,
de,
d,
AlwaysTargetsSelf,
ApplyMove,
ApplyTeleport,
AreaOfEffect,
@ -231,6 +234,7 @@ pub fn load_game(ecs: &mut World) {
Name,
NaturalAttackDefense,
ObfuscatedName,
OnDeath,
OtherLevelPosition,
ParticleLifetime,
Player,