veloren_world/site/plot/
desert_city_multiplot.rs

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