mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Reduced downward fall of birds, Humanoid travelers no longer visit dungeons, birds only travel between dungeons
This commit is contained in:
parent
40a301cbf6
commit
ae366e03c5
@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Map indicators for group members
|
- Map indicators for group members
|
||||||
- Hot-reloading for i18n, sounds, loot lotteries, and more
|
- Hot-reloading for i18n, sounds, loot lotteries, and more
|
||||||
- Initial support for alternate style keyboards
|
- Initial support for alternate style keyboards
|
||||||
|
- Flying birds travel the world
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -71,6 +71,8 @@ pub struct TraversalConfig {
|
|||||||
pub min_tgt_dist: f32,
|
pub min_tgt_dist: f32,
|
||||||
/// Whether the agent can climb.
|
/// Whether the agent can climb.
|
||||||
pub can_climb: bool,
|
pub can_climb: bool,
|
||||||
|
/// Whether the agent can fly.
|
||||||
|
pub can_fly: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DIAGONALS: [Vec2<i32>; 8] = [
|
const DIAGONALS: [Vec2<i32>; 8] = [
|
||||||
@ -427,7 +429,7 @@ impl Chaser {
|
|||||||
.unwrap_or(false)
|
.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))
|
Some(((tgt - pos) * Vec3::new(1.0, 1.0, 0.0), 1.0))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -545,14 +547,14 @@ where
|
|||||||
.filter(|_| {
|
.filter(|_| {
|
||||||
vol.get(pos).map(|b| !b.is_liquid()).unwrap_or(true)
|
vol.get(pos).map(|b| !b.is_liquid()).unwrap_or(true)
|
||||||
|| traversal_cfg.can_climb
|
|| traversal_cfg.can_climb
|
||||||
|
|| traversal_cfg.can_fly
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)
|
)
|
||||||
.map(move |dir| (pos, dir))
|
.map(move |dir| (pos, dir))
|
||||||
.filter(move |(pos, dir)| {
|
.filter(move |(pos, dir)| {
|
||||||
is_walkable(pos)
|
(traversal_cfg.can_fly || is_walkable(pos) && is_walkable(&(*pos + **dir)))
|
||||||
&& is_walkable(&(*pos + **dir))
|
|
||||||
&& ((dir.z < 1
|
&& ((dir.z < 1
|
||||||
|| vol
|
|| vol
|
||||||
.get(pos + Vec3::unit_z() * 2)
|
.get(pos + Vec3::unit_z() * 2)
|
||||||
|
@ -212,6 +212,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
in_liquid: physics_state.in_liquid.is_some(),
|
in_liquid: physics_state.in_liquid.is_some(),
|
||||||
min_tgt_dist: 1.0,
|
min_tgt_dist: 1.0,
|
||||||
can_climb: body.map(|b| b.can_climb()).unwrap_or(false),
|
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;
|
let mut do_idle = false;
|
||||||
@ -221,6 +222,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
match &mut agent.activity {
|
match &mut agent.activity {
|
||||||
Activity::Idle { bearing, chaser } => {
|
Activity::Idle { bearing, chaser } => {
|
||||||
if let Some(travel_to) = agent.rtsim_controller.travel_to {
|
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)) =
|
if let Some((bearing, speed)) =
|
||||||
chaser.chase(&*terrain, pos.0, vel.0, travel_to, TraversalConfig {
|
chaser.chase(&*terrain, pos.0, vel.0, travel_to, TraversalConfig {
|
||||||
min_tgt_dist: 1.25,
|
min_tgt_dist: 1.25,
|
||||||
@ -230,10 +233,31 @@ impl<'a> System<'a> for Sys {
|
|||||||
inputs.move_dir =
|
inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
||||||
* speed.min(agent.rtsim_controller.speed_factor);
|
* 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);
|
inputs.climb = Some(comp::Climb::Up);
|
||||||
//.filter(|_| bearing.z > 0.1 || physics_state.in_liquid.is_some());
|
//.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 {
|
} else {
|
||||||
*bearing += Vec2::new(
|
*bearing += Vec2::new(
|
||||||
|
@ -20,15 +20,42 @@ const PERM_SPECIES: u32 = 0;
|
|||||||
const PERM_BODY: u32 = 1;
|
const PERM_BODY: u32 = 1;
|
||||||
const PERM_LOADOUT: u32 = 2;
|
const PERM_LOADOUT: u32 = 2;
|
||||||
const PERM_LEVEL: u32 = 3;
|
const PERM_LEVEL: u32 = 3;
|
||||||
|
const PERM_GENUS: u32 = 4;
|
||||||
|
|
||||||
impl Entity {
|
impl Entity {
|
||||||
pub fn rng(&self, perm: u32) -> impl Rng { RandomPerm::new(self.seed + perm) }
|
pub fn rng(&self, perm: u32) -> impl Rng { RandomPerm::new(self.seed + perm) }
|
||||||
|
|
||||||
pub fn get_body(&self) -> comp::Body {
|
pub fn get_body(&self) -> comp::Body {
|
||||||
let species = *(&comp::humanoid::ALL_SPECIES)
|
match self.rng(PERM_GENUS).gen::<f32>() {
|
||||||
.choose(&mut self.rng(PERM_SPECIES))
|
//we want 75% birds, 25% humans for now
|
||||||
.unwrap();
|
x if x < 0.75 => {
|
||||||
comp::humanoid::Body::random_with(&mut self.rng(PERM_BODY), &species).into()
|
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 {
|
pub fn get_level(&self) -> u32 {
|
||||||
@ -102,6 +129,10 @@ impl Entity {
|
|||||||
.civs()
|
.civs()
|
||||||
.sites
|
.sites
|
||||||
.iter()
|
.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)
|
.filter(|_| thread_rng().gen_range(0i32, 4) == 0)
|
||||||
.min_by_key(|(_, site)| {
|
.min_by_key(|(_, site)| {
|
||||||
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
let wpos = site.center * TerrainChunk::RECT_SIZE.map(|e| e as i32);
|
||||||
|
@ -88,7 +88,7 @@ pub fn init(state: &mut State, #[cfg(feature = "worldgen")] world: &world::World
|
|||||||
#[cfg(not(feature = "worldgen"))]
|
#[cfg(not(feature = "worldgen"))]
|
||||||
let mut rtsim = RtSim::new(Vec2::new(40, 40));
|
let mut rtsim = RtSim::new(Vec2::new(40, 40));
|
||||||
|
|
||||||
for _ in 0..2500 {
|
for _ in 0..10000 {
|
||||||
let pos = rtsim
|
let pos = rtsim
|
||||||
.chunks
|
.chunks
|
||||||
.size()
|
.size()
|
||||||
|
@ -98,13 +98,23 @@ impl<'a> System<'a> for Sys {
|
|||||||
let body = entity.get_body();
|
let body = entity.get_body();
|
||||||
server_emitter.emit(ServerEvent::CreateNpc {
|
server_emitter.emit(ServerEvent::CreateNpc {
|
||||||
pos: comp::Pos(spawn_pos),
|
pos: comp::Pos(spawn_pos),
|
||||||
stats: comp::Stats::new("Traveller".to_string(), body)
|
stats: comp::Stats::new(entity.get_name(), body).with_level(entity.get_level()),
|
||||||
.with_level(entity.get_level()),
|
|
||||||
health: comp::Health::new(body, 10),
|
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,
|
body,
|
||||||
agent: Some(comp::Agent::new(None, true, &body, false)),
|
agent: Some(comp::Agent::new(
|
||||||
alignment: comp::Alignment::Npc,
|
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),
|
scale: comp::Scale(1.0),
|
||||||
drop_item: None,
|
drop_item: None,
|
||||||
home_chunk: None,
|
home_chunk: None,
|
||||||
|
@ -1071,6 +1071,12 @@ impl Site {
|
|||||||
};
|
};
|
||||||
self.population += years * self.population * (birth_rate - DEATH_RATE);
|
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)]
|
#[repr(u8)]
|
||||||
|
Loading…
Reference in New Issue
Block a user