Merge branch 'savannah_town_tweaks' into 'master'

savannah_town_tweaks

See merge request veloren/veloren!4619
This commit is contained in:
flo
2024-11-08 17:40:11 +00:00
32 changed files with 629 additions and 1801 deletions

View File

@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Npcs can catch you stealing.
- Button to show unknown recipes.
- Water splashes and river particles.
- Custom furniture for Coastal Houses
### Changed
@ -73,6 +74,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- RiposteMelee attacks have a recovery phase after missing
- Switched from Rodio to Kira
- Ambient noise now gets filtered when underwater.
- Renamed Site Savannah Pit to Savannah Town
- Replaced building Savannah Pit with Savannah Town Airship Dock
### Removed

View File

@ -3,7 +3,7 @@
// Biomes: Grassland, Forest, Desert, Snowland, Lake, Mountain, Ocean, Jungle, Savannah, Taiga
// planned biomes: Swamp
// Number after biome indicates weighting; higher numbers are less frequent
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahPit), Cave, Dungeon(Old or Gnarling), or Void [none]
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahTown), Cave, Dungeon, or Void [none]
// Music states: Activity(Explore or Combat)
// Combat music is looped. Needs three files: start, loop, and end. Start contains leadup to the loop.
// Artist format is ("Artist", "https://website.com/"). If no website, use None.
@ -22,7 +22,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
)),
@ -33,7 +33,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
)),
@ -44,7 +44,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("FaceImplosion", "https://www.youtube.com/c/FaceImplosion"),
)),
@ -55,7 +55,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Crow", None),
)),
@ -66,7 +66,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("GeekyGami", "https://geekygami.newgrounds.com/audio/"),
)),
@ -77,7 +77,7 @@
timing: None,
weather: Rain,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Oolnokk", "https://soundcloud.com/walkerhallplaysthegeetar"),
)),
@ -88,7 +88,7 @@
timing: None,
weather: Rain,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Oolnokk", "https://soundcloud.com/walkerhallplaysthegeetar"),
)),
@ -99,7 +99,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Oolnokk", "https://soundcloud.com/walkerhallplaysthegeetar"),
)),
@ -110,7 +110,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Oolnokk", "https://soundcloud.com/walkerhallplaysthegeetar"),
)),
@ -121,7 +121,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
)),
@ -132,7 +132,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Eden", "https://soundcloud.com/usernumberuser"),
)),
@ -143,7 +143,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Aeronic", "https://soundcloud.com/aeronic"),
)),
@ -154,7 +154,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Aeronic", "https://soundcloud.com/aeronic"),
)),
@ -165,7 +165,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("badbbad", "https://soundcloud.com/tomerbarnea"),
)),
@ -176,7 +176,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("badbbad", "https://soundcloud.com/tomerbarnea"),
)),
@ -187,7 +187,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("badbbad", "https://soundcloud.com/tomerbarnea"),
)),
@ -198,7 +198,7 @@
timing: Day,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("GeekyGami", "https://geekygami.newgrounds.com/audio/"),
)),
@ -209,7 +209,7 @@
timing: Night,
weather: None,
biomes:[],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Crow", None),
)),
@ -220,7 +220,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("Tobias Thy - (Thy SFX)", "https://soundcloud.com/thyofficial"),
)),
@ -231,7 +231,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
)),
@ -242,7 +242,7 @@
timing: Night,
weather: None,
biomes: [],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahPit)],
sites: [Void, Settlement(Default), Settlement(CliffTown), Settlement(DesertCity), Settlement(SavannahTown)],
music_state: Activity(Explore),
artist: ("DragonDee", "https://soundcloud.com/deanna-rusnock"),
)),

View File

@ -3,7 +3,7 @@
// Biomes: Grassland, Forest, Desert, Snowland, Lake, Mountain, Ocean, Jungle, Savannah, Taiga
// planned biomes: Swamp
// Number after biome indicates weighting; higher numbers are less frequent
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahPit), Cave, Dungeon(Old or Gnarling), or Void [none]
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahTown), Cave, Dungeon, or Void [none]
// Music states: Activity(Explore or Combat)
// Combat music is looped. Needs three files: start, loop, and end. Start contains leadup to the loop.
// Artist format is ("Artist", "https://website.com/"). If no website, use None.

View File

