mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make NPCs respond to each other
This commit is contained in:
parent
a5b1e41d8b
commit
f000347cac
@ -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
|
||||||
|
@ -543,38 +543,55 @@ 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| {
|
||||||
// Mention nearby sites
|
if matches!(tgt, Actor::Npc(_)) && ctx.rng.gen_bool(0.2) {
|
||||||
let comment = if ctx.rng.gen_bool(0.3)
|
// Cut off the conversation sometimes to avoid infinite conversations (but only
|
||||||
&& let Some(current_site) = ctx.npc.current_site
|
// if the target is an NPC!) TODO: Don't special case this, have
|
||||||
&& let Some(current_site) = ctx.state.data().sites.get(current_site)
|
// some sort of 'bored of conversation' system
|
||||||
&& let Some(mention_site) = current_site.nearby_sites_by_size.choose(&mut ctx.rng)
|
idle().l()
|
||||||
&& let Some(mention_site) = ctx.state.data().sites.get(*mention_site)
|
|
||||||
&& let Some(mention_site_name) = mention_site.world_site
|
|
||||||
.map(|ws| ctx.index.sites.get(ws).name().to_string())
|
|
||||||
{
|
|
||||||
Content::localized_with_args("npc-speech-tell_site", [
|
|
||||||
("site", Content::Plain(mention_site_name)),
|
|
||||||
("dir", Direction::from_dir(mention_site.wpos.as_() - ctx.npc.wpos.xy()).localize_npc()),
|
|
||||||
("dist", Distance::from_length(mention_site.wpos.as_().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
|
||||||
])
|
|
||||||
// Mention nearby monsters
|
|
||||||
} else if ctx.rng.gen_bool(0.3)
|
|
||||||
&& let Some(monster) = ctx.state.data().npcs
|
|
||||||
.values()
|
|
||||||
.filter(|other| matches!(&other.role, Role::Monster))
|
|
||||||
.min_by_key(|other| other.wpos.xy().distance(ctx.npc.wpos.xy()) as i32)
|
|
||||||
{
|
|
||||||
Content::localized_with_args("npc-speech-tell_monster", [
|
|
||||||
("body", monster.body.localize()),
|
|
||||||
("dir", Direction::from_dir(monster.wpos.xy() - ctx.npc.wpos.xy()).localize_npc()),
|
|
||||||
("dist", Distance::from_length(monster.wpos.xy().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
|
||||||
])
|
|
||||||
} else {
|
} else {
|
||||||
ctx.npc.personality.get_generic_comment(&mut ctx.rng)
|
// Mention nearby sites
|
||||||
};
|
let comment = if ctx.rng.gen_bool(0.3)
|
||||||
just(move |ctx| ctx.controller.say(tgt, comment.clone()))
|
&& let Some(current_site) = ctx.npc.current_site
|
||||||
|
&& let Some(current_site) = ctx.state.data().sites.get(current_site)
|
||||||
|
&& let Some(mention_site) = current_site.nearby_sites_by_size.choose(&mut ctx.rng)
|
||||||
|
&& let Some(mention_site) = ctx.state.data().sites.get(*mention_site)
|
||||||
|
&& let Some(mention_site_name) = mention_site.world_site
|
||||||
|
.map(|ws| ctx.index.sites.get(ws).name().to_string())
|
||||||
|
{
|
||||||
|
Content::localized_with_args("npc-speech-tell_site", [
|
||||||
|
("site", Content::Plain(mention_site_name)),
|
||||||
|
("dir", Direction::from_dir(mention_site.wpos.as_() - ctx.npc.wpos.xy()).localize_npc()),
|
||||||
|
("dist", Distance::from_length(mention_site.wpos.as_().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
||||||
|
])
|
||||||
|
// Mention nearby monsters
|
||||||
|
} else if ctx.rng.gen_bool(0.3)
|
||||||
|
&& let Some(monster) = ctx.state.data().npcs
|
||||||
|
.values()
|
||||||
|
.filter(|other| matches!(&other.role, Role::Monster))
|
||||||
|
.min_by_key(|other| other.wpos.xy().distance(ctx.npc.wpos.xy()) as i32)
|
||||||
|
{
|
||||||
|
Content::localized_with_args("npc-speech-tell_monster", [
|
||||||
|
("body", monster.body.localize()),
|
||||||
|
("dir", Direction::from_dir(monster.wpos.xy() - ctx.npc.wpos.xy()).localize_npc()),
|
||||||
|
("dist", Distance::from_length(monster.wpos.xy().distance(ctx.npc.wpos.xy()) as i32).localize_npc()),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
ctx.npc.personality.get_generic_comment(&mut ctx.rng)
|
||||||
|
};
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user