mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added simple keeps
This commit is contained in:
parent
eea64f78ff
commit
ae8195fac9
@ -165,6 +165,7 @@ impl Archetype for House {
|
||||
#[allow(clippy::int_plus_one)] // TODO: Pending review in #587
|
||||
fn draw(
|
||||
&self,
|
||||
pos: Vec3<i32>,
|
||||
dist: i32,
|
||||
bound_offset: Vec2<i32>,
|
||||
center_offset: Vec2<i32>,
|
||||
|
@ -13,16 +13,16 @@ impl Archetype for Keep {
|
||||
type Attr = ();
|
||||
|
||||
fn generate<R: Rng>(rng: &mut R) -> (Self, Skeleton<Self::Attr>) {
|
||||
let len = rng.gen_range(-8, 12).max(0);
|
||||
let len = rng.gen_range(-8, 20).max(0);
|
||||
let skel = Skeleton {
|
||||
offset: -rng.gen_range(0, len + 7).clamped(0, len),
|
||||
ori: if rng.gen() { Ori::East } else { Ori::North },
|
||||
root: Branch {
|
||||
len,
|
||||
attr: Self::Attr::default(),
|
||||
locus: 5 + rng.gen_range(0, 5),
|
||||
locus: 6 + rng.gen_range(0, 5),
|
||||
border: 3,
|
||||
children: (0..rng.gen_range(0, 4))
|
||||
children: (0..1)
|
||||
.map(|_| {
|
||||
(
|
||||
rng.gen_range(-5, len + 5).clamped(0, len.max(1) - 1),
|
||||
@ -45,36 +45,71 @@ impl Archetype for Keep {
|
||||
#[allow(clippy::if_same_then_else)] // TODO: Pending review in #587
|
||||
fn draw(
|
||||
&self,
|
||||
pos: Vec3<i32>,
|
||||
dist: i32,
|
||||
bound_offset: Vec2<i32>,
|
||||
_center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
_ori: Ori,
|
||||
ori: Ori,
|
||||
branch: &Branch<Self::Attr>,
|
||||
) -> BlockMask {
|
||||
let profile = Vec2::new(bound_offset.x, z);
|
||||
|
||||
let weak_layer = 1;
|
||||
let normal_layer = weak_layer + 1;
|
||||
let important_layer = normal_layer + 1;
|
||||
let internal_layer = important_layer + 1;
|
||||
|
||||
let make_block =
|
||||
|r, g, b| BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b)), 2);
|
||||
|r, g, b| BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b)), normal_layer);
|
||||
|
||||
let foundation = make_block(100, 100, 100);
|
||||
let wall = make_block(75, 100, 125);
|
||||
let roof = make_block(150, 120, 50);
|
||||
let empty = BlockMask::new(Block::empty(), 2);
|
||||
let wall = make_block(100, 100, 110);
|
||||
let floor = make_block(120, 80, 50).with_priority(important_layer);
|
||||
let internal = BlockMask::new(Block::empty(), internal_layer);
|
||||
let empty = BlockMask::nothing();
|
||||
|
||||
let width = branch.locus;
|
||||
let rampart_width = 5 + branch.locus;
|
||||
let ceil_height = 16;
|
||||
let rampart_width = 2 + branch.locus;
|
||||
let ceil_height = 12;
|
||||
let door_height = 6;
|
||||
let edge_pos = if (bound_offset.x == rampart_width) ^ (ori == Ori::East) {
|
||||
pos.y
|
||||
} else {
|
||||
pos.x
|
||||
};
|
||||
let rampart_height = ceil_height + if edge_pos % 2 == 0 { 3 } else { 4 };
|
||||
let min_dist = bound_offset.reduce_max();
|
||||
|
||||
if profile.y <= 1 - (dist - width - 1).max(0) && dist < width + 3 {
|
||||
if profile.y <= 0 - (min_dist - width - 1).max(0) && min_dist < width + 3 {
|
||||
// Foundations
|
||||
foundation
|
||||
} else if profile.y == ceil_height && dist < rampart_width {
|
||||
roof
|
||||
} else if dist == rampart_width && profile.y >= ceil_height && profile.y < ceil_height + 4 {
|
||||
} else if profile.y == ceil_height && min_dist < rampart_width {
|
||||
if min_dist < width {
|
||||
floor
|
||||
} else {
|
||||
wall
|
||||
}
|
||||
} else if bound_offset.x.abs() == 4 && min_dist == width + 1 && profile.y < ceil_height {
|
||||
wall
|
||||
} else if dist == width && profile.y <= ceil_height {
|
||||
} else if bound_offset.x.abs() < 3 && profile.y < door_height - bound_offset.x.abs() && profile.y > 0 {
|
||||
internal
|
||||
} else if min_dist == width && profile.y <= ceil_height {
|
||||
wall
|
||||
} else if profile.y >= ceil_height {
|
||||
if profile.y > ceil_height && min_dist < rampart_width {
|
||||
internal
|
||||
} else if min_dist == rampart_width {
|
||||
if profile.y < rampart_height {
|
||||
wall
|
||||
} else {
|
||||
internal
|
||||
}
|
||||
} else {
|
||||
empty
|
||||
}
|
||||
} else if profile.y < ceil_height && min_dist < width {
|
||||
internal
|
||||
} else {
|
||||
empty
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ pub trait Archetype {
|
||||
Self: Sized;
|
||||
fn draw(
|
||||
&self,
|
||||
pos: Vec3<i32>,
|
||||
dist: i32,
|
||||
bound_offset: Vec2<i32>,
|
||||
center_offset: Vec2<i32>,
|
||||
|
@ -10,6 +10,8 @@ use rand::prelude::*;
|
||||
use vek::*;
|
||||
|
||||
pub type HouseBuilding = Building<archetype::house::House>;
|
||||
pub type KeepBuilding = Building<archetype::keep::Keep>;
|
||||
|
||||
|
||||
pub struct Building<A: Archetype> {
|
||||
skel: Skeleton<A::Attr>,
|
||||
@ -50,10 +52,10 @@ impl<A: Archetype> Building<A> {
|
||||
let rpos = pos - self.origin;
|
||||
self.skel
|
||||
.sample_closest(
|
||||
rpos.into(),
|
||||
|dist, bound_offset, center_offset, ori, branch| {
|
||||
rpos,
|
||||
|pos, dist, bound_offset, center_offset, ori, branch| {
|
||||
self.archetype
|
||||
.draw(dist, bound_offset, center_offset, rpos.z, ori, branch)
|
||||
.draw(pos, dist, bound_offset, center_offset, rpos.z, ori, branch)
|
||||
},
|
||||
)
|
||||
.finish()
|
||||
|
@ -76,8 +76,8 @@ impl<T> Skeleton<T> {
|
||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||
pub fn sample_closest(
|
||||
&self,
|
||||
pos: Vec2<i32>,
|
||||
mut f: impl FnMut(i32, Vec2<i32>, Vec2<i32>, Ori, &Branch<T>) -> BlockMask,
|
||||
pos: Vec3<i32>,
|
||||
mut f: impl FnMut(Vec3<i32>, i32, Vec2<i32>, Vec2<i32>, Ori, &Branch<T>) -> BlockMask,
|
||||
) -> BlockMask {
|
||||
let mut min = None::<(_, BlockMask)>;
|
||||
self.for_each(|node, ori, branch, is_child, parent_locus| {
|
||||
@ -117,7 +117,7 @@ impl<T> Skeleton<T> {
|
||||
}
|
||||
|| true
|
||||
{
|
||||
let new_bm = f(dist, bound_offset, center_offset, ori, branch);
|
||||
let new_bm = f(pos, dist, bound_offset, center_offset, ori, branch);
|
||||
min = min
|
||||
.map(|(_, bm)| (dist_locus, bm.resolve_with(new_bm)))
|
||||
.or(Some((dist_locus, new_bm)));
|
||||
|
@ -1,6 +1,6 @@
|
||||
mod building;
|
||||
|
||||
use self::building::HouseBuilding;
|
||||
use self::building::{HouseBuilding, KeepBuilding};
|
||||
use super::SpawnRules;
|
||||
use crate::{
|
||||
column::ColumnSample,
|
||||
@ -83,6 +83,8 @@ fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as
|
||||
|
||||
pub enum StructureKind {
|
||||
House(HouseBuilding),
|
||||
Keep(KeepBuilding),
|
||||
|
||||
}
|
||||
|
||||
pub struct Structure {
|
||||
@ -93,6 +95,24 @@ impl Structure {
|
||||
pub fn bounds_2d(&self) -> Aabr<i32> {
|
||||
match &self.kind {
|
||||
StructureKind::House(house) => house.bounds_2d(),
|
||||
StructureKind::Keep(keep) => keep.bounds_2d(),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bounds(&self) -> Aabb<i32> {
|
||||
match &self.kind {
|
||||
StructureKind::House(house) => house.bounds(),
|
||||
StructureKind::Keep(keep) => keep.bounds(),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sample(&self, rpos: Vec3<i32>) -> Option<Block> {
|
||||
match &self.kind {
|
||||
StructureKind::House(house) => house.sample(rpos),
|
||||
StructureKind::Keep(keep) => keep.sample(rpos),
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,9 +346,10 @@ impl Settlement {
|
||||
return;
|
||||
};
|
||||
|
||||
for tile in Spiral2d::new()
|
||||
for (i, tile) in Spiral2d::new()
|
||||
.map(|offs| town_center + offs)
|
||||
.take(16usize.pow(2))
|
||||
.enumerate()
|
||||
{
|
||||
// This is a stupid way to decide how to place buildings
|
||||
for _ in 0..ctx.rng.gen_range(2, 5) {
|
||||
@ -356,17 +377,31 @@ impl Settlement {
|
||||
}
|
||||
|
||||
let structure = Structure {
|
||||
kind: StructureKind::House(HouseBuilding::generate(
|
||||
ctx.rng,
|
||||
Vec3::new(
|
||||
house_pos.x,
|
||||
house_pos.y,
|
||||
ctx.sim
|
||||
.and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
.unwrap_or(0.0)
|
||||
.ceil() as i32,
|
||||
),
|
||||
)),
|
||||
kind: if i == 0 {
|
||||
StructureKind::Keep(KeepBuilding::generate(
|
||||
ctx.rng,
|
||||
Vec3::new(
|
||||
house_pos.x,
|
||||
house_pos.y,
|
||||
ctx.sim
|
||||
.and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
.unwrap_or(0.0)
|
||||
.ceil() as i32,
|
||||
),
|
||||
))
|
||||
} else {
|
||||
StructureKind::House(HouseBuilding::generate(
|
||||
ctx.rng,
|
||||
Vec3::new(
|
||||
house_pos.x,
|
||||
house_pos.y,
|
||||
ctx.sim
|
||||
.and_then(|sim| sim.get_alt_approx(self.origin + house_pos))
|
||||
.unwrap_or(0.0)
|
||||
.ceil() as i32,
|
||||
),
|
||||
))
|
||||
},
|
||||
};
|
||||
|
||||
let bounds = structure.bounds_2d();
|
||||
@ -728,33 +763,26 @@ impl Settlement {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &structure.kind {
|
||||
StructureKind::House(b) => {
|
||||
let bounds = b.bounds();
|
||||
let bounds = structure.bounds();
|
||||
|
||||
for x in bounds.min.x..bounds.max.x + 1 {
|
||||
for y in bounds.min.y..bounds.max.y + 1 {
|
||||
let col = if let Some(col) =
|
||||
get_column(self.origin + Vec2::new(x, y) - wpos2d)
|
||||
{
|
||||
col
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
for x in bounds.min.x..bounds.max.x + 1 {
|
||||
for y in bounds.min.y..bounds.max.y + 1 {
|
||||
let col = if let Some(col) = get_column(self.origin + Vec2::new(x, y) - wpos2d) {
|
||||
col
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
for z in bounds.min.z.min(col.alt.floor() as i32 - 1)..bounds.max.z + 1
|
||||
{
|
||||
let rpos = Vec3::new(x, y, z);
|
||||
let wpos = Vec3::from(self.origin) + rpos;
|
||||
let coffs = wpos - Vec3::from(wpos2d);
|
||||
for z in bounds.min.z.min(col.alt.floor() as i32 - 1)..bounds.max.z + 1 {
|
||||
let rpos = Vec3::new(x, y, z);
|
||||
let wpos = Vec3::from(self.origin) + rpos;
|
||||
let coffs = wpos - Vec3::from(wpos2d);
|
||||
|
||||
if let Some(block) = b.sample(rpos) {
|
||||
let _ = vol.set(coffs, block);
|
||||
}
|
||||
}
|
||||
if let Some(block) = structure.sample(rpos) {
|
||||
let _ = vol.set(coffs, block);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user