Make NPCs respond to each other

This commit is contained in:
Joshua Barretto 2023-05-04 11:53:01 +01:00
parent a5b1e41d8b
commit f000347cac
3 changed files with 55 additions and 32 deletions

View File

@ -277,7 +277,7 @@ npc-speech-dir_south_east = south-east
npc-speech-dir_south = south npc-speech-dir_south = south
npc-speech-dir_south_west = south-west npc-speech-dir_south_west = south-west
npc-speech-dir_west = west npc-speech-dir_west = west
npc-speech-dir_north_west = very far away npc-speech-dir_north_west = north-west
npc-speech-dist_very_far = very far away npc-speech-dist_very_far = very far away
npc-speech-dist_far = far away npc-speech-dist_far = far away

View File

@ -543,8 +543,14 @@ fn timeout(time: f64) -> impl FnMut(&mut NpcCtx) -> bool + Clone + Send + Sync {
move |ctx| ctx.time.0 > *timeout.get_or_insert(ctx.time.0 + time) move |ctx| ctx.time.0 > *timeout.get_or_insert(ctx.time.0 + time)
} }
fn talk_to(tgt: Actor, subject: Option<Subject>) -> impl Action { fn talk_to(tgt: Actor, _subject: Option<Subject>) -> impl Action {
now(move |ctx| { now(move |ctx| {
if matches!(tgt, Actor::Npc(_)) && ctx.rng.gen_bool(0.2) {
// Cut off the conversation sometimes to avoid infinite conversations (but only
// if the target is an NPC!) TODO: Don't special case this, have
// some sort of 'bored of conversation' system
idle().l()
} else {
// Mention nearby sites // Mention nearby sites
let comment = if ctx.rng.gen_bool(0.3) let comment = if ctx.rng.gen_bool(0.3)
&& let Some(current_site) = ctx.npc.current_site && let Some(current_site) = ctx.npc.current_site
@ -574,7 +580,18 @@ fn talk_to(tgt: Actor, subject: Option<Subject>) -> impl Action {
} else { } else {
ctx.npc.personality.get_generic_comment(&mut ctx.rng) ctx.npc.personality.get_generic_comment(&mut ctx.rng)
}; };
just(move |ctx| ctx.controller.say(tgt, comment.clone())) // TODO: Don't special-case players
let wait = if matches!(tgt, Actor::Character(_)) {
0.0
} else {
1.5
};
idle()
.repeat()
.stop_if(timeout(wait))
.then(just(move |ctx| ctx.controller.say(tgt, comment.clone())))
.r()
}
}) })
} }

View File

@ -4,6 +4,7 @@ use common::{
AgentEvent, AwarenessState, Target, TimerAction, DEFAULT_INTERACTION_TIME, AgentEvent, AwarenessState, Target, TimerAction, DEFAULT_INTERACTION_TIME,
TRADE_INTERACTION_TIME, TRADE_INTERACTION_TIME,
}, },
dialogue::Subject,
Agent, Alignment, BehaviorCapability, BehaviorState, Body, BuffKind, ControlAction, Agent, Alignment, BehaviorCapability, BehaviorState, Body, BuffKind, ControlAction,
ControlEvent, Controller, InputKind, InventoryEvent, Pos, UtteranceKind, ControlEvent, Controller, InputKind, InventoryEvent, Pos, UtteranceKind,
}, },
@ -494,8 +495,13 @@ fn handle_rtsim_actions(bdata: &mut BehaviorData) -> bool {
.timer .timer
.start(bdata.read_data.time.0, TimerAction::Interact); .start(bdata.read_data.time.0, TimerAction::Interact);
bdata.controller.push_action(ControlAction::Stand); bdata.controller.push_action(ControlAction::Stand);
}
if let Some(target_uid) = bdata.read_data.uids.get(target) {
bdata
.controller
.push_event(ControlEvent::Interact(*target_uid, Subject::Regular));
}
}
bdata.controller.push_utterance(UtteranceKind::Greeting); bdata.controller.push_utterance(UtteranceKind::Greeting);
bdata.agent_data.chat_npc(msg, bdata.event_emitter); bdata.agent_data.chat_npc(msg, bdata.event_emitter);
} }