diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index e5673bfc98..d6349628f4 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -10,7 +10,7 @@ use specs_idvs::IdvStorage; use std::collections::VecDeque; use vek::*; -use super::dialogue::Subject; +use super::{dialogue::Subject, Behavior}; pub const DEFAULT_INTERACTION_TIME: f32 = 3.0; pub const TRADE_INTERACTION_TIME: f32 = 300.0; @@ -210,6 +210,7 @@ pub struct Agent { pub patrol_origin: Option>, pub target: Option, pub chaser: Chaser, + pub behavior: Behavior, pub psyche: Psyche, pub inbox: VecDeque, pub action_timer: f32, @@ -217,20 +218,26 @@ pub struct Agent { } impl Agent { - pub fn with_patrol_origin(mut self, origin: Vec3) -> Self { + pub fn set_patrol_origin(mut self, origin: Vec3) -> Self { self.patrol_origin = Some(origin); self } - pub fn with_destination(pos: Vec3) -> Self { + pub fn with_destination(behavior: Behavior, pos: Vec3) -> Self { Self { psyche: Psyche { aggro: 1.0 }, rtsim_controller: RtSimController::with_destination(pos), + behavior, ..Default::default() } } - pub fn new(patrol_origin: Option>, body: &Body, no_flee: bool) -> Self { + pub fn new( + patrol_origin: Option>, + body: &Body, + behavior: Behavior, + no_flee: bool, + ) -> Self { Agent { patrol_origin, psyche: if no_flee { @@ -238,6 +245,7 @@ impl Agent { } else { Psyche::from(body) }, + behavior, ..Default::default() } } diff --git a/common/src/comp/behavior.rs b/common/src/comp/behavior.rs index f57ee7beb2..84e3bbdf89 100644 --- a/common/src/comp/behavior.rs +++ b/common/src/comp/behavior.rs @@ -1,16 +1,13 @@ -use specs::Component; -use specs_idvs::IdvStorage; - use crate::trade::SiteId; -bitflags! { +bitflags::bitflags! { #[derive(Default)] pub struct BehaviorCapability: u8 { const SPEAK = 0b00000001; const TRADE = 0b00000010; } } -bitflags! { +bitflags::bitflags! { #[derive(Default)] pub struct BehaviorState: u8 { const TRADING = 0b00000001; @@ -66,10 +63,6 @@ impl Behavior { pub fn is(&self, state: BehaviorState) -> bool { self.state.contains(state) } } -impl Component for Behavior { - type Storage = IdvStorage; -} - #[cfg(test)] mod tests { use super::{Behavior, BehaviorCapability, BehaviorState}; diff --git a/common/src/event.rs b/common/src/event.rs index 5240643991..db2e7e1a40 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -120,7 +120,6 @@ pub enum ServerEvent { loadout: comp::inventory::loadout::Loadout, body: comp::Body, agent: Option, - behavior: Option, alignment: comp::Alignment, scale: comp::Scale, home_chunk: Option, diff --git a/common/src/lib.rs b/common/src/lib.rs index a37812d95e..c78e861453 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -18,8 +18,6 @@ type_alias_impl_trait )] -#[macro_use] extern crate bitflags; - /// Re-exported crates pub use uuid; diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index f27e1e6951..86f3f857fd 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -104,8 +104,12 @@ impl CharacterBehavior for Data { poise: comp::Poise::new(body), loadout, body, - agent: Some(comp::Agent::new(None, &body, true)), - behavior: Some(Behavior::from(BehaviorCapability::SPEAK)), + agent: Some(comp::Agent::new( + None, + &body, + Behavior::from(BehaviorCapability::SPEAK), + true, + )), alignment: comp::Alignment::Owned(*data.uid), scale: self .static_data diff --git a/common/sys/src/state.rs b/common/sys/src/state.rs index 0c0fe24bac..ca31775284 100644 --- a/common/sys/src/state.rs +++ b/common/sys/src/state.rs @@ -198,7 +198,6 @@ impl State { ecs.register::>(); ecs.register::(); ecs.register::(); - ecs.register::(); ecs.register::(); ecs.register::(); ecs.register::(); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index c44abda3c8..96d73e625d 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -31,6 +31,7 @@ use common_net::{ sync::WorldSyncExt, }; use common_sys::state::BuildAreas; +use comp::Behavior; use rand::Rng; use specs::{Builder, Entity as EcsEntity, Join, WorldExt}; use std::{ @@ -888,7 +889,7 @@ fn handle_spawn( if let comp::Alignment::Owned(_) | comp::Alignment::Npc = alignment { comp::Agent::default() } else { - comp::Agent::default().with_patrol_origin(pos.0) + comp::Agent::default().set_patrol_origin(pos.0) }; for _ in 0..amount { @@ -1074,8 +1075,10 @@ fn handle_spawn_airship( animated: true, }); if let Some(pos) = destination { - builder = builder.with(comp::Agent::with_destination(pos)); - builder = builder.with(comp::Behavior::from(BehaviorCapability::SPEAK)) + builder = builder.with(comp::Agent::with_destination( + Behavior::from(BehaviorCapability::SPEAK), + pos, + )); } builder.build(); diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index 652a045e5a..ed9c515d32 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -7,9 +7,8 @@ use common::{ beam, buff::{BuffCategory, BuffData, BuffKind, BuffSource}, inventory::loadout::Loadout, - shockwave, Agent, Alignment, Behavior, Body, Gravity, Health, HomeChunk, Inventory, Item, - ItemDrop, LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, - WaypointArea, + shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop, + LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea, }, outcome::Outcome, rtsim::RtSimEntity, @@ -55,7 +54,6 @@ pub fn handle_create_npc( loadout: Loadout, body: Body, agent: impl Into>, - behavior: Option, alignment: Alignment, scale: Scale, drop_item: Option, @@ -76,8 +74,6 @@ pub fn handle_create_npc( entity }; - let entity = entity.with(behavior.unwrap_or_default()); - let entity = if let Some(drop_item) = drop_item { entity.with(ItemDrop(drop_item)) } else { diff --git a/server/src/events/invite.rs b/server/src/events/invite.rs index 430bc44b8c..47aadb64d2 100644 --- a/server/src/events/invite.rs +++ b/server/src/events/invite.rs @@ -6,7 +6,7 @@ use common::{ agent::{Agent, AgentEvent}, group::GroupManager, invite::{Invite, InviteKind, InviteResponse, PendingInvites}, - Behavior, ChatType, + ChatType, }, trade::Trades, uid::Uid, @@ -167,7 +167,6 @@ pub fn handle_invite_accept(server: &mut Server, entity: specs::Entity) { let clients = state.ecs().read_storage::(); let uids = state.ecs().read_storage::(); let mut agents = state.ecs().write_storage::(); - let behaviors = state.ecs().read_storage::(); let mut invites = state.ecs().write_storage::(); if let Some((inviter, kind)) = invites.remove(entity).and_then(|invite| { let Invite { inviter, kind } = invite; @@ -224,13 +223,13 @@ pub fn handle_invite_accept(server: &mut Server, entity: specs::Entity) { .inbox .push_front(AgentEvent::TradeAccepted(invitee_uid)); } - let pricing = behaviors + let pricing = agents .get(inviter) - .and_then(|b| b.trade_site.map(|id| index.get_site_prices(id))) + .and_then(|a| a.behavior.trade_site.map(|id| index.get_site_prices(id))) .or_else(|| { - behaviors - .get(entity) - .and_then(|b| b.trade_site.map(|id| index.get_site_prices(id))) + agents.get(entity).and_then(|a| { + a.behavior.trade_site.map(|id| index.get_site_prices(id)) + }) }) .flatten(); clients.get(inviter).map(|c| { diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index 0186674ebf..348b0043ca 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -142,7 +142,6 @@ impl Server { loadout, body, agent, - behavior, alignment, scale, home_chunk, @@ -157,7 +156,6 @@ impl Server { loadout, body, agent, - behavior, alignment, scale, drop_item, diff --git a/server/src/events/trade.rs b/server/src/events/trade.rs index 70f637f6cf..7c1d6c792d 100644 --- a/server/src/events/trade.rs +++ b/server/src/events/trade.rs @@ -3,7 +3,6 @@ use common::{ comp::{ agent::{Agent, AgentEvent}, inventory::{item::MaterialStatManifest, Inventory}, - Behavior, }, trade::{PendingTrade, ReducedInventory, TradeAction, TradeId, TradeResult, Trades}, }; @@ -29,13 +28,12 @@ fn notify_agent_simple( fn notify_agent_prices( mut agents: specs::WriteStorage, - behaviors: specs::ReadStorage, index: &IndexOwned, entity: EcsEntity, event: AgentEvent, ) { - if let (Some(agent), Some(behavior)) = (agents.get_mut(entity), behaviors.get(entity)) { - if let Some(site_id) = behavior.trade_site { + if let Some(agent) = agents.get_mut(entity) { + if let Some(site_id) = agent.behavior.trade_site { let prices = index.get_site_prices(site_id); if let AgentEvent::UpdatePendingTrade(boxval) = event { // Box<(tid, pend, _, inventories)>) = event { @@ -108,7 +106,6 @@ pub fn handle_process_trade_action( let mut inventories: [Option; 2] = [None, None]; let mut prices = None; let agents = server.state.ecs().read_storage::(); - let behaviors = server.state.ecs().read_storage::(); // sadly there is no map and collect on arrays for i in 0..2 { // parties.len()) { @@ -123,10 +120,12 @@ pub fn handle_process_trade_action( // Get price info from the first Agent in the trade (currently, an // Agent will never initiate a trade with another agent though) prices = prices.or_else(|| { - behaviors + agents .get(e) - .and_then(|b| { - b.trade_site.map(|id| server.index.get_site_prices(id)) + .and_then(|a| { + a.behavior + .trade_site + .map(|id| server.index.get_site_prices(id)) }) .flatten() }); @@ -145,7 +144,6 @@ pub fn handle_process_trade_action( ); notify_agent_prices( server.state.ecs().write_storage::(), - server.state.ecs().read_storage::(), &server.index, e, AgentEvent::UpdatePendingTrade(Box::new(( diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index 48dc60a44d..fa526e995d 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -103,9 +103,17 @@ 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, false)); - let behavior = matches!(body, comp::Body::Humanoid(_)) - .then(|| Behavior::from(BehaviorCapability::SPEAK)); + let agent = Some(comp::Agent::new( + None, + &body, + if matches!(body, comp::Body::Humanoid(_)) { + Behavior::from(BehaviorCapability::SPEAK) + } else { + Behavior::default() + }, + false, + )); + let rtsim_entity = Some(RtSimEntity(id)); let event = match body { comp::Body::Ship(ship) => ServerEvent::CreateShip { @@ -126,7 +134,6 @@ impl<'a> System<'a> for Sys { poise: comp::Poise::new(body), body, agent, - behavior, alignment: match body { comp::Body::Humanoid(_) => comp::Alignment::Npc, _ => comp::Alignment::Wild, diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index cfb951e7dd..1110c5bfd1 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -14,9 +14,9 @@ use common::{ ItemDesc, ItemKind, }, skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill}, - Agent, Alignment, Behavior, BehaviorCapability, BehaviorState, Body, CharacterState, - ControlAction, ControlEvent, Controller, Energy, Health, InputKind, Inventory, - LightEmitter, MountState, Ori, PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg, Vel, + Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterState, ControlAction, + ControlEvent, Controller, Energy, Health, InputKind, Inventory, LightEmitter, MountState, + Ori, PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg, Vel, }, event::{Emitter, EventBus, ServerEvent}, path::TraversalConfig, @@ -121,7 +121,6 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Agent>, WriteStorage<'a, Controller>, WriteExpect<'a, RtSim>, - WriteStorage<'a, Behavior>, ); const NAME: &'static str = "agent"; @@ -131,7 +130,7 @@ impl<'a> System<'a> for Sys { #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 fn run( job: &mut Job, - (read_data, event_bus, mut agents, mut controllers, mut rtsim, mut behaviors): Self::SystemData, + (read_data, event_bus, mut agents, mut controllers, mut rtsim): Self::SystemData, ) { let rtsim = &mut *rtsim; job.cpu_stats.measure(ParMode::Rayon); @@ -154,10 +153,9 @@ impl<'a> System<'a> for Sys { read_data.groups.maybe(), read_data.mount_states.maybe(), &read_data.char_states, - &mut behaviors, ) .par_join() - .filter(|(_, _, _, _, _, _, _, _, _, _, _, _, mount_state, _, _)| { + .filter(|(_, _, _, _, _, _, _, _, _, _, _, _, mount_state, _)| { // Skip mounted entities mount_state .map(|ms| *ms == MountState::Unmounted) @@ -184,7 +182,6 @@ impl<'a> System<'a> for Sys { groups, _, char_state, - behavior, )| { //// Hack, replace with better system when groups are more sophisticated //// Override alignment if in a group unless entity is owned already @@ -318,7 +315,6 @@ impl<'a> System<'a> for Sys { if hostile { data.hostile_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -396,7 +392,6 @@ impl<'a> System<'a> for Sys { } else { data.idle_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -406,7 +401,6 @@ impl<'a> System<'a> for Sys { } else { data.idle_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -414,23 +408,11 @@ impl<'a> System<'a> for Sys { } } else { agent.target = None; - data.idle_tree( - agent, - behavior, - controller, - &read_data, - &mut event_emitter, - ); + data.idle_tree(agent, controller, &read_data, &mut event_emitter); } } else { agent.target = None; - data.idle_tree( - agent, - behavior, - controller, - &read_data, - &mut event_emitter, - ); + data.idle_tree(agent, controller, &read_data, &mut event_emitter); } } else { // Target an entity that's attacking us if the attack was recent and we @@ -454,7 +436,6 @@ impl<'a> System<'a> for Sys { agent.target = None; data.idle_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -495,7 +476,6 @@ impl<'a> System<'a> for Sys { agent.target = None; data.idle_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -506,7 +486,6 @@ impl<'a> System<'a> for Sys { agent.target = None; data.idle_tree( agent, - behavior, controller, &read_data, &mut event_emitter, @@ -514,13 +493,7 @@ impl<'a> System<'a> for Sys { } }, _ => { - data.idle_tree( - agent, - behavior, - controller, - &read_data, - &mut event_emitter, - ); + data.idle_tree(agent, controller, &read_data, &mut event_emitter); }, } } @@ -554,7 +527,6 @@ impl<'a> AgentData<'a> { fn idle_tree( &self, agent: &mut Agent, - behavior: &mut Behavior, controller: &mut Controller, read_data: &ReadData, event_emitter: &mut Emitter<'_, ServerEvent>, @@ -577,13 +549,13 @@ impl<'a> AgentData<'a> { } if agent.action_timer > 0.0 { if agent.action_timer - < (if behavior.is(BehaviorState::TRADING) { + < (if agent.behavior.is(BehaviorState::TRADING) { TRADE_INTERACTION_TIME } else { DEFAULT_INTERACTION_TIME }) { - self.interact(agent, behavior, controller, &read_data, event_emitter); + self.interact(agent, controller, &read_data, event_emitter); } else { agent.action_timer = 0.0; agent.target = None; @@ -591,7 +563,7 @@ impl<'a> AgentData<'a> { self.idle(agent, controller, &read_data); } } else if thread_rng().gen::() < 0.1 { - self.choose_target(agent, behavior, controller, &read_data, event_emitter); + self.choose_target(agent, controller, &read_data, event_emitter); } else { self.idle(agent, controller, &read_data); } @@ -600,7 +572,6 @@ impl<'a> AgentData<'a> { fn hostile_tree( &self, agent: &mut Agent, - behavior: &mut Behavior, controller: &mut Controller, read_data: &ReadData, event_emitter: &mut Emitter<'_, ServerEvent>, @@ -615,7 +586,7 @@ impl<'a> AgentData<'a> { let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0); // Should the agent flee? if 1.0 - agent.psyche.aggro > self.damage && self.flees { - if agent.action_timer == 0.0 && behavior.can(BehaviorCapability::SPEAK) { + if agent.action_timer == 0.0 && agent.behavior.can(BehaviorCapability::SPEAK) { let msg = "npc.speech.villager_under_attack".to_string(); event_emitter .emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); @@ -643,7 +614,7 @@ impl<'a> AgentData<'a> { read_data.buffs.get(target), ) { agent.target = None; - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { let msg = "npc.speech.villager_enemy_killed".to_string(); event_emitter .emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); @@ -654,7 +625,7 @@ impl<'a> AgentData<'a> { // weapon, etc, into the decision to change // target. } else if read_data.time.0 - selected_at > RETARGETING_THRESHOLD_SECONDS { - self.choose_target(agent, behavior, controller, &read_data, event_emitter); + self.choose_target(agent, controller, &read_data, event_emitter); } else if dist_sqrd < SIGHT_DIST.powi(2) { self.attack( agent, @@ -884,7 +855,6 @@ impl<'a> AgentData<'a> { fn interact( &self, agent: &mut Agent, - behavior: &mut Behavior, controller: &mut Controller, read_data: &ReadData, event_emitter: &mut Emitter<'_, ServerEvent>, @@ -907,7 +877,7 @@ impl<'a> AgentData<'a> { let msg = agent.inbox.pop_back(); match msg { Some(AgentEvent::Talk(by, subject)) => { - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { if let Some(target) = read_data.uid_allocator.retrieve_entity_internal(by.id()) { agent.target = Some(Target { @@ -960,7 +930,7 @@ impl<'a> AgentData<'a> { event_emitter.emit(ServerEvent::Chat( UnresolvedChatMsg::npc(*self.uid, msg), )); - } else if behavior.can(BehaviorCapability::TRADE) { + } else if agent.behavior.can(BehaviorCapability::TRADE) { let msg = "npc.speech.merchant_advertisement".to_string(); event_emitter.emit(ServerEvent::Chat( UnresolvedChatMsg::npc(*self.uid, msg), @@ -973,8 +943,8 @@ impl<'a> AgentData<'a> { } }, Subject::Trade => { - if behavior.can(BehaviorCapability::TRADE) { - if !behavior.is(BehaviorState::TRADING) { + if agent.behavior.can(BehaviorCapability::TRADE) { + if !agent.behavior.is(BehaviorState::TRADING) { controller.events.push(ControlEvent::InitiateInvite( by, InviteKind::Trade, @@ -1122,8 +1092,8 @@ impl<'a> AgentData<'a> { } }, Some(AgentEvent::TradeInvite(with)) => { - if behavior.can(BehaviorCapability::TRADE) { - if !behavior.is(BehaviorState::TRADING) { + if agent.behavior.can(BehaviorCapability::TRADE) { + if !agent.behavior.is(BehaviorState::TRADING) { // stand still and looking towards the trading player controller.actions.push(ControlAction::Stand); controller.actions.push(ControlAction::Talk); @@ -1139,13 +1109,13 @@ impl<'a> AgentData<'a> { controller .events .push(ControlEvent::InviteResponse(InviteResponse::Accept)); - behavior.unset(BehaviorState::TRADING_ISSUER); - behavior.set(BehaviorState::TRADING); + agent.behavior.unset(BehaviorState::TRADING_ISSUER); + agent.behavior.set(BehaviorState::TRADING); } else { controller .events .push(ControlEvent::InviteResponse(InviteResponse::Decline)); - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc( *self.uid, "npc.speech.merchant_busy".to_string(), @@ -1157,7 +1127,7 @@ impl<'a> AgentData<'a> { controller .events .push(ControlEvent::InviteResponse(InviteResponse::Decline)); - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc( *self.uid, "npc.speech.villager_decline_trade".to_string(), @@ -1166,7 +1136,7 @@ impl<'a> AgentData<'a> { } }, Some(AgentEvent::TradeAccepted(with)) => { - if !behavior.is(BehaviorState::TRADING) { + if !agent.behavior.is(BehaviorState::TRADING) { if let Some(target) = read_data.uid_allocator.retrieve_entity_internal(with.id()) { @@ -1176,12 +1146,12 @@ impl<'a> AgentData<'a> { selected_at: read_data.time.0, }); } - behavior.set(BehaviorState::TRADING); - behavior.set(BehaviorState::TRADING_ISSUER); + agent.behavior.set(BehaviorState::TRADING); + agent.behavior.set(BehaviorState::TRADING_ISSUER); } }, Some(AgentEvent::FinishedTrade(result)) => { - if behavior.is(BehaviorState::TRADING) { + if agent.behavior.is(BehaviorState::TRADING) { match result { TradeResult::Completed => { event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc( @@ -1194,13 +1164,13 @@ impl<'a> AgentData<'a> { "npc.speech.merchant_trade_declined".to_string(), ))), } - behavior.unset(BehaviorState::TRADING); + agent.behavior.unset(BehaviorState::TRADING); } }, Some(AgentEvent::UpdatePendingTrade(boxval)) => { let (tradeid, pending, prices, inventories) = *boxval; - if behavior.is(BehaviorState::TRADING) { - let who: usize = if behavior.is(BehaviorState::TRADING_ISSUER) { + if agent.behavior.is(BehaviorState::TRADING) { + let who: usize = if agent.behavior.is(BehaviorState::TRADING_ISSUER) { 0 } else { 1 @@ -1234,7 +1204,7 @@ impl<'a> AgentData<'a> { } if pending.phase != TradePhase::Mutate { // we got into the review phase but without balanced goods, decline - behavior.unset(BehaviorState::TRADING); + agent.behavior.unset(BehaviorState::TRADING); event_emitter.emit(ServerEvent::ProcessTradeAction( *self.entity, tradeid, @@ -1245,7 +1215,7 @@ impl<'a> AgentData<'a> { } }, None => { - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { // no new events, continue looking towards the last interacting player for some // time if let Some(Target { target, .. }) = &agent.target { @@ -1321,7 +1291,6 @@ impl<'a> AgentData<'a> { fn choose_target( &self, agent: &mut Agent, - behavior: &mut Behavior, controller: &mut Controller, read_data: &ReadData, event_emitter: &mut Emitter<'_, ServerEvent>, @@ -1369,7 +1338,7 @@ impl<'a> AgentData<'a> { ( self.alignment.map_or(false, |alignment| { if matches!(alignment, Alignment::Npc) && e_inventory.equipped_items().filter(|item| item.tags().contains(&ItemTag::Cultist)).count() > 2 { - if behavior.can(BehaviorCapability::SPEAK) { + if agent.behavior.can(BehaviorCapability::SPEAK) { if self.rtsim_entity.is_some() { agent.rtsim_controller.events.push( RtSimEvent::AddMemory(Memory { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index a345b8dc53..0b3b7d8c85 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -193,18 +193,6 @@ impl<'a> System<'a> for Sys { poise, loadout, agent: if entity.has_agency { - Some(comp::Agent::new( - Some(entity.pos), - &body, - matches!( - loadout_config, - Some(comp::inventory::loadout_builder::LoadoutConfig::Guard) - ), - )) - } else { - None - }, - behavior: if entity.has_agency { let mut behavior = Behavior::default(); if can_speak { behavior.allow(BehaviorCapability::SPEAK); @@ -213,7 +201,15 @@ impl<'a> System<'a> for Sys { behavior.allow(BehaviorCapability::TRADE); behavior.trade_site = trade_for_site } - Some(behavior) + Some(comp::Agent::new( + Some(entity.pos), + &body, + behavior, + matches!( + loadout_config, + Some(comp::inventory::loadout_builder::LoadoutConfig::Guard) + ), + )) } else { None },