diff --git a/rtsim/src/data/npc.rs b/rtsim/src/data/npc.rs index aaf8924d51..36c5d2ae16 100644 --- a/rtsim/src/data/npc.rs +++ b/rtsim/src/data/npc.rs @@ -57,7 +57,8 @@ pub struct Npc { /// (wpos, speed_factor) #[serde(skip_serializing, skip_deserializing)] - pub target: Option<(Vec3, f32)>, + pub goto: Option<(Vec3, f32)>, + /// Whether the NPC is in simulated or loaded mode (when rtsim is run on the server, loaded corresponds to being /// within a loaded chunk). When in loaded mode, the interactions of the NPC should not be simulated but should /// instead be derived from the game. @@ -78,7 +79,7 @@ impl Npc { faction: None, pathing: Default::default(), current_site: None, - target: None, + goto: None, mode: NpcMode::Simulated, } } diff --git a/rtsim/src/rule/npc_ai.rs b/rtsim/src/rule/npc_ai.rs index 9f43a7b265..0b6d50937a 100644 --- a/rtsim/src/rule/npc_ai.rs +++ b/rtsim/src/rule/npc_ai.rs @@ -241,12 +241,19 @@ impl Rule for NpcAi { }); if let Some(home_id) = npc.home { - if let Some((target, _)) = npc.target { + if let Some((target, _)) = npc.goto { // Walk to the current target if target.xy().distance_squared(npc.wpos.xy()) < 4.0 { - npc.target = None; + npc.goto = None; } } else { + // Walk slower when pathing in a site, and faster when between sites + if npc.pathing.intersite_path.is_none() { + npc.goto = Some((npc.goto.map_or(npc.wpos, |(wpos, _)| wpos), 0.7)); + } else { + npc.goto = Some((npc.goto.map_or(npc.wpos, |(wpos, _)| wpos), 1.0)); + } + if let Some((ref mut path, site)) = npc.pathing.intrasite_path { // If the npc walking in a site and want to reroll (because the path was // exhausted.) to try to find a complete path. @@ -256,6 +263,7 @@ impl Rule for NpcAi { .map(|path| (path, site)); } } + if let Some((ref mut path, site)) = npc.pathing.intrasite_path { if let Some(next_tile) = path.path.pop_front() { match &ctx.index.sites.get(site).kind { @@ -268,7 +276,7 @@ impl Rule for NpcAi { ctx.world.sim().get_alt_approx(wpos).unwrap_or(0.0), ); - npc.target = Some((wpos, 1.0)); + npc.goto = Some((wpos, npc.goto.map_or(1.0, |(_, sf)| sf))); }, _ => {}, } @@ -373,7 +381,7 @@ impl Rule for NpcAi { let wpos = wpos.as_::().with_z( ctx.world.sim().get_alt_approx(wpos).unwrap_or(0.0), ); - npc.target = Some((wpos, 1.0)); + npc.goto = Some((wpos, npc.goto.map_or(1.0, |(_, sf)| sf))); *progress += 1; } } else { @@ -417,14 +425,14 @@ impl Rule for NpcAi { } } else { // TODO: Don't make homeless people walk around in circles - npc.target = Some(( + npc.goto = Some(( npc.wpos + Vec3::new( ctx.event.time.0.sin() as f32 * 16.0, ctx.event.time.0.cos() as f32 * 16.0, 0.0, ), - 1.0, + 0.7, )); } } diff --git a/rtsim/src/rule/simulate_npcs.rs b/rtsim/src/rule/simulate_npcs.rs index baebf45c27..34fa6e8d6d 100644 --- a/rtsim/src/rule/simulate_npcs.rs +++ b/rtsim/src/rule/simulate_npcs.rs @@ -21,8 +21,8 @@ impl Rule for SimulateNpcs { { let body = npc.get_body(); - // Move NPCs if they have a target - if let Some((target, speed_factor)) = npc.target { + // Move NPCs if they have a target destination + if let Some((target, speed_factor)) = npc.goto { let diff = target.xy() - npc.wpos.xy(); let dist2 = diff.magnitude_squared(); diff --git a/server/src/rtsim2/tick.rs b/server/src/rtsim2/tick.rs index 20345a8667..bc62d60cc5 100644 --- a/server/src/rtsim2/tick.rs +++ b/server/src/rtsim2/tick.rs @@ -254,8 +254,8 @@ impl<'a> System<'a> for Sys { // Update entity state if let Some(agent) = agent { - agent.rtsim_controller.travel_to = npc.target.map(|(wpos, _)| wpos); - agent.rtsim_controller.speed_factor = npc.target.map_or(1.0, |(_, sf)| sf); + agent.rtsim_controller.travel_to = npc.goto.map(|(wpos, _)| wpos); + agent.rtsim_controller.speed_factor = npc.goto.map_or(1.0, |(_, sf)| sf); agent.rtsim_controller.heading_to = npc.pathing.intersite_path.as_ref().and_then(|(path, _)| { Some(