Complete section 5.26
This commit is contained in:
parent
051be94bc9
commit
a40f43b839
@ -521,3 +521,8 @@ pub struct TileSize {
|
|||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct OnDeath {
|
||||||
|
pub abilities: Vec<SpecialAbility>,
|
||||||
|
}
|
||||||
|
@ -51,3 +51,6 @@ pub struct ProvidesIdentification {}
|
|||||||
|
|
||||||
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Confusion {}
|
pub struct Confusion {}
|
||||||
|
|
||||||
|
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct AlwaysTargetsSelf {}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
use ::rltk::RandomNumberGenerator;
|
use ::rltk::RandomNumberGenerator;
|
||||||
use ::specs::prelude::*;
|
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::game_log::GameLog;
|
||||||
use crate::raws::{self, SpawnType, RAWS};
|
use crate::raws::{self, SpawnType, RAWS};
|
||||||
use crate::RunState;
|
use crate::{Map, RunState};
|
||||||
|
|
||||||
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();
|
||||||
@ -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 {
|
for victim in dead {
|
||||||
ecs.delete_entity(victim)
|
ecs.delete_entity(victim)
|
||||||
.expect("Unable to delete the dead");
|
.expect("Unable to delete the dead");
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
use ::rltk::Point;
|
||||||
use ::specs::prelude::*;
|
use ::specs::prelude::*;
|
||||||
|
|
||||||
use super::{add_effect, EffectType, Targets};
|
use super::{add_effect, EffectType, Targets};
|
||||||
use crate::components::{
|
use crate::components::{
|
||||||
AttributeBonus, Confusion, Consumable, DamageOverTime, Duration, Hidden, InflictsDamage,
|
AlwaysTargetsSelf, AreaOfEffect, AttributeBonus, Confusion, Consumable, DamageOverTime,
|
||||||
MagicMapper, Name, Pools, ProvidesFood, ProvidesHealing, ProvidesIdentification, ProvidesMana,
|
Duration, Hidden, InflictsDamage, KnownSpell, KnownSpells, MagicMapper, Name, Pools, Position,
|
||||||
ProvidesRemoveCurse, SingleActivation, Slow, SpawnParticleBurst, SpawnParticleLine,
|
ProvidesFood, ProvidesHealing, ProvidesIdentification, ProvidesMana, ProvidesRemoveCurse,
|
||||||
SpellTemplate, TeachesSpell, TeleportTo, TownPortal,
|
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::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) {
|
pub fn item_trigger(creator: Option<Entity>, item: Entity, targets: &Targets, ecs: &mut World) {
|
||||||
// Check charges
|
// 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) {
|
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) {
|
if let Some(template) = ecs.read_storage::<SpellTemplate>().get(spell) {
|
||||||
let mut pools = ecs.write_storage::<Pools>();
|
let mut pools = ecs.write_storage::<Pools>();
|
||||||
if let Some(caster) = creator {
|
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;
|
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) {
|
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) {
|
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 map = ecs.fetch::<Map>();
|
||||||
let start_pt = Point::new(start % map.width, end / map.width);
|
let start_pt = Point::new(start % map.width, end / map.width);
|
||||||
|
@ -81,6 +81,7 @@ fn init_state() -> State {
|
|||||||
|
|
||||||
register!(
|
register!(
|
||||||
state <-
|
state <-
|
||||||
|
AlwaysTargetsSelf,
|
||||||
ApplyMove,
|
ApplyMove,
|
||||||
ApplyTeleport,
|
ApplyTeleport,
|
||||||
AreaOfEffect,
|
AreaOfEffect,
|
||||||
@ -120,6 +121,7 @@ fn init_state() -> State {
|
|||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
ObfuscatedName,
|
ObfuscatedName,
|
||||||
|
OnDeath,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
|
@ -25,6 +25,7 @@ pub struct Mob {
|
|||||||
pub gold: Option<String>,
|
pub gold: Option<String>,
|
||||||
pub vendor: Option<Vec<String>>,
|
pub vendor: Option<Vec<String>>,
|
||||||
pub abilities: Option<Vec<MobAbility>>,
|
pub abilities: Option<Vec<MobAbility>>,
|
||||||
|
pub on_death: Option<Vec<MobAbility>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -337,6 +337,7 @@ macro_rules! apply_effects {
|
|||||||
damage: effect.1.parse::<i32>().unwrap(),
|
damage: effect.1.parse::<i32>().unwrap(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
"target_self" => $eb = $eb.with(AlwaysTargetsSelf {}),
|
||||||
_ => {
|
_ => {
|
||||||
console::log(format!(
|
console::log(format!(
|
||||||
"WARNING: consumable effect '{}' not implemented.",
|
"WARNING: consumable effect '{}' not implemented.",
|
||||||
@ -667,6 +668,20 @@ pub fn spawn_named_mob(
|
|||||||
eb = eb.with(a);
|
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();
|
let new_mob = eb.build();
|
||||||
|
|
||||||
// Are they wielding anything?
|
// Are they wielding anything?
|
||||||
|
@ -60,6 +60,7 @@ pub fn save_game(ecs: &mut World) {
|
|||||||
ecs,
|
ecs,
|
||||||
serializer,
|
serializer,
|
||||||
data,
|
data,
|
||||||
|
AlwaysTargetsSelf,
|
||||||
ApplyMove,
|
ApplyMove,
|
||||||
ApplyTeleport,
|
ApplyTeleport,
|
||||||
AreaOfEffect,
|
AreaOfEffect,
|
||||||
@ -99,6 +100,7 @@ pub fn save_game(ecs: &mut World) {
|
|||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
ObfuscatedName,
|
ObfuscatedName,
|
||||||
|
OnDeath,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
@ -192,6 +194,7 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
ecs,
|
ecs,
|
||||||
de,
|
de,
|
||||||
d,
|
d,
|
||||||
|
AlwaysTargetsSelf,
|
||||||
ApplyMove,
|
ApplyMove,
|
||||||
ApplyTeleport,
|
ApplyTeleport,
|
||||||
AreaOfEffect,
|
AreaOfEffect,
|
||||||
@ -231,6 +234,7 @@ pub fn load_game(ecs: &mut World) {
|
|||||||
Name,
|
Name,
|
||||||
NaturalAttackDefense,
|
NaturalAttackDefense,
|
||||||
ObfuscatedName,
|
ObfuscatedName,
|
||||||
|
OnDeath,
|
||||||
OtherLevelPosition,
|
OtherLevelPosition,
|
||||||
ParticleLifetime,
|
ParticleLifetime,
|
||||||
Player,
|
Player,
|
||||||
|
Loading…
Reference in New Issue
Block a user