mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Better NPC spawning
This commit is contained in:
parent
64324262c7
commit
5062920b5c
@ -18,7 +18,7 @@ use common::{
|
||||
use rand::prelude::*;
|
||||
use tracing::info;
|
||||
use vek::*;
|
||||
use world::{site::SiteKind, IndexRef, World};
|
||||
use world::{site::SiteKind, site2::PlotKind, IndexRef, World};
|
||||
|
||||
impl Data {
|
||||
pub fn generate(settings: &WorldSettings, world: &World, index: IndexRef) -> Self {
|
||||
@ -77,10 +77,16 @@ impl Data {
|
||||
this.sites.len()
|
||||
);
|
||||
// Spawn some test entities at the sites
|
||||
for (site_id, site) in this.sites.iter()
|
||||
// TODO: Stupid
|
||||
.filter(|(_, site)| site.world_site.map_or(false, |ws|
|
||||
matches!(&index.sites.get(ws).kind, SiteKind::Refactor(_))))
|
||||
for (site_id, site, site2) in this.sites.iter()
|
||||
// TODO: Stupid. Only find site2 towns
|
||||
.filter_map(|(site_id, site)| Some((site_id, site, site.world_site
|
||||
.and_then(|ws| match &index.sites.get(ws).kind {
|
||||
SiteKind::Refactor(site2)
|
||||
| SiteKind::CliffTown(site2)
|
||||
| SiteKind::SavannahPit(site2)
|
||||
| SiteKind::DesertCity(site2) => Some(site2),
|
||||
_ => None,
|
||||
})?)))
|
||||
{
|
||||
let Some(good_or_evil) = site
|
||||
.faction
|
||||
@ -88,8 +94,13 @@ impl Data {
|
||||
.map(|f| f.good_or_evil)
|
||||
else { continue };
|
||||
|
||||
let rand_wpos = |rng: &mut SmallRng| {
|
||||
let wpos2d = site.wpos.map(|e| e + rng.gen_range(-10..10));
|
||||
let rand_wpos = |rng: &mut SmallRng, matches_plot: fn(&PlotKind) -> bool| {
|
||||
let wpos2d = site2
|
||||
.plots()
|
||||
.filter(|plot| matches_plot(plot.kind()))
|
||||
.choose(&mut thread_rng())
|
||||
.map(|plot| site2.tile_center_wpos(plot.root_tile()))
|
||||
.unwrap_or_else(|| site.wpos.map(|e| e + rng.gen_range(-10..10)));
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
@ -98,47 +109,71 @@ impl Data {
|
||||
let species = comp::humanoid::ALL_SPECIES.choose(&mut *rng).unwrap();
|
||||
Body::Humanoid(comp::humanoid::Body::random_with(rng, species))
|
||||
};
|
||||
let matches_buildings = (|kind: &PlotKind| {
|
||||
matches!(
|
||||
kind,
|
||||
PlotKind::House(_) | PlotKind::Workshop(_) | PlotKind::Plaza
|
||||
)
|
||||
}) as _;
|
||||
let matches_plazas = (|kind: &PlotKind| matches!(kind, PlotKind::Plaza)) as _;
|
||||
if good_or_evil {
|
||||
for _ in 0..32 {
|
||||
for _ in 0..site2.plots().len() {
|
||||
this.npcs.create_npc(
|
||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||
.with_faction(site.faction)
|
||||
.with_home(site_id)
|
||||
.with_personality(Personality::random(&mut rng))
|
||||
.with_profession(match rng.gen_range(0..20) {
|
||||
0 => Profession::Hunter,
|
||||
1 => Profession::Blacksmith,
|
||||
2 => Profession::Chef,
|
||||
3 => Profession::Alchemist,
|
||||
5..=8 => Profession::Farmer,
|
||||
9..=10 => Profession::Herbalist,
|
||||
11..=15 => Profession::Guard,
|
||||
_ => Profession::Adventurer(rng.gen_range(0..=3)),
|
||||
}),
|
||||
Npc::new(
|
||||
rng.gen(),
|
||||
rand_wpos(&mut rng, matches_buildings),
|
||||
random_humanoid(&mut rng),
|
||||
)
|
||||
.with_faction(site.faction)
|
||||
.with_home(site_id)
|
||||
.with_personality(Personality::random(&mut rng))
|
||||
.with_profession(match rng.gen_range(0..20) {
|
||||
0 => Profession::Hunter,
|
||||
1 => Profession::Blacksmith,
|
||||
2 => Profession::Chef,
|
||||
3 => Profession::Alchemist,
|
||||
5..=8 => Profession::Farmer,
|
||||
9..=10 => Profession::Herbalist,
|
||||
11..=16 => Profession::Guard,
|
||||
_ => Profession::Adventurer(rng.gen_range(0..=3)),
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
for _ in 0..15 {
|
||||
this.npcs.create_npc(
|
||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||
.with_personality(Personality::random_evil(&mut rng))
|
||||
.with_faction(site.faction)
|
||||
.with_home(site_id)
|
||||
.with_profession(match rng.gen_range(0..20) {
|
||||
_ => Profession::Cultist,
|
||||
}),
|
||||
Npc::new(
|
||||
rng.gen(),
|
||||
rand_wpos(&mut rng, matches_buildings),
|
||||
random_humanoid(&mut rng),
|
||||
)
|
||||
.with_personality(Personality::random_evil(&mut rng))
|
||||
.with_faction(site.faction)
|
||||
.with_home(site_id)
|
||||
.with_profession(match rng.gen_range(0..20) {
|
||||
_ => Profession::Cultist,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
// Merchants
|
||||
if good_or_evil {
|
||||
for _ in 0..(site2.plots().len() / 6) + 1 {
|
||||
this.npcs.create_npc(
|
||||
Npc::new(
|
||||
rng.gen(),
|
||||
rand_wpos(&mut rng, matches_plazas),
|
||||
random_humanoid(&mut rng),
|
||||
)
|
||||
.with_home(site_id)
|
||||
.with_personality(Personality::random_good(&mut rng))
|
||||
.with_profession(Profession::Merchant),
|
||||
);
|
||||
}
|
||||
}
|
||||
this.npcs.create_npc(
|
||||
Npc::new(rng.gen(), rand_wpos(&mut rng), random_humanoid(&mut rng))
|
||||
.with_home(site_id)
|
||||
.with_personality(Personality::random_good(&mut rng))
|
||||
.with_profession(Profession::Merchant),
|
||||
);
|
||||
|
||||
if rng.gen_bool(0.4) {
|
||||
let wpos = rand_wpos(&mut rng) + Vec3::unit_z() * 50.0;
|
||||
let wpos = rand_wpos(&mut rng, matches_plazas) + Vec3::unit_z() * 50.0;
|
||||
let vehicle_id = this
|
||||
.npcs
|
||||
.create_vehicle(Vehicle::new(wpos, comp::body::ship::Body::DefaultAirship));
|
||||
|
@ -395,13 +395,13 @@ fn travel_to_point(wpos: Vec2<f32>) -> impl Action {
|
||||
const WAYPOINT: f32 = 24.0;
|
||||
let start = ctx.npc.wpos.xy();
|
||||
let diff = wpos - start;
|
||||
// if diff.magnitude() > 1.0 {
|
||||
let n = (diff.magnitude() / WAYPOINT).max(1.0);
|
||||
let mut points = (1..n as usize + 1).map(move |i| start + diff * (i as f32 / n));
|
||||
if diff.magnitude() > 1.0 {
|
||||
traverse_points(move |_| points.next()).boxed()
|
||||
} else {
|
||||
finish().boxed()
|
||||
}
|
||||
traverse_points(move |_| points.next()).boxed()
|
||||
// } else {
|
||||
// finish().boxed()
|
||||
// }
|
||||
})
|
||||
.debug(|| "travel to point")
|
||||
}
|
||||
@ -525,11 +525,16 @@ fn adventure() -> impl Action {
|
||||
.min_by_key(|(_, site)| site.wpos.as_().distance(ctx.npc.wpos.xy()) as i32)
|
||||
.map(|(site_id, _)| site_id)
|
||||
{
|
||||
let wait_time = if matches!(ctx.npc.profession, Some(Profession::Merchant)) {
|
||||
60.0 * 15.0
|
||||
} else {
|
||||
60.0 * 3.0
|
||||
};
|
||||
// Travel to the site
|
||||
important(
|
||||
travel_to_site(tgt_site)
|
||||
// Stop for a few minutes
|
||||
.then(villager(tgt_site).repeat().stop_if(timeout(60.0 * 3.0)))
|
||||
.then(villager(tgt_site).repeat().stop_if(timeout(wait_time)))
|
||||
.map(|_| ())
|
||||
.boxed(),
|
||||
)
|
||||
|
@ -212,7 +212,7 @@ impl RtSim {
|
||||
});
|
||||
|
||||
if wait_until_finished {
|
||||
handle.join();
|
||||
handle.join().expect("Save thread failed to join");
|
||||
}
|
||||
|
||||
self.last_saved = Some(Instant::now());
|
||||
|
Loading…
Reference in New Issue
Block a user