Complete section 5.24
This commit is contained in:
parent
52235a571e
commit
408f9e6ab9
@ -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,6 +68,43 @@ impl<'a> System<'a> for VisibleAI {
|
||||
for reaction in reactions.iter() {
|
||||
match reaction.1 {
|
||||
Reaction::Attack => {
|
||||
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,
|
||||
@ -68,6 +118,7 @@ impl<'a> System<'a> for VisibleAI {
|
||||
.expect("Unable to insert intent to chase");
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
Reaction::Flee => {
|
||||
flee.push(reaction.0);
|
||||
}
|
||||
|
@ -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>,
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ fn init_state() -> State {
|
||||
Slow,
|
||||
SpawnParticleBurst,
|
||||
SpawnParticleLine,
|
||||
SpecialAbilities,
|
||||
SpellTemplate,
|
||||
StatusEffect,
|
||||
TeachesSpell,
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user