1
0
Fork 0

Complete section 5.24

This commit is contained in:
Timothy Warren 2022-01-25 15:04:00 -05:00
parent 52235a571e
commit 408f9e6ab9
6 changed files with 119 additions and 14 deletions

View File

@ -1,9 +1,11 @@
use ::rltk::RandomNumberGenerator;
use ::specs::prelude::*;
use crate::components::{
Chasing, Faction, MyTurn, Position, Viewshed, WantsToApproach, WantsToFlee,
Chasing, Faction, MyTurn, Name, Position, SpecialAbilities, SpellTemplate, Viewshed,
WantsToApproach, WantsToCastSpell, WantsToFlee,
};
use crate::raws::{self, Reaction, RAWS};
use crate::raws::{self, find_spell_entity_by_name, Reaction, RAWS};
use crate::{spatial, Map};
pub struct VisibleAI {}
@ -21,9 +23,15 @@ impl<'a> System<'a> for VisibleAI {
ReadExpect<'a, Entity>,
ReadStorage<'a, Viewshed>,
WriteStorage<'a, Chasing>,
ReadStorage<'a, SpecialAbilities>,
WriteExpect<'a, RandomNumberGenerator>,
WriteStorage<'a, WantsToCastSpell>,
ReadStorage<'a, Name>,
ReadStorage<'a, SpellTemplate>,
);
fn run(&mut self, data: Self::SystemData) {
use ::rltk::{DistanceAlg, Point};
let (
turns,
factions,
@ -35,6 +43,11 @@ impl<'a> System<'a> for VisibleAI {
player,
viewsheds,
mut chasing,
abilities,
mut rng,
mut casting,
names,
spells,
) = data;
for (entity, _turn, my_faction, pos, viewshed) in
@ -55,18 +68,56 @@ impl<'a> System<'a> for VisibleAI {
for reaction in reactions.iter() {
match reaction.1 {
Reaction::Attack => {
want_approach
.insert(
entity,
WantsToApproach {
idx: reaction.0 as i32,
},
)
.expect("Unable to insert intent to approach");
chasing
.insert(entity, Chasing { target: reaction.2 })
.expect("Unable to insert intent to chase");
done = true;
if let Some(abilities) = abilities.get(entity) {
let range = DistanceAlg::Pythagoras.distance2d(
Point::from(*pos),
Point::new(
reaction.0 as i32 % map.width,
reaction.0 as i32 / map.width,
),
);
for ability in abilities.abilities.iter() {
if range >= ability.min_range
&& range <= ability.range
&& rng.roll_dice(1, 100) >= (ability.chance * 100.0) as i32
{
casting
.insert(
entity,
WantsToCastSpell {
spell: find_spell_entity_by_name(
&ability.spell,
&names,
&spells,
&entities,
)
.unwrap(),
target: Some(Point::new(
reaction.0 as i32 % map.width,
reaction.0 as i32 / map.width,
)),
},
)
.expect("Unable to insert intent to cast spell");
done = true;
}
}
}
if !done {
want_approach
.insert(
entity,
WantsToApproach {
idx: reaction.0 as i32,
},
)
.expect("Unable to insert intent to approach");
chasing
.insert(entity, Chasing { target: reaction.2 })
.expect("Unable to insert intent to chase");
done = true;
}
}
Reaction::Flee => {
flee.push(reaction.0);

View File

@ -445,3 +445,16 @@ pub struct Slow {
pub struct DamageOverTime {
pub damage: i32,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SpecialAbility {
pub spell: String,
pub chance: f32,
pub range: f32,
pub min_range: f32,
}
#[derive(Component, Debug, Default, Serialize, Deserialize, Clone)]
pub struct SpecialAbilities {
pub abilities: Vec<SpecialAbility>,
}

View File

@ -140,6 +140,7 @@ fn init_state() -> State {
Slow,
SpawnParticleBurst,
SpawnParticleLine,
SpecialAbilities,
SpellTemplate,
StatusEffect,
TeachesSpell,

View File

@ -24,6 +24,15 @@ pub struct Mob {
pub faction: Option<String>,
pub gold: Option<String>,
pub vendor: Option<Vec<String>>,
pub abilities: Option<Vec<MobAbility>>,
}
#[derive(Deserialize, Debug)]
pub struct MobAbility {
pub spell: String,
pub chance: f32,
pub range: f32,
pub min_range: f32,
}
#[derive(Deserialize, Debug)]

View File

@ -647,6 +647,20 @@ pub fn spawn_named_mob(
})
}
if let Some(ability_list) = &mob_template.abilities {
let mut a = SpecialAbilities::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?
@ -821,3 +835,18 @@ pub fn find_spell_entity(ecs: &World, name: &str) -> Option<Entity> {
None
}
pub fn find_spell_entity_by_name(
name: &str,
names: &ReadStorage<Name>,
spell_templates: &ReadStorage<SpellTemplate>,
entities: &Entities,
) -> Option<Entity> {
for (entity, sname, _template) in (entities, names, spell_templates).join() {
if name == sname.name {
return Some(entity);
}
}
None
}

View File

@ -118,6 +118,7 @@ pub fn save_game(ecs: &mut World) {
Slow,
SpawnParticleBurst,
SpawnParticleLine,
SpecialAbilities,
SpellTemplate,
StatusEffect,
TeachesSpell,
@ -248,6 +249,7 @@ pub fn load_game(ecs: &mut World) {
Skills,
SpawnParticleBurst,
SpawnParticleLine,
SpecialAbilities,
SpellTemplate,
StatusEffect,
TeachesSpell,