Better Agent API

This commit is contained in:
Joshua Barretto 2021-08-02 13:08:39 +01:00
parent b8716e03a6
commit 45f94b0bce
9 changed files with 66 additions and 53 deletions

View File

@ -341,7 +341,7 @@ pub struct Target {
}
#[allow(clippy::type_complexity)]
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
pub struct Agent {
pub rtsim_controller: RtSimController,
pub patrol_origin: Option<Vec3<f32>>,
@ -366,11 +366,43 @@ pub struct ActionState {
}
impl Agent {
pub fn from_body(body: &Body) -> Self {
Agent {
rtsim_controller: RtSimController::default(),
patrol_origin: None,
target: None,
chaser: Chaser::default(),
behavior: Behavior::default(),
psyche: Psyche::from(body),
inbox: VecDeque::new(),
action_state: ActionState::default(),
bearing: Vec2::zero(),
sounds_heard: Vec::new(),
awareness: 0.0,
position_pid_controller: None,
}
}
pub fn with_patrol_origin(mut self, origin: Vec3<f32>) -> Self {
self.patrol_origin = Some(origin);
self
}
pub fn with_behavior(mut self, behavior: Behavior) -> Self {
self.behavior = behavior;
self
}
pub fn with_no_flee(mut self, no_flee: bool) -> Self {
if no_flee {
self.set_no_flee();
}
self
}
pub fn set_no_flee(&mut self) { self.psyche.flee_health = 0.0; }
// TODO: Get rid of this method, it does weird things
pub fn with_destination(mut self, pos: Vec3<f32>) -> Self {
self.psyche.flee_health = 0.0;
self.rtsim_controller = RtSimController::with_destination(pos);
@ -386,27 +418,6 @@ impl Agent {
self.position_pid_controller = Some(pid);
self
}
pub fn new(
patrol_origin: Option<Vec3<f32>>,
body: &Body,
behavior: Behavior,
no_flee: bool,
) -> Self {
Agent {
patrol_origin,
psyche: if no_flee {
Psyche {
flee_health: 0.0,
..Psyche::from(body)
}
} else {
Psyche::from(body)
},
behavior,
..Default::default()
}
}
}
impl Component for Agent {

View File

@ -1,7 +1,7 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};
use strum_macros::{Display, EnumString};
make_proj_elim!(
body,

View File

@ -1,7 +1,7 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};
use strum_macros::{Display, EnumString};
make_proj_elim!(
body,

View File

@ -1,7 +1,7 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use strum::{Display, EnumString};
use strum_macros::{Display, EnumString};
make_proj_elim!(
body,

View File

@ -174,12 +174,11 @@ impl CharacterBehavior for Data {
poise: comp::Poise::new(body),
loadout,
body,
agent: Some(comp::Agent::new(
None,
&body,
Behavior::from(BehaviorCapability::SPEAK),
true,
)),
agent: Some(
comp::Agent::from_body(&body)
.with_behavior(Behavior::from(BehaviorCapability::SPEAK))
.with_no_flee(true),
),
alignment: comp::Alignment::Owned(*data.uid),
scale: self
.static_data

View File

@ -1005,11 +1005,12 @@ fn handle_spawn(
let ai = opt_ai.unwrap_or(true);
let pos = position(server, target, "target")?;
let agent = if let comp::Alignment::Owned(_) | comp::Alignment::Npc = alignment {
comp::Agent::default()
} else {
comp::Agent::default().with_patrol_origin(pos.0)
};
let mut agent = comp::Agent::from_body(&body());
// If unowned, the agent should stay in a particular place
if !matches!(alignment, comp::Alignment::Owned(_)) {
agent = agent.with_patrol_origin(pos.0);
}
for _ in 0..amount {
let vel = Vec3::new(
@ -1160,7 +1161,7 @@ fn handle_spawn_airship(
if let Some(pos) = destination {
let (kp, ki, kd) = comp::agent::pid_coefficients(&comp::Body::Ship(ship));
fn pure_z(sp: Vec3<f32>, pv: Vec3<f32>) -> f32 { (sp - pv).z }
let agent = comp::Agent::default()
let agent = comp::Agent::from_body(&comp::Body::Ship(ship))
.with_destination(pos)
.with_position_pid_controller(comp::PidController::new(kp, ki, kd, pos, 0.0, pure_z));
builder = builder.with(agent);

View File

@ -49,9 +49,9 @@ fn tame_pet_internal(ecs: &specs::World, pet_entity: Entity, owner: Entity, pet:
.write_storage()
.insert(pet_entity, pet.unwrap_or_default());
// TODO: Review whether we should be doing this or not, should the Agent always
// be overwritten when taming a pet?
let _ = ecs.write_storage().insert(pet_entity, Agent::default());
if let Some(agent) = ecs.write_storage::<Agent>().get_mut(pet_entity) {
agent.set_no_flee();
}
// Add to group system
let clients = ecs.read_storage::<Client>();

View File

@ -103,15 +103,12 @@ impl<'a> System<'a> for Sys {
.map(|e| e as f32)
+ Vec3::new(0.5, 0.5, body.flying_height());
let pos = comp::Pos(spawn_pos);
let agent = Some(comp::Agent::new(
None,
&body,
let agent = Some(comp::Agent::from_body(&body).with_behavior(
if matches!(body, comp::Body::Humanoid(_)) {
Behavior::from(BehaviorCapability::SPEAK)
} else {
Behavior::default()
},
false,
));
let rtsim_entity = Some(RtSimEntity(id));

View File

@ -296,16 +296,21 @@ impl<'a> System<'a> for Sys {
poise,
loadout,
agent: if entity.has_agency {
Some(comp::Agent::new(
Some(entity.pos),
&body,
Behavior::default()
.maybe_with_capabilities(
can_speak.then(|| BehaviorCapability::SPEAK),
Some(
comp::Agent::from_body(&body)
.with_behavior(
Behavior::default()
.maybe_with_capabilities(
can_speak.then(|| BehaviorCapability::SPEAK),
)
.with_trade_site(trade_for_site),
)
.with_trade_site(trade_for_site),
matches!(entity.agent_mark, Some(agent::Mark::Guard)),
))
.with_patrol_origin(entity.pos)
.with_no_flee(!matches!(
entity.agent_mark,
Some(agent::Mark::Guard)
)),
)
} else {
None
},