Skip to main content

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