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:
@ -5,7 +5,7 @@ mod tile;
|
|||||||
use self::{
|
use self::{
|
||||||
gen::{Fill, Primitive, Structure},
|
gen::{Fill, Primitive, Structure},
|
||||||
plot::{Plot, PlotKind},
|
plot::{Plot, PlotKind},
|
||||||
tile::{HazardKind, Ori, Tile, TileGrid, TileKind, TILE_SIZE},
|
tile::{HazardKind, KeepKind, Ori, RoofKind, Tile, TileGrid, TileKind, TILE_SIZE},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
site::SpawnRules,
|
site::SpawnRules,
|
||||||
@ -326,15 +326,15 @@ impl Site {
|
|||||||
},
|
},
|
||||||
// Guard tower
|
// Guard tower
|
||||||
2 => {
|
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))
|
site.find_roadside_aabr(&mut rng, 4..4, Extent2::new(2, 2))
|
||||||
}) {
|
}) {
|
||||||
|
/*
|
||||||
let plot = site.create_plot(Plot {
|
let plot = site.create_plot(Plot {
|
||||||
kind: PlotKind::Castle(plot::Castle::generate(
|
kind: PlotKind::Castle(plot::Castle::generate(
|
||||||
land,
|
land,
|
||||||
&mut rng,
|
&mut rng,
|
||||||
&site,
|
&site,
|
||||||
entrance_tile,
|
|
||||||
aabr,
|
aabr,
|
||||||
)),
|
)),
|
||||||
root_tile: aabr.center(),
|
root_tile: aabr.center(),
|
||||||
@ -346,6 +346,7 @@ impl Site {
|
|||||||
kind: TileKind::Castle,
|
kind: TileKind::Castle,
|
||||||
plot: Some(plot),
|
plot: Some(plot),
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Field
|
// Field
|
||||||
@ -381,40 +382,87 @@ impl Site {
|
|||||||
},
|
},
|
||||||
// Castle
|
// Castle
|
||||||
4 if castles < 1 => {
|
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))
|
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 {
|
let plot = site.create_plot(Plot {
|
||||||
kind: PlotKind::Castle(plot::Castle::generate(
|
kind: PlotKind::Castle(plot::Castle::generate(
|
||||||
land,
|
land, &mut rng, &site, aabr, gate_aabr,
|
||||||
&mut rng,
|
|
||||||
&site,
|
|
||||||
entrance_tile,
|
|
||||||
aabr,
|
|
||||||
)),
|
)),
|
||||||
root_tile: aabr.center(),
|
root_tile: aabr.center(),
|
||||||
tiles: aabr_tiles(aabr).collect(),
|
tiles: aabr_tiles(aabr).collect(),
|
||||||
seed: rng.gen(),
|
seed: rng.gen(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Walls
|
let wall_north = Tile {
|
||||||
site.blit_aabr(aabr, Tile {
|
|
||||||
kind: TileKind::Wall(Ori::North),
|
kind: TileKind::Wall(Ori::North),
|
||||||
plot: Some(plot),
|
plot: Some(plot),
|
||||||
});
|
};
|
||||||
|
|
||||||
let tower = Tile {
|
let wall_east = Tile {
|
||||||
kind: TileKind::Tower,
|
kind: TileKind::Wall(Ori::East),
|
||||||
plot: Some(plot),
|
plot: Some(plot),
|
||||||
};
|
};
|
||||||
|
for x in 0..aabr.size().w {
|
||||||
site.tiles
|
site.tiles
|
||||||
.set(Vec2::new(aabr.min.x, aabr.min.y), tower.clone());
|
.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
|
site.tiles
|
||||||
.set(Vec2::new(aabr.max.x - 1, aabr.min.y), tower.clone());
|
.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
|
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
|
site.tiles
|
||||||
.set(Vec2::new(aabr.max.x - 1, aabr.max.y - 1), tower.clone());
|
.set(Vec2::new(aabr.min.x + offset, aabr.min.y), gate.clone());
|
||||||
|
site.tiles
|
||||||
|
.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.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
|
// Courtyard
|
||||||
site.blit_aabr(
|
site.blit_aabr(
|
||||||
@ -441,19 +489,19 @@ impl Site {
|
|||||||
);
|
);
|
||||||
site.tiles.set(
|
site.tiles.set(
|
||||||
Vec2::new(aabr.center().x + 2, aabr.center().y + 2),
|
Vec2::new(aabr.center().x + 2, aabr.center().y + 2),
|
||||||
tower.clone(),
|
tower_pyramid.clone(),
|
||||||
);
|
);
|
||||||
site.tiles.set(
|
site.tiles.set(
|
||||||
Vec2::new(aabr.center().x + 2, aabr.center().y - 3),
|
Vec2::new(aabr.center().x + 2, aabr.center().y - 3),
|
||||||
tower.clone(),
|
tower_pyramid.clone(),
|
||||||
);
|
);
|
||||||
site.tiles.set(
|
site.tiles.set(
|
||||||
Vec2::new(aabr.center().x - 3, aabr.center().y + 2),
|
Vec2::new(aabr.center().x - 3, aabr.center().y + 2),
|
||||||
tower.clone(),
|
tower_pyramid.clone(),
|
||||||
);
|
);
|
||||||
site.tiles.set(
|
site.tiles.set(
|
||||||
Vec2::new(aabr.center().x - 3, aabr.center().y - 3),
|
Vec2::new(aabr.center().x - 3, aabr.center().y - 3),
|
||||||
tower.clone(),
|
tower_pyramid.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
site.blit_aabr(
|
site.blit_aabr(
|
||||||
@ -462,7 +510,7 @@ impl Site {
|
|||||||
max: aabr.center() + 2,
|
max: aabr.center() + 2,
|
||||||
},
|
},
|
||||||
Tile {
|
Tile {
|
||||||
kind: TileKind::Keep(tile::KeepKind::Middle),
|
kind: TileKind::Keep(KeepKind::Middle),
|
||||||
plot: Some(plot),
|
plot: Some(plot),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::Land;
|
use crate::{util::SQUARE_4, Land};
|
||||||
use common::terrain::{Block, BlockKind};
|
use common::terrain::{Block, BlockKind};
|
||||||
|
use num::Integer;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub struct Castle {
|
pub struct Castle {
|
||||||
_entrance_tile: Vec2<i32>,
|
|
||||||
tile_aabr: Aabr<i32>,
|
tile_aabr: Aabr<i32>,
|
||||||
_bounds: Aabr<i32>,
|
_bounds: Aabr<i32>,
|
||||||
|
gate_aabr: Aabr<i32>,
|
||||||
|
gate_alt: i32,
|
||||||
alt: i32,
|
alt: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,22 +18,31 @@ impl Castle {
|
|||||||
land: &Land,
|
land: &Land,
|
||||||
_rng: &mut impl Rng,
|
_rng: &mut impl Rng,
|
||||||
site: &Site,
|
site: &Site,
|
||||||
entrance_tile: Vec2<i32>,
|
|
||||||
tile_aabr: Aabr<i32>,
|
tile_aabr: Aabr<i32>,
|
||||||
|
gate_aabr: Aabr<i32>,
|
||||||
) -> Self {
|
) -> 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 {
|
Self {
|
||||||
_entrance_tile: entrance_tile,
|
|
||||||
tile_aabr,
|
tile_aabr,
|
||||||
_bounds: Aabr {
|
_bounds: Aabr {
|
||||||
min: site.tile_wpos(tile_aabr.min),
|
min: site.tile_wpos(tile_aabr.min),
|
||||||
max: site.tile_wpos(tile_aabr.max),
|
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 {
|
impl Structure for Castle {
|
||||||
|
#[allow(clippy::identity_op)]
|
||||||
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
|
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
|
||||||
&self,
|
&self,
|
||||||
site: &Site,
|
site: &Site,
|
||||||
@ -39,177 +50,232 @@ impl Structure for Castle {
|
|||||||
mut fill: G,
|
mut fill: G,
|
||||||
) {
|
) {
|
||||||
let wall_height = 24;
|
let wall_height = 24;
|
||||||
let _thickness = 12;
|
|
||||||
let parapet_height = 2;
|
let parapet_height = 2;
|
||||||
let parapet_width = 1;
|
let parapet_gap = 2;
|
||||||
let _downwards = 40;
|
let parapet_offset = 2;
|
||||||
|
let ts = TILE_SIZE as i32;
|
||||||
let tower_height = 12;
|
let tower_height = 16;
|
||||||
|
|
||||||
let keep_levels = 3;
|
let keep_levels = 3;
|
||||||
let keep_level_height = 8;
|
let keep_level_height = 8;
|
||||||
let _keep_height = wall_height + keep_levels * keep_level_height + 1;
|
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 x in 0..self.tile_aabr.size().w {
|
||||||
for y in 0..self.tile_aabr.size().h {
|
for y in 0..self.tile_aabr.size().h {
|
||||||
let tile_pos = self.tile_aabr.min + Vec2::new(x, y);
|
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 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() {
|
match site.tiles.get(tile_pos).kind.clone() {
|
||||||
TileKind::Wall(_ori) => {
|
TileKind::Wall(ori) => {
|
||||||
|
let dir = ori.dir();
|
||||||
let wall = prim(Primitive::Aabb(Aabb {
|
let wall = prim(Primitive::Aabb(Aabb {
|
||||||
min: wpos.with_z(self.alt),
|
min: wpos.with_z(self.alt - 20),
|
||||||
max: (wpos + 6).with_z(self.alt + wall_height + parapet_height),
|
max: (wpos + ts).with_z(self.alt + wall_height),
|
||||||
}));
|
}));
|
||||||
let cut_path = prim(Primitive::Aabb(Aabb {
|
// TODO Figure out logic to choose on on which site wall should be placed
|
||||||
min: (wpos + (parapet_width * ori) as Vec2<i32>)
|
// (inner, outer)
|
||||||
.with_z(self.alt + wall_height),
|
let parapet = prim(Primitive::Aabb(Aabb {
|
||||||
max: (wpos
|
min: (wpos - dir.yx()).with_z(self.alt + wall_height),
|
||||||
+ (6 - parapet_width) * ori as Vec2<i32>
|
max: (wpos + ts * dir).with_z(self.alt + wall_height + parapet_height),
|
||||||
+ 6 * ori.yx() as Vec2<i32>)
|
}));
|
||||||
|
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),
|
.with_z(self.alt + wall_height + parapet_height),
|
||||||
}));
|
}));
|
||||||
let cut_sides1 = prim(Primitive::Aabb(Aabb {
|
let cut_sides = prim(Primitive::Aabb(Aabb {
|
||||||
min: Vec3::new(wpos.x, wpos.y, self.alt + wall_height + 1),
|
min: (wpos + parapet_offset * dir - dir.yx())
|
||||||
max: Vec3::new(
|
.with_z(self.alt + wall_height + parapet_height - 1),
|
||||||
wpos.x + 6 * ori.x + ori.y,
|
max: (wpos
|
||||||
wpos.y + 6 * ori.y + ori.x,
|
+ (ts + 1) * dir.yx()
|
||||||
self.alt + wall_height + parapet_height,
|
+ (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),
|
fill(wall, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||||
max: Vec3::new(wpos.x + 1, wpos.y + 7, self.alt + wall_height),
|
let sides = prim(Primitive::Or(parapet, parapet2));
|
||||||
}));
|
fill(sides, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||||
let pillar_end = prim(Primitive::Aabb(Aabb {
|
if (x + y).is_odd() {
|
||||||
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(
|
fill(
|
||||||
prim(Primitive::Or(wall, pillars)),
|
prim(Primitive::Aabb(Aabb {
|
||||||
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
|
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),
|
||||||
);
|
);
|
||||||
fill(cut_path, Fill::Block(Block::empty()));
|
} else {
|
||||||
fill(cut_sides1, Fill::Block(Block::empty()));
|
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 {
|
let tower_lower = prim(Primitive::Aabb(Aabb {
|
||||||
min: wpos.with_z(self.alt),
|
min: (wpos - 1).with_z(self.alt - 20),
|
||||||
max: (wpos + 6).with_z(self.alt + wall_height + tower_height),
|
max: (wpos + ts + 1).with_z(tower_total_height),
|
||||||
}));
|
}));
|
||||||
let tower_lower_inner_x = prim(Primitive::Aabb(Aabb {
|
fill(tower_lower, Fill::Brick(BlockKind::Rock, wall_rgb, 12));
|
||||||
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))),
|
|
||||||
);
|
|
||||||
let tower_upper = prim(Primitive::Aabb(Aabb {
|
let tower_upper = prim(Primitive::Aabb(Aabb {
|
||||||
min: Vec3::new(
|
min: (wpos - 2).with_z(tower_total_height - 4i32),
|
||||||
wpos.x - 1,
|
max: (wpos + ts + 2).with_z(tower_total_height - 2i32),
|
||||||
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,
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
let tower_upper2 = prim(Primitive::Aabb(Aabb {
|
let tower_upper2 = prim(Primitive::Aabb(Aabb {
|
||||||
min: Vec3::new(
|
min: (wpos - 3).with_z(tower_total_height - 2i32),
|
||||||
wpos.x - 2,
|
max: (wpos + ts + 3).with_z(tower_total_height),
|
||||||
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,
|
|
||||||
),
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
fill(
|
fill(
|
||||||
prim(Primitive::Or(tower_upper, tower_upper2)),
|
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),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
match roof {
|
||||||
|
RoofKind::Pyramid => {
|
||||||
let roof_lip = 1;
|
let roof_lip = 1;
|
||||||
let roof_height = 8 / 2 + roof_lip + 1;
|
let roof_height = (ts + 3) / 2 + roof_lip + 1;
|
||||||
|
|
||||||
// Roof
|
|
||||||
fill(
|
fill(
|
||||||
prim(Primitive::Pyramid {
|
prim(Primitive::Pyramid {
|
||||||
aabb: Aabb {
|
aabb: Aabb {
|
||||||
min: (wpos - 2 - roof_lip)
|
min: (wpos - 3 - roof_lip).with_z(tower_total_height),
|
||||||
.with_z(self.alt + wall_height + tower_height),
|
max: (wpos + ts + 3 + roof_lip)
|
||||||
max: (wpos + 8 + roof_lip).with_z(
|
.with_z(tower_total_height + roof_height),
|
||||||
self.alt + wall_height + tower_height + roof_height,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
inset: roof_height,
|
inset: roof_height,
|
||||||
}),
|
}),
|
||||||
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(116, 20, 20))),
|
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,
|
||||||
|
),
|
||||||
|
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) => {
|
TileKind::Keep(kind) => {
|
||||||
match kind {
|
match kind {
|
||||||
tile::KeepKind::Middle => {
|
KeepKind::Middle => {
|
||||||
for i in 0..keep_levels + 1 {
|
for i in 0..keep_levels + 1 {
|
||||||
let height = keep_level_height * i;
|
let height = keep_level_height * i;
|
||||||
fill(
|
fill(
|
||||||
prim(Primitive::Aabb(Aabb {
|
prim(Primitive::Aabb(Aabb {
|
||||||
min: wpos.with_z(self.alt + height),
|
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(
|
Fill::Block(Block::new(
|
||||||
BlockKind::Rock,
|
BlockKind::Wood,
|
||||||
Rgb::new(89, 44, 14),
|
Rgb::new(89, 44, 14),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tile::KeepKind::Corner => {},
|
KeepKind::Corner => {},
|
||||||
tile::KeepKind::Wall(_ori) => {
|
KeepKind::Wall(_ori) => {
|
||||||
for i in 0..keep_levels + 1 {
|
for i in 0..keep_levels + 1 {
|
||||||
let _height = keep_level_height * i;
|
let _height = keep_level_height * i;
|
||||||
// TODO clamp value in case of big heights
|
// 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,
|
Building,
|
||||||
Castle,
|
Castle,
|
||||||
Wall(Ori),
|
Wall(Ori),
|
||||||
Tower,
|
Tower(RoofKind),
|
||||||
Keep(KeepKind),
|
Keep(KeepKind),
|
||||||
|
Gate,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
@ -229,6 +230,12 @@ pub enum KeepKind {
|
|||||||
Wall(Ori),
|
Wall(Ori),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub enum RoofKind {
|
||||||
|
Parapet,
|
||||||
|
Pyramid,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum Ori {
|
pub enum Ori {
|
||||||
|
Reference in New Issue
Block a user