mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
use bitflags instead of HashSet
This commit is contained in:
committed by
Marcel Märtens
parent
738f074f89
commit
c33e73bbed
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5377,6 +5377,7 @@ dependencies = [
|
|||||||
"approx 0.4.0",
|
"approx 0.4.0",
|
||||||
"arraygen",
|
"arraygen",
|
||||||
"assets_manager",
|
"assets_manager",
|
||||||
|
"bitflags",
|
||||||
"criterion",
|
"criterion",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"crossbeam-utils 0.8.3",
|
"crossbeam-utils 0.8.3",
|
||||||
|
@ -24,6 +24,7 @@ serde = { version = "1.0.110", features = ["derive", "rc"] }
|
|||||||
approx = "0.4.0"
|
approx = "0.4.0"
|
||||||
arraygen = "0.1.13"
|
arraygen = "0.1.13"
|
||||||
crossbeam-utils = "0.8.1"
|
crossbeam-utils = "0.8.1"
|
||||||
|
bitflags = "1.2"
|
||||||
crossbeam-channel = "0.5"
|
crossbeam-channel = "0.5"
|
||||||
enum-iterator = "0.6"
|
enum-iterator = "0.6"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -1,72 +1,44 @@
|
|||||||
use specs::Component;
|
use specs::Component;
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::{collections::HashSet, mem};
|
|
||||||
|
|
||||||
use crate::trade::SiteId;
|
use crate::trade::SiteId;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct BehaviorFlag: u8 {
|
||||||
|
const CAN_SPEAK = 0b00000001;
|
||||||
|
const CAN_TRADE = 0b00000010;
|
||||||
|
const IS_TRADING = 0b00000100;
|
||||||
|
const IS_TRADING_ISSUER = 0b00001000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// # Behavior Component
|
/// # Behavior Component
|
||||||
/// This component allow an Entity to register one or more behavior tags.
|
/// This component allow an Entity to register one or more behavior tags.
|
||||||
/// These tags act as flags of what an Entity can do, or what it is doing.
|
/// These tags act as flags of what an Entity can do, or what it is doing.
|
||||||
/// Behaviors Tags can be added and removed as the Entity lives, to update its
|
/// Behaviors Tags can be added and removed as the Entity lives, to update its
|
||||||
/// state when needed
|
/// state when needed
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Copy, Clone, Debug)]
|
||||||
pub struct Behavior {
|
pub struct Behavior {
|
||||||
tags: HashSet<BehaviorTag>,
|
pub flags: BehaviorFlag,
|
||||||
|
pub trade_site: Option<SiteId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Versatile tags attached to behaviors
|
impl From<BehaviorFlag> for Behavior {
|
||||||
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
|
fn from(flags: BehaviorFlag) -> Self {
|
||||||
pub enum BehaviorTag {
|
Behavior {
|
||||||
/// The entity is allowed to speak
|
flags,
|
||||||
CanSpeak,
|
trade_site: None,
|
||||||
/// The entity is able to trade
|
}
|
||||||
CanTrade(Option<SiteId>),
|
}
|
||||||
|
|
||||||
/// The entity is currently trading
|
|
||||||
IsTrading,
|
|
||||||
/// The entity has issued a trade
|
|
||||||
IsTradingIssuer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Behavior {
|
impl Behavior {
|
||||||
pub fn new(behavior_tags: &[BehaviorTag]) -> Self {
|
pub fn set(&mut self, flags: BehaviorFlag) { self.flags.set(flags, true) }
|
||||||
let mut behavior = Self::default();
|
|
||||||
for tag in behavior_tags.iter() {
|
|
||||||
behavior.add_tag(tag.clone())
|
|
||||||
}
|
|
||||||
behavior
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply a tag to the Behavior
|
pub fn unset(&mut self, flags: BehaviorFlag) { self.flags.set(flags, false) }
|
||||||
pub fn add_tag(&mut self, tag: BehaviorTag) {
|
|
||||||
if !self.has_tag(&tag) {
|
|
||||||
self.tags.insert(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Revoke a tag to the Behavior
|
pub fn has(&self, flags: BehaviorFlag) -> bool { self.flags.contains(flags) }
|
||||||
pub fn remove_tag(&mut self, tag: BehaviorTag) {
|
|
||||||
if self.has_tag(&tag) {
|
|
||||||
let tag = self.get_tag(&tag).cloned();
|
|
||||||
if let Some(tag) = tag {
|
|
||||||
self.tags.remove(&tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the Behavior possess a specific tag
|
|
||||||
pub fn has_tag(&self, tag: &BehaviorTag) -> bool {
|
|
||||||
self.tags
|
|
||||||
.iter()
|
|
||||||
.any(|behavior_tag| mem::discriminant(behavior_tag) == mem::discriminant(tag))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a specific tag by variant
|
|
||||||
pub fn get_tag(&self, tag: &BehaviorTag) -> Option<&BehaviorTag> {
|
|
||||||
self.tags
|
|
||||||
.iter()
|
|
||||||
.find(|behavior_tag| mem::discriminant(*behavior_tag) == mem::discriminant(tag))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Behavior {
|
impl Component for Behavior {
|
||||||
|
@ -49,7 +49,7 @@ pub use self::{
|
|||||||
agent::{Agent, Alignment},
|
agent::{Agent, Alignment},
|
||||||
aura::{Aura, AuraChange, AuraKind, Auras},
|
aura::{Aura, AuraChange, AuraKind, Auras},
|
||||||
beam::{Beam, BeamSegment},
|
beam::{Beam, BeamSegment},
|
||||||
behavior::{Behavior, BehaviorTag},
|
behavior::{Behavior, BehaviorFlag},
|
||||||
body::{
|
body::{
|
||||||
biped_large, biped_small, bird_medium, bird_small, dragon, fish_medium, fish_small, golem,
|
biped_large, biped_small, bird_medium, bird_small, dragon, fish_medium, fish_small, golem,
|
||||||
humanoid, object, quadruped_low, quadruped_medium, quadruped_small, ship, theropod,
|
humanoid, object, quadruped_low, quadruped_medium, quadruped_small, ship, theropod,
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
type_alias_impl_trait
|
type_alias_impl_trait
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
#[macro_use] extern crate bitflags;
|
||||||
|
|
||||||
/// Re-exported crates
|
/// Re-exported crates
|
||||||
pub use uuid;
|
pub use uuid;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
inventory::loadout_builder::{LoadoutBuilder, LoadoutConfig},
|
inventory::loadout_builder::{LoadoutBuilder, LoadoutConfig},
|
||||||
Behavior, BehaviorTag, CharacterState, StateUpdate,
|
Behavior, BehaviorFlag, CharacterState, StateUpdate,
|
||||||
},
|
},
|
||||||
event::{LocalEvent, ServerEvent},
|
event::{LocalEvent, ServerEvent},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -105,7 +105,7 @@ impl CharacterBehavior for Data {
|
|||||||
loadout,
|
loadout,
|
||||||
body,
|
body,
|
||||||
agent: Some(comp::Agent::new(None, &body, true)),
|
agent: Some(comp::Agent::new(None, &body, true)),
|
||||||
behavior: Some(Behavior::new(&[BehaviorTag::CanSpeak])),
|
behavior: Some(Behavior::from(BehaviorFlag::CAN_SPEAK)),
|
||||||
alignment: comp::Alignment::Owned(*data.uid),
|
alignment: comp::Alignment::Owned(*data.uid),
|
||||||
scale: self
|
scale: self
|
||||||
.static_data
|
.static_data
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
||||||
inventory::item::MaterialStatManifest,
|
inventory::item::MaterialStatManifest,
|
||||||
invite::InviteKind,
|
invite::InviteKind,
|
||||||
BehaviorTag, ChatType, Inventory, Item, LightEmitter, WaypointArea,
|
BehaviorFlag, ChatType, Inventory, Item, LightEmitter, WaypointArea,
|
||||||
},
|
},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
@ -1075,7 +1075,7 @@ fn handle_spawn_airship(
|
|||||||
});
|
});
|
||||||
if let Some(pos) = destination {
|
if let Some(pos) = destination {
|
||||||
builder = builder.with(comp::Agent::with_destination(pos));
|
builder = builder.with(comp::Agent::with_destination(pos));
|
||||||
builder = builder.with(comp::Behavior::new(&[BehaviorTag::CanSpeak]))
|
builder = builder.with(comp::Behavior::from(BehaviorFlag::CAN_SPEAK))
|
||||||
}
|
}
|
||||||
builder.build();
|
builder.build();
|
||||||
|
|
||||||
|
@ -75,11 +75,8 @@ pub fn handle_create_npc(
|
|||||||
} else {
|
} else {
|
||||||
entity
|
entity
|
||||||
};
|
};
|
||||||
let entity = if let Some(behavior) = behavior {
|
|
||||||
entity.with(behavior)
|
let entity = entity.with(behavior.unwrap_or_default());
|
||||||
} else {
|
|
||||||
entity.with(Behavior::default())
|
|
||||||
};
|
|
||||||
|
|
||||||
let entity = if let Some(drop_item) = drop_item {
|
let entity = if let Some(drop_item) = drop_item {
|
||||||
entity.with(ItemDrop(drop_item))
|
entity.with(ItemDrop(drop_item))
|
||||||
|
@ -226,8 +226,12 @@ pub fn handle_invite_accept(server: &mut Server, entity: specs::Entity) {
|
|||||||
}
|
}
|
||||||
let pricing = behaviors
|
let pricing = behaviors
|
||||||
.get(inviter)
|
.get(inviter)
|
||||||
.and_then(|b| index.get_site_prices(b))
|
.and_then(|b| index.get_site_prices(b.trade_site))
|
||||||
.or_else(|| behaviors.get(entity).and_then(|b| index.get_site_prices(b)));
|
.or_else(|| {
|
||||||
|
behaviors
|
||||||
|
.get(entity)
|
||||||
|
.and_then(|b| index.get_site_prices(b.trade_site))
|
||||||
|
});
|
||||||
clients.get(inviter).map(|c| {
|
clients.get(inviter).map(|c| {
|
||||||
c.send(ServerGeneral::UpdatePendingTrade(
|
c.send(ServerGeneral::UpdatePendingTrade(
|
||||||
id,
|
id,
|
||||||
|
@ -35,7 +35,7 @@ fn notify_agent_prices(
|
|||||||
event: AgentEvent,
|
event: AgentEvent,
|
||||||
) {
|
) {
|
||||||
if let (Some(agent), Some(behavior)) = (agents.get_mut(entity), behaviors.get(entity)) {
|
if let (Some(agent), Some(behavior)) = (agents.get_mut(entity), behaviors.get(entity)) {
|
||||||
let prices = index.get_site_prices(behavior);
|
let prices = index.get_site_prices(behavior.trade_site);
|
||||||
if let AgentEvent::UpdatePendingTrade(boxval) = event {
|
if let AgentEvent::UpdatePendingTrade(boxval) = event {
|
||||||
// Box<(tid, pend, _, inventories)>) = event {
|
// Box<(tid, pend, _, inventories)>) = event {
|
||||||
agent
|
agent
|
||||||
@ -123,7 +123,7 @@ pub fn handle_process_trade_action(
|
|||||||
prices = prices.or_else(|| {
|
prices = prices.or_else(|| {
|
||||||
behaviors
|
behaviors
|
||||||
.get(e)
|
.get(e)
|
||||||
.and_then(|b| server.index.get_site_prices(b))
|
.and_then(|b| server.index.get_site_prices(b.trade_site))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use common::{
|
use common::{
|
||||||
comp::{self, inventory::loadout_builder::LoadoutBuilder, Behavior, BehaviorTag},
|
comp::{self, inventory::loadout_builder::LoadoutBuilder, Behavior, BehaviorFlag},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
resources::{DeltaTime, Time},
|
resources::{DeltaTime, Time},
|
||||||
terrain::TerrainGrid,
|
terrain::TerrainGrid,
|
||||||
@ -104,11 +104,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
+ Vec3::new(0.5, 0.5, body.flying_height());
|
+ Vec3::new(0.5, 0.5, body.flying_height());
|
||||||
let pos = comp::Pos(spawn_pos);
|
let pos = comp::Pos(spawn_pos);
|
||||||
let agent = Some(comp::Agent::new(None, &body, false));
|
let agent = Some(comp::Agent::new(None, &body, false));
|
||||||
let behavior = if matches!(body, comp::Body::Humanoid(_)) {
|
let behavior = matches!(body, comp::Body::Humanoid(_))
|
||||||
Some(Behavior::new(&[BehaviorTag::CanSpeak]))
|
.then(|| Behavior::from(BehaviorFlag::CAN_SPEAK));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let rtsim_entity = Some(RtSimEntity(id));
|
let rtsim_entity = Some(RtSimEntity(id));
|
||||||
let event = match body {
|
let event = match body {
|
||||||
comp::Body::Ship(ship) => ServerEvent::CreateShip {
|
comp::Body::Ship(ship) => ServerEvent::CreateShip {
|
||||||
|
@ -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, Behavior, BehaviorTag, Body, CharacterState, ControlAction, ControlEvent,
|
Agent, Alignment, Behavior, BehaviorFlag, Body, CharacterState, ControlAction,
|
||||||
Controller, Energy, Health, InputKind, Inventory, LightEmitter, MountState, Ori,
|
ControlEvent, Controller, Energy, Health, InputKind, Inventory, LightEmitter, MountState,
|
||||||
PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg, Vel,
|
Ori, PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg, Vel,
|
||||||
},
|
},
|
||||||
event::{Emitter, EventBus, ServerEvent},
|
event::{Emitter, EventBus, ServerEvent},
|
||||||
path::TraversalConfig,
|
path::TraversalConfig,
|
||||||
@ -554,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 self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
< (if self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
TRADE_INTERACTION_TIME
|
TRADE_INTERACTION_TIME
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_INTERACTION_TIME
|
DEFAULT_INTERACTION_TIME
|
||||||
@ -591,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 && self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if agent.action_timer == 0.0 && self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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)));
|
||||||
@ -619,7 +619,7 @@ impl<'a> AgentData<'a> {
|
|||||||
read_data.buffs.get(target),
|
read_data.buffs.get(target),
|
||||||
) {
|
) {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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)));
|
||||||
@ -882,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 self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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 {
|
||||||
@ -935,7 +935,7 @@ impl<'a> AgentData<'a> {
|
|||||||
event_emitter.emit(ServerEvent::Chat(
|
event_emitter.emit(ServerEvent::Chat(
|
||||||
UnresolvedChatMsg::npc(*self.uid, msg),
|
UnresolvedChatMsg::npc(*self.uid, msg),
|
||||||
));
|
));
|
||||||
} else if self.behavior.has_tag(&BehaviorTag::CanTrade(None)) {
|
} else if self.behavior.has(BehaviorFlag::CAN_TRADE) {
|
||||||
let msg = "npc.speech.merchant_advertisement".to_string();
|
let msg = "npc.speech.merchant_advertisement".to_string();
|
||||||
event_emitter.emit(ServerEvent::Chat(
|
event_emitter.emit(ServerEvent::Chat(
|
||||||
UnresolvedChatMsg::npc(*self.uid, msg),
|
UnresolvedChatMsg::npc(*self.uid, msg),
|
||||||
@ -948,8 +948,8 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Subject::Trade => {
|
Subject::Trade => {
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanTrade(None)) {
|
if self.behavior.has(BehaviorFlag::CAN_TRADE) {
|
||||||
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
if !self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
controller.events.push(ControlEvent::InitiateInvite(
|
controller.events.push(ControlEvent::InitiateInvite(
|
||||||
by,
|
by,
|
||||||
InviteKind::Trade,
|
InviteKind::Trade,
|
||||||
@ -1097,8 +1097,8 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::TradeInvite(with)) => {
|
Some(AgentEvent::TradeInvite(with)) => {
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanTrade(None)) {
|
if self.behavior.has(BehaviorFlag::CAN_TRADE) {
|
||||||
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
if !self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
// 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);
|
||||||
@ -1114,13 +1114,13 @@ impl<'a> AgentData<'a> {
|
|||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Accept));
|
.push(ControlEvent::InviteResponse(InviteResponse::Accept));
|
||||||
self.behavior.remove_tag(BehaviorTag::IsTradingIssuer);
|
self.behavior.unset(BehaviorFlag::IS_TRADING_ISSUER);
|
||||||
self.behavior.add_tag(BehaviorTag::IsTrading);
|
self.behavior.set(BehaviorFlag::IS_TRADING);
|
||||||
} else {
|
} else {
|
||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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(),
|
||||||
@ -1132,7 +1132,7 @@ impl<'a> AgentData<'a> {
|
|||||||
controller
|
controller
|
||||||
.events
|
.events
|
||||||
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
.push(ControlEvent::InviteResponse(InviteResponse::Decline));
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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(),
|
||||||
@ -1141,7 +1141,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::TradeAccepted(with)) => {
|
Some(AgentEvent::TradeAccepted(with)) => {
|
||||||
if !self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
if !self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
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())
|
||||||
{
|
{
|
||||||
@ -1151,12 +1151,12 @@ impl<'a> AgentData<'a> {
|
|||||||
selected_at: read_data.time.0,
|
selected_at: read_data.time.0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.behavior.add_tag(BehaviorTag::IsTrading);
|
self.behavior.set(BehaviorFlag::IS_TRADING);
|
||||||
self.behavior.add_tag(BehaviorTag::IsTradingIssuer);
|
self.behavior.set(BehaviorFlag::IS_TRADING_ISSUER);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::FinishedTrade(result)) => {
|
Some(AgentEvent::FinishedTrade(result)) => {
|
||||||
if self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
if self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
match result {
|
match result {
|
||||||
TradeResult::Completed => {
|
TradeResult::Completed => {
|
||||||
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(
|
||||||
@ -1169,13 +1169,13 @@ impl<'a> AgentData<'a> {
|
|||||||
"npc.speech.merchant_trade_declined".to_string(),
|
"npc.speech.merchant_trade_declined".to_string(),
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
self.behavior.remove_tag(BehaviorTag::IsTrading);
|
self.behavior.unset(BehaviorFlag::IS_TRADING);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(AgentEvent::UpdatePendingTrade(boxval)) => {
|
Some(AgentEvent::UpdatePendingTrade(boxval)) => {
|
||||||
let (tradeid, pending, prices, inventories) = *boxval;
|
let (tradeid, pending, prices, inventories) = *boxval;
|
||||||
if self.behavior.has_tag(&BehaviorTag::IsTrading) {
|
if self.behavior.has(BehaviorFlag::IS_TRADING) {
|
||||||
let who: usize = if self.behavior.has_tag(&BehaviorTag::IsTradingIssuer) {
|
let who: usize = if self.behavior.has(BehaviorFlag::IS_TRADING_ISSUER) {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
@ -1209,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
|
||||||
self.behavior.remove_tag(BehaviorTag::IsTrading);
|
self.behavior.unset(BehaviorFlag::IS_TRADING);
|
||||||
event_emitter.emit(ServerEvent::ProcessTradeAction(
|
event_emitter.emit(ServerEvent::ProcessTradeAction(
|
||||||
*self.entity,
|
*self.entity,
|
||||||
tradeid,
|
tradeid,
|
||||||
@ -1220,7 +1220,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
if self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
// 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 {
|
||||||
@ -1343,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 self.behavior.has_tag(&BehaviorTag::CanSpeak) {
|
if self.behavior.has(BehaviorFlag::CAN_SPEAK) {
|
||||||
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 {
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
self, bird_medium, inventory::loadout_builder::LoadoutConfig, Alignment, BehaviorTag, Pos,
|
self, bird_medium, inventory::loadout_builder::LoadoutConfig, Alignment, BehaviorFlag, Pos,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
generation::get_npc_name,
|
generation::get_npc_name,
|
||||||
@ -14,6 +14,7 @@ use common::{
|
|||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use common_net::msg::ServerGeneral;
|
use common_net::msg::ServerGeneral;
|
||||||
use common_sys::state::TerrainChanges;
|
use common_sys::state::TerrainChanges;
|
||||||
|
use comp::Behavior;
|
||||||
use specs::{Join, Read, ReadStorage, Write, WriteExpect};
|
use specs::{Join, Read, ReadStorage, Write, WriteExpect};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -203,14 +204,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
None
|
None
|
||||||
},
|
},
|
||||||
behavior: if entity.has_agency {
|
behavior: if entity.has_agency {
|
||||||
let mut behavior_tags = vec![];
|
let mut behavior = Behavior::default();
|
||||||
if can_speak {
|
if can_speak {
|
||||||
behavior_tags.push(BehaviorTag::CanSpeak);
|
behavior.set(BehaviorFlag::CAN_SPEAK);
|
||||||
}
|
}
|
||||||
if trade_for_site.is_some() {
|
if trade_for_site.is_some() {
|
||||||
behavior_tags.push(BehaviorTag::CanTrade(trade_for_site));
|
behavior.set(BehaviorFlag::CAN_TRADE);
|
||||||
|
behavior.trade_site = trade_for_site
|
||||||
}
|
}
|
||||||
Some(comp::Behavior::new(&behavior_tags))
|
Some(behavior)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
@ -4,9 +4,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
assets::{AssetExt, AssetHandle},
|
assets::{AssetExt, AssetHandle},
|
||||||
comp::{Behavior, BehaviorTag},
|
|
||||||
store::Store,
|
store::Store,
|
||||||
trade::SitePrices,
|
trade::{SiteId, SitePrices},
|
||||||
};
|
};
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use noise::{Seedable, SuperSimplex};
|
use noise::{Seedable, SuperSimplex};
|
||||||
@ -72,17 +71,12 @@ impl Index {
|
|||||||
|
|
||||||
pub fn colors(&self) -> AssetHandle<Arc<Colors>> { self.colors }
|
pub fn colors(&self) -> AssetHandle<Arc<Colors>> { self.colors }
|
||||||
|
|
||||||
pub fn get_site_prices(&self, behavior: &Behavior) -> Option<SitePrices> {
|
pub fn get_site_prices(&self, site_id: Option<SiteId>) -> Option<SitePrices> {
|
||||||
if let Some(BehaviorTag::CanTrade(site_id)) = behavior.get_tag(&BehaviorTag::CanTrade(None))
|
|
||||||
{
|
|
||||||
site_id
|
site_id
|
||||||
.map(|i| self.sites.recreate_id(i))
|
.map(|i| self.sites.recreate_id(i))
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|i| self.sites.get(i))
|
.map(|i| self.sites.get(i))
|
||||||
.map(|s| s.economy.get_site_prices())
|
.map(|s| s.economy.get_site_prices())
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user