mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Made agents cleverer
This commit is contained in:
parent
8af3187df4
commit
d28f5f24fb
@ -25,6 +25,7 @@ impl Alignment {
|
||||
// Never attacks
|
||||
pub fn passive_towards(self, other: Alignment) -> bool {
|
||||
match (self, other) {
|
||||
(Alignment::Enemy, Alignment::Enemy) => true,
|
||||
(Alignment::Owned(a), Alignment::Owned(b)) if a == b => true,
|
||||
_ => false,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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,
|
||||
state::{Time, DeltaTime},
|
||||
sync::UidAllocator,
|
||||
@ -92,7 +92,8 @@ impl<'a> System<'a> for Sys {
|
||||
const AVG_FOLLOW_DIST: f32 = 6.0;
|
||||
const MAX_FOLLOW_DIST: f32 = 12.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 MIN_ATTACK_DIST: f32 = 3.25;
|
||||
|
||||
@ -124,7 +125,7 @@ impl<'a> System<'a> for Sys {
|
||||
+ Vec3::from(*bearing)
|
||||
.try_normalized()
|
||||
.unwrap_or(Vec3::unit_y())
|
||||
* 1.5
|
||||
* 5.0
|
||||
+ Vec3::unit_z(),
|
||||
)
|
||||
.until(|block| block.is_solid())
|
||||
@ -142,8 +143,18 @@ impl<'a> System<'a> for Sys {
|
||||
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
|
||||
if thread_rng().gen::<f32>() < 0.1 {
|
||||
if thread_rng().gen::<f32>() < 0.05 {
|
||||
choose_target = true;
|
||||
}
|
||||
},
|
||||
@ -177,9 +188,9 @@ impl<'a> System<'a> for Sys {
|
||||
..
|
||||
} => {
|
||||
enum Tactic {
|
||||
Melee, // Attack: primary/secondary
|
||||
Melee,
|
||||
RangedPowerup,
|
||||
RangedConstant,
|
||||
Staff,
|
||||
}
|
||||
|
||||
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})
|
||||
{
|
||||
Some(ToolKind::Bow(_)) => Tactic::RangedPowerup,
|
||||
Some(ToolKind::Staff(_)) => Tactic::RangedConstant,
|
||||
Some(ToolKind::Staff(_)) => Tactic::Staff,
|
||||
_ => Tactic::Melee,
|
||||
};
|
||||
|
||||
@ -223,34 +234,40 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
if let Tactic::Melee = tactic {
|
||||
inputs.primary.set_state(true);
|
||||
} else if let Tactic::RangedPowerup = tactic {
|
||||
} else if let Tactic::Staff = tactic {
|
||||
inputs.primary.set_state(true);
|
||||
} else {
|
||||
inputs.move_dir = -Vec2::from(tgt_pos.0 - pos.0)
|
||||
.try_normalized()
|
||||
.unwrap_or(Vec2::unit_y());
|
||||
inputs.roll.set_state(true);
|
||||
}
|
||||
} else if dist_sqrd < MAX_CHASE_DIST.powf(2.0)
|
||||
|| (dist_sqrd < SIGHT_DIST.powf(2.0) && !*been_close)
|
||||
{
|
||||
if let Tactic::RangedPowerup = tactic {
|
||||
if *powerup > 2.0 {
|
||||
inputs.primary.set_state(false);
|
||||
*powerup = 0.0;
|
||||
} else {
|
||||
inputs.primary.set_state(true);
|
||||
*powerup += dt.0;
|
||||
}
|
||||
} else if let Tactic::RangedConstant = tactic {
|
||||
if !character_state.is_wield() {
|
||||
inputs.primary.set_state(true);
|
||||
let can_see_tgt = terrain
|
||||
.ray(pos.0 + Vec3::unit_z(), tgt_pos.0 + Vec3::unit_z())
|
||||
.until(|block| !block.is_air())
|
||||
.cast()
|
||||
.0.powf(2.0) >= dist_sqrd;
|
||||
|
||||
if can_see_tgt {
|
||||
if let Tactic::RangedPowerup = tactic {
|
||||
if *powerup > 2.0 {
|
||||
inputs.primary.set_state(false);
|
||||
*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
|
||||
@ -290,13 +307,20 @@ impl<'a> System<'a> for Sys {
|
||||
let closest_entity = (&entities, &positions, &stats, alignments.maybe())
|
||||
.join()
|
||||
.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_stats.is_dead
|
||||
&& alignment
|
||||
.and_then(|a| e_alignment.map(|b| a.hostile_towards(*b)))
|
||||
.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)
|
||||
.map(|(e, _, _, _)| e);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user