Made agents cleverer

This commit is contained in:
Joshua Barretto
2020-04-19 12:50:25 +01:00
parent 8af3187df4
commit d28f5f24fb
2 changed files with 53 additions and 28 deletions

View File

@ -25,6 +25,7 @@ impl Alignment {
// Never attacks // Never attacks
pub fn passive_towards(self, other: Alignment) -> bool { pub fn passive_towards(self, other: Alignment) -> bool {
match (self, other) { match (self, other) {
(Alignment::Enemy, Alignment::Enemy) => true,
(Alignment::Owned(a), Alignment::Owned(b)) if a == b => true, (Alignment::Owned(a), Alignment::Owned(b)) if a == b => true,
_ => false, _ => false,
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
comp::{self, agent::Activity, Agent, Alignment, Controller, MountState, Ori, Scale, Pos, Stats, Loadout, item::{ItemKind, tool::ToolKind}, CharacterState}, comp::{self, agent::Activity, Agent, Alignment, Controller, ControlAction, MountState, Ori, Scale, Pos, Stats, Loadout, item::{ItemKind, tool::ToolKind}, CharacterState},
path::Chaser, path::Chaser,
state::{Time, DeltaTime}, state::{Time, DeltaTime},
sync::UidAllocator, sync::UidAllocator,
@ -92,7 +92,8 @@ impl<'a> System<'a> for Sys {
const AVG_FOLLOW_DIST: f32 = 6.0; const AVG_FOLLOW_DIST: f32 = 6.0;
const MAX_FOLLOW_DIST: f32 = 12.0; const MAX_FOLLOW_DIST: f32 = 12.0;
const MAX_CHASE_DIST: f32 = 24.0; const MAX_CHASE_DIST: f32 = 24.0;
const SEARCH_DIST: f32 = 30.0; const LISTEN_DIST: f32 = 16.0;
const SEARCH_DIST: f32 = 48.0;
const SIGHT_DIST: f32 = 128.0; const SIGHT_DIST: f32 = 128.0;
const MIN_ATTACK_DIST: f32 = 3.25; const MIN_ATTACK_DIST: f32 = 3.25;
@ -124,7 +125,7 @@ impl<'a> System<'a> for Sys {
+ Vec3::from(*bearing) + Vec3::from(*bearing)
.try_normalized() .try_normalized()
.unwrap_or(Vec3::unit_y()) .unwrap_or(Vec3::unit_y())
* 1.5 * 5.0
+ Vec3::unit_z(), + Vec3::unit_z(),
) )
.until(|block| block.is_solid()) .until(|block| block.is_solid())
@ -142,8 +143,18 @@ impl<'a> System<'a> for Sys {
inputs.move_dir = *bearing * 0.65; inputs.move_dir = *bearing * 0.65;
} }
// Put away weapon
if thread_rng().gen::<f32>() < 0.005 {
controller.actions.push(ControlAction::Unwield);
}
// Sit
if thread_rng().gen::<f32>() < 0.0035 {
controller.actions.push(ControlAction::Sit);
}
// Sometimes try searching for new targets // Sometimes try searching for new targets
if thread_rng().gen::<f32>() < 0.1 { if thread_rng().gen::<f32>() < 0.05 {
choose_target = true; choose_target = true;
} }
}, },
@ -177,9 +188,9 @@ impl<'a> System<'a> for Sys {
.. ..
} => { } => {
enum Tactic { enum Tactic {
Melee, // Attack: primary/secondary Melee,
RangedPowerup, RangedPowerup,
RangedConstant, Staff,
} }
let tactic = match loadout.active_item let tactic = match loadout.active_item
@ -187,7 +198,7 @@ impl<'a> System<'a> for Sys {
.and_then(|ic| if let ItemKind::Tool(tool) = &ic.item.kind { Some(&tool.kind) } else { None}) .and_then(|ic| if let ItemKind::Tool(tool) = &ic.item.kind { Some(&tool.kind) } else { None})
{ {
Some(ToolKind::Bow(_)) => Tactic::RangedPowerup, Some(ToolKind::Bow(_)) => Tactic::RangedPowerup,
Some(ToolKind::Staff(_)) => Tactic::RangedConstant, Some(ToolKind::Staff(_)) => Tactic::Staff,
_ => Tactic::Melee, _ => Tactic::Melee,
}; };
@ -223,34 +234,40 @@ impl<'a> System<'a> for Sys {
if let Tactic::Melee = tactic { if let Tactic::Melee = tactic {
inputs.primary.set_state(true); inputs.primary.set_state(true);
} else if let Tactic::RangedPowerup = tactic { } else if let Tactic::Staff = tactic {
inputs.primary.set_state(true); inputs.primary.set_state(true);
} else { } else {
inputs.move_dir = -Vec2::from(tgt_pos.0 - pos.0) inputs.roll.set_state(true);
.try_normalized()
.unwrap_or(Vec2::unit_y());
} }
} else if dist_sqrd < MAX_CHASE_DIST.powf(2.0) } else if dist_sqrd < MAX_CHASE_DIST.powf(2.0)
|| (dist_sqrd < SIGHT_DIST.powf(2.0) && !*been_close) || (dist_sqrd < SIGHT_DIST.powf(2.0) && !*been_close)
{ {
if let Tactic::RangedPowerup = tactic { let can_see_tgt = terrain
if *powerup > 2.0 { .ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
inputs.primary.set_state(false); .until(|block| !block.is_air())
*powerup = 0.0; .cast()
} else { .0.powf(2.0) >= dist_sqrd;
inputs.primary.set_state(true);
*powerup += dt.0; if can_see_tgt {
} if let Tactic::RangedPowerup = tactic {
} else if let Tactic::RangedConstant = tactic { if *powerup > 2.0 {
if !character_state.is_wield() { inputs.primary.set_state(false);
inputs.primary.set_state(true); *powerup = 0.0;
} else {
inputs.primary.set_state(true);
*powerup += dt.0;
}
} else if let Tactic::Staff = tactic {
if !character_state.is_wield() {
inputs.primary.set_state(true);
}
inputs.secondary.set_state(true);
} }
inputs.secondary.set_state(true); if dist_sqrd < MAX_CHASE_DIST.powf(2.0) {
} *been_close = true;
}
if dist_sqrd < MAX_CHASE_DIST.powf(2.0) {
*been_close = true;
} }
// Long-range chase // Long-range chase
@ -290,13 +307,20 @@ impl<'a> System<'a> for Sys {
let closest_entity = (&entities, &positions, &stats, alignments.maybe()) let closest_entity = (&entities, &positions, &stats, alignments.maybe())
.join() .join()
.filter(|(e, e_pos, e_stats, e_alignment)| { .filter(|(e, e_pos, e_stats, e_alignment)| {
e_pos.0.distance_squared(pos.0) < SEARCH_DIST.powf(2.0) ((e_pos.0.distance_squared(pos.0) < SEARCH_DIST.powf(2.0) && (e_pos.0 - pos.0).try_normalized().map(|v| v.dot(*inputs.look_dir) > 0.3).unwrap_or(true))
|| e_pos.0.distance_squared(pos.0) < LISTEN_DIST.powf(2.0))
&& *e != entity && *e != entity
&& !e_stats.is_dead && !e_stats.is_dead
&& alignment && alignment
.and_then(|a| e_alignment.map(|b| a.hostile_towards(*b))) .and_then(|a| e_alignment.map(|b| a.hostile_towards(*b)))
.unwrap_or(false) .unwrap_or(false)
}) })
// Can we even see them?
.filter(|(_, e_pos, _, _)| terrain
.ray(pos.0 + Vec3::unit_z(), e_pos.0 + Vec3::unit_z())
.until(|block| !block.is_air())
.cast()
.0 >= e_pos.0.distance(pos.0))
.min_by_key(|(_, e_pos, _, _)| (e_pos.0.distance_squared(pos.0) * 100.0) as i32) .min_by_key(|(_, e_pos, _, _)| (e_pos.0.distance_squared(pos.0) * 100.0) as i32)
.map(|(e, _, _, _)| e); .map(|(e, _, _, _)| e);