mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'synis/castles-cont' into 'master'
Castle generation See merge request veloren/veloren!1881
This commit is contained in:
commit
e43b57f119
@ -5,7 +5,7 @@ mod tile;
|
||||
use self::{
|
||||
gen::{Fill, Primitive, Structure},
|
||||
plot::{Plot, PlotKind},
|
||||
tile::{HazardKind, Ori, Tile, TileGrid, TileKind, TILE_SIZE},
|
||||
tile::{HazardKind, KeepKind, Ori, RoofKind, Tile, TileGrid, TileKind, TILE_SIZE},
|
||||
};
|
||||
use crate::{
|
||||
site::SpawnRules,
|
||||
@ -326,15 +326,15 @@ impl Site {
|
||||
},
|
||||
// Guard tower
|
||||
2 => {
|
||||
if let Some((aabr, entrance_tile)) = attempt(10, || {
|
||||
if let Some((_aabr, _)) = attempt(10, || {
|
||||
site.find_roadside_aabr(&mut rng, 4..4, Extent2::new(2, 2))
|
||||
}) {
|
||||
/*
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::Castle(plot::Castle::generate(
|
||||
land,
|
||||
&mut rng,
|
||||
&site,
|
||||
entrance_tile,
|
||||
aabr,
|
||||
)),
|
||||
root_tile: aabr.center(),
|
||||
@ -346,6 +346,7 @@ impl Site {
|
||||
kind: TileKind::Castle,
|
||||
plot: Some(plot),
|
||||
});
|
||||
*/
|
||||
}
|
||||
},
|
||||
// Field
|
||||
@ -381,40 +382,87 @@ impl Site {
|
||||
},
|
||||
// Castle
|
||||
4 if castles < 1 => {
|
||||
if let Some((aabr, entrance_tile)) = attempt(10, || {
|
||||
if let Some((aabr, _entrance_tile)) = attempt(10, || {
|
||||
site.find_roadside_aabr(&mut rng, 16 * 16..18 * 18, Extent2::new(16, 16))
|
||||
}) {
|
||||
let offset = rng.gen_range(5..(aabr.size().w.min(aabr.size().h) - 4));
|
||||
let gate_aabr = Aabr {
|
||||
min: Vec2::new(aabr.min.x + offset - 1, aabr.min.y),
|
||||
max: Vec2::new(aabr.min.x + offset + 2, aabr.min.y + 1),
|
||||
};
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::Castle(plot::Castle::generate(
|
||||
land,
|
||||
&mut rng,
|
||||
&site,
|
||||
entrance_tile,
|
||||
aabr,
|
||||
land, &mut rng, &site, aabr, gate_aabr,
|
||||
)),
|
||||
root_tile: aabr.center(),
|
||||
tiles: aabr_tiles(aabr).collect(),
|
||||
seed: rng.gen(),
|
||||
});
|
||||
|
||||
// Walls
|
||||
site.blit_aabr(aabr, Tile {
|
||||
let wall_north = Tile {
|
||||
kind: TileKind::Wall(Ori::North),
|
||||
plot: Some(plot),
|
||||
});
|
||||
};
|
||||
|
||||
let tower = Tile {
|
||||
kind: TileKind::Tower,
|
||||
let wall_east = Tile {
|
||||
kind: TileKind::Wall(Ori::East),
|
||||
plot: Some(plot),
|
||||
};
|
||||
for x in 0..aabr.size().w {
|
||||
site.tiles
|
||||
.set(aabr.min + Vec2::new(x, 0), wall_east.clone());
|
||||
site.tiles.set(
|
||||
aabr.min + Vec2::new(x, aabr.size().h - 1),
|
||||
wall_east.clone(),
|
||||
);
|
||||
}
|
||||
for y in 0..aabr.size().h {
|
||||
site.tiles
|
||||
.set(aabr.min + Vec2::new(0, y), wall_north.clone());
|
||||
site.tiles.set(
|
||||
aabr.min + Vec2::new(aabr.size().w - 1, y),
|
||||
wall_north.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
let gate = Tile {
|
||||
kind: TileKind::Gate,
|
||||
plot: Some(plot),
|
||||
};
|
||||
let tower_parapet = Tile {
|
||||
kind: TileKind::Tower(RoofKind::Parapet),
|
||||
plot: Some(plot),
|
||||
};
|
||||
let tower_pyramid = Tile {
|
||||
kind: TileKind::Tower(RoofKind::Pyramid),
|
||||
plot: Some(plot),
|
||||
};
|
||||
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.min.x + offset - 2, aabr.min.y),
|
||||
tower_parapet.clone(),
|
||||
);
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.min.x, aabr.min.y), tower.clone());
|
||||
.set(Vec2::new(aabr.min.x + offset - 1, aabr.min.y), gate.clone());
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.max.x - 1, aabr.min.y), tower.clone());
|
||||
.set(Vec2::new(aabr.min.x + offset, aabr.min.y), gate.clone());
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.min.x, aabr.max.y - 1), tower.clone());
|
||||
.set(Vec2::new(aabr.min.x + offset + 1, aabr.min.y), gate.clone());
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.min.x + offset + 2, aabr.min.y),
|
||||
tower_parapet.clone(),
|
||||
);
|
||||
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.max.x - 1, aabr.max.y - 1), tower.clone());
|
||||
.set(Vec2::new(aabr.min.x, aabr.min.y), tower_parapet.clone());
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.max.x - 1, aabr.min.y), tower_parapet.clone());
|
||||
site.tiles
|
||||
.set(Vec2::new(aabr.min.x, aabr.max.y - 1), tower_parapet.clone());
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.max.x - 1, aabr.max.y - 1),
|
||||
tower_parapet.clone(),
|
||||
);
|
||||
|
||||
// Courtyard
|
||||
site.blit_aabr(
|
||||
@ -441,19 +489,19 @@ impl Site {
|
||||
);
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.center().x + 2, aabr.center().y + 2),
|
||||
tower.clone(),
|
||||
tower_pyramid.clone(),
|
||||
);
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.center().x + 2, aabr.center().y - 3),
|
||||
tower.clone(),
|
||||
tower_pyramid.clone(),
|
||||
);
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.center().x - 3, aabr.center().y + 2),
|
||||
tower.clone(),
|
||||
tower_pyramid.clone(),
|
||||
);
|
||||
site.tiles.set(
|
||||
Vec2::new(aabr.center().x - 3, aabr.center().y - 3),
|
||||
tower.clone(),
|
||||
tower_pyramid.clone(),
|
||||
);
|
||||
|
||||
site.blit_aabr(
|
||||
@ -462,7 +510,7 @@ impl Site {
|
||||
max: aabr.center() + 2,
|
||||
},
|
||||
Tile {
|
||||
kind: TileKind::Keep(tile::KeepKind::Middle),
|
||||
kind: TileKind::Keep(KeepKind::Middle),
|
||||
plot: Some(plot),
|
||||
},
|
||||
);
|
||||
|
@ -1,13 +1,15 @@
|
||||
use super::*;
|
||||
use crate::Land;
|
||||
use crate::{util::SQUARE_4, Land};
|
||||
use common::terrain::{Block, BlockKind};
|
||||
use num::Integer;
|
||||
use rand::prelude::*;
|
||||
use vek::*;
|
||||
|
||||
pub struct Castle {
|
||||
_entrance_tile: Vec2<i32>,
|
||||
tile_aabr: Aabr<i32>,
|
||||
_bounds: Aabr<i32>,
|
||||
gate_aabr: Aabr<i32>,
|
||||
gate_alt: i32,
|
||||
alt: i32,
|
||||
}
|
||||
|
||||
@ -16,22 +18,31 @@ impl Castle {
|
||||
land: &Land,
|
||||
_rng: &mut impl Rng,
|
||||
site: &Site,
|
||||
entrance_tile: Vec2<i32>,
|
||||
tile_aabr: Aabr<i32>,
|
||||
gate_aabr: Aabr<i32>,
|
||||
) -> Self {
|
||||
let alt = SQUARE_4
|
||||
.iter()
|
||||
.map(|corner| tile_aabr.min + (tile_aabr.max - tile_aabr.min - 1) * corner)
|
||||
.map(|pos| land.get_alt_approx(site.tile_center_wpos(pos)) as i32)
|
||||
.sum::<i32>()
|
||||
/ 4;
|
||||
|
||||
Self {
|
||||
_entrance_tile: entrance_tile,
|
||||
tile_aabr,
|
||||
_bounds: Aabr {
|
||||
min: site.tile_wpos(tile_aabr.min),
|
||||
max: site.tile_wpos(tile_aabr.max),
|
||||
},
|
||||
alt: land.get_alt_approx(site.tile_center_wpos(entrance_tile)) as i32,
|
||||
gate_aabr,
|
||||
gate_alt: land.get_alt_approx(site.tile_center_wpos(gate_aabr.center())) as i32,
|
||||
alt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for Castle {
|
||||
#[allow(clippy::identity_op)]
|
||||
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
|
||||
&self,
|
||||
site: &Site,
|
||||
@ -39,177 +50,232 @@ impl Structure for Castle {
|
||||
mut fill: G,
|
||||
) {
|
||||
let wall_height = 24;
|
||||
let _thickness = 12;
|
||||
let parapet_height = 2;
|
||||
let parapet_width = 1;
|
||||
let _downwards = 40;
|
||||
|
||||
let tower_height = 12;
|
||||
|
||||
let parapet_gap = 2;
|
||||
let parapet_offset = 2;
|
||||
let ts = TILE_SIZE as i32;
|
||||
let tower_height = 16;
|
||||
let keep_levels = 3;
|
||||
let keep_level_height = 8;
|
||||
let _keep_height = wall_height + keep_levels * keep_level_height + 1;
|
||||
let wall_rgb = Rgb::new(38, 46, 43);
|
||||
// Flatten inside of the castle
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: site.tile_wpos(self.tile_aabr.min).with_z(self.gate_alt),
|
||||
max: site
|
||||
.tile_wpos(self.tile_aabr.max)
|
||||
.with_z(self.alt + tower_height),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: site.tile_wpos(self.tile_aabr.min).with_z(self.gate_alt),
|
||||
max: site.tile_wpos(self.tile_aabr.max).with_z(self.gate_alt + 1),
|
||||
})),
|
||||
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(55, 45, 65))),
|
||||
);
|
||||
for x in 0..self.tile_aabr.size().w {
|
||||
for y in 0..self.tile_aabr.size().h {
|
||||
let tile_pos = self.tile_aabr.min + Vec2::new(x, y);
|
||||
let _wpos_center = site.tile_center_wpos(tile_pos);
|
||||
let wpos = site.tile_wpos(tile_pos);
|
||||
let ori = if x == 0 || x == self.tile_aabr.size().w - 1 {
|
||||
Vec2::new(1, 0)
|
||||
} else {
|
||||
Vec2::new(0, 1)
|
||||
};
|
||||
let ori_tower_x = if x == 0 {
|
||||
Vec2::new(1, 0)
|
||||
} else {
|
||||
Vec2::new(0, 0)
|
||||
};
|
||||
let ori_tower_y = if y == 0 {
|
||||
Vec2::new(0, 1)
|
||||
} else {
|
||||
Vec2::new(0, 0)
|
||||
};
|
||||
let ori_tower = ori_tower_x + ori_tower_y;
|
||||
match site.tiles.get(tile_pos).kind.clone() {
|
||||
TileKind::Wall(_ori) => {
|
||||
TileKind::Wall(ori) => {
|
||||
let dir = ori.dir();
|
||||
let wall = prim(Primitive::Aabb(Aabb {
|
||||
min: wpos.with_z(self.alt),
|
||||
max: (wpos + 6).with_z(self.alt + wall_height + parapet_height),
|
||||
min: wpos.with_z(self.alt - 20),
|
||||
max: (wpos + ts).with_z(self.alt + wall_height),
|
||||
}));
|
||||
let cut_path = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + (parapet_width * ori) as Vec2<i32>)
|
||||
.with_z(self.alt + wall_height),
|
||||
max: (wpos
|
||||
+ (6 - parapet_width) * ori as Vec2<i32>
|
||||
+ 6 * ori.yx() as Vec2<i32>)
|
||||
// TODO Figure out logic to choose on on which site wall should be placed
|
||||
// (inner, outer)
|
||||
let parapet = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos - dir.yx()).with_z(self.alt + wall_height),
|
||||
max: (wpos + ts * dir).with_z(self.alt + wall_height + parapet_height),
|
||||
}));
|
||||
let parapet2 = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + ts * dir.yx()).with_z(self.alt + wall_height),
|
||||
max: (wpos + (ts + 1) * dir.yx() + ts * dir)
|
||||
.with_z(self.alt + wall_height + parapet_height),
|
||||
}));
|
||||
let cut_sides1 = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(wpos.x, wpos.y, self.alt + wall_height + 1),
|
||||
max: Vec3::new(
|
||||
wpos.x + 6 * ori.x + ori.y,
|
||||
wpos.y + 6 * ori.y + ori.x,
|
||||
self.alt + wall_height + parapet_height,
|
||||
),
|
||||
let cut_sides = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + parapet_offset * dir - dir.yx())
|
||||
.with_z(self.alt + wall_height + parapet_height - 1),
|
||||
max: (wpos
|
||||
+ (ts + 1) * dir.yx()
|
||||
+ (parapet_offset + parapet_gap) * dir)
|
||||
.with_z(self.alt + wall_height + parapet_height),
|
||||
}));
|
||||
let pillar_start = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(wpos.x, wpos.y - 1, self.alt),
|
||||
max: Vec3::new(wpos.x + 1, wpos.y + 7, self.alt + wall_height),
|
||||
}));
|
||||
let pillar_end = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(wpos.x + 5, wpos.y - 1, self.alt),
|
||||
max: Vec3::new(wpos.x + 6, wpos.y + 7, self.alt + wall_height),
|
||||
}));
|
||||
let pillars = prim(Primitive::Or(pillar_start, pillar_end));
|
||||
fill(
|
||||
prim(Primitive::Or(wall, pillars)),
|
||||
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
|
||||
);
|
||||
fill(cut_path, Fill::Block(Block::empty()));
|
||||
fill(cut_sides1, Fill::Block(Block::empty()));
|
||||
|
||||
fill(wall, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||
let sides = prim(Primitive::Or(parapet, parapet2));
|
||||
fill(sides, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||
if (x + y).is_odd() {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + 2 * dir - dir.yx()).with_z(self.alt - 20),
|
||||
max: (wpos + 4 * dir + (ts + 1) * dir.yx())
|
||||
.with_z(self.alt + wall_height),
|
||||
})),
|
||||
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
|
||||
);
|
||||
} else {
|
||||
let window_top = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + 2 * dir).with_z(self.alt + wall_height / 4 + 9),
|
||||
max: (wpos + (ts - 2) * dir + dir.yx())
|
||||
.with_z(self.alt + wall_height / 4 + 12),
|
||||
}));
|
||||
let window_bottom = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + 1 * dir).with_z(self.alt + wall_height / 4),
|
||||
max: (wpos + (ts - 1) * dir + dir.yx())
|
||||
.with_z(self.alt + wall_height / 4 + 9),
|
||||
}));
|
||||
let window_top2 = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + 2 * dir + (ts - 1) * dir.yx())
|
||||
.with_z(self.alt + wall_height / 4 + 9),
|
||||
max: (wpos + (ts - 2) * dir + ts * dir.yx())
|
||||
.with_z(self.alt + wall_height / 4 + 12),
|
||||
}));
|
||||
let window_bottom2 = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos + 1 * dir + (ts - 1) * dir.yx())
|
||||
.with_z(self.alt + wall_height / 4),
|
||||
max: (wpos + (ts - 1) * dir + ts * dir.yx())
|
||||
.with_z(self.alt + wall_height / 4 + 9),
|
||||
}));
|
||||
|
||||
fill(window_bottom, Fill::Block(Block::empty()));
|
||||
fill(window_top, Fill::Block(Block::empty()));
|
||||
fill(window_bottom2, Fill::Block(Block::empty()));
|
||||
fill(window_top2, Fill::Block(Block::empty()));
|
||||
}
|
||||
fill(cut_sides, Fill::Block(Block::empty()));
|
||||
},
|
||||
TileKind::Tower => {
|
||||
TileKind::Tower(roof) => {
|
||||
let tower_total_height =
|
||||
self.alt + wall_height + parapet_height + tower_height;
|
||||
let tower_lower = prim(Primitive::Aabb(Aabb {
|
||||
min: wpos.with_z(self.alt),
|
||||
max: (wpos + 6).with_z(self.alt + wall_height + tower_height),
|
||||
min: (wpos - 1).with_z(self.alt - 20),
|
||||
max: (wpos + ts + 1).with_z(tower_total_height),
|
||||
}));
|
||||
let tower_lower_inner_x = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(
|
||||
wpos.x + ori_tower.x,
|
||||
wpos.y + parapet_width,
|
||||
self.alt + wall_height,
|
||||
),
|
||||
max: Vec3::new(
|
||||
wpos.x + 6 + ori_tower.x - 1,
|
||||
wpos.y + 6 - parapet_width,
|
||||
self.alt + wall_height + tower_height / 3,
|
||||
),
|
||||
}));
|
||||
let tower_lower_inner_y = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(
|
||||
wpos.x + parapet_width,
|
||||
wpos.y + ori_tower.y,
|
||||
self.alt + wall_height,
|
||||
),
|
||||
max: Vec3::new(
|
||||
wpos.x + 6 - parapet_width,
|
||||
wpos.y + 6 + ori_tower.y - 1,
|
||||
self.alt + wall_height + tower_height / 3,
|
||||
),
|
||||
}));
|
||||
let tower_lower_inner =
|
||||
prim(Primitive::Or(tower_lower_inner_x, tower_lower_inner_y));
|
||||
fill(
|
||||
prim(Primitive::Xor(tower_lower, tower_lower_inner)),
|
||||
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
|
||||
);
|
||||
fill(tower_lower, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||
let tower_upper = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(
|
||||
wpos.x - 1,
|
||||
wpos.y - 1,
|
||||
self.alt + wall_height + tower_height - 3i32,
|
||||
),
|
||||
max: Vec3::new(
|
||||
wpos.x + 7,
|
||||
wpos.y + 7,
|
||||
self.alt + wall_height + tower_height - 1i32,
|
||||
),
|
||||
min: (wpos - 2).with_z(tower_total_height - 4i32),
|
||||
max: (wpos + ts + 2).with_z(tower_total_height - 2i32),
|
||||
}));
|
||||
let tower_upper2 = prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(
|
||||
wpos.x - 2,
|
||||
wpos.y - 2,
|
||||
self.alt + wall_height + tower_height - 1i32,
|
||||
),
|
||||
max: Vec3::new(
|
||||
wpos.x + 8,
|
||||
wpos.y + 8,
|
||||
self.alt + wall_height + tower_height,
|
||||
),
|
||||
min: (wpos - 3).with_z(tower_total_height - 2i32),
|
||||
max: (wpos + ts + 3).with_z(tower_total_height),
|
||||
}));
|
||||
|
||||
fill(
|
||||
prim(Primitive::Or(tower_upper, tower_upper2)),
|
||||
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
|
||||
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
|
||||
);
|
||||
|
||||
let roof_lip = 1;
|
||||
let roof_height = 8 / 2 + roof_lip + 1;
|
||||
match roof {
|
||||
RoofKind::Pyramid => {
|
||||
let roof_lip = 1;
|
||||
let roof_height = (ts + 3) / 2 + roof_lip + 1;
|
||||
|
||||
// Roof
|
||||
fill(
|
||||
prim(Primitive::Pyramid {
|
||||
aabb: Aabb {
|
||||
min: (wpos - 2 - roof_lip)
|
||||
.with_z(self.alt + wall_height + tower_height),
|
||||
max: (wpos + 8 + roof_lip).with_z(
|
||||
self.alt + wall_height + tower_height + roof_height,
|
||||
fill(
|
||||
prim(Primitive::Pyramid {
|
||||
aabb: Aabb {
|
||||
min: (wpos - 3 - roof_lip).with_z(tower_total_height),
|
||||
max: (wpos + ts + 3 + roof_lip)
|
||||
.with_z(tower_total_height + roof_height),
|
||||
},
|
||||
inset: roof_height,
|
||||
}),
|
||||
Fill::Brick(BlockKind::Wood, Rgb::new(40, 5, 11), 10),
|
||||
);
|
||||
},
|
||||
RoofKind::Parapet => {
|
||||
let tower_top_outer = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos - 3).with_z(
|
||||
self.alt + wall_height + parapet_height + tower_height,
|
||||
),
|
||||
},
|
||||
inset: roof_height,
|
||||
}),
|
||||
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(116, 20, 20))),
|
||||
);
|
||||
max: (wpos + ts + 3)
|
||||
.with_z(tower_total_height + parapet_height),
|
||||
}));
|
||||
let tower_top_inner = prim(Primitive::Aabb(Aabb {
|
||||
min: (wpos - 2).with_z(tower_total_height),
|
||||
max: (wpos + ts + 2)
|
||||
.with_z(tower_total_height + parapet_height),
|
||||
}));
|
||||
|
||||
fill(
|
||||
prim(Primitive::Xor(tower_top_outer, tower_top_inner)),
|
||||
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
|
||||
);
|
||||
|
||||
for x in (wpos.x..wpos.x + ts).step_by(2 * parapet_gap as usize) {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(x, wpos.y - 3, tower_total_height + 1),
|
||||
max: Vec3::new(
|
||||
x + parapet_gap,
|
||||
wpos.y + ts + 3,
|
||||
tower_total_height + parapet_height,
|
||||
),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
}
|
||||
for y in (wpos.y..wpos.y + ts).step_by(2 * parapet_gap as usize) {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(wpos.x - 3, y, tower_total_height + 1),
|
||||
max: Vec3::new(
|
||||
wpos.x + ts + 3,
|
||||
y + parapet_gap,
|
||||
tower_total_height + parapet_height,
|
||||
),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
}
|
||||
|
||||
for &cpos in SQUARE_4.iter() {
|
||||
let pos = wpos - 3 + (ts + 6) * cpos - cpos;
|
||||
let pos2 = wpos - 2 + (ts + 4) * cpos - cpos;
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: pos.with_z(tower_total_height - 2),
|
||||
max: (pos + 1)
|
||||
.with_z(tower_total_height + parapet_height),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: pos2.with_z(tower_total_height - 4),
|
||||
max: (pos2 + 1).with_z(tower_total_height - 2),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
TileKind::Keep(kind) => {
|
||||
match kind {
|
||||
tile::KeepKind::Middle => {
|
||||
KeepKind::Middle => {
|
||||
for i in 0..keep_levels + 1 {
|
||||
let height = keep_level_height * i;
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: wpos.with_z(self.alt + height),
|
||||
max: (wpos + 6).with_z(self.alt + height + 1),
|
||||
max: (wpos + ts).with_z(self.alt + height + 1),
|
||||
})),
|
||||
Fill::Block(Block::new(
|
||||
BlockKind::Rock,
|
||||
BlockKind::Wood,
|
||||
Rgb::new(89, 44, 14),
|
||||
)),
|
||||
);
|
||||
}
|
||||
},
|
||||
tile::KeepKind::Corner => {},
|
||||
tile::KeepKind::Wall(_ori) => {
|
||||
KeepKind::Corner => {},
|
||||
KeepKind::Wall(_ori) => {
|
||||
for i in 0..keep_levels + 1 {
|
||||
let _height = keep_level_height * i;
|
||||
// TODO clamp value in case of big heights
|
||||
@ -222,5 +288,57 @@ impl Structure for Castle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render gate here
|
||||
// TODO move this into tile loop
|
||||
let gate_aabb = Aabb {
|
||||
min: (site.tile_wpos(self.gate_aabr.min) + Vec2::unit_x()).with_z(self.gate_alt - 1),
|
||||
max: (site.tile_wpos(self.gate_aabr.max) - Vec2::unit_x())
|
||||
.with_z(self.alt + wall_height),
|
||||
};
|
||||
fill(
|
||||
prim(Primitive::Aabb(gate_aabb)),
|
||||
Fill::Brick(BlockKind::Rock, wall_rgb, 12),
|
||||
);
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: (gate_aabb.min + Vec3::unit_x() * 2 + Vec3::unit_z() * 2),
|
||||
max: (gate_aabb.max - Vec3::unit_x() * 2 - Vec3::unit_z() * 16),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
let height = self.alt + wall_height - 17;
|
||||
for i in 1..5 {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(gate_aabb.min.x + 2 + i, gate_aabb.min.y, height + i as i32),
|
||||
max: Vec3::new(
|
||||
gate_aabb.max.x - 2 - i,
|
||||
gate_aabb.max.y,
|
||||
height + i as i32 + 1,
|
||||
),
|
||||
})),
|
||||
Fill::Block(Block::empty()),
|
||||
);
|
||||
}
|
||||
let height = self.alt + wall_height - 7;
|
||||
for x in (gate_aabb.min.x + 1..gate_aabb.max.x - 2).step_by(4) {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(x, gate_aabb.min.y + 1, height - 13),
|
||||
max: Vec3::new(x + 2, gate_aabb.min.y + 2, height),
|
||||
})),
|
||||
Fill::Brick(BlockKind::Rock, Rgb::new(27, 35, 32), 8),
|
||||
);
|
||||
}
|
||||
for z in (height - 12..height).step_by(4) {
|
||||
fill(
|
||||
prim(Primitive::Aabb(Aabb {
|
||||
min: Vec3::new(gate_aabb.min.x + 2, gate_aabb.min.y + 1, z),
|
||||
max: Vec3::new(gate_aabb.max.x - 2, gate_aabb.min.y + 2, z + 2),
|
||||
})),
|
||||
Fill::Brick(BlockKind::Rock, Rgb::new(27, 35, 32), 8),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,8 +183,9 @@ pub enum TileKind {
|
||||
Building,
|
||||
Castle,
|
||||
Wall(Ori),
|
||||
Tower,
|
||||
Tower(RoofKind),
|
||||
Keep(KeepKind),
|
||||
Gate,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
@ -229,6 +230,12 @@ pub enum KeepKind {
|
||||
Wall(Ori),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum RoofKind {
|
||||
Parapet,
|
||||
Pyramid,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Ori {
|
||||
|
Loading…
Reference in New Issue
Block a user