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