diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 7226c44a9c..30473b8c8f 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -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>, @@ -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) -> 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) -> 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>, - 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 { diff --git a/common/src/comp/body/quadruped_low.rs b/common/src/comp/body/quadruped_low.rs index 9b39604c0a..5ddd680500 100644 --- a/common/src/comp/body/quadruped_low.rs +++ b/common/src/comp/body/quadruped_low.rs @@ -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, diff --git a/common/src/comp/body/quadruped_medium.rs b/common/src/comp/body/quadruped_medium.rs index 7f8d36ea0f..708c55db9e 100644 --- a/common/src/comp/body/quadruped_medium.rs +++ b/common/src/comp/body/quadruped_medium.rs @@ -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, diff --git a/common/src/comp/body/quadruped_small.rs b/common/src/comp/body/quadruped_small.rs index 75a5428283..fe0cdd9404 100644 --- a/common/src/comp/body/quadruped_small.rs +++ b/common/src/comp/body/quadruped_small.rs @@ -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, diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 35f012b5bf..562175c12c 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -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 diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 2a7bb6f0a4..e319d789b9 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -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, pv: Vec3) -> 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); diff --git a/server/src/pet.rs b/server/src/pet.rs index 1077b6fe9f..ffef6cc3d9 100644 --- a/server/src/pet.rs +++ b/server/src/pet.rs @@ -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::().get_mut(pet_entity) { + agent.set_no_flee(); + } // Add to group system let clients = ecs.read_storage::(); diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 5121a7193a..c8c9362bc3 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -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)); diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index 589b742592..c68189a39c 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -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 },