This commit is contained in:
Joshua Barretto 2020-04-23 17:00:48 +01:00
parent 0c491bb558
commit 2a6a19f7ef
18 changed files with 177 additions and 129 deletions

View File

@ -75,7 +75,8 @@ impl Route {
None
} else {
let next_tgt = next.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
if ((pos - (next_tgt + Vec3::unit_z() * 0.5)) * Vec3::new(1.0, 1.0, 0.3)).magnitude_squared()
if ((pos - (next_tgt + Vec3::unit_z() * 0.5)) * Vec3::new(1.0, 1.0, 0.3))
.magnitude_squared()
< (traversal_tolerance * 2.0).powf(2.0)
{
self.next_idx += 1;

View File

@ -115,9 +115,10 @@ impl<'a> System<'a> for Sys {
let scale = scales.get(entity).map(|s| s.0).unwrap_or(1.0);
// This controls how picky NPCs are about their pathfinding. Giants are larger and so
// can afford to be less precise when trying to move around the world (especially since
// they would otherwise get stuck on obstacles that smaller entities would not).
// This controls how picky NPCs are about their pathfinding. Giants are larger
// and so can afford to be less precise when trying to move around
// the world (especially since they would otherwise get stuck on
// obstacles that smaller entities would not).
let traversal_tolerance = scale;
let mut do_idle = false;

View File

@ -317,13 +317,14 @@ impl<'a> System<'a> for Sys {
&& was_on_ground
&& !collision_with(
pos.0 - Vec3::unit_z() * 0.05,
&|block| block.is_solid() && block.get_height() >= (pos.0.z - 0.05).rem_euclid(1.0),
&|block| {
block.is_solid() && block.get_height() >= (pos.0.z - 0.05).rem_euclid(1.0)
},
near_iter.clone(),
)
{
let snap_height = terrain
.get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.05)
.map(|e| e.floor() as i32))
.get(Vec3::new(pos.0.x, pos.0.y, pos.0.z - 0.05).map(|e| e.floor() as i32))
.ok()
.filter(|block| block.is_solid())
.map(|block| block.get_height())
@ -340,7 +341,11 @@ impl<'a> System<'a> for Sys {
];
if let (wall_dir, true) = dirs.iter().fold((Vec3::zero(), false), |(a, hit), dir| {
if collision_with(pos.0 + *dir * 0.01, &|block| block.is_solid(), near_iter.clone()) {
if collision_with(
pos.0 + *dir * 0.01,
&|block| block.is_solid(),
near_iter.clone(),
) {
(a + dir, true)
} else {
(a, hit)
@ -352,7 +357,8 @@ impl<'a> System<'a> for Sys {
}
// Figure out if we're in water
physics_state.in_fluid = collision_with(pos.0, &|block| block.is_fluid(), near_iter.clone());
physics_state.in_fluid =
collision_with(pos.0, &|block| block.is_fluid(), near_iter.clone());
let _ = physics_states.insert(entity, physics_state);
}

View File

@ -303,9 +303,11 @@ impl Block {
pub fn get_ori(&self) -> Option<u8> {
match self.kind {
BlockKind::Window1 | BlockKind::Window2 | BlockKind::Window3 | BlockKind::Window4 | BlockKind::Door => {
Some(self.color[0] & 0b111)
},
BlockKind::Window1
| BlockKind::Window2
| BlockKind::Window3
| BlockKind::Window4
| BlockKind::Door => Some(self.color[0] & 0b111),
_ => None,
}
}

View File

@ -49,9 +49,9 @@ use uvth::{ThreadPool, ThreadPoolBuilder};
use vek::*;
#[cfg(feature = "worldgen")]
use world::{
civ::SiteKind,
sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP, WORLD_SIZE},
World,
civ::SiteKind,
};
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
@ -141,7 +141,9 @@ impl Server {
// calculate the absolute position of the chunk in the world
// (we could add TerrainChunkSize::RECT_SIZE / 2 here, to spawn in the midde of
// the chunk)
let spawn_location = spawn_chunk.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 * sz as i32 + sz as i32 / 2);
let spawn_location = spawn_chunk.map2(TerrainChunkSize::RECT_SIZE, |e, sz| {
e as i32 * sz as i32 + sz as i32 / 2
});
// get a z cache for the collumn in which we want to spawn
let mut block_sampler = world.sample_blocks();

View File

@ -4,11 +4,11 @@ use common::{
assets,
comp::{self, item, CharacterAbility, Item, ItemConfig, Player, Pos},
event::{EventBus, ServerEvent},
generation::get_npc_name,
msg::ServerMsg,
npc::NPC_NAMES,
state::TerrainChanges,
terrain::TerrainGrid,
generation::get_npc_name,
};
use rand::Rng;
use specs::{Join, Read, ReadStorage, System, Write, WriteExpect, WriteStorage};

View File

@ -302,9 +302,8 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
for j in 0..3 {
for k in 0..3 {
blocks[k][j][i] = Some(flat_get(
Vec3::new(x, y, z_start)
+ Vec3::new(i as i32, j as i32, k as i32)
- 1
Vec3::new(x, y, z_start) + Vec3::new(i as i32, j as i32, k as i32)
- 1,
));
}
}
@ -314,14 +313,20 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
for i in 0..3 {
for j in 0..3 {
for k in 0..3 {
lights[k][j][i] = if blocks[k][j][i].map(|block| block.is_opaque()).unwrap_or(false) {
lights[k][j][i] = if blocks[k][j][i]
.map(|block| block.is_opaque())
.unwrap_or(false)
{
None
} else {
Some(light(Vec3::new(
x + range.min.x,
y + range.min.y,
z_start + range.min.z,
) + Vec3::new(i as i32, j as i32, k as i32) - 1))
Some(light(
Vec3::new(
x + range.min.x,
y + range.min.y,
z_start + range.min.z,
) + Vec3::new(i as i32, j as i32, k as i32)
- 1,
))
};
}
}
@ -344,7 +349,6 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
blocks[0] = blocks[1];
blocks[1] = blocks[2];
for i in 0..3 {
for j in 0..3 {
let block = Some(flat_get(pos + Vec3::new(i as i32, j as i32, 2) - 1));
@ -353,10 +357,15 @@ impl<V: RectRasterableVol<Vox = Block> + ReadVol + Debug> Meshable<TerrainPipeli
}
for i in 0..3 {
for j in 0..3 {
lights[2][j][i] = if blocks[2][j][i].map(|block| block.is_opaque()).unwrap_or(false) {
lights[2][j][i] = if blocks[2][j][i]
.map(|block| block.is_opaque())
.unwrap_or(false)
{
None
} else {
Some(light(pos + range.min + Vec3::new(i as i32, j as i32, 2) - 1))
Some(light(
pos + range.min + Vec3::new(i as i32, j as i32, 2) - 1,
))
};
}
}

View File

@ -39,10 +39,8 @@ fn get_ao_quad(
for x in 0..2 {
for y in 0..2 {
let dark_pos = shift + offs[0] * x + offs[1] * y + 1;
if let Some(dark) = darknesses
[dark_pos.z as usize]
[dark_pos.y as usize]
[dark_pos.x as usize]
if let Some(dark) =
darknesses[dark_pos.z as usize][dark_pos.y as usize][dark_pos.x as usize]
{
darkness += dark;
total += 1.0;

View File

@ -369,10 +369,13 @@ impl Civs {
.expect("Track locations must be neighbors")
.0;
ctx.sim.get_mut(locs[0]).unwrap().path.neighbors |= 1 << ((to_prev_idx as u8 + 4) % 8);
ctx.sim.get_mut(locs[2]).unwrap().path.neighbors |= 1 << ((to_next_idx as u8 + 4) % 8);
ctx.sim.get_mut(locs[0]).unwrap().path.neighbors |=
1 << ((to_prev_idx as u8 + 4) % 8);
ctx.sim.get_mut(locs[2]).unwrap().path.neighbors |=
1 << ((to_next_idx as u8 + 4) % 8);
let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
chunk.path.neighbors |= (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
chunk.path.neighbors |=
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
chunk.path.offset = Vec2::new(
ctx.rng.gen_range(-16.0, 16.0),
ctx.rng.gen_range(-16.0, 16.0),

View File

@ -221,7 +221,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
sim.gen_ctx.turb_x_nz.get((wposf.div(48.0)).into_array()) as f32,
sim.gen_ctx.turb_y_nz.get((wposf.div(48.0)).into_array()) as f32,
) * 12.0;
let wposf_turb = wposf;// + turb.map(|e| e as f64);
let wposf_turb = wposf; // + turb.map(|e| e as f64);
let chaos = sim.get_interpolated(wpos, |chunk| chunk.chaos)?;
let temp = sim.get_interpolated(wpos, |chunk| chunk.temp)?;
@ -590,12 +590,9 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
let near_cliffs = sim_chunk.near_cliffs;
let river_gouge = 0.5;
let (_in_water, water_dist, alt_, water_level, riverless_alt, warp_factor) = if let Some((
max_border_river_pos,
river_chunk,
max_border_river,
max_border_river_dist,
)) =
let (_in_water, water_dist, alt_, water_level, riverless_alt, warp_factor) = if let Some(
(max_border_river_pos, river_chunk, max_border_river, max_border_river_dist),
) =
max_river
{
// This is flowing into a lake, or a lake, or is at least a non-ocean tile.

View File

@ -1,13 +1,13 @@
use std::f32;
use vek::*;
use common::{
terrain::{Block, BlockKind},
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
};
use crate::{
column::ColumnSample,
util::{RandomField, Sampler},
};
use common::{
terrain::{Block, BlockKind},
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
};
use std::f32;
use vek::*;
pub fn apply_paths_to<'a>(
wpos2d: Vec2<i32>,
@ -37,7 +37,8 @@ pub fn apply_paths_to<'a>(
})
};
if let Some((path_dist, path_nearest)) = col_sample.path.filter(|(dist, _)| *dist < 5.0) {
if let Some((path_dist, path_nearest)) = col_sample.path.filter(|(dist, _)| *dist < 5.0)
{
let inset = 0;
// Try to use the column at the centre of the path for sampling to make them
@ -47,7 +48,9 @@ pub fn apply_paths_to<'a>(
let col10 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 0));
let col01 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(0, 1));
let col11 = get_column(col_pos.map(|e| e.floor() as i32) + Vec2::new(1, 1));
let col_attr = |col: &ColumnSample| Vec3::new(col.riverless_alt, col.alt, col.water_dist.unwrap_or(1000.0));
let col_attr = |col: &ColumnSample| {
Vec3::new(col.riverless_alt, col.alt, col.water_dist.unwrap_or(1000.0))
};
let [riverless_alt, alt, water_dist] = match (col00, col10, col01, col11) {
(Some(col00), Some(col10), Some(col01), Some(col11)) => Lerp::lerp(
Lerp::lerp(col_attr(col00), col_attr(col10), path_nearest.x.fract()),
@ -55,7 +58,8 @@ pub fn apply_paths_to<'a>(
path_nearest.y.fract(),
),
_ => col_attr(col_sample),
}.into_array();
}
.into_array();
let (bridge_offset, depth) = (
((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs())
@ -71,7 +75,9 @@ pub fn apply_paths_to<'a>(
if bridge_offset >= 2.0 && path_dist >= 3.0 || z < inset - 1 {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
} else {
let path_color = col_sample.sub_surface_color.map(|e| (e * 255.0 * 0.7) as u8);
let path_color = col_sample
.sub_surface_color
.map(|e| (e * 255.0 * 0.7) as u8);
Block::new(BlockKind::Normal, noisy_color(path_color, 8))
},
);

View File

@ -7,9 +7,9 @@ mod block;
pub mod civ;
mod column;
pub mod config;
pub mod layer;
pub mod sim;
pub mod site;
pub mod layer;
pub mod util;
// Reexports

View File

@ -147,31 +147,39 @@ impl MapConfig {
let pos =
(focus_rect + Vec2::new(i as f64, j as f64) * scale).map(|e: f64| e as i32);
let (alt, basement, water_alt, humidity, temperature, downhill, river_kind, is_path) =
sampler
.get(pos)
.map(|sample| {
(
sample.alt,
sample.basement,
sample.water_alt,
sample.humidity,
sample.temp,
sample.downhill,
sample.river.river_kind,
sample.path.is_path(),
)
})
.unwrap_or((
CONFIG.sea_level,
CONFIG.sea_level,
CONFIG.sea_level,
0.0,
0.0,
None,
None,
false,
));
let (
alt,
basement,
water_alt,
humidity,
temperature,
downhill,
river_kind,
is_path,
) = sampler
.get(pos)
.map(|sample| {
(
sample.alt,
sample.basement,
sample.water_alt,
sample.humidity,
sample.temp,
sample.downhill,
sample.river.river_kind,
sample.path.is_path(),
)
})
.unwrap_or((
CONFIG.sea_level,
CONFIG.sea_level,
CONFIG.sea_level,
0.0,
0.0,
None,
None,
false,
));
let humidity = humidity.min(1.0).max(0.0);
let temperature = temperature.min(1.0).max(-1.0) * 0.5 + 0.5;
let pos = pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);

View File

@ -27,10 +27,7 @@ use crate::{
all::ForestKind,
civ::Place,
site::Site,
util::{
seed_expan, FastNoise, RandomField, StructureGen2d, LOCALITY,
NEIGHBORS,
},
util::{seed_expan, FastNoise, RandomField, StructureGen2d, LOCALITY, NEIGHBORS},
CONFIG,
};
use common::{

View File

@ -8,9 +8,7 @@ pub struct PathData {
}
impl PathData {
pub fn is_path(&self) -> bool {
self.neighbors != 0
}
pub fn is_path(&self) -> bool { self.neighbors != 0 }
}
impl Default for PathData {

View File

@ -3,7 +3,7 @@ use crate::{
column::ColumnSample,
sim::WorldSim,
site::BlockMask,
util::{attempt, DIRS, CARDINALS, Grid, RandomField, Sampler},
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
};
use common::{
assets,
@ -118,16 +118,17 @@ impl Dungeon {
};
if area.contains_point(Vec2::zero()) {
let offs = Vec2::new(
rng.gen_range(-1.0, 1.0),
rng.gen_range(-1.0, 1.0),
).try_normalized().unwrap_or(Vec2::unit_y()) * 16.0;
supplement.add_entity(EntityInfo::at(Vec3::new(
self.origin.x,
self.origin.y,
self.alt + 4,
).map(|e| e as f32) + Vec3::from(offs))
.into_waypoint());
let offs = Vec2::new(rng.gen_range(-1.0, 1.0), rng.gen_range(-1.0, 1.0))
.try_normalized()
.unwrap_or(Vec2::unit_y())
* 16.0;
supplement.add_entity(
EntityInfo::at(
Vec3::new(self.origin.x, self.origin.y, self.alt + 4).map(|e| e as f32)
+ Vec3::from(offs),
)
.into_waypoint(),
);
}
let mut z = self.alt;

View File

@ -312,27 +312,37 @@ impl Archetype for House {
if dist == width && profile.y < roof_level {
// Doors
if center_offset.x > 0 && center_offset.y > 0
&& bound_offset.x > 0 && bound_offset.x < width
if center_offset.x > 0
&& center_offset.y > 0
&& bound_offset.x > 0
&& bound_offset.x < width
&& profile.y < ceil_height
&& branch.attr.storey_fill.has_lower()
{
return Some(if (bound_offset.x == (width - 1) / 2 || bound_offset.x == (width - 1) / 2 + 1) && profile.y <= foundation_height + 3 {
if profile.y == foundation_height + 1 {
BlockMask::new(
Block::new(BlockKind::Door, if bound_offset.x == (width - 1) / 2 {
make_meta(ori.flip())
} else {
make_meta(ori.flip()) + Rgb::new(4, 0, 0)
}),
structural_layer,
)
return Some(
if (bound_offset.x == (width - 1) / 2
|| bound_offset.x == (width - 1) / 2 + 1)
&& profile.y <= foundation_height + 3
{
if profile.y == foundation_height + 1 {
BlockMask::new(
Block::new(
BlockKind::Door,
if bound_offset.x == (width - 1) / 2 {
make_meta(ori.flip())
} else {
make_meta(ori.flip()) + Rgb::new(4, 0, 0)
},
),
structural_layer,
)
} else {
empty.with_priority(structural_layer)
}
} else {
empty.with_priority(structural_layer)
}
} else {
wall
});
wall
},
);
}
if bound_offset.x == bound_offset.y || profile.y == ceil_height {

View File

@ -8,6 +8,7 @@ use crate::{
util::{RandomField, Sampler, StructureGen2d},
};
use common::{
assets,
astar::Astar,
comp::{self, bird_medium, humanoid, quadruped_small},
generation::{ChunkSupplement, EntityInfo},
@ -16,7 +17,6 @@ use common::{
store::{Id, Store},
terrain::{Block, BlockKind, TerrainChunkSize},
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
assets,
};
use hashbrown::{HashMap, HashSet};
use rand::prelude::*;
@ -341,7 +341,8 @@ impl Settlement {
.tile_at(tile_pos)
.map(|t| t.contains(WayKind::Path))
.unwrap_or(true)
|| ctx.sim
|| ctx
.sim
.and_then(|sim| sim.get_nearest_path(self.origin + house_pos))
.map(|(dist, _)| dist < 28.0)
.unwrap_or(false)
@ -548,9 +549,8 @@ impl Settlement {
} else {
let mut surface_block = None;
let roll = |seed, n| {
self.noise.get(Vec3::new(wpos2d.x, wpos2d.y, seed * 5)) % n
};
let roll =
|seed, n| self.noise.get(Vec3::new(wpos2d.x, wpos2d.y, seed * 5)) % n;
let color = match sample.plot {
Some(Plot::Dirt) => Some(Rgb::new(90, 70, 50)),
@ -558,16 +558,21 @@ impl Settlement {
Some(Plot::Water) => Some(Rgb::new(100, 150, 250)),
Some(Plot::Town) => {
if let Some((_, path_nearest)) = col_sample.path {
let path_dir = (path_nearest - wpos2d.map(|e| e as f32)).rotated_z(f32::consts::PI / 2.0).normalized();
let path_dir = (path_nearest - wpos2d.map(|e| e as f32))
.rotated_z(f32::consts::PI / 2.0)
.normalized();
let is_lamp = if path_dir.x.abs() > path_dir.y.abs() {
wpos2d.x as f32 % 20.0 / path_dir.dot(Vec2::unit_y()).abs() <= 1.0
wpos2d.x as f32 % 20.0 / path_dir.dot(Vec2::unit_y()).abs()
<= 1.0
} else {
wpos2d.y as f32 % 20.0 / path_dir.dot(Vec2::unit_x()).abs() <= 1.0
wpos2d.y as f32 % 20.0 / path_dir.dot(Vec2::unit_x()).abs()
<= 1.0
};
if (col_sample.path.map(|(dist, _)| dist > 6.0 && dist < 7.0).unwrap_or(false) && is_lamp) //roll(0, 50) == 0)
|| roll(0, 2000) == 0
{
surface_block = Some(Block::new(BlockKind::StreetLamp, Rgb::white()));
surface_block =
Some(Block::new(BlockKind::StreetLamp, Rgb::white()));
}
}
@ -804,14 +809,18 @@ impl Settlement {
},
_ => comp::Body::Humanoid(humanoid::Body::random()),
})
.do_if(rng.gen(), |entity| entity.with_main_tool(assets::load_expect_cloned(match rng.gen_range(0, 6) {
0 => "common.items.weapons.starter_axe",
1 => "common.items.weapons.starter_sword",
2 => "common.items.weapons.short_sword_0",
3 => "common.items.weapons.hammer_1",
4 => "common.items.weapons.starter_staff",
_ => "common.items.weapons.starter_bow",
})))
.do_if(rng.gen(), |entity| {
entity.with_main_tool(assets::load_expect_cloned(
match rng.gen_range(0, 6) {
0 => "common.items.weapons.starter_axe",
1 => "common.items.weapons.starter_sword",
2 => "common.items.weapons.short_sword_0",
3 => "common.items.weapons.hammer_1",
4 => "common.items.weapons.starter_staff",
_ => "common.items.weapons.starter_bow",
},
))
})
.with_automatic_name();
supplement.add_entity(entity);