mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
rtsim personalities
This commit is contained in:
parent
7ac6c6b453
commit
1c0fdf9228
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -7032,6 +7032,7 @@ dependencies = [
|
|||||||
"veloren-common-base",
|
"veloren-common-base",
|
||||||
"veloren-common-dynlib",
|
"veloren-common-dynlib",
|
||||||
"veloren-common-ecs",
|
"veloren-common-ecs",
|
||||||
|
"veloren-rtsim",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
// `Agent`). When possible, this should be moved to the `rtsim`
|
// `Agent`). When possible, this should be moved to the `rtsim`
|
||||||
// module in `server`.
|
// module in `server`.
|
||||||
|
|
||||||
|
use rand::{Rng, seq::IteratorRandom};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::Component;
|
use specs::Component;
|
||||||
|
use strum::{EnumIter, IntoEnumIterator};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
use crate::comp::dialogue::MoodState;
|
use crate::comp::dialogue::MoodState;
|
||||||
@ -54,6 +56,121 @@ pub enum MemoryItem {
|
|||||||
Mood { state: MoodState },
|
Mood { state: MoodState },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(EnumIter, Clone, Copy)]
|
||||||
|
pub enum PersonalityTrait {
|
||||||
|
Open,
|
||||||
|
Adventurous,
|
||||||
|
Closed,
|
||||||
|
Conscientious,
|
||||||
|
Busybody,
|
||||||
|
Unconscientious,
|
||||||
|
Extroverted,
|
||||||
|
Introverted,
|
||||||
|
Agreeable,
|
||||||
|
Sociable,
|
||||||
|
Disagreeable,
|
||||||
|
Neurotic,
|
||||||
|
Seeker,
|
||||||
|
Worried,
|
||||||
|
SadLoner,
|
||||||
|
Stable,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
|
||||||
|
pub struct Personality {
|
||||||
|
openness: u8,
|
||||||
|
conscientiousness: u8,
|
||||||
|
extraversion: u8,
|
||||||
|
agreeableness: u8,
|
||||||
|
neuroticism: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn distributed(min: u8, max: u8, rng: &mut impl Rng) -> u8 {
|
||||||
|
let l = max - min;
|
||||||
|
min + rng.gen_range(0..=l / 3) + rng.gen_range(0..=l / 3 + l % 3 % 2) + rng.gen_range(0..=l / 3 + l % 3 / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Personality {
|
||||||
|
pub const HIGH_THRESHOLD: u8 = Self::MAX - Self::LOW_THRESHOLD;
|
||||||
|
pub const LITTLE_HIGH: u8 = Self::MID + (Self::MAX - Self::MIN) / 20;
|
||||||
|
pub const LITTLE_LOW: u8 = Self::MID - (Self::MAX - Self::MIN) / 20;
|
||||||
|
pub const LOW_THRESHOLD: u8 = (Self::MAX - Self::MIN) / 5 * 2 + Self::MIN;
|
||||||
|
const MIN: u8 = 0;
|
||||||
|
pub const MID: u8 = (Self::MAX - Self::MIN) / 2;
|
||||||
|
const MAX: u8 = 255;
|
||||||
|
|
||||||
|
fn distributed_value(rng: &mut impl Rng) -> u8 {
|
||||||
|
distributed(Self::MIN, Self::MAX, rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random(rng: &mut impl Rng) -> Self {
|
||||||
|
Self {
|
||||||
|
openness: Self::distributed_value(rng),
|
||||||
|
conscientiousness: Self::distributed_value(rng),
|
||||||
|
extraversion: Self::distributed_value(rng),
|
||||||
|
agreeableness: Self::distributed_value(rng),
|
||||||
|
neuroticism: Self::distributed_value(rng),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_evil(rng: &mut impl Rng) -> Self {
|
||||||
|
Self {
|
||||||
|
openness: Self::distributed_value(rng),
|
||||||
|
extraversion: Self::distributed_value(rng),
|
||||||
|
neuroticism: Self::distributed_value(rng),
|
||||||
|
agreeableness: distributed(0, Self::LOW_THRESHOLD - 1, rng),
|
||||||
|
conscientiousness: distributed(0, Self::LOW_THRESHOLD - 1, rng),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_good(rng: &mut impl Rng) -> Self {
|
||||||
|
Self {
|
||||||
|
openness: Self::distributed_value(rng),
|
||||||
|
extraversion: Self::distributed_value(rng),
|
||||||
|
neuroticism: Self::distributed_value(rng),
|
||||||
|
agreeableness: Self::distributed_value(rng),
|
||||||
|
conscientiousness: distributed(Self::LOW_THRESHOLD, Self::MAX, rng),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is(&self, trait_: PersonalityTrait) -> bool {
|
||||||
|
match trait_ {
|
||||||
|
PersonalityTrait::Open => self.openness > Personality::HIGH_THRESHOLD,
|
||||||
|
PersonalityTrait::Adventurous => self.openness > Personality::HIGH_THRESHOLD && self.neuroticism < Personality::MID,
|
||||||
|
PersonalityTrait::Closed => self.openness < Personality::LOW_THRESHOLD,
|
||||||
|
PersonalityTrait::Conscientious => self.conscientiousness > Personality::HIGH_THRESHOLD,
|
||||||
|
PersonalityTrait::Busybody => self.agreeableness < Personality::LOW_THRESHOLD,
|
||||||
|
PersonalityTrait::Unconscientious => self.conscientiousness < Personality::LOW_THRESHOLD,
|
||||||
|
PersonalityTrait::Extroverted => self.extraversion > Personality::HIGH_THRESHOLD,
|
||||||
|
PersonalityTrait::Introverted => self.extraversion < Personality::LOW_THRESHOLD,
|
||||||
|
PersonalityTrait::Agreeable => self.agreeableness > Personality::HIGH_THRESHOLD,
|
||||||
|
PersonalityTrait::Sociable => self.agreeableness > Personality::HIGH_THRESHOLD && self.extraversion > Personality::MID,
|
||||||
|
PersonalityTrait::Disagreeable => self.agreeableness < Personality::LOW_THRESHOLD,
|
||||||
|
PersonalityTrait::Neurotic => self.neuroticism > Personality::HIGH_THRESHOLD,
|
||||||
|
PersonalityTrait::Seeker => self.neuroticism > Personality::HIGH_THRESHOLD && self.openness > Personality::LITTLE_HIGH,
|
||||||
|
PersonalityTrait::Worried => self.neuroticism > Personality::HIGH_THRESHOLD && self.agreeableness > Personality::LITTLE_HIGH,
|
||||||
|
PersonalityTrait::SadLoner => self.neuroticism > Personality::HIGH_THRESHOLD && self.extraversion < Personality::LITTLE_LOW,
|
||||||
|
PersonalityTrait::Stable => self.neuroticism < Personality::LOW_THRESHOLD,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chat_trait(&self, rng: &mut impl Rng) -> Option<PersonalityTrait> {
|
||||||
|
PersonalityTrait::iter().filter(|t| self.is(*t)).choose(rng)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn will_ambush(&self) -> bool {
|
||||||
|
self.agreeableness < Self::LOW_THRESHOLD
|
||||||
|
&& self.conscientiousness < Self::LOW_THRESHOLD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Personality {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { openness: Personality::MID, conscientiousness: Personality::MID, extraversion: Personality::MID, agreeableness: Personality::MID, neuroticism: Personality::MID }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This type is the map route through which the rtsim (real-time simulation)
|
/// This type is the map route through which the rtsim (real-time simulation)
|
||||||
/// aspect of the game communicates with the rest of the game. It is analagous
|
/// aspect of the game communicates with the rest of the game. It is analagous
|
||||||
/// to `comp::Controller` in that it provides a consistent interface for
|
/// to `comp::Controller` in that it provides a consistent interface for
|
||||||
@ -69,6 +186,7 @@ pub struct RtSimController {
|
|||||||
/// toward the given location, accounting for obstacles and other
|
/// toward the given location, accounting for obstacles and other
|
||||||
/// high-priority situations like being attacked.
|
/// high-priority situations like being attacked.
|
||||||
pub travel_to: Option<Vec3<f32>>,
|
pub travel_to: Option<Vec3<f32>>,
|
||||||
|
pub personality: Personality,
|
||||||
pub heading_to: Option<String>,
|
pub heading_to: Option<String>,
|
||||||
/// Proportion of full speed to move
|
/// Proportion of full speed to move
|
||||||
pub speed_factor: f32,
|
pub speed_factor: f32,
|
||||||
@ -80,6 +198,7 @@ impl Default for RtSimController {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
travel_to: None,
|
travel_to: None,
|
||||||
|
personality:Personality::default(),
|
||||||
heading_to: None,
|
heading_to: None,
|
||||||
speed_factor: 1.0,
|
speed_factor: 1.0,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
@ -91,6 +210,7 @@ impl RtSimController {
|
|||||||
pub fn with_destination(pos: Vec3<f32>) -> Self {
|
pub fn with_destination(pos: Vec3<f32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
travel_to: Some(pos),
|
travel_to: Some(pos),
|
||||||
|
personality:Personality::default(),
|
||||||
heading_to: None,
|
heading_to: None,
|
||||||
speed_factor: 0.5,
|
speed_factor: 0.5,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
|
@ -3,7 +3,7 @@ pub use common::rtsim::{NpcId, Profession};
|
|||||||
use common::{
|
use common::{
|
||||||
comp,
|
comp,
|
||||||
grid::Grid,
|
grid::Grid,
|
||||||
rtsim::{FactionId, SiteId, VehicleId},
|
rtsim::{FactionId, SiteId, VehicleId, Personality},
|
||||||
store::Id,
|
store::Id,
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
@ -80,9 +80,10 @@ pub struct Npc {
|
|||||||
pub profession: Option<Profession>,
|
pub profession: Option<Profession>,
|
||||||
pub home: Option<SiteId>,
|
pub home: Option<SiteId>,
|
||||||
pub faction: Option<FactionId>,
|
pub faction: Option<FactionId>,
|
||||||
|
|
||||||
pub riding: Option<Riding>,
|
pub riding: Option<Riding>,
|
||||||
|
|
||||||
|
pub personality: Personality,
|
||||||
|
|
||||||
// Unpersisted state
|
// Unpersisted state
|
||||||
#[serde(skip_serializing, skip_deserializing)]
|
#[serde(skip_serializing, skip_deserializing)]
|
||||||
pub chunk_pos: Option<Vec2<i32>>,
|
pub chunk_pos: Option<Vec2<i32>>,
|
||||||
@ -113,6 +114,7 @@ impl Clone for Npc {
|
|||||||
faction: self.faction,
|
faction: self.faction,
|
||||||
riding: self.riding.clone(),
|
riding: self.riding.clone(),
|
||||||
body: self.body,
|
body: self.body,
|
||||||
|
personality: self.personality,
|
||||||
// Not persisted
|
// Not persisted
|
||||||
chunk_pos: None,
|
chunk_pos: None,
|
||||||
current_site: Default::default(),
|
current_site: Default::default(),
|
||||||
@ -129,6 +131,7 @@ impl Npc {
|
|||||||
seed,
|
seed,
|
||||||
wpos,
|
wpos,
|
||||||
body,
|
body,
|
||||||
|
personality: Personality::default(),
|
||||||
profession: None,
|
profession: None,
|
||||||
home: None,
|
home: None,
|
||||||
faction: None,
|
faction: None,
|
||||||
@ -141,6 +144,11 @@ impl Npc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_personality(mut self, personality: Personality) -> Self {
|
||||||
|
self.personality = personality;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_profession(mut self, profession: impl Into<Option<Profession>>) -> Self {
|
pub fn with_profession(mut self, profession: impl Into<Option<Profession>>) -> Self {
|
||||||
self.profession = profession.into();
|
self.profession = profession.into();
|
||||||
self
|
self
|
||||||
|
@ -11,7 +11,7 @@ use common::{
|
|||||||
comp::{self, Body},
|
comp::{self, Body},
|
||||||
grid::Grid,
|
grid::Grid,
|
||||||
resources::TimeOfDay,
|
resources::TimeOfDay,
|
||||||
rtsim::WorldSettings,
|
rtsim::{WorldSettings, Personality},
|
||||||
terrain::TerrainChunkSize,
|
terrain::TerrainChunkSize,
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
@ -103,6 +103,7 @@ impl Data {
|
|||||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||||
.with_faction(site.faction)
|
.with_faction(site.faction)
|
||||||
.with_home(site_id)
|
.with_home(site_id)
|
||||||
|
.with_personality(Personality::random(&mut rng))
|
||||||
.with_profession(match rng.gen_range(0..20) {
|
.with_profession(match rng.gen_range(0..20) {
|
||||||
0 => Profession::Hunter,
|
0 => Profession::Hunter,
|
||||||
1 => Profession::Blacksmith,
|
1 => Profession::Blacksmith,
|
||||||
@ -119,6 +120,7 @@ impl Data {
|
|||||||
for _ in 0..15 {
|
for _ in 0..15 {
|
||||||
this.npcs.create_npc(
|
this.npcs.create_npc(
|
||||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||||
|
.with_personality(Personality::random_evil(&mut rng))
|
||||||
.with_faction(site.faction)
|
.with_faction(site.faction)
|
||||||
.with_home(site_id)
|
.with_home(site_id)
|
||||||
.with_profession(match rng.gen_range(0..20) {
|
.with_profession(match rng.gen_range(0..20) {
|
||||||
@ -130,6 +132,7 @@ impl Data {
|
|||||||
this.npcs.create_npc(
|
this.npcs.create_npc(
|
||||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||||
.with_home(site_id)
|
.with_home(site_id)
|
||||||
|
.with_personality(Personality::random_good(&mut rng))
|
||||||
.with_profession(Profession::Merchant),
|
.with_profession(Profession::Merchant),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -143,6 +146,7 @@ impl Data {
|
|||||||
Npc::new(rng.gen(), wpos, random_humanoid(&mut rng))
|
Npc::new(rng.gen(), wpos, random_humanoid(&mut rng))
|
||||||
.with_home(site_id)
|
.with_home(site_id)
|
||||||
.with_profession(Profession::Captain)
|
.with_profession(Profession::Captain)
|
||||||
|
.with_personality(Personality::random_good(&mut rng))
|
||||||
.steering(vehicle_id),
|
.steering(vehicle_id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ use-dyn-lib = ["common-dynlib"]
|
|||||||
be-dyn-lib = []
|
be-dyn-lib = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
common = {package = "veloren-common", path = "../../common"}
|
common = { package = "veloren-common", path = "../../common"}
|
||||||
common-base = { package = "veloren-common-base", path = "../../common/base" }
|
common-base = { package = "veloren-common-base", path = "../../common/base" }
|
||||||
common-ecs = { package = "veloren-common-ecs", path = "../../common/ecs" }
|
common-ecs = { package = "veloren-common-ecs", path = "../../common/ecs" }
|
||||||
common-dynlib = {package = "veloren-common-dynlib", path = "../../common/dynlib", optional = true}
|
common-dynlib = { package = "veloren-common-dynlib", path = "../../common/dynlib", optional = true}
|
||||||
|
rtsim = { package = "veloren-rtsim", path = "../../rtsim" }
|
||||||
|
|
||||||
specs = { version = "0.18", features = ["shred-derive"] }
|
specs = { version = "0.18", features = ["shred-derive"] }
|
||||||
vek = { version = "0.15.8", features = ["serde"] }
|
vek = { version = "0.15.8", features = ["serde"] }
|
||||||
|
@ -650,7 +650,6 @@ impl<'a> AgentData<'a> {
|
|||||||
controller: &mut Controller,
|
controller: &mut Controller,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
event_emitter: &mut Emitter<ServerEvent>,
|
event_emitter: &mut Emitter<ServerEvent>,
|
||||||
will_ambush: bool,
|
|
||||||
) {
|
) {
|
||||||
enum ActionStateTimers {
|
enum ActionStateTimers {
|
||||||
TimerChooseTarget = 0,
|
TimerChooseTarget = 0,
|
||||||
@ -673,7 +672,7 @@ impl<'a> AgentData<'a> {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.map_or(false, |eu| eu != self.uid)
|
.map_or(false, |eu| eu != self.uid)
|
||||||
};
|
};
|
||||||
if will_ambush
|
if agent.rtsim_controller.personality.will_ambush()
|
||||||
&& self_different_from_entity()
|
&& self_different_from_entity()
|
||||||
&& !self.passive_towards(entity, read_data)
|
&& !self.passive_towards(entity, read_data)
|
||||||
{
|
{
|
||||||
|
@ -364,6 +364,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
// Update entity state
|
// Update entity state
|
||||||
if let Some(agent) = agent {
|
if let Some(agent) = agent {
|
||||||
|
agent.rtsim_controller.personality = npc.personality;
|
||||||
if let Some(action) = npc.action {
|
if let Some(action) = npc.action {
|
||||||
match action {
|
match action {
|
||||||
rtsim2::data::npc::NpcAction::Goto(wpos, sf) => {
|
rtsim2::data::npc::NpcAction::Goto(wpos, sf) => {
|
||||||
|
@ -498,7 +498,6 @@ fn handle_timed_events(bdata: &mut BehaviorData) -> bool {
|
|||||||
bdata.controller,
|
bdata.controller,
|
||||||
bdata.read_data,
|
bdata.read_data,
|
||||||
bdata.event_emitter,
|
bdata.event_emitter,
|
||||||
will_ambush(/* bdata.rtsim_entity */ None, &bdata.agent_data),
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
bdata.agent_data.handle_sounds_heard(
|
bdata.agent_data.handle_sounds_heard(
|
||||||
@ -747,7 +746,6 @@ fn do_combat(bdata: &mut BehaviorData) -> bool {
|
|||||||
controller,
|
controller,
|
||||||
read_data,
|
read_data,
|
||||||
event_emitter,
|
event_emitter,
|
||||||
will_ambush(agent_data.rtsim_entity, agent_data),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,15 +773,6 @@ fn do_combat(bdata: &mut BehaviorData) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn will_ambush(rtsim_entity: Option<&RtSimEntity>, agent_data: &AgentData) -> bool {
|
|
||||||
// TODO: implement for rtsim2
|
|
||||||
// agent_data
|
|
||||||
// .health
|
|
||||||
// .map_or(false, |h| h.current() / h.maximum() > 0.7)
|
|
||||||
// && rtsim_entity.map_or(false, |re| re.brain.personality.will_ambush)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remembers_fight_with(
|
fn remembers_fight_with(
|
||||||
rtsim_entity: Option<&RtSimEntity>,
|
rtsim_entity: Option<&RtSimEntity>,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
|
@ -2,14 +2,14 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
agent::{AgentEvent, Target, TimerAction},
|
agent::{AgentEvent, Target, TimerAction},
|
||||||
compass::{Direction, Distance},
|
compass::{Direction, Distance},
|
||||||
dialogue::{MoodContext, MoodState, Subject},
|
dialogue::Subject,
|
||||||
inventory::item::{ItemTag, MaterialStatManifest},
|
inventory::item::{ItemTag, MaterialStatManifest},
|
||||||
invite::{InviteKind, InviteResponse},
|
invite::{InviteKind, InviteResponse},
|
||||||
tool::AbilityMap,
|
tool::AbilityMap,
|
||||||
BehaviorState, ControlAction, Item, TradingBehavior, UnresolvedChatMsg, UtteranceKind,
|
BehaviorState, ControlAction, Item, TradingBehavior, UnresolvedChatMsg, UtteranceKind,
|
||||||
},
|
},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
rtsim::{Memory, MemoryItem, RtSimEvent},
|
rtsim::{Memory, MemoryItem, RtSimEvent, PersonalityTrait},
|
||||||
trade::{TradeAction, TradePhase, TradeResult},
|
trade::{TradeAction, TradePhase, TradeResult},
|
||||||
};
|
};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
@ -105,172 +105,142 @@ pub fn handle_inbox_talk(bdata: &mut BehaviorData) -> bool {
|
|||||||
|
|
||||||
match subject {
|
match subject {
|
||||||
Subject::Regular => {
|
Subject::Regular => {
|
||||||
if let Some(destination_name) = &agent.rtsim_controller.heading_to {
|
if let Some(tgt_stats) = read_data.stats.get(target) {
|
||||||
let msg = format!(
|
agent.rtsim_controller.events.push(RtSimEvent::AddMemory(
|
||||||
"I'm heading to {}! Want to come along?",
|
Memory {
|
||||||
destination_name
|
item: MemoryItem::CharacterInteraction {
|
||||||
);
|
name: tgt_stats.name.clone(),
|
||||||
agent_data.chat_npc(msg, event_emitter);
|
|
||||||
}
|
|
||||||
/*if let (
|
|
||||||
Some((_travel_to, destination_name)),
|
|
||||||
Some(rtsim_entity),
|
|
||||||
) = (&agent.rtsim_controller.travel_to, &agent_data.rtsim_entity)
|
|
||||||
{
|
|
||||||
let personality = &rtsim_entity.brain.personality;
|
|
||||||
let standard_response_msg = || -> String {
|
|
||||||
if personality.will_ambush {
|
|
||||||
format!(
|
|
||||||
"I'm heading to {}! Want to come along? We'll make \
|
|
||||||
great travel buddies, hehe.",
|
|
||||||
destination_name
|
|
||||||
)
|
|
||||||
} else if personality
|
|
||||||
.personality_traits
|
|
||||||
.contains(PersonalityTrait::Extroverted)
|
|
||||||
{
|
|
||||||
format!(
|
|
||||||
"I'm heading to {}! Want to come along?",
|
|
||||||
destination_name
|
|
||||||
)
|
|
||||||
} else if personality
|
|
||||||
.personality_traits
|
|
||||||
.contains(PersonalityTrait::Disagreeable)
|
|
||||||
{
|
|
||||||
"Hrm.".to_string()
|
|
||||||
} else {
|
|
||||||
"Hello!".to_string()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let msg = if let Some(tgt_stats) = read_data.stats.get(target) {
|
|
||||||
agent.rtsim_controller.events.push(RtSimEvent::AddMemory(
|
|
||||||
Memory {
|
|
||||||
item: MemoryItem::CharacterInteraction {
|
|
||||||
name: tgt_stats.name.clone(),
|
|
||||||
},
|
|
||||||
time_to_forget: read_data.time.0 + 600.0,
|
|
||||||
},
|
},
|
||||||
));
|
time_to_forget: read_data.time.0 + 600.0,
|
||||||
if rtsim_entity.brain.remembers_character(&tgt_stats.name) {
|
},
|
||||||
if personality.will_ambush {
|
));
|
||||||
"Just follow me a bit more, hehe.".to_string()
|
if let Some(destination_name) = &agent.rtsim_controller.heading_to {
|
||||||
} else if personality
|
let personality = &agent.rtsim_controller.personality;
|
||||||
.personality_traits
|
let standard_response_msg = || -> String {
|
||||||
.contains(PersonalityTrait::Extroverted)
|
if personality.will_ambush() {
|
||||||
|
format!(
|
||||||
|
"I'm heading to {}! Want to come along? We'll make \
|
||||||
|
great travel buddies, hehe.",
|
||||||
|
destination_name
|
||||||
|
)
|
||||||
|
} else if personality.is(PersonalityTrait::Extroverted)
|
||||||
{
|
{
|
||||||
if personality
|
format!(
|
||||||
.personality_traits
|
"I'm heading to {}! Want to come along?",
|
||||||
.contains(PersonalityTrait::Extroverted)
|
destination_name
|
||||||
|
)
|
||||||
|
} else if personality.is(PersonalityTrait::Disagreeable)
|
||||||
|
{
|
||||||
|
"Hrm.".to_string()
|
||||||
|
} else {
|
||||||
|
"Hello!".to_string()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let msg = if false /* TODO: Remembers character */ {
|
||||||
|
if personality.will_ambush() {
|
||||||
|
"Just follow me a bit more, hehe.".to_string()
|
||||||
|
} else if personality.is(PersonalityTrait::Extroverted)
|
||||||
{
|
{
|
||||||
format!(
|
if personality.is(PersonalityTrait::Extroverted)
|
||||||
"Greetings fair {}! It has been far \
|
{
|
||||||
too long since last I saw you. I'm \
|
format!(
|
||||||
going to {} right now.",
|
"Greetings fair {}! It has been far \
|
||||||
&tgt_stats.name, destination_name
|
too long since last I saw you. I'm \
|
||||||
)
|
going to {} right now.",
|
||||||
} else if personality
|
&tgt_stats.name, destination_name
|
||||||
.personality_traits
|
)
|
||||||
.contains(PersonalityTrait::Disagreeable)
|
} else if personality.is(PersonalityTrait::Disagreeable)
|
||||||
{
|
{
|
||||||
"Oh. It's you again.".to_string()
|
"Oh. It's you again.".to_string()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"Hi again {}! Unfortunately I'm in a \
|
||||||
|
hurry right now. See you!",
|
||||||
|
&tgt_stats.name
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
format!(
|
standard_response_msg()
|
||||||
"Hi again {}! Unfortunately I'm in a \
|
|
||||||
hurry right now. See you!",
|
|
||||||
&tgt_stats.name
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
standard_response_msg()
|
standard_response_msg()
|
||||||
}
|
};
|
||||||
|
agent_data.chat_npc(msg, event_emitter);
|
||||||
|
}
|
||||||
|
/*else if agent.behavior.can_trade(agent_data.alignment.copied(), by) {
|
||||||
|
if !agent.behavior.is(BehaviorState::TRADING) {
|
||||||
|
controller.push_initiate_invite(by, InviteKind::Trade);
|
||||||
|
agent_data.chat_npc(
|
||||||
|
"npc-speech-merchant_advertisement",
|
||||||
|
event_emitter,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
standard_response_msg()
|
let default_msg = "npc-speech-merchant_busy";
|
||||||
};
|
let msg = if agent.rtsim_controller.personality.is(PersonalityTrait::Disagreeable) {
|
||||||
agent_data.chat_npc(msg, event_emitter);
|
|
||||||
} else*/
|
|
||||||
else if agent.behavior.can_trade(agent_data.alignment.copied(), by) {
|
|
||||||
if !agent.behavior.is(BehaviorState::TRADING) {
|
|
||||||
controller.push_initiate_invite(by, InviteKind::Trade);
|
|
||||||
agent_data.chat_npc(
|
|
||||||
"npc-speech-merchant_advertisement",
|
|
||||||
event_emitter,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let default_msg = "npc-speech-merchant_busy";
|
|
||||||
let msg = default_msg/*agent_data.rtsim_entity.map_or(default_msg, |e| {
|
|
||||||
if e.brain
|
|
||||||
.personality
|
|
||||||
.personality_traits
|
|
||||||
.contains(PersonalityTrait::Disagreeable)
|
|
||||||
{
|
|
||||||
"npc-speech-merchant_busy_rude"
|
"npc-speech-merchant_busy_rude"
|
||||||
} else {
|
} else {
|
||||||
default_msg
|
default_msg
|
||||||
}
|
};
|
||||||
})*/;
|
agent_data.chat_npc(msg, event_emitter);
|
||||||
agent_data.chat_npc(msg, event_emitter);
|
}
|
||||||
}
|
}*/ else {
|
||||||
} else {
|
let mut rng = thread_rng();
|
||||||
let mut rng = thread_rng();
|
if let Some(extreme_trait) = agent.rtsim_controller.personality.chat_trait(&mut rng)
|
||||||
/*if let Some(extreme_trait) =
|
{
|
||||||
agent_data.rtsim_entity.and_then(|e| {
|
let msg = match extreme_trait {
|
||||||
e.brain.personality.random_chat_trait(&mut rng)
|
PersonalityTrait::Open => {
|
||||||
})
|
"npc-speech-villager_open"
|
||||||
{
|
},
|
||||||
let msg = match extreme_trait {
|
PersonalityTrait::Adventurous => {
|
||||||
PersonalityTrait::Open => {
|
"npc-speech-villager_adventurous"
|
||||||
"npc-speech-villager_open"
|
},
|
||||||
},
|
PersonalityTrait::Closed => {
|
||||||
PersonalityTrait::Adventurous => {
|
"npc-speech-villager_closed"
|
||||||
"npc-speech-villager_adventurous"
|
},
|
||||||
},
|
PersonalityTrait::Conscientious => {
|
||||||
PersonalityTrait::Closed => {
|
"npc-speech-villager_conscientious"
|
||||||
"npc-speech-villager_closed"
|
},
|
||||||
},
|
PersonalityTrait::Busybody => {
|
||||||
PersonalityTrait::Conscientious => {
|
"npc-speech-villager_busybody"
|
||||||
"npc-speech-villager_conscientious"
|
},
|
||||||
},
|
PersonalityTrait::Unconscientious => {
|
||||||
PersonalityTrait::Busybody => {
|
"npc-speech-villager_unconscientious"
|
||||||
"npc-speech-villager_busybody"
|
},
|
||||||
},
|
PersonalityTrait::Extroverted => {
|
||||||
PersonalityTrait::Unconscientious => {
|
"npc-speech-villager_extroverted"
|
||||||
"npc-speech-villager_unconscientious"
|
},
|
||||||
},
|
PersonalityTrait::Introverted => {
|
||||||
PersonalityTrait::Extroverted => {
|
"npc-speech-villager_introverted"
|
||||||
"npc-speech-villager_extroverted"
|
},
|
||||||
},
|
PersonalityTrait::Agreeable => {
|
||||||
PersonalityTrait::Introverted => {
|
"npc-speech-villager_agreeable"
|
||||||
"npc-speech-villager_introverted"
|
},
|
||||||
},
|
PersonalityTrait::Sociable => {
|
||||||
PersonalityTrait::Agreeable => {
|
"npc-speech-villager_sociable"
|
||||||
"npc-speech-villager_agreeable"
|
},
|
||||||
},
|
PersonalityTrait::Disagreeable => {
|
||||||
PersonalityTrait::Sociable => {
|
"npc-speech-villager_disagreeable"
|
||||||
"npc-speech-villager_sociable"
|
},
|
||||||
},
|
PersonalityTrait::Neurotic => {
|
||||||
PersonalityTrait::Disagreeable => {
|
"npc-speech-villager_neurotic"
|
||||||
"npc-speech-villager_disagreeable"
|
},
|
||||||
},
|
PersonalityTrait::Seeker => {
|
||||||
PersonalityTrait::Neurotic => {
|
"npc-speech-villager_seeker"
|
||||||
"npc-speech-villager_neurotic"
|
},
|
||||||
},
|
PersonalityTrait::SadLoner => {
|
||||||
PersonalityTrait::Seeker => {
|
"npc-speech-villager_sad_loner"
|
||||||
"npc-speech-villager_seeker"
|
},
|
||||||
},
|
PersonalityTrait::Worried => {
|
||||||
PersonalityTrait::SadLoner => {
|
"npc-speech-villager_worried"
|
||||||
"npc-speech-villager_sad_loner"
|
},
|
||||||
},
|
PersonalityTrait::Stable => {
|
||||||
PersonalityTrait::Worried => {
|
"npc-speech-villager_stable"
|
||||||
"npc-speech-villager_worried"
|
},
|
||||||
},
|
};
|
||||||
PersonalityTrait::Stable => {
|
agent_data.chat_npc(msg, event_emitter);
|
||||||
"npc-speech-villager_stable"
|
} else {
|
||||||
},
|
agent_data.chat_npc("npc-speech-villager", event_emitter);
|
||||||
};
|
}
|
||||||
agent_data.chat_npc(msg, event_emitter);
|
|
||||||
} else*/
|
|
||||||
{
|
|
||||||
agent_data.chat_npc("npc-speech-villager", event_emitter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user