Reduced downward fall of birds, Humanoid travelers no longer visit dungeons, birds only travel between dungeons

This commit is contained in:
ubruntu 2021-01-05 01:04:01 +00:00 committed by Joshua Barretto
parent 40a301cbf6
commit ae366e03c5
7 changed files with 89 additions and 15 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Map indicators for group members
- Hot-reloading for i18n, sounds, loot lotteries, and more
- Initial support for alternate style keyboards
- Flying birds travel the world
### Changed

View File

@ -71,6 +71,8 @@ pub struct TraversalConfig {
pub min_tgt_dist: f32,
/// Whether the agent can climb.
pub can_climb: bool,
/// Whether the agent can fly.
pub can_fly: bool,
}
const DIAGONALS: [Vec2<i32>; 8] = [
@ -427,7 +429,7 @@ impl Chaser {
.unwrap_or(false)
});
if !walking_towards_edge {
if !walking_towards_edge || traversal_cfg.can_fly {
Some(((tgt - pos) * Vec3::new(1.0, 1.0, 0.0), 1.0))
} else {
None
@ -545,14 +547,14 @@ where
.filter(|_| {
vol.get(pos).map(|b| !b.is_liquid()).unwrap_or(true)
|| traversal_cfg.can_climb
|| traversal_cfg.can_fly
})
.into_iter()
.flatten(),
)
.map(move |dir| (pos, dir))
.filter(move |(pos, dir)| {
is_walkable(pos)
&& is_walkable(&(*pos + **dir))
(traversal_cfg.can_fly || is_walkable(pos) && is_walkable(&(*pos + **dir)))
&& ((dir.z < 1
|| vol
.get(pos + Vec3::unit_z() * 2)

View File

@ -212,6 +212,7 @@ impl<'a> System<'a> for Sys {
in_liquid: physics_state.in_liquid.is_some(),
min_tgt_dist: 1.0,
can_climb: body.map(|b| b.can_climb()).unwrap_or(false),
can_fly: body.map(|b| b.can_fly()).unwrap_or(false),
};
let mut do_idle = false;
@ -221,6 +222,8 @@ impl<'a> System<'a> for Sys {
match &mut agent.activity {
Activity::Idle { bearing, chaser } => {
if let Some(travel_to) = agent.rtsim_controller.travel_to {
//if it has an rtsim destination and can fly then it should
inputs.fly.set_state(traversal_config.can_fly);
if let Some((bearing, speed)) =
chaser.chase(&*terrain, pos.0, vel.0, travel_to, TraversalConfig {
min_tgt_dist: 1.25,
@ -230,10 +233,31 @@ impl<'a> System<'a> for Sys {
inputs.move_dir =
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
* speed.min(agent.rtsim_controller.speed_factor);
inputs.jump.set_state(bearing.z > 1.5);
inputs.jump.set_state(bearing.z > 1.5 || traversal_config.can_fly && traversal_config.on_ground);
inputs.climb = Some(comp::Climb::Up);
//.filter(|_| bearing.z > 0.1 || physics_state.in_liquid.is_some());
inputs.move_z = bearing.z + 0.05;
inputs.move_z = bearing.z + if traversal_config.can_fly {
if terrain
.ray(
pos.0 + Vec3::unit_z(),
pos.0
+ bearing
.try_normalized()
.unwrap_or(Vec3::unit_y())
* 60.0
+ Vec3::unit_z(),
)
.until(Block::is_solid)
.cast()
.1
.map_or(true, |b| b.is_some())
{
1.0 //fly up when approaching obstacles
} else { -0.1 } //flying things should slowly come down from the stratosphere
} else {
0.05 //normal land traveller offset
};
}
} else {
*bearing += Vec2::new(

View File

@ -20,15 +20,42 @@ const PERM_SPECIES: u32 = 0;
const PERM_BODY: u32 = 1;
const PERM_LOADOUT: u32 = 2;
const PERM_LEVEL: u32 = 3;
const PERM_GENUS: u32 = 4;
impl Entity {
pub fn rng(&self, perm: u32) -> impl Rng { RandomPerm::new(self.seed + perm) }
pub fn get_body(&self) -> comp::Body {
let species = *(&comp::humanoid::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
.unwrap();
comp::humanoid::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
match self.rng(PERM_GENUS).gen::<f32>() {
//we want 75% birds, 25% humans for now
x if x < 0.75 => {
let species = *(&comp::bird_medium::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
.unwrap();
comp::bird_medium::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
},
_ => {
let species = *(&comp::humanoid::ALL_SPECIES)
.choose(&mut self.rng(PERM_SPECIES))
.unwrap();
comp::humanoid::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
},
}
}
pub fn get_name(&self) -> String {
use common::{generation::get_npc_name, npc::NPC_NAMES};
let npc_names = NPC_NAMES.read();
match self.get_body() {
comp::Body::BirdMedium(b) => {
get_npc_name(&npc_names.bird_medium, b.species).to_string()
},
comp::Body::BirdSmall(_) => "Warbler".to_string(),
comp::Body::Dragon(b) => get_npc_name(&npc_names.dragon, b.species).to_string(),
comp::Body::Humanoid(b) => get_npc_name(&npc_names.humanoid, b.species).to_string(),
//TODO: finish match as necessary
_ => unimplemented!(),
}
}
pub fn get_level(&self) -> u32 {
@ -102,6 +129,10 @@ impl Entity {
.civs()
.sites
.iter()
.filter(|s| match self.get_body() {
comp::Body::Humanoid(_) => s.1.is_settlement() | s.1.is_castle(),
_ => s.1.is_dungeon(),
})
.filter(|_| thread_rng().gen_range(0i32, 4) == 0)
.min_by_key(|(_, site)| {
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);

View File

@ -88,7 +88,7 @@ pub fn init(state: &mut State, #[cfg(feature = "worldgen")] world: &world::World
#[cfg(not(feature = "worldgen"))]
let mut rtsim = RtSim::new(Vec2::new(40, 40));
for _ in 0..2500 {
for _ in 0..10000 {
let pos = rtsim
.chunks
.size()

View File

@ -98,13 +98,23 @@ impl<'a> System<'a> for Sys {
let body = entity.get_body();
server_emitter.emit(ServerEvent::CreateNpc {
pos: comp::Pos(spawn_pos),
stats: comp::Stats::new("Traveller".to_string(), body)
.with_level(entity.get_level()),
stats: comp::Stats::new(entity.get_name(), body).with_level(entity.get_level()),
health: comp::Health::new(body, 10),
loadout: entity.get_loadout(&ability_map),
loadout: match body {
comp::Body::Humanoid(_) => entity.get_loadout(&ability_map),
_ => comp::Loadout::default(),
},
body,
agent: Some(comp::Agent::new(None, true, &body, false)),
alignment: comp::Alignment::Npc,
agent: Some(comp::Agent::new(
None,
matches!(body, comp::Body::Humanoid(_)),
&body,
false,
)),
alignment: match body {
comp::Body::Humanoid(_) => comp::Alignment::Npc,
_ => comp::Alignment::Wild,
},
scale: comp::Scale(1.0),
drop_item: None,
home_chunk: None,

View File

@ -1071,6 +1071,12 @@ impl Site {
};
self.population += years * self.population * (birth_rate - DEATH_RATE);
}
pub fn is_dungeon(&self) -> bool { matches!(self.kind, SiteKind::Dungeon) }
pub fn is_settlement(&self) -> bool { matches!(self.kind, SiteKind::Settlement) }
pub fn is_castle(&self) -> bool { matches!(self.kind, SiteKind::Castle) }
}
#[repr(u8)]