veloren_world/site2/plot/desert_city_multiplot.rs
1use super::*;
2use crate::{
3 Land,
4 assets::AssetHandle,
5 site2::{
6 gen::{PrimitiveTransform, spiral_staircase},
7 util::sprites::PainterSpriteExt,
8 },
9 util::{DIAGONALS, NEIGHBORS, RandomField, Sampler},
10};
11use common::{
12 generation::{EntityInfo, SpecialEntity},
13 terrain::{Block, BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup},
14};
15use lazy_static::lazy_static;
16use rand::prelude::*;
17use std::sync::Arc;
18use vek::*;
19
20enum PlotKind {
21 MarketHall {
22 floors: i32,
23 towers: [(WatchTower, Vec2<i32>); 4],
24 },
25 Multiple {
26 subplots: Vec<(SubPlotKind, Vec2<i32>)>,
27 },
28}
29
30enum SubPlotKind {
31 WorkshopHouse { floors: i32 },
32 Library,
33 WatchTower(WatchTower),
34 PalmTree,
35 AnimalShed,
36}
37
38struct WatchTower {
39 length: i32,
40 height: i32,
41}
42
43/// Represents house data generated by the `generate()` method
44pub struct DesertCityMultiPlot {
45 /// Tile position of the door tile
46 pub door_tile: Vec2<i32>,
47 /// Axis aligned bounding region for the house
48 bounds: Aabr<i32>,
49 /// Approximate altitude of the door tile
50 pub(crate) alt: i32,
51 diameter: i32,
52 plot_kind: PlotKind,
53 campfire: bool,
54}
55
56impl DesertCityMultiPlot {
57 pub fn generate(
58 land: &Land,
59 rng: &mut impl Rng,
60 site: &Site,
61 door_tile: Vec2<i32>,
62 door_dir: Vec2<i32>,
63 tile_aabr: Aabr<i32>,
64 campfire: bool,
65 alt: Option<i32>,
66 ) -> Self {
67 let door_tile_pos = site.tile_center_wpos(door_tile);
68 let bounds = Aabr {
69 min: site.tile_wpos(tile_aabr.min),
70 max: site.tile_wpos(tile_aabr.max),
71 };
72 let diameter = 10 + (bounds.max.x - bounds.min.x).min(bounds.max.y - bounds.min.y);
73 let plot_kind = match rng.gen_range(0..5) {
74 0 => {
75 let floors = rng.gen_range(2..5);
76 let towers = {
77 let center = bounds.center();
78 let room_length = diameter / 4;
79 let tower_length = diameter / 14;
80 let mut tower = |i| {
81 let tower_center = center
82 + DIAGONALS[i]
83 * (Vec2::new(
84 room_length + tower_length + 1,
85 room_length + 2 * tower_length,
86 ));
87 let height = rng.gen_range(25..35);
88 (
89 WatchTower {
90 length: tower_length,
91 height,
92 },
93 tower_center,
94 )
95 };
96 [tower(0), tower(1), tower(2), tower(3)]
97 };
98 PlotKind::MarketHall { floors, towers }
99 },
100 _ => {
101 let mut subplot_kind = || match rng.gen_range(0..15) {
102 0..=5 => SubPlotKind::WorkshopHouse {
103 floors: rng.gen_range(1..4),
104 },
105 6..=7 => SubPlotKind::Library,
106 8..=9 => SubPlotKind::AnimalShed,
107 10..=11 => SubPlotKind::WatchTower(WatchTower {
108 length: diameter / 14,
109 height: rng.gen_range(25..35),
110 }),
111 _ => SubPlotKind::PalmTree,
112 };
113 let subplot_center = |i| {
114 let corner_pos = bounds.min + diameter / 5;
115 corner_pos + SQUARE_4[i] * (diameter / 2 - 5)
116 };
117
118 let sw_plot = (subplot_kind(), subplot_center(0));
119 let se_plot = (subplot_kind(), subplot_center(1));
120 let nw_plot = (subplot_kind(), subplot_center(2));
121 let ne_plot = (subplot_kind(), subplot_center(3));
122
123 PlotKind::Multiple {
124 subplots: vec![ne_plot, se_plot, sw_plot, nw_plot],
125 }
126 },
127 };
128 Self {
129 bounds,
130 door_tile: door_tile_pos,
131 alt: alt.unwrap_or_else(|| {
132 land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
133 }),
134 diameter,
135 plot_kind,
136 campfire,
137 }
138 }
139}
140
141impl Structure for DesertCityMultiPlot {
142 #[cfg(feature = "use-dyn-lib")]
143 const UPDATE_FN: &'static [u8] = b"render_desertcitymultiplot\0";
144
145 #[cfg_attr(
146 feature = "be-dyn-lib",
147 unsafe(export_name = "render_desertcitymultiplot")
148 )]
149 fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
150 let sandstone = Fill::Sampling(Arc::new(|center| {
151 Some(match (RandomField::new(0).get(center)) % 37 {
152 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
153 9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
154 18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
155 27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
156 _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
157 })
158 }));
159 let sandstone_broken = Fill::Sampling(Arc::new(|center| {
160 Some(match (RandomField::new(0).get(center)) % 42 {
161 0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
162 9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
163 18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
164 27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
165 36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
166 _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
167 })
168 }));
169 let wood = Fill::Brick(BlockKind::Wood, Rgb::new(71, 33, 11), 12);
170 let base = self.alt + 1;
171 let center = self.bounds.center();
172 // Fence
173 painter
174 .aabb(Aabb {
175 min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
176 max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
177 })
178 .union(painter.aabb(Aabb {
179 min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
180 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
181 }))
182 .union(painter.aabb(Aabb {
183 min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
184 max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
185 }))
186 .union(painter.aabb(Aabb {
187 min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
188 max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
189 }))
190 .fill(sandstone_broken.clone());
191
192 // Gate1
193 painter
194 .aabb(Aabb {
195 min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base - 20),
196 max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
197 })
198 .fill(sandstone.clone());
199
200 painter
201 .aabb(Aabb {
202 min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base + 9),
203 max: Vec2::new(self.bounds.max.x, center.y - 1).with_z(base + 10),
204 })
205 .clear();
206 painter
207 .aabb(Aabb {
208 min: Vec2::new(self.bounds.min.x + 1, center.y + 1).with_z(base + 9),
209 max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
210 })
211 .clear();
212 painter
213 .aabb(Aabb {
214 min: Vec2::new(self.bounds.min.x + 2, center.y - 3).with_z(base + 8),
215 max: Vec2::new(self.bounds.max.x - 1, center.y + 3).with_z(base + 10),
216 })
217 .clear();
218 painter
219 .aabb(Aabb {
220 min: Vec2::new(self.bounds.min.x + 3, center.y - 3).with_z(base - 20),
221 max: Vec2::new(self.bounds.max.x - 2, center.y + 3).with_z(base + 10),
222 })
223 .clear();
224 // Gate2
225 painter
226 .aabb(Aabb {
227 min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base - 20),
228 max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
229 })
230 .fill(sandstone.clone());
231 painter
232 .aabb(Aabb {
233 min: Vec2::new(center.x + 2, self.bounds.min.y + 1).with_z(base + 9),
234 max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
235 })
236 .clear();
237 painter
238 .aabb(Aabb {
239 min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base + 9),
240 max: Vec2::new(center.x, self.bounds.max.y).with_z(base + 10),
241 })
242 .clear();
243 painter
244 .aabb(Aabb {
245 min: Vec2::new(center.x - 2, self.bounds.min.y + 2).with_z(base + 8),
246 max: Vec2::new(center.x + 4, self.bounds.max.y - 1).with_z(base + 10),
247 })
248 .clear();
249 painter
250 .aabb(Aabb {
251 min: Vec2::new(center.x - 2, self.bounds.min.y + 3).with_z(base - 20),
252 max: Vec2::new(center.x + 4, self.bounds.max.y - 2).with_z(base + 10),
253 })
254 .clear();
255 // gate clear
256 painter
257 .aabb(Aabb {
258 min: Vec2::new(self.bounds.min.x + 1, center.y - 2).with_z(base),
259 max: Vec2::new(self.bounds.max.x, center.y + 2).with_z(base + 7),
260 })
261 .clear();
262 painter
263 .aabb(Aabb {
264 min: Vec2::new(center.x - 1, self.bounds.min.y + 1).with_z(base),
265 max: Vec2::new(center.x + 3, self.bounds.max.y).with_z(base + 7),
266 })
267 .clear();
268 // Foundation
269 painter
270 .aabb(Aabb {
271 min: (self.bounds.min + 1).with_z(base - 20),
272 max: (self.bounds.max).with_z(base),
273 })
274 .fill(sandstone.clone());
275
276 // buildings
277 match &self.plot_kind {
278 // Market Hall with Watchtowers
279 PlotKind::MarketHall { floors, towers } => {
280 for floor in 0..*floors {
281 let room_height = self.diameter / 6;
282 let floor_level = base + (room_height * floor);
283 let room_length = (self.diameter / 4) - (2 * floor);
284 // Windowsills
285 painter
286 .aabb(Aabb {
287 min: Vec2::new(center.x - room_length - 1, center.y)
288 .with_z(floor_level + 1),
289 max: Vec2::new(center.x + room_length + 1, center.y + 2)
290 .with_z(floor_level + 2),
291 })
292 .fill(wood.clone());
293 // Room
294 painter
295 .aabb(Aabb {
296 min: Vec2::new(center.x - room_length, center.y - room_length + 3)
297 .with_z(floor_level),
298 max: Vec2::new(center.x + room_length, center.y + room_length - 1)
299 .with_z(floor_level + room_height),
300 })
301 .fill(sandstone.clone());
302 // Window Sprites
303 painter
304 .aabb(Aabb {
305 min: Vec2::new(center.x - room_length, center.y)
306 .with_z(floor_level + 2),
307 max: Vec2::new(center.x + room_length, center.y + 2)
308 .with_z(floor_level + 5),
309 })
310 .fill(Fill::Block(
311 Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
312 ));
313 // Clear Room
314 painter
315 .aabb(Aabb {
316 min: Vec2::new(center.x - room_length + 1, center.y - room_length + 4)
317 .with_z(floor_level),
318 max: Vec2::new(center.x + room_length - 1, center.y + room_length - 2)
319 .with_z(floor_level + room_height - 2),
320 })
321 .clear();
322 // Overhang1
323 painter
324 .aabb(Aabb {
325 min: Vec2::new(center.x - room_length + 1, center.y + room_length - 1)
326 .with_z(floor_level + room_height - 1),
327 max: Vec2::new(center.x + room_length - 1, center.y + room_length)
328 .with_z(floor_level + room_height),
329 })
330 .fill(wood.clone());
331 // Overhang2
332 painter
333 .aabb(Aabb {
334 min: Vec2::new(center.x + room_length, center.y - room_length + 2)
335 .with_z(floor_level + room_height - 1),
336 max: Vec2::new(center.x + room_length + 1, center.y + room_length - 2)
337 .with_z(floor_level + room_height),
338 })
339 .fill(wood.clone());
340 // Overhang3
341 painter
342 .aabb(Aabb {
343 min: Vec2::new(center.x - room_length - 1, center.y - room_length + 4)
344 .with_z(floor_level + room_height - 1),
345 max: Vec2::new(center.x - room_length, center.y + room_length - 2)
346 .with_z(floor_level + room_height),
347 })
348 .fill(wood.clone());
349 // Door Frame
350 painter
351 .aabb(Aabb {
352 min: Vec2::new(center.x - 2, center.y + room_length - 1)
353 .with_z(floor_level),
354 max: Vec2::new(center.x + 2, center.y + room_length)
355 .with_z(floor_level + 5),
356 })
357 .fill(sandstone.clone());
358 // Clear Door
359 painter
360 .aabb(Aabb {
361 min: Vec2::new(center.x - 1, center.y + room_length - 2)
362 .with_z(floor_level),
363 max: Vec2::new(center.x + 1, center.y + room_length)
364 .with_z(floor_level + 4),
365 })
366 .clear();
367 // Remove Terrain in front of doors
368 painter
369 .aabb(Aabb {
370 min: Vec2::new(center.x - 2, center.y + room_length)
371 .with_z(floor_level),
372 max: Vec2::new(center.x + 2, center.y + room_length + 4)
373 .with_z(floor_level + 5),
374 })
375 .clear();
376 // Stairs for each storey
377 painter
378 .ramp_inset(
379 Aabb {
380 min: Vec2::new(center.x - room_length, center.y - room_length + 1)
381 .with_z(floor_level),
382 max: Vec2::new(center.x + room_length, center.y - room_length + 3)
383 .with_z(floor_level + room_height),
384 },
385 2 * room_length,
386 Dir::X,
387 )
388 .fill(sandstone.clone());
389 //interior room compartment with entries
390 painter
391 .aabb(Aabb {
392 min: Vec2::new(
393 center.x - (2 * room_length / 3) + 1,
394 center.y - (2 * room_length / 3) + 4,
395 )
396 .with_z(floor_level),
397 max: Vec2::new(
398 center.x + (2 * room_length / 3) - 1,
399 center.y + (2 * room_length / 3) - 2,
400 )
401 .with_z(floor_level + room_height - 2),
402 })
403 .fill(sandstone.clone());
404
405 painter
406 .aabb(Aabb {
407 min: Vec2::new(
408 center.x - (2 * room_length / 3) + 2,
409 center.y - (2 * room_length / 3) + 5,
410 )
411 .with_z(floor_level),
412 max: Vec2::new(
413 center.x + (2 * room_length / 3) - 2,
414 center.y + (2 * room_length / 3) - 3,
415 )
416 .with_z(floor_level + room_height - 2),
417 })
418 .clear();
419
420 painter
421 .aabb(Aabb {
422 min: Vec2::new(
423 center.x - (room_length / 6),
424 center.y - (2 * room_length / 3) + 4,
425 )
426 .with_z(floor_level),
427 max: Vec2::new(
428 center.x + (room_length / 6),
429 center.y + (2 * room_length / 3) - 2,
430 )
431 .with_z(floor_level + 3),
432 })
433 .clear();
434 painter
435 .aabb(Aabb {
436 min: Vec2::new(
437 center.x - (2 * room_length / 3) + 1,
438 center.y + 1 + (room_length / 6),
439 )
440 .with_z(floor_level),
441 max: Vec2::new(
442 center.x + (2 * room_length / 3) - 1,
443 center.y + 1 - (room_length / 6),
444 )
445 .with_z(floor_level + 3),
446 })
447 .clear();
448
449 // interior room Wall Lamps
450 painter
451 .aabb(Aabb {
452 min: Vec2::new(center.x - 1, center.y - (2 * room_length / 3) + 5)
453 .with_z(floor_level + 4),
454 max: Vec2::new(center.x + 1, center.y - (2 * room_length / 3) + 6)
455 .with_z(floor_level + 5),
456 })
457 .fill(Fill::Block(
458 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
459 ));
460
461 painter
462 .aabb(Aabb {
463 min: Vec2::new(center.x - 1, center.y + (2 * room_length / 3) - 2)
464 .with_z(floor_level + 4),
465 max: Vec2::new(center.x + 1, center.y + (2 * room_length / 3) - 1)
466 .with_z(floor_level + 5),
467 })
468 .fill(Fill::Block(
469 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
470 ));
471
472 // Wall Lamps
473 painter
474 .aabb(Aabb {
475 min: Vec2::new(center.x - 1, center.y - room_length + 4)
476 .with_z(floor_level + 4),
477 max: Vec2::new(center.x + 1, center.y - room_length + 5)
478 .with_z(floor_level + 5),
479 })
480 .fill(Fill::Block(
481 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
482 ));
483
484 painter
485 .aabb(Aabb {
486 min: Vec2::new(center.x - 1, center.y + room_length)
487 .with_z(floor_level + 4),
488 max: Vec2::new(center.x + 1, center.y + room_length + 1)
489 .with_z(floor_level + 5),
490 })
491 .fill(Fill::Block(
492 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
493 ));
494
495 // Floor specific stuff
496 match floor {
497 // Ground level room furniture - bank
498 0 => {
499 for dir in NEIGHBORS {
500 let pos = center + dir * 4;
501 painter.owned_resource_sprite(
502 pos.with_z(floor_level),
503 SpriteKind::Crate,
504 0,
505 );
506 }
507 for dir in NEIGHBORS {
508 let pos = center + dir * 8;
509 painter.sprite(
510 pos.with_z(floor_level),
511 SpriteKind::DrawerWoodWoodlandS,
512 );
513 }
514
515 for dir in SQUARE_4 {
516 let corner_pos =
517 Vec2::new(center.x - 4, center.y - room_length + 4);
518 let planter_pos = Vec2::new(
519 corner_pos.x + dir.x * 7,
520 corner_pos.y + dir.y * ((2 * room_length) - 7),
521 );
522 painter.rotated_sprite(
523 planter_pos.with_z(floor_level),
524 SpriteKind::DrawerWoodWoodlandM1,
525 4 - (4 * dir.y) as u8,
526 );
527 }
528 },
529 // First floor room furniture
530 1 => {
531 for dir in NEIGHBORS {
532 let pos = center + dir * 7;
533 painter.sprite(pos.with_z(floor_level), SpriteKind::Planter);
534 }
535
536 for dir in SQUARE_4 {
537 let corner_pos =
538 Vec2::new(center.x - 4, center.y - room_length + 4);
539 let planter_pos = Vec2::new(
540 corner_pos.x + dir.x * 7,
541 corner_pos.y + dir.y * ((2 * room_length) - 7),
542 );
543 painter.rotated_sprite(
544 planter_pos.with_z(floor_level),
545 SpriteKind::DrawerWoodWoodlandS,
546 4 - (4 * dir.y) as u8,
547 );
548 }
549 },
550 _ => {},
551 }
552 // On top floor, carve the roof terrace
553 if floor == (*floors - 1) {
554 painter
555 .aabb(Aabb {
556 min: Vec2::new(
557 center.x - room_length + 1,
558 center.y - room_length + 4,
559 )
560 .with_z(floor_level + room_height - 1),
561 max: Vec2::new(
562 center.x + room_length - 1,
563 center.y + room_length - 2,
564 )
565 .with_z(floor_level + room_height),
566 })
567 .clear();
568 painter
569 .aabb(Aabb {
570 min: Vec2::new(
571 center.x + room_length - 3,
572 center.y - room_length + 1,
573 )
574 .with_z(floor_level + room_height - 1),
575 max: Vec2::new(
576 center.x + room_length - 1,
577 center.y - room_length + 4,
578 )
579 .with_z(floor_level + room_height),
580 })
581 .clear();
582 // Roof Ornament
583 painter
584 .aabb(Aabb {
585 min: Vec2::new(center.x - room_length, center.y + room_length - 2)
586 .with_z(floor_level + room_height),
587 max: Vec2::new(center.x + room_length, center.y + room_length - 1)
588 .with_z(floor_level + room_height + 2),
589 })
590 .fill(sandstone.clone());
591 painter
592 .aabb(Aabb {
593 min: Vec2::new(
594 center.x - room_length + 2,
595 center.y + room_length - 2,
596 )
597 .with_z(floor_level + room_height + 2),
598 max: Vec2::new(
599 center.x + room_length - 2,
600 center.y + room_length - 1,
601 )
602 .with_z(floor_level + room_height + 3),
603 })
604 .fill(sandstone.clone());
605 painter
606 .aabb(Aabb {
607 min: Vec2::new(center.x - 2, center.y + room_length - 2)
608 .with_z(floor_level + room_height + 3),
609 max: Vec2::new(center.x + 2, center.y + room_length - 1)
610 .with_z(floor_level + room_height + 4),
611 })
612 .fill(sandstone.clone());
613 // Wood Beams
614 for dir in SQUARE_4 {
615 let corner_pos =
616 Vec2::new(center.x - room_length + 3, center.y - room_length + 7);
617 let pos = Vec2::new(
618 corner_pos.x + dir.x * ((2 * room_length) - 8),
619 corner_pos.y + dir.y * ((2 * room_length) - 12),
620 );
621 painter
622 .aabb(Aabb {
623 min: pos.with_z(floor_level + room_height - 1),
624 max: (pos + 1)
625 .with_z(floor_level + room_height + (room_height / 2)),
626 })
627 .fill(wood.clone());
628 }
629 painter
630 .aabb(Aabb {
631 min: Vec2::new(
632 center.x - room_length + 2,
633 center.y - room_length + 6,
634 )
635 .with_z(floor_level + room_height + (room_height / 2) - 1),
636 max: Vec2::new(
637 center.x + room_length - 3,
638 center.y + room_length - 3,
639 )
640 .with_z(floor_level + room_height + (room_height / 2)),
641 })
642 .fill(wood.clone());
643
644 painter
645 .aabb(Aabb {
646 min: Vec2::new(
647 center.x - room_length + 3,
648 center.y - room_length + 7,
649 )
650 .with_z(floor_level + room_height + (room_height / 2) - 1),
651 max: Vec2::new(
652 center.x + room_length - 4,
653 center.y + room_length - 4,
654 )
655 .with_z(floor_level + room_height + (room_height / 2)),
656 })
657 .clear();
658
659 for b in 0..(room_length - 3) {
660 painter
661 .aabb(Aabb {
662 min: Vec2::new(
663 center.x - room_length + 3 + (b * 2),
664 center.y - room_length + 5,
665 )
666 .with_z(floor_level + room_height + (room_height / 2)),
667 max: Vec2::new(
668 center.x - room_length + 4 + (b * 2),
669 center.y + room_length - 2,
670 )
671 .with_z(floor_level + room_height + (room_height / 2) + 1),
672 })
673 .fill(wood.clone());
674 }
675 // roof furniture
676 for d in 0..2 {
677 for dir in NEIGHBORS {
678 let pos = center + dir * (3 + d * 3);
679 painter.sprite(
680 pos.with_z(floor_level + room_height - 1),
681 SpriteKind::Planter,
682 );
683 }
684 }
685 }
686 }
687 // WatchTowers
688 for (tower, tower_center) in towers {
689 // Tower Windowsills
690 for h in 0..4 {
691 painter
692 .aabb(Aabb {
693 min: Vec2::new(
694 tower_center.x - 1,
695 tower_center.y - tower.length - 1,
696 )
697 .with_z(base + 8 + (h * (tower.height / 5))),
698 max: Vec2::new(
699 tower_center.x + 1,
700 tower_center.y + tower.length + 1,
701 )
702 .with_z(base + 9 + (h * (tower.height / 5))),
703 })
704 .fill(wood.clone());
705 }
706 for h in 0..4 {
707 painter
708 .aabb(Aabb {
709 min: Vec2::new(
710 tower_center.x - tower.length - 1,
711 tower_center.y - 1,
712 )
713 .with_z(base + 8 + (h * (tower.height / 5))),
714 max: Vec2::new(
715 tower_center.x + tower.length + 1,
716 tower_center.y + 1,
717 )
718 .with_z(base + 9 + (h * (tower.height / 5))),
719 })
720 .fill(wood.clone());
721 }
722 // Tower base
723 painter
724 .aabb(Aabb {
725 min: (tower_center - tower.length - 1).with_z(base - 10),
726 max: (tower_center + tower.length + 1).with_z(base + 6),
727 })
728 .fill(sandstone.clone());
729 // Tower
730 painter
731 .aabb(Aabb {
732 min: (tower_center - tower.length).with_z(base),
733 max: (tower_center + tower.length).with_z(base + tower.height),
734 })
735 .fill(sandstone.clone());
736 // Tower Windows
737 for h in 0..4 {
738 painter
739 .aabb(Aabb {
740 min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length)
741 .with_z(base + 9 + (h * (tower.height / 5))),
742 max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length)
743 .with_z(base + 12 + (h * (tower.height / 5))),
744 })
745 .fill(Fill::Block(
746 Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
747 ));
748 }
749 for h in 0..4 {
750 painter
751 .aabb(Aabb {
752 min: Vec2::new(tower_center.x - tower.length, tower_center.y - 1)
753 .with_z(base + 9 + (h * (tower.height / 5))),
754 max: Vec2::new(tower_center.x + tower.length, tower_center.y + 1)
755 .with_z(base + 12 + (h * (tower.height / 5))),
756 })
757 .fill(Fill::Block(
758 Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
759 ));
760 }
761 // Tower entries1
762 painter
763 .aabb(Aabb {
764 min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
765 .with_z(base - 20),
766 max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
767 .with_z(base + 5),
768 })
769 .fill(sandstone.clone());
770 painter
771 .aabb(Aabb {
772 min: Vec2::new(tower_center.x - tower.length - 4, tower_center.y - 1)
773 .with_z(base),
774 max: Vec2::new(tower_center.x + tower.length + 4, tower_center.y + 1)
775 .with_z(base + 4),
776 })
777 .clear();
778 // Tower entries2
779 painter
780 .aabb(Aabb {
781 min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
782 .with_z(base - 20),
783 max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
784 .with_z(base + 5),
785 })
786 .fill(sandstone.clone());
787 painter
788 .aabb(Aabb {
789 min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length - 4)
790 .with_z(base),
791 max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length + 4)
792 .with_z(base + 4),
793 })
794 .clear();
795 // clear Tower base
796 painter
797 .aabb(Aabb {
798 min: (tower_center - tower.length).with_z(base),
799 max: (tower_center + tower.length).with_z(base + 5),
800 })
801 .clear();
802 // Tower Entry Lamps
803 for d in 0..2 {
804 painter
805 .aabb(Aabb {
806 min: Vec2::new(
807 tower_center.x - 1,
808 tower_center.y - tower.length - 3
809 + (d * ((2 * tower.length) + 6)),
810 )
811 .with_z(base + 4),
812 max: Vec2::new(
813 tower_center.x + 1,
814 tower_center.y - tower.length - 2
815 + (d * ((2 * tower.length) + 4)),
816 )
817 .with_z(base + 5),
818 })
819 .fill(Fill::Block(
820 Block::air(SpriteKind::WallLampSmall)
821 .with_ori(0 + (4 * d) as u8)
822 .unwrap(),
823 ));
824 }
825 // Platform
826 painter
827 .aabb(Aabb {
828 min: (tower_center - tower.length - 2).with_z(base + tower.height),
829 max: (tower_center + tower.length + 2).with_z(base + tower.height + 4),
830 })
831 .fill(sandstone.clone());
832 painter
833 .aabb(Aabb {
834 min: (tower_center - tower.length - 1).with_z(base + tower.height + 2),
835 max: (tower_center + tower.length + 1).with_z(base + tower.height + 4),
836 })
837 .clear();
838
839 painter
840 .aabb(Aabb {
841 min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
842 .with_z(base + tower.height + 3),
843 max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
844 .with_z(base + tower.height + 4),
845 })
846 .clear();
847 painter
848 .aabb(Aabb {
849 min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
850 .with_z(base + tower.height + 3),
851 max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
852 .with_z(base + tower.height + 4),
853 })
854 .clear();
855
856 // clear Tower
857 let tower_clear = painter.aabb(Aabb {
858 min: (tower_center - tower.length + 1).with_z(base),
859 max: (tower_center + tower.length - 1).with_z(base + tower.height + 3),
860 });
861 tower_clear.clear();
862 // stairway
863 let stair_radius = tower.length + 1;
864 let stairs_clear = painter.aabb(Aabb {
865 min: (tower_center - stair_radius).with_z(base),
866 max: (tower_center + stair_radius).with_z(base + tower.height + 2),
867 });
868 stairs_clear
869 .sample(spiral_staircase(
870 tower_center.with_z(base + tower.height + 2),
871 stair_radius as f32,
872 0.5,
873 (2 * tower.length) as f32,
874 ))
875 .intersect(tower_clear)
876 .fill(sandstone.clone());
877 }
878 },
879 PlotKind::Multiple { subplots } => {
880 // House, Workshop, Library, Palm, WatchTower
881 for (subplot_kind, subplot_center) in subplots {
882 match subplot_kind {
883 // House or Workshop (one storey house)
884 SubPlotKind::WorkshopHouse { floors } => {
885 for floor in 0..*floors {
886 let room_height = self.diameter / 6;
887 let floor_level = base + (room_height * floor);
888 let room_length = (self.diameter / 7) - (2 * floor);
889 // Windowsills
890 painter
891 .aabb(Aabb {
892 min: Vec2::new(
893 subplot_center.x - room_length - 1,
894 subplot_center.y,
895 )
896 .with_z(floor_level + 1),
897 max: Vec2::new(
898 subplot_center.x + room_length + 1,
899 subplot_center.y + 2,
900 )
901 .with_z(floor_level + 2),
902 })
903 .fill(wood.clone());
904 // Room
905 painter
906 .aabb(Aabb {
907 min: Vec2::new(
908 subplot_center.x - room_length,
909 subplot_center.y - room_length + 3,
910 )
911 .with_z(floor_level),
912 max: Vec2::new(
913 subplot_center.x + room_length,
914 subplot_center.y + room_length - 1,
915 )
916 .with_z(floor_level + room_height),
917 })
918 .fill(sandstone.clone());
919 // Window Sprites
920 painter
921 .aabb(Aabb {
922 min: Vec2::new(
923 subplot_center.x - room_length,
924 subplot_center.y,
925 )
926 .with_z(floor_level + 2),
927 max: Vec2::new(
928 subplot_center.x + room_length,
929 subplot_center.y + 2,
930 )
931 .with_z(floor_level + 5),
932 })
933 .fill(Fill::Block(
934 Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
935 ));
936 // Clear Room
937 painter
938 .aabb(Aabb {
939 min: Vec2::new(
940 subplot_center.x - room_length + 1,
941 subplot_center.y - room_length + 4,
942 )
943 .with_z(floor_level),
944 max: Vec2::new(
945 subplot_center.x + room_length - 1,
946 subplot_center.y + room_length - 2,
947 )
948 .with_z(floor_level + room_height - 2),
949 })
950 .clear();
951 // Overhang1
952 painter
953 .aabb(Aabb {
954 min: Vec2::new(
955 subplot_center.x - room_length + 1,
956 subplot_center.y + room_length - 1,
957 )
958 .with_z(floor_level + room_height - 1),
959 max: Vec2::new(
960 subplot_center.x + room_length - 1,
961 subplot_center.y + room_length,
962 )
963 .with_z(floor_level + room_height),
964 })
965 .fill(wood.clone());
966 // Overhang2
967 painter
968 .aabb(Aabb {
969 min: Vec2::new(
970 subplot_center.x + room_length,
971 subplot_center.y - room_length + 2,
972 )
973 .with_z(floor_level + room_height - 1),
974 max: Vec2::new(
975 subplot_center.x + room_length + 1,
976 subplot_center.y + room_length - 2,
977 )
978 .with_z(floor_level + room_height),
979 })
980 .fill(wood.clone());
981 // Overhang3
982 painter
983 .aabb(Aabb {
984 min: Vec2::new(
985 subplot_center.x - room_length - 1,
986 subplot_center.y - room_length + 4,
987 )
988 .with_z(floor_level + room_height - 1),
989 max: Vec2::new(
990 subplot_center.x - room_length,
991 subplot_center.y + room_length - 2,
992 )
993 .with_z(floor_level + room_height),
994 })
995 .fill(wood.clone());
996 // Door Frame
997 painter
998 .aabb(Aabb {
999 min: Vec2::new(
1000 subplot_center.x - 2,
1001 subplot_center.y + room_length - 1,
1002 )
1003 .with_z(floor_level),
1004 max: Vec2::new(
1005 subplot_center.x + 2,
1006 subplot_center.y + room_length,
1007 )
1008 .with_z(floor_level + 5),
1009 })
1010 .fill(sandstone.clone());
1011 // Clear Door
1012 painter
1013 .aabb(Aabb {
1014 min: Vec2::new(
1015 subplot_center.x - 1,
1016 subplot_center.y + room_length - 2,
1017 )
1018 .with_z(floor_level),
1019 max: Vec2::new(
1020 subplot_center.x + 1,
1021 subplot_center.y + room_length,
1022 )
1023 .with_z(floor_level + 4),
1024 })
1025 .clear();
1026 // Remove Terrain in front of doors
1027 painter
1028 .aabb(Aabb {
1029 min: Vec2::new(
1030 subplot_center.x - 2,
1031 subplot_center.y + room_length,
1032 )
1033 .with_z(floor_level),
1034 max: Vec2::new(
1035 subplot_center.x + 2,
1036 subplot_center.y + room_length + 4,
1037 )
1038 .with_z(floor_level + 5),
1039 })
1040 .clear();
1041 // Stairs for each storey
1042 painter
1043 .ramp_inset(
1044 Aabb {
1045 min: Vec2::new(
1046 subplot_center.x - room_length,
1047 subplot_center.y - room_length + 1,
1048 )
1049 .with_z(floor_level),
1050 max: Vec2::new(
1051 subplot_center.x + room_length,
1052 subplot_center.y - room_length + 3,
1053 )
1054 .with_z(floor_level + room_height),
1055 },
1056 2 * room_length,
1057 Dir::X,
1058 )
1059 .fill(sandstone.clone());
1060 // Carve Roof Terrace
1061 if floor == floors - 1 {
1062 painter
1063 .aabb(Aabb {
1064 min: Vec2::new(
1065 subplot_center.x - room_length + 1,
1066 subplot_center.y - room_length + 4,
1067 )
1068 .with_z(floor_level + room_height - 1),
1069 max: Vec2::new(
1070 subplot_center.x + room_length - 1,
1071 subplot_center.y + room_length - 2,
1072 )
1073 .with_z(floor_level + room_height),
1074 })
1075 .clear();
1076 painter
1077 .aabb(Aabb {
1078 min: Vec2::new(
1079 subplot_center.x + room_length - 3,
1080 subplot_center.y - room_length + 1,
1081 )
1082 .with_z(floor_level + room_height - 1),
1083 max: Vec2::new(
1084 subplot_center.x + room_length - 1,
1085 subplot_center.y - room_length + 4,
1086 )
1087 .with_z(floor_level + room_height),
1088 })
1089 .clear();
1090 // Roof Ornament
1091 painter
1092 .aabb(Aabb {
1093 min: Vec2::new(
1094 subplot_center.x - room_length,
1095 subplot_center.y + room_length - 2,
1096 )
1097 .with_z(floor_level + room_height),
1098 max: Vec2::new(
1099 subplot_center.x + room_length,
1100 subplot_center.y + room_length - 1,
1101 )
1102 .with_z(floor_level + room_height + 2),
1103 })
1104 .fill(sandstone.clone());
1105 painter
1106 .aabb(Aabb {
1107 min: Vec2::new(
1108 subplot_center.x - room_length + 2,
1109 subplot_center.y + room_length - 2,
1110 )
1111 .with_z(floor_level + room_height + 2),
1112 max: Vec2::new(
1113 subplot_center.x + room_length - 2,
1114 subplot_center.y + room_length - 1,
1115 )
1116 .with_z(floor_level + room_height + 3),
1117 })
1118 .fill(sandstone.clone());
1119 painter
1120 .aabb(Aabb {
1121 min: Vec2::new(
1122 subplot_center.x - 2,
1123 subplot_center.y + room_length - 2,
1124 )
1125 .with_z(floor_level + room_height + 3),
1126 max: Vec2::new(
1127 subplot_center.x + 2,
1128 subplot_center.y + room_length - 1,
1129 )
1130 .with_z(floor_level + room_height + 4),
1131 })
1132 .fill(sandstone.clone());
1133 };
1134 // furniture
1135 if *floors == 1 {
1136 // Workshop in one-storey buildings
1137 painter
1138 .aabb(Aabb {
1139 min: (subplot_center - 2).with_z(floor_level),
1140 max: (subplot_center + 2)
1141 .with_z(floor_level + room_height + 1),
1142 })
1143 .fill(sandstone.clone());
1144
1145 painter
1146 .aabb(Aabb {
1147 min: (subplot_center - 2).with_z(floor_level + 1),
1148 max: (subplot_center + 2)
1149 .with_z(floor_level + room_height - 2),
1150 })
1151 .clear();
1152 painter
1153 .aabb(Aabb {
1154 min: (subplot_center - 1).with_z(floor_level),
1155 max: (subplot_center + 1)
1156 .with_z(floor_level + room_height + 1),
1157 })
1158 .clear();
1159 painter
1160 .aabb(Aabb {
1161 min: (subplot_center - 1).with_z(floor_level - 1),
1162 max: (subplot_center + 1).with_z(floor_level),
1163 })
1164 .fill(Fill::Block(Block::air(SpriteKind::Ember)));
1165 let mut stations = vec![
1166 SpriteKind::CraftingBench,
1167 SpriteKind::Forge,
1168 SpriteKind::SpinningWheel,
1169 SpriteKind::TanningRack,
1170 SpriteKind::Loom,
1171 SpriteKind::Anvil,
1172 SpriteKind::DismantlingBench,
1173 SpriteKind::RepairBench,
1174 ];
1175 'outer: for d in 0..2 {
1176 for dir in NEIGHBORS {
1177 if stations.is_empty() {
1178 break 'outer;
1179 }
1180 let position = subplot_center + dir * (4 + d * 2);
1181 let cr_station = stations.swap_remove(
1182 RandomField::new(0).get(position.with_z(base))
1183 as usize
1184 % stations.len(),
1185 );
1186 painter
1187 .sprite(position.with_z(floor_level), cr_station);
1188 }
1189 }
1190 } else {
1191 // kitchen, bath, living room in buildings with 2-3 storeys
1192 match floor {
1193 0 => {
1194 // kitchen
1195 // cupboards / ovens / cushions / jugs
1196 for d in 0..2 {
1197 let a_pos = Vec2::new(
1198 subplot_center.x + 3 - (d * 6),
1199 subplot_center.y - room_length + 4,
1200 );
1201 painter.rotated_sprite(
1202 a_pos.with_z(floor_level),
1203 match (RandomField::new(0)
1204 .get(a_pos.with_z(floor_level)))
1205 % 2
1206 {
1207 0 => SpriteKind::CupboardArabic,
1208 _ => SpriteKind::OvenArabic,
1209 },
1210 4,
1211 );
1212 let b_pos = Vec2::new(
1213 subplot_center.x + 3 - (d * 6),
1214 subplot_center.y + room_length - 3,
1215 );
1216 painter.rotated_sprite(
1217 b_pos.with_z(floor_level),
1218 match (RandomField::new(0)
1219 .get(b_pos.with_z(floor_level)))
1220 % 4
1221 {
1222 0 => SpriteKind::CupboardArabic,
1223 1 => SpriteKind::OvenArabic,
1224 2 => SpriteKind::CushionArabic,
1225 _ => SpriteKind::JugArabic,
1226 },
1227 0,
1228 );
1229 // wall tables with varying items
1230 let c_pos = Vec2::new(
1231 subplot_center.x - room_length
1232 + 1
1233 + (d * ((2 * room_length) - 3)),
1234 subplot_center.y,
1235 );
1236 painter.rotated_sprite(
1237 c_pos.with_z(floor_level),
1238 SpriteKind::WallTableArabic,
1239 6 - (4 * d) as u8,
1240 );
1241 painter.owned_resource_sprite(
1242 c_pos.with_z(floor_level + 1),
1243 match (RandomField::new(0)
1244 .get(c_pos.with_z(floor_level)))
1245 % 5
1246 {
1247 0 => SpriteKind::Melon,
1248 1 => SpriteKind::JugAndBowlArabic,
1249 2 => SpriteKind::Bowl,
1250 3 => SpriteKind::JugArabic,
1251 _ => SpriteKind::VialEmpty,
1252 },
1253 6 - (4 * d) as u8,
1254 );
1255 }
1256 // CookingPot, Cauldron
1257 painter.sprite(
1258 (subplot_center - 2).with_z(floor_level),
1259 SpriteKind::CookingPot,
1260 );
1261 painter.sprite(
1262 (subplot_center + 2).with_z(floor_level),
1263 SpriteKind::Cauldron,
1264 );
1265 },
1266 1 => {
1267 // living room
1268 // canape
1269 let canape_pos = Vec2::new(
1270 subplot_center.x - 4 + 7,
1271 subplot_center.y - room_length
1272 + 5
1273 + ((2 * room_length) - 9),
1274 );
1275
1276 painter.rotated_sprite(
1277 canape_pos.with_z(floor_level),
1278 SpriteKind::CanapeArabic,
1279 4_u8,
1280 );
1281
1282 // bed
1283 let bed_pos = Vec2::new(
1284 subplot_center.x - 5,
1285 subplot_center.y - room_length + 4,
1286 );
1287
1288 painter.bed_desert(bed_pos.with_z(floor_level), Dir::X);
1289
1290 for d in 0..2 {
1291 // other sprites
1292 let b_pos = Vec2::new(
1293 subplot_center.x + 3 - (d * 7),
1294 subplot_center.y - room_length
1295 + 5
1296 + (d * ((2 * room_length) - 9)),
1297 );
1298 painter.sprite(
1299 b_pos.with_z(floor_level),
1300 match (RandomField::new(0)
1301 .get(b_pos.with_z(floor_level - d)))
1302 % 6
1303 {
1304 0 => SpriteKind::TableArabicLarge,
1305 1 => SpriteKind::DecorSetArabic,
1306 2 => SpriteKind::DrawerWoodWoodlandS,
1307 3 => SpriteKind::CoatrackWoodWoodland,
1308 4 => SpriteKind::TableArabicSmall,
1309 _ => SpriteKind::SepareArabic,
1310 },
1311 )
1312 }
1313 },
1314 _ => {
1315 // bath
1316 // wall tables with varying items
1317 for d in 0..2 {
1318 // wall tables with varying items
1319 let a_pos = Vec2::new(
1320 subplot_center.x - room_length
1321 + 1
1322 + (d * ((2 * room_length) - 3)),
1323 subplot_center.y,
1324 );
1325 painter.rotated_sprite(
1326 a_pos.with_z(floor_level),
1327 SpriteKind::WallTableArabic,
1328 6 - (4 * d) as u8,
1329 );
1330 painter.owned_resource_sprite(
1331 a_pos.with_z(floor_level + 1),
1332 match (RandomField::new(0)
1333 .get(a_pos.with_z(floor_level)))
1334 % 4
1335 {
1336 0 => SpriteKind::Bowl,
1337 1 => SpriteKind::VialEmpty,
1338 2 => SpriteKind::JugArabic,
1339 _ => SpriteKind::JugAndBowlArabic,
1340 },
1341 6 - (4 * d) as u8,
1342 );
1343 // fountain
1344 painter.sprite(
1345 subplot_center.with_z(floor_level),
1346 SpriteKind::FountainArabic,
1347 )
1348 }
1349 },
1350 }
1351 }
1352 // Wall Lamps
1353 painter
1354 .aabb(Aabb {
1355 min: Vec2::new(
1356 subplot_center.x - 1,
1357 subplot_center.y - room_length + 4,
1358 )
1359 .with_z(floor_level + 4),
1360 max: Vec2::new(
1361 subplot_center.x + 1,
1362 subplot_center.y - room_length + 5,
1363 )
1364 .with_z(floor_level + 5),
1365 })
1366 .fill(Fill::Block(
1367 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
1368 ));
1369 painter
1370 .aabb(Aabb {
1371 min: Vec2::new(
1372 subplot_center.x - 1,
1373 subplot_center.y + room_length,
1374 )
1375 .with_z(floor_level + 4),
1376 max: Vec2::new(
1377 subplot_center.x + 1,
1378 subplot_center.y + room_length + 1,
1379 )
1380 .with_z(floor_level + 5),
1381 })
1382 .fill(Fill::Block(
1383 Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
1384 ));
1385 }
1386 },
1387 SubPlotKind::Library => {
1388 // Library with stairway
1389 let tower_length = self.diameter / 14;
1390 let tower_height = 23;
1391 let bldg_a_center = Vec2::new(
1392 subplot_center.x - (2 * tower_length) + 1,
1393 subplot_center.y,
1394 );
1395 let bldg_b_center =
1396 Vec2::new(subplot_center.x + tower_length + 1, subplot_center.y);
1397 // Library windowsills
1398 let sq_corner = Vec2::new(
1399 bldg_b_center.x - 3,
1400 bldg_b_center.y - (2 * tower_length) + 1,
1401 );
1402 for dir in SQUARE_4 {
1403 for h in 0..2 {
1404 for n in 0..2 {
1405 let window_sill_pos = Vec2::new(
1406 sq_corner.x - 1 + (dir.x * 7),
1407 sq_corner.y - 2 + (dir.y * ((4 * tower_length) + 1)),
1408 );
1409 painter
1410 .aabb(Aabb {
1411 min: Vec2::new(
1412 window_sill_pos.x - 1,
1413 window_sill_pos.y,
1414 )
1415 .with_z(
1416 base + 1 + (n * (tower_height / 2)) + (h * 4),
1417 ),
1418 max: Vec2::new(
1419 window_sill_pos.x + 1,
1420 window_sill_pos.y + 1,
1421 )
1422 .with_z(
1423 base + 2 + (n * (tower_height / 2)) + (h * 4),
1424 ),
1425 })
1426 .fill(wood.clone());
1427 }
1428 }
1429 }
1430 for w in 0..2 {
1431 for h in 0..2 {
1432 for n in 0..2 {
1433 painter
1434 .aabb(Aabb {
1435 min: Vec2::new(
1436 bldg_b_center.x + (2 * tower_length),
1437 bldg_b_center.y - 4 + (6 * w),
1438 )
1439 .with_z(
1440 base + 1 + (n * (tower_height / 2)) + (h * 4),
1441 ),
1442 max: Vec2::new(
1443 bldg_b_center.x + (2 * tower_length) + 1,
1444 bldg_b_center.y - 2 + (6 * w),
1445 )
1446 .with_z(
1447 base + 2 + (n * (tower_height / 2)) + (h * 4),
1448 ),
1449 })
1450 .fill(wood.clone());
1451 }
1452 }
1453 }
1454 // Library
1455 painter
1456 .aabb(Aabb {
1457 min: (bldg_b_center - (2 * tower_length)).with_z(base),
1458 max: (bldg_b_center + (2 * tower_length))
1459 .with_z(base + tower_height),
1460 })
1461 .fill(sandstone.clone());
1462 // Library windows
1463 for dir in SQUARE_4 {
1464 for h in 0..2 {
1465 for n in 0..2 {
1466 let window_pos = Vec2::new(
1467 sq_corner.x - 1 + (dir.x * 7),
1468 sq_corner.y - 1 + (dir.y * ((4 * tower_length) - 1)),
1469 );
1470 painter
1471 .aabb(Aabb {
1472 min: Vec2::new(window_pos.x - 1, window_pos.y)
1473 .with_z(
1474 base + 2
1475 + (n * (tower_height / 2))
1476 + (h * 4),
1477 ),
1478 max: Vec2::new(window_pos.x + 1, window_pos.y + 1)
1479 .with_z(
1480 base + 5
1481 + (n * (tower_height / 2))
1482 + (h * 4),
1483 ),
1484 })
1485 .fill(Fill::Block(
1486 Block::air(SpriteKind::WindowArabic)
1487 .with_ori(2)
1488 .unwrap(),
1489 ));
1490 }
1491 }
1492 }
1493 for h in 0..2 {
1494 for n in 0..2 {
1495 painter
1496 .aabb(Aabb {
1497 min: Vec2::new(
1498 bldg_b_center.x + (2 * tower_length) - 1,
1499 bldg_b_center.y - 4,
1500 )
1501 .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
1502 max: Vec2::new(
1503 bldg_b_center.x + (2 * tower_length),
1504 bldg_b_center.y - 2,
1505 )
1506 .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1507 })
1508 .fill(Fill::Block(
1509 Block::air(SpriteKind::WindowArabic)
1510 .with_ori(4)
1511 .unwrap(),
1512 ));
1513 painter
1514 .aabb(Aabb {
1515 min: Vec2::new(
1516 bldg_b_center.x + (2 * tower_length) - 1,
1517 bldg_b_center.y + 2,
1518 )
1519 .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
1520 max: Vec2::new(
1521 bldg_b_center.x + (2 * tower_length),
1522 bldg_b_center.y + 4,
1523 )
1524 .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1525 })
1526 .fill(Fill::Block(
1527 Block::air(SpriteKind::WindowArabic)
1528 .with_ori(4)
1529 .unwrap(),
1530 ));
1531 }
1532 }
1533 // roof carve out
1534 painter
1535 .aabb(Aabb {
1536 min: Vec2::new(
1537 bldg_b_center.x - (2 * tower_length) + 2,
1538 bldg_b_center.y - (2 * tower_length) + 1,
1539 )
1540 .with_z(base + tower_height - 1),
1541 max: Vec2::new(
1542 bldg_b_center.x + (2 * tower_length) - 1,
1543 bldg_b_center.y + (2 * tower_length) - 1,
1544 )
1545 .with_z(base + tower_height),
1546 })
1547 .clear();
1548
1549 // Clear Library
1550 painter
1551 .aabb(Aabb {
1552 min: (bldg_b_center - (2 * tower_length) + 1).with_z(base),
1553 max: (bldg_b_center + (2 * tower_length) - 1)
1554 .with_z(base + tower_height - 2),
1555 })
1556 .clear();
1557 // Library Floor
1558 painter
1559 .aabb(Aabb {
1560 min: (bldg_b_center - (2 * tower_length))
1561 .with_z(base + (tower_height / 2) - 1),
1562 max: (bldg_b_center + (2 * tower_length))
1563 .with_z(base + (tower_height / 2)),
1564 })
1565 .fill(sandstone.clone());
1566 // furniture
1567 for h in 0..2 {
1568 for dir in NEIGHBORS {
1569 let sprite_pos = (bldg_b_center
1570 + (dir * ((2 * tower_length) - 4)))
1571 .with_z(base + ((tower_height / 2) * h));
1572 match (RandomField::new(0).get(sprite_pos)) % 9 {
1573 0 => painter
1574 .sprite(sprite_pos, SpriteKind::DrawerWoodWoodlandS),
1575 1 => painter
1576 .sprite(sprite_pos, SpriteKind::ChairWoodWoodland),
1577 2 => painter
1578 .sprite(sprite_pos, SpriteKind::ChairWoodWoodland),
1579 3 => painter
1580 .sprite(sprite_pos, SpriteKind::CoatrackWoodWoodland),
1581 4 => painter.mirrored2(
1582 sprite_pos,
1583 Dir::X,
1584 SpriteKind::BenchWoodWoodland,
1585 ),
1586 5 => painter.mirrored2(
1587 sprite_pos,
1588 Dir::X,
1589 SpriteKind::BenchWoodWoodlandGreen1,
1590 ),
1591 6 => painter.mirrored2(
1592 sprite_pos,
1593 Dir::X,
1594 SpriteKind::BenchWoodWoodlandGreen2,
1595 ),
1596 7 => painter.mirrored2(
1597 sprite_pos,
1598 Dir::X,
1599 SpriteKind::BenchWoodWoodlandGreen3,
1600 ),
1601 _ => painter.sprite(
1602 sprite_pos,
1603 SpriteKind::DiningtableWoodWoodlandRound,
1604 ),
1605 }
1606 }
1607
1608 for d in 0..2 {
1609 for e in 0..2 {
1610 // bookshelfs
1611 let a_pos = Vec2::new(
1612 bldg_b_center.x - 3 + (e * 6),
1613 bldg_b_center.y - (2 * tower_length)
1614 + 1
1615 + (d * ((2 * (2 * tower_length)) - 3)),
1616 );
1617 painter.rotated_sprite(
1618 a_pos.with_z(base + 1 + ((tower_height / 2) * h)),
1619 SpriteKind::BookshelfArabic,
1620 4 - (4 * d) as u8,
1621 );
1622 }
1623 }
1624 }
1625 // Library Wall Lamps
1626 for h in 0..2 {
1627 for n in 0..2 {
1628 painter
1629 .aabb(Aabb {
1630 min: Vec2::new(
1631 bldg_b_center.x + (2 * tower_length) - 2,
1632 bldg_b_center.y - 1,
1633 )
1634 .with_z(base + 4 + (n * (tower_height / 2)) + (h * 4)),
1635 max: Vec2::new(
1636 bldg_b_center.x + (2 * tower_length) - 1,
1637 bldg_b_center.y + 1,
1638 )
1639 .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1640 })
1641 .fill(Fill::Block(
1642 Block::air(SpriteKind::WallLampSmall)
1643 .with_ori(6)
1644 .unwrap(),
1645 ));
1646 }
1647 }
1648 // Library Roof Overhangs
1649 for d in 0..2 {
1650 painter
1651 .aabb(Aabb {
1652 min: Vec2::new(
1653 bldg_b_center.x - (2 * tower_length) + 1,
1654 bldg_b_center.y + (2 * tower_length)
1655 - (d * ((4 * tower_length) + 1)),
1656 )
1657 .with_z(base + tower_height - 1),
1658 max: Vec2::new(
1659 bldg_b_center.x + (2 * tower_length) - 1,
1660 bldg_b_center.y + (2 * tower_length) + 1
1661 - (d * ((4 * tower_length) + 1)),
1662 )
1663 .with_z(base + tower_height),
1664 })
1665 .fill(wood.clone());
1666 }
1667 painter
1668 .aabb(Aabb {
1669 min: Vec2::new(
1670 bldg_b_center.x + (2 * tower_length),
1671 bldg_b_center.y - (2 * tower_length) + 1,
1672 )
1673 .with_z(base + tower_height - 1),
1674 max: Vec2::new(
1675 bldg_b_center.x + (2 * tower_length) + 1,
1676 bldg_b_center.y + (2 * tower_length) - 1,
1677 )
1678 .with_z(base + tower_height),
1679 })
1680 .fill(wood.clone());
1681 // Stairs to Tower Top
1682 painter
1683 .ramp(
1684 Aabb {
1685 min: Vec2::new(
1686 bldg_b_center.x - (2 * tower_length) + 2,
1687 bldg_b_center.y - 1,
1688 )
1689 .with_z(base + tower_height - 1),
1690 max: Vec2::new(
1691 bldg_b_center.x - (2 * tower_length) + 4,
1692 bldg_b_center.y + 1,
1693 )
1694 .with_z(base + tower_height + 1),
1695 },
1696 Dir::NegX,
1697 )
1698 .fill(sandstone.clone());
1699 // Library Top Room
1700 painter
1701 .aabb(Aabb {
1702 min: Vec2::new(
1703 bldg_b_center.x - tower_length + 2,
1704 bldg_b_center.y - tower_length,
1705 )
1706 .with_z(base + tower_height - 1),
1707 max: Vec2::new(
1708 bldg_b_center.x + tower_length + 2,
1709 bldg_b_center.y + tower_length,
1710 )
1711 .with_z(base + tower_height + tower_length),
1712 })
1713 .fill(sandstone.clone());
1714 painter
1715 .aabb(Aabb {
1716 min: Vec2::new(
1717 bldg_b_center.x - tower_length + 3,
1718 bldg_b_center.y - tower_length + 1,
1719 )
1720 .with_z(base + tower_height - 1),
1721 max: Vec2::new(
1722 bldg_b_center.x + tower_length + 1,
1723 bldg_b_center.y + tower_length - 1,
1724 )
1725 .with_z(base + tower_height + tower_length - 2),
1726 })
1727 .clear();
1728 painter
1729 .aabb(Aabb {
1730 min: Vec2::new(
1731 bldg_b_center.x - tower_length + 3,
1732 bldg_b_center.y - tower_length + 1,
1733 )
1734 .with_z(base + tower_height + tower_length - 1),
1735 max: Vec2::new(
1736 bldg_b_center.x + tower_length + 1,
1737 bldg_b_center.y + tower_length - 1,
1738 )
1739 .with_z(base + tower_height + tower_length),
1740 })
1741 .clear();
1742 painter
1743 .aabb(Aabb {
1744 min: Vec2::new(
1745 bldg_b_center.x + 1,
1746 bldg_b_center.y - tower_length - 1,
1747 )
1748 .with_z(base + tower_height - 1),
1749 max: Vec2::new(
1750 bldg_b_center.x + 3,
1751 bldg_b_center.y + tower_length + 1,
1752 )
1753 .with_z(base + tower_height + 2),
1754 })
1755 .clear();
1756 painter
1757 .aabb(Aabb {
1758 min: Vec2::new(
1759 bldg_b_center.x - tower_length + 1,
1760 bldg_b_center.y - 1,
1761 )
1762 .with_z(base + tower_height - 1),
1763 max: Vec2::new(
1764 bldg_b_center.x + tower_length + 3,
1765 bldg_b_center.y + 1,
1766 )
1767 .with_z(base + tower_height + 2),
1768 })
1769 .clear();
1770
1771 // Library Top Room Overhangs
1772 for d in 0..2 {
1773 painter
1774 .aabb(Aabb {
1775 min: Vec2::new(
1776 bldg_b_center.x - tower_length + 3,
1777 bldg_b_center.y + tower_length
1778 - (d * ((2 * tower_length) + 1)),
1779 )
1780 .with_z(base + tower_height + tower_length - 1),
1781 max: Vec2::new(
1782 bldg_b_center.x + tower_length + 1,
1783 bldg_b_center.y + tower_length + 1
1784 - (d * ((2 * tower_length) + 1)),
1785 )
1786 .with_z(base + tower_height + tower_length),
1787 })
1788 .fill(wood.clone());
1789 }
1790 painter
1791 .aabb(Aabb {
1792 min: Vec2::new(
1793 bldg_b_center.x + tower_length + 2,
1794 bldg_b_center.y - tower_length + 1,
1795 )
1796 .with_z(base + tower_height + tower_length - 1),
1797 max: Vec2::new(
1798 bldg_b_center.x + tower_length + 3,
1799 bldg_b_center.y + tower_length - 1,
1800 )
1801 .with_z(base + tower_height + tower_length),
1802 })
1803 .fill(wood.clone());
1804 // Library Top Room Roof Ornament
1805 painter
1806 .aabb(Aabb {
1807 min: Vec2::new(
1808 bldg_b_center.x + tower_length + 1,
1809 bldg_b_center.y - tower_length,
1810 )
1811 .with_z(base + tower_height + tower_length),
1812 max: Vec2::new(
1813 bldg_b_center.x + tower_length + 2,
1814 bldg_b_center.y + tower_length,
1815 )
1816 .with_z(base + tower_height + tower_length + 2),
1817 })
1818 .fill(sandstone.clone());
1819 painter
1820 .aabb(Aabb {
1821 min: Vec2::new(
1822 bldg_b_center.x + tower_length + 1,
1823 bldg_b_center.y - tower_length + 2,
1824 )
1825 .with_z(base + tower_height + tower_length + 2),
1826 max: Vec2::new(
1827 bldg_b_center.x + tower_length + 2,
1828 bldg_b_center.y + tower_length - 2,
1829 )
1830 .with_z(base + tower_height + tower_length + 3),
1831 })
1832 .fill(sandstone.clone());
1833 painter
1834 .aabb(Aabb {
1835 min: Vec2::new(
1836 bldg_b_center.x + tower_length + 1,
1837 bldg_b_center.y - 1,
1838 )
1839 .with_z(base + tower_height + tower_length + 3),
1840 max: Vec2::new(
1841 bldg_b_center.x + tower_length + 2,
1842 bldg_b_center.y + 1,
1843 )
1844 .with_z(base + tower_height + tower_length + 4),
1845 })
1846 .fill(sandstone.clone());
1847 // Stairway Tower windowsills
1848 for h in 0..2 {
1849 painter
1850 .aabb(Aabb {
1851 min: Vec2::new(
1852 bldg_a_center.x - 1,
1853 bldg_a_center.y - tower_length - 1,
1854 )
1855 .with_z(base + (tower_height / 2) - 4 + (h * 6)),
1856 max: Vec2::new(
1857 bldg_a_center.x + 1,
1858 bldg_a_center.y + tower_length + 1,
1859 )
1860 .with_z(base + (tower_height / 2) - 3 + (h * 6)),
1861 })
1862 .fill(wood.clone());
1863 }
1864 // Stairway Tower base
1865 painter
1866 .aabb(Aabb {
1867 min: (bldg_a_center - tower_length - 1).with_z(base),
1868 max: (bldg_a_center + tower_length + 1).with_z(base + 6),
1869 })
1870 .fill(sandstone.clone());
1871 // Tower
1872 painter
1873 .aabb(Aabb {
1874 min: (bldg_a_center - tower_length).with_z(base),
1875 max: (bldg_a_center + tower_length).with_z(base + tower_height),
1876 })
1877 .fill(sandstone.clone());
1878 // Stairway Tower windows
1879 for h in 0..2 {
1880 painter
1881 .aabb(Aabb {
1882 min: Vec2::new(
1883 bldg_a_center.x - 1,
1884 bldg_a_center.y - tower_length,
1885 )
1886 .with_z(base + (tower_height / 2) - 3 + (h * 6)),
1887 max: Vec2::new(
1888 bldg_a_center.x + 1,
1889 bldg_a_center.y + tower_length,
1890 )
1891 .with_z(base + (tower_height / 2) + (h * 6)),
1892 })
1893 .fill(Fill::Block(
1894 Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
1895 ));
1896 }
1897 // Stairway Tower entry
1898 painter
1899 .aabb(Aabb {
1900 min: Vec2::new(
1901 bldg_a_center.x - 2,
1902 bldg_a_center.y - tower_length - 2,
1903 )
1904 .with_z(base),
1905 max: Vec2::new(
1906 bldg_a_center.x + 2,
1907 bldg_a_center.y + tower_length + 2,
1908 )
1909 .with_z(base + 5),
1910 })
1911 .fill(sandstone.clone());
1912 // clear Stairway Tower entry
1913 painter
1914 .aabb(Aabb {
1915 min: Vec2::new(
1916 bldg_a_center.x - 1,
1917 bldg_a_center.y - tower_length - 5,
1918 )
1919 .with_z(base),
1920 max: Vec2::new(
1921 bldg_a_center.x + 1,
1922 bldg_a_center.y + tower_length + 5,
1923 )
1924 .with_z(base + 4),
1925 })
1926 .clear();
1927 // clear Stairway Tower base
1928 painter
1929 .aabb(Aabb {
1930 min: (bldg_a_center - tower_length).with_z(base),
1931 max: (bldg_a_center + tower_length).with_z(base + 6),
1932 })
1933 .clear();
1934 // Stairway Tower Entry Lamps
1935 for d in 0..2 {
1936 painter
1937 .aabb(Aabb {
1938 min: Vec2::new(
1939 bldg_a_center.x - 1,
1940 bldg_a_center.y - tower_length - 3
1941 + (d * ((2 * tower_length) + 6)),
1942 )
1943 .with_z(base + 4),
1944 max: Vec2::new(
1945 bldg_a_center.x + 1,
1946 bldg_a_center.y - tower_length - 2
1947 + (d * ((2 * tower_length) + 4)),
1948 )
1949 .with_z(base + 5),
1950 })
1951 .fill(Fill::Block(
1952 Block::air(SpriteKind::WallLampSmall)
1953 .with_ori(0 + (4 * d) as u8)
1954 .unwrap(),
1955 ));
1956 }
1957 // Library entries from Stairway Tower
1958 for h in 0..2 {
1959 painter
1960 .aabb(Aabb {
1961 min: Vec2::new(
1962 bldg_a_center.x + tower_length - 1,
1963 bldg_a_center.y - 1,
1964 )
1965 .with_z(base + (h * (tower_height / 2))),
1966 max: Vec2::new(
1967 bldg_a_center.x + tower_length + 1,
1968 bldg_a_center.y + 1,
1969 )
1970 .with_z(base + (h * (tower_height / 2)) + 3),
1971 })
1972 .clear();
1973 }
1974 // Stairway Tower Platform
1975 painter
1976 .aabb(Aabb {
1977 min: (bldg_a_center - tower_length - 2)
1978 .with_z(base + tower_height),
1979 max: (bldg_a_center + tower_length + 2)
1980 .with_z(base + tower_height + 3),
1981 })
1982 .fill(sandstone.clone());
1983
1984 painter
1985 .aabb(Aabb {
1986 min: (bldg_a_center - tower_length - 1)
1987 .with_z(base + tower_height + 2),
1988 max: (bldg_a_center + tower_length + 1)
1989 .with_z(base + tower_height + 3),
1990 })
1991 .clear();
1992
1993 painter
1994 .aabb(Aabb {
1995 min: Vec2::new(
1996 bldg_a_center.x + tower_length + 1,
1997 bldg_a_center.y - 1,
1998 )
1999 .with_z(base + tower_height + 2),
2000 max: Vec2::new(
2001 bldg_a_center.x + tower_length + 2,
2002 bldg_a_center.y + 1,
2003 )
2004 .with_z(base + tower_height + 3),
2005 })
2006 .clear();
2007 // clear Tower
2008 let tower_clear = painter.aabb(Aabb {
2009 min: (bldg_a_center - tower_length + 1).with_z(base),
2010 max: (bldg_a_center + tower_length - 1)
2011 .with_z(base + tower_height + 3),
2012 });
2013 tower_clear.clear();
2014 // stairway
2015 let stair_radius = tower_length + 1;
2016 let stairs_clear = painter.aabb(Aabb {
2017 min: (bldg_a_center - stair_radius).with_z(base),
2018 max: (bldg_a_center + stair_radius).with_z(base + tower_height + 2),
2019 });
2020 stairs_clear
2021 .sample(spiral_staircase(
2022 bldg_a_center.with_z(base + tower_height + 2),
2023 stair_radius as f32,
2024 0.5,
2025 ((2 * tower_length) - 1) as f32,
2026 ))
2027 .intersect(tower_clear)
2028 .fill(sandstone.clone());
2029 },
2030 SubPlotKind::WatchTower(tower) => {
2031 // WatchTower Windowsills
2032 for h in 0..4 {
2033 painter
2034 .aabb(Aabb {
2035 min: Vec2::new(
2036 subplot_center.x - 1,
2037 subplot_center.y - tower.length - 1,
2038 )
2039 .with_z(base + 8 + (h * (tower.height / 5))),
2040 max: Vec2::new(
2041 subplot_center.x + 1,
2042 subplot_center.y + tower.length + 1,
2043 )
2044 .with_z(base + 9 + (h * (tower.height / 5))),
2045 })
2046 .fill(wood.clone());
2047 }
2048 for h in 0..4 {
2049 painter
2050 .aabb(Aabb {
2051 min: Vec2::new(
2052 subplot_center.x - tower.length - 1,
2053 subplot_center.y - 1,
2054 )
2055 .with_z(base + 8 + (h * (tower.height / 5))),
2056 max: Vec2::new(
2057 subplot_center.x + tower.length + 1,
2058 subplot_center.y + 1,
2059 )
2060 .with_z(base + 9 + (h * (tower.height / 5))),
2061 })
2062 .fill(wood.clone());
2063 }
2064 // Watch Tower base
2065 painter
2066 .aabb(Aabb {
2067 min: (subplot_center - tower.length - 1).with_z(base),
2068 max: (subplot_center + tower.length + 1).with_z(base + 6),
2069 })
2070 .fill(sandstone.clone());
2071 // WatchTower
2072 painter
2073 .aabb(Aabb {
2074 min: (subplot_center - tower.length).with_z(base),
2075 max: (subplot_center + tower.length)
2076 .with_z(base + tower.height),
2077 })
2078 .fill(sandstone.clone());
2079 // WatchTower Windows
2080 for h in 0..4 {
2081 painter
2082 .aabb(Aabb {
2083 min: Vec2::new(
2084 subplot_center.x - 1,
2085 subplot_center.y - tower.length,
2086 )
2087 .with_z(base + 9 + (h * (tower.height / 5))),
2088 max: Vec2::new(
2089 subplot_center.x + 1,
2090 subplot_center.y + tower.length,
2091 )
2092 .with_z(base + 12 + (h * (tower.height / 5))),
2093 })
2094 .fill(Fill::Block(
2095 Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
2096 ));
2097 }
2098 for h in 0..4 {
2099 painter
2100 .aabb(Aabb {
2101 min: Vec2::new(
2102 subplot_center.x - tower.length,
2103 subplot_center.y - 1,
2104 )
2105 .with_z(base + 9 + (h * (tower.height / 5))),
2106 max: Vec2::new(
2107 subplot_center.x + tower.length,
2108 subplot_center.y + 1,
2109 )
2110 .with_z(base + 12 + (h * (tower.height / 5))),
2111 })
2112 .fill(Fill::Block(
2113 Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
2114 ));
2115 }
2116 // Watch Tower entries
2117 painter
2118 .aabb(Aabb {
2119 min: Vec2::new(
2120 subplot_center.x - 2,
2121 subplot_center.y - tower.length - 2,
2122 )
2123 .with_z(base),
2124 max: Vec2::new(
2125 subplot_center.x + 2,
2126 subplot_center.y + tower.length + 2,
2127 )
2128 .with_z(base + 5),
2129 })
2130 .fill(sandstone.clone());
2131 painter
2132 .aabb(Aabb {
2133 min: Vec2::new(
2134 subplot_center.x - 1,
2135 subplot_center.y - tower.length - 2,
2136 )
2137 .with_z(base),
2138 max: Vec2::new(
2139 subplot_center.x + 1,
2140 subplot_center.y + tower.length + 2,
2141 )
2142 .with_z(base + 4),
2143 })
2144 .clear();
2145 // clear Watch Tower base
2146 painter
2147 .aabb(Aabb {
2148 min: (subplot_center - tower.length).with_z(base),
2149 max: (subplot_center + tower.length).with_z(base + 5),
2150 })
2151 .clear();
2152 // WatchTower Entry Lamps
2153 for d in 0..2 {
2154 painter
2155 .aabb(Aabb {
2156 min: Vec2::new(
2157 subplot_center.x - 1,
2158 subplot_center.y - tower.length - 3
2159 + (d * ((2 * tower.length) + 6)),
2160 )
2161 .with_z(base + 4),
2162 max: Vec2::new(
2163 subplot_center.x + 1,
2164 subplot_center.y - tower.length - 2
2165 + (d * ((2 * tower.length) + 4)),
2166 )
2167 .with_z(base + 5),
2168 })
2169 .fill(Fill::Block(
2170 Block::air(SpriteKind::WallLampSmall)
2171 .with_ori(0 + (4 * d) as u8)
2172 .unwrap(),
2173 ));
2174 }
2175 // Watchtower Platform
2176 painter
2177 .aabb(Aabb {
2178 min: (subplot_center - tower.length - 2)
2179 .with_z(base + tower.height),
2180 max: (subplot_center + tower.length + 2)
2181 .with_z(base + tower.height + 4),
2182 })
2183 .fill(sandstone.clone());
2184
2185 painter
2186 .aabb(Aabb {
2187 min: (subplot_center - tower.length - 1)
2188 .with_z(base + tower.height + 2),
2189 max: (subplot_center + tower.length + 1)
2190 .with_z(base + tower.height + 4),
2191 })
2192 .clear();
2193
2194 painter
2195 .aabb(Aabb {
2196 min: Vec2::new(
2197 subplot_center.x - tower.length - 2,
2198 subplot_center.y - 2,
2199 )
2200 .with_z(base + tower.height + 3),
2201 max: Vec2::new(
2202 subplot_center.x + tower.length + 2,
2203 subplot_center.y + 2,
2204 )
2205 .with_z(base + tower.height + 4),
2206 })
2207 .clear();
2208 painter
2209 .aabb(Aabb {
2210 min: Vec2::new(
2211 subplot_center.x - 2,
2212 subplot_center.y - tower.length - 2,
2213 )
2214 .with_z(base + tower.height + 3),
2215 max: Vec2::new(
2216 subplot_center.x + 2,
2217 subplot_center.y + tower.length + 2,
2218 )
2219 .with_z(base + tower.height + 4),
2220 })
2221 .clear();
2222
2223 // clear Tower
2224 let tower_clear = painter.aabb(Aabb {
2225 min: (subplot_center - tower.length + 1).with_z(base),
2226 max: (subplot_center + tower.length - 1)
2227 .with_z(base + tower.height + 3),
2228 });
2229 tower_clear.clear();
2230 // stairway
2231 let stair_radius = tower.length + 1;
2232 let stairs_clear = painter.aabb(Aabb {
2233 min: (subplot_center - stair_radius).with_z(base),
2234 max: (subplot_center + stair_radius)
2235 .with_z(base + tower.height + 2),
2236 });
2237 stairs_clear
2238 .sample(spiral_staircase(
2239 subplot_center.with_z(base + tower.height + 2),
2240 stair_radius as f32,
2241 0.5,
2242 (2 * tower.length) as f32,
2243 ))
2244 .intersect(tower_clear)
2245 .fill(sandstone.clone());
2246 },
2247 SubPlotKind::AnimalShed => {
2248 // fenced animal shed
2249 let shed_length = self.diameter / 14;
2250 // small fence
2251 painter
2252 .aabb(Aabb {
2253 min: Vec2::new(
2254 subplot_center.x - (2 * shed_length),
2255 subplot_center.y - (2 * shed_length) - 1,
2256 )
2257 .with_z(base),
2258 max: Vec2::new(
2259 subplot_center.x - (2 * shed_length) + 1,
2260 subplot_center.y + (2 * shed_length) + 1,
2261 )
2262 .with_z(base + 2),
2263 })
2264 .union(
2265 painter.aabb(Aabb {
2266 min: Vec2::new(
2267 subplot_center.x + (2 * shed_length) + 1,
2268 subplot_center.y - (2 * shed_length) - 1,
2269 )
2270 .with_z(base),
2271 max: Vec2::new(
2272 subplot_center.x + (2 * shed_length) + 2,
2273 subplot_center.y + (2 * shed_length) + 1,
2274 )
2275 .with_z(base + 2),
2276 }),
2277 )
2278 .union(
2279 painter.aabb(Aabb {
2280 min: Vec2::new(
2281 subplot_center.x - (2 * shed_length),
2282 subplot_center.y - (2 * shed_length) - 1,
2283 )
2284 .with_z(base),
2285 max: Vec2::new(
2286 subplot_center.x + (2 * shed_length) + 2,
2287 subplot_center.y - (2 * shed_length),
2288 )
2289 .with_z(base + 2),
2290 }),
2291 )
2292 .union(
2293 painter.aabb(Aabb {
2294 min: Vec2::new(
2295 subplot_center.x - (2 * shed_length),
2296 subplot_center.y + (2 * shed_length),
2297 )
2298 .with_z(base),
2299 max: Vec2::new(
2300 subplot_center.x + (2 * shed_length) + 2,
2301 subplot_center.y + (2 * shed_length) + 1,
2302 )
2303 .with_z(base + 2),
2304 }),
2305 )
2306 .fill(sandstone_broken.clone());
2307 // shed
2308 painter
2309 .aabb(Aabb {
2310 min: Vec2::new(
2311 subplot_center.x - shed_length + 2,
2312 subplot_center.y - shed_length,
2313 )
2314 .with_z(base),
2315 max: Vec2::new(
2316 subplot_center.x + shed_length + 2,
2317 subplot_center.y + shed_length,
2318 )
2319 .with_z(base + shed_length + 1),
2320 })
2321 .fill(sandstone.clone());
2322 painter
2323 .aabb(Aabb {
2324 min: Vec2::new(
2325 subplot_center.x - shed_length + 3,
2326 subplot_center.y - shed_length + 1,
2327 )
2328 .with_z(base),
2329 max: Vec2::new(
2330 subplot_center.x + shed_length + 1,
2331 subplot_center.y + shed_length - 1,
2332 )
2333 .with_z(base + shed_length - 1),
2334 })
2335 .clear();
2336 painter
2337 .aabb(Aabb {
2338 min: Vec2::new(
2339 subplot_center.x - shed_length + 3,
2340 subplot_center.y - shed_length + 1,
2341 )
2342 .with_z(base + shed_length),
2343 max: Vec2::new(
2344 subplot_center.x + shed_length + 1,
2345 subplot_center.y + shed_length - 1,
2346 )
2347 .with_z(base + shed_length + 1),
2348 })
2349 .clear();
2350 painter
2351 .aabb(Aabb {
2352 min: Vec2::new(
2353 subplot_center.x + 1,
2354 subplot_center.y - shed_length - 1,
2355 )
2356 .with_z(base),
2357 max: Vec2::new(
2358 subplot_center.x + 3,
2359 subplot_center.y + shed_length + 1,
2360 )
2361 .with_z(base + 3),
2362 })
2363 .clear();
2364 painter
2365 .aabb(Aabb {
2366 min: Vec2::new(
2367 subplot_center.x - shed_length + 1,
2368 subplot_center.y - 1,
2369 )
2370 .with_z(base),
2371 max: Vec2::new(
2372 subplot_center.x + shed_length + 3,
2373 subplot_center.y + 1,
2374 )
2375 .with_z(base + 3),
2376 })
2377 .clear();
2378 // Shed Overhangs
2379 for d in 0..2 {
2380 painter
2381 .aabb(Aabb {
2382 min: Vec2::new(
2383 subplot_center.x - shed_length + 3,
2384 subplot_center.y + shed_length
2385 - (d * ((2 * shed_length) + 1)),
2386 )
2387 .with_z(base + shed_length - 1),
2388 max: Vec2::new(
2389 subplot_center.x + shed_length + 1,
2390 subplot_center.y + shed_length + 1
2391 - (d * ((2 * shed_length) + 1)),
2392 )
2393 .with_z(base + shed_length),
2394 })
2395 .fill(wood.clone());
2396 }
2397 painter
2398 .aabb(Aabb {
2399 min: Vec2::new(
2400 subplot_center.x + shed_length + 2,
2401 subplot_center.y - shed_length + 1,
2402 )
2403 .with_z(base + shed_length - 1),
2404 max: Vec2::new(
2405 subplot_center.x + shed_length + 3,
2406 subplot_center.y + shed_length - 1,
2407 )
2408 .with_z(base + shed_length),
2409 })
2410 .fill(wood.clone());
2411 // Shed Roof Ornament
2412 painter
2413 .aabb(Aabb {
2414 min: Vec2::new(
2415 subplot_center.x + shed_length + 1,
2416 subplot_center.y - shed_length,
2417 )
2418 .with_z(base + shed_length),
2419 max: Vec2::new(
2420 subplot_center.x + shed_length + 2,
2421 subplot_center.y + shed_length,
2422 )
2423 .with_z(base + shed_length + 2),
2424 })
2425 .fill(sandstone.clone());
2426 painter
2427 .aabb(Aabb {
2428 min: Vec2::new(
2429 subplot_center.x + shed_length + 1,
2430 subplot_center.y - shed_length + 2,
2431 )
2432 .with_z(base + shed_length + 2),
2433 max: Vec2::new(
2434 subplot_center.x + shed_length + 2,
2435 subplot_center.y + shed_length - 2,
2436 )
2437 .with_z(base + shed_length + 3),
2438 })
2439 .fill(sandstone.clone());
2440 painter
2441 .aabb(Aabb {
2442 min: Vec2::new(
2443 subplot_center.x + shed_length + 1,
2444 subplot_center.y - 1,
2445 )
2446 .with_z(base + shed_length + 3),
2447 max: Vec2::new(
2448 subplot_center.x + shed_length + 2,
2449 subplot_center.y + 1,
2450 )
2451 .with_z(base + shed_length + 4),
2452 })
2453 .fill(sandstone.clone());
2454 },
2455 SubPlotKind::PalmTree => {
2456 // Palm
2457 painter
2458 .cylinder(Aabb {
2459 min: (subplot_center - 8).with_z(base),
2460 max: (subplot_center + 14).with_z(base + 1),
2461 })
2462 .fill(sandstone.clone());
2463 painter
2464 .cylinder(Aabb {
2465 min: (subplot_center - 7).with_z(base),
2466 max: (subplot_center + 13).with_z(base + 1),
2467 })
2468 .fill(Fill::Brick(BlockKind::Rock, Rgb::new(235, 178, 99), 12));
2469 for p in 0..2 {
2470 let palm_pos = (subplot_center + 3 + (2 * p)).with_z(base);
2471 lazy_static! {
2472 pub static ref PALM: AssetHandle<StructuresGroup> =
2473 PrefabStructure::load_group("trees.palms");
2474 }
2475 let rng = RandomField::new(0).get(palm_pos) % 10;
2476 let palm = PALM.read();
2477 let palm = palm[rng as usize % palm.len()].clone();
2478 painter
2479 .prim(Primitive::Prefab(Box::new(palm.clone())))
2480 .translate(palm_pos)
2481 .fill(Fill::Prefab(Box::new(palm), palm_pos, rng));
2482 }
2483 },
2484 }
2485 }
2486 // spawn campfire in some multiplots that are not markethall
2487 let campfire_pos = (center).with_z(base + 1);
2488 if self.campfire {
2489 painter.spawn(
2490 EntityInfo::at(campfire_pos.map(|e| e as f32))
2491 .into_special(SpecialEntity::Waypoint),
2492 )
2493 }
2494 },
2495 }
2496 }
2497}