mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Finally Behavior isn't good enough as a component, Remove it from ECS and include it onto Agent directly
This commit is contained in:
parent
45fb9f3211
commit
dbee13f9be
@ -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<Vec3<f32>>,
|
||||
pub target: Option<Target>,
|
||||
pub chaser: Chaser,
|
||||
pub behavior: Behavior,
|
||||
pub psyche: Psyche,
|
||||
pub inbox: VecDeque<AgentEvent>,
|
||||
pub action_timer: f32,
|
||||
@ -217,20 +218,26 @@ pub struct Agent {
|
||||
}
|
||||
|
||||
impl Agent {
|
||||
pub fn with_patrol_origin(mut self, origin: Vec3<f32>) -> Self {
|
||||
pub fn set_patrol_origin(mut self, origin: Vec3<f32>) -> Self {
|
||||
self.patrol_origin = Some(origin);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_destination(pos: Vec3<f32>) -> Self {
|
||||
pub fn with_destination(behavior: Behavior, pos: Vec3<f32>) -> Self {
|
||||
Self {
|
||||
psyche: Psyche { aggro: 1.0 },
|
||||
rtsim_controller: RtSimController::with_destination(pos),
|
||||
behavior,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(patrol_origin: Option<Vec3<f32>>, body: &Body, no_flee: bool) -> Self {
|
||||
pub fn new(
|
||||
patrol_origin: Option<Vec3<f32>>,
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -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<Self>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Behavior, BehaviorCapability, BehaviorState};
|
||||
|
@ -120,7 +120,6 @@ pub enum ServerEvent {
|
||||
loadout: comp::inventory::loadout::Loadout,
|
||||
body: comp::Body,
|
||||
agent: Option<comp::Agent>,
|
||||
behavior: Option<comp::Behavior>,
|
||||
alignment: comp::Alignment,
|
||||
scale: comp::Scale,
|
||||
home_chunk: Option<comp::HomeChunk>,
|
||||
|
@ -18,8 +18,6 @@
|
||||
type_alias_impl_trait
|
||||
)]
|
||||
|
||||
#[macro_use] extern crate bitflags;
|
||||
|
||||
/// Re-exported crates
|
||||
pub use uuid;
|
||||
|
||||
|
@ -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
|
||||
|
@ -198,7 +198,6 @@ impl State {
|
||||
ecs.register::<comp::Last<comp::Ori>>();
|
||||
ecs.register::<comp::Alignment>();
|
||||
ecs.register::<comp::Agent>();
|
||||
ecs.register::<comp::Behavior>();
|
||||
ecs.register::<comp::WaypointArea>();
|
||||
ecs.register::<comp::ForceUpdate>();
|
||||
ecs.register::<comp::InventoryUpdate>();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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<Option<Agent>>,
|
||||
behavior: Option<Behavior>,
|
||||
alignment: Alignment,
|
||||
scale: Scale,
|
||||
drop_item: Option<Item>,
|
||||
@ -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 {
|
||||
|
@ -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::<Client>();
|
||||
let uids = state.ecs().read_storage::<Uid>();
|
||||
let mut agents = state.ecs().write_storage::<Agent>();
|
||||
let behaviors = state.ecs().read_storage::<Behavior>();
|
||||
let mut invites = state.ecs().write_storage::<Invite>();
|
||||
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| {
|
||||
|
@ -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,
|
||||
|
@ -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<Agent>,
|
||||
behaviors: specs::ReadStorage<Behavior>,
|
||||
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<ReducedInventory>; 2] = [None, None];
|
||||
let mut prices = None;
|
||||
let agents = server.state.ecs().read_storage::<Agent>();
|
||||
let behaviors = server.state.ecs().read_storage::<Behavior>();
|
||||
// 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::<Agent>(),
|
||||
server.state.ecs().read_storage::<Behavior>(),
|
||||
&server.index,
|
||||
e,
|
||||
AgentEvent::UpdatePendingTrade(Box::new((
|
||||
|
@ -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,
|
||||
|
@ -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<Self>,
|
||||
(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::<f32>() < 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 {
|
||||
|
@ -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
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user