From f7f7f12a3828d0c66f35f1952e1ae8a5737a2e95 Mon Sep 17 00:00:00 2001 From: Synis Date: Thu, 4 Mar 2021 19:23:13 +0100 Subject: [PATCH] Basic Castle Wall --- world/src/site2/mod.rs | 21 +++++-- world/src/site2/plot.rs | 5 +- world/src/site2/plot/castle.rs | 101 +++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 world/src/site2/plot/castle.rs diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 9581e140c4..c41cf921c9 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -329,11 +329,17 @@ impl Site { }, // Guard tower 2 => { - if let Some((aabr, _)) = attempt(10, || { + if let Some((aabr, entrance_tile)) = attempt(10, || { site.find_roadside_aabr(&mut rng, 4..4, Extent2::new(2, 2)) }) { let plot = site.create_plot(Plot { - kind: PlotKind::Castle, + kind: PlotKind::Castle(plot::Castle::generate( + land, + &mut rng, + &site, + entrance_tile, + aabr, + )), root_tile: aabr.center(), tiles: aabr_tiles(aabr).collect(), seed: rng.gen(), @@ -381,11 +387,17 @@ impl Site { }, // Castle 4 if castles < 1 => { - if let Some((aabr, _)) = 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 plot = site.create_plot(Plot { - kind: PlotKind::Castle, + kind: PlotKind::Castle(plot::Castle::generate( + land, + &mut rng, + &site, + entrance_tile, + aabr, + )), root_tile: aabr.center(), tiles: aabr_tiles(aabr).collect(), seed: rng.gen(), @@ -626,6 +638,7 @@ impl Site { for plot in plots_to_render { let (prim_tree, fills) = match &self.plots[plot].kind { PlotKind::House(house) => house.render_collect(self), + PlotKind::Castle(castle) => castle.render_collect(self), _ => continue, }; diff --git a/world/src/site2/plot.rs b/world/src/site2/plot.rs index d2af39b252..57b55084ca 100644 --- a/world/src/site2/plot.rs +++ b/world/src/site2/plot.rs @@ -1,6 +1,7 @@ +mod castle; mod house; -pub use self::house::House; +pub use self::{castle::Castle, house::House}; use super::*; use crate::util::DHashSet; @@ -28,6 +29,6 @@ pub enum PlotKind { Field, House(House), Plaza, - Castle, + Castle(Castle), Road(Path>), } diff --git a/world/src/site2/plot/castle.rs b/world/src/site2/plot/castle.rs new file mode 100644 index 0000000000..93ab1204dd --- /dev/null +++ b/world/src/site2/plot/castle.rs @@ -0,0 +1,101 @@ +use super::*; +use crate::{util::SQUARE_4, Land}; +use common::terrain::{Block, BlockKind, SpriteKind}; +use rand::prelude::*; +use vek::*; + +pub struct Castle { + entrance_tile: Vec2, + tile_aabr: Aabr, + bounds: Aabr, + alt: i32, +} + +impl Castle { + pub fn generate( + land: &Land, + rng: &mut impl Rng, + site: &Site, + entrance_tile: Vec2, + tile_aabr: Aabr, + ) -> Self { + Self { + 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, + } + } +} + +impl Structure for Castle { + fn render Id, G: FnMut(Id, Fill)>( + &self, + site: &Site, + mut prim: F, + mut fill: G, + ) { + let wall_height = 24; + let thickness = 12; + let parapet_height = 2; + let parapet_width = 1; + let downwards = 40; + 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); + match site.tiles.get(tile_pos).kind.clone() { + TileKind::Wall => { + let ori = if x == 0 || x == self.tile_aabr.size().w - 1 { + Vec2::new(1, 0) + } else { + Vec2::new(0, 1) + }; + let wall = prim(Primitive::Aabb(Aabb { + min: wpos.with_z(self.alt), + max: (wpos + 7).with_z(self.alt + wall_height + parapet_height), + })); + let cut_path = prim(Primitive::Aabb(Aabb { + min: Vec3::new( + wpos.x + parapet_width * ori.x, + wpos.y + parapet_width * ori.y, + self.alt + wall_height, + ), + max: Vec3::new( + wpos.x + (7 - parapet_width) * ori.x + 7 * ori.y, + wpos.y + (7 - parapet_width) * ori.y + 7 * ori.x, + 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 + 7 * ori.x + ori.y, + wpos.y + 7 * ori.y + ori.x, + self.alt + wall_height + parapet_height, + ), + })); + fill( + prim(Primitive::Xor(wall, cut_path)), + Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))), + ); + fill(cut_sides1, Fill::Block(Block::air(SpriteKind::Empty))); + }, + _ => { + fill( + prim(Primitive::Aabb(Aabb { + min: wpos_center.with_z(self.alt + 9), + max: (wpos_center + 1).with_z(self.alt + 10), + })), + Fill::Block(Block::new(BlockKind::Rock, Rgb::new(255, 255, 255))), + ); + }, + } + } + } + } +}