Merge branch 'floppy-DesertCity' into 'master'

DesertCity

See merge request veloren/veloren!3495
This commit is contained in:
Samuel Keiffer 2022-08-08 09:58:19 +00:00
commit 8602a04e71
12 changed files with 3368 additions and 57 deletions

View File

@ -3329,7 +3329,7 @@ Lantern: Some((
],
wind_sway: 0.0,
)),
// CliffTown Decor
// CliffTown & DesertCity Decor
WindowArabic: Some((
variations: [
(

View File

@ -275,7 +275,6 @@ pub fn init(
});
}
},
SiteKind::CliffTown(site2) => {
for _ in 0..(site2.plazas().len() as f32 * 1.5) as usize {
rtsim.entities.insert(Entity {
@ -300,6 +299,75 @@ pub fn init(
});
}
},
SiteKind::DesertCity(site2) => {
// villagers
for _ in 0..(site2.plazas().len() as f32 * 1.5) as usize {
rtsim.entities.insert(Entity {
is_loaded: false,
pos: site2
.plots()
.choose(&mut thread_rng())
.map_or(site.get_origin(), |plot| {
site2.tile_center_wpos(plot.root_tile())
})
.with_z(0)
.map(|e| e as f32),
seed: thread_rng().gen(),
controller: RtSimController::default(),
last_time_ticked: 0.0,
kind: RtSimEntityKind::Villager,
brain: Brain::villager(site_id, &mut thread_rng()),
});
}
// guards
for _ in 0..site2.plazas().len() as usize {
rtsim.entities.insert(Entity {
is_loaded: false,
pos: site2
.plazas()
.choose(&mut thread_rng())
.map_or(site.get_origin(), |p| {
site2.tile_center_wpos(site2.plot(p).root_tile())
+ Vec2::new(
thread_rng().gen_range(-8..9),
thread_rng().gen_range(-8..9),
)
})
.with_z(0)
.map(|e| e as f32),
seed: thread_rng().gen(),
controller: RtSimController::default(),
last_time_ticked: 0.0,
kind: RtSimEntityKind::TownGuard,
brain: Brain::town_guard(site_id, &mut thread_rng()),
});
}
// merchants
for _ in 0..site2.plazas().len() as usize {
rtsim.entities.insert(Entity {
is_loaded: false,
pos: site2
.plazas()
.choose(&mut thread_rng())
.map_or(site.get_origin(), |p| {
site2.tile_center_wpos(site2.plot(p).root_tile())
+ Vec2::new(
thread_rng().gen_range(-8..9),
thread_rng().gen_range(-8..9),
)
})
.with_z(0)
.map(|e| e as f32),
seed: thread_rng().gen(),
controller: RtSimController::default(),
last_time_ticked: 0.0,
kind: RtSimEntityKind::Merchant,
brain: Brain::merchant(site_id, &mut thread_rng()),
});
}
},
_ => {},
}
}

View File