@ -3,7 +3,7 @@
// Biomes: Grassland, Forest, Desert, Snowland, Lake, Mountain, Ocean, Jungle, Savannah, Taiga
// planned biomes: Swamp
// Number after biome indicates weighting; higher numbers are less frequent
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahPit), Cave, Dungeon(Old or Gnarling), or Void [none]
// Sites: Settlement(Default, CliffTown, DesertCity, or SavannahTown), Cave, Dungeon, or Void [none]
// Music states: Activity(Explore or Combat)
// Combat music is looped. Needs three files: start, loop, and end. Start contains leadup to the loop.
// Artist format is ("Artist", "https://website.com/"). If no website, use None.
@ -537,7 +537,7 @@
biomes: [],
sites: [
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("Stone Music Productions", "https://www.stonemusicproductions.com/"),
@ -555,7 +555,7 @@
sites: [
Settlement(Default),
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("GeekyGami", "https://geekygami.newgrounds.com/audio/"),
@ -571,7 +571,7 @@
Settlement(Default),
Settlement(CliffTown),
Settlement(DesertCity),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("Crow", None),
@ -587,7 +587,7 @@
Settlement(Default),
Settlement(CliffTown),
Settlement(DesertCity),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("Tobias Thy - (Thy SFX)", "https://soundcloud.com/thyofficial"),
@ -602,7 +602,7 @@
sites: [
Settlement(Default),
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("phoenix13032005", None),
@ -618,7 +618,7 @@
Settlement(Default),
Settlement(CliffTown),
Settlement(DesertCity),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("Oolnokk; mixed by cereal7", "https://soundcloud.com/walkerhallplaysthegeetar"),
@ -633,7 +633,7 @@
sites: [
Settlement(Default),
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
@ -649,7 +649,7 @@
Settlement(Default),
Settlement(CliffTown),
Settlement(DesertCity),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("DaforLynx", "https://daforlynx.neocities.org/"),
@ -677,7 +677,7 @@
sites: [
Settlement(Default),
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("badbbad", "https://soundcloud.com/tomerbarnea"),
@ -692,7 +692,7 @@
sites: [
Settlement(Default),
Settlement(CliffTown),
Settlement(SavannahPit),
Settlement(SavannahTown),
],
music_state: Activity(Explore),
artist: ("badbbad", "https://soundcloud.com/tomerbarnea"),

BIN
assets/voxygen/voxel/sprite/furniture/bench_coastal-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/sprite/furniture/bench_coastal-1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/sprite/furniture/bench_coastal-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4760,6 +4760,47 @@ ForgeTools: [(
],
wind_sway: 0.0,
)],
// CoastalTown Sprites
TableCoastalLarge: [(
variations: [
(
model: "voxygen.voxel.sprite.furniture.table_coastal_large",
offset: (-10.5, -16.5, 0.0),
lod_axes: (0.0, 0.0, 0.0),
),
],
wind_sway: 0.0,
)],
BenchCoastal: [(
variations: [
(
model: "voxygen.voxel.sprite.furniture.bench_coastal-0",
offset: (-5.5, -3.5, 0.0),
lod_axes: (1.0, 1.0, 1.0),
),
(
model: "voxygen.voxel.sprite.furniture.bench_coastal-1",
offset: (-5.5, -3.5, 0.0),
lod_axes: (1.0, 1.0, 1.0),
),
(
model: "voxygen.voxel.sprite.furniture.bench_coastal-2",
offset: (-5.5, -3.5, 0.0),
lod_axes: (1.0, 1.0, 1.0),
),
],
wind_sway: 0.0,
)],
JugAndCupsCoastal: [(
variations: [
(
model: "voxygen.voxel.sprite.furniture.jug_and_cups_coastal",
offset: (-6.0, -7.0, 3.0),
lod_axes: (0.0, 0.0, 0.0),
),
],
wind_sway: 0.0,
)],
// CliffTown Sprites
CliffDecorBlock: [(
variations: [

View File

@ -37,7 +37,7 @@ pub enum ObjectKind {
Palm,
Arena,
SavannahHut,
SavannahPit,
SavannahAirshipDock,
TerracottaPalace,
TerracottaHouse,
TerracottaYard,

View File

@ -29,6 +29,6 @@ pub enum SettlementKindMeta {
Default,
CliffTown,
DesertCity,
SavannahPit,
SavannahTown,
CoastalTown,
}

View File

@ -103,6 +103,8 @@ sprites! {
WardrobeSingleMesa = 0x1B,
WardrobeDoubleMesa = 0x1C,
CupboardMesa = 0x1D,
TableCoastalLarge = 0x1E,
BenchCoastal = 0x1F,
// Crafting
CraftingBench = 0x20,
Forge = 0x21,
@ -352,21 +354,22 @@ sprites! {
DiamondLight = 0x0A,
// Artificial
Gravestone = 0x10,
Melon = 0x11,
ForgeTools = 0x12,
JugAndBowlArabic = 0x13,
JugArabic = 0x14,
DecorSetArabic = 0x15,
SepareArabic = 0x16,
Candle = 0x17,
SmithingTable = 0x18,
Forge0 = 0x19,
GearWheel0 = 0x1A,
Quench0 = 0x1B,
SeaDecorEmblem = 0x1C,
SeaDecorPillar = 0x1D,
MagicalSeal = 0x1E,
Gravestone = 0x10,
Melon = 0x11,
ForgeTools = 0x12,
JugAndBowlArabic = 0x13,
JugArabic = 0x14,
DecorSetArabic = 0x15,
SepareArabic = 0x16,
Candle = 0x17,
SmithingTable = 0x18,
Forge0 = 0x19,
GearWheel0 = 0x1A,
Quench0 = 0x1B,
SeaDecorEmblem = 0x1C,
SeaDecorPillar = 0x1D,
MagicalSeal = 0x1E,
JugAndCupsCoastal = 0x1F,
},
Lamp = 8 has Ori, LightEnabled {
// Standalone lights
@ -582,10 +585,13 @@ impl SpriteKind {
SpriteKind::JugArabic => 1.4,
SpriteKind::TableArabicSmall => 0.9,
SpriteKind::TableArabicLarge => 1.0,
SpriteKind::TableCoastalLarge => 1.0,
SpriteKind::BenchCoastal => 1.0,
SpriteKind::CanapeArabic => 1.2,
SpriteKind::CupboardArabic => 4.5,
SpriteKind::WallTableArabic => 2.3,
SpriteKind::JugAndBowlArabic => 1.4,
SpriteKind::JugAndCupsCoastal => 1.4,
SpriteKind::Melon => 0.7,
SpriteKind::OvenArabic => 3.2,
SpriteKind::FountainArabic => 2.4,
@ -761,9 +767,10 @@ impl SpriteKind {
#[inline]
pub fn mount_offset(&self) -> Option<(Vec3<f32>, Vec3<f32>)> {
match self {
SpriteKind::ChairSingle | SpriteKind::ChairDouble | SpriteKind::Bench => {
Some((Vec3::new(0.0, 0.0, 0.5), -Vec3::unit_y()))
},
SpriteKind::ChairSingle
| SpriteKind::ChairDouble
| SpriteKind::Bench
| SpriteKind::BenchCoastal => Some((Vec3::new(0.0, 0.0, 0.5), -Vec3::unit_y())),
SpriteKind::Helm => Some((Vec3::new(0.0, -1.0, 0.0), Vec3::unit_y())),
SpriteKind::Bed => Some((Vec3::new(0.0, 0.0, 0.6), -Vec3::unit_y())),
SpriteKind::BedMesa => Some((Vec3::new(0.0, 0.0, 0.6), -Vec3::unit_y())),

View File

@ -78,7 +78,7 @@ impl Data {
.and_then(|ws| match &index.sites.get(ws).kind {
SiteKind::Refactor(site2)
| SiteKind::CliffTown(site2)
| SiteKind::SavannahPit(site2)
| SiteKind::SavannahTown(site2)
| SiteKind::CoastalTown(site2)
| SiteKind::DesertCity(site2) => Some(site2),
_ => None,
@ -115,7 +115,7 @@ impl Data {
| PlotKind::AirshipDock(_)
| PlotKind::Tavern(_)
| PlotKind::Plaza
| PlotKind::SavannahPit(_)
| PlotKind::SavannahAirshipDock(_)
| PlotKind::SavannahHut(_)
| PlotKind::SavannahWorkshop(_)
| PlotKind::CliffTower(_)

View File

@ -25,7 +25,7 @@ impl Site {
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::DesertCity(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_) => Some(true),
// Evil
SiteKind::Myrmidon(_)

View File

@ -79,7 +79,7 @@ impl Rule for Migrate {
&ctx.index.sites.get(ws).kind,
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_)
)

View File

@ -763,7 +763,7 @@ fn adventure() -> impl Action<DefaultState> {
Some(
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_)
),
@ -885,7 +885,7 @@ fn villager(visiting_site: SiteId) -> impl Action<DefaultState> {
let site2 = match site.world_site.map(|ws| &ctx.index.sites.get(ws).kind) {
Some(SiteKind::Refactor(site2)
| SiteKind::CliffTown(site2)
| SiteKind::SavannahPit(site2)
| SiteKind::SavannahTown(site2)
| SiteKind::CoastalTown(site2)
| SiteKind::DesertCity(site2)) => site2,
_ => return None,
@ -1228,7 +1228,12 @@ fn pilot<S: State>(ship: common::comp::ship::Body) -> impl Action<S> {
.filter_map(|(_, site)| ctx.index.sites.get(site.world_site?).site2())
.flat_map(|site| {
site.plots()
.filter(|plot| matches!(plot.kind(), PlotKind::AirshipDock(_)))
.filter(|plot| {
matches!(
plot.kind(),
PlotKind::AirshipDock(_) | PlotKind::SavannahAirshipDock(_)
)
})
.map(|plot| site.tile_center_wpos(plot.root_tile()))
})
.choose(&mut ctx.rng);

View File

@ -69,7 +69,7 @@ fn on_death(ctx: EventCtx<SimulateNpcs, OnDeath>) {
ctx.index.sites.get(s).kind,
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_)
)

View File

@ -120,7 +120,7 @@ impl ActivityUpdate {
Settlement(Default) => format!("Visiting {chunk_name}"),
Settlement(CliffTown) => format!("Climbing the towers of {chunk_name}"),
Settlement(DesertCity) => format!("Hiding from the sun in {chunk_name}"),
Settlement(SavannahPit) => format!("Shop at the market down in {chunk_name}"),
Settlement(SavannahTown) => format!("Shop at the market down in {chunk_name}"),
Settlement(CoastalTown) => {
format!("Dip your feet in the water in {chunk_name}")
},

View File

@ -5378,7 +5378,10 @@ pub fn get_sprite_desc(sprite: SpriteKind, localized_strings: &Localization) ->
| SpriteKind::TerracottaChest => "common-sprite-chest",
SpriteKind::Mud => "common-sprite-mud",
SpriteKind::Grave => "common-sprite-grave",
SpriteKind::ChairSingle | SpriteKind::ChairDouble => "common-sprite-chair",
SpriteKind::ChairSingle
| SpriteKind::ChairDouble
| SpriteKind::Bench
| SpriteKind::BenchCoastal => "common-sprite-chair",
SpriteKind::Crate => "common-sprite-crate",
SpriteKind::HangingSign => "common-sprite-signboard",
SpriteKind::StreetLamp => "common-sprite-street_lamp",

View File

@ -111,8 +111,8 @@ impl Lod {
make_lod_object("savannah_hut", renderer),
),
(
lod::ObjectKind::SavannahPit,
make_lod_object("savannah_pit", renderer),
lod::ObjectKind::SavannahAirshipDock,
make_lod_object("savannah_airship_dock", renderer),
),
(
lod::ObjectKind::TerracottaPalace,

View File

@ -498,7 +498,7 @@ impl Civs {
SiteKind::Castle => (16i32, 5.0),
SiteKind::Refactor => (32i32, 10.0),
SiteKind::CliffTown => (2i32, 1.0),
SiteKind::SavannahPit => (48i32, 25.0),
SiteKind::SavannahTown => (48i32, 25.0),
SiteKind::CoastalTown => (64i32, 35.0),
SiteKind::JungleRuin => (8i32, 3.0),
SiteKind::DesertCity => (64i32, 25.0),
@ -620,8 +620,8 @@ impl Civs {
&mut rng,
wpos,
)),
SiteKind::SavannahPit => {
WorldSite::savannah_pit(site2::Site::generate_savannah_pit(
SiteKind::SavannahTown => {
WorldSite::savannah_town(site2::Site::generate_savannah_town(
&Land::from_sim(ctx.sim),
&mut rng,
wpos,
@ -1014,7 +1014,7 @@ impl Civs {
let kind = match ctx.rng.gen_range(0..64) {
0..=8 => SiteKind::CliffTown,
9..=17 => SiteKind::DesertCity,
18..=23 => SiteKind::SavannahPit,
18..=23 => SiteKind::SavannahTown,
24..=33 => SiteKind::CoastalTown,
_ => SiteKind::Refactor,
};
@ -1462,7 +1462,7 @@ impl Civs {
SiteKind::Refactor
| SiteKind::Settlement
| SiteKind::CliffTown
| SiteKind::SavannahPit
| SiteKind::SavannahTown
| SiteKind::CoastalTown
| SiteKind::DesertCity
| SiteKind::Castle
@ -1476,7 +1476,7 @@ impl Civs {
if let SiteKind::Refactor
| SiteKind::Settlement
| SiteKind::CliffTown
| SiteKind::SavannahPit
| SiteKind::SavannahTown
| SiteKind::CoastalTown
| SiteKind::DesertCity
| SiteKind::Castle = self.sites[site].kind
@ -2036,7 +2036,7 @@ pub enum SiteKind {
Castle,
Refactor,
CliffTown,
SavannahPit,
SavannahTown,
CoastalTown,
DesertCity,
ChapelSite,
@ -2130,7 +2130,7 @@ impl SiteKind {
SiteKind::GliderCourse => {
chunk.alt > 1400.0
},
SiteKind::SavannahPit => {
SiteKind::SavannahTown => {
matches!(chunk.get_biome(), BiomeKind::Savannah)
&& !chunk.near_cliffs()
&& !chunk.river.near_water()
@ -2247,9 +2247,6 @@ impl Site {
SiteKind::Adlet
| SiteKind::Gnarling
| SiteKind::ChapelSite
| SiteKind::DesertCity
| SiteKind::SavannahPit
| SiteKind::CoastalTown
| SiteKind::Terracotta
| SiteKind::Haniwa
| SiteKind::Myrmidon
@ -2267,7 +2264,7 @@ impl Site {
| SiteKind::Refactor
| SiteKind::CliffTown
| SiteKind::DesertCity
| SiteKind::SavannahPit
| SiteKind::SavannahTown
| SiteKind::CoastalTown
)
}

View File

@ -194,7 +194,7 @@ impl World {
civ::SiteKind::Settlement
| civ::SiteKind::Refactor
| civ::SiteKind::CliffTown
| civ::SiteKind::SavannahPit
| civ::SiteKind::SavannahTown
| civ::SiteKind::CoastalTown
| civ::SiteKind::DesertCity
| civ::SiteKind::PirateHideout
@ -739,10 +739,10 @@ impl World {
Rgb::black(),
lod::ObjectKind::SavannahHut,
)),
site2::plot::PlotKind::SavannahPit(_) => Some((
site2::plot::PlotKind::SavannahAirshipDock(_) => Some((
site.tile_wpos(plot.root_tile),
Rgb::black(),
lod::ObjectKind::SavannahPit,
lod::ObjectKind::SavannahAirshipDock,
)),
site2::plot::PlotKind::TerracottaPalace(_) => Some((
site.tile_wpos(plot.root_tile),

View File

@ -122,7 +122,7 @@ impl Environment {
SiteKind::Settlement(_)
| SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_) => towns += site.economy.pop,
SiteKind::Castle(_) => castles += site.economy.pop,

View File

@ -65,7 +65,7 @@ pub enum SiteKind {
Castle(Castle),
Refactor(site2::Site),
CliffTown(site2::Site),
SavannahPit(site2::Site),
SavannahTown(site2::Site),
Tree(Tree),
DesertCity(site2::Site),
ChapelSite(site2::Site),
@ -139,9 +139,9 @@ impl Site {
}
}
pub fn savannah_pit(sp: site2::Site) -> Self {
pub fn savannah_town(st: site2::Site) -> Self {
Self {
kind: SiteKind::SavannahPit(sp),
kind: SiteKind::SavannahTown(st),
economy: Economy::default(),
}
}
@ -278,7 +278,7 @@ impl Site {
SiteKind::Castle(c) => c.radius(),
SiteKind::Refactor(s) => s.radius(),
SiteKind::CliffTown(ct) => ct.radius(),
SiteKind::SavannahPit(sp) => sp.radius(),
SiteKind::SavannahTown(st) => st.radius(),
SiteKind::CoastalTown(ct) => ct.radius(),
SiteKind::PirateHideout(ph) => ph.radius(),
SiteKind::JungleRuin(jr) => jr.radius(),
@ -309,7 +309,7 @@ impl Site {
SiteKind::Castle(c) => c.get_origin(),
SiteKind::Refactor(s) => s.origin,
SiteKind::CliffTown(ct) => ct.origin,
SiteKind::SavannahPit(sp) => sp.origin,
SiteKind::SavannahTown(st) => st.origin,
SiteKind::CoastalTown(ct) => ct.origin,
SiteKind::PirateHideout(ph) => ph.origin,
SiteKind::JungleRuin(jr) => jr.origin,
@ -340,7 +340,7 @@ impl Site {
SiteKind::Castle(c) => c.spawn_rules(wpos),
SiteKind::Refactor(s) => s.spawn_rules(wpos),
SiteKind::CliffTown(ct) => ct.spawn_rules(wpos),
SiteKind::SavannahPit(sp) => sp.spawn_rules(wpos),
SiteKind::SavannahTown(st) => st.spawn_rules(wpos),
SiteKind::CoastalTown(ct) => ct.spawn_rules(wpos),
SiteKind::PirateHideout(ph) => ph.spawn_rules(wpos),
SiteKind::JungleRuin(jr) => jr.spawn_rules(wpos),
@ -371,7 +371,7 @@ impl Site {
SiteKind::Castle(c) => c.name(),
SiteKind::Refactor(s) => s.name(),
SiteKind::CliffTown(ct) => ct.name(),
SiteKind::SavannahPit(sp) => sp.name(),
SiteKind::SavannahTown(st) => st.name(),
SiteKind::CoastalTown(ct) => ct.name(),
SiteKind::PirateHideout(ph) => ph.name(),
SiteKind::JungleRuin(jr) => jr.name(),
@ -404,7 +404,7 @@ impl Site {
SiteKind::Settlement(_)
| SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_) => Some(common::trade::SiteInformation {
id: site_id,
@ -422,7 +422,7 @@ impl Site {
SiteKind::Castle(c) => c.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
SiteKind::Refactor(s) => s.render(canvas, dynamic_rng),
SiteKind::CliffTown(ct) => ct.render(canvas, dynamic_rng),
SiteKind::SavannahPit(sp) => sp.render(canvas, dynamic_rng),
SiteKind::SavannahTown(st) => st.render(canvas, dynamic_rng),
SiteKind::CoastalTown(ct) => ct.render(canvas, dynamic_rng),
SiteKind::PirateHideout(ph) => ph.render(canvas, dynamic_rng),
SiteKind::JungleRuin(jr) => jr.render(canvas, dynamic_rng),
@ -467,7 +467,7 @@ impl Site {
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::PirateHideout(_)
| SiteKind::JungleRuin(_)
@ -497,7 +497,7 @@ impl Site {
self.kind,
SiteKind::Refactor(_)
| SiteKind::CliffTown(_)
| SiteKind::SavannahPit(_)
| SiteKind::SavannahTown(_)
| SiteKind::CoastalTown(_)
| SiteKind::DesertCity(_)
| SiteKind::Settlement(_)
@ -512,7 +512,7 @@ impl Site {
SiteKind::Castle(_) => None,
SiteKind::Refactor(site2) => Some(site2),
SiteKind::CliffTown(site2) => Some(site2),
SiteKind::SavannahPit(site2) => Some(site2),
SiteKind::SavannahTown(site2) => Some(site2),
SiteKind::CoastalTown(site2) => Some(site2),
SiteKind::PirateHideout(site2) => Some(site2),
SiteKind::JungleRuin(site2) => Some(site2),
@ -545,8 +545,8 @@ impl SiteKind {
Some(SiteKindMeta::Settlement(SettlementKindMeta::Default))
},
SiteKind::CliffTown(_) => Some(SiteKindMeta::Settlement(SettlementKindMeta::CliffTown)),
SiteKind::SavannahPit(_) => {
Some(SiteKindMeta::Settlement(SettlementKindMeta::SavannahPit))
SiteKind::SavannahTown(_) => {
Some(SiteKindMeta::Settlement(SettlementKindMeta::SavannahTown))
},
SiteKind::CoastalTown(_) => {
Some(SiteKindMeta::Settlement(SettlementKindMeta::CoastalTown))

View File

@ -1397,7 +1397,7 @@ impl Site {
site
}
pub fn generate_savannah_pit(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
pub fn generate_savannah_town(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
let mut rng = reseed(rng);
let mut site = Site {
origin,
@ -1409,32 +1409,10 @@ impl Site {
site.make_plaza(land, &mut rng);
let size = 11.0 as i32;
let aabr = Aabr {
min: Vec2::broadcast(-size),
max: Vec2::broadcast(size),
};
{
let savannah_pit =
plot::SavannahPit::generate(land, &mut reseed(&mut rng), &site, aabr);
let savannah_pit_alt = savannah_pit.alt;
let plot = site.create_plot(Plot {
kind: PlotKind::SavannahPit(savannah_pit),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
seed: rng.gen(),
});
let mut airship_dock = 0;
let build_chance = Lottery::from(vec![(25.0, 1), (7.0, 2), (3.0, 3), (15.0, 4)]);
site.blit_aabr(aabr, Tile {
kind: TileKind::Building,
plot: Some(plot),
hard_alt: Some(savannah_pit_alt),
});
}
let build_chance = Lottery::from(vec![(38.0, 1), (7.0, 2), (15.0, 3)]);
for _ in 0..45 {
for _ in 0..50 {
match *build_chance.choose_seeded(rng.gen()) {
1 => {
// SavannahHut
@ -1508,8 +1486,45 @@ impl Site {
site.make_plaza(land, &mut rng);
}
},
3 if airship_dock < 1 => {
// SavannahAirshipDock
let size = (4.0 + rng.gen::<f32>().powf(5.0) * 1.5).round() as u32;
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
site.find_roadside_aabr(
&mut rng,
4..(size + 1).pow(2),
Extent2::broadcast(size),
)
}) {
let savannah_airship_dock = plot::SavannahAirshipDock::generate(
land,
&mut reseed(&mut rng),
&site,
door_tile,
door_dir,
aabr,
);
let savannah_airship_dock_alt = savannah_airship_dock.alt;
let plot = site.create_plot(Plot {
kind: PlotKind::SavannahAirshipDock(savannah_airship_dock),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
seed: rng.gen(),
});
site.blit_aabr(aabr, Tile {
kind: TileKind::Building,
plot: Some(plot),
hard_alt: Some(savannah_airship_dock_alt),
});
} else {
site.make_plaza(land, &mut rng);
}
airship_dock += 1;
},
// Field
3 => {
4 => {
Self::generate_farm(false, &mut rng, &mut site, land);
},
_ => {},
@ -2490,7 +2505,9 @@ impl Site {
PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas),
PlotKind::CliffTower(cliff_tower) => cliff_tower.render_collect(self, canvas),
PlotKind::Sahagin(sahagin) => sahagin.render_collect(self, canvas),
PlotKind::SavannahPit(savannah_pit) => savannah_pit.render_collect(self, canvas),
PlotKind::SavannahAirshipDock(savannah_airship_dock) => {
savannah_airship_dock.render_collect(self, canvas)
},
PlotKind::SavannahHut(savannah_hut) => savannah_hut.render_collect(self, canvas),
PlotKind::SavannahWorkshop(savannah_workshop) => {
savannah_workshop.render_collect(self, canvas)

View File

@ -330,46 +330,30 @@ impl Structure for CoastalHouse {
// furniture
let mut sprites = vec![
SpriteKind::DrawerSmall,
SpriteKind::DrawerMedium,
SpriteKind::DrawerMedium,
SpriteKind::ChairSingle,
SpriteKind::ChairDouble,
SpriteKind::CoatRack,
SpriteKind::WardrobeDouble,
SpriteKind::WardrobeSingle,
SpriteKind::TableSide,
SpriteKind::Bowl,
SpriteKind::VialEmpty,
SpriteKind::SepareArabic,
SpriteKind::FountainArabic,
SpriteKind::JugAndBowlArabic,
SpriteKind::Crate,
SpriteKind::Pot,
SpriteKind::Lantern,
SpriteKind::TableArabicSmall,
SpriteKind::CushionArabic,
SpriteKind::JugArabic,
SpriteKind::DecorSetArabic,
];
'outer: for dir in DIAGONALS {
'outer: for dir in NEIGHBORS {
let furniture_pos = Vec2::new(
center.x + dir.x * ((length / 2) - 2),
center.y + dir.y * ((width / 2) - 2),
center.x + dir.x * ((length / 2) + 1),
center.y + dir.y * ((width / 2) + 1),
);
for dir in NEIGHBORS {
if sprites.is_empty() {
break 'outer;
}
let position = furniture_pos + dir * 3;
let sprite = sprites.swap_remove(
RandomField::new(0).get(position.with_z(base)) as usize % sprites.len(),
);
painter.owned_resource_sprite(
position.with_z(base - 2 + (s * height)),
sprite,
0,
);
if sprites.is_empty() {
break 'outer;
}
let sprite = sprites.swap_remove(
RandomField::new(0).get(furniture_pos.with_z(base)) as usize % sprites.len(),
);
painter.owned_resource_sprite(
furniture_pos.with_z(base - 2 + (s * height)),
sprite,
0,
);
}
// clear floor center if stairs
@ -383,12 +367,47 @@ impl Structure for CoastalHouse {
};
// draws a random index based of base and currently storey
let random_index = (RandomField::new(0).get(center.with_z(base + s)) % 4) as usize;
// add beds at random corners
let random_index_1 = (RandomField::new(0).get(center.with_z(base + s)) % 4) as usize;
let random_index_2 = 3 - random_index_1;
// add beds and tables at random corners
for (d, dir) in DIAGONALS.iter().enumerate() {
let bed_pos = center + dir * ((length / 2) - 2);
if d == random_index {
let table_pos = Vec2::new(
center.x + dir.x * ((length / 2) - 1),
center.y + dir.y * ((width / 2) - 2),
);
if d == random_index_1 {
painter.sprite(bed_pos.with_z(base - 2 + (s * height)), SpriteKind::Bed);
} else if d == random_index_2 {
painter.rotated_sprite(
table_pos.with_z(base - 2 + (s * height)),
SpriteKind::TableCoastalLarge,
2,
);
painter.sprite(
table_pos.with_z(base - 1 + (s * height)),
SpriteKind::JugAndCupsCoastal,
);
for dir in CARDINALS {
let bench_pos = Vec2::new(table_pos.x + dir.x * 2, table_pos.y + dir.y);
let ori = match dir.y {
0 => {
if dir.x < 0 {
2
} else {
6
}
},
1 => 0,
_ => 4,
};
painter.rotated_sprite(
bench_pos.with_z(base - 2 + (s * height)),
SpriteKind::BenchCoastal,
ori as u8,
);
}
}
}
@ -450,31 +469,34 @@ impl Structure for CoastalHouse {
)
.intersect(top_limit)
.fill(white.clone());
if storeys > 1 {
// stairway1 stairs
let stair_radius1 = 3.0;
let stairs_clear1 = painter.cylinder(Aabb {
min: (center - 1 - stair_radius1 as i32).with_z(base - 2),
max: (center + 2 + stair_radius1 as i32)
.with_z(base + ((storeys - 1) * height) - 2),
});
let stairs_clear2 = painter.cylinder(Aabb {
min: (center - 2 - stair_radius1 as i32).with_z(base - 2),
max: (center + 3 + stair_radius1 as i32)
.with_z(base + ((storeys - 1) * height) - 2),
});
stairs_clear1.clear();
painter
.cylinder(Aabb {
min: (center - 1).with_z(base - 2),
max: (center + 2).with_z(base + ((storeys - 1) * height) - 2),
})
.fill(white.clone());
// stairway1 stairs
let stair_radius1 = 3.0;
let stairs_clear1 = painter.cylinder(Aabb {
min: (center - 1 - stair_radius1 as i32).with_z(base - 2),
max: (center + 2 + stair_radius1 as i32).with_z(base + ((storeys - 1) * height) - 2),
});
let stairs_clear2 = painter.cylinder(Aabb {
min: (center - 2 - stair_radius1 as i32).with_z(base - 2),
max: (center + 3 + stair_radius1 as i32).with_z(base + ((storeys - 1) * height) - 2),
});
stairs_clear1.clear();
painter
.cylinder(Aabb {
min: (center - 1).with_z(base - 2),
max: (center + 2).with_z(base + ((storeys - 1) * height) - 2),
})
.fill(white.clone());
stairs_clear2
.sample(wall_staircase(
center.with_z(base + ((storeys - 1) * height) - 2),
stair_radius1,
(height / 2) as f32,
))
.fill(white);
stairs_clear2
.sample(wall_staircase(
center.with_z(base + ((storeys - 1) * height) - 2),
stair_radius1,
(height / 2) as f32,
))
.fill(white);
}
}
}

View File

@ -26,8 +26,8 @@ mod myrmidon_house;
mod pirate_hideout;
mod rock_circle;
mod sahagin;
mod savannah_airship_dock;
mod savannah_hut;
mod savannah_pit;
mod savannah_workshop;
mod sea_chapel;
pub mod tavern;
@ -47,8 +47,8 @@ pub use self::{
glider_finish::GliderFinish, glider_platform::GliderPlatform, glider_ring::GliderRing,
gnarling::GnarlingFortification, haniwa::Haniwa, house::House, jungle_ruin::JungleRuin,
myrmidon_arena::MyrmidonArena, myrmidon_house::MyrmidonHouse, pirate_hideout::PirateHideout,
rock_circle::RockCircle, sahagin::Sahagin, savannah_hut::SavannahHut,
savannah_pit::SavannahPit, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel,
rock_circle::RockCircle, sahagin::Sahagin, savannah_airship_dock::SavannahAirshipDock,
savannah_hut::SavannahHut, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel,
tavern::Tavern, terracotta_house::TerracottaHouse, terracotta_palace::TerracottaPalace,
terracotta_yard::TerracottaYard, troll_cave::TrollCave, vampire_castle::VampireCastle,
workshop::Workshop,
@ -117,7 +117,7 @@ pub enum PlotKind {
CliffTower(CliffTower),
Sahagin(Sahagin),
Citadel(Citadel),
SavannahPit(SavannahPit),
SavannahAirshipDock(SavannahAirshipDock),
SavannahHut(SavannahHut),
SavannahWorkshop(SavannahWorkshop),
Bridge(Bridge),
@ -157,7 +157,7 @@ macro_rules! foreach_plot {
PlotKind::GiantTree($x) => $y,
PlotKind::CliffTower($x) => $y,
PlotKind::Citadel($x) => $y,
PlotKind::SavannahPit($x) => $y,
PlotKind::SavannahAirshipDock($x) => $y,
PlotKind::SavannahHut($x) => $y,
PlotKind::SavannahWorkshop($x) => $y,
PlotKind::Bridge($x) => $y,

View File

@ -139,7 +139,7 @@ impl Structure for MyrmidonArena {
painter
.cylinder(Aabb {
min: (center - radius + 5).with_z(base),
max: (center + radius - 5).with_z(base + 20),
max: (center + radius - 5).with_z(base + 30),
})
.clear();

View File

@ -0,0 +1,332 @@
use super::*;
use crate::{
site2::gen::{place_circular_as_vec, spiral_staircase},
util::{RandomField, Sampler, CARDINALS, DIAGONALS},
Land,
};
use common::terrain::{BlockKind, SpriteKind};
use rand::prelude::*;
use std::{f32::consts::TAU, sync::Arc};
use vek::*;
/// Represents house data generated by the `generate()` method
pub struct SavannahAirshipDock {
/// Tile position of the door tile
pub door_tile: Vec2<i32>,
/// Axis aligned bounding region for the house
bounds: Aabr<i32>,
/// Approximate altitude of the door tile
pub(crate) alt: i32,
}
impl SavannahAirshipDock {
pub fn generate(
land: &Land,
_rng: &mut impl Rng,
site: &Site,
door_tile: Vec2<i32>,
door_dir: Vec2<i32>,
tile_aabr: Aabr<i32>,
) -> Self {
let door_tile_pos = site.tile_center_wpos(door_tile);
let bounds = Aabr {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
Self {
bounds,
door_tile: door_tile_pos,
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32 + 2,
}
}
}
impl Structure for SavannahAirshipDock {
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_savannah_airship_dock\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_savannah_airship_dock")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let base = self.alt + 1;
let center = self.bounds.center();
let wood_dark = Fill::Brick(BlockKind::Misc, Rgb::new(142, 67, 27), 12);
let reed = Fill::Brick(BlockKind::Misc, Rgb::new(72, 55, 46), 22);
let clay = Fill::Brick(BlockKind::Misc, Rgb::new(209, 124, 57), 22);
let color = Fill::Sampling(Arc::new(|center| {
Some(match (RandomField::new(0).get(center)) % 7 {
0 => Block::new(BlockKind::GlowingRock, Rgb::new(153, 82, 40)),
1 => Block::new(BlockKind::GlowingRock, Rgb::new(172, 104, 57)),
2 => Block::new(BlockKind::GlowingRock, Rgb::new(135, 106, 100)),
3 => Block::new(BlockKind::GlowingRock, Rgb::new(198, 164, 139)),
4 => Block::new(BlockKind::GlowingRock, Rgb::new(168, 163, 157)),
5 => Block::new(BlockKind::GlowingRock, Rgb::new(73, 53, 42)),
_ => Block::new(BlockKind::GlowingRock, Rgb::new(178, 124, 90)),
})
}));
let length = 18;
let height = length / 2;
let storeys = 1;
let platform_height = 40;
let radius = length + (length / 3);
let reed_var = (1 + RandomField::new(0).get(center.with_z(base)) % 4) as f32;
let reed_parts = 36_f32 + reed_var;
let phi = TAU / reed_parts;
// foundation
painter
.cylinder(Aabb {
min: (center - length).with_z(base - 3),
max: (center + length + 1).with_z(base - 2),
})
.fill(clay.clone());
painter
.cylinder(Aabb {
min: (center - length - 1).with_z(base - 4),
max: (center + length + 2).with_z(base - 3),
})
.fill(clay.clone());
painter
.cylinder(Aabb {
min: (center - length - 2).with_z(base - 5),
max: (center + length + 3).with_z(base - 4),
})
.fill(clay.clone());
painter
.cylinder(Aabb {
min: (center - length - 3).with_z(base - height),
max: (center + length + 4).with_z(base - 5),
})
.fill(clay.clone());
// platform
painter
.cylinder(Aabb {
min: (center - (2 * (length / 3)) - 1).with_z(base + platform_height - 4),
max: (center + (2 * (length / 3)) + 1).with_z(base + platform_height - 3),
})
.fill(color.clone());
painter
.cylinder(Aabb {
min: (center - (2 * (length / 3))).with_z(base + platform_height - 4),
max: (center + (2 * (length / 3))).with_z(base + platform_height - 3),
})
.fill(clay.clone());
painter
.cylinder(Aabb {
min: (center - length - 2).with_z(base + platform_height - 3),
max: (center + length + 2).with_z(base + platform_height - 2),
})
.fill(color.clone());
painter
.cylinder(Aabb {
min: (center - length - 1).with_z(base + platform_height - 3),
max: (center + length + 1).with_z(base + platform_height - 2),
})
.fill(clay.clone());
// lanterns, crates & barrels
for dir in CARDINALS {
let lantern_pos = center + (dir * length);
painter.sprite(
lantern_pos.with_z(base + platform_height - 2),
SpriteKind::Lantern,
);
}
for dir in DIAGONALS {
let cargo_pos = center + (dir * ((length / 2) - 1));
for dir in CARDINALS {
let sprite_pos = cargo_pos + dir;
let rows = (RandomField::new(0).get(sprite_pos.with_z(base)) % 3) as i32;
for r in 0..rows {
painter
.aabb(Aabb {
min: (sprite_pos).with_z(base + platform_height - 2 + r),
max: (sprite_pos + 1).with_z(base + platform_height - 1 + r),
})
.fill(Fill::Block(Block::air(
match (RandomField::new(0).get(sprite_pos.with_z(base + r)) % 2) as i32
{
0 => SpriteKind::Barrel,
_ => SpriteKind::CrateBlock,
},
)));
if r > 0 {
painter.owned_resource_sprite(
sprite_pos.with_z(base + platform_height - 1 + r),
SpriteKind::Crate,
0,
);
}
}
}
}
for b in 0..2 {
let base = base + (b * platform_height);
let radius = radius - (b * (radius / 3));
let length = length - (b * (length / 3));
// roof cone
painter
.cone(Aabb {
min: (center - radius).with_z(base + (storeys * height) - (height / 2) + 1),
max: (center + radius)
.with_z(base + (storeys * height) + (height / 2) - 1 + reed_var as i32),
})
.fill(reed.clone());
painter
.cone(Aabb {
min: (center - radius).with_z(base + (storeys * height) - (height / 2)),
max: (center + radius)
.with_z(base + (storeys * height) + (height / 2) - 2 + reed_var as i32),
})
.clear();
// room
for s in 0..storeys {
let room = painter.cylinder(Aabb {
min: (center - length + 2 + s).with_z(base - 2 + (s * height)),
max: (center + 1 + length - 2 - s).with_z(base + height + (s * height)),
});
room.fill(clay.clone());
// decor inlays
for dir in DIAGONALS {
let decor_pos = center + dir * (length - 2 - s);
let decor = painter
.line(
center.with_z(base - 1 + (s * (height + 2))),
decor_pos.with_z(base - 1 + (s * (height + 2))),
5.0,
)
.intersect(room);
decor.fill(color.clone());
painter
.line(
center.with_z(base - 1 + (s * (height + 2))),
decor_pos.with_z(base - 1 + (s * (height + 2))),
4.0,
)
.intersect(decor)
.fill(clay.clone());
}
}
// clear rooms
painter
.cylinder(Aabb {
min: (center - length + 4).with_z(base - 2),
max: (center + 1 + length - 4).with_z(base + (storeys * height)),
})
.clear();
// wood decor
painter
.cylinder(Aabb {
min: (center - length + 4).with_z(base - 1),
max: (center + 1 + length - 4).with_z(base),
})
.fill(wood_dark.clone());
painter
.cylinder(Aabb {
min: (center - length + 4).with_z(base + (storeys * height) - 1),
max: (center + 1 + length - 4).with_z(base + (storeys * height) + 1),
})
.fill(wood_dark.clone());
for s in 0..storeys {
// entries, windows
for dir in CARDINALS {
let frame_pos = center + dir * (length - 2 - s);
let clear_pos = center + dir * (length + 2 - s);
painter
.line(
center.with_z(base - 1 + (s * (height + 2))),
frame_pos.with_z(base - 1 + (s * (height + 2))),
3.0,
)
.fill(color.clone());
painter
.line(
center.with_z(base - 1 + (s * (height + 2))),
clear_pos.with_z(base - 1 + (s * (height + 2))),
2.0,
)
.clear();
}
}
// re clear room
painter
.cylinder(Aabb {
min: (center - length + 5).with_z(base - 2),
max: (center + 1 + length - 5).with_z(base + (storeys * height) + 1),
})
.clear();
// floor
painter
.cylinder(Aabb {
min: (center - (length / 2) - 1).with_z(base - 3),
max: (center + (length / 2) + 1).with_z(base - 2),
})
.fill(color.clone());
painter
.cylinder(Aabb {
min: (center - (length / 2) + 1).with_z(base - 3),
max: (center + (length / 2) - 1).with_z(base - 2),
})
.fill(clay.clone());
// reed roof lines
for n in 1..=reed_parts as i32 {
let pos = Vec2::new(
center.x + ((radius as f32) * ((n as f32 * phi).cos())) as i32,
center.y + ((radius as f32) * ((n as f32 * phi).sin())) as i32,
);
painter
.line(
pos.with_z(base + (storeys * height) - (height / 2)),
center.with_z(base + (storeys * height) + (height / 2) + reed_var as i32),
1.0,
)
.fill(reed.clone());
}
}
// tower
let beams_low = place_circular_as_vec(center, (2 * (length / 3)) as f32, 10);
let beams_high = place_circular_as_vec(center, (2 * (length / 4)) as f32, 10);
for b in 0..beams_low.len() {
painter
.cylinder(Aabb {
min: (beams_low[b] - 4).with_z(base + height - 1),
max: (beams_low[b] + 4).with_z(base + height),
})
.fill(wood_dark.clone());
painter
.line(
beams_low[b].with_z(base + height),
beams_high[b].with_z(base + platform_height - 4),
1.5,
)
.fill(wood_dark.clone());
}
//stairs
painter
.cylinder(Aabb {
min: (center - (length / 3)).with_z(base),
max: (center + (length / 3)).with_z(base + platform_height),
})
.clear();
let stairs = painter.cylinder(Aabb {
min: (center - (length / 3)).with_z(base - 3),
max: (center + (length / 3)).with_z(base + platform_height - 2),
});
stairs
.sample(spiral_staircase(
center.with_z(base - 3),
((length / 3) + 1) as f32,
0.5,
(platform_height / 4) as f32,
))
.fill(clay.clone());
}
}

File diff suppressed because it is too large Load Diff