diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index 173aa7d1f7..d10478e5f7 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -66,15 +66,19 @@ impl<'a> BlockGen<'a> { // Conservative range of radius: [8, 47] let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8; - max_height.max( - if cliff_pos.map(|e| e as f32).distance_squared(wpos) - < (radius as f32 + tolerance).powf(2.0) - { - cliff_sample.alt + height * (1.0 - cliff_sample.chaos) + cliff_hill - } else { - 0.0 - }, - ) + if cliff_sample.water_dist.map(|d| d > radius as f32).unwrap_or(true) { + max_height.max( + if cliff_pos.map(|e| e as f32).distance_squared(wpos) + < (radius as f32 + tolerance).powf(2.0) + { + cliff_sample.alt + height * (1.0 - cliff_sample.chaos) + cliff_hill + } else { + 0.0 + }, + ) + } else { + max_height + } }, _ => max_height, }, diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs index 0f285fef28..ecd223dfd8 100644 --- a/world/src/block/natural.rs +++ b/world/src/block/natural.rs @@ -28,6 +28,7 @@ pub fn structure_gen<'a>( if (st_sample.tree_density as f64) < random_seed || st_sample.alt < st_sample.water_level || st_sample.spawn_rate < 0.5 + || st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false) { return None; } diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs index edf842d98e..b693f5a41a 100644 --- a/world/src/civ/mod.rs +++ b/world/src/civ/mod.rs @@ -95,9 +95,11 @@ impl Civs { let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32); // Flatten ground - let flatten_radius = 12.0; + let flatten_radius = 10.0; if let Some(center_alt) = ctx.sim.get_alt_approx(wpos) { - for pos in Spiral2d::new().map(|offs| site.center + offs).take(radius.pow(2) as usize) { + for offs in Spiral2d::new().take(radius.pow(2) as usize) { + let center_alt = center_alt + if offs.magnitude_squared() <= 6i32.pow(2) { 16.0 } else { 0.0 }; // Raise the town centre up a little + let pos = site.center + offs; let factor = (1.0 - (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius) * 1.15; ctx.sim .get_mut(pos) diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 97a2c9108c..6de86303b8 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -679,7 +679,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { Some((river_dist - river_width * 0.5) as f32), alt_for_river.min(lake_water_alt - 1.0 - river_gouge), lake_water_alt - river_gouge, - alt_for_river.min(lake_water_alt - 1.0), + alt_for_river.max(lake_water_alt), 0.0, )); } @@ -753,7 +753,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { Some(lake_dist as f32), alt_for_river.min(lake_water_alt - 1.0 - river_gouge), lake_water_alt - river_gouge, - alt_for_river.min(lake_water_alt - 1.0), + alt_for_river.max(lake_water_alt), 0.0, )); } @@ -774,7 +774,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { alt.min(lake_water_alt - 1.0 - river_gouge), downhill_water_alt.max(lake_water_alt) - river_gouge, - alt.min(lake_water_alt - 1.0), + alt.max(lake_water_alt), 0.0, )); } else { diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 7c0ac61f25..dab24656ea 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1867,7 +1867,8 @@ impl SimChunk { ) }; - let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2; + //let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2; + let cliff = 0.0; // Disable cliffs // Logistic regression. Make sure x ∈ (0, 1). let logit = |x: f64| x.ln() - x.neg().ln_1p(); diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs index 25040f44d4..25101a4abd 100644 --- a/world/src/site/settlement/building/archetype/house.rs +++ b/world/src/site/settlement/building/archetype/house.rs @@ -11,6 +11,20 @@ use super::{ super::skeleton::*, }; +const COLOR_THEMES: [Rgb; 11] = [ + Rgb::new(0x1D, 0x4D, 0x45), + Rgb::new(0xB3, 0x7D, 0x60), + Rgb::new(0xAC, 0x5D, 0x26), + Rgb::new(0x32, 0x46, 0x6B), + Rgb::new(0x2B, 0x19, 0x0F), + Rgb::new(0x93, 0x78, 0x51), + Rgb::new(0x92, 0x57, 0x24), + Rgb::new(0x4A, 0x4E, 0x4E), + Rgb::new(0x2F, 0x32, 0x47), + Rgb::new(0x8F, 0x35, 0x43), + Rgb::new(0x6D, 0x1E, 0x3A), +]; + pub struct House { roof_color: Rgb, noise: RandomField, @@ -116,11 +130,10 @@ impl Archetype for House { }; let this = Self { - roof_color: Rgb::new( - rng.gen_range(50, 200), - rng.gen_range(50, 200), - rng.gen_range(50, 200), - ), + roof_color: COLOR_THEMES + .choose(rng) + .unwrap() + .map(|e| e.saturating_add(rng.gen_range(0, 20)) - 10), noise: RandomField::new(rng.gen()), roof_ribbing: rng.gen(), roof_ribbing_diagonal: rng.gen(), @@ -141,7 +154,7 @@ impl Archetype for House { let make_block = |r, g, b| { let nz = self.noise.get(Vec3::new(center_offset.x, center_offset.y, z * 8)); - BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b) + (nz & 0x0F) as u8 - 8), 2) + BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b).map(|e: u8| e.saturating_add((nz & 0x0F) as u8).saturating_sub(8))), 2) }; let facade_layer = 3; diff --git a/world/src/site/settlement/mod.rs b/world/src/site/settlement/mod.rs index c2174e6fc9..002253bd88 100644 --- a/world/src/site/settlement/mod.rs +++ b/world/src/site/settlement/mod.rs @@ -251,7 +251,7 @@ impl Settlement { } pub fn place_town(&mut self, ctx: &mut GenCtx) { - const PLOT_COUNT: usize = 2; + const PLOT_COUNT: usize = 3; let mut origin = Vec2::new(ctx.rng.gen_range(-2, 3), ctx.rng.gen_range(-2, 3)); @@ -273,6 +273,7 @@ impl Settlement { } // Boundary wall + /* let spokes = CARDINALS .iter() .filter_map(|dir| { @@ -316,6 +317,7 @@ impl Settlement { } self.land .write_path(&wall_path, WayKind::Wall, buildable, true); + */ } pub fn place_buildings(&mut self, ctx: &mut GenCtx) { @@ -326,10 +328,11 @@ impl Settlement { }; for tile in Spiral2d::new().map(|offs| town_center + offs).take(16usize.pow(2)) { - for _ in 0..ctx.rng.gen_range(1, 5) { - for _ in 0..10 { + // This is a stupid way to decide how to place buildings + for _ in 0..ctx.rng.gen_range(2, 5) { + for _ in 0..25 { let house_pos = tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2) - + Vec2::::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32) / 2); + + Vec2::::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32 / 2)); let tile_pos = house_pos.map(|e| e.div_euclid(AREA_SIZE as i32)); if !matches!(self.land.plot_at(tile_pos), Some(Plot::Town)) @@ -481,20 +484,23 @@ impl Settlement { // Try to use the column at the centre of the path for sampling to make them flatter let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos)).unwrap_or(col_sample); - let bridge_offset = if let Some(water_dist) = col.water_dist { - ((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0 + let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist { + ( + ((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()) * (col.riverless_alt + 5.0 - col.alt).max(0.0) * 1.75 + 3.0) as i32, + ) } else { - 0.0 + (0.0, 3) }; let surface_z = (col.riverless_alt + bridge_offset).floor() as i32; - for z in inset - 3..inset { + for z in inset - depth..inset { vol.set( Vec3::new(offs.x, offs.y, surface_z + z), - if bridge_offset >= 2.0 { + if bridge_offset >= 2.0 && dist >= 2.5 || z < inset - 1 { Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8)) } else { - Block::new(BlockKind::Normal, noisy_color(Rgb::new(90, 70, 50), 8)) + Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8)) }, ); } @@ -622,7 +628,10 @@ impl Settlement { Some(Plot::Dirt) => return Some(Rgb::new(90, 70, 50)), Some(Plot::Grass) => return Some(Rgb::new(100, 200, 0)), Some(Plot::Water) => return Some(Rgb::new(100, 150, 250)), - Some(Plot::Town) => return Some(Rgb::new(130, 120, 80)), + Some(Plot::Town) => return Some(Rgb::new(150, 110, 60) + .map2(Rgb::iota(), |e: u8, i: i32| e + .saturating_add((self.noise.get(Vec3::new(pos.x, pos.y, i * 5)) % 16) as u8) + .saturating_sub(8))), Some(Plot::Field { seed, .. }) => { let furrow_dirs = [ Vec2::new(1, 0), @@ -760,7 +769,9 @@ impl Land { let proj_point = line.projected_point(pos.map(|e| e as f32)); let dist = proj_point.distance(pos.map(|e| e as f32)); if dist < way.width() { - sample.way = Some((way, dist, proj_point)); + sample.way = sample.way + .filter(|(_, d, _)| *d < dist) + .or(Some((way, dist, proj_point))); } } }