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}