1use super::*;
2use crate::{
3 Land,
4 site2::util::Dir,
5 util::{DIRS, RandomField, Sampler},
6};
7use common::{
8 calendar::{Calendar, CalendarEvent},
9 terrain::{Block, BlockKind, SpriteKind},
10};
11use rand::prelude::*;
12use strum::IntoEnumIterator;
13use vek::*;
14
15pub struct House {
17 pub door_tile: Vec2<i32>,
19 tile_aabr: Aabr<i32>,
21 bounds: Aabr<i32>,
23 pub(crate) alt: i32,
25 levels: u32,
27 overhang: i32,
29 roof_color: Rgb<u8>,
31 front: Dir,
32 christmas_decorations: bool,
33}
34
35impl House {
36 pub fn generate(
37 land: &Land,
38 rng: &mut impl Rng,
39 site: &Site,
40 door_tile: Vec2<i32>,
41 door_dir: Vec2<i32>,
42 tile_aabr: Aabr<i32>,
43 calendar: Option<&Calendar>,
44 alt: Option<i32>,
45 ) -> Self {
46 let levels = rng.gen_range(1..2 + (tile_aabr.max - tile_aabr.min).product() / 6) as u32;
47 let door_tile_pos = site.tile_center_wpos(door_tile);
48 let bounds = Aabr {
49 min: site.tile_wpos(tile_aabr.min),
50 max: site.tile_wpos(tile_aabr.max),
51 };
52
53 let front = match door_dir {
54 dir if dir.y < 0 => Dir::NegY,
55 dir if dir.x < 0 => Dir::NegX,
56 dir if dir.y > 0 => Dir::Y,
57 _ => Dir::X,
58 };
59
60 let christmas_decorations = calendar.is_some_and(|c| c.is_event(CalendarEvent::Christmas));
61
62 Self {
63 door_tile: door_tile_pos,
64 tile_aabr,
65 bounds,
66 alt: alt.unwrap_or_else(|| {
67 land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
68 }),
69 levels,
70 overhang: if levels > 3 {
71 *[-5, 1, 2].choose(rng).unwrap_or(&-5)
75 } else if levels > 1 {
76 *[-5, 1, 2, 3].choose(rng).unwrap_or(&2)
77 } else {
78 0
80 },
81 roof_color: {
82 let colors = [
83 Rgb::new(21, 43, 48),
84 Rgb::new(11, 23, 38),
85 Rgb::new(45, 28, 21),
86 Rgb::new(10, 55, 40),
87 Rgb::new(5, 35, 15),
88 Rgb::new(40, 5, 11),
89 Rgb::new(55, 45, 11),
90 ];
91 *colors.choose(rng).unwrap_or(&Rgb::new(21, 43, 48))
92 },
93 front,
94 christmas_decorations,
95 }
96 }
97
98 pub fn z_range(&self) -> Range<i32> { self.alt..self.alt + self.levels as i32 * STOREY }
99
100 pub fn roof_color(&self) -> Rgb<u8> { self.roof_color }
101}
102
103const STOREY: i32 = 5;
104
105impl Structure for House {
106 #[cfg(feature = "use-dyn-lib")]
107 const UPDATE_FN: &'static [u8] = b"render_house\0";
108
109 #[cfg_attr(feature = "be-dyn-lib", export_name = "render_house")]
110 fn render_inner(&self, site: &Site, _land: &Land, painter: &Painter) {
111 let storey = STOREY;
112 let roof = storey * self.levels as i32 - 1;
113 let foundations = 20;
114 let alt = self.alt + 1;
115
116 let roof_lip = 1;
118 let roof_height = (self.bounds.min - self.bounds.max)
119 .map(|e| e.abs())
120 .reduce_min()
121 / 2
122 + roof_lip
123 + 1;
124
125 let (roof_primitive, roof_empty) = match self.front {
126 Dir::Y => {
127 (
128 painter.prim(Primitive::Gable {
129 aabb: Aabb {
130 min: (self.bounds.min - roof_lip).with_z(alt + roof),
131 max: (Vec2::new(
132 self.bounds.max.x + 1 + roof_lip,
133 self.bounds.max.y
134 + 1
135 + roof_lip
136 + (self.levels as i32 - 1) * self.overhang,
137 ))
138 .with_z(alt + roof + roof_height),
139 },
140 inset: roof_height,
141 dir: Dir::Y,
142 }),
143 painter.prim(Primitive::Gable {
144 aabb: Aabb {
145 min: (Vec2::new(self.bounds.min.x, self.bounds.min.y - 1))
146 .with_z(alt + roof), max: (Vec2::new(
149 self.bounds.max.x + 1,
150 self.bounds.max.y
151 + 1
152 + (self.levels as i32 - 1) * self.overhang
153 + 1,
154 ))
155 .with_z(alt + roof + roof_height - 1),
156 },
157 inset: roof_height - 1,
158 dir: Dir::Y,
159 }),
160 )
161 },
162 Dir::X => {
163 (
164 painter.prim(Primitive::Gable {
165 aabb: Aabb {
166 min: (self.bounds.min - roof_lip).with_z(alt + roof),
167 max: Vec2::new(
168 self.bounds.max.x
169 + 1
170 + roof_lip
171 + (self.levels as i32 - 1) * self.overhang,
172 self.bounds.max.y + 1 + roof_lip,
173 )
174 .with_z(alt + roof + roof_height),
175 },
176 inset: roof_height,
177 dir: Dir::X,
178 }),
179 painter.prim(Primitive::Gable {
180 aabb: Aabb {
181 min: (Vec2::new(self.bounds.min.x - 1, self.bounds.min.y))
182 .with_z(alt + roof), max: Vec2::new(
185 self.bounds.max.x
186 + 1
187 + (self.levels as i32 - 1) * self.overhang
188 + 1,
189 self.bounds.max.y + 1,
190 )
191 .with_z(alt + roof + roof_height - 1),
192 },
193 inset: roof_height - 1,
194 dir: Dir::X,
195 }),
196 )
197 },
198 Dir::NegY => (
199 painter.prim(Primitive::Gable {
200 aabb: Aabb {
201 min: Vec2::new(
202 self.bounds.min.x - roof_lip,
203 self.bounds.min.y - roof_lip - (self.levels as i32 - 1) * self.overhang,
204 )
205 .with_z(alt + roof),
206 max: Vec2::new(
207 self.bounds.max.x + 1 + roof_lip,
208 self.bounds.max.y + roof_lip + 1,
209 )
210 .with_z(alt + roof + roof_height),
211 },
212 inset: roof_height,
213 dir: Dir::Y,
214 }),
215 painter.prim(Primitive::Gable {
216 aabb: Aabb {
217 min: Vec2::new(
218 self.bounds.min.x,
219 self.bounds.min.y - 1 - (self.levels as i32 - 1) * self.overhang - 1,
220 )
221 .with_z(alt + roof),
222 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + roof_lip + 1)
223 .with_z(alt + roof + roof_height - 1),
224 },
225 inset: roof_height - 1,
226 dir: Dir::Y,
227 }),
228 ),
229 _ => (
230 painter.prim(Primitive::Gable {
231 aabb: Aabb {
232 min: Vec2::new(
233 self.bounds.min.x - roof_lip - (self.levels as i32 - 1) * self.overhang,
234 self.bounds.min.y - roof_lip,
235 )
236 .with_z(alt + roof),
237 max: Vec2::new(
238 self.bounds.max.x + 1 + roof_lip,
239 self.bounds.max.y + 1 + roof_lip,
240 )
241 .with_z(alt + roof + roof_height),
242 },
243 inset: roof_height,
244 dir: Dir::X,
245 }),
246 painter.prim(Primitive::Gable {
247 aabb: Aabb {
248 min: Vec2::new(
249 self.bounds.min.x
250 - roof_lip
251 - 1
252 - (self.levels as i32 - 1) * self.overhang,
253 self.bounds.min.y,
254 )
255 .with_z(alt + roof),
256 max: Vec2::new(self.bounds.max.x + 1 + roof_lip, self.bounds.max.y + 1)
257 .with_z(alt + roof + roof_height - 1),
258 },
259 inset: roof_height - 1,
260 dir: Dir::X,
261 }),
262 ),
263 };
264
265 let (roof_front_wall, roof_rear_wall) = match self.front {
266 Dir::Y => (
267 painter.prim(Primitive::Aabb(Aabb {
268 min: (Vec2::new(
269 self.bounds.min.x,
270 self.bounds.max.y + (self.levels as i32 - 1) * self.overhang,
271 ))
272 .with_z(alt + roof),
273 max: (Vec2::new(
274 self.bounds.max.x + 1,
275 self.bounds.max.y + (self.levels as i32 - 1) * self.overhang + 1,
276 ))
277 .with_z(alt + roof + roof_height),
278 })),
279 painter.prim(Primitive::Aabb(Aabb {
280 min: (Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof)),
281 max: (Vec2::new(self.bounds.max.x + 1, self.bounds.min.y + 1)
282 .with_z(alt + roof + roof_height)),
283 })),
284 ),
285 Dir::X => (
286 painter.prim(Primitive::Aabb(Aabb {
287 min: Vec2::new(
288 self.bounds.max.x + (self.levels as i32 - 1) * self.overhang,
289 self.bounds.min.y,
290 )
291 .with_z(alt + roof),
292 max: Vec2::new(
293 self.bounds.max.x + (self.levels as i32 - 1) * self.overhang + 1,
294 self.bounds.max.y + 1,
295 )
296 .with_z(alt + roof + roof_height),
297 })),
298 painter.prim(Primitive::Aabb(Aabb {
299 min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof),
300 max: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y + 1)
301 .with_z(alt + roof + roof_height),
302 })),
303 ),
304 Dir::NegY => (
305 painter.prim(Primitive::Aabb(Aabb {
306 min: Vec2::new(
307 self.bounds.min.x,
308 self.bounds.min.y - (self.levels as i32 - 1) * self.overhang,
309 )
310 .with_z(alt + roof),
311 max: Vec2::new(
312 self.bounds.max.x + 1,
313 self.bounds.min.y - (self.levels as i32 - 1) * self.overhang + 1,
314 )
315 .with_z(alt + roof + roof_height),
316 })),
317 painter.prim(Primitive::Aabb(Aabb {
318 min: Vec2::new(self.bounds.min.x, self.bounds.max.y).with_z(alt + roof),
319 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
320 .with_z(alt + roof + roof_height),
321 })),
322 ),
323 _ => (
324 painter.prim(Primitive::Aabb(Aabb {
325 min: Vec2::new(
326 self.bounds.min.x - (self.levels as i32 - 1) * self.overhang,
327 self.bounds.min.y,
328 )
329 .with_z(alt + roof),
330 max: Vec2::new(
331 self.bounds.min.x - (self.levels as i32 - 1) * self.overhang + 1,
332 self.bounds.max.y + 1,
333 )
334 .with_z(alt + roof + roof_height),
335 })),
336 painter.prim(Primitive::Aabb(Aabb {
337 min: Vec2::new(self.bounds.max.x, self.bounds.min.y).with_z(alt + roof),
338 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
339 .with_z(alt + roof + roof_height),
340 })),
341 ),
342 };
343 let roof_front = painter.prim(Primitive::intersect(roof_empty, roof_front_wall));
344 let roof_rear = painter.prim(Primitive::intersect(roof_empty, roof_rear_wall));
345 painter.fill(
346 roof_primitive,
347 Fill::Brick(BlockKind::Wood, self.roof_color, 24),
348 );
349 painter.fill(roof_empty, Fill::Block(Block::empty()));
350 let roof_walls = painter.prim(Primitive::union(roof_front, roof_rear));
351 painter.fill(
352 roof_walls,
353 Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
354 );
355 let max_overhang = (self.levels as i32 - 1) * self.overhang;
356 let (roof_beam, roof_beam_right, roof_beam_left) = match self.front {
357 Dir::Y => (
358 painter.prim(Primitive::Aabb(Aabb {
359 min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof),
360 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1 + max_overhang)
361 .with_z(alt + roof + 1),
362 })),
363 painter.prim(Primitive::Aabb(Aabb {
364 min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof),
365 max: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y + 1 + max_overhang)
366 .with_z(alt + roof + 1),
367 })),
368 painter.prim(Primitive::Aabb(Aabb {
369 min: Vec2::new(self.bounds.max.x, self.bounds.min.y).with_z(alt + roof),
370 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1 + max_overhang)
371 .with_z(alt + roof + 1),
372 })),
373 ),
374 Dir::X => (
375 painter.prim(Primitive::Aabb(Aabb {
376 min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof),
377 max: Vec2::new(self.bounds.max.x + max_overhang + 1, self.bounds.max.y + 1)
378 .with_z(alt + roof + 1),
379 })),
380 painter.prim(Primitive::Aabb(Aabb {
381 min: Vec2::new(self.bounds.min.x, self.bounds.min.y).with_z(alt + roof),
382 max: Vec2::new(self.bounds.max.x + max_overhang + 1, self.bounds.min.y + 1)
383 .with_z(alt + roof + 1),
384 })),
385 painter.prim(Primitive::Aabb(Aabb {
386 min: Vec2::new(self.bounds.min.x, self.bounds.max.y).with_z(alt + roof),
387 max: Vec2::new(self.bounds.max.x + max_overhang + 1, self.bounds.max.y + 1)
388 .with_z(alt + roof + 1),
389 })),
390 ),
391 Dir::NegY => (
392 painter.prim(Primitive::Aabb(Aabb {
393 min: Vec2::new(self.bounds.min.x, self.bounds.min.y - max_overhang)
394 .with_z(alt + roof),
395 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
396 .with_z(alt + roof + 1),
397 })),
398 painter.prim(Primitive::Aabb(Aabb {
399 min: Vec2::new(self.bounds.max.x, self.bounds.min.y - max_overhang)
400 .with_z(alt + roof),
401 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
402 .with_z(alt + roof + 1),
403 })),
404 painter.prim(Primitive::Aabb(Aabb {
405 min: Vec2::new(self.bounds.min.x, self.bounds.min.y - max_overhang)
406 .with_z(alt + roof),
407 max: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y + 1)
408 .with_z(alt + roof + 1),
409 })),
410 ),
411 _ => (
412 painter.prim(Primitive::Aabb(Aabb {
413 min: Vec2::new(self.bounds.min.x - max_overhang - 1, self.bounds.min.y)
414 .with_z(alt + roof),
415 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
416 .with_z(alt + roof + 1),
417 })),
418 painter.prim(Primitive::Aabb(Aabb {
419 min: Vec2::new(self.bounds.min.x - max_overhang, self.bounds.min.y)
420 .with_z(alt + roof),
421 max: Vec2::new(self.bounds.max.x + 1, self.bounds.min.y + 1)
422 .with_z(alt + roof + 1),
423 })),
424 painter.prim(Primitive::Aabb(Aabb {
425 min: Vec2::new(self.bounds.min.x - max_overhang, self.bounds.max.y)
426 .with_z(alt + roof),
427 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
428 .with_z(alt + roof + 1),
429 })),
430 ),
431 };
432 let quarter_x = self.bounds.min.x + (self.bounds.max.x - self.bounds.min.x) / 4;
433 let quarter_y = self.bounds.min.y + (self.bounds.max.y - self.bounds.min.y) / 4;
434 let half_x = self.bounds.min.x + (self.bounds.max.x - self.bounds.min.x) / 2;
435 let half_y = self.bounds.min.y + (self.bounds.max.y - self.bounds.min.y) / 2;
436 let three_quarter_x = self.bounds.min.x + 3 * (self.bounds.max.x - self.bounds.min.x) / 4;
437 let three_quarter_y = self.bounds.min.y + 3 * (self.bounds.max.y - self.bounds.min.y) / 4;
438 let top_rafter = if self.front.is_y() {
439 painter.prim(Primitive::Aabb(Aabb {
440 min: (Vec2::new(half_x, self.bounds.min.y - 2 - max_overhang.abs())
441 .with_z(alt + roof)),
442 max: (Vec2::new(half_x + 1, self.bounds.max.y + 2 + max_overhang.abs()))
443 .with_z(alt + roof + roof_height),
444 }))
445 } else {
446 painter.prim(Primitive::Aabb(Aabb {
447 min: (Vec2::new(self.bounds.min.x - 1 - max_overhang.abs(), half_y)
448 .with_z(alt + roof)),
449 max: (Vec2::new(self.bounds.max.x + 1 + max_overhang.abs(), half_y + 1))
450 .with_z(alt + roof + roof_height),
451 }))
452 };
453 let left_rafter = if self.front.is_y() {
454 painter.prim(Primitive::Plane(
455 Aabr {
456 min: Vec2::new(half_x, self.bounds.min.y - 1 - max_overhang.abs()),
457 max: Vec2::new(
458 three_quarter_x + 1,
459 self.bounds.max.y + 1 + max_overhang.abs(),
460 ),
461 },
462 Vec2::new(half_x, self.bounds.min.y - 1 - max_overhang.abs()).with_z(alt + roof),
463 Vec2::new(1.0, 0.0),
464 ))
465 } else {
466 painter.prim(Primitive::Plane(
467 Aabr {
468 min: Vec2::new(self.bounds.min.x - 1 - max_overhang.abs(), half_y),
469 max: Vec2::new(
470 self.bounds.max.x + 1 + max_overhang.abs(),
471 three_quarter_y + 1,
472 ),
473 },
474 Vec2::new(self.bounds.min.x - 1 - max_overhang.abs(), half_y).with_z(alt + roof),
475 Vec2::new(0.0, 1.0),
476 ))
477 };
478 let right_rafter = if self.front.is_y() {
479 painter.prim(Primitive::Plane(
480 Aabr {
481 min: Vec2::new(quarter_x, self.bounds.min.y - 1 - max_overhang.abs()),
482 max: Vec2::new(half_x + 1, self.bounds.max.y + 1 + max_overhang.abs()),
483 },
484 Vec2::new(half_x, self.bounds.min.y - 1 - max_overhang.abs()).with_z(alt + roof),
485 Vec2::new(1.0, 0.0),
486 ))
487 } else {
488 painter.prim(Primitive::Plane(
489 Aabr {
490 min: Vec2::new(self.bounds.min.x - 1 - max_overhang.abs(), quarter_y),
491 max: Vec2::new(self.bounds.max.x + 1 + max_overhang.abs(), half_y + 1),
492 },
493 Vec2::new(self.bounds.min.x - 1 - max_overhang.abs(), half_y).with_z(alt + roof),
494 Vec2::new(0.0, 1.0),
495 ))
496 };
497 let rafters1 = painter.prim(Primitive::union(left_rafter, right_rafter));
498 let rafters2 = painter.prim(Primitive::union(rafters1, top_rafter));
499
500 painter.fill(
501 painter.prim(Primitive::intersect(roof_beam, roof_walls)),
502 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
503 );
504 painter.fill(
505 painter.prim(Primitive::union(roof_beam_left, roof_beam_right)),
506 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
507 );
508 painter.fill(
509 painter.prim(Primitive::intersect(rafters2, roof_walls)),
510 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
511 );
512
513 for i in 1..self.levels + 1 {
516 let previous_height = (storey * (i as i32 - 1) - 1).max(-1);
517 let height = storey * i as i32 - 1;
518 let window_height = storey - 3;
519 let storey_increase = (i as i32 - 1) * self.overhang;
520
521 let inner_level = if self.overhang < -4 && i > 1 {
523 match self.front {
524 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
525 min: (self.bounds.min + 1).with_z(alt + previous_height),
526 max: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase + 1)
527 .with_z(alt + height),
528 })),
529 Dir::X => painter.prim(Primitive::Aabb(Aabb {
530 min: (self.bounds.min + 1).with_z(alt + previous_height),
531 max: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.max.y)
532 .with_z(alt + height),
533 })),
534 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
535 min: Vec2::new(
536 self.bounds.min.x + 1,
537 self.bounds.min.y - storey_increase + 1,
538 )
539 .with_z(alt + previous_height),
540 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(alt + height),
541 })),
542 _ => painter.prim(Primitive::Aabb(Aabb {
543 min: Vec2::new(
544 self.bounds.min.x - storey_increase + 1,
545 self.bounds.min.y + 1,
546 )
547 .with_z(alt + previous_height),
548 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(alt + height),
549 })),
550 }
551 } else {
552 match self.front {
553 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
554 min: (self.bounds.min + 1).with_z(alt + previous_height),
555 max: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase)
556 .with_z(alt + height),
557 })),
558 Dir::X => painter.prim(Primitive::Aabb(Aabb {
559 min: (self.bounds.min + 1).with_z(alt + previous_height),
560 max: (Vec2::new(self.bounds.max.x + storey_increase, self.bounds.max.y))
561 .with_z(alt + height),
562 })),
563 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
564 min: Vec2::new(
565 self.bounds.min.x + 1,
566 self.bounds.min.y - storey_increase + 1,
567 )
568 .with_z(alt + previous_height),
569 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(alt + height),
570 })),
571 _ => painter.prim(Primitive::Aabb(Aabb {
572 min: Vec2::new(
573 self.bounds.min.x - storey_increase + 1,
574 self.bounds.min.y + 1,
575 )
576 .with_z(alt + previous_height),
577 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(alt + height),
578 })),
579 }
580 };
581 let outer_level = match self.front {
582 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
583 min: self.bounds.min.with_z(alt + previous_height),
584 max: (Vec2::new(
585 self.bounds.max.x + 1,
586 self.bounds.max.y + storey_increase + 1,
587 ))
588 .with_z(alt + height),
589 })),
590 Dir::X => painter.prim(Primitive::Aabb(Aabb {
591 min: self.bounds.min.with_z(alt + previous_height),
592 max: Vec2::new(
593 self.bounds.max.x + storey_increase + 1,
594 self.bounds.max.y + 1,
595 )
596 .with_z(alt + height),
597 })),
598 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
599 min: Vec2::new(self.bounds.min.x, self.bounds.min.y - storey_increase)
600 .with_z(alt + previous_height),
601 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
602 .with_z(alt + height),
603 })),
604 _ => painter.prim(Primitive::Aabb(Aabb {
605 min: Vec2::new(self.bounds.min.x - storey_increase, self.bounds.min.y)
606 .with_z(alt + previous_height),
607 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
608 .with_z(alt + height),
609 })),
610 };
611
612 let wall_block_fill = if i < 2 {
614 Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24)
615 } else {
616 Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24)
617 };
618 painter.fill(outer_level, wall_block_fill);
619 painter.fill(inner_level, Fill::Block(Block::empty()));
620
621 let walls = outer_level
622 .union(inner_level)
623 .without(outer_level.intersect(inner_level));
624
625 if i > 1 {
628 let mut pillars_y = painter.prim(Primitive::Empty);
629 let mut overhang_supports = painter.prim(Primitive::Empty);
630
631 for x in self.tile_aabr.min.x - 2..self.tile_aabr.max.x + 2 {
632 if self.overhang >= 2 && self.front.is_y() {
633 let temp = match self.front {
634 Dir::Y => site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y)),
635 _ => Vec2::zero(),
637 };
638 let support = match self.front {
642 Dir::Y => painter.line(
643 Vec2::new(
644 temp.x,
645 self.bounds.max.y + storey_increase - self.overhang + 1,
646 )
647 .with_z(alt + previous_height - 3),
648 Vec2::new(
649 temp.x,
650 self.bounds.max.y + storey_increase - self.overhang + 2,
651 )
652 .with_z(alt + previous_height),
653 0.75,
654 ),
655 _ => painter.prim(Primitive::Empty),
663 };
664 if temp.x <= self.bounds.max.x && temp.x >= self.bounds.min.x {
665 overhang_supports =
666 painter.prim(Primitive::union(overhang_supports, support));
667 }
668 }
669 let pillar = painter.prim(Primitive::Aabb(Aabb {
670 min: site
671 .tile_wpos(Vec2::new(x, self.tile_aabr.min.y - 4))
672 .with_z(alt + previous_height),
673 max: (site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y + 4))
674 + Vec2::unit_x())
675 .with_z(alt + height),
676 }));
677 pillars_y = painter.prim(Primitive::union(pillars_y, pillar));
678 }
679 let mut pillars_x = painter.prim(Primitive::Empty);
680 for y in self.tile_aabr.min.y - 2..self.tile_aabr.max.y + 2 {
681 if self.overhang >= 2 && !self.front.is_y() {
682 let temp = match self.front {
683 Dir::Y => Vec2::zero(),
684 Dir::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y)),
685 Dir::NegY => Vec2::zero(),
686 _ => site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y)),
687 };
688 let support = match self.front {
689 Dir::Y => painter.prim(Primitive::Empty),
690 Dir::X => painter.line(
691 Vec2::new(
692 self.bounds.max.x + storey_increase - self.overhang + 1,
693 temp.y,
694 )
695 .with_z(alt + previous_height - 3),
696 Vec2::new(
697 self.bounds.max.x + storey_increase - self.overhang + 2,
698 temp.y,
699 )
700 .with_z(alt + previous_height),
701 0.75,
702 ),
703 Dir::NegY => painter.prim(Primitive::Empty),
704 _ => painter.line(
705 Vec2::new(
706 self.bounds.min.x - storey_increase + self.overhang - 1,
707 temp.y,
708 )
709 .with_z(alt + previous_height - 3),
710 Vec2::new(
711 self.bounds.min.x - storey_increase + self.overhang - 2,
712 temp.y,
713 )
714 .with_z(alt + previous_height),
715 0.75,
716 ),
717 };
718 if temp.y <= self.bounds.max.y && temp.y >= self.bounds.min.y {
719 overhang_supports =
720 painter.prim(Primitive::union(overhang_supports, support));
721 }
722 }
723 let pillar = painter.prim(Primitive::Aabb(Aabb {
724 min: site
725 .tile_wpos(Vec2::new(self.tile_aabr.min.x - 4, y))
726 .with_z(alt + previous_height),
727 max: (site.tile_wpos(Vec2::new(self.tile_aabr.max.x + 4, y))
728 + Vec2::unit_y())
729 .with_z(alt + height),
730 }));
731 pillars_x = painter.prim(Primitive::union(pillars_x, pillar));
732 }
733 let front_wall = if self.overhang < -4 && i > 1 {
734 painter.prim(Primitive::Empty)
735 } else {
736 match self.front {
737 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
738 min: Vec2::new(
739 self.bounds.min.x - 1,
740 self.bounds.max.y + storey_increase,
741 )
742 .with_z(alt + previous_height),
743 max: Vec2::new(
744 self.bounds.max.x + 1,
745 self.bounds.max.y + storey_increase + 1,
746 )
747 .with_z(alt + height),
748 })),
749 Dir::X => painter.prim(Primitive::Aabb(Aabb {
750 min: Vec2::new(
751 self.bounds.max.x + storey_increase,
752 self.bounds.min.y - 1,
753 )
754 .with_z(alt + previous_height),
755 max: Vec2::new(
756 self.bounds.max.x + storey_increase + 1,
757 self.bounds.max.y + 1,
758 )
759 .with_z(alt + height),
760 })),
761 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
762 min: Vec2::new(
763 self.bounds.min.x - 1,
764 self.bounds.min.y - storey_increase,
765 )
766 .with_z(alt + previous_height),
767 max: Vec2::new(
768 self.bounds.max.x + 1,
769 self.bounds.min.y - storey_increase + 1,
770 )
771 .with_z(alt + height),
772 })),
773 _ => painter.prim(Primitive::Aabb(Aabb {
774 min: Vec2::new(
775 self.bounds.min.x - storey_increase,
776 self.bounds.min.y - 1,
777 )
778 .with_z(alt + previous_height),
779 max: Vec2::new(
780 self.bounds.min.x - storey_increase + 1,
781 self.bounds.max.y + 1,
782 )
783 .with_z(alt + height),
784 })),
785 }
786 };
787 let pillars1 = if self.front.is_y() {
788 painter.prim(Primitive::intersect(pillars_y, front_wall))
789 } else {
790 painter.prim(Primitive::intersect(pillars_x, front_wall))
791 };
792 let pillars2 = painter.prim(Primitive::intersect(pillars_x, pillars_y));
793 let pillars3 = painter.prim(Primitive::union(pillars1, pillars2));
794 let pillars4 = match self.front {
795 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
796 min: Vec2::new(self.bounds.min.x - 1, self.bounds.min.y - 1)
797 .with_z(alt + previous_height),
798 max: Vec2::new(
799 self.bounds.max.x + 1,
800 self.bounds.max.y + storey_increase + 1,
801 )
802 .with_z(alt + previous_height + 1),
803 })),
804 Dir::X => painter.prim(Primitive::Aabb(Aabb {
805 min: Vec2::new(self.bounds.min.x - 1, self.bounds.min.y - 1)
806 .with_z(alt + previous_height),
807 max: Vec2::new(
808 self.bounds.max.x + storey_increase + 1,
809 self.bounds.max.y + 1,
810 )
811 .with_z(alt + previous_height + 1),
812 })),
813 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
814 min: Vec2::new(
815 self.bounds.min.x - 1,
816 self.bounds.min.y - storey_increase - 1,
817 )
818 .with_z(alt + previous_height),
819 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
820 .with_z(alt + previous_height + 1),
821 })),
822 _ => painter.prim(Primitive::Aabb(Aabb {
823 min: Vec2::new(
824 self.bounds.min.x - storey_increase - 1,
825 self.bounds.min.y - 1,
826 )
827 .with_z(alt + previous_height),
828 max: Vec2::new(self.bounds.max.x + 1, self.bounds.max.y + 1)
829 .with_z(alt + previous_height + 1),
830 })),
831 };
832 let pillars = painter.prim(Primitive::union(pillars3, pillars4));
833 painter.fill(
834 painter.prim(Primitive::intersect(walls, pillars)),
835 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
836 );
837
838 painter.fill(
839 overhang_supports,
840 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
841 );
842 }
843
844 {
846 let mut windows = painter.prim(Primitive::Empty);
847 for y in self.tile_aabr.min.y - 2..self.tile_aabr.max.y + 2 {
848 let min = (site.tile_wpos(Vec2::new(self.tile_aabr.min.x - 4, y))
849 + Vec2::unit_y() * 2)
850 .with_z(alt + previous_height + 2);
851 let max = (site.tile_wpos(Vec2::new(self.tile_aabr.max.x + 4, y + 1))
852 + Vec2::new(1, -1))
853 .with_z(alt + previous_height + 2 + window_height);
854 let window = painter.prim(Primitive::Aabb(Aabb { min, max }));
855 let add_windows = match self.front {
856 Dir::Y => {
857 max.y < self.bounds.max.y + storey_increase && min.y > self.bounds.min.y
858 },
859 Dir::X => max.y < self.bounds.max.y && min.y > self.bounds.min.y,
860 Dir::NegY => {
861 max.y < self.bounds.max.y && min.y > self.bounds.min.y - storey_increase
862 },
863 _ => max.y < self.bounds.max.y && min.y > self.bounds.min.y,
864 };
865 if add_windows {
866 windows = painter.prim(Primitive::union(windows, window));
867 }
868 }
869 painter.fill(
870 painter.prim(Primitive::intersect(walls, windows)),
871 Fill::Block(Block::air(SpriteKind::Window1).with_ori(2).unwrap()),
872 );
873 if i == 1 {
875 let mut torches_min = painter.prim(Primitive::Empty);
876 let mut torches_max = painter.prim(Primitive::Empty);
877 for y in self.tile_aabr.min.y..self.tile_aabr.max.y {
878 let pos = site
879 .tile_wpos(Vec2::new(self.tile_aabr.min.x, y))
880 .with_z(alt + previous_height + 3)
881 + Vec3::new(-1, 0, 0);
882 let torch = painter.prim(Primitive::Aabb(Aabb {
883 min: pos,
884 max: pos + 1,
885 }));
886 torches_min = painter.prim(Primitive::union(torches_min, torch));
887
888 let pos = site
889 .tile_wpos(Vec2::new(self.tile_aabr.max.x, y + 1))
890 .with_z(alt + previous_height + 3)
891 + Vec3::new(1, 0, 0);
892 let torch = painter.prim(Primitive::Aabb(Aabb {
893 min: pos,
894 max: pos + 1,
895 }));
896 torches_max = painter.prim(Primitive::union(torches_max, torch));
897 }
898 painter.fill(
899 torches_min,
900 Fill::Block(Block::air(SpriteKind::WallLampSmall).with_ori(6).unwrap()),
901 );
902 painter.fill(
903 torches_max,
904 Fill::Block(Block::air(SpriteKind::WallLampSmall).with_ori(2).unwrap()),
905 );
906 }
907 }
908 {
910 let mut windows = painter.prim(Primitive::Empty);
911 for x in self.tile_aabr.min.x - 2..self.tile_aabr.max.x + 2 {
912 let min = (site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y - 4))
913 + Vec2::unit_x() * 2)
914 .with_z(alt + previous_height + 2);
915 let max = (site.tile_wpos(Vec2::new(x + 1, self.tile_aabr.max.y + 4))
916 + Vec2::new(-1, 1))
917 .with_z(alt + previous_height + 2 + window_height);
918 let window = painter.prim(Primitive::Aabb(Aabb { min, max }));
919 let add_windows = match self.front {
920 Dir::Y => max.x < self.bounds.max.x && min.x > self.bounds.min.x,
921 Dir::X => {
922 max.x < self.bounds.max.x + storey_increase && min.x > self.bounds.min.x
923 },
924 Dir::NegY => max.x < self.bounds.max.x && min.x > self.bounds.min.x,
925 _ => {
926 max.x < self.bounds.max.x && min.x > self.bounds.min.x - storey_increase
927 },
928 };
929 if add_windows {
930 windows = painter.prim(Primitive::union(windows, window));
931 };
932 }
933 painter.fill(
934 painter.prim(Primitive::intersect(walls, windows)),
935 Fill::Block(Block::air(SpriteKind::Window1).with_ori(0).unwrap()),
936 );
937 if i == 1 {
939 let mut torches_min = painter.prim(Primitive::Empty);
940 let mut torches_max = painter.prim(Primitive::Empty);
941 for x in self.tile_aabr.min.x..self.tile_aabr.max.x {
942 let pos = site
943 .tile_wpos(Vec2::new(x + 1, self.tile_aabr.min.y))
944 .with_z(alt + previous_height + 3)
945 + Vec3::new(0, -1, 0);
946 let torch = painter.prim(Primitive::Aabb(Aabb {
947 min: pos,
948 max: pos + 1,
949 }));
950 torches_min = painter.prim(Primitive::union(torches_min, torch));
951
952 let pos = site
953 .tile_wpos(Vec2::new(x, self.tile_aabr.max.y))
954 .with_z(alt + previous_height + 3)
955 + Vec3::new(0, 1, 0);
956 let torch = painter.prim(Primitive::Aabb(Aabb {
957 min: pos,
958 max: pos + 1,
959 }));
960 torches_max = painter.prim(Primitive::union(torches_max, torch));
961 }
962 painter.fill(
963 torches_min,
964 Fill::Block(Block::air(SpriteKind::WallLampSmall).with_ori(0).unwrap()),
965 );
966 painter.fill(
967 torches_max,
968 Fill::Block(Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap()),
969 );
970 }
971 }
972
973 if self.overhang < -4 && i > 1 {
975 let shed = match self.front {
976 Dir::Y => painter.prim(Primitive::Ramp {
977 aabb: Aabb {
978 min: Vec2::new(
979 self.bounds.min.x - 1,
980 self.bounds.max.y + storey_increase + 1,
981 )
982 .with_z(alt + previous_height),
983 max: Vec2::new(
984 self.bounds.max.x + 1,
985 self.bounds.max.y + storey_increase + self.overhang.abs() + 1,
986 )
987 .with_z(alt + height),
988 },
989 inset: storey,
990 dir: Dir::NegY,
991 }),
992 Dir::X => painter.prim(Primitive::Ramp {
993 aabb: Aabb {
994 min: Vec2::new(
995 self.bounds.max.x + storey_increase + 1,
996 self.bounds.min.y - 1,
997 )
998 .with_z(alt + previous_height),
999 max: Vec2::new(
1000 self.bounds.max.x + storey_increase + self.overhang.abs() + 1,
1001 self.bounds.max.y + 1,
1002 )
1003 .with_z(alt + height),
1004 },
1005 inset: storey,
1006 dir: Dir::NegX,
1007 }),
1008 Dir::NegY => painter.prim(Primitive::Ramp {
1009 aabb: Aabb {
1010 min: Vec2::new(
1011 self.bounds.min.x - 1,
1012 self.bounds.min.y - storey_increase - self.overhang.abs(),
1013 )
1014 .with_z(alt + previous_height),
1015 max: Vec2::new(
1016 self.bounds.max.x + 2,
1017 self.bounds.min.y - storey_increase,
1018 )
1019 .with_z(alt + height),
1020 },
1021 inset: storey,
1022 dir: Dir::Y,
1023 }),
1024 _ => painter.prim(Primitive::Ramp {
1025 aabb: Aabb {
1026 min: Vec2::new(
1027 self.bounds.min.x - storey_increase - self.overhang.abs(),
1028 self.bounds.min.y - 1,
1029 )
1030 .with_z(alt + previous_height),
1031 max: Vec2::new(
1032 self.bounds.min.x - storey_increase + 1,
1033 self.bounds.max.y + 2,
1034 )
1035 .with_z(alt + height),
1036 },
1037 inset: storey,
1038 dir: Dir::X,
1039 }),
1040 };
1041 let shed_empty = match self.front {
1042 Dir::Y => painter.prim(Primitive::Ramp {
1043 aabb: Aabb {
1044 min: Vec2::new(
1045 self.bounds.min.x - 1,
1046 self.bounds.max.y + storey_increase + 1,
1047 )
1048 .with_z(alt + previous_height),
1049 max: Vec2::new(
1050 self.bounds.max.x + 1,
1051 self.bounds.max.y + storey_increase + self.overhang.abs(),
1052 )
1053 .with_z(alt + height - 1),
1054 },
1055 inset: storey - 1,
1056 dir: Dir::NegY,
1057 }),
1058 Dir::X => painter.prim(Primitive::Ramp {
1059 aabb: Aabb {
1060 min: Vec2::new(
1061 self.bounds.max.x + storey_increase + 1,
1062 self.bounds.min.y - 1,
1063 )
1064 .with_z(alt + previous_height),
1065 max: Vec2::new(
1066 self.bounds.max.x + storey_increase + self.overhang.abs(),
1067 self.bounds.max.y + 1,
1068 )
1069 .with_z(alt + height - 1),
1070 },
1071 inset: storey - 1,
1072 dir: Dir::NegX,
1073 }),
1074 Dir::NegY => painter.prim(Primitive::Ramp {
1075 aabb: Aabb {
1076 min: Vec2::new(
1077 self.bounds.min.x - 1,
1078 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1079 )
1080 .with_z(alt + previous_height),
1081 max: Vec2::new(
1082 self.bounds.max.x + 2,
1083 self.bounds.min.y - storey_increase + 1,
1084 )
1085 .with_z(alt + height),
1086 },
1087 inset: storey - 1,
1088 dir: Dir::Y,
1089 }),
1090 _ => painter.prim(Primitive::Ramp {
1091 aabb: Aabb {
1092 min: Vec2::new(
1093 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1094 self.bounds.min.y - 1,
1095 )
1096 .with_z(alt + previous_height),
1097 max: Vec2::new(
1098 self.bounds.min.x - storey_increase + 1,
1099 self.bounds.max.y + 2,
1100 )
1101 .with_z(alt + height),
1102 },
1103 inset: storey - 1,
1104 dir: Dir::X,
1105 }),
1106 };
1107 painter.fill(shed, Fill::Brick(BlockKind::Wood, self.roof_color, 24));
1108 painter.fill(shed_empty, Fill::Block(Block::empty()));
1109 let shed_left_wall = match self.front {
1110 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1111 min: Vec2::new(self.bounds.min.x, self.bounds.max.y + storey_increase + 1)
1112 .with_z(alt + previous_height),
1113 max: Vec2::new(
1114 self.bounds.min.x + 1,
1115 self.bounds.max.y + storey_increase + self.overhang.abs(),
1116 )
1117 .with_z(alt + height - 1),
1118 })),
1119 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1120 min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.min.y)
1121 .with_z(alt + previous_height),
1122 max: Vec2::new(
1123 self.bounds.max.x + storey_increase + self.overhang.abs(),
1124 self.bounds.min.y + 1,
1125 )
1126 .with_z(alt + height - 1),
1127 })),
1128 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1129 min: Vec2::new(
1130 self.bounds.max.x,
1131 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1132 )
1133 .with_z(alt + previous_height),
1134 max: Vec2::new(
1135 self.bounds.max.x + 1,
1136 self.bounds.min.y - storey_increase + 1,
1137 )
1138 .with_z(alt + height),
1139 })),
1140 _ => painter.prim(Primitive::Aabb(Aabb {
1141 min: Vec2::new(
1142 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1143 self.bounds.max.y,
1144 )
1145 .with_z(alt + previous_height),
1146 max: Vec2::new(
1147 self.bounds.min.x - storey_increase + 1,
1148 self.bounds.max.y + 1,
1149 )
1150 .with_z(alt + height),
1151 })),
1152 };
1153 let shed_right_wall = match self.front {
1154 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1155 min: Vec2::new(self.bounds.max.x, self.bounds.max.y + storey_increase + 1)
1156 .with_z(alt + previous_height),
1157 max: Vec2::new(
1158 self.bounds.max.x + 1,
1159 self.bounds.max.y + storey_increase + self.overhang.abs(),
1160 )
1161 .with_z(alt + height - 1),
1162 })),
1163 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1164 min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.max.y)
1165 .with_z(alt + previous_height),
1166 max: Vec2::new(
1167 self.bounds.max.x + storey_increase + self.overhang.abs(),
1168 self.bounds.max.y + 1,
1169 )
1170 .with_z(alt + height - 1),
1171 })),
1172 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1173 min: Vec2::new(
1174 self.bounds.min.x,
1175 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1176 )
1177 .with_z(alt + previous_height),
1178 max: Vec2::new(
1179 self.bounds.min.x + 1,
1180 self.bounds.min.y - storey_increase + 1,
1181 )
1182 .with_z(alt + height),
1183 })),
1184 _ => painter.prim(Primitive::Aabb(Aabb {
1185 min: Vec2::new(
1186 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1187 self.bounds.min.y,
1188 )
1189 .with_z(alt + previous_height),
1190 max: Vec2::new(
1191 self.bounds.min.x - storey_increase + 1,
1192 self.bounds.min.y + 1,
1193 )
1194 .with_z(alt + height),
1195 })),
1196 };
1197 let shed_wall_beams = match self.front {
1198 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1199 min: Vec2::new(self.bounds.min.x, self.bounds.max.y + storey_increase + 1)
1200 .with_z(alt + previous_height),
1201 max: Vec2::new(
1202 self.bounds.max.x + 1,
1203 self.bounds.max.y + storey_increase + self.overhang.abs(),
1204 )
1205 .with_z(alt + previous_height + 1),
1206 })),
1207 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1208 min: Vec2::new(self.bounds.max.x + storey_increase + 1, self.bounds.min.y)
1209 .with_z(alt + previous_height),
1210 max: Vec2::new(
1211 self.bounds.max.x + storey_increase + self.overhang.abs(),
1212 self.bounds.max.y + 1,
1213 )
1214 .with_z(alt + previous_height + 1),
1215 })),
1216 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1217 min: Vec2::new(
1218 self.bounds.min.x,
1219 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1220 )
1221 .with_z(alt + previous_height),
1222 max: Vec2::new(
1223 self.bounds.max.x + 1,
1224 self.bounds.min.y - storey_increase + 1,
1225 )
1226 .with_z(alt + previous_height + 1),
1227 })),
1228 _ => painter.prim(Primitive::Aabb(Aabb {
1229 min: Vec2::new(
1230 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1231 self.bounds.min.y,
1232 )
1233 .with_z(alt + previous_height),
1234 max: Vec2::new(
1235 self.bounds.min.x - storey_increase + 1,
1236 self.bounds.max.y + 1,
1237 )
1238 .with_z(alt + previous_height + 1),
1239 })),
1240 };
1241 let shed_walls = painter.prim(Primitive::union(shed_left_wall, shed_right_wall));
1242 painter.fill(
1243 painter.prim(Primitive::intersect(shed_walls, shed_empty)),
1244 Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
1245 );
1246 painter.fill(
1247 painter.prim(Primitive::intersect(shed_wall_beams, shed_walls)),
1248 Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
1249 );
1250
1251 let range = if self.front.is_y() {
1253 self.tile_aabr.min.x - 3..self.tile_aabr.max.x + 3
1254 } else {
1255 self.tile_aabr.min.y - 3..self.tile_aabr.max.y + 3
1256 };
1257 for n in range {
1258 let temp = match self.front {
1259 Dir::Y => site.tile_wpos(Vec2::new(n, self.tile_aabr.max.y)) - 4,
1260 Dir::X => site.tile_wpos(Vec2::new(self.tile_aabr.max.x, n)) - 4,
1261 Dir::NegY => site.tile_wpos(Vec2::new(n, self.tile_aabr.min.y)) - 4,
1262 _ => site.tile_wpos(Vec2::new(self.tile_aabr.min.x, n)) - 4,
1263 };
1264 let dormer_box = match self.front {
1265 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1266 min: Vec2::new(temp.x - 1, self.bounds.max.y + storey_increase + 1)
1267 .with_z(alt + previous_height),
1268 max: Vec2::new(
1269 temp.x + 4,
1270 self.bounds.max.y + storey_increase + self.overhang.abs(),
1271 )
1272 .with_z(alt + height - 1),
1273 })),
1274 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1275 min: Vec2::new(self.bounds.max.x + storey_increase + 1, temp.y - 1)
1276 .with_z(alt + previous_height),
1277 max: Vec2::new(
1278 self.bounds.max.x + storey_increase + self.overhang.abs(),
1279 temp.y + 4,
1280 )
1281 .with_z(alt + height - 1),
1282 })),
1283 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1284 min: Vec2::new(
1285 temp.x - 1,
1286 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1287 )
1288 .with_z(alt + previous_height),
1289 max: Vec2::new(temp.x + 4, self.bounds.min.y - storey_increase - 1)
1290 .with_z(alt + height - 1),
1291 })),
1292 _ => painter.prim(Primitive::Aabb(Aabb {
1293 min: Vec2::new(
1294 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1295 temp.y - 1,
1296 )
1297 .with_z(alt + previous_height),
1298 max: Vec2::new(self.bounds.min.x - storey_increase - 1, temp.y + 4)
1299 .with_z(alt + height - 1),
1300 })),
1301 };
1302 let dormer_roof = match self.front {
1303 Dir::Y => painter.prim(Primitive::Gable {
1304 aabb: Aabb {
1305 min: Vec2::new(temp.x - 1, self.bounds.max.y + storey_increase + 1)
1306 .with_z(alt + height - 2),
1307 max: Vec2::new(
1308 temp.x + 4,
1309 self.bounds.max.y + storey_increase + self.overhang.abs(),
1310 )
1311 .with_z(alt + height + 1),
1312 },
1313 inset: 3,
1314 dir: Dir::Y,
1315 }),
1316 Dir::X => painter.prim(Primitive::Gable {
1317 aabb: Aabb {
1318 min: Vec2::new(self.bounds.max.x + storey_increase + 1, temp.y - 1)
1319 .with_z(alt + height - 2),
1320 max: Vec2::new(
1321 self.bounds.max.x + storey_increase + self.overhang.abs(),
1322 temp.y + 4,
1323 )
1324 .with_z(alt + height + 1),
1325 },
1326 inset: 3,
1327 dir: Dir::X,
1328 }),
1329 Dir::NegY => painter.prim(Primitive::Gable {
1330 aabb: Aabb {
1331 min: Vec2::new(
1332 temp.x - 1,
1333 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1334 )
1335 .with_z(alt + height - 2),
1336 max: Vec2::new(temp.x + 4, self.bounds.min.y - storey_increase)
1337 .with_z(alt + height + 1),
1338 },
1339 inset: 3,
1340 dir: Dir::Y,
1341 }),
1342 _ => painter.prim(Primitive::Gable {
1343 aabb: Aabb {
1344 min: Vec2::new(
1345 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1346 temp.y - 1,
1347 )
1348 .with_z(alt + height - 2),
1349 max: Vec2::new(self.bounds.min.x - storey_increase, temp.y + 4)
1350 .with_z(alt + height + 1),
1351 },
1352 inset: 3,
1353 dir: Dir::X,
1354 }),
1355 };
1356 let window_min = match self.front {
1357 Dir::Y => Vec2::new(
1358 temp.x,
1359 self.bounds.max.y + storey_increase + self.overhang.abs() - 1,
1360 )
1361 .with_z(alt + previous_height + 2),
1362 Dir::X => Vec2::new(
1363 self.bounds.max.x + storey_increase + self.overhang.abs() - 1,
1364 temp.y,
1365 )
1366 .with_z(alt + previous_height + 2),
1367 Dir::NegY => Vec2::new(
1368 temp.x,
1369 self.bounds.min.y - storey_increase - self.overhang.abs() + 1,
1370 )
1371 .with_z(alt + previous_height + 2),
1372 _ => Vec2::new(
1373 self.bounds.min.x - storey_increase - self.overhang.abs() + 1,
1374 temp.y,
1375 )
1376 .with_z(alt + previous_height + 2),
1377 };
1378 let window_max = match self.front {
1379 Dir::Y => Vec2::new(
1380 temp.x + 3,
1381 self.bounds.max.y + storey_increase + self.overhang.abs(),
1382 )
1383 .with_z(alt + previous_height + 2 + window_height),
1384 Dir::X => Vec2::new(
1385 self.bounds.max.x + storey_increase + self.overhang.abs(),
1386 temp.y + 3,
1387 )
1388 .with_z(alt + previous_height + 2 + window_height),
1389 Dir::NegY => Vec2::new(
1390 temp.x + 3,
1391 self.bounds.min.y - storey_increase - self.overhang.abs() + 2,
1392 )
1393 .with_z(alt + previous_height + 2 + window_height),
1394 _ => Vec2::new(
1395 self.bounds.min.x - storey_increase - self.overhang.abs() + 2,
1396 temp.y + 3,
1397 )
1398 .with_z(alt + previous_height + 2 + window_height),
1399 };
1400 let window = painter.prim(Primitive::Aabb(Aabb {
1401 min: window_min,
1402 max: window_max,
1403 }));
1404 let window_cavity = match self.front {
1405 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1406 min: Vec2::new(temp.x, self.bounds.max.y + storey_increase)
1407 .with_z(alt + previous_height),
1408 max: Vec2::new(
1409 temp.x + 3,
1410 self.bounds.max.y + storey_increase + self.overhang.abs() - 1,
1411 )
1412 .with_z(alt + previous_height + 2 + window_height),
1413 })),
1414 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1415 min: Vec2::new(self.bounds.max.x + storey_increase, temp.y)
1416 .with_z(alt + previous_height),
1417 max: Vec2::new(
1418 self.bounds.max.x + storey_increase + self.overhang.abs() - 1,
1419 temp.y + 3,
1420 )
1421 .with_z(alt + previous_height + 2 + window_height),
1422 })),
1423 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1424 min: Vec2::new(
1425 temp.x,
1426 self.bounds.min.y - storey_increase - self.overhang.abs() + 2,
1427 )
1428 .with_z(alt + previous_height),
1429 max: Vec2::new(temp.x + 3, self.bounds.min.y - storey_increase + 1)
1430 .with_z(alt + previous_height + 2 + window_height),
1431 })),
1432 _ => painter.prim(Primitive::Aabb(Aabb {
1433 min: Vec2::new(
1434 self.bounds.min.x - storey_increase - self.overhang.abs() + 2,
1435 temp.y,
1436 )
1437 .with_z(alt + previous_height),
1438 max: Vec2::new(self.bounds.min.x - storey_increase + 1, temp.y + 3)
1439 .with_z(alt + previous_height + 2 + window_height),
1440 })),
1441 };
1442 let valid_dormer = if self.front.is_y() {
1443 window_min.x > self.bounds.min.x && window_max.x < self.bounds.max.x
1444 } else {
1445 window_min.y > self.bounds.min.y && window_max.y < self.bounds.max.y
1446 };
1447 let window_ori = if self.front.is_y() { 0 } else { 2 };
1448 if valid_dormer {
1449 painter.fill(
1450 painter.prim(Primitive::without(dormer_box, shed)),
1451 Fill::Brick(BlockKind::Wood, Rgb::new(200, 180, 150), 24),
1452 );
1453 painter.fill(
1454 painter.prim(Primitive::without(dormer_roof, shed)),
1455 Fill::Brick(BlockKind::Wood, self.roof_color, 24),
1456 );
1457 painter.fill(window_cavity, Fill::Block(Block::empty()));
1458 painter.fill(
1459 window,
1460 Fill::Block(
1461 Block::air(SpriteKind::Window1)
1462 .with_ori(window_ori)
1463 .unwrap(),
1464 ),
1465 );
1466 }
1467 }
1468 }
1469
1470 if i > 1 {
1473 let floor = if self.overhang < -1 && i > 1 {
1474 match self.front {
1475 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1476 min: (self.bounds.min + 1).with_z(alt + previous_height),
1477 max: Vec2::new(
1478 self.bounds.max.x,
1479 self.bounds.max.y + storey_increase + self.overhang.abs(),
1480 )
1481 .with_z(alt + previous_height + 1),
1482 })),
1483 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1484 min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1)
1485 .with_z(alt + previous_height),
1486 max: Vec2::new(
1487 self.bounds.max.x + storey_increase + self.overhang.abs(),
1488 self.bounds.max.y,
1489 )
1490 .with_z(alt + previous_height + 1),
1491 })),
1492 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1493 min: Vec2::new(
1494 self.bounds.min.x + 1,
1495 self.bounds.min.y + 1 - storey_increase - self.overhang.abs(),
1496 )
1497 .with_z(alt + previous_height),
1498 max: Vec2::new(self.bounds.max.x, self.bounds.max.y)
1499 .with_z(alt + previous_height + 1),
1500 })),
1501 _ => painter.prim(Primitive::Aabb(Aabb {
1502 min: Vec2::new(
1503 self.bounds.min.x + 1 - storey_increase - self.overhang.abs(),
1504 self.bounds.min.y + 1,
1505 )
1506 .with_z(alt + previous_height),
1507 max: Vec2::new(self.bounds.max.x, self.bounds.max.y)
1508 .with_z(alt + previous_height + 1),
1509 })),
1510 }
1511 } else {
1512 match self.front {
1513 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1514 min: (self.bounds.min + 1).with_z(alt + previous_height),
1515 max: (Vec2::new(
1516 self.bounds.max.x,
1517 self.bounds.max.y + storey_increase,
1518 ))
1519 .with_z(alt + previous_height + 1),
1520 })),
1521 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1522 min: (self.bounds.min + 1).with_z(alt + previous_height),
1523 max: (Vec2::new(
1524 self.bounds.max.x + storey_increase,
1525 self.bounds.max.y,
1526 ))
1527 .with_z(alt + previous_height + 1),
1528 })),
1529 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1530 min: Vec2::new(
1531 self.bounds.min.x + 1,
1532 self.bounds.min.y + 1 - storey_increase,
1533 )
1534 .with_z(alt + previous_height),
1535 max: (Vec2::new(self.bounds.max.x, self.bounds.max.y))
1536 .with_z(alt + previous_height + 1),
1537 })),
1538 _ => painter.prim(Primitive::Aabb(Aabb {
1539 min: Vec2::new(
1540 self.bounds.min.x + 1 - storey_increase,
1541 self.bounds.min.y + 1,
1542 )
1543 .with_z(alt + previous_height),
1544 max: (Vec2::new(self.bounds.max.x, self.bounds.max.y))
1545 .with_z(alt + previous_height + 1),
1546 })),
1547 }
1548 };
1549 painter.fill(
1550 floor,
1551 Fill::Block(Block::new(BlockKind::Rock, Rgb::new(89, 44, 14))),
1552 );
1553 }
1554
1555 let base = alt + (storey * (i as i32 - 1)).max(0);
1557 if i % 2 == 0 {
1558 let bed_pos = match self.front {
1560 Dir::X => Vec2::new(half_x, quarter_y),
1561 Dir::NegY => Vec2::new(three_quarter_x, half_y),
1562 _ => Vec2::new(half_x, half_y),
1563 };
1564 let nightstand_pos = Vec2::new(bed_pos.x + 2, bed_pos.y + 1);
1565 painter.sprite(bed_pos.with_z(base), SpriteKind::Bed);
1566 painter.sprite(nightstand_pos.with_z(base), SpriteKind::DrawerSmall);
1568 let rng0 = RandomField::new(0).get(nightstand_pos.with_z(base + 1));
1570 let rng1 = RandomField::new(1).get(nightstand_pos.with_z(base + 1));
1571 painter.owned_resource_sprite(
1572 nightstand_pos.with_z(base + 1),
1573 match rng0 % 5 {
1574 0 => SpriteKind::Lantern,
1575 1 => SpriteKind::PotionMinor,
1576 2 => SpriteKind::VialEmpty,
1577 3 => SpriteKind::Bowl,
1578 _ => SpriteKind::Empty,
1579 },
1580 (rng1 % 4) as u8 * 2,
1581 );
1582 let (wardrobe_pos, drawer_ori) = match self.front {
1584 Dir::Y => (Vec2::new(self.bounds.max.x - 2, self.bounds.min.y + 1), 4),
1585 Dir::X => (Vec2::new(self.bounds.min.x + 6, self.bounds.max.y - 1), 0),
1586 Dir::NegY => (Vec2::new(self.bounds.min.x + 2, self.bounds.max.y - 1), 0),
1587 _ => (Vec2::new(self.bounds.max.x - 6, self.bounds.max.y - 1), 0),
1588 };
1589 painter.rotated_sprite(
1590 wardrobe_pos.with_z(base),
1591 SpriteKind::WardrobeDouble,
1592 drawer_ori,
1593 );
1594 } else {
1595 for dir in DIRS {
1597 let sprite_pos = self.bounds.center() + dir * 5;
1599 let rng0 = RandomField::new(0).get(sprite_pos.with_z(base));
1600 let rng1 = RandomField::new(1).get(sprite_pos.with_z(base));
1601 painter.owned_resource_sprite(
1602 sprite_pos.with_z(base),
1603 match rng0 % 32 {
1604 0..=2 => SpriteKind::Crate,
1605 3..=4 => SpriteKind::CoatRack,
1606 5..=7 => SpriteKind::Pot,
1607 8..=9 => SpriteKind::Lantern,
1608 _ => SpriteKind::Empty,
1609 },
1610 (rng1 % 4) as u8 * 2,
1611 );
1612 }
1613
1614 if self.bounds.max.x - self.bounds.min.x < 16
1615 || self.bounds.max.y - self.bounds.min.y < 16
1616 {
1617 let table_pos = Vec2::new(half_x, half_y);
1618 painter.sprite(table_pos.with_z(base), SpriteKind::TableDining);
1620 for dir in Dir::iter() {
1621 let chair_pos = table_pos + dir.to_vec2();
1622 painter.rotated_sprite(
1623 chair_pos.with_z(base),
1624 SpriteKind::ChairSingle,
1625 dir.opposite().sprite_ori(),
1626 );
1627 }
1628 } else {
1629 let table_pos = match self.front {
1631 Dir::Y => Vec2::new(half_x, three_quarter_y),
1632 Dir::X => Vec2::new(half_x, half_y),
1633 _ => Vec2::new(quarter_x, half_y),
1634 };
1635 painter.sprite(table_pos.with_z(base), SpriteKind::TableDouble);
1636 for dir in Dir::iter() {
1637 let chair_pos = table_pos + dir.select((2, 1)) * dir.to_vec2();
1638 painter.rotated_sprite(
1639 chair_pos.with_z(base),
1640 SpriteKind::ChairSingle,
1641 dir.opposite().sprite_ori(),
1642 );
1643 }
1644 }
1645 let (drawer_pos, drawer_ori) = match self.front {
1647 Dir::Y => (Vec2::new(self.bounds.max.x - 1, self.bounds.max.y - 2), 6),
1648 Dir::X => (Vec2::new(self.bounds.max.x - 2, self.bounds.max.y - 1), 0),
1649 Dir::NegY => (Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 2), 6),
1650 _ => (Vec2::new(self.bounds.min.x + 2, self.bounds.max.y - 1), 0),
1651 };
1652 painter.rotated_sprite(
1653 drawer_pos.with_z(base),
1654 SpriteKind::DrawerLarge,
1655 drawer_ori,
1656 );
1657 }
1658
1659 if i > 1 {
1661 let stair_width = 3;
1662 let previous_floor_height = (storey * (i as i32 - 2)).max(0);
1663 let stair_origin = match self.front {
1664 Dir::Y => self.bounds.min + 1,
1665 Dir::X => self.bounds.min + 1,
1666 Dir::NegY => {
1667 Vec2::new(self.bounds.max.x - 12, self.bounds.max.y - stair_width * 2)
1668 },
1669 _ => Vec2::new(self.bounds.max.x - 12, self.bounds.min.y + 1),
1670 };
1671 let staircase = if i < 2 {
1672 painter.prim(Primitive::Empty)
1673 } else if i % 2 == 0 {
1674 let ramp = {
1675 painter.prim(Primitive::Ramp {
1677 aabb: Aabb {
1678 min: Vec2::new(stair_origin.x + 3, stair_origin.y).with_z(alt + previous_floor_height),
1679 max: Vec2::new(stair_origin.x + 10, stair_origin.y + stair_width).with_z(alt + previous_height + 1),
1680 },
1681 inset: storey,
1682 dir: Dir::X,
1683 })
1684 };
1716 let support = {
1717 painter.prim(Primitive::Aabb(Aabb {
1720 min: Vec2::new(stair_origin.x + 10, stair_origin.y)
1721 .with_z(alt + previous_floor_height),
1722 max: Vec2::new(stair_origin.x + 12, stair_origin.y + stair_width)
1723 .with_z(alt + previous_height + 1),
1724 }))
1725 };
1751 painter.prim(Primitive::union(ramp, support))
1752 } else {
1753 let ramp = {
1754 painter.prim(Primitive::Ramp {
1756 aabb: Aabb {
1757 min: Vec2::new(stair_origin.x + 1, stair_origin.y + stair_width).with_z(alt + previous_floor_height),
1758 max: Vec2::new(stair_origin.x + 8, stair_origin.y + 2 * stair_width).with_z(alt + previous_height + 1),
1759 },
1760 inset: storey,
1761 dir: Dir::NegX,
1762 })
1763 };
1796 let support = {
1797 painter.prim(Primitive::Aabb(Aabb {
1800 min: Vec2::new(stair_origin.x, stair_origin.y + stair_width)
1801 .with_z(alt + previous_floor_height),
1802 max: Vec2::new(stair_origin.x + 2, stair_origin.y + 2 * stair_width)
1803 .with_z(alt + previous_height + 1),
1804 }))
1805 };
1831 painter.prim(Primitive::union(ramp, support))
1832 };
1833 let stairwell = if i < 2 {
1834 painter.prim(Primitive::Empty)
1835 } else if i % 2 == 0 {
1836 painter.prim(Primitive::Aabb(Aabb {
1837 min: Vec2::new(stair_origin.x + 2, stair_origin.y)
1838 .with_z(alt + previous_floor_height + 1),
1839 max: Vec2::new(stair_origin.x + 9, stair_origin.y + stair_width)
1840 .with_z(alt + previous_height + 1),
1841 }))
1842 } else {
1877 painter.prim(Primitive::Aabb(Aabb {
1878 min: Vec2::new(stair_origin.x + 2, stair_origin.y + stair_width)
1879 .with_z(alt + previous_floor_height + 1),
1880 max: Vec2::new(stair_origin.x + 11, stair_origin.y + 2 * stair_width)
1881 .with_z(alt + previous_height + 1),
1882 }))
1883 };
1922
1923 painter.fill(stairwell, Fill::Block(Block::empty()));
1924 painter.fill(
1925 staircase,
1926 Fill::Block(Block::new(BlockKind::Rock, Rgb::new(89, 44, 14))),
1927 );
1928 }
1929 }
1930
1931 painter.fill(
1933 painter.prim(Primitive::Aabb(Aabb {
1934 min: (self.bounds.min - 1).with_z(self.alt - foundations),
1935 max: (self.bounds.max + 2).with_z(self.alt + 1),
1936 })),
1937 Fill::Block(Block::new(BlockKind::Rock, Rgb::new(31, 33, 32))),
1938 );
1939
1940 let fireplace_origin = {
1957 match self.front {
1958 Dir::Y => {
1959 Vec2::new(half_x, self.bounds.min.y + 1)
1960 },
1961 Dir::X => {
1962 Vec2::new(self.bounds.min.x + 1, half_y)
1963 },
1964 Dir::NegY => {
1965 Vec2::new(half_x - 4, self.bounds.max.y - 3)
1966 },
1967 _ => {
1968 Vec2::new(self.bounds.max.x - 3, half_y)
1969 },
1970 }
1971 };
1972 let chimney = match self.front {
1973 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1974 min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt),
1975 max: Vec2::new(fireplace_origin.x + 4, fireplace_origin.y + 3)
1976 .with_z(alt + roof + roof_height + 2),
1977 })),
1978 Dir::X => painter.prim(Primitive::Aabb(Aabb {
1979 min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt),
1980 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 4)
1981 .with_z(alt + roof + roof_height + 2),
1982 })),
1983 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
1984 min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt),
1985 max: Vec2::new(fireplace_origin.x + 4, fireplace_origin.y + 3)
1986 .with_z(alt + roof + roof_height + 2),
1987 })),
1988 _ => painter.prim(Primitive::Aabb(Aabb {
1989 min: Vec2::new(fireplace_origin.x, fireplace_origin.y).with_z(alt),
1990 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 4)
1991 .with_z(alt + roof + roof_height + 2),
1992 })),
1993 };
1994
1995 let chimney_cavity = match self.front {
1996 Dir::Y => painter.prim(Primitive::Aabb(Aabb {
1997 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
1998 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2)
1999 .with_z(alt + roof + roof_height + 2),
2000 })),
2001 Dir::X => painter.prim(Primitive::Aabb(Aabb {
2002 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2003 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3)
2004 .with_z(alt + roof + roof_height + 2),
2005 })),
2006 Dir::NegY => painter.prim(Primitive::Aabb(Aabb {
2007 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2008 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2)
2009 .with_z(alt + roof + roof_height + 2),
2010 })),
2011 _ => painter.prim(Primitive::Aabb(Aabb {
2012 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2013 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3)
2014 .with_z(alt + roof + roof_height + 2),
2015 })),
2016 };
2017 let fire_embers = match self.front {
2018 Dir::Y => Aabb {
2019 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2020 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 1),
2021 },
2022 Dir::X => Aabb {
2023 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2024 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3).with_z(alt + 1),
2025 },
2026 Dir::NegY => Aabb {
2027 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2028 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 1),
2029 },
2030 _ => Aabb {
2031 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2032 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3).with_z(alt + 1),
2033 },
2034 };
2035 let fireplace_cavity = match self.front {
2036 Dir::Y => Aabb {
2037 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2038 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 3).with_z(alt + 2),
2039 },
2040 Dir::X => Aabb {
2041 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 1).with_z(alt),
2042 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 3).with_z(alt + 2),
2043 },
2044 Dir::NegY => Aabb {
2045 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y).with_z(alt),
2046 max: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 2).with_z(alt + 2),
2047 },
2048 _ => Aabb {
2049 min: Vec2::new(fireplace_origin.x, fireplace_origin.y + 1).with_z(alt),
2050 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 3).with_z(alt + 2),
2051 },
2052 };
2053
2054 painter.fill(
2055 chimney,
2056 Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24),
2057 );
2058 painter.fill(chimney_cavity, Fill::Block(Block::empty()));
2059 painter.fill(
2060 painter.prim(Primitive::Aabb(fireplace_cavity)),
2061 Fill::Block(Block::empty()),
2062 );
2063 painter.fill(
2064 painter.prim(Primitive::Aabb(fire_embers)),
2065 Fill::Block(Block::air(SpriteKind::Ember)),
2066 );
2067
2068 if self.levels == 1 {
2070 let bed_pos;
2071 let bed_ori;
2072
2073 if self.bounds.max.x - self.bounds.min.x < 16
2075 || self.bounds.max.y - self.bounds.min.y < 16
2076 {
2077 (bed_pos, bed_ori) = match self.front {
2078 Dir::Y => (Vec2::new(self.bounds.min.x + 4, self.bounds.min.y + 2), 6),
2079 Dir::X => (Vec2::new(self.bounds.min.x + 2, self.bounds.min.y + 4), 0),
2080 Dir::NegY => (Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), 6),
2081 _ => (Vec2::new(self.bounds.max.x - 8, self.bounds.max.y - 2), 0),
2082 };
2083 } else {
2084 (bed_pos, bed_ori) = match self.front {
2085 Dir::Y => (Vec2::new(self.bounds.max.x - 4, self.bounds.min.y + 2), 6),
2086 Dir::X => (Vec2::new(self.bounds.min.x + 8, self.bounds.max.y - 2), 0),
2087 Dir::NegY => (Vec2::new(self.bounds.max.x - 4, self.bounds.max.y - 2), 6),
2088 _ => (Vec2::new(self.bounds.max.x - 8, self.bounds.max.y - 2), 0),
2089 };
2090 }
2091
2092 painter.rotated_sprite(bed_pos.with_z(alt), SpriteKind::Bed, bed_ori);
2093 }
2094
2095 if self.christmas_decorations {
2096 let (wreath_pos, wreath_ori) = match self.front {
2097 Dir::Y => (
2098 Aabb {
2099 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y + 3)
2100 .with_z(alt + 2),
2101 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y + 4)
2102 .with_z(alt + 3),
2103 },
2104 4,
2105 ),
2106 Dir::X => (
2107 Aabb {
2108 min: Vec2::new(fireplace_origin.x + 3, fireplace_origin.y + 1)
2109 .with_z(alt + 2),
2110 max: Vec2::new(fireplace_origin.x + 4, fireplace_origin.y + 2)
2111 .with_z(alt + 3),
2112 },
2113 2,
2114 ),
2115 Dir::NegY => (
2116 Aabb {
2117 min: Vec2::new(fireplace_origin.x + 1, fireplace_origin.y - 1)
2118 .with_z(alt + 2),
2119 max: Vec2::new(fireplace_origin.x + 2, fireplace_origin.y).with_z(alt + 3),
2120 },
2121 0,
2122 ),
2123 _ => (
2124 Aabb {
2125 min: Vec2::new(fireplace_origin.x - 1, fireplace_origin.y + 1)
2126 .with_z(alt + 2),
2127 max: Vec2::new(fireplace_origin.x, fireplace_origin.y + 2).with_z(alt + 3),
2128 },
2129 6,
2130 ),
2131 };
2132 painter.fill(
2133 painter.prim(Primitive::Aabb(wreath_pos)),
2134 Fill::Block(
2135 Block::air(SpriteKind::ChristmasWreath)
2136 .with_ori(wreath_ori)
2137 .unwrap(),
2138 ),
2139 );
2140 }
2141
2142 let doorway1 = match self.front {
2145 Dir::Y => Aabb {
2146 min: Vec2::new(self.door_tile.x - 1, self.bounds.max.y).with_z(alt),
2147 max: Vec2::new(self.door_tile.x + 3, self.bounds.max.y + 1).with_z(alt + 4),
2148 },
2149 Dir::X => Aabb {
2150 min: Vec2::new(self.bounds.max.x, self.door_tile.y - 1).with_z(alt),
2151 max: Vec2::new(self.bounds.max.x + 1, self.door_tile.y + 3).with_z(alt + 4),
2152 },
2153 Dir::NegY => Aabb {
2154 min: Vec2::new(self.door_tile.x - 1, self.bounds.min.y).with_z(alt),
2155 max: Vec2::new(self.door_tile.x + 3, self.bounds.min.y + 1).with_z(alt + 4),
2156 },
2157 _ => Aabb {
2158 min: Vec2::new(self.bounds.min.x, self.door_tile.y - 1).with_z(alt),
2159 max: Vec2::new(self.bounds.min.x + 1, self.door_tile.y + 3).with_z(alt + 4),
2160 },
2161 };
2162 painter.fill(
2163 painter.prim(Primitive::Aabb(doorway1)),
2164 Fill::Brick(BlockKind::Rock, Rgb::new(80, 75, 85), 24),
2165 );
2166
2167 let doorway2 = match self.front {
2169 Dir::Y => Aabb {
2170 min: Vec2::new(self.door_tile.x, self.bounds.max.y).with_z(alt),
2171 max: Vec2::new(self.door_tile.x + 2, self.bounds.max.y + 1).with_z(alt + 3),
2172 },
2173 Dir::X => Aabb {
2174 min: Vec2::new(self.bounds.max.x, self.door_tile.y).with_z(alt),
2175 max: Vec2::new(self.bounds.max.x + 1, self.door_tile.y + 2).with_z(alt + 3),
2176 },
2177 Dir::NegY => Aabb {
2178 min: Vec2::new(self.door_tile.x, self.bounds.min.y).with_z(alt),
2179 max: Vec2::new(self.door_tile.x + 2, self.bounds.min.y + 1).with_z(alt + 3),
2180 },
2181 _ => Aabb {
2182 min: Vec2::new(self.bounds.min.x, self.door_tile.y).with_z(alt),
2183 max: Vec2::new(self.bounds.min.x + 1, self.door_tile.y + 2).with_z(alt + 3),
2184 },
2185 };
2186 painter.fill(
2187 painter.prim(Primitive::Aabb(doorway2)),
2188 Fill::Block(Block::empty()),
2189 );
2190
2191 let (door_gap, door1, door1_ori, door2, door2_ori) = match self.front {
2193 Dir::Y => (
2194 Aabb {
2195 min: Vec2::new(self.door_tile.x - 1, self.bounds.max.y + 1).with_z(alt),
2196 max: Vec2::new(self.door_tile.x + 3, self.bounds.max.y + 4).with_z(alt + 3),
2197 },
2198 Aabb {
2199 min: Vec2::new(self.door_tile.x, self.bounds.max.y).with_z(alt),
2200 max: Vec2::new(self.door_tile.x + 1, self.bounds.max.y + 1).with_z(alt + 1),
2201 },
2202 0,
2203 Aabb {
2204 min: Vec2::new(self.door_tile.x + 1, self.bounds.max.y).with_z(alt),
2205 max: Vec2::new(self.door_tile.x + 2, self.bounds.max.y + 1).with_z(alt + 1),
2206 },
2207 4,
2208 ),
2209 Dir::X => (
2210 Aabb {
2211 min: Vec2::new(self.bounds.max.x + 1, self.door_tile.y - 1).with_z(alt),
2212 max: Vec2::new(self.bounds.max.x + 4, self.door_tile.y + 3).with_z(alt + 3),
2213 },
2214 Aabb {
2215 min: Vec2::new(self.bounds.max.x, self.door_tile.y).with_z(alt),
2216 max: Vec2::new(self.bounds.max.x + 1, self.door_tile.y + 1).with_z(alt + 1),
2217 },
2218 2,
2219 Aabb {
2220 min: Vec2::new(self.bounds.max.x, self.door_tile.y + 1).with_z(alt),
2221 max: Vec2::new(self.bounds.max.x + 1, self.door_tile.y + 2).with_z(alt + 1),
2222 },
2223 6,
2224 ),
2225 Dir::NegY => (
2226 Aabb {
2227 min: Vec2::new(self.door_tile.x - 1, self.bounds.min.y - 4).with_z(alt),
2228 max: Vec2::new(self.door_tile.x + 3, self.bounds.min.y).with_z(alt + 3),
2229 },
2230 Aabb {
2231 min: Vec2::new(self.door_tile.x, self.bounds.min.y).with_z(alt),
2232 max: Vec2::new(self.door_tile.x + 1, self.bounds.min.y + 1).with_z(alt + 1),
2233 },
2234 0,
2235 Aabb {
2236 min: Vec2::new(self.door_tile.x + 1, self.bounds.min.y).with_z(alt),
2237 max: Vec2::new(self.door_tile.x + 2, self.bounds.min.y + 1).with_z(alt + 1),
2238 },
2239 4,
2240 ),
2241 _ => (
2242 Aabb {
2243 min: Vec2::new(self.bounds.min.x - 4, self.door_tile.y - 1).with_z(alt),
2244 max: Vec2::new(self.bounds.min.x, self.door_tile.y + 3).with_z(alt + 3),
2245 },
2246 Aabb {
2247 min: Vec2::new(self.bounds.min.x, self.door_tile.y).with_z(alt),
2248 max: Vec2::new(self.bounds.min.x + 1, self.door_tile.y + 1).with_z(alt + 1),
2249 },
2250 2,
2251 Aabb {
2252 min: Vec2::new(self.bounds.min.x, self.door_tile.y + 1).with_z(alt),
2253 max: Vec2::new(self.bounds.min.x + 1, self.door_tile.y + 2).with_z(alt + 1),
2254 },
2255 6,
2256 ),
2257 };
2258 painter.fill(
2259 painter.prim(Primitive::Aabb(door_gap)),
2260 Fill::Block(Block::air(SpriteKind::Empty)),
2261 );
2262 painter.fill(
2263 painter.prim(Primitive::Aabb(door1)),
2264 Fill::Block(Block::air(SpriteKind::Door).with_ori(door1_ori).unwrap()),
2265 );
2266 painter.fill(
2267 painter.prim(Primitive::Aabb(door2)),
2268 Fill::Block(Block::air(SpriteKind::Door).with_ori(door2_ori).unwrap()),
2269 );
2270 if self.christmas_decorations {
2271 let rng = RandomField::new(0).get(self.door_tile.with_z(alt + 3));
2273 let right = (rng % 2) as i32;
2274 let (door_light_pos, door_light_ori) = match self.front {
2275 Dir::Y => (
2276 Aabb {
2277 min: Vec2::new(self.door_tile.x + right, self.bounds.max.y + 1)
2278 .with_z(alt + 3),
2279 max: Vec2::new(self.door_tile.x + 1 + right, self.bounds.max.y + 2)
2280 .with_z(alt + 4),
2281 },
2282 4,
2283 ),
2284 Dir::X => (
2285 Aabb {
2286 min: Vec2::new(self.bounds.max.x + 1, self.door_tile.y + right)
2287 .with_z(alt + 3),
2288 max: Vec2::new(self.bounds.max.x + 2, self.door_tile.y + 1 + right)
2289 .with_z(alt + 4),
2290 },
2291 2,
2292 ),
2293 Dir::NegY => (
2294 Aabb {
2295 min: Vec2::new(self.door_tile.x + right, self.bounds.min.y - 1)
2296 .with_z(alt + 3),
2297 max: Vec2::new(self.door_tile.x + 1 + right, self.bounds.min.y)
2298 .with_z(alt + 4),
2299 },
2300 0,
2301 ),
2302 _ => (
2303 Aabb {
2304 min: Vec2::new(self.bounds.min.x - 1, self.door_tile.y + right)
2305 .with_z(alt + 3),
2306 max: Vec2::new(self.bounds.min.x, self.door_tile.y + 1 + right)
2307 .with_z(alt + 4),
2308 },
2309 6,
2310 ),
2311 };
2312 painter.fill(
2313 painter.prim(Primitive::Aabb(door_light_pos)),
2314 Fill::Block(
2315 Block::air(SpriteKind::ChristmasOrnament)
2316 .with_ori(door_light_ori)
2317 .unwrap(),
2318 ),
2319 );
2320 }
2321 }
2322}