mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Made agents flee
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
use crate::{path::Chaser, sync::Uid};
|
use crate::{path::Chaser, sync::Uid, comp::Body};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, Entity as EcsEntity};
|
use specs::{Component, Entity as EcsEntity};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -54,6 +55,33 @@ impl Component for Alignment {
|
|||||||
type Storage = IdvStorage<Self>;
|
type Storage = IdvStorage<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct Psyche {
|
||||||
|
pub aggro: f32, // 0.0 = always flees, 1.0 = always attacks
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Body> for Psyche {
|
||||||
|
fn from(body: &'a Body) -> Self {
|
||||||
|
Self {
|
||||||
|
aggro: match body {
|
||||||
|
Body::Humanoid(_) => 0.8,
|
||||||
|
Body::QuadrupedSmall(_) => 0.35,
|
||||||
|
Body::QuadrupedMedium(_) => 0.5,
|
||||||
|
Body::QuadrupedLow(_) => 0.65,
|
||||||
|
Body::BirdMedium(_) => 1.0,
|
||||||
|
Body::BirdSmall(_) => 0.2,
|
||||||
|
Body::FishMedium(_) => 0.15,
|
||||||
|
Body::FishSmall(_) => 0.0,
|
||||||
|
Body::BipedLarge(_) => 1.0,
|
||||||
|
Body::Object(_) => 0.0,
|
||||||
|
Body::Golem(_) => 1.0,
|
||||||
|
Body::Critter(_) => 0.1,
|
||||||
|
Body::Dragon(_) => 1.0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct Agent {
|
pub struct Agent {
|
||||||
pub patrol_origin: Option<Vec3<f32>>,
|
pub patrol_origin: Option<Vec3<f32>>,
|
||||||
@ -61,6 +89,7 @@ pub struct Agent {
|
|||||||
/// Does the agent talk when e.g. hit by the player
|
/// Does the agent talk when e.g. hit by the player
|
||||||
// TODO move speech patterns into a Behavior component
|
// TODO move speech patterns into a Behavior component
|
||||||
pub can_speak: bool,
|
pub can_speak: bool,
|
||||||
|
pub psyche: Psyche,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Agent {
|
impl Agent {
|
||||||
@ -69,11 +98,12 @@ impl Agent {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(origin: Vec3<f32>, can_speak: bool) -> Self {
|
pub fn new(origin: Vec3<f32>, can_speak: bool, body: &Body) -> Self {
|
||||||
let patrol_origin = Some(origin);
|
let patrol_origin = Some(origin);
|
||||||
Agent {
|
Agent {
|
||||||
patrol_origin,
|
patrol_origin,
|
||||||
can_speak,
|
can_speak,
|
||||||
|
psyche: Psyche::from(body),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ fn walkable<V>(vol: &V, pos: Vec3<i32>) -> bool
|
|||||||
where
|
where
|
||||||
V: BaseVol<Vox = Block> + ReadVol,
|
V: BaseVol<Vox = Block> + ReadVol,
|
||||||
{
|
{
|
||||||
vol.get(pos - Vec3::new(0, 0, 1))
|
(vol.get(pos - Vec3::new(0, 0, 1))
|
||||||
.map(|b| b.is_solid() && b.get_height() == 1.0)
|
.map(|b| b.is_solid() && b.get_height() == 1.0)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
&& vol
|
&& vol
|
||||||
@ -412,7 +412,15 @@ where
|
|||||||
&& vol
|
&& vol
|
||||||
.get(pos + Vec3::new(0, 0, 1))
|
.get(pos + Vec3::new(0, 0, 1))
|
||||||
.map(|b| !b.is_solid())
|
.map(|b| !b.is_solid())
|
||||||
|
.unwrap_or(true))
|
||||||
|
|| (vol
|
||||||
|
.get(pos + Vec3::new(0, 0, 0))
|
||||||
|
.map(|b| b.is_fluid())
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
|
&& vol
|
||||||
|
.get(pos + Vec3::new(0, 0, 1))
|
||||||
|
.map(|b| b.is_fluid())
|
||||||
|
.unwrap_or(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::float_cmp)] // TODO: Pending review in #587
|
#[allow(clippy::float_cmp)] // TODO: Pending review in #587
|
||||||
@ -449,7 +457,7 @@ where
|
|||||||
let heuristic = |pos: &Vec3<i32>| (pos.distance_squared(end) as f32).sqrt();
|
let heuristic = |pos: &Vec3<i32>| (pos.distance_squared(end) as f32).sqrt();
|
||||||
let neighbors = |pos: &Vec3<i32>| {
|
let neighbors = |pos: &Vec3<i32>| {
|
||||||
let pos = *pos;
|
let pos = *pos;
|
||||||
const DIRS: [Vec3<i32>; 17] = [
|
const DIRS: [Vec3<i32>; 18] = [
|
||||||
Vec3::new(0, 1, 0), // Forward
|
Vec3::new(0, 1, 0), // Forward
|
||||||
Vec3::new(0, 1, 1), // Forward upward
|
Vec3::new(0, 1, 1), // Forward upward
|
||||||
Vec3::new(0, 1, 2), // Forward Upwardx2
|
Vec3::new(0, 1, 2), // Forward Upwardx2
|
||||||
@ -466,7 +474,8 @@ where
|
|||||||
Vec3::new(-1, 0, 1), // Left upward
|
Vec3::new(-1, 0, 1), // Left upward
|
||||||
Vec3::new(-1, 0, 2), // Left Upwardx2
|
Vec3::new(-1, 0, 2), // Left Upwardx2
|
||||||
Vec3::new(-1, 0, -1), // Left downward
|
Vec3::new(-1, 0, -1), // Left downward
|
||||||
Vec3::new(0, 0, -1), // Downwards
|
Vec3::new(0, 0, -1), // Downwards (water)
|
||||||
|
Vec3::new(0, 0, 1), // Upwards (water)
|
||||||
];
|
];
|
||||||
|
|
||||||
// let walkable = [
|
// let walkable = [
|
||||||
|
@ -240,6 +240,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
||||||
* speed.min(0.2 + (dist - AVG_FOLLOW_DIST) / 8.0);
|
* speed.min(0.2 + (dist - AVG_FOLLOW_DIST) / 8.0);
|
||||||
inputs.jump.set_state(bearing.z > 1.5);
|
inputs.jump.set_state(bearing.z > 1.5);
|
||||||
|
inputs.swim.set_state(bearing.z > 0.5);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
do_idle = true;
|
do_idle = true;
|
||||||
@ -297,7 +298,37 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let dist_sqrd = pos.0.distance_squared(tgt_pos.0);
|
let dist_sqrd = pos.0.distance_squared(tgt_pos.0);
|
||||||
if dist_sqrd < (MIN_ATTACK_DIST * scale).powf(2.0) {
|
|
||||||
|
let damage = stats
|
||||||
|
.get(entity)
|
||||||
|
.map(|s| s.health.current() as f32 / s.health.maximum() as f32)
|
||||||
|
.unwrap_or(0.5);
|
||||||
|
|
||||||
|
// Flee
|
||||||
|
if 1.0 - agent.psyche.aggro > damage {
|
||||||
|
if let Some((bearing, speed)) = chaser.chase(
|
||||||
|
&*terrain,
|
||||||
|
pos.0,
|
||||||
|
vel.0,
|
||||||
|
// Away from the target (ironically)
|
||||||
|
tgt_pos.0 + (pos.0 - tgt_pos.0)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec3::unit_y) * 32.0,
|
||||||
|
TraversalConfig {
|
||||||
|
node_tolerance,
|
||||||
|
slow_factor,
|
||||||
|
on_ground: physics_state.on_ground,
|
||||||
|
min_tgt_dist: 1.25,
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
inputs.move_dir = Vec2::from(bearing)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or(Vec2::zero())
|
||||||
|
* speed;
|
||||||
|
inputs.jump.set_state(bearing.z > 1.5);
|
||||||
|
inputs.swim.set_state(bearing.z > 0.5);
|
||||||
|
}
|
||||||
|
} else if dist_sqrd < (MIN_ATTACK_DIST * scale).powf(2.0) {
|
||||||
// Close-range attack
|
// Close-range attack
|
||||||
inputs.move_dir = Vec2::from(tgt_pos.0 - pos.0)
|
inputs.move_dir = Vec2::from(tgt_pos.0 - pos.0)
|
||||||
.try_normalized()
|
.try_normalized()
|
||||||
@ -360,6 +391,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
.unwrap_or(Vec2::zero())
|
.unwrap_or(Vec2::zero())
|
||||||
* speed;
|
* speed;
|
||||||
inputs.jump.set_state(bearing.z > 1.5);
|
inputs.jump.set_state(bearing.z > 1.5);
|
||||||
|
inputs.swim.set_state(bearing.z > 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if dist_sqrd < 16.0f32.powf(2.0)
|
if dist_sqrd < 16.0f32.powf(2.0)
|
||||||
|
Reference in New Issue
Block a user