mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Better castle variation, improved paths, multi-storey houses
This commit is contained in:
parent
6a41f6aa88
commit
bdb39b8e7f
@ -11,6 +11,11 @@ pub struct Spiral2d {
|
||||
impl Spiral2d {
|
||||
#[allow(clippy::new_without_default)] // TODO: Pending review in #587
|
||||
pub fn new() -> Self { Self { layer: 0, i: 0 } }
|
||||
|
||||
pub fn radius(self, radius: i32) -> impl Iterator<Item = Vec2<i32>> {
|
||||
self.take((radius * 2 + 1).pow(2) as usize)
|
||||
.filter(move |pos| pos.magnitude_squared() < (radius + 1).pow(2))
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Spiral2d {
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::{
|
||||
all::ForestKind,
|
||||
block::StructureMeta,
|
||||
sim::{local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, RiverKind, SimChunk, WorldSim, Path},
|
||||
sim::{
|
||||
local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, Path, RiverKind, SimChunk, WorldSim,
|
||||
},
|
||||
util::Sampler,
|
||||
Index, CONFIG,
|
||||
};
|
||||
@ -196,6 +198,7 @@ where
|
||||
let tree_density = sim.get_interpolated(wpos, |chunk| chunk.tree_density)?;
|
||||
let spawn_rate = sim.get_interpolated(wpos, |chunk| chunk.spawn_rate)?;
|
||||
let alt = sim.get_interpolated_monotone(wpos, |chunk| chunk.alt)?;
|
||||
let surface_veg = sim.get_interpolated_monotone(wpos, |chunk| chunk.surface_veg)?;
|
||||
let chunk_warp_factor = sim.get_interpolated_monotone(wpos, |chunk| chunk.warp_factor)?;
|
||||
let sim_chunk = sim.get(chunk_pos)?;
|
||||
let neighbor_coef = TerrainChunkSize::RECT_SIZE.map(|e| e as f64);
|
||||
@ -860,8 +863,8 @@ where
|
||||
let cold_stone = Rgb::new(0.57, 0.67, 0.8);
|
||||
let hot_stone = Rgb::new(0.07, 0.07, 0.06);
|
||||
let warm_stone = Rgb::new(0.77, 0.77, 0.64);
|
||||
let beach_sand = Rgb::new(0.9, 0.82, 0.6);
|
||||
let desert_sand = Rgb::new(0.95, 0.75, 0.5);
|
||||
let beach_sand = Rgb::new(0.8, 0.75, 0.5);
|
||||
let desert_sand = Rgb::new(0.7, 0.4, 0.25);
|
||||
let snow = Rgb::new(0.8, 0.85, 1.0);
|
||||
|
||||
let stone_col = Rgb::new(195, 187, 201);
|
||||
@ -1088,11 +1091,15 @@ where
|
||||
water_level,
|
||||
warp_factor,
|
||||
surface_color: Rgb::lerp(
|
||||
Rgb::lerp(cliff, sand, alt.sub(basement).mul(0.25)),
|
||||
// Land
|
||||
ground,
|
||||
// Beach
|
||||
((ocean_level - 1.0) / 2.0).max(0.0),
|
||||
sub_surface_color,
|
||||
Rgb::lerp(
|
||||
Rgb::lerp(cliff, sand, alt.sub(basement).mul(0.25)),
|
||||
// Land
|
||||
ground,
|
||||
// Beach
|
||||
((ocean_level - 1.0) / 2.0).max(0.0),
|
||||
),
|
||||
surface_veg,
|
||||
),
|
||||
sub_surface_color,
|
||||
// No growing directly on bedrock.
|
||||
|
@ -37,7 +37,9 @@ pub fn apply_paths_to<'a>(
|
||||
})
|
||||
};
|
||||
|
||||
if let Some((path_dist, path_nearest, path, _)) = col_sample.path.filter(|(dist, _, path, _)| *dist < path.width)
|
||||
if let Some((path_dist, path_nearest, path, _)) = col_sample
|
||||
.path
|
||||
.filter(|(dist, _, path, _)| *dist < path.width)
|
||||
{
|
||||
let inset = 0;
|
||||
|
||||
@ -75,9 +77,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 = path.surface_color(
|
||||
col_sample.sub_surface_color.map(|e| (e * 255.0) as u8),
|
||||
);
|
||||
Block::new(BlockKind::Normal, noisy_color(path_color, 8))
|
||||
},
|
||||
);
|
||||
|
@ -1699,8 +1699,8 @@ impl WorldSim {
|
||||
Some(z0 + z1 + z2 + z3)
|
||||
}
|
||||
|
||||
/// Return the distance to the nearest path in blocks, along with the closest point on the path
|
||||
/// and the tangent vector of that path.
|
||||
/// Return the distance to the nearest path in blocks, along with the closest point on the
|
||||
/// path, the path metadata, and the tangent vector of that path.
|
||||
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
|
||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||
e.div_euclid(sz as i32)
|
||||
@ -1761,7 +1761,9 @@ impl WorldSim {
|
||||
.clamped(0.0, 1.0);
|
||||
let pos = bez.evaluate(nearest_interval);
|
||||
let dist_sqrd = pos.distance_squared(wpos.map(|e| e as f32));
|
||||
Some((dist_sqrd, pos, chunk.path.path, move || bez.evaluate_derivative(nearest_interval).normalized()))
|
||||
Some((dist_sqrd, pos, chunk.path.path, move || {
|
||||
bez.evaluate_derivative(nearest_interval).normalized()
|
||||
}))
|
||||
}),
|
||||
)
|
||||
})
|
||||
@ -1789,6 +1791,7 @@ pub struct SimChunk {
|
||||
pub spawn_rate: f32,
|
||||
pub river: RiverData,
|
||||
pub warp_factor: f32,
|
||||
pub surface_veg: f32,
|
||||
|
||||
pub sites: Vec<Id<Site>>,
|
||||
pub place: Option<Id<Place>>,
|
||||
@ -2024,6 +2027,7 @@ impl SimChunk {
|
||||
spawn_rate: 1.0,
|
||||
river,
|
||||
warp_factor: 1.0,
|
||||
surface_veg: 1.0,
|
||||
|
||||
sites: Vec::new(),
|
||||
place: None,
|
||||
|
@ -2,7 +2,7 @@ use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Path {
|
||||
pub width: f32,
|
||||
pub width: f32, // Actually radius
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -15,23 +15,27 @@ pub struct PathData {
|
||||
|
||||
impl PathData {
|
||||
pub fn is_path(&self) -> bool { self.neighbors != 0 }
|
||||
|
||||
pub fn clear(&mut self) { self.neighbors = 0; }
|
||||
}
|
||||
|
||||
impl Default for PathData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Vec2::zero(),
|
||||
path: Path {
|
||||
width: 5.0,
|
||||
},
|
||||
path: Path { width: 5.0 },
|
||||
neighbors: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
/// Return the number of blocks of headspace required at the given path distance
|
||||
/// Return the number of blocks of headspace required at the given path
|
||||
/// distance
|
||||
pub fn head_space(&self, dist: f32) -> i32 {
|
||||
(8 - (dist * 0.25).powf(6.0).round() as i32).max(1)
|
||||
}
|
||||
|
||||
/// Get the surface colour of a path given the surrounding surface color
|
||||
pub fn surface_color(&self, col: Rgb<u8>) -> Rgb<u8> { col.map(|e| (e as f32 * 0.7) as u8) }
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
sim::WorldSim,
|
||||
site::{
|
||||
settlement::building::{
|
||||
archetype::keep::{Attr, Keep},
|
||||
archetype::keep::{Attr, Keep as KeepArchetype},
|
||||
Archetype, Branch, Ori,
|
||||
},
|
||||
BlockMask,
|
||||
@ -18,6 +18,7 @@ use common::{
|
||||
comp,
|
||||
generation::{ChunkSupplement, EntityInfo},
|
||||
npc,
|
||||
spiral::Spiral2d,
|
||||
store::{Id, Store},
|
||||
terrain::{Block, BlockKind, Structure, TerrainChunkSize},
|
||||
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
|
||||
@ -29,11 +30,12 @@ use rand::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
struct Segment {
|
||||
struct Keep {
|
||||
offset: Vec2<i32>,
|
||||
locus: i32,
|
||||
height: i32,
|
||||
is_tower: bool,
|
||||
alt: i32,
|
||||
}
|
||||
|
||||
struct Tower {
|
||||
@ -47,29 +49,44 @@ pub struct Castle {
|
||||
seed: u32,
|
||||
radius: i32,
|
||||
towers: Vec<Tower>,
|
||||
segments: Vec<Segment>,
|
||||
keeps: Vec<Keep>,
|
||||
rounded_towers: bool,
|
||||
}
|
||||
|
||||
pub struct GenCtx<'a, R: Rng> {
|
||||
sim: Option<&'a WorldSim>,
|
||||
sim: Option<&'a mut WorldSim>,
|
||||
rng: &'a mut R,
|
||||
}
|
||||
|
||||
impl Castle {
|
||||
#[allow(clippy::let_and_return)] // TODO: Pending review in #587
|
||||
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
|
||||
pub fn generate(wpos: Vec2<i32>, sim: Option<&mut WorldSim>, rng: &mut impl Rng) -> Self {
|
||||
let mut ctx = GenCtx { sim, rng };
|
||||
|
||||
let boundary_towers = ctx.rng.gen_range(5, 10);
|
||||
let keep_count = ctx.rng.gen_range(1, 4);
|
||||
let boundary_noise = ctx.rng.gen_range(-2i32, 8).max(1) as f32;
|
||||
|
||||
let radius = 150;
|
||||
|
||||
// Adjust ground
|
||||
if let Some(sim) = ctx.sim.as_mut() {
|
||||
for rpos in Spiral2d::new()
|
||||
.radius((radius as f32 * 0.7) as i32 / TerrainChunkSize::RECT_SIZE.x as i32)
|
||||
{
|
||||
sim.get_mut(wpos / TerrainChunkSize::RECT_SIZE.map(|e| e as i32) + rpos)
|
||||
.map(|chunk| {
|
||||
chunk.surface_veg = 0.0;
|
||||
chunk.path.clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let this = Self {
|
||||
origin: wpos,
|
||||
alt: ctx
|
||||
.sim
|
||||
.as_ref()
|
||||
.and_then(|sim| sim.get_alt_approx(wpos))
|
||||
.unwrap_or(0.0) as i32
|
||||
+ 6,
|
||||
@ -87,6 +104,7 @@ impl Castle {
|
||||
for i in (1..80).step_by(5) {
|
||||
if ctx
|
||||
.sim
|
||||
.as_ref()
|
||||
.and_then(|sim| sim.get_nearest_path(wpos + offset))
|
||||
.map(|(dist, _, _, _)| dist > 24.0)
|
||||
.unwrap_or(true)
|
||||
@ -101,6 +119,7 @@ impl Castle {
|
||||
offset,
|
||||
alt: ctx
|
||||
.sim
|
||||
.as_ref()
|
||||
.and_then(|sim| sim.get_alt_approx(wpos + offset))
|
||||
.unwrap_or(0.0) as i32
|
||||
+ 2,
|
||||
@ -108,19 +127,28 @@ impl Castle {
|
||||
})
|
||||
.collect(),
|
||||
rounded_towers: ctx.rng.gen(),
|
||||
keeps: (0..keep_count)
|
||||
.map(|i| {
|
||||
let angle = (i as f32 / keep_count as f32) * f32::consts::PI * 2.0;
|
||||
let dir = Vec2::new(angle.cos(), angle.sin());
|
||||
let dist =
|
||||
(radius as f32 + ((angle * boundary_noise).sin() - 1.0) * 40.0) * 0.3;
|
||||
|
||||
segments: (0..0) //rng.gen_range(18, 24))
|
||||
.map(|_| {
|
||||
let dir = Vec2::new(ctx.rng.gen_range(-1.0, 1.0), ctx.rng.gen_range(-1.0, 1.0))
|
||||
.normalized();
|
||||
let dist = 16.0 + ctx.rng.gen_range(0.0f32, 1.0).powf(0.5) * 64.0;
|
||||
let height = 48.0 - (dist / 64.0).powf(2.0) * 32.0;
|
||||
let locus = ctx.rng.gen_range(20, 26);
|
||||
let offset = (dir * dist).map(|e| e as i32);
|
||||
let height = ctx.rng.gen_range(25, 70).clamped(30, 48);
|
||||
|
||||
Segment {
|
||||
offset: (dir * dist).map(|e| e as i32),
|
||||
locus: ctx.rng.gen_range(6, 26),
|
||||
height: height as i32,
|
||||
is_tower: height > 36.0,
|
||||
Keep {
|
||||
offset,
|
||||
locus,
|
||||
height,
|
||||
is_tower: true,
|
||||
alt: ctx
|
||||
.sim
|
||||
.as_ref()
|
||||
.and_then(|sim| sim.get_alt_approx(wpos + offset))
|
||||
.unwrap_or(0.0) as i32
|
||||
+ 2,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
@ -209,7 +237,8 @@ impl Castle {
|
||||
} else {
|
||||
rpos.yx()
|
||||
};
|
||||
let head_space = col_sample.path
|
||||
let head_space = col_sample
|
||||
.path
|
||||
.map(|(dist, _, path, _)| path.head_space(dist))
|
||||
.unwrap_or(0);
|
||||
|
||||
@ -220,34 +249,37 @@ impl Castle {
|
||||
col_sample
|
||||
};
|
||||
|
||||
let keep_archetype = KeepArchetype {
|
||||
flag_color: Rgb::new(200, 80, 40),
|
||||
};
|
||||
|
||||
for z in -10..64 {
|
||||
let wpos = Vec3::new(wpos2d.x, wpos2d.y, col_sample.alt as i32 + z);
|
||||
|
||||
let keep = Keep {
|
||||
flag_color: Rgb::new(200, 80, 40),
|
||||
};
|
||||
|
||||
// Boundary
|
||||
// Boundary wall
|
||||
let wall_z = wpos.z - wall_alt;
|
||||
let mut mask = if z < head_space {
|
||||
BlockMask::nothing()
|
||||
} else {
|
||||
keep.draw(
|
||||
Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt,
|
||||
wall_dist,
|
||||
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
|
||||
rpos - wall_pos,
|
||||
wall_z,
|
||||
wall_ori,
|
||||
4,
|
||||
0,
|
||||
&Attr {
|
||||
height: 16,
|
||||
is_tower: false,
|
||||
rounded: true,
|
||||
},
|
||||
)
|
||||
};
|
||||
if z < head_space {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut mask = keep_archetype.draw(
|
||||
Vec3::from(wall_rpos) + Vec3::unit_z() * wpos.z - wall_alt,
|
||||
wall_dist,
|
||||
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
|
||||
rpos - wall_pos,
|
||||
wall_z,
|
||||
wall_ori,
|
||||
4,
|
||||
0,
|
||||
&Attr {
|
||||
height: 16,
|
||||
is_tower: false,
|
||||
ridged: false,
|
||||
rounded: true,
|
||||
},
|
||||
);
|
||||
|
||||
// Boundary towers
|
||||
for tower in &self.towers {
|
||||
let tower_wpos = Vec3::new(
|
||||
self.origin.x + tower.offset.x,
|
||||
@ -257,7 +289,7 @@ impl Castle {
|
||||
let tower_locus = 10;
|
||||
|
||||
let border_pos = (tower_wpos - wpos).xy().map(|e| e.abs());
|
||||
mask = mask.resolve_with(keep.draw(
|
||||
mask = mask.resolve_with(keep_archetype.draw(
|
||||
if (tower_wpos.x - wpos.x).abs() < (tower_wpos.y - wpos.y).abs() {
|
||||
wpos - tower_wpos
|
||||
} else {
|
||||
@ -277,6 +309,42 @@ impl Castle {
|
||||
&Attr {
|
||||
height: 28,
|
||||
is_tower: true,
|
||||
ridged: false,
|
||||
rounded: self.rounded_towers,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
// Keeps
|
||||
for keep in &self.keeps {
|
||||
let keep_wpos = Vec3::new(
|
||||
self.origin.x + keep.offset.x,
|
||||
self.origin.y + keep.offset.y,
|
||||
keep.alt,
|
||||
);
|
||||
|
||||
let border_pos = (keep_wpos - wpos).xy().map(|e| e.abs());
|
||||
mask = mask.resolve_with(keep_archetype.draw(
|
||||
if (keep_wpos.x - wpos.x).abs() < (keep_wpos.y - wpos.y).abs() {
|
||||
wpos - keep_wpos
|
||||
} else {
|
||||
Vec3::new(
|
||||
wpos.y - keep_wpos.y,
|
||||
wpos.x - keep_wpos.x,
|
||||
wpos.z - keep_wpos.z,
|
||||
)
|
||||
},
|
||||
border_pos.reduce_max() - keep.locus,
|
||||
Vec2::new(border_pos.reduce_max(), border_pos.reduce_min()),
|
||||
(wpos - keep_wpos).xy(),
|
||||
wpos.z - keep.alt,
|
||||
Ori::East,
|
||||
keep.locus,
|
||||
0,
|
||||
&Attr {
|
||||
height: keep.height,
|
||||
is_tower: keep.is_tower,
|
||||
ridged: true,
|
||||
rounded: self.rounded_towers,
|
||||
},
|
||||
));
|
||||
|
@ -105,7 +105,7 @@ impl Attr {
|
||||
},
|
||||
mansard: rng.gen_range(-7, 4).max(0),
|
||||
pillar: match rng.gen_range(0, 4) {
|
||||
0 => Pillar::Chimney(rng.gen_range(1, 5)),
|
||||
0 => Pillar::Chimney(rng.gen_range(2, 6)),
|
||||
_ => Pillar::None,
|
||||
},
|
||||
levels: rng.gen_range(1, 3),
|
||||
@ -135,7 +135,7 @@ impl Archetype for House {
|
||||
storey_fill: StoreyFill::All,
|
||||
mansard: 0,
|
||||
pillar: match rng.gen_range(0, 3) {
|
||||
0 => Pillar::Chimney(rng.gen_range(1, 5)),
|
||||
0 => Pillar::Chimney(rng.gen_range(2, 6)),
|
||||
1 => Pillar::Tower(5 + rng.gen_range(1, 5)),
|
||||
_ => Pillar::None,
|
||||
},
|
||||
@ -409,7 +409,7 @@ impl Archetype for House {
|
||||
// Window
|
||||
if (frame_bounds.size() + 1).reduce_min() > 2 {
|
||||
// Window frame is large enough for a window
|
||||
let surface_pos = Vec2::new(bound_offset.x, profile.y - floor_height);
|
||||
let surface_pos = Vec2::new(bound_offset.x, profile.y);
|
||||
if window_bounds.contains_point(surface_pos) {
|
||||
return Some(end_window);
|
||||
} else if frame_bounds.contains_point(surface_pos) {
|
||||
|
@ -14,6 +14,7 @@ pub struct Keep {
|
||||
pub struct Attr {
|
||||
pub height: i32,
|
||||
pub is_tower: bool,
|
||||
pub ridged: bool,
|
||||
pub rounded: bool,
|
||||
}
|
||||
|
||||
@ -30,6 +31,7 @@ impl Archetype for Keep {
|
||||
attr: Attr {
|
||||
height: rng.gen_range(12, 16),
|
||||
is_tower: false,
|
||||
ridged: false,
|
||||
rounded: true,
|
||||
},
|
||||
locus: 10 + rng.gen_range(0, 5),
|
||||
@ -43,6 +45,7 @@ impl Archetype for Keep {
|
||||
attr: Attr {
|
||||
height: rng.gen_range(20, 28),
|
||||
is_tower: true,
|
||||
ridged: false,
|
||||
rounded: true,
|
||||
},
|
||||
locus: 4 + rng.gen_range(0, 5),
|
||||
@ -104,15 +107,21 @@ impl Archetype for Keep {
|
||||
let internal = BlockMask::new(Block::empty(), internal_layer);
|
||||
let empty = BlockMask::nothing();
|
||||
|
||||
let width = locus;
|
||||
let rampart_width = 2 + locus;
|
||||
let ceil_height = attr.height;
|
||||
let door_height = 6;
|
||||
let edge_pos = if (bound_offset.x == rampart_width) ^ (ori == Ori::East) {
|
||||
let edge_pos = if (bound_offset.x.abs() > bound_offset.y.abs()) ^ (ori == Ori::East) {
|
||||
pos.y
|
||||
} else {
|
||||
pos.x
|
||||
};
|
||||
|
||||
let width = locus
|
||||
+ if edge_pos % 4 == 0 && attr.ridged && !attr.rounded {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let rampart_width = 2 + width;
|
||||
let ceil_height = attr.height;
|
||||
let door_height = 6;
|
||||
let rampart_height = ceil_height + if edge_pos % 2 == 0 { 3 } else { 4 };
|
||||
let min_dist = if attr.rounded {
|
||||
bound_offset.map(|e| e.pow(2) as f32).sum().powf(0.5) as i32
|
||||
|
@ -593,14 +593,15 @@ impl Settlement {
|
||||
// if let Some((WayKind::Path, dist, nearest)) = sample.way {
|
||||
// let inset = -1;
|
||||
|
||||
// // Try to use the column at the centre of the path for sampling to make them
|
||||
// // flatter
|
||||
// // 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, 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())
|
||||
// ((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,
|
||||
@ -614,10 +615,10 @@ impl Settlement {
|
||||
// let _ = vol.set(
|
||||
// Vec3::new(offs.x, offs.y, surface_z + z),
|
||||
// if bridge_offset >= 2.0 && dist >= 3.0 || z < inset - 1 {
|
||||
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
|
||||
// } else {
|
||||
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8))
|
||||
// },
|
||||
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80,
|
||||
// 100), 8)) } else {
|
||||
// Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50,
|
||||
// 30), 8)) },
|
||||
// );
|
||||
// }
|
||||
// let head_space = (8 - (dist * 0.25).powf(6.0).round() as i32).max(1);
|
||||
@ -639,6 +640,7 @@ impl Settlement {
|
||||
Some(Plot::Dirt) => Some(Rgb::new(90, 70, 50)),
|
||||
Some(Plot::Grass) => Some(Rgb::new(100, 200, 0)),
|
||||
Some(Plot::Water) => Some(Rgb::new(100, 150, 250)),
|
||||
Some(Plot::Town { district }) => None,
|
||||
Some(Plot::Town { district }) => {
|
||||
if let Some((_, path_nearest, _, _)) = col_sample.path {
|
||||
let path_dir = (path_nearest - wpos2d.map(|e| e as f32))
|
||||
@ -669,65 +671,87 @@ impl Settlement {
|
||||
}))
|
||||
},
|
||||
Some(Plot::Field { seed, crop, .. }) => {
|
||||
let furrow_dirs = [
|
||||
Vec2::new(1, 0),
|
||||
Vec2::new(0, 1),
|
||||
Vec2::new(1, 1),
|
||||
Vec2::new(-1, 1),
|
||||
];
|
||||
let furrow_dir = furrow_dirs[*seed as usize % furrow_dirs.len()];
|
||||
let in_furrow = (wpos2d * furrow_dir).sum().rem_euclid(5) < 2;
|
||||
if let Some(color) = col_sample.path.and_then(|(dist, _, path, _)| {
|
||||
if dist < path.width {
|
||||
Some(path.surface_color(
|
||||
col_sample.sub_surface_color.map(|e| (e * 255.0) as u8),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) {
|
||||
Some(color)
|
||||
} else {
|
||||
let furrow_dirs = [
|
||||
Vec2::new(1, 0),
|
||||
Vec2::new(0, 1),
|
||||
Vec2::new(1, 1),
|
||||
Vec2::new(-1, 1),
|
||||
];
|
||||
let furrow_dir = furrow_dirs[*seed as usize % furrow_dirs.len()];
|
||||
let in_furrow = (wpos2d * furrow_dir).sum().rem_euclid(5) < 2;
|
||||
|
||||
let dirt = Rgb::new(80, 55, 35).map(|e| {
|
||||
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 0) as i32)) % 32)
|
||||
as u8
|
||||
});
|
||||
let mound =
|
||||
Rgb::new(70, 80, 30).map(|e| e + roll(0, 8) as u8).map(|e| {
|
||||
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 1) as i32))
|
||||
let dirt = Rgb::new(80, 55, 35).map(|e| {
|
||||
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 0) as i32))
|
||||
% 32) as u8
|
||||
});
|
||||
let mound =
|
||||
Rgb::new(70, 80, 30).map(|e| e + roll(0, 8) as u8).map(|e| {
|
||||
e + (self
|
||||
.noise
|
||||
.get(Vec3::broadcast((seed % 4096 + 1) as i32))
|
||||
% 32) as u8
|
||||
});
|
||||
|
||||
if in_furrow {
|
||||
if roll(0, 5) == 0 {
|
||||
surface_block = match crop {
|
||||
Crop::Corn => Some(BlockKind::Corn),
|
||||
Crop::Wheat if roll(1, 2) == 0 => {
|
||||
Some(BlockKind::WheatYellow)
|
||||
},
|
||||
Crop::Wheat => Some(BlockKind::WheatGreen),
|
||||
Crop::Cabbage if roll(2, 2) == 0 => {
|
||||
Some(BlockKind::Cabbage)
|
||||
},
|
||||
Crop::Pumpkin if roll(3, 2) == 0 => {
|
||||
Some(BlockKind::Pumpkin)
|
||||
},
|
||||
Crop::Flax if roll(4, 2) == 0 => Some(BlockKind::Flax),
|
||||
Crop::Carrot if roll(5, 2) == 0 => Some(BlockKind::Carrot),
|
||||
Crop::Tomato if roll(6, 2) == 0 => Some(BlockKind::Tomato),
|
||||
Crop::Radish if roll(7, 2) == 0 => Some(BlockKind::Radish),
|
||||
Crop::Turnip if roll(8, 2) == 0 => Some(BlockKind::Turnip),
|
||||
Crop::Sunflower => Some(BlockKind::Sunflower),
|
||||
_ => None,
|
||||
}
|
||||
.or_else(|| {
|
||||
if roll(9, 400) == 0 {
|
||||
Some(BlockKind::Scarecrow)
|
||||
} else {
|
||||
None
|
||||
if in_furrow {
|
||||
if roll(0, 5) == 0 {
|
||||
surface_block = match crop {
|
||||
Crop::Corn => Some(BlockKind::Corn),
|
||||
Crop::Wheat if roll(1, 2) == 0 => {
|
||||
Some(BlockKind::WheatYellow)
|
||||
},
|
||||
Crop::Wheat => Some(BlockKind::WheatGreen),
|
||||
Crop::Cabbage if roll(2, 2) == 0 => {
|
||||
Some(BlockKind::Cabbage)
|
||||
},
|
||||
Crop::Pumpkin if roll(3, 2) == 0 => {
|
||||
Some(BlockKind::Pumpkin)
|
||||
},
|
||||
Crop::Flax if roll(4, 2) == 0 => Some(BlockKind::Flax),
|
||||
Crop::Carrot if roll(5, 2) == 0 => {
|
||||
Some(BlockKind::Carrot)
|
||||
},
|
||||
Crop::Tomato if roll(6, 2) == 0 => {
|
||||
Some(BlockKind::Tomato)
|
||||
},
|
||||
Crop::Radish if roll(7, 2) == 0 => {
|
||||
Some(BlockKind::Radish)
|
||||
},
|
||||
Crop::Turnip if roll(8, 2) == 0 => {
|
||||
Some(BlockKind::Turnip)
|
||||
},
|
||||
Crop::Sunflower => Some(BlockKind::Sunflower),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.map(|kind| Block::new(kind, Rgb::white()));
|
||||
.or_else(|| {
|
||||
if roll(9, 400) == 0 {
|
||||
Some(BlockKind::Scarecrow)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|kind| Block::new(kind, Rgb::white()));
|
||||
}
|
||||
} else if roll(0, 20) == 0 {
|
||||
surface_block =
|
||||
Some(Block::new(BlockKind::ShortGrass, Rgb::white()));
|
||||
} else if roll(1, 30) == 0 {
|
||||
surface_block =
|
||||
Some(Block::new(BlockKind::MediumGrass, Rgb::white()));
|
||||
}
|
||||
} else if roll(0, 20) == 0 {
|
||||
surface_block =
|
||||
Some(Block::new(BlockKind::ShortGrass, Rgb::white()));
|
||||
} else if roll(1, 30) == 0 {
|
||||
surface_block =
|
||||
Some(Block::new(BlockKind::MediumGrass, Rgb::white()));
|
||||
}
|
||||
|
||||
Some(if in_furrow { dirt } else { mound })
|
||||
Some(if in_furrow { dirt } else { mound })
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user