mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Use Behavior into Agent
This commit is contained in:
parent
41314e9098
commit
18694b30ad
@ -3,7 +3,7 @@ use specs_idvs::IdvStorage;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
/// Behavior Component
|
/// Behavior Component
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Behavior {
|
pub struct Behavior {
|
||||||
tags: Vec<BehaviorTag>,
|
tags: Vec<BehaviorTag>,
|
||||||
}
|
}
|
||||||
@ -15,8 +15,11 @@ pub enum BehaviorTag {
|
|||||||
CanSpeak,
|
CanSpeak,
|
||||||
/// The entity is able to trade
|
/// The entity is able to trade
|
||||||
CanTrade,
|
CanTrade,
|
||||||
|
|
||||||
|
/// The entity is currently trading
|
||||||
|
IsTrading,
|
||||||
/// The entity has issued a trade
|
/// The entity has issued a trade
|
||||||
TradingIssuer,
|
IsTradingIssuer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Behavior {
|
impl Behavior {
|
||||||
@ -57,17 +60,13 @@ impl Behavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a specific tag by variant
|
/// Get a specific tag by variant
|
||||||
pub fn get_tag(&self, tag: &BehaviorTag) -> Option<&BehaviorTag> {
|
pub fn get_tag(&self, tag: BehaviorTag) -> Option<&BehaviorTag> {
|
||||||
self.tags
|
self.tags
|
||||||
.iter()
|
.iter()
|
||||||
.find(|behavior_tag| mem::discriminant(*behavior_tag) == mem::discriminant(tag))
|
.find(|behavior_tag| mem::discriminant(*behavior_tag) == mem::discriminant(&tag))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Behavior {
|
|
||||||
fn default() -> Self { Behavior { tags: vec![] } }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Component for Behavior {
|
impl Component for Behavior {
|
||||||
type Storage = IdvStorage<Self>;
|
type Storage = IdvStorage<Self>;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,7 @@ impl State {
|
|||||||
ecs.register::<comp::Last<comp::Ori>>();
|
ecs.register::<comp::Last<comp::Ori>>();
|
||||||
ecs.register::<comp::Alignment>();
|
ecs.register::<comp::Alignment>();
|
||||||
ecs.register::<comp::Agent>();
|
ecs.register::<comp::Agent>();
|
||||||
|
ecs.register::<comp::Behavior>();
|
||||||
ecs.register::<comp::WaypointArea>();
|
ecs.register::<comp::WaypointArea>();
|
||||||
ecs.register::<comp::ForceUpdate>();
|
ecs.register::<comp::ForceUpdate>();
|
||||||
ecs.register::<comp::InventoryUpdate>();
|
ecs.register::<comp::InventoryUpdate>();
|
||||||
|
@ -83,45 +83,6 @@ pub fn handle_npc_interaction(server: &mut Server, interactor: EcsEntity, npc_en
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_npc_find_merchant(server: &mut Server, interactor: EcsEntity, npc_entity: EcsEntity) {
|
|
||||||
let state = server.state_mut();
|
|
||||||
let trader_positions: Vec<Vec3<f32>> = {
|
|
||||||
let positions = state.ecs().read_storage::<comp::Pos>();
|
|
||||||
let agents = state.ecs().read_storage::<comp::Agent>();
|
|
||||||
(&agents, &positions)
|
|
||||||
.join()
|
|
||||||
.filter_map(|(a, p)| a.trade_for_site.map(|_| p.0))
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
if let Some(agent) = state
|
|
||||||
.ecs()
|
|
||||||
.write_storage::<comp::Agent>()
|
|
||||||
.get_mut(npc_entity)
|
|
||||||
{
|
|
||||||
if let Some(interactor_uid) = state.ecs().uid_from_entity(interactor) {
|
|
||||||
if let Some(mypos) = state.ecs().read_storage::<comp::Pos>().get(interactor) {
|
|
||||||
let mut closest = std::f32::INFINITY;
|
|
||||||
let mut closest_pos = None;
|
|
||||||
for p in trader_positions.iter() {
|
|
||||||
let diff = p - mypos.0;
|
|
||||||
let dist = diff.magnitude();
|
|
||||||
if dist < closest {
|
|
||||||
closest = dist;
|
|
||||||
closest_pos = Some(*p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
agent.inbox.push_front(AgentEvent::Talk(
|
|
||||||
interactor_uid,
|
|
||||||
Subject::Person(AskedPerson {
|
|
||||||
person_type: comp::dialogue::PersonType::Merchant,
|
|
||||||
origin: closest_pos,
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_mount(server: &mut Server, mounter: EcsEntity, mountee: EcsEntity) {
|
pub fn handle_mount(server: &mut Server, mounter: EcsEntity, mountee: EcsEntity) {
|
||||||
let state = server.state_mut();
|
let state = server.state_mut();
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@ use common::{
|
|||||||
ItemDesc, ItemKind,
|
ItemDesc, ItemKind,
|
||||||
},
|
},
|
||||||
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
||||||
Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent, Controller, Energy,
|
Agent, Alignment, Behavior, BehaviorTag, Body, CharacterState, ControlAction, ControlEvent,
|
||||||
Health, InputKind, Inventory, LightEmitter, MountState, Ori, PhysicsState, Pos, Scale,
|
Controller, Energy, Health, InputKind, Inventory, LightEmitter, MountState, Ori,
|
||||||
Stats, UnresolvedChatMsg, Vel,
|
PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg, Vel,
|
||||||
},
|
},
|
||||||
event::{Emitter, EventBus, ServerEvent},
|
event::{Emitter, EventBus, ServerEvent},
|
||||||
path::TraversalConfig,
|
path::TraversalConfig,
|
||||||
@ -65,6 +65,7 @@ struct AgentData<'a> {
|
|||||||
is_gliding: bool,
|
is_gliding: bool,
|
||||||
health: Option<&'a Health>,
|
health: Option<&'a Health>,
|
||||||
char_state: &'a CharacterState,
|
char_state: &'a CharacterState,
|
||||||
|
behavior: &'a mut Behavior,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SystemData)]
|
#[derive(SystemData)]
|
||||||
@ -121,6 +122,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Agent>,
|
WriteStorage<'a, Agent>,
|
||||||
WriteStorage<'a, Controller>,
|
WriteStorage<'a, Controller>,
|
||||||
WriteExpect<'a, RtSim>,
|
WriteExpect<'a, RtSim>,
|
||||||
|
WriteStorage<'a, Behavior>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAME: &'static str = "agent";
|
const NAME: &'static str = "agent";
|
||||||
@ -130,16 +132,18 @@ impl<'a> System<'a> for Sys {
|
|||||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||||
fn run(
|
fn run(
|
||||||
job: &mut Job<Self>,
|
job: &mut Job<Self>,
|
||||||
(read_data, event_bus, mut agents, mut controllers, mut rtsim): Self::SystemData,
|
(read_data, event_bus, mut agents, mut controllers, mut rtsim, mut behaviors): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let rtsim = &mut *rtsim;
|
let rtsim = &mut *rtsim;
|
||||||
job.cpu_stats.measure(ParMode::Rayon);
|
job.cpu_stats.measure(ParMode::Rayon);
|
||||||
(
|
(
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
(&read_data.energies, read_data.healths.maybe()),
|
(&read_data.energies, read_data.healths.maybe()),
|
||||||
&read_data.positions,
|
(
|
||||||
&read_data.velocities,
|
&read_data.positions,
|
||||||
&read_data.orientations,
|
&read_data.velocities,
|
||||||
|
&read_data.orientations,
|
||||||
|
),
|
||||||
read_data.bodies.maybe(),
|
read_data.bodies.maybe(),
|
||||||
&read_data.inventories,
|
&read_data.inventories,
|
||||||
&read_data.stats,
|
&read_data.stats,
|
||||||
@ -151,16 +155,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
read_data.groups.maybe(),
|
read_data.groups.maybe(),
|
||||||
read_data.mount_states.maybe(),
|
read_data.mount_states.maybe(),
|
||||||
&read_data.char_states,
|
&read_data.char_states,
|
||||||
|
&mut behaviors,
|
||||||
)
|
)
|
||||||
.par_join()
|
.par_join()
|
||||||
.filter(
|
.filter(|(_, _, _, _, _, _, _, _, _, _, _, _, mount_state, _, _)| {
|
||||||
|(_, _, _, _, _, _, _, _, _, _, _, _, _, _, mount_state, _)| {
|
// Skip mounted entities
|
||||||
// Skip mounted entities
|
mount_state
|
||||||
mount_state
|
.map(|ms| *ms == MountState::Unmounted)
|
||||||
.map(|ms| *ms == MountState::Unmounted)
|
.unwrap_or(true)
|
||||||
.unwrap_or(true)
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
.for_each_init(
|
.for_each_init(
|
||||||
|| {
|
|| {
|
||||||
prof_span!(guard, "agent rayon job");
|
prof_span!(guard, "agent rayon job");
|
||||||
@ -170,9 +173,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
(
|
(
|
||||||
entity,
|
entity,
|
||||||
(energy, health),
|
(energy, health),
|
||||||
pos,
|
(pos, vel, ori),
|
||||||
vel,
|
|
||||||
ori,
|
|
||||||
body,
|
body,
|
||||||
inventory,
|
inventory,
|
||||||
stats,
|
stats,
|
||||||
@ -184,6 +185,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
groups,
|
groups,
|
||||||
_,
|
_,
|
||||||
char_state,
|
char_state,
|
||||||
|
behavior,
|
||||||
)| {
|
)| {
|
||||||
//// Hack, replace with better system when groups are more sophisticated
|
//// Hack, replace with better system when groups are more sophisticated
|
||||||
//// Override alignment if in a group unless entity is owned already
|
//// Override alignment if in a group unless entity is owned already
|
||||||
@ -258,7 +260,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
.and_then(|rtsim_ent| rtsim.get_entity(rtsim_ent.0));
|
.and_then(|rtsim_ent| rtsim.get_entity(rtsim_ent.0));
|
||||||
|
|
||||||
// Package all this agent's data into a convenient struct
|
// Package all this agent's data into a convenient struct
|
||||||
let data = AgentData {
|
let mut data = AgentData {
|
||||||
entity: &entity,
|
entity: &entity,
|
||||||
rtsim_entity,
|
rtsim_entity,
|
||||||
uid,
|
uid,
|
||||||
@ -280,6 +282,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
is_gliding,
|
is_gliding,
|
||||||
health: read_data.healths.get(entity),
|
health: read_data.healths.get(entity),
|
||||||
char_state,
|
char_state,
|
||||||
|
behavior,
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
@ -527,7 +530,7 @@ impl<'a> AgentData<'a> {
|
|||||||
// Subtrees
|
// Subtrees
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
fn idle_tree(
|
fn idle_tree(
|
||||||
&self,
|
&mut self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
controller: &mut Controller,
|
controller: &mut Controller,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
@ -551,7 +554,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
if agent.action_timer > 0.0 {
|
if agent.action_timer > 0.0 {
|
||||||
if agent.action_timer
|
if agent.action_timer
|
||||||
< (if agent.trading {
|
< (if self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
TRADE_INTERACTION_TIME
|
TRADE_INTERACTION_TIME
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_INTERACTION_TIME
|
DEFAULT_INTERACTION_TIME
|
||||||
@ -588,7 +591,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
|
let dist_sqrd = self.pos.0.distance_squared(tgt_pos.0);
|
||||||
// Should the agent flee?
|
// Should the agent flee?
|
||||||
if 1.0 - agent.psyche.aggro > self.damage && self.flees {
|
if 1.0 - agent.psyche.aggro > self.damage && self.flees {
|
||||||
if agent.action_timer == 0.0 && agent.can_speak {
|
if agent.action_timer == 0.0 && self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
let msg = "npc.speech.villager_under_attack".to_string();
|
let msg = "npc.speech.villager_under_attack".to_string();
|
||||||
event_emitter
|
event_emitter
|
||||||
.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
|
.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
|
||||||
@ -616,7 +619,7 @@ impl<'a> AgentData<'a> {
|
|||||||
read_data.buffs.get(target),
|
read_data.buffs.get(target),
|
||||||
) {
|
) {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
let msg = "npc.speech.villager_enemy_killed".to_string();
|
let msg = "npc.speech.villager_enemy_killed".to_string();
|
||||||
event_emitter
|
event_emitter
|
||||||
.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
|
.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
|
||||||
@ -855,7 +858,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn interact(
|
fn interact(
|
||||||
&self,
|
&mut self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
controller: &mut Controller,
|
controller: &mut Controller,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
@ -879,7 +882,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let msg = agent.inbox.pop_back();
|
let msg = agent.inbox.pop_back();
|
||||||
match msg {
|
match msg {
|
||||||
Some(AgentEvent::Talk(by, subject)) => {
|
Some(AgentEvent::Talk(by, subject)) => {
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
if let Some(target) = read_data.uid_allocator.retrieve_entity_internal(by.id())
|
if let Some(target) = read_data.uid_allocator.retrieve_entity_internal(by.id())
|
||||||
{
|
{
|
||||||
agent.target = Some(Target {
|
agent.target = Some(Target {
|
||||||
@ -945,8 +948,8 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Subject::Trade => {
|
Subject::Trade => {
|
||||||
if agent.trade_for_site.is_some() {
|
if self.behavior.has_tag(&BehaviorTag::CanTrade) {
|
||||||
if !agent.trading {
|
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
controller.events.push(ControlEvent::InitiateInvite(
|
controller.events.push(ControlEvent::InitiateInvite(
|
||||||
by,
|
by,
|
||||||
InviteKind::Trade,
|
InviteKind::Trade,
|
||||||
@ -1094,8 +1097,8 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::TradeInvite(with)) => {
|
Some(AgentEvent::TradeInvite(with)) => {
|
||||||
if agent.trade_for_site.is_some() {
|
if self.behavior.has_tag(&BehaviorTag::CanTrade) {
|
||||||
if !agent.trading {
|
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
// stand still and looking towards the trading player
|
// stand still and looking towards the trading player
|
||||||
controller.actions.push(ControlAction::Stand);
|
controller.actions.push(ControlAction::Stand);
|
||||||
controller.actions.push(ControlAction::Talk);
|
controller.actions.push(ControlAction::Talk);
|
||||||
@ -1111,13 +1114,13 @@ impl<'a> AgentData<'a> {
|
|||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Accept));
|
.push(ControlEvent::InviteResponse(InviteResponse::Accept));
|
||||||
agent.trading_issuer = false;
|
self.behavior.remove_tag(BehaviorTag::IsTradingIssuer);
|
||||||
agent.trading = true;
|
self.behavior.add_tag(BehaviorTag::IsTrading);
|
||||||
} else {
|
} else {
|
||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
||||||
*self.uid,
|
*self.uid,
|
||||||
"npc.speech.merchant_busy".to_string(),
|
"npc.speech.merchant_busy".to_string(),
|
||||||
@ -1129,7 +1132,7 @@ impl<'a> AgentData<'a> {
|
|||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
||||||
*self.uid,
|
*self.uid,
|
||||||
"npc.speech.villager_decline_trade".to_string(),
|
"npc.speech.villager_decline_trade".to_string(),
|
||||||
@ -1138,7 +1141,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::TradeAccepted(with)) => {
|
Some(AgentEvent::TradeAccepted(with)) => {
|
||||||
if !agent.trading {
|
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
if let Some(target) =
|
if let Some(target) =
|
||||||
read_data.uid_allocator.retrieve_entity_internal(with.id())
|
read_data.uid_allocator.retrieve_entity_internal(with.id())
|
||||||
{
|
{
|
||||||
@ -1148,12 +1151,12 @@ impl<'a> AgentData<'a> {
|
|||||||
selected_at: read_data.time.0,
|
selected_at: read_data.time.0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
agent.trading = true;
|
self.behavior.add_tag(BehaviorTag::IsTrading);
|
||||||
agent.trading_issuer = true;
|
self.behavior.add_tag(BehaviorTag::IsTradingIssuer);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::FinishedTrade(result)) => {
|
Some(AgentEvent::FinishedTrade(result)) => {
|
||||||
if agent.trading {
|
if self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
match result {
|
match result {
|
||||||
TradeResult::Completed => {
|
TradeResult::Completed => {
|
||||||
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
||||||
@ -1166,13 +1169,17 @@ impl<'a> AgentData<'a> {
|
|||||||
"npc.speech.merchant_trade_declined".to_string(),
|
"npc.speech.merchant_trade_declined".to_string(),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
agent.trading = false;
|
self.behavior.remove_tag(BehaviorTag::IsTrading);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::UpdatePendingTrade(boxval)) => {
|
Some(AgentEvent::UpdatePendingTrade(boxval)) => {
|
||||||
let (tradeid, pending, prices, inventories) = *boxval;
|
let (tradeid, pending, prices, inventories) = *boxval;
|
||||||
if agent.trading {
|
if self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
||||||
let who: usize = if agent.trading_issuer { 0 } else { 1 };
|
let who: usize = if self.behavior.has_tag(&BehaviorTag::IsTradingIssuer) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
let balance0: f32 =
|
let balance0: f32 =
|
||||||
prices.balance(&pending.offers, &inventories, 1 - who, true);
|
prices.balance(&pending.offers, &inventories, 1 - who, true);
|
||||||
let balance1: f32 = prices.balance(&pending.offers, &inventories, who, false);
|
let balance1: f32 = prices.balance(&pending.offers, &inventories, who, false);
|
||||||
@ -1202,7 +1209,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
if pending.phase != TradePhase::Mutate {
|
if pending.phase != TradePhase::Mutate {
|
||||||
// we got into the review phase but without balanced goods, decline
|
// we got into the review phase but without balanced goods, decline
|
||||||
agent.trading = false;
|
self.behavior.remove_tag(BehaviorTag::IsTrading);
|
||||||
event_emitter.emit(ServerEvent::ProcessTradeAction(
|
event_emitter.emit(ServerEvent::ProcessTradeAction(
|
||||||
*self.entity,
|
*self.entity,
|
||||||
tradeid,
|
tradeid,
|
||||||
@ -1213,7 +1220,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
// no new events, continue looking towards the last interacting player for some
|
// no new events, continue looking towards the last interacting player for some
|
||||||
// time
|
// time
|
||||||
if let Some(Target { target, .. }) = &agent.target {
|
if let Some(Target { target, .. }) = &agent.target {
|
||||||
@ -1336,7 +1343,7 @@ impl<'a> AgentData<'a> {
|
|||||||
(
|
(
|
||||||
self.alignment.map_or(false, |alignment| {
|
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 matches!(alignment, Alignment::Npc) && e_inventory.equipped_items().filter(|item| item.tags().contains(&ItemTag::Cultist)).count() > 2 {
|
||||||
if agent.can_speak {
|
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
||||||
if self.rtsim_entity.is_some() {
|
if self.rtsim_entity.is_some() {
|
||||||
agent.rtsim_controller.events.push(
|
agent.rtsim_controller.events.push(
|
||||||
RtSimEvent::AddMemory(Memory {
|
RtSimEvent::AddMemory(Memory {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user