@ -170,6 +170,7 @@ impl Civs {
SiteKind::Castle => (16i32, 5.0),
SiteKind::Refactor => (32i32, 10.0),
SiteKind::CliffTown => (32i32, 10.0),
SiteKind::DesertCity => (64i32, 25.0),
SiteKind::Tree => (12i32, 8.0),
SiteKind::GiantTree => (12i32, 8.0),
SiteKind::Gnarling => (16i32, 10.0),
@ -231,42 +232,46 @@ impl Civs {
});
let mut rng = ctx.reseed().rng;
let site = index.sites.insert(match &sim_site.kind {
SiteKind::Settlement => {
WorldSite::settlement(Settlement::generate(wpos, Some(ctx.sim), &mut rng))
},
SiteKind::Dungeon => WorldSite::dungeon(site2::Site::generate_dungeon(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::Castle => {
WorldSite::castle(Castle::generate(wpos, Some(ctx.sim), &mut rng))
},
SiteKind::Refactor => WorldSite::refactor(site2::Site::generate_city(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::CliffTown => WorldSite::cliff_town(site2::Site::generate_cliff_town(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::Tree => {
WorldSite::tree(Tree::generate(wpos, &Land::from_sim(ctx.sim), &mut rng))
},
SiteKind::GiantTree => WorldSite::giant_tree(site2::Site::generate_giant_tree(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::Gnarling => WorldSite::gnarling(site2::Site::generate_gnarling(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
});
let site =
index.sites.insert(match &sim_site.kind {
SiteKind::Settlement => {
WorldSite::settlement(Settlement::generate(wpos, Some(ctx.sim), &mut rng))
},
SiteKind::Dungeon => WorldSite::dungeon(site2::Site::generate_dungeon(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::Castle => {
WorldSite::castle(Castle::generate(wpos, Some(ctx.sim), &mut rng))
},
SiteKind::Refactor => WorldSite::refactor(site2::Site::generate_city(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::CliffTown => WorldSite::cliff_town(site2::Site::generate_cliff_town(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::DesertCity => WorldSite::desert_city(
site2::Site::generate_desert_city(&Land::from_sim(ctx.sim), &mut rng, wpos),
),
SiteKind::Tree => {
WorldSite::tree(Tree::generate(wpos, &Land::from_sim(ctx.sim), &mut rng))
},
SiteKind::GiantTree => WorldSite::giant_tree(site2::Site::generate_giant_tree(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
SiteKind::Gnarling => WorldSite::gnarling(site2::Site::generate_gnarling(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
)),
});
sim_site.site_tmp = Some(site);
let site_ref = &index.sites[site];
@ -549,6 +554,7 @@ impl Civs {
// TODO: specify SiteKind based on where a suitable location is found
let kind = match ctx.rng.gen_range(0..64) {
0..=10 => SiteKind::CliffTown,
11..=12 => SiteKind::DesertCity,
_ => SiteKind::Refactor,
};
let site = attempt(100, || {
@ -968,6 +974,7 @@ impl Civs {
SiteKind::Refactor
| SiteKind::Settlement
| SiteKind::CliffTown
| SiteKind::DesertCity
| SiteKind::Castle
)
})
@ -976,8 +983,11 @@ impl Civs {
.collect::<Vec<_>>();
nearby.sort_by_key(|(_, dist)| *dist as i32);
if let SiteKind::Refactor | SiteKind::Settlement | SiteKind::CliffTown | SiteKind::Castle =
self.sites[site].kind
if let SiteKind::Refactor
| SiteKind::Settlement
| SiteKind::CliffTown
| SiteKind::DesertCity
| SiteKind::Castle = self.sites[site].kind
{
for (nearby, _) in nearby.into_iter().take(5) {
// Find a novel path
@ -1229,6 +1239,7 @@ pub enum SiteKind {
Castle,
Refactor,
CliffTown,
DesertCity,
Tree,
GiantTree,
Gnarling,
@ -1344,6 +1355,11 @@ impl SiteKind {
&& chunk.near_cliffs()
&& suitable_for_town(4.0)
},
SiteKind::DesertCity => {
(0.9..1.0).contains(&chunk.temp)
&& !chunk.near_cliffs()
&& suitable_for_town(4.0)
},
SiteKind::Castle => {
if chunk.tree_density > 0.4 || chunk.river.near_water() || chunk.near_cliffs() {
return false;
@ -1392,7 +1408,10 @@ impl Site {
pub fn is_dungeon(&self) -> bool { matches!(self.kind, SiteKind::Dungeon) }
pub fn is_settlement(&self) -> bool {
matches!(self.kind, SiteKind::Settlement | SiteKind::Refactor)
matches!(
self.kind,
SiteKind::Settlement | SiteKind::Refactor | SiteKind::CliffTown | SiteKind::DesertCity
)
}
pub fn is_castle(&self) -> bool { matches!(self.kind, SiteKind::Castle) }

View File

@ -149,7 +149,7 @@ impl World {
name: site.site_tmp.map(|id| index.sites[id].name().to_string()),
// TODO: Probably unify these, at some point
kind: match &site.kind {
civ::SiteKind::Settlement | civ::SiteKind::Refactor | civ::SiteKind::CliffTown => world_msg::SiteKind::Town,
civ::SiteKind::Settlement | civ::SiteKind::Refactor | civ::SiteKind::CliffTown | civ::SiteKind::DesertCity => world_msg::SiteKind::Town,
civ::SiteKind::Dungeon => world_msg::SiteKind::Dungeon {
difficulty: match site.site_tmp.map(|id| &index.sites[id].kind) {
Some(SiteKind::Dungeon(d)) => d.dungeon_difficulty().unwrap_or(0),

View File

@ -119,9 +119,10 @@ impl Environment {
for site in index.sites.ids() {
let site = &index.sites[site];
match site.kind {
SiteKind::Settlement(_) | SiteKind::Refactor(_) | SiteKind::CliffTown(_) => {
towns += site.economy.pop
},
SiteKind::Settlement(_)
| SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::DesertCity(_) => towns += site.economy.pop,
SiteKind::Dungeon(_) => dungeons += site.economy.pop,
SiteKind::Castle(_) => castles += site.economy.pop,
SiteKind::Tree(_) => (),
@ -383,7 +384,8 @@ mod tests {
kind: match i.kind {
crate::site::SiteKind::Settlement(_)
| crate::site::SiteKind::Refactor(_)
| crate::site::SiteKind::CliffTown(_) => {
| crate::site::SiteKind::CliffTown(_)
| crate::site::SiteKind::DesertCity(_) => {
common::terrain::site::SitesKind::Settlement
},
crate::site::SiteKind::Dungeon(_) => {

View File

@ -66,6 +66,7 @@ pub enum SiteKind {
Refactor(site2::Site),
CliffTown(site2::Site),
Tree(Tree),
DesertCity(site2::Site),
GiantTree(site2::Site),
Gnarling(site2::Site),
}
@ -113,6 +114,13 @@ impl Site {
}
}
pub fn desert_city(dc: site2::Site) -> Self {
Self {
kind: SiteKind::DesertCity(dc),
economy: Economy::default(),
}
}
pub fn tree(t: Tree) -> Self {
Self {
kind: SiteKind::Tree(t),
@ -134,6 +142,7 @@ impl Site {
SiteKind::Castle(c) => c.radius(),
SiteKind::Refactor(s) => s.radius(),
SiteKind::CliffTown(ct) => ct.radius(),
SiteKind::DesertCity(dc) => dc.radius(),
SiteKind::Tree(t) => t.radius(),
SiteKind::GiantTree(gt) => gt.radius(),
SiteKind::Gnarling(g) => g.radius(),
@ -147,6 +156,7 @@ impl Site {
SiteKind::Castle(c) => c.get_origin(),
SiteKind::Refactor(s) => s.origin,
SiteKind::CliffTown(ct) => ct.origin,
SiteKind::DesertCity(dc) => dc.origin,
SiteKind::Tree(t) => t.origin,
SiteKind::GiantTree(gt) => gt.origin,
SiteKind::Gnarling(g) => g.origin,
@ -160,6 +170,7 @@ impl Site {
SiteKind::Castle(c) => c.spawn_rules(wpos),
SiteKind::Refactor(s) => s.spawn_rules(wpos),
SiteKind::CliffTown(ct) => ct.spawn_rules(wpos),
SiteKind::DesertCity(dc) => dc.spawn_rules(wpos),
SiteKind::Tree(t) => t.spawn_rules(wpos),
SiteKind::GiantTree(gt) => gt.spawn_rules(wpos),
SiteKind::Gnarling(g) => g.spawn_rules(wpos),
@ -173,6 +184,7 @@ impl Site {
SiteKind::Castle(c) => c.name(),
SiteKind::Refactor(s) => s.name(),
SiteKind::CliffTown(ct) => ct.name(),
SiteKind::DesertCity(dc) => dc.name(),
SiteKind::Tree(_) => "Giant Tree",
SiteKind::GiantTree(gt) => gt.name(),
SiteKind::Gnarling(g) => g.name(),
@ -184,12 +196,13 @@ impl Site {
site_id: common::trade::SiteId,
) -> Option<common::trade::SiteInformation> {
match &self.kind {
SiteKind::Settlement(_) | SiteKind::Refactor(_) | SiteKind::CliffTown(_) => {
Some(common::trade::SiteInformation {
id: site_id,
unconsumed_stock: self.economy.get_available_stock(),
})
},
SiteKind::Settlement(_)
| SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::DesertCity(_) => Some(common::trade::SiteInformation {
id: site_id,
unconsumed_stock: self.economy.get_available_stock(),
}),
_ => None,
}
}
@ -203,6 +216,7 @@ impl Site {
SiteKind::Castle(c) => c.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
SiteKind::Refactor(s) => s.render(canvas, dynamic_rng),
SiteKind::CliffTown(ct) => ct.render(canvas, dynamic_rng),
SiteKind::DesertCity(dc) => dc.render(canvas, dynamic_rng),
SiteKind::Tree(t) => t.render(canvas, dynamic_rng),
SiteKind::GiantTree(gt) => gt.render(canvas, dynamic_rng),
SiteKind::Gnarling(g) => g.render(canvas, dynamic_rng),
@ -229,6 +243,7 @@ impl Site {
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
SiteKind::Refactor(_) => {},
SiteKind::CliffTown(_) => {},
SiteKind::DesertCity(_) => {},
SiteKind::Tree(_) => {},
SiteKind::GiantTree(gt) => gt.apply_supplement(dynamic_rng, wpos2d, supplement),
SiteKind::Gnarling(g) => g.apply_supplement(dynamic_rng, wpos2d, supplement),
@ -238,7 +253,10 @@ impl Site {
pub fn do_economic_simulation(&self) -> bool {
matches!(
self.kind,
SiteKind::Refactor(_) | SiteKind::CliffTown(_) | SiteKind::Settlement(_)
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::DesertCity(_)
| SiteKind::Settlement(_)
)
}
}

View File

@ -623,8 +623,8 @@ impl<'a, R: Rng> NameGen<'a, R> {
self.generate_theme_from_parts(&start, &middle, &vowel, &end)
}
// arabic inspired location names for cliff towns
pub fn generate_cliff_town(mut self) -> String {
// arabic inspired location names for clifftown and desertcity
pub fn generate_arabic(mut self) -> String {
let start = [
"zor", "el", "mas", "yaz", "ra", "boh", "mah", "ah", "lam", "mak", "mol", "wa", "bisk",
"moj", "bis", "ay", "sha", "rez", "bakh", "ta", "je", "ki", "mos", "asj", "meh",

View File

@ -747,7 +747,7 @@ impl Site {
let mut site = Site {
origin,
name: NameGen::location(&mut rng).generate_cliff_town(),
name: NameGen::location(&mut rng).generate_arabic(),
..Site::default()
};
@ -787,6 +787,100 @@ impl Site {
site
}
pub fn generate_desert_city(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
let mut rng = reseed(rng);
let mut site = Site {
origin,
name: NameGen::location(&mut rng).generate_arabic(),
..Site::default()
};
site.demarcate_obstacles(land);
site.make_plaza(land, &mut rng);
let build_chance = Lottery::from(vec![(20.0, 1), (10.0, 2)]);
let mut temples = 0;
for _ in 0..30 {
match *build_chance.choose_seeded(rng.gen()) {
// DesertCityMultiplot
1 => {
let size = (9.0 + rng.gen::<f32>().powf(5.0) * 1.5).round() as u32;
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
site.find_roadside_aabr(
&mut rng,
8..(size + 1).pow(2),
Extent2::broadcast(size),
)
}) {
let desert_city_multi_plot = plot::DesertCityMultiPlot::generate(
land,
&mut reseed(&mut rng),
&site,
door_tile,
door_dir,
aabr,
);
let desert_city_multi_plot_alt = desert_city_multi_plot.alt;
let plot = site.create_plot(Plot {
kind: PlotKind::DesertCityMultiPlot(desert_city_multi_plot),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
seed: rng.gen(),
});
site.blit_aabr(aabr, Tile {
kind: TileKind::Building,
plot: Some(plot),
hard_alt: Some(desert_city_multi_plot_alt),
});
} else {
site.make_plaza(land, &mut rng);
}
},
// DesertCityTemple
2 if temples < 1 => {
let size = (9.0 + rng.gen::<f32>().powf(5.0) * 1.5).round() as u32;
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
site.find_roadside_aabr(
&mut rng,
8..(size + 1).pow(2),
Extent2::broadcast(size),
)
}) {
let desert_city_temple = plot::DesertCityTemple::generate(
land,
&mut reseed(&mut rng),
&site,
door_tile,
door_dir,
aabr,
);
let desert_city_temple_alt = desert_city_temple.alt;
let plot = site.create_plot(Plot {
kind: PlotKind::DesertCityTemple(desert_city_temple),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
seed: rng.gen(),
});
site.blit_aabr(aabr, Tile {
kind: TileKind::Building,
plot: Some(plot),
hard_alt: Some(desert_city_temple_alt),
});
temples += 1;
}
},
_ => {},
}
}
site
}
pub fn wpos_tile_pos(&self, wpos2d: Vec2<i32>) -> Vec2<i32> {
(wpos2d - self.origin).map(|e| e.div_euclid(TILE_SIZE as i32))
}
@ -1035,6 +1129,12 @@ impl Site {
PlotKind::Gnarling(gnarling) => gnarling.render_collect(self, canvas),
PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas),
PlotKind::CliffTower(cliff_tower) => cliff_tower.render_collect(self, canvas),
PlotKind::DesertCityMultiPlot(desert_city_multi_plot) => {
desert_city_multi_plot.render_collect(self, canvas)
},
PlotKind::DesertCityTemple(desert_city_temple) => {
desert_city_temple.render_collect(self, canvas)
},
_ => continue,
};

View File

@ -1,5 +1,7 @@
mod castle;
mod cliff_tower;
mod desert_city_multiplot;
mod desert_city_temple;
pub mod dungeon;
mod giant_tree;
mod gnarling;
@ -7,7 +9,8 @@ mod house;
mod workshop;
pub use self::{
castle::Castle, cliff_tower::CliffTower, dungeon::Dungeon, giant_tree::GiantTree,
castle::Castle, cliff_tower::CliffTower, desert_city_multiplot::DesertCityMultiPlot,
desert_city_temple::DesertCityTemple, dungeon::Dungeon, giant_tree::GiantTree,
gnarling::GnarlingFortification, house::House, workshop::Workshop,
};
@ -47,6 +50,8 @@ impl Plot {
pub enum PlotKind {
House(House),
Workshop(Workshop),
DesertCityMultiPlot(DesertCityMultiPlot),
DesertCityTemple(DesertCityTemple),
Plaza,
Castle(Castle),
Road(Path<Vec2<i32>>),

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,679 @@
use super::*;
use crate::{
util::{RandomField, Sampler},
Land,
};
use common::terrain::{Block, BlockKind};
use rand::prelude::*;
use std::sync::Arc;
use vek::*;
/// Represents house data generated by the `generate()` method
pub struct DesertCityTemple {
/// Axis aligned bounding region for the house
bounds: Aabr<i32>,
/// Approximate altitude of the door tile
pub(crate) alt: i32,
}
impl DesertCityTemple {
pub fn generate(
land: &Land,
_rng: &mut impl Rng,
site: &Site,
door_tile: Vec2<i32>,
door_dir: Vec2<i32>,
tile_aabr: Aabr<i32>,
) -> Self {
let bounds = Aabr {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
Self {
bounds,
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32,
}
}
}
impl Structure for DesertCityTemple {
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) {
let sandstone = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 37 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
_ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
})
}));
let sandstone_broken = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 42 {
0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
_ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
})
}));
let base = self.alt + 1;
let center = self.bounds.center();
let diameter =
10 + (self.bounds.max.x - self.bounds.min.x).min(self.bounds.max.y - self.bounds.min.y);
// Fence
painter
.aabb(Aabb {
min: (self.bounds.min + 1).with_z(base - 20),
max: (self.bounds.max).with_z(base + 2),
})
.without(painter.aabb(Aabb {
min: (self.bounds.min + 2).with_z(base - 20),
max: (self.bounds.max - 1).with_z(base + 2),
}))
.fill(sandstone_broken);
painter
.aabb(Aabb {
min: Vec2::new(self.bounds.min.x + 1, center.y - 8).with_z(base),
max: Vec2::new(self.bounds.max.x, center.y + 8).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 7, self.bounds.min.y + 1).with_z(base),
max: Vec2::new(center.x + 9, self.bounds.max.y).with_z(base + 7),
})
.clear();
// Foundation
painter
.aabb(Aabb {
min: (self.bounds.min + 1).with_z(base - 20),
max: (self.bounds.max).with_z(base),
})
.fill(sandstone.clone());
// Temple
let temple_color = match (RandomField::new(0).get((center - 3).with_z(base))) % 2 {
0 => Fill::Brick(BlockKind::Rock, Rgb::new(100, 101, 250), 3),
_ => Fill::Brick(BlockKind::Rock, Rgb::new(63, 49, 63), 24),
};
let temple_size = diameter / 3;
let floaty_block = Fill::Brick(BlockKind::GlowingWeakRock, Rgb::new(253, 240, 149), 2);
let temple = Aabb {
min: (center - temple_size).with_z(base),
max: (center + temple_size - 1).with_z(base + temple_size + 1),
};
// temple with roof carve out
painter.aabb(temple).fill(sandstone.clone());
// roof decoration
painter
.aabb(Aabb {
min: (center - temple_size - 1).with_z(base + temple_size + 1),
max: (center + temple_size).with_z(base + temple_size + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (center - temple_size).with_z(base + temple_size + 2),
max: (center + temple_size - 1).with_z(base + temple_size + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size - 1, center.y - (temple_size / 4) - 2)
.with_z(base + temple_size + 3),
max: Vec2::new(center.x + temple_size, center.y + (temple_size / 4) + 1)
.with_z(base + temple_size + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - (temple_size / 4) - 2, center.y - temple_size - 1)
.with_z(base + temple_size + 3),
max: Vec2::new(center.x + (temple_size / 4) + 1, center.y + temple_size)
.with_z(base + temple_size + 4),
})
.clear();
// roof carve out
painter
.aabb(Aabb {
min: (center - temple_size + 1).with_z(base + temple_size),
max: (center + temple_size - 2).with_z(base + temple_size + 3),
})
.clear();
//corner pillars
for dir in SQUARE_4 {
let corner_pos = center - temple_size;
let pillar_center = corner_pos + (dir * ((2 * temple_size) - 1));
// Pillar foot
painter
.aabb(Aabb {
min: (pillar_center - 4).with_z(base),
max: (pillar_center + 4).with_z(base + 4),
})
.fill(sandstone.clone());
// Pillar
painter
.aabb(Aabb {
min: (pillar_center - 3).with_z(base + 4),
max: (pillar_center + 3).with_z(base + temple_size + 3),
})
.fill(sandstone.clone());
// Pillar Top
painter
.aabb(Aabb {
min: (pillar_center - 4).with_z(base + temple_size + 3),
max: (pillar_center + 4).with_z(base + temple_size + 6),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: (pillar_center - 3).with_z(base + temple_size + 4),
max: (pillar_center + 3).with_z(base + temple_size + 6),
})
.clear();
// clear parts of pillar top for roof carve out
painter
.aabb(Aabb {
min: (center - temple_size).with_z(base + temple_size + 3),
max: (center + temple_size - 1).with_z(base + temple_size + 6),
})
.clear()
}
// temple decor carve out
// apply three carve options (horizontal, vertical, none) with two spread
// options (for horizontal and vertical)
for s in 0..2 {
// decor carve out style
let spread_select = ((RandomField::new(0).get((center - 1).with_z(base))) % 2) as i32;
let spread = 3 * spread_select;
let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
match carve_style {
//vertical
0 => {
// decor carve outs1
for c in 0..(temple_size - 5) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size + 5 + (2 * c),
center.y - temple_size,
)
.with_z(base + 2),
max: Vec2::new(
center.x - temple_size + 6 + (2 * c),
center.y + temple_size - 1,
)
.with_z(base + temple_size - 1),
})
.clear();
}
for c in 0..(temple_size - 5) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size,
center.y - temple_size + 5 + (2 * c),
)
.with_z(base + 2),
max: Vec2::new(
center.x + temple_size - 1,
center.y - temple_size + 6 + (2 * c),
)
.with_z(base + temple_size - 1),
})
.clear();
}
},
1 => {
// horizontal
for c in 0..((temple_size / 2) - 2) {
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 5, center.y - temple_size)
.with_z(base + 2 + ((spread + 2) * c)),
max: Vec2::new(
center.x + temple_size - 6,
center.y + temple_size - 1,
)
.with_z(base + 3 + ((spread + 2) * c) + spread_select),
})
.clear();
}
for c in 0..((temple_size / 2) - 2) {
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - temple_size + 5)
.with_z(base + 2 + ((spread + 2) * c)),
max: Vec2::new(
center.x + temple_size - 1,
center.y + temple_size - 6,
)
.with_z(base + 3 + ((spread + 2) * c) + spread_select),
})
.clear();
}
},
_ => {},
}
}
// color inlays1
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
})
.without(
painter.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 3)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 4)
.with_z(base + temple_size - 1),
}),
)
.fill(temple_color.clone());
// color inlays2
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 2, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 3, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
})
.without(
painter.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 3, center.y - temple_size + 2)
.with_z(base + 2),
max: Vec2::new(center.x + temple_size - 4, center.y + temple_size - 3)
.with_z(base + temple_size - 1),
}),
)
.fill(temple_color.clone());
// carve outside plane1
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 6, center.y - temple_size).with_z(base + 3),
max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 1)
.with_z(base + temple_size - 2),
})
.without(
painter.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 6, center.y - temple_size + 1)
.with_z(base + 3),
max: Vec2::new(center.x + temple_size - 7, center.y + temple_size - 2)
.with_z(base + temple_size - 2),
}),
)
.clear();
// carve outside plane2
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - temple_size + 6).with_z(base + 3),
max: Vec2::new(center.x + temple_size - 1, center.y + temple_size - 7)
.with_z(base + temple_size - 2),
})
.without(
painter.aabb(Aabb {
min: Vec2::new(center.x - temple_size + 1, center.y - temple_size + 6)
.with_z(base + 3),
max: Vec2::new(center.x + temple_size - 2, center.y + temple_size - 7)
.with_z(base + temple_size - 2),
}),
)
.clear();
// Temple top
painter
.sphere(Aabb {
min: (center - temple_size + 3).with_z(base),
max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 6),
})
.without(painter.aabb(Aabb {
min: (center - temple_size + 2).with_z(base + 1),
max: (center + temple_size - 3).with_z(base + temple_size - 3),
}))
.without(painter.aabb(Aabb {
min: (center - temple_size + 1).with_z(base),
max: (center + temple_size - 1).with_z(base + temple_size),
}))
// carve temple top
.without(painter.sphere(Aabb {
min: (center - temple_size + 5).with_z(base + 2),
max: (center + temple_size - 6).with_z(base + (2 * temple_size) - 8),
}))
.fill(sandstone.clone());
// temple top decoration
// apply two decoration options (horizontal, vertical, none) with two spread
// options for hor/ver options
for s in 0..2 {
let top = painter
.sphere(Aabb {
min: (center - temple_size + 3).with_z(base),
max: (center + temple_size - 4).with_z(base + (2 * temple_size) - 6),
})
.without(painter.sphere(Aabb {
min: (center - temple_size + 5).with_z(base + 2),
max: (center + temple_size - 6).with_z(base + (2 * temple_size) - 8),
}))
.without(painter.aabb(Aabb {
min: (center - temple_size + 1).with_z(base),
max: (center + temple_size - 2).with_z(base + temple_size + 1),
}));
// decor carve out style
let spread_select =
((RandomField::new(0).get((center - 1 - s).with_z(base))) % 2) as i32;
let spread = 3 * spread_select;
let carve_style = ((RandomField::new(0).get((center - 2 - s).with_z(base))) % 3) as i32;
match carve_style {
//vertical
0 => {
// decor carve outs1
for c in 0..(temple_size - 2) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size + 2 + ((spread + 2) * c),
center.y - temple_size,
)
.with_z(base + temple_size),
max: Vec2::new(
center.x - temple_size + 3 + ((spread + 2) * c) + spread_select,
center.y + temple_size - 1,
)
.with_z(base + (2 * temple_size)),
})
.intersect(top)
.fill(temple_color.clone());
}
},
1 => {
for c in 0..(temple_size - 2) {
painter
.aabb(Aabb {
min: Vec2::new(
center.x - temple_size,
center.y - temple_size + 2 + ((spread + 2) * c),
)
.with_z(base + temple_size),
max: Vec2::new(
center.x + temple_size - 1,
center.y - temple_size + 3 + ((spread + 2) * c) + spread_select,
)
.with_z(base + (2 * temple_size)),
})
.intersect(top)
.fill(temple_color.clone());
}
},
_ => {},
}
}
// round or rectangle entries
let entry_select = ((RandomField::new(0).get((center + 1).with_z(base))) % 2) as i32;
match entry_select {
0 => {
//round Temple entries1
painter
.aabb(Aabb {
min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 4, center.y - temple_size).with_z(base + 4),
max: Vec2::new(center.x + 3, center.y + temple_size - 1).with_z(base + 7),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 4),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base + 7),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 7),
max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 9),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - 2, center.y - temple_size).with_z(base + 9),
max: Vec2::new(center.x + 1, center.y + temple_size - 1).with_z(base + 10),
})
.fill(sandstone.clone());
// round Temple entries2
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 4),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 4),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 4).with_z(base + 4),
max: Vec2::new(center.x + temple_size - 1, center.y + 3).with_z(base + 7),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 4),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 7),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base + 7),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 7),
max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 9),
})
.clear();
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 2).with_z(base + 9),
max: Vec2::new(center.x + temple_size - 1, center.y + 1).with_z(base + 10),
})
.fill(sandstone.clone());
},
_ => {
//rectangle Temple entries1
painter
.aabb(Aabb {
min: Vec2::new(center.x - 5, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 4, center.y + temple_size - 1).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - 3, center.y - temple_size).with_z(base),
max: Vec2::new(center.x + 2, center.y + temple_size - 1).with_z(base + 6),
})
.clear();
//rectangle Temple entries1
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 5).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 4).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.aabb(Aabb {
min: Vec2::new(center.x - temple_size, center.y - 3).with_z(base),
max: Vec2::new(center.x + temple_size - 1, center.y + 2).with_z(base + 6),
})
.clear();
},
}
// Temple Top Socket
painter
.cylinder(Aabb {
min: (center - temple_size + 3).with_z(base + temple_size),
max: (center + temple_size - 4).with_z(base + temple_size + 1),
})
.without(painter.cylinder(Aabb {
min: (center - temple_size + 5).with_z(base + temple_size),
max: (center + temple_size - 6).with_z(base + temple_size + 1),
}))
.fill(sandstone.clone());
// carve temple
painter
.aabb(Aabb {
min: (center - temple_size + 4).with_z(base),
max: (center + temple_size - 5).with_z(base + temple_size - 1),
})
.clear();
// carve round opening to dome
painter
.cylinder(Aabb {
min: (center - temple_size + 6).with_z(base + temple_size - 1),
max: (center + temple_size - 7).with_z(base + temple_size),
})
.clear();
// floating sculpture, placeholder for sun god
painter
.sphere(Aabb {
min: (center - 3).with_z(base),
max: (center + 2).with_z(base + 5),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 4),
max: (center + 2).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 4).with_z(base + 8),
max: (center + 3).with_z(base + 13),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 4).with_z(base + 14),
max: (center + 3).with_z(base + 15),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 16),
max: (center + 2).with_z(base + 21),
})
.fill(floaty_block.clone());
// floating sculptures
for dir in SQUARE_4 {
let corner_pos = center - temple_size / 2;
let sclpt_center = corner_pos + (dir * (temple_size));
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base),
max: (sclpt_center + 1).with_z(base + 3),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base + 2),
max: (sclpt_center + 1).with_z(base + 5),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 3).with_z(base + 5),
max: (sclpt_center + 2).with_z(base + 6),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 3).with_z(base + 7),
max: (sclpt_center + 2).with_z(base + 8),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (sclpt_center - 2).with_z(base + 9),
max: (sclpt_center + 1).with_z(base + 12),
})
.fill(floaty_block.clone());
}
// floating sculpture, placeholder for sun god
painter
.sphere(Aabb {
min: (center - 3).with_z(base),
max: (center + 2).with_z(base + 5),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 4),
max: (center + 2).with_z(base + 9),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 4).with_z(base + 8),
max: (center + 3).with_z(base + 13),
})
.fill(sandstone.clone());
painter
.sphere(Aabb {
min: (center - 4).with_z(base + 14),
max: (center + 3).with_z(base + 15),
})
.fill(sandstone);
painter
.sphere(Aabb {
min: (center - 3).with_z(base + 16),
max: (center + 2).with_z(base + 21),
})
.fill(floaty_block);
}
}

View File

@ -54,6 +54,13 @@ pub const DIRS: [Vec2<i32>; 8] = [
Vec2::new(1, -1),
];
pub const DIAGONALS: [Vec2<i32>; 4] = [
Vec2::new(-1, -1),
Vec2::new(1, -1),
Vec2::new(-1, 1),
Vec2::new(1, 1),
];
pub const NEIGHBORS: [Vec2<i32>; 8] = [
Vec2::new(1, 0),
Vec2::new(1, 1),