mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
savannah_hut
This commit is contained in:
parent
e71eee0cd2
commit
22854cbea2
@ -113,7 +113,15 @@ impl Data {
|
||||
let matches_buildings = (|kind: &PlotKind| {
|
||||
matches!(
|
||||
kind,
|
||||
PlotKind::House(_) | PlotKind::Workshop(_) | PlotKind::Plaza
|
||||
PlotKind::House(_)
|
||||
| PlotKind::Workshop(_)
|
||||
| PlotKind::Plaza
|
||||
| PlotKind::SavannahPit(_)
|
||||
| PlotKind::SavannahHut(_)
|
||||
| PlotKind::SavannahWorkshop(_)
|
||||
| PlotKind::CliffTower(_)
|
||||
| PlotKind::DesertCityMultiPlot(_)
|
||||
| PlotKind::DesertCityTemple(_)
|
||||
)
|
||||
}) as _;
|
||||
let matches_plazas = (|kind: &PlotKind| matches!(kind, PlotKind::Plaza)) as _;
|
||||
|
@ -330,7 +330,7 @@ impl Civs {
|
||||
SiteKind::Castle => (16i32, 5.0),
|
||||
SiteKind::Refactor => (32i32, 10.0),
|
||||
SiteKind::CliffTown => (32i32, 10.0),
|
||||
SiteKind::SavannahPit => (36i32, 20.0),
|
||||
SiteKind::SavannahPit => (48i32, 25.0),
|
||||
SiteKind::DesertCity => (64i32, 25.0),
|
||||
SiteKind::ChapelSite => (36i32, 10.0),
|
||||
SiteKind::Tree => (12i32, 8.0),
|
||||
|
@ -893,6 +893,11 @@ impl Site {
|
||||
name: NameGen::location(&mut rng).generate_savannah_custom(),
|
||||
..Site::default()
|
||||
};
|
||||
|
||||
site.demarcate_obstacles(land);
|
||||
|
||||
site.make_plaza(land, &mut rng);
|
||||
|
||||
let size = 11.0 as i32;
|
||||
let aabr = Aabr {
|
||||
min: Vec2::broadcast(-size),
|
||||
@ -915,6 +920,86 @@ impl Site {
|
||||
hard_alt: Some(savannah_pit_alt),
|
||||
});
|
||||
}
|
||||
|
||||
let build_chance = Lottery::from(vec![(38.0, 1), (7.0, 2)]);
|
||||
|
||||
for _ in 0..45 {
|
||||
match *build_chance.choose_seeded(rng.gen()) {
|
||||
1 => {
|
||||
// SavannahHut
|
||||
|
||||
let size = (4.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,
|
||||
4..(size + 1).pow(2),
|
||||
Extent2::broadcast(size),
|
||||
)
|
||||
}) {
|
||||
let savannah_hut = plot::SavannahHut::generate(
|
||||
land,
|
||||
&mut reseed(&mut rng),
|
||||
&site,
|
||||
door_tile,
|
||||
door_dir,
|
||||
aabr,
|
||||
);
|
||||
let savannah_hut_alt = savannah_hut.alt;
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::SavannahHut(savannah_hut),
|
||||
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(savannah_hut_alt),
|
||||
});
|
||||
} else {
|
||||
site.make_plaza(land, &mut rng);
|
||||
}
|
||||
},
|
||||
2 => {
|
||||
// SavannahWorkshop
|
||||
|
||||
let size = (4.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,
|
||||
4..(size + 1).pow(2),
|
||||
Extent2::broadcast(size),
|
||||
)
|
||||
}) {
|
||||
let savannah_workshop = plot::SavannahWorkshop::generate(
|
||||
land,
|
||||
&mut reseed(&mut rng),
|
||||
&site,
|
||||
door_tile,
|
||||
door_dir,
|
||||
aabr,
|
||||
);
|
||||
let savannah_workshop_alt = savannah_workshop.alt;
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::SavannahWorkshop(savannah_workshop),
|
||||
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(savannah_workshop_alt),
|
||||
});
|
||||
} else {
|
||||
site.make_plaza(land, &mut rng);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
site
|
||||
}
|
||||
|
||||
@ -1382,6 +1467,10 @@ impl Site {
|
||||
PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas),
|
||||
PlotKind::CliffTower(cliff_tower) => cliff_tower.render_collect(self, canvas),
|
||||
PlotKind::SavannahPit(savannah_pit) => savannah_pit.render_collect(self, canvas),
|
||||
PlotKind::SavannahHut(savannah_hut) => savannah_hut.render_collect(self, canvas),
|
||||
PlotKind::SavannahWorkshop(savannah_workshop) => {
|
||||
savannah_workshop.render_collect(self, canvas)
|
||||
},
|
||||
PlotKind::DesertCityMultiPlot(desert_city_multi_plot) => {
|
||||
desert_city_multi_plot.render_collect(self, canvas)
|
||||
},
|
||||
|
@ -9,7 +9,9 @@ pub mod dungeon;
|
||||
mod giant_tree;
|
||||
mod gnarling;
|
||||
mod house;
|
||||
mod savannah_hut;
|
||||
mod savannah_pit;
|
||||
mod savannah_workshop;
|
||||
mod sea_chapel;
|
||||
mod workshop;
|
||||
|
||||
@ -17,8 +19,9 @@ pub use self::{
|
||||
adlet::AdletStronghold, bridge::Bridge, castle::Castle, citadel::Citadel,
|
||||
cliff_tower::CliffTower, desert_city_multiplot::DesertCityMultiPlot,
|
||||
desert_city_temple::DesertCityTemple, dungeon::Dungeon, giant_tree::GiantTree,
|
||||
gnarling::GnarlingFortification, house::House, savannah_pit::SavannahPit,
|
||||
sea_chapel::SeaChapel, workshop::Workshop,
|
||||
gnarling::GnarlingFortification, house::House, savannah_hut::SavannahHut,
|
||||
savannah_pit::SavannahPit, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel,
|
||||
workshop::Workshop,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@ -74,5 +77,7 @@ pub enum PlotKind {
|
||||
CliffTower(CliffTower),
|
||||
Citadel(Citadel),
|
||||
SavannahPit(SavannahPit),
|
||||
SavannahHut(SavannahHut),
|
||||
SavannahWorkshop(SavannahWorkshop),
|
||||
Bridge(Bridge),
|
||||
}
|
||||
|
@ -883,16 +883,6 @@ impl Structure for CliffTower {
|
||||
))
|
||||
.fill(brick.clone());
|
||||
}
|
||||
// spawn mountaineers in each room
|
||||
let spawn_pos = super_center.with_z(floor_level + 4);
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 4;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.mountaineer", &mut rng),
|
||||
);
|
||||
}
|
||||
}
|
||||
// vary next storey
|
||||
length += -1;
|
||||
|
266
world/src/site2/plot/savannah_hut.rs
Normal file
266
world/src/site2/plot/savannah_hut.rs
Normal file
@ -0,0 +1,266 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
util::{RandomField, Sampler, CARDINALS, DIAGONALS},
|
||||
Land,
|
||||
};
|
||||
use common::terrain::{BlockKind, SpriteKind};
|
||||
use rand::prelude::*;
|
||||
use std::{f32::consts::TAU, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
/// Represents house data generated by the `generate()` method
|
||||
pub struct SavannahHut {
|
||||
/// Tile position of the door tile
|
||||
pub door_tile: Vec2<i32>,
|
||||
/// Axis aligned bounding region for the house
|
||||
bounds: Aabr<i32>,
|
||||
/// Approximate altitude of the door tile
|
||||
pub(crate) alt: i32,
|
||||
}
|
||||
|
||||
impl SavannahHut {
|
||||
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 door_tile_pos = site.tile_center_wpos(door_tile);
|
||||
let bounds = Aabr {
|
||||
min: site.tile_wpos(tile_aabr.min),
|
||||
max: site.tile_wpos(tile_aabr.max),
|
||||
};
|
||||
Self {
|
||||
bounds,
|
||||
door_tile: door_tile_pos,
|
||||
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32 + 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for SavannahHut {
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"render_savannahhut\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_savannahhut")]
|
||||
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
|
||||
let base = self.alt + 1;
|
||||
let center = self.bounds.center();
|
||||
let sprite_fill = Fill::Sampling(Arc::new(|wpos| {
|
||||
Some(match (RandomField::new(0).get(wpos)) % 25 {
|
||||
0 => Block::air(SpriteKind::Bowl),
|
||||
1 => Block::air(SpriteKind::VialEmpty),
|
||||
2 => Block::air(SpriteKind::Lantern),
|
||||
3 => Block::air(SpriteKind::JugArabic),
|
||||
4 => Block::air(SpriteKind::Crate),
|
||||
_ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
|
||||
})
|
||||
}));
|
||||
let wood_dark = Fill::Brick(BlockKind::Misc, Rgb::new(142, 67, 27), 12);
|
||||
let reed = Fill::Brick(BlockKind::Misc, Rgb::new(72, 55, 46), 22);
|
||||
let clay = Fill::Brick(BlockKind::Misc, Rgb::new(209, 124, 57), 22);
|
||||
let color = Fill::Sampling(Arc::new(|center| {
|
||||
Some(match (RandomField::new(0).get(center)) % 7 {
|
||||
0 => Block::new(BlockKind::GlowingRock, Rgb::new(153, 82, 40)),
|
||||
1 => Block::new(BlockKind::GlowingRock, Rgb::new(172, 104, 57)),
|
||||
2 => Block::new(BlockKind::GlowingRock, Rgb::new(135, 106, 100)),
|
||||
3 => Block::new(BlockKind::GlowingRock, Rgb::new(198, 164, 139)),
|
||||
4 => Block::new(BlockKind::GlowingRock, Rgb::new(168, 163, 157)),
|
||||
5 => Block::new(BlockKind::GlowingRock, Rgb::new(73, 53, 42)),
|
||||
_ => Block::new(BlockKind::GlowingRock, Rgb::new(178, 124, 90)),
|
||||
})
|
||||
}));
|
||||
let length = (10 + RandomField::new(0).get(center.with_z(base)) % 6) as i32;
|
||||
let height = 2 * length / 3;
|
||||
let storeys = (1 + RandomField::new(0).get(center.with_z(base)) % 2) as i32;
|
||||
let radius = length + (length / 3);
|
||||
let reed_var = (1 + RandomField::new(0).get(center.with_z(base)) % 4) as f32;
|
||||
let reed_parts = 36_f32 + reed_var;
|
||||
let phi = TAU / reed_parts;
|
||||
// roof cone
|
||||
painter
|
||||
.cone(Aabb {
|
||||
min: (center - radius).with_z(base + (storeys * height) - (height / 2) + 1),
|
||||
max: (center + radius)
|
||||
.with_z(base + (storeys * height) + (height / 2) - 1 + reed_var as i32),
|
||||
})
|
||||
.fill(reed.clone());
|
||||
painter
|
||||
.cone(Aabb {
|
||||
min: (center - radius).with_z(base + (storeys * height) - (height / 2)),
|
||||
max: (center + radius)
|
||||
.with_z(base + (storeys * height) + (height / 2) - 2 + reed_var as i32),
|
||||
})
|
||||
.clear();
|
||||
// foundation
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length).with_z(base - 3),
|
||||
max: (center + length + 1).with_z(base - 2),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 1).with_z(base - 4),
|
||||
max: (center + length + 2).with_z(base - 3),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 2).with_z(base - 5),
|
||||
max: (center + length + 3).with_z(base - 4),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 3).with_z(base - height),
|
||||
max: (center + length + 4).with_z(base - 5),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
// room
|
||||
for s in 0..storeys {
|
||||
let room = painter.cylinder(Aabb {
|
||||
min: (center - length + 2 + s).with_z(base - 2 + (s * height)),
|
||||
max: (center + 1 + length - 2 - s).with_z(base + height + (s * height)),
|
||||
});
|
||||
room.fill(clay.clone());
|
||||
// decor inlays
|
||||
for dir in DIAGONALS {
|
||||
let decor_pos = center + dir * (length - 2 - s);
|
||||
let decor = painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
decor_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
5.0,
|
||||
)
|
||||
.intersect(room);
|
||||
decor.fill(color.clone());
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
decor_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
4.0,
|
||||
)
|
||||
.intersect(decor)
|
||||
.fill(clay.clone());
|
||||
}
|
||||
}
|
||||
// clear rooms
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base - 2),
|
||||
max: (center + 1 + length - 4).with_z(base + (storeys * height)),
|
||||
})
|
||||
.clear();
|
||||
// wood decor
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base - 1),
|
||||
max: (center + 1 + length - 4).with_z(base),
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base),
|
||||
max: (center + 1 + length - 4).with_z(base + 1),
|
||||
})
|
||||
.fill(sprite_fill);
|
||||
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base + (storeys * height) - 1),
|
||||
max: (center + 1 + length - 4).with_z(base + (storeys * height) + 1),
|
||||
})
|
||||
.fill(wood_dark);
|
||||
|
||||
for s in 0..storeys {
|
||||
// entries, windows
|
||||
for dir in CARDINALS {
|
||||
let frame_pos = center + dir * (length - 2 - s);
|
||||
let clear_pos = center + dir * (length + 2 - s);
|
||||
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
frame_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
3.0,
|
||||
)
|
||||
.fill(color.clone());
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
clear_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
2.0,
|
||||
)
|
||||
.clear();
|
||||
}
|
||||
}
|
||||
// re clear room
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 5).with_z(base - 2),
|
||||
max: (center + 1 + length - 5).with_z(base + (storeys * height) + 1),
|
||||
})
|
||||
.clear();
|
||||
// floor
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (length / 2) - 1).with_z(base - 3),
|
||||
max: (center + (length / 2) + 1).with_z(base - 2),
|
||||
})
|
||||
.fill(color);
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (length / 2) + 1).with_z(base - 3),
|
||||
max: (center + (length / 2) - 1).with_z(base - 2),
|
||||
})
|
||||
.fill(clay);
|
||||
|
||||
// furniture
|
||||
let mut sprites = vec![
|
||||
SpriteKind::DrawerSmall,
|
||||
SpriteKind::ChairSingle,
|
||||
SpriteKind::CoatRack,
|
||||
SpriteKind::Bed,
|
||||
SpriteKind::WardrobeSingle,
|
||||
SpriteKind::CushionArabic,
|
||||
SpriteKind::TableArabicSmall,
|
||||
SpriteKind::DecorSetArabic,
|
||||
SpriteKind::Bowl,
|
||||
SpriteKind::VialEmpty,
|
||||
SpriteKind::JugArabic,
|
||||
SpriteKind::JugAndBowlArabic,
|
||||
SpriteKind::SepareArabic,
|
||||
];
|
||||
let rows = if length > 12 { 2 } else { 1 };
|
||||
'outer: for d in 0..rows {
|
||||
for dir in DIAGONALS {
|
||||
if sprites.is_empty() {
|
||||
break 'outer;
|
||||
}
|
||||
let position = center + dir * (length - (9 + (d * 3)));
|
||||
let sprite = sprites.swap_remove(
|
||||
RandomField::new(0).get(position.with_z(base)) as usize % sprites.len(),
|
||||
);
|
||||
painter.sprite(position.with_z(base - 2), sprite);
|
||||
}
|
||||
}
|
||||
|
||||
// reed roof lines
|
||||
for n in 1..=reed_parts as i32 {
|
||||
let pos = Vec2::new(
|
||||
center.x + ((radius as f32) * ((n as f32 * phi).cos())) as i32,
|
||||
center.y + ((radius as f32) * ((n as f32 * phi).sin())) as i32,
|
||||
);
|
||||
painter
|
||||
.line(
|
||||
pos.with_z(base + (storeys * height) - (height / 2)),
|
||||
center.with_z(base + (storeys * height) + (height / 2) + reed_var as i32),
|
||||
1.0,
|
||||
)
|
||||
.fill(reed.clone());
|
||||
}
|
||||
}
|
||||
}
|
@ -284,6 +284,135 @@ impl Structure for SavannahPit {
|
||||
max: (center + length).with_z(base - (2 * length)),
|
||||
})
|
||||
.clear();
|
||||
// floor -1 donut room & floor -2 donut room
|
||||
let rooms_clear = painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length)),
|
||||
max: (center + (4 * length)).with_z(base - length - 1),
|
||||
})
|
||||
.union(painter.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length)),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) - 1),
|
||||
}));
|
||||
|
||||
let rooms = painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (2 * length) - 2).with_z(base - (2 * length)),
|
||||
max: (center + (2 * length) + 2).with_z(base - length - 1),
|
||||
})
|
||||
.union(painter.cylinder(Aabb {
|
||||
min: (center - length - 2).with_z(base - (3 * length)),
|
||||
max: (center + length + 2).with_z(base - (2 * length) - 1),
|
||||
}));
|
||||
rooms_clear.without(rooms).clear();
|
||||
|
||||
// floor 0 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (3 * length)).with_z(base - length + (length / 2) - 3),
|
||||
max: (center + (3 * length)).with_z(base - length + (length / 2) - 2),
|
||||
})
|
||||
.fill(wood_light.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (3 * length) + 1).with_z(base - length + (length / 2) - 3),
|
||||
max: (center + (3 * length) - 1).with_z(base - length + (length / 2) - 2),
|
||||
})
|
||||
.clear();
|
||||
// floor -1 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
})
|
||||
.fill(wood_light.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length) - 1).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
})
|
||||
.clear();
|
||||
// floor -1 wood ring sprites
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
})
|
||||
.fill(sprite_fill.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length) - 1).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
})
|
||||
.clear();
|
||||
// floor -1 center decor ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (2 * length) - 2).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (2 * length) + 2).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
})
|
||||
.fill(color.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (2 * length)).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (2 * length)).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
})
|
||||
.clear();
|
||||
// floor -1 room entry
|
||||
let room1_entry_pos = Vec2::new(center.x, center.y - (2 * length));
|
||||
painter
|
||||
.sphere(Aabb {
|
||||
min: (room1_entry_pos - 5).with_z(base - (2 * length)),
|
||||
max: (room1_entry_pos + 5).with_z(base - (2 * length) + 5),
|
||||
})
|
||||
.clear();
|
||||
// floor -2 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length)).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
})
|
||||
.fill(wood_light.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length) - 1).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
})
|
||||
.clear();
|
||||
// floor -2 wood ring sprites
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length)).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
})
|
||||
.fill(sprite_fill.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length) - 1).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
})
|
||||
.clear();
|
||||
// floor -2 center decor ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 2).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + length + 2).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
})
|
||||
.fill(color);
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + length).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
})
|
||||
.clear();
|
||||
// floor -2 room entry
|
||||
let room2_entry_pos = Vec2::new(center.x, center.y - length);
|
||||
painter
|
||||
.sphere(Aabb {
|
||||
min: (room2_entry_pos - 5).with_z(base - (3 * length)),
|
||||
max: (room2_entry_pos + 5).with_z(base - (3 * length) + 5),
|
||||
})
|
||||
.clear();
|
||||
|
||||
// floor stairs lamps
|
||||
for dir in SQUARE_4 {
|
||||
@ -391,8 +520,8 @@ impl Structure for SavannahPit {
|
||||
.fill(wood_dark.clone());
|
||||
let stair_radius2 = ((2 * length) + 1) as f32;
|
||||
let stairs_clear2 = painter.prim(Primitive::Cylinder(Aabb {
|
||||
min: (center - (3 * length)).with_z(base - (3 * length)),
|
||||
max: (center + (3 * length)).with_z(base - (2 * length)),
|
||||
min: (center - length).with_z(base - (3 * length)),
|
||||
max: (center + length).with_z(base - (2 * length)),
|
||||
}));
|
||||
painter
|
||||
.prim(Primitive::sampling(
|
||||
@ -405,101 +534,6 @@ impl Structure for SavannahPit {
|
||||
),
|
||||
))
|
||||
.fill(wood_dark.clone());
|
||||
// floor -1 donut room
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length)),
|
||||
max: (center + (4 * length)).with_z(base - length - 1),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (2 * length) - 2).with_z(base - (2 * length)),
|
||||
max: (center + (2 * length) + 2).with_z(base - length - 1),
|
||||
}))
|
||||
.clear();
|
||||
// floor -1 room entry
|
||||
let room1_entry_pos = Vec2::new(center.x, center.y - (2 * length));
|
||||
painter
|
||||
.sphere(Aabb {
|
||||
min: (room1_entry_pos - 5).with_z(base - (2 * length)),
|
||||
max: (room1_entry_pos + 5).with_z(base - (2 * length) + 5),
|
||||
})
|
||||
.clear();
|
||||
|
||||
// floor -2 donut room
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length)),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) - 1),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - length - 2).with_z(base - (3 * length)),
|
||||
max: (center + length + 2).with_z(base - (2 * length) - 1),
|
||||
}))
|
||||
.clear();
|
||||
// floor -2 room entry
|
||||
let room2_entry_pos = Vec2::new(center.x, center.y - length);
|
||||
painter
|
||||
.sphere(Aabb {
|
||||
min: (room2_entry_pos - 5).with_z(base - (3 * length)),
|
||||
max: (room2_entry_pos + 5).with_z(base - (3 * length) + 5),
|
||||
})
|
||||
.clear();
|
||||
// floor 0 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (3 * length)).with_z(base - length + (length / 2) - 3),
|
||||
max: (center + (3 * length)).with_z(base - length + (length / 2) - 2),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (3 * length) + 1).with_z(base - length + (length / 2) - 3),
|
||||
max: (center + (3 * length) - 1).with_z(base - length + (length / 2) - 2),
|
||||
}))
|
||||
.fill(wood_light.clone());
|
||||
// floor -1 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (2 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length) - 1).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
}))
|
||||
.fill(wood_light.clone());
|
||||
// floor -2 wood ring
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length)).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (3 * length) + (length / 2) - 3),
|
||||
max: (center + (4 * length) - 1).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
}))
|
||||
.fill(wood_light.clone());
|
||||
// floor -1 wood ring sprites
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length)).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (2 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length) - 1).with_z(base - (2 * length) + (length / 2) - 1),
|
||||
}))
|
||||
.fill(sprite_fill.clone());
|
||||
// floor -2 wood ring sprites
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (4 * length)).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length)).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
})
|
||||
.without(painter.cylinder(Aabb {
|
||||
min: (center - (4 * length) + 1).with_z(base - (3 * length) + (length / 2) - 2),
|
||||
max: (center + (4 * length) - 1).with_z(base - (3 * length) + (length / 2) - 1),
|
||||
}))
|
||||
.fill(sprite_fill.clone());
|
||||
|
||||
// top wood cone
|
||||
painter
|
||||
.cone(Aabb {
|
||||
@ -597,16 +631,6 @@ impl Structure for SavannahPit {
|
||||
max: (entries_clear + 2).with_z(base - ((1 + f) * length) + 4),
|
||||
})
|
||||
.clear();
|
||||
// villagers in each room
|
||||
let spawn_pos = (room_center - 3).with_z(base - ((1 + f) * length));
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
}
|
||||
// outside platforms
|
||||
painter
|
||||
@ -642,16 +666,6 @@ impl Structure for SavannahPit {
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
}
|
||||
// villagers on platforms
|
||||
let spawn_pos = (room_center - 2).with_z(base + length + 2);
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
let lantern_pos = center + dir * ((4 * length) - (length / 4) + 4);
|
||||
painter.sprite(lantern_pos.with_z(base + length + 1), SpriteKind::Lantern);
|
||||
}
|
||||
@ -698,16 +712,6 @@ impl Structure for SavannahPit {
|
||||
max: (entries_clear + 3).with_z(base - ((1 + f) * length) + 4),
|
||||
})
|
||||
.clear();
|
||||
// villagers in each room
|
||||
let spawn_pos = (room_center - 3).with_z(base - ((1 + f) * length));
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
// furniture
|
||||
match RandomField::new(0).get(room_center.with_z(base)) % 2 {
|
||||
0 => {
|
||||
@ -815,16 +819,6 @@ impl Structure for SavannahPit {
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
}
|
||||
// villagers on platforms
|
||||
let spawn_pos = (room_center - 2).with_z(base + length + 2);
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
let lantern_pos = center + dir * ((3 * length) - (length / 3) + 4);
|
||||
painter.sprite(lantern_pos.with_z(base + length + 1), SpriteKind::Lantern);
|
||||
}
|
||||
@ -944,18 +938,6 @@ impl Structure for SavannahPit {
|
||||
}
|
||||
}
|
||||
}
|
||||
// villagers outside on every floor
|
||||
for a in 0..5 {
|
||||
let spawn_pos = (center - 5).with_z(base + length - (length * a));
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 4;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// campfire
|
||||
let campfire_pos = (center - 10).with_z(base);
|
||||
@ -1059,13 +1041,6 @@ impl Structure for SavannahPit {
|
||||
max: (crate_pos + 2).with_z(base - (5 * length) + 5),
|
||||
})
|
||||
.clear();
|
||||
// villager and lantern in each stand
|
||||
let spawn_pos = (crate_pos - 1).with_z(base - (5 * length) + 3);
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
painter.sprite(
|
||||
(crate_pos + 1).with_z(base - (5 * length) + 3),
|
||||
SpriteKind::Lantern,
|
||||
@ -1098,16 +1073,6 @@ impl Structure for SavannahPit {
|
||||
// placeholder for market items
|
||||
.fill(Fill::Block(Block::air(SpriteKind::Crate)));
|
||||
}
|
||||
// villagers in market hall
|
||||
let spawn_pos = (center + 10).with_z(base - (5 * length) + 4);
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 12;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.villager", &mut rng),
|
||||
);
|
||||
}
|
||||
// supports
|
||||
for dir in CARDINALS {
|
||||
let outer_support = center + dir * ((4 * length) - 2);
|
||||
@ -1574,16 +1539,6 @@ impl Structure for SavannahPit {
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
}
|
||||
// guards and lanterns on towers
|
||||
let spawn_pos = (tower_center - 2).with_z(base + (length / 2) + 2);
|
||||
let npc_amount = 1 + RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 1..(npc_amount + 1) {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.guard", &mut rng),
|
||||
);
|
||||
}
|
||||
let lantern_pos = tower_center - 3;
|
||||
painter.sprite(lantern_pos.with_z(base + (length / 2)), SpriteKind::Lantern);
|
||||
// tunnel lanterns
|
||||
@ -1643,16 +1598,6 @@ impl Structure for SavannahPit {
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
}
|
||||
// guards and lanterns on towers
|
||||
let spawn_pos = (tower_center - 2).with_z(base + (length / 2) + 2);
|
||||
let npc_amount = 1 + RandomField::new(0).get(spawn_pos) % 3;
|
||||
for _ in 1..(npc_amount + 1) {
|
||||
let mut rng = thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.guard", &mut rng),
|
||||
);
|
||||
}
|
||||
let lantern_pos = center + dir * (7 * wall_length);
|
||||
painter.sprite(lantern_pos.with_z(base + (length / 2)), SpriteKind::Lantern);
|
||||
// tunnel lanterns
|
||||
|
308
world/src/site2/plot/savannah_workshop.rs
Normal file
308
world/src/site2/plot/savannah_workshop.rs
Normal file
@ -0,0 +1,308 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
util::{RandomField, Sampler, CARDINALS, DIAGONALS},
|
||||
Land,
|
||||
};
|
||||
use common::terrain::{BlockKind, SpriteKind};
|
||||
use rand::prelude::*;
|
||||
use std::{f32::consts::TAU, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
/// Represents house data generated by the `generate()` method
|
||||
pub struct SavannahWorkshop {
|
||||
/// Tile position of the door tile
|
||||
pub door_tile: Vec2<i32>,
|
||||
/// Axis aligned bounding region for the house
|
||||
bounds: Aabr<i32>,
|
||||
/// Approximate altitude of the door tile
|
||||
pub(crate) alt: i32,
|
||||
}
|
||||
|
||||
impl SavannahWorkshop {
|
||||
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 door_tile_pos = site.tile_center_wpos(door_tile);
|
||||
let bounds = Aabr {
|
||||
min: site.tile_wpos(tile_aabr.min),
|
||||
max: site.tile_wpos(tile_aabr.max),
|
||||
};
|
||||
Self {
|
||||
bounds,
|
||||
door_tile: door_tile_pos,
|
||||
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32 + 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for SavannahWorkshop {
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"render_savannahworkshop\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_savannahworkshop")]
|
||||
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
|
||||
let base = self.alt + 1;
|
||||
let center = self.bounds.center();
|
||||
let sprite_fill = Fill::Sampling(Arc::new(|wpos| {
|
||||
Some(match (RandomField::new(0).get(wpos)) % 25 {
|
||||
0 => Block::air(SpriteKind::Bowl),
|
||||
1 => Block::air(SpriteKind::VialEmpty),
|
||||
2 => Block::air(SpriteKind::Lantern),
|
||||
3 => Block::air(SpriteKind::JugArabic),
|
||||
4 => Block::air(SpriteKind::Crate),
|
||||
_ => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
|
||||
})
|
||||
}));
|
||||
let wood_dark = Fill::Brick(BlockKind::Misc, Rgb::new(142, 67, 27), 12);
|
||||
let reed = Fill::Brick(BlockKind::Misc, Rgb::new(72, 55, 46), 22);
|
||||
let clay = Fill::Brick(BlockKind::Misc, Rgb::new(209, 124, 57), 22);
|
||||
let color = Fill::Sampling(Arc::new(|center| {
|
||||
Some(match (RandomField::new(0).get(center)) % 7 {
|
||||
0 => Block::new(BlockKind::GlowingRock, Rgb::new(153, 82, 40)),
|
||||
1 => Block::new(BlockKind::GlowingRock, Rgb::new(172, 104, 57)),
|
||||
2 => Block::new(BlockKind::GlowingRock, Rgb::new(135, 106, 100)),
|
||||
3 => Block::new(BlockKind::GlowingRock, Rgb::new(198, 164, 139)),
|
||||
4 => Block::new(BlockKind::GlowingRock, Rgb::new(168, 163, 157)),
|
||||
5 => Block::new(BlockKind::GlowingRock, Rgb::new(73, 53, 42)),
|
||||
_ => Block::new(BlockKind::GlowingRock, Rgb::new(178, 124, 90)),
|
||||
})
|
||||
}));
|
||||
let length = (10 + RandomField::new(0).get(center.with_z(base)) % 6) as i32;
|
||||
let height = 2 * length / 3;
|
||||
let storeys = (1 + RandomField::new(0).get(center.with_z(base)) % 2) as i32;
|
||||
let radius = length + (length / 3);
|
||||
let reed_var = (1 + RandomField::new(0).get(center.with_z(base)) % 4) as f32;
|
||||
let reed_parts = 36_f32 + reed_var;
|
||||
let phi = TAU / reed_parts;
|
||||
// roof cone
|
||||
painter
|
||||
.cone(Aabb {
|
||||
min: (center - radius).with_z(base + (storeys * height) - (height / 2) + 1),
|
||||
max: (center + radius)
|
||||
.with_z(base + (storeys * height) + (height / 2) - 1 + reed_var as i32),
|
||||
})
|
||||
.fill(reed.clone());
|
||||
painter
|
||||
.cone(Aabb {
|
||||
min: (center - radius).with_z(base + (storeys * height) - (height / 2)),
|
||||
max: (center + radius)
|
||||
.with_z(base + (storeys * height) + (height / 2) - 2 + reed_var as i32),
|
||||
})
|
||||
.clear();
|
||||
// foundation
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length).with_z(base - 3),
|
||||
max: (center + length + 1).with_z(base - 2),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 1).with_z(base - 4),
|
||||
max: (center + length + 2).with_z(base - 3),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 2).with_z(base - 5),
|
||||
max: (center + length + 3).with_z(base - 4),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length - 3).with_z(base - height),
|
||||
max: (center + length + 4).with_z(base - 5),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
// room
|
||||
for s in 0..storeys {
|
||||
let room = painter.cylinder(Aabb {
|
||||
min: (center - length + 2 + s).with_z(base - 2 + (s * height)),
|
||||
max: (center + 1 + length - 2 - s).with_z(base + height + (s * height)),
|
||||
});
|
||||
room.fill(clay.clone());
|
||||
// decor inlays
|
||||
for dir in DIAGONALS {
|
||||
let decor_pos = center + dir * (length - 2 - s);
|
||||
let decor = painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
decor_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
5.0,
|
||||
)
|
||||
.intersect(room);
|
||||
decor.fill(color.clone());
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
decor_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
4.0,
|
||||
)
|
||||
.intersect(decor)
|
||||
.fill(clay.clone());
|
||||
}
|
||||
}
|
||||
// clear rooms
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base - 2),
|
||||
max: (center + 1 + length - 4).with_z(base + (storeys * height)),
|
||||
})
|
||||
.clear();
|
||||
// wood decor
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base - 1),
|
||||
max: (center + 1 + length - 4).with_z(base),
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base),
|
||||
max: (center + 1 + length - 4).with_z(base + 1),
|
||||
})
|
||||
.fill(sprite_fill);
|
||||
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 4).with_z(base + (storeys * height) - 1),
|
||||
max: (center + 1 + length - 4).with_z(base + (storeys * height) + 1),
|
||||
})
|
||||
.fill(wood_dark.clone());
|
||||
|
||||
for s in 0..storeys {
|
||||
// entries, windows
|
||||
for dir in CARDINALS {
|
||||
let frame_pos = center + dir * (length - 2 - s);
|
||||
let clear_pos = center + dir * (length + 2 - s);
|
||||
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
frame_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
3.0,
|
||||
)
|
||||
.fill(color.clone());
|
||||
painter
|
||||
.line(
|
||||
center.with_z(base - 1 + (s * (height + 2))),
|
||||
clear_pos.with_z(base - 1 + (s * (height + 2))),
|
||||
2.0,
|
||||
)
|
||||
.clear();
|
||||
}
|
||||
}
|
||||
// re clear room
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - length + 5).with_z(base - 2),
|
||||
max: (center + 1 + length - 5).with_z(base + (storeys * height) + 1),
|
||||
})
|
||||
.clear();
|
||||
// floor
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (length / 2) - 1).with_z(base - 3),
|
||||
max: (center + (length / 2) + 1).with_z(base - 2),
|
||||
})
|
||||
.fill(color);
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - (length / 2) + 1).with_z(base - 3),
|
||||
max: (center + (length / 2) - 1).with_z(base - 2),
|
||||
})
|
||||
.fill(clay.clone());
|
||||
|
||||
// reed roof lines
|
||||
|
||||
for n in 1..=reed_parts as i32 {
|
||||
let pos = Vec2::new(
|
||||
center.x + ((radius as f32) * ((n as f32 * phi).cos())) as i32,
|
||||
center.y + ((radius as f32) * ((n as f32 * phi).sin())) as i32,
|
||||
);
|
||||
painter
|
||||
.line(
|
||||
pos.with_z(base + (storeys * height) - (height / 2)),
|
||||
center.with_z(base + (storeys * height) + (height / 2) + reed_var as i32),
|
||||
1.0,
|
||||
)
|
||||
.fill(reed.clone());
|
||||
}
|
||||
// chimney
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - 3)
|
||||
.with_z(base - 1 + (storeys * height) + (height / 2) + reed_var as i32),
|
||||
max: (center + 4)
|
||||
.with_z(base + (storeys * height) + (height / 2) + reed_var as i32),
|
||||
})
|
||||
.fill(wood_dark);
|
||||
// clear chimney
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - 2).with_z(base + (storeys * height) - 4),
|
||||
max: (center + 3)
|
||||
.with_z(base + 5 * (storeys * height) + (height / 2) + reed_var as i32),
|
||||
})
|
||||
.clear();
|
||||
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (center - 1).with_z(base - 2),
|
||||
max: (center + 2).with_z(base - 1),
|
||||
})
|
||||
.fill(clay);
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: (center).with_z(base - 2),
|
||||
max: (center + 1).with_z(base - 1),
|
||||
})
|
||||
.clear();
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: (center).with_z(base - 3),
|
||||
max: (center + 1).with_z(base - 2),
|
||||
})
|
||||
.fill(Fill::Block(Block::air(SpriteKind::Ember)));
|
||||
|
||||
let mut stations = vec![
|
||||
SpriteKind::CraftingBench,
|
||||
SpriteKind::Forge,
|
||||
SpriteKind::SpinningWheel,
|
||||
SpriteKind::TanningRack,
|
||||
SpriteKind::CookingPot,
|
||||
SpriteKind::Cauldron,
|
||||
SpriteKind::Loom,
|
||||
SpriteKind::Anvil,
|
||||
SpriteKind::DismantlingBench,
|
||||
SpriteKind::RepairBench,
|
||||
];
|
||||
let cr_pos = stations.len() as f32;
|
||||
let phi = TAU / cr_pos;
|
||||
'outer: for d in 0..2 {
|
||||
let dist = 4 + d;
|
||||
for n in 1..=cr_pos as i32 {
|
||||
let pos = Vec2::new(
|
||||
center.x + ((dist as f32) * ((n as f32 * phi).cos())) as i32,
|
||||
center.y + ((dist as f32) * ((n as f32 * phi).sin())) as i32,
|
||||
);
|
||||
if stations.is_empty() {
|
||||
break 'outer;
|
||||
}
|
||||
let cr_station = stations.swap_remove(
|
||||
RandomField::new(0).get(pos.with_z(base)) as usize % stations.len(),
|
||||
);
|
||||
painter.sprite(pos.with_z(base - 2), cr_station);
|
||||
}
|
||||
}
|
||||
|
||||
painter.spawn(
|
||||
EntityInfo::at((center).with_z(base - 2).map(|e| e as f32 + 0.5)).into_waypoint(),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user