mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Tavern room layout
This commit is contained in:
parent
63e500d3d8
commit
ecb85a0534
@ -113,6 +113,7 @@ impl Data {
|
||||
PlotKind::House(_)
|
||||
| PlotKind::Workshop(_)
|
||||
| PlotKind::AirshipDock(_)
|
||||
| PlotKind::Tavern(_)
|
||||
| PlotKind::Plaza
|
||||
| PlotKind::SavannahPit(_)
|
||||
| PlotKind::SavannahHut(_)
|
||||
|
@ -539,6 +539,7 @@ impl Civs {
|
||||
let size = Lerp::lerp(0.03, 1.0, rng.gen_range(0.0..1f32).powi(5));
|
||||
WorldSite::refactor(site2::Site::generate_city(
|
||||
&Land::from_sim(ctx.sim),
|
||||
index_ref,
|
||||
&mut rng,
|
||||
wpos,
|
||||
size,
|
||||
|
@ -573,7 +573,13 @@ impl Site {
|
||||
}
|
||||
|
||||
// Size is 0..1
|
||||
pub fn generate_city(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>, size: f32) -> Self {
|
||||
pub fn generate_city(
|
||||
land: &Land,
|
||||
index: IndexRef,
|
||||
rng: &mut impl Rng,
|
||||
origin: Vec2<i32>,
|
||||
size: f32,
|
||||
) -> Self {
|
||||
let mut rng = reseed(rng);
|
||||
|
||||
let mut site = Site {
|
||||
@ -587,12 +593,13 @@ impl Site {
|
||||
site.make_plaza(land, &mut rng);
|
||||
|
||||
let build_chance = Lottery::from(vec![
|
||||
(64.0, 1),
|
||||
(5.0, 2),
|
||||
(8.0, 3),
|
||||
(5.0, 4),
|
||||
(5.0, 5),
|
||||
(15.0, 6),
|
||||
// (64.0, 1),
|
||||
// (5.0, 2),
|
||||
// (8.0, 3),
|
||||
// (5.0, 4),
|
||||
// (5.0, 5),
|
||||
// (15.0, 6),
|
||||
(15.0, 7),
|
||||
]);
|
||||
|
||||
let mut castles = 0;
|
||||
@ -917,6 +924,42 @@ impl Site {
|
||||
}
|
||||
}
|
||||
},
|
||||
7 if size > 0.125 => {
|
||||
let size = (3.5 + rng.gen::<f32>().powf(5.0) * 2.0).round() as u32;
|
||||
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
|
||||
site.find_roadside_aabr(
|
||||
&mut rng,
|
||||
7..(size + 1).pow(2),
|
||||
Extent2::broadcast(size),
|
||||
)
|
||||
}) {
|
||||
let tavern = plot::Tavern::generate(
|
||||
land,
|
||||
index,
|
||||
&mut reseed(&mut rng),
|
||||
&site,
|
||||
door_tile,
|
||||
Dir::from_vector(door_dir),
|
||||
aabr,
|
||||
);
|
||||
let tavern_alt = tavern.door_wpos.z;
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::Tavern(tavern),
|
||||
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(tavern_alt),
|
||||
});
|
||||
workshops += 1;
|
||||
} else {
|
||||
site.make_plaza(land, &mut rng);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
@ -1824,6 +1867,7 @@ impl Site {
|
||||
let (prim_tree, fills, mut entities) = match &self.plots[plot].kind {
|
||||
PlotKind::House(house) => house.render_collect(self, canvas),
|
||||
PlotKind::AirshipDock(airship_dock) => airship_dock.render_collect(self, canvas),
|
||||
PlotKind::Tavern(tavern) => tavern.render_collect(self, canvas),
|
||||
PlotKind::CoastalHouse(coastal_house) => coastal_house.render_collect(self, canvas),
|
||||
PlotKind::CoastalWorkshop(coastal_workshop) => {
|
||||
coastal_workshop.render_collect(self, canvas)
|
||||
@ -1963,7 +2007,19 @@ impl Site {
|
||||
}
|
||||
|
||||
pub fn test_site() -> Site {
|
||||
Site::generate_city(&Land::empty(), &mut thread_rng(), Vec2::zero(), 0.5)
|
||||
let index = crate::index::Index::new(0);
|
||||
let index_ref = IndexRef {
|
||||
colors: &index.colors(),
|
||||
features: &index.features(),
|
||||
index: &index,
|
||||
};
|
||||
Site::generate_city(
|
||||
&Land::empty(),
|
||||
index_ref,
|
||||
&mut thread_rng(),
|
||||
Vec2::zero(),
|
||||
0.5,
|
||||
)
|
||||
}
|
||||
|
||||
fn wpos_is_hazard(land: &Land, wpos: Vec2<i32>) -> Option<HazardKind> {
|
||||
|
@ -22,6 +22,7 @@ mod savannah_hut;
|
||||
mod savannah_pit;
|
||||
mod savannah_workshop;
|
||||
mod sea_chapel;
|
||||
mod tavern;
|
||||
mod troll_cave;
|
||||
mod workshop;
|
||||
|
||||
@ -34,7 +35,7 @@ pub use self::{
|
||||
gnarling::GnarlingFortification, house::House, jungle_ruin::JungleRuin,
|
||||
pirate_hideout::PirateHideout, rock_circle::RockCircle, savannah_hut::SavannahHut,
|
||||
savannah_pit::SavannahPit, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel,
|
||||
troll_cave::TrollCave, workshop::Workshop,
|
||||
tavern::Tavern, troll_cave::TrollCave, workshop::Workshop,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@ -77,6 +78,7 @@ impl Plot {
|
||||
pub enum PlotKind {
|
||||
House(House),
|
||||
AirshipDock(AirshipDock),
|
||||
Tavern(Tavern),
|
||||
CoastalHouse(CoastalHouse),
|
||||
CoastalWorkshop(CoastalWorkshop),
|
||||
Workshop(Workshop),
|
||||
|
535
world/src/site2/plot/tavern.rs
Normal file
535
world/src/site2/plot/tavern.rs
Normal file
@ -0,0 +1,535 @@
|
||||
use std::{mem::swap, ops::RangeInclusive};
|
||||
|
||||
use common::{
|
||||
lottery::Lottery,
|
||||
store::{Id, Store},
|
||||
terrain::{Block, BlockKind},
|
||||
};
|
||||
use enum_map::EnumMap;
|
||||
use fxhash::hash;
|
||||
use rand::Rng;
|
||||
use strum::{EnumIter, IntoEnumIterator};
|
||||
use vek::*;
|
||||
|
||||
use crate::{
|
||||
site2::{Dir, Fill, Site, Structure},
|
||||
IndexRef, Land,
|
||||
};
|
||||
|
||||
type Neighbor = Option<Id<Room>>;
|
||||
|
||||
struct Wall {
|
||||
start: Vec2<i32>,
|
||||
end: Vec2<i32>,
|
||||
base_alt: i32,
|
||||
top_alt: i32,
|
||||
from: Neighbor,
|
||||
to: Neighbor,
|
||||
out_dir: Dir,
|
||||
door: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, EnumIter, enum_map::Enum)]
|
||||
enum RoomKind {
|
||||
Garden,
|
||||
StageRoom,
|
||||
BarRoom,
|
||||
EntranceRoom,
|
||||
}
|
||||
|
||||
impl RoomKind {
|
||||
/// Returns the (side length size range, area size range)
|
||||
fn size_range(&self) -> (RangeInclusive<i32>, RangeInclusive<i32>) {
|
||||
match self {
|
||||
RoomKind::Garden => (4..=20, 25..=250),
|
||||
RoomKind::StageRoom => (10..=20, 130..=400),
|
||||
RoomKind::BarRoom => (7..=14, 56..=196),
|
||||
RoomKind::EntranceRoom => (3..=10, 9..=50),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Room {
|
||||
/// Inclusive
|
||||
bounds: Aabb<i32>,
|
||||
kind: RoomKind,
|
||||
// stairs: Option<Id<Stairs>>,
|
||||
// walls: Vec<Wall>,
|
||||
}
|
||||
|
||||
struct Stairs {
|
||||
end: Vec2<i32>,
|
||||
dir: Dir,
|
||||
in_room: Id<Room>,
|
||||
to_room: Id<Room>,
|
||||
}
|
||||
|
||||
pub struct Tavern {
|
||||
rooms: Store<Room>,
|
||||
stairs: Store<Stairs>,
|
||||
walls: Store<Wall>,
|
||||
/// Tile position of the door tile
|
||||
pub door_tile: Vec2<i32>,
|
||||
pub(crate) door_wpos: Vec3<i32>,
|
||||
/// Axis aligned bounding region for the house
|
||||
bounds: Aabr<i32>,
|
||||
}
|
||||
|
||||
impl Tavern {
|
||||
pub fn generate(
|
||||
land: &Land,
|
||||
index: IndexRef,
|
||||
rng: &mut impl Rng,
|
||||
site: &Site,
|
||||
door_tile: Vec2<i32>,
|
||||
door_dir: Dir,
|
||||
tile_aabr: Aabr<i32>,
|
||||
) -> Self {
|
||||
let mut rooms = Store::default();
|
||||
let stairs = Store::default();
|
||||
let mut walls = Store::default();
|
||||
let mut room_counts = EnumMap::<RoomKind, u32>::default();
|
||||
|
||||
let bounds = Aabr {
|
||||
min: site.tile_wpos(tile_aabr.min),
|
||||
max: site.tile_wpos(tile_aabr.max),
|
||||
};
|
||||
|
||||
let ibounds = Aabr {
|
||||
min: bounds.min + 1,
|
||||
max: bounds.max - 2,
|
||||
};
|
||||
|
||||
let door_tile_center = site.tile_center_wpos(door_tile);
|
||||
let door_wpos = door_dir.select_aabr_with(ibounds, door_tile_center);
|
||||
|
||||
let door_alt = land
|
||||
.column_sample(door_wpos, index)
|
||||
.map_or_else(|| land.get_alt_approx(door_wpos), |sample| sample.alt);
|
||||
let door_wpos = door_wpos.with_z(door_alt.ceil() as i32);
|
||||
|
||||
/// Place room in bounds.
|
||||
fn place_room_in(
|
||||
room: RoomKind,
|
||||
max_bounds: Aabr<i32>,
|
||||
in_dir: Dir,
|
||||
in_pos: Vec2<i32>,
|
||||
rng: &mut impl Rng,
|
||||
) -> Option<Aabr<i32>> {
|
||||
let (size_range, area_range) = room.size_range();
|
||||
|
||||
let mut gen_range = |min, max, snap_max| {
|
||||
let res = rng.gen_range(min..=max);
|
||||
if snap_max <= max && snap_max - res <= 2 {
|
||||
snap_max
|
||||
} else {
|
||||
res
|
||||
}
|
||||
};
|
||||
let min = *size_range.start();
|
||||
let snap_max = in_dir.select(max_bounds.size());
|
||||
let max = snap_max.min(*size_range.end());
|
||||
if max < min {
|
||||
return None;
|
||||
}
|
||||
let size_x = gen_range(min, max, snap_max);
|
||||
|
||||
let min = ((*area_range.start() + size_x - 1) / size_x).max(*size_range.start());
|
||||
let snap_max = in_dir.orthogonal().select(max_bounds.size());
|
||||
let max = snap_max
|
||||
.min(*size_range.end())
|
||||
.min(*area_range.end() / size_x);
|
||||
|
||||
if max < min {
|
||||
return None;
|
||||
}
|
||||
let size_y = gen_range(min, max, snap_max);
|
||||
|
||||
// calculate a valid aabr
|
||||
let half_size_y = size_y / 2 + (size_y % 2) * rng.gen_range(0..=1);
|
||||
let min = in_pos + in_dir.to_vec2() + in_dir.rotated_cw().to_vec2() * half_size_y;
|
||||
let min = max_bounds.projected_point(min);
|
||||
let max = min + in_dir.to_vec2() * size_x + in_dir.rotated_ccw().to_vec2() * size_y;
|
||||
let max = max_bounds.projected_point(max);
|
||||
let min = max - in_dir.to_vec2() * size_x + in_dir.rotated_cw().to_vec2() * size_y;
|
||||
|
||||
let bounds = Aabr { min, max }.made_valid();
|
||||
Some(bounds)
|
||||
}
|
||||
struct RoomMeta {
|
||||
id: Id<Room>,
|
||||
walls: Vec<Dir>,
|
||||
}
|
||||
|
||||
let mut room_metas = Vec::new();
|
||||
|
||||
{
|
||||
let entrance_rooms =
|
||||
Lottery::from(vec![(1.0, RoomKind::Garden), (2.0, RoomKind::EntranceRoom)]);
|
||||
|
||||
let entrance_room = *entrance_rooms.choose_seeded(rng.gen());
|
||||
let entrance_room_hgt = rng.gen_range(3..=4);
|
||||
let entrance_room_aabr =
|
||||
place_room_in(entrance_room, ibounds, -door_dir, door_wpos.xy(), rng)
|
||||
.expect("Not enough room in plot for a tavern");
|
||||
let entrance_room_aabb = Aabb {
|
||||
min: entrance_room_aabr.min.with_z(door_wpos.z),
|
||||
max: entrance_room_aabr
|
||||
.max
|
||||
.with_z(door_wpos.z + entrance_room_hgt),
|
||||
}
|
||||
.made_valid();
|
||||
|
||||
let entrance_id = rooms.insert(Room {
|
||||
bounds: entrance_room_aabb,
|
||||
kind: entrance_room,
|
||||
});
|
||||
|
||||
let start = door_dir.select_aabr_with(
|
||||
entrance_room_aabr,
|
||||
Vec2::broadcast(door_dir.rotated_cw().select_aabr(entrance_room_aabr)),
|
||||
) + door_dir.rotated_cw().to_vec2()
|
||||
+ door_dir.to_vec2();
|
||||
walls.insert(Wall {
|
||||
start,
|
||||
end: door_dir.select_aabr_with(
|
||||
entrance_room_aabr,
|
||||
Vec2::broadcast(door_dir.rotated_ccw().select_aabr(entrance_room_aabr)),
|
||||
) + door_dir.rotated_ccw().to_vec2()
|
||||
+ door_dir.to_vec2(),
|
||||
base_alt: entrance_room_aabb.min.z,
|
||||
top_alt: entrance_room_aabb.max.z,
|
||||
from: None,
|
||||
to: Some(entrance_id),
|
||||
out_dir: -door_dir,
|
||||
door: Some(door_dir.rotated_cw().select(door_wpos.xy() - start).abs()),
|
||||
});
|
||||
|
||||
room_metas.push(RoomMeta {
|
||||
id: entrance_id,
|
||||
walls: Dir::iter()
|
||||
.filter(|d| *d != door_dir)
|
||||
// .map(|d| {
|
||||
// let a = d.rotated_cw().select_aabr(entrance_room_aabr);
|
||||
// let b = d.rotated_ccw().select_aabr(entrance_room_aabr);
|
||||
// (d, a.min(b)..=a.max(b))
|
||||
// })
|
||||
.collect(),
|
||||
});
|
||||
|
||||
room_counts[entrance_room] += 1;
|
||||
}
|
||||
|
||||
let to_aabr = |aabb: Aabb<i32>| Aabr {
|
||||
min: aabb.min.xy(),
|
||||
max: aabb.max.xy(),
|
||||
};
|
||||
'room_gen: while room_metas.len() > 0 {
|
||||
let mut room_meta = room_metas.swap_remove(rng.gen_range(0..room_metas.len()));
|
||||
if room_meta.walls.is_empty() {
|
||||
continue 'room_gen;
|
||||
}
|
||||
let in_dir = room_meta
|
||||
.walls
|
||||
.swap_remove(rng.gen_range(0..room_meta.walls.len()));
|
||||
|
||||
let right = in_dir.orthogonal();
|
||||
let left = -right;
|
||||
|
||||
let from_id = room_meta.id;
|
||||
let from_room = &rooms[from_id];
|
||||
|
||||
if !room_meta.walls.is_empty() {
|
||||
room_metas.push(room_meta);
|
||||
}
|
||||
|
||||
let from_bounds = to_aabr(from_room.bounds);
|
||||
|
||||
// The maximum bounds, limited by the plot bounds and other rooms.
|
||||
let mut max_bounds = Aabr {
|
||||
min: in_dir.select_aabr_with(from_bounds, ibounds.min) + in_dir.to_vec2() * 2,
|
||||
max: in_dir.select_aabr_with(ibounds, ibounds.max),
|
||||
}
|
||||
.made_valid();
|
||||
|
||||
// Take other rooms into account when calculating `max_bounds`. We don't care
|
||||
// about this room if it's the originating room or at another
|
||||
// height.
|
||||
for (_, room) in rooms.iter().filter(|(room_id, room)| {
|
||||
*room_id != from_id
|
||||
&& room.bounds.min.z <= from_room.bounds.max.z
|
||||
&& room.bounds.max.z >= from_room.bounds.min.z
|
||||
}) {
|
||||
let mut bounds = to_aabr(room.bounds);
|
||||
bounds.min -= 2;
|
||||
bounds.max += 2;
|
||||
let intersection = bounds.intersection(max_bounds);
|
||||
if intersection.is_valid() {
|
||||
let Some(bounds) = Dir::iter()
|
||||
.filter(|dir| {
|
||||
*dir != in_dir
|
||||
&& dir.select_aabr(intersection) * dir.signum()
|
||||
< dir.select_aabr(max_bounds) * dir.signum()
|
||||
})
|
||||
.map(|min_dir| {
|
||||
Aabr {
|
||||
min: min_dir.select_aabr_with(
|
||||
max_bounds,
|
||||
Vec2::broadcast(min_dir.rotated_ccw().select_aabr(max_bounds)),
|
||||
),
|
||||
max: min_dir.select_aabr_with(
|
||||
intersection,
|
||||
Vec2::broadcast(min_dir.rotated_cw().select_aabr(max_bounds)),
|
||||
),
|
||||
}
|
||||
.made_valid()
|
||||
})
|
||||
.filter(|bounds| {
|
||||
left.select_aabr(*bounds) < right.select_aabr(from_bounds)
|
||||
&& right.select_aabr(*bounds) > left.select_aabr(from_bounds)
|
||||
})
|
||||
.max_by_key(|bounds| bounds.size().product())
|
||||
else {
|
||||
continue 'room_gen;
|
||||
};
|
||||
|
||||
max_bounds = bounds;
|
||||
}
|
||||
}
|
||||
|
||||
// the smallest side on the maximum bounds
|
||||
let max_min_size = max_bounds.size().reduce_min();
|
||||
// max bounds area
|
||||
let max_area = max_bounds.size().product();
|
||||
|
||||
let room_lottery = RoomKind::iter()
|
||||
// Filter out rooms that won't fit here.
|
||||
.filter(|room_kind| {
|
||||
let (size_range, area_range) = room_kind.size_range();
|
||||
*size_range.start() <= max_min_size && *area_range.start() <= max_area
|
||||
})
|
||||
// Calculate chance for each room.
|
||||
.map(|room_kind| {
|
||||
(
|
||||
match room_kind {
|
||||
RoomKind::Garden => {
|
||||
1.0 / (1.0 + room_counts[RoomKind::Garden] as f32 / 2.0)
|
||||
},
|
||||
RoomKind::StageRoom => {
|
||||
2.0 / (1.0 + room_counts[RoomKind::StageRoom] as f32).powi(2)
|
||||
},
|
||||
RoomKind::BarRoom => {
|
||||
2.0 / (1.0 + room_counts[RoomKind::BarRoom] as f32).powi(2)
|
||||
},
|
||||
RoomKind::EntranceRoom => {
|
||||
0.1 / (1.0 + room_counts[RoomKind::EntranceRoom] as f32)
|
||||
},
|
||||
},
|
||||
room_kind,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// We have no rooms to pick from.
|
||||
if room_lottery.is_empty() {
|
||||
continue 'room_gen;
|
||||
}
|
||||
|
||||
// Pick a room.
|
||||
let room_lottery = Lottery::from(room_lottery);
|
||||
let room = *room_lottery.choose_seeded(rng.gen());
|
||||
|
||||
// Select a door position
|
||||
let mut min = left
|
||||
.select_aabr(from_bounds)
|
||||
.max(left.select_aabr(max_bounds));
|
||||
let mut max = right
|
||||
.select_aabr(from_bounds)
|
||||
.min(right.select_aabr(max_bounds));
|
||||
if max < min {
|
||||
swap(&mut min, &mut max);
|
||||
}
|
||||
if min + 2 > max {
|
||||
continue 'room_gen;
|
||||
}
|
||||
let in_pos = rng.gen_range(min + 1..=max - 1);
|
||||
let in_pos =
|
||||
in_dir.select_aabr_with(from_bounds, Vec2::broadcast(in_pos)) + in_dir.to_vec2();
|
||||
|
||||
let Some(bounds) = place_room_in(room, max_bounds, in_dir, in_pos, rng) else {
|
||||
continue 'room_gen;
|
||||
};
|
||||
|
||||
let room_hgt = rng.gen_range(3..=5);
|
||||
|
||||
let bounds3 = Aabb {
|
||||
min: bounds.min.with_z(from_room.bounds.min.z),
|
||||
max: bounds.max.with_z(from_room.bounds.min.z + room_hgt),
|
||||
};
|
||||
let id = rooms.insert(Room {
|
||||
bounds: bounds3,
|
||||
kind: room,
|
||||
});
|
||||
|
||||
let start = in_dir.select_aabr_with(
|
||||
from_bounds,
|
||||
Vec2::broadcast(left.select_aabr(from_bounds).max(left.select_aabr(bounds))),
|
||||
) + in_dir.to_vec2()
|
||||
+ left.to_vec2();
|
||||
|
||||
let end = in_dir.select_aabr_with(
|
||||
from_bounds,
|
||||
Vec2::broadcast(
|
||||
right
|
||||
.select_aabr(from_bounds)
|
||||
.min(right.select_aabr(bounds)),
|
||||
),
|
||||
) + in_dir.to_vec2()
|
||||
+ right.to_vec2();
|
||||
|
||||
walls.insert(Wall {
|
||||
start,
|
||||
end,
|
||||
base_alt: bounds3.min.z,
|
||||
top_alt: bounds3.max.z,
|
||||
from: Some(from_id),
|
||||
to: Some(id),
|
||||
out_dir: in_dir,
|
||||
door: Some(right.select(in_pos - start)),
|
||||
});
|
||||
|
||||
room_metas.push(RoomMeta {
|
||||
id,
|
||||
walls: Dir::iter().filter(|d| *d != -in_dir).collect(),
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
rooms,
|
||||
stairs,
|
||||
walls,
|
||||
door_tile,
|
||||
door_wpos,
|
||||
bounds,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn aabb(mut aabb: Aabb<i32>) -> Aabb<i32> {
|
||||
aabb.make_valid();
|
||||
aabb.max += 1;
|
||||
aabb
|
||||
}
|
||||
|
||||
impl Structure for Tavern {
|
||||
#[cfg(feature = "use-dyn-lib")]
|
||||
const UPDATE_FN: &'static [u8] = b"render_tavern\0";
|
||||
|
||||
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_tavern")]
|
||||
fn render_inner(&self, _site: &Site, _land: &Land, painter: &crate::site2::Painter) {
|
||||
let bounds = Aabr {
|
||||
min: self.bounds.min,
|
||||
max: self.bounds.max - 1,
|
||||
};
|
||||
|
||||
let stone = Fill::Brick(BlockKind::Rock, Rgb::new(70, 70, 70), 10);
|
||||
let wood = Fill::Block(Block::new(BlockKind::Wood, Rgb::new(106, 73, 64)));
|
||||
|
||||
painter
|
||||
.aabb(aabb(Aabb {
|
||||
min: bounds.min.with_z(self.door_wpos.z - 10),
|
||||
max: bounds.max.with_z(self.door_wpos.z - 1),
|
||||
}))
|
||||
.fill(stone.clone());
|
||||
|
||||
for (id, room) in self.rooms.iter() {
|
||||
painter.aabb(aabb(room.bounds)).clear();
|
||||
let hash = hash(&id).to_le_bytes();
|
||||
painter
|
||||
.aabb(aabb(Aabb {
|
||||
min: room.bounds.min.with_z(room.bounds.min.z - 1),
|
||||
max: room.bounds.max.with_z(room.bounds.min.z - 1),
|
||||
}))
|
||||
.fill(Fill::Block(Block::new(
|
||||
BlockKind::Wood,
|
||||
Rgb::new(hash[0], hash[1], hash[2]),
|
||||
)));
|
||||
}
|
||||
|
||||
for (_, wall) in self.walls.iter() {
|
||||
let get_kind = |room| self.rooms.get(room).kind;
|
||||
let wall_aabb = Aabb {
|
||||
min: wall.start.with_z(wall.base_alt),
|
||||
max: wall.end.with_z(wall.top_alt),
|
||||
};
|
||||
match (wall.from.map(get_kind), wall.to.map(get_kind)) {
|
||||
(Some(RoomKind::Garden), Some(RoomKind::Garden) | None)
|
||||
| (None, Some(RoomKind::Garden)) => {
|
||||
let hgt = wall_aabb.min.z..=wall_aabb.max.z;
|
||||
painter
|
||||
.column(wall_aabb.min.xy(), hgt.clone())
|
||||
.fill(wood.clone());
|
||||
painter.column(wall_aabb.max.xy(), hgt).fill(wood.clone());
|
||||
painter
|
||||
.aabb(aabb(Aabb {
|
||||
min: wall_aabb.min,
|
||||
max: wall_aabb.max.with_z(wall_aabb.min.z),
|
||||
}))
|
||||
.fill(wood.clone());
|
||||
},
|
||||
(None, None) => {},
|
||||
_ => {
|
||||
painter.aabb(aabb(wall_aabb)).fill(wood.clone());
|
||||
},
|
||||
}
|
||||
let wall_dir = Dir::from_vector(wall.end - wall.start);
|
||||
if let Some(door) = wall.door {
|
||||
let door_pos = wall.start + wall_dir.to_vec2() * door;
|
||||
let min = match wall.from {
|
||||
None => door_pos - wall.out_dir.to_vec2(),
|
||||
Some(_) => door_pos,
|
||||
};
|
||||
let max = match wall.to {
|
||||
None => door_pos + wall.out_dir.to_vec2(),
|
||||
Some(_) => door_pos,
|
||||
};
|
||||
painter
|
||||
.aabb(aabb(Aabb {
|
||||
min: min.with_z(wall.base_alt),
|
||||
max: max.with_z(wall.base_alt + 2),
|
||||
}))
|
||||
.clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (_, stairs) in self.stairs.iter() {
|
||||
let down_room = &self.rooms[stairs.in_room];
|
||||
let up_room = &self.rooms[stairs.to_room];
|
||||
|
||||
let down = -stairs.dir;
|
||||
let right = stairs.dir.rotated_cw();
|
||||
|
||||
let aabr = Aabr {
|
||||
min: stairs.end - right.to_vec2()
|
||||
+ down.to_vec2() * (up_room.bounds.min.z - 1 - down_room.bounds.min.z),
|
||||
max: stairs.end + right.to_vec2(),
|
||||
};
|
||||
|
||||
painter
|
||||
.aabb(aabb(Aabb {
|
||||
min: aabr.min.with_z(up_room.bounds.min.z - 1),
|
||||
max: aabr.max.with_z(up_room.bounds.min.z - 1),
|
||||
}))
|
||||
.clear();
|
||||
|
||||
painter
|
||||
.ramp(
|
||||
aabb(Aabb {
|
||||
min: aabr.min.with_z(down_room.bounds.min.z),
|
||||
max: aabr.max.with_z(up_room.bounds.min.z - 1),
|
||||
}),
|
||||
stairs.dir,
|
||||
)
|
||||
.fill(wood.clone());
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ use rand::Rng;
|
||||
use vek::*;
|
||||
|
||||
/// A 2d direction.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, enum_map::Enum, strum::EnumIter)]
|
||||
pub enum Dir {
|
||||
X,
|
||||
Y,
|
||||
|
Loading…
Reference in New Issue
Block a user