mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Non-humanoid rtsim respawning, made monsters wander
This commit is contained in:
parent
0f92f38967
commit
6fbd007cea
@ -224,15 +224,16 @@ impl Data {
|
||||
// Spawn monsters into the world
|
||||
for _ in 0..100 {
|
||||
// Try a few times to find a location that's not underwater
|
||||
if let Some(pos) = (0..10)
|
||||
if let Some(wpos) = (0..10)
|
||||
.map(|_| world.sim().get_size().map(|sz| rng.gen_range(0..sz as i32)))
|
||||
.find(|pos| world.sim().get(*pos).map_or(false, |c| !c.is_underwater()))
|
||||
.map(|pos| {
|
||||
let wpos2d = pos.cpos_to_wpos_center();
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
})
|
||||
{
|
||||
let wpos2d = pos.cpos_to_wpos_center();
|
||||
let wpos = wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(world.sim().get_alt_approx(wpos2d).unwrap_or(0.0));
|
||||
|
||||
let species = match rng.gen_range(0..3) {
|
||||
0 => comp::body::biped_large::Species::Cyclops,
|
||||
1 => comp::body::biped_large::Species::Wendigo,
|
||||
|
@ -975,7 +975,9 @@ fn check_inbox(ctx: &mut NpcCtx) -> Option<impl Action> {
|
||||
Some(report_id) if !ctx.known_reports.contains(&report_id) => {
|
||||
#[allow(clippy::single_match)]
|
||||
match ctx.state.data().reports.get(report_id).map(|r| r.kind) {
|
||||
Some(ReportKind::Death { killer, actor, .. }) => {
|
||||
Some(ReportKind::Death { killer, actor, .. })
|
||||
if matches!(&ctx.npc.role, Role::Civilised(_)) =>
|
||||
{
|
||||
// TODO: Don't report self
|
||||
let phrase = if let Some(killer) = killer {
|
||||
// TODO: For now, we don't make sentiment changes if the killer was an
|
||||
@ -1015,7 +1017,8 @@ fn check_inbox(ctx: &mut NpcCtx) -> Option<impl Action> {
|
||||
ctx.controller.say(killer, Content::localized(phrase))
|
||||
}));
|
||||
},
|
||||
None => {}, // Stale report, ignore
|
||||
Some(ReportKind::Death { .. }) => {}, // We don't care about death
|
||||
None => {}, // Stale report, ignore
|
||||
}
|
||||
},
|
||||
Some(_) => {}, // Reports we already know of are ignored
|
||||
@ -1069,11 +1072,11 @@ fn humanoid() -> impl Action {
|
||||
ctx.npc.profession(),
|
||||
Some(Profession::Adventurer(_) | Profession::Merchant)
|
||||
) {
|
||||
adventure().boxed()
|
||||
adventure().l().l()
|
||||
} else if let Some(home) = ctx.npc.home {
|
||||
villager(home).boxed()
|
||||
villager(home).r().l()
|
||||
} else {
|
||||
idle().boxed() // Homeless
|
||||
idle().r() // Homeless
|
||||
};
|
||||
|
||||
casual(action.interrupt_with(react_to_events))
|
||||
@ -1123,10 +1126,28 @@ fn bird_large() -> impl Action {
|
||||
})
|
||||
}
|
||||
|
||||
fn monster() -> impl Action {
|
||||
let mut bearing = Vec2::zero();
|
||||
now(move |ctx| {
|
||||
bearing = bearing
|
||||
.map(|e| e + ctx.rng.gen_range(-0.1..0.1))
|
||||
.try_normalized()
|
||||
.unwrap_or_default();
|
||||
goto_2d(ctx.npc.wpos.xy() + bearing * 24.0, 0.7, 8.0)
|
||||
.debug(move || format!("Moving with a bearing of {:?}", bearing))
|
||||
})
|
||||
.repeat()
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
fn think() -> impl Action {
|
||||
choose(|ctx| match ctx.npc.body {
|
||||
common::comp::Body::Humanoid(_) => casual(humanoid()),
|
||||
common::comp::Body::BirdLarge(_) => casual(bird_large()),
|
||||
_ => casual(socialize()),
|
||||
now(|ctx| match ctx.npc.body {
|
||||
common::comp::Body::Humanoid(_) => humanoid().l().l().l(),
|
||||
common::comp::Body::BirdLarge(_) => bird_large().r().l().l(),
|
||||
_ => match &ctx.npc.role {
|
||||
Role::Civilised(_) => socialize().l().r().l(),
|
||||
Role::Monster => monster().r().r().l(),
|
||||
Role::Wild => idle().r(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp::{self, Body},
|
||||
rtsim::{Actor, NpcAction, NpcActivity, Personality, Role},
|
||||
rtsim::{Actor, NpcAction, NpcActivity, Personality},
|
||||
terrain::CoordinateConversions,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
@ -92,62 +92,62 @@ fn on_death(ctx: EventCtx<SimulateNpcs, OnDeath>) {
|
||||
.with_home(site_id)
|
||||
.with_faction(npc.faction),
|
||||
);
|
||||
Some((npc_id, site_id))
|
||||
Some((npc_id, Some(site_id)))
|
||||
} else {
|
||||
warn!("No site found for respawning humanoid");
|
||||
None
|
||||
}
|
||||
},
|
||||
Body::BirdLarge(_) => {
|
||||
if let Some((site_id, site)) = data
|
||||
.sites
|
||||
.iter()
|
||||
.filter(|(id, site)| {
|
||||
Some(*id) != npc.home
|
||||
&& site.world_site.map_or(false, |s| {
|
||||
matches!(ctx.index.sites.get(s).kind, SiteKind::Dungeon(_))
|
||||
})
|
||||
})
|
||||
.min_by_key(|(_, site)| site.population.len())
|
||||
{
|
||||
let rand_wpos = |rng: &mut ChaChaRng| {
|
||||
let wpos2d = site.wpos.map(|e| e + rng.gen_range(-10..10));
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(ctx.world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
};
|
||||
let species = [
|
||||
comp::body::bird_large::Species::Phoenix,
|
||||
comp::body::bird_large::Species::Cockatrice,
|
||||
comp::body::bird_large::Species::Roc,
|
||||
]
|
||||
.choose(&mut rng)
|
||||
.unwrap();
|
||||
let npc_id = data.npcs.create_npc(
|
||||
Npc::new(
|
||||
rng.gen(),
|
||||
rand_wpos(&mut rng),
|
||||
Body::BirdLarge(comp::body::bird_large::Body::random_with(
|
||||
&mut rng, species,
|
||||
)),
|
||||
Role::Wild,
|
||||
)
|
||||
.with_home(site_id),
|
||||
);
|
||||
Some((npc_id, site_id))
|
||||
} else {
|
||||
warn!("No site found for respawning bird");
|
||||
None
|
||||
}
|
||||
},
|
||||
body => {
|
||||
error!("Tried to respawn rtsim NPC with invalid body: {:?}", body);
|
||||
None
|
||||
let home = npc.home.and_then(|_| {
|
||||
data.sites
|
||||
.iter()
|
||||
.filter(|(id, site)| {
|
||||
Some(*id) != npc.home
|
||||
&& site.world_site.map_or(false, |s| {
|
||||
matches!(ctx.index.sites.get(s).kind, SiteKind::Dungeon(_))
|
||||
})
|
||||
})
|
||||
.min_by_key(|(_, site)| site.population.len())
|
||||
});
|
||||
|
||||
let wpos = if let Some((_, home)) = home {
|
||||
let wpos2d = home.wpos.map(|e| e + rng.gen_range(-10..10));
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(ctx.world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
} else {
|
||||
let pos = (0..10)
|
||||
.map(|_| {
|
||||
ctx.world
|
||||
.sim()
|
||||
.get_size()
|
||||
.map(|sz| rng.gen_range(0..sz as i32))
|
||||
})
|
||||
.find(|pos| {
|
||||
ctx.world
|
||||
.sim()
|
||||
.get(*pos)
|
||||
.map_or(false, |c| !c.is_underwater())
|
||||
})
|
||||
.unwrap_or(ctx.world.sim().get_size().as_() / 2);
|
||||
let wpos2d = pos.cpos_to_wpos_center();
|
||||
wpos2d
|
||||
.map(|e| e as f32 + 0.5)
|
||||
.with_z(ctx.world.sim().get_alt_approx(wpos2d).unwrap_or(0.0))
|
||||
};
|
||||
|
||||
let home = home.map(|(site_id, _)| site_id);
|
||||
|
||||
let npc_id = data.npcs.create_npc(
|
||||
Npc::new(rng.gen(), wpos, body, npc.role.clone()).with_home(home),
|
||||
);
|
||||
Some((npc_id, home))
|
||||
},
|
||||
};
|
||||
|
||||
// Add the NPC to their home site
|
||||
if let Some((npc_id, home_site)) = details {
|
||||
if let Some((npc_id, Some(home_site))) = details {
|
||||
if let Some(home) = data.sites.get_mut(home_site) {
|
||||
home.population.insert(npc_id);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user