mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
CliffTowns
This commit is contained in:
parent
a7e8b22d1d
commit
3d24b1d635
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Admin command to reload all chunks on the server
|
||||
- Furniture and waypoints in site2 towns
|
||||
- text input for trading
|
||||
- Themed Site CliffTown, hoodoo/arabic inspired stone structures inhabited by mountaineer NPCs.
|
||||
|
||||
### Changed
|
||||
|
||||
|
22
assets/common/entity/village/mountaineer.ron
Normal file
22
assets/common/entity/village/mountaineer.ron
Normal file
@ -0,0 +1,22 @@
|
||||
(
|
||||
name: Name("Mountaineer"),
|
||||
body: RandomWith("orc"),
|
||||
alignment: Alignment(Npc),
|
||||
|
||||
loadout: Extended(
|
||||
hands: TwoHanded(Choice([
|
||||
(1, Some(Item("common.items.weapons.tool.broom"))),
|
||||
(1, Some(Item("common.items.weapons.tool.hoe"))),
|
||||
(1, Some(Item("common.items.weapons.tool.pickaxe"))),
|
||||
(1, Some(Item("common.items.weapons.tool.rake"))),
|
||||
(1, Some(Item("common.items.weapons.tool.shovel-0"))),
|
||||
(1, Some(Item("common.items.weapons.tool.shovel-1"))),
|
||||
])),
|
||||
base_asset: Loadout("common.loadout.village.mountaineer"),
|
||||
inventory: [
|
||||
(10, "common.items.consumable.potion_big"),
|
||||
],
|
||||
),
|
||||
loot: LootTable("common.loot_tables.creature.humanoid"),
|
||||
meta: [],
|
||||
)
|
39
assets/common/loadout/village/mountaineer.ron
Normal file
39
assets/common/loadout/village/mountaineer.ron
Normal file
@ -0,0 +1,39 @@
|
||||
({
|
||||
Armor(Belt): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.belt"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.belt"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.belt"))),
|
||||
]),
|
||||
Armor(Chest): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.chest"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.chest"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.chest"))),
|
||||
]),
|
||||
Armor(Feet): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.foot"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.foot"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.foot"))),
|
||||
]),
|
||||
Armor(Hands): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.hand"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.hand"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.hand"))),
|
||||
]),
|
||||
Armor(Legs): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.pants"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.pants"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.pants"))),
|
||||
]),
|
||||
Armor(Shoulders): Choice([
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.shoulder_0"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_blue.shoulder_1"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_green.shoulder"))),
|
||||
(1.0, Some(Item("common.items.armor.cloth_purple.shoulder"))),
|
||||
]),
|
||||
Armor(Head): Choice([
|
||||
// Christmas event
|
||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||
(1.0, Some(Item("common.items.armor.misc.head.headband"))),
|
||||
(2.0, None),
|
||||
]),
|
||||
})
|
BIN
assets/voxygen/voxel/sprite/furniture/books_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/books_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/bookshelf_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/bookshelf_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/canape_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/canape_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/cliff_decor_block.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/cliff_decor_block.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/cupboard_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/cupboard_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/cushion_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/cushion_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/decor_set_arabic-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/decor_set_arabic-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/forge_tools.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/forge_tools.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/fountain_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/fountain_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/hearth.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/hearth.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/jug_and_bowl_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/jug_and_bowl_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/jug_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/jug_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/melon_cut.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/melon_cut.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/oven_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/oven_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/separe_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/separe_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/table_arabic_large.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/table_arabic_large.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/table_arabic_small.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/table_arabic_small.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/furniture/wall_table_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/furniture/wall_table_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/sprite/window/window_arabic.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/sprite/window/window_arabic.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -3323,6 +3323,187 @@ Lantern: Some((
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// CliffTown Decor
|
||||
WindowArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.window.window_arabic",
|
||||
offset: (-5.5, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
BookshelfArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.bookshelf_arabic",
|
||||
offset: (-22.0, -5.5, -6.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
DecorSetArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.decor_set_arabic-0",
|
||||
offset: (-10.5, -10.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
SepareArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.separe_arabic",
|
||||
offset: (-5.5, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
CushionArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.cushion_arabic",
|
||||
offset: (-5.5, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
JugArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.jug_arabic",
|
||||
offset: (-5.5, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
TableArabicSmall: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.table_arabic_small",
|
||||
offset: (-7.5, -7.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
TableArabicLarge: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.table_arabic_large",
|
||||
offset: (-21.0, -13.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
CanapeArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.canape_arabic",
|
||||
offset: (-12.5, -14.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
CupboardArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.cupboard_arabic",
|
||||
offset: (-9.5, -5.5, 4.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
WallTableArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.wall_table_arabic",
|
||||
offset: (-15.0, -5.5, 2.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
JugAndBowlArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.jug_and_bowl_arabic",
|
||||
offset: (-15.0, -7.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
MelonCut: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.melon_cut",
|
||||
offset: (-15.0, -7.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
FountainArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.fountain_arabic",
|
||||
offset: (-15.5, -15.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
OvenArabic: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.oven_arabic",
|
||||
offset: (-6.5, -8.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
Hearth: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.hearth",
|
||||
offset: (-19.0, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
ForgeTools: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.forge_tools",
|
||||
offset: (-19.0, -5.0, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
CliffDecorBlock: Some((
|
||||
variations: [
|
||||
(
|
||||
model: "voxygen.voxel.sprite.furniture.cliff_decor_block",
|
||||
offset: (-5.5, -5.5, 0.0),
|
||||
lod_axes: (0.0, 0.0, 0.0),
|
||||
),
|
||||
],
|
||||
wind_sway: 0.0,
|
||||
)),
|
||||
// Anvil
|
||||
Anvil: Some((
|
||||
variations: [
|
||||
|
@ -208,6 +208,7 @@ impl Block {
|
||||
| SpriteKind::WallSconce
|
||||
| SpriteKind::FireBowlGround
|
||||
| SpriteKind::ChristmasOrnament
|
||||
| SpriteKind::CliffDecorBlock
|
||||
| SpriteKind::Orb => Some(16),
|
||||
SpriteKind::Velorite
|
||||
| SpriteKind::VeloriteFrag
|
||||
|
@ -191,6 +191,24 @@ make_case_elim!(
|
||||
ChristmasOrnament = 0xA4,
|
||||
ChristmasWreath = 0xA5,
|
||||
EnsnaringWeb = 0xA6,
|
||||
WindowArabic = 0xA7,
|
||||
MelonCut = 0xA8,
|
||||
BookshelfArabic = 0xA9,
|
||||
DecorSetArabic = 0xAA,
|
||||
SepareArabic = 0xAB,
|
||||
CushionArabic = 0xAC,
|
||||
JugArabic = 0xAD,
|
||||
TableArabicSmall = 0xAE,
|
||||
TableArabicLarge = 0xAF,
|
||||
CanapeArabic = 0xB0,
|
||||
CupboardArabic = 0xB1,
|
||||
WallTableArabic = 0xB2,
|
||||
JugAndBowlArabic = 0xB3,
|
||||
OvenArabic = 0xB4,
|
||||
FountainArabic = 0xB5,
|
||||
Hearth = 0xB6,
|
||||
ForgeTools = 0xB7,
|
||||
CliffDecorBlock = 0xB8,
|
||||
}
|
||||
);
|
||||
|
||||
@ -283,6 +301,23 @@ impl SpriteKind {
|
||||
| SpriteKind::CavernLillypadBlue
|
||||
| SpriteKind::EnsnaringWeb => 0.1,
|
||||
SpriteKind::LillyPads => 0.1,
|
||||
SpriteKind::WindowArabic | SpriteKind::BookshelfArabic => 1.9,
|
||||
SpriteKind::DecorSetArabic => 2.6,
|
||||
SpriteKind::SepareArabic => 2.2,
|
||||
SpriteKind::CushionArabic => 0.4,
|
||||
SpriteKind::JugArabic => 1.4,
|
||||
SpriteKind::TableArabicSmall => 0.9,
|
||||
SpriteKind::TableArabicLarge => 1.0,
|
||||
SpriteKind::CanapeArabic => 1.2,
|
||||
SpriteKind::CupboardArabic => 4.5,
|
||||
SpriteKind::WallTableArabic => 2.3,
|
||||
SpriteKind::JugAndBowlArabic => 1.4,
|
||||
SpriteKind::MelonCut => 0.7,
|
||||
SpriteKind::OvenArabic => 3.2,
|
||||
SpriteKind::FountainArabic => 2.4,
|
||||
SpriteKind::Hearth => 2.3,
|
||||
SpriteKind::ForgeTools => 2.8,
|
||||
SpriteKind::CliffDecorBlock => 1.0,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@ -458,6 +493,18 @@ impl SpriteKind {
|
||||
| SpriteKind::DismantlingBench
|
||||
| SpriteKind::ChristmasOrnament
|
||||
| SpriteKind::ChristmasWreath
|
||||
| SpriteKind::WindowArabic
|
||||
| SpriteKind::BookshelfArabic
|
||||
| SpriteKind::TableArabicLarge
|
||||
| SpriteKind::CanapeArabic
|
||||
| SpriteKind::CupboardArabic
|
||||
| SpriteKind::WallTableArabic
|
||||
| SpriteKind::JugAndBowlArabic
|
||||
| SpriteKind::JugArabic
|
||||
| SpriteKind::MelonCut
|
||||
| SpriteKind::OvenArabic
|
||||
| SpriteKind::Hearth
|
||||
| SpriteKind::ForgeTools
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -266,6 +266,31 @@ pub fn init(
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
SiteKind::CliffTown(site2) => {
|
||||
for _ in 0..(site2.plazas().len() as f32 * 1.5) as usize {
|
||||
rtsim.entities.insert(Entity {
|
||||
is_loaded: false,
|
||||
pos: site2
|
||||
.plazas()
|
||||
.choose(&mut thread_rng())
|
||||
.map_or(site.get_origin(), |p| {
|
||||
site2.tile_center_wpos(site2.plot(p).root_tile())
|
||||
+ Vec2::new(
|
||||
thread_rng().gen_range(-8..9),
|
||||
thread_rng().gen_range(-8..9),
|
||||
)
|
||||
})
|
||||
.with_z(0)
|
||||
.map(|e| e as f32),
|
||||
seed: thread_rng().gen(),
|
||||
controller: RtSimController::default(),
|
||||
last_time_ticked: 0.0,
|
||||
kind: RtSimEntityKind::Merchant,
|
||||
brain: Brain::merchant(site_id),
|
||||
});
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -161,6 +161,7 @@ impl Civs {
|
||||
SiteKind::Dungeon => (8i32, 3.0),
|
||||
SiteKind::Castle => (16i32, 5.0),
|
||||
SiteKind::Refactor => (32i32, 10.0),
|
||||
SiteKind::CliffTown => (32i32, 10.0),
|
||||
SiteKind::Tree => (12i32, 8.0),
|
||||
SiteKind::GiantTree => (12i32, 8.0),
|
||||
SiteKind::Gnarling => (16i32, 10.0),
|
||||
@ -239,6 +240,11 @@ impl Civs {
|
||||
&mut rng,
|
||||
wpos,
|
||||
)),
|
||||
SiteKind::CliffTown => WorldSite::cliff_town(site2::Site::generate_cliff_town(
|
||||
&Land::from_sim(ctx.sim),
|
||||
&mut rng,
|
||||
wpos,
|
||||
)),
|
||||
SiteKind::Tree => {
|
||||
WorldSite::tree(Tree::generate(wpos, &Land::from_sim(ctx.sim), &mut rng))
|
||||
},
|
||||
@ -479,7 +485,11 @@ impl Civs {
|
||||
ctx: &mut GenCtx<impl Rng>,
|
||||
start_locations: &mut Vec<Vec2<i32>>,
|
||||
) -> Option<Id<Civ>> {
|
||||
let kind = SiteKind::Refactor;
|
||||
// TODO: specify SiteKind based on where a suitable location is found
|
||||
let kind = match ctx.rng.gen_range(0..64) {
|
||||
0..=10 => SiteKind::CliffTown,
|
||||
_ => SiteKind::Refactor,
|
||||
};
|
||||
let site = attempt(100, || {
|
||||
let loc = find_site_loc(ctx, (start_locations, 60), 0, kind)?;
|
||||
start_locations.push(loc);
|
||||
@ -887,7 +897,10 @@ impl Civs {
|
||||
.filter(|(_, p)| {
|
||||
matches!(
|
||||
p.kind,
|
||||
SiteKind::Refactor | SiteKind::Settlement | SiteKind::Castle
|
||||
SiteKind::Refactor
|
||||
| SiteKind::Settlement
|
||||
| SiteKind::CliffTown
|
||||
| SiteKind::Castle
|
||||
)
|
||||
})
|
||||
.map(|(id, p)| (id, (p.center.distance_squared(loc) as f32).sqrt()))
|
||||
@ -895,7 +908,8 @@ impl Civs {
|
||||
.collect::<Vec<_>>();
|
||||
nearby.sort_by_key(|(_, dist)| *dist as i32);
|
||||
|
||||
if let SiteKind::Refactor | SiteKind::Settlement | SiteKind::Castle = self.sites[site].kind
|
||||
if let SiteKind::Refactor | SiteKind::Settlement | SiteKind::CliffTown | SiteKind::Castle =
|
||||
self.sites[site].kind
|
||||
{
|
||||
for (nearby, _) in nearby.into_iter().take(5) {
|
||||
// Find a novel path
|
||||
@ -1149,6 +1163,7 @@ pub enum SiteKind {
|
||||
Dungeon,
|
||||
Castle,
|
||||
Refactor,
|
||||
CliffTown,
|
||||
Tree,
|
||||
GiantTree,
|
||||
Gnarling,
|
||||
@ -1156,36 +1171,8 @@ pub enum SiteKind {
|
||||
|
||||
impl SiteKind {
|
||||
pub fn is_suitable_loc(&self, loc: Vec2<i32>, sim: &WorldSim) -> bool {
|
||||
sim.get(loc).map_or(false, |chunk| match self {
|
||||
SiteKind::Gnarling => (-0.3..0.4).contains(&chunk.temp) && chunk.tree_density > 0.75,
|
||||
SiteKind::GiantTree | SiteKind::Tree => chunk.tree_density > 0.4,
|
||||
SiteKind::Castle => {
|
||||
if chunk.tree_density > 0.4 || chunk.river.near_water() || chunk.near_cliffs() {
|
||||
return false;
|
||||
}
|
||||
const HILL_RADIUS: i32 = 3 * TERRAIN_CHUNK_BLOCKS_LG as i32;
|
||||
for x in (-HILL_RADIUS)..HILL_RADIUS {
|
||||
for y in (-HILL_RADIUS)..HILL_RADIUS {
|
||||
let check_loc = loc + Vec2::new(x, y);
|
||||
if let Some(true) = sim
|
||||
.get_alt_approx(check_loc)
|
||||
.map(|surrounding_alt| surrounding_alt > chunk.alt + 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Castles are really big, so to avoid parts of them ending up underwater or
|
||||
// in other awkward positions we have to do this
|
||||
if sim
|
||||
.get(check_loc)
|
||||
.map_or(true, |c| c.is_underwater() || c.near_cliffs())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
SiteKind::Refactor | SiteKind::Settlement => {
|
||||
sim.get(loc).map_or(false, |chunk| {
|
||||
let suitable_for_town = |score_threshold: f32| -> bool {
|
||||
const RESOURCE_RADIUS: i32 = 1;
|
||||
let mut river_chunks = 0;
|
||||
let mut lake_chunks = 0;
|
||||
@ -1277,10 +1264,49 @@ impl SiteKind {
|
||||
+ (trading_score as f32 + 1.0).log2();
|
||||
has_potable_water
|
||||
&& has_building_materials
|
||||
&& industry_score > 6.7
|
||||
&& industry_score > score_threshold
|
||||
&& warm_or_firewood
|
||||
},
|
||||
_ => true,
|
||||
};
|
||||
match self {
|
||||
SiteKind::Gnarling => {
|
||||
(-0.3..0.4).contains(&chunk.temp) && chunk.tree_density > 0.75
|
||||
},
|
||||
SiteKind::GiantTree | SiteKind::Tree => chunk.tree_density > 0.4,
|
||||
SiteKind::CliffTown => {
|
||||
(-0.6..0.4).contains(&chunk.temp)
|
||||
&& chunk.near_cliffs()
|
||||
&& suitable_for_town(4.0)
|
||||
},
|
||||
SiteKind::Castle => {
|
||||
if chunk.tree_density > 0.4 || chunk.river.near_water() || chunk.near_cliffs() {
|
||||
return false;
|
||||
}
|
||||
const HILL_RADIUS: i32 = 3 * TERRAIN_CHUNK_BLOCKS_LG as i32;
|
||||
for x in (-HILL_RADIUS)..HILL_RADIUS {
|
||||
for y in (-HILL_RADIUS)..HILL_RADIUS {
|
||||
let check_loc = loc + Vec2::new(x, y);
|
||||
if let Some(true) = sim
|
||||
.get_alt_approx(check_loc)
|
||||
.map(|surrounding_alt| surrounding_alt > chunk.alt + 1.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Castles are really big, so to avoid parts of them ending up
|
||||
// underwater or in other awkward positions
|
||||
// we have to do this
|
||||
if sim
|
||||
.get(check_loc)
|
||||
.map_or(true, |c| c.is_underwater() || c.near_cliffs())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
},
|
||||
SiteKind::Refactor | SiteKind::Settlement => suitable_for_town(6.7),
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ impl World {
|
||||
name: site.site_tmp.map(|id| index.sites[id].name().to_string()),
|
||||
// TODO: Probably unify these, at some point
|
||||
kind: match &site.kind {
|
||||
civ::SiteKind::Settlement => world_msg::SiteKind::Town,
|
||||
civ::SiteKind::Settlement | civ::SiteKind::Refactor | civ::SiteKind::CliffTown => world_msg::SiteKind::Town,
|
||||
civ::SiteKind::Dungeon => world_msg::SiteKind::Dungeon {
|
||||
difficulty: match site.site_tmp.map(|id| &index.sites[id].kind) {
|
||||
Some(site::SiteKind::Dungeon(d)) => d.dungeon_difficulty().unwrap_or(0),
|
||||
@ -154,7 +154,6 @@ impl World {
|
||||
},
|
||||
},
|
||||
civ::SiteKind::Castle => world_msg::SiteKind::Castle,
|
||||
civ::SiteKind::Refactor => world_msg::SiteKind::Town,
|
||||
civ::SiteKind::Tree | civ::SiteKind::GiantTree => world_msg::SiteKind::Tree,
|
||||
// TODO: Maybe change?
|
||||
civ::SiteKind::Gnarling => world_msg::SiteKind::Gnarling,
|
||||
|
@ -166,11 +166,12 @@ fn simulate_return(index: &mut Index, world: &mut WorldSim) -> Result<(), std::i
|
||||
for site in index.sites.ids() {
|
||||
let site = &index.sites[site];
|
||||
match site.kind {
|
||||
SiteKind::Settlement(_) | SiteKind::Refactor(_) | SiteKind::CliffTown(_) => {
|
||||
towns += site.economy.pop
|
||||
},
|
||||
SiteKind::Dungeon(_) => dungeons += site.economy.pop,
|
||||
SiteKind::Settlement(_) => towns += site.economy.pop,
|
||||
SiteKind::Castle(_) => castles += site.economy.pop,
|
||||
SiteKind::Tree(_) => (),
|
||||
SiteKind::Refactor(_) => towns += site.economy.pop,
|
||||
SiteKind::GiantTree(_) => (),
|
||||
SiteKind::Gnarling(_) => {},
|
||||
}
|
||||
@ -360,7 +361,9 @@ mod tests {
|
||||
resources,
|
||||
neighbors,
|
||||
kind: match i.kind {
|
||||
crate::site::SiteKind::Settlement(_) => {
|
||||
crate::site::SiteKind::Settlement(_)
|
||||
| crate::site::SiteKind::Refactor(_)
|
||||
| crate::site::SiteKind::CliffTown(_) => {
|
||||
common::terrain::site::SitesKind::Settlement
|
||||
},
|
||||
crate::site::SiteKind::Dungeon(_) => {
|
||||
@ -369,9 +372,6 @@ mod tests {
|
||||
crate::site::SiteKind::Castle(_) => {
|
||||
common::terrain::site::SitesKind::Castle
|
||||
},
|
||||
crate::site::SiteKind::Refactor(_) => {
|
||||
common::terrain::site::SitesKind::Settlement
|
||||
},
|
||||
_ => common::terrain::site::SitesKind::Void,
|
||||
},
|
||||
};
|
||||
|
@ -64,6 +64,7 @@ pub enum SiteKind {
|
||||
Dungeon(site2::Site),
|
||||
Castle(Castle),
|
||||
Refactor(site2::Site),
|
||||
CliffTown(site2::Site),
|
||||
Tree(tree::Tree),
|
||||
GiantTree(site2::Site),
|
||||
Gnarling(site2::Site),
|
||||
@ -105,6 +106,13 @@ impl Site {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cliff_town(ct: site2::Site) -> Self {
|
||||
Self {
|
||||
kind: SiteKind::CliffTown(ct),
|
||||
economy: Economy::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tree(t: tree::Tree) -> Self {
|
||||
Self {
|
||||
kind: SiteKind::Tree(t),
|
||||
@ -125,6 +133,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.radius(),
|
||||
SiteKind::Castle(c) => c.radius(),
|
||||
SiteKind::Refactor(s) => s.radius(),
|
||||
SiteKind::CliffTown(ct) => ct.radius(),
|
||||
SiteKind::Tree(t) => t.radius(),
|
||||
SiteKind::GiantTree(gt) => gt.radius(),
|
||||
SiteKind::Gnarling(g) => g.radius(),
|
||||
@ -137,6 +146,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.origin,
|
||||
SiteKind::Castle(c) => c.get_origin(),
|
||||
SiteKind::Refactor(s) => s.origin,
|
||||
SiteKind::CliffTown(ct) => ct.origin,
|
||||
SiteKind::Tree(t) => t.origin,
|
||||
SiteKind::GiantTree(gt) => gt.origin,
|
||||
SiteKind::Gnarling(g) => g.origin,
|
||||
@ -149,6 +159,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.spawn_rules(wpos),
|
||||
SiteKind::Castle(c) => c.spawn_rules(wpos),
|
||||
SiteKind::Refactor(s) => s.spawn_rules(wpos),
|
||||
SiteKind::CliffTown(ct) => ct.spawn_rules(wpos),
|
||||
SiteKind::Tree(t) => t.spawn_rules(wpos),
|
||||
SiteKind::GiantTree(gt) => gt.spawn_rules(wpos),
|
||||
SiteKind::Gnarling(g) => g.spawn_rules(wpos),
|
||||
@ -161,6 +172,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.name(),
|
||||
SiteKind::Castle(c) => c.name(),
|
||||
SiteKind::Refactor(s) => s.name(),
|
||||
SiteKind::CliffTown(ct) => ct.name(),
|
||||
SiteKind::Tree(_) => "Giant Tree",
|
||||
SiteKind::GiantTree(gt) => gt.name(),
|
||||
SiteKind::Gnarling(g) => g.name(),
|
||||
@ -172,7 +184,7 @@ impl Site {
|
||||
site_id: common::trade::SiteId,
|
||||
) -> Option<common::trade::SiteInformation> {
|
||||
match &self.kind {
|
||||
SiteKind::Settlement(_) | SiteKind::Refactor(_) => {
|
||||
SiteKind::Settlement(_) | SiteKind::Refactor(_) | SiteKind::CliffTown(_) => {
|
||||
Some(common::trade::SiteInformation {
|
||||
id: site_id,
|
||||
unconsumed_stock: self
|
||||
@ -195,6 +207,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.render(canvas, dynamic_rng),
|
||||
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::Tree(t) => t.render(canvas, dynamic_rng),
|
||||
SiteKind::GiantTree(gt) => gt.render(canvas, dynamic_rng),
|
||||
SiteKind::Gnarling(g) => g.render(canvas, dynamic_rng),
|
||||
@ -220,6 +233,7 @@ impl Site {
|
||||
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, supplement),
|
||||
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||
SiteKind::Refactor(_) => {},
|
||||
SiteKind::CliffTown(_) => {},
|
||||
SiteKind::Tree(_) => {},
|
||||
SiteKind::GiantTree(gt) => gt.apply_supplement(dynamic_rng, wpos2d, supplement),
|
||||
SiteKind::Gnarling(g) => g.apply_supplement(dynamic_rng, wpos2d, supplement),
|
||||
@ -227,6 +241,9 @@ impl Site {
|
||||
}
|
||||
|
||||
pub fn do_economic_simulation(&self) -> bool {
|
||||
matches!(self.kind, SiteKind::Refactor(_) | SiteKind::Settlement(_))
|
||||
matches!(
|
||||
self.kind,
|
||||
SiteKind::Refactor(_) | SiteKind::CliffTown(_) | SiteKind::Settlement(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -622,4 +622,26 @@ impl<'a, R: Rng> NameGen<'a, R> {
|
||||
];
|
||||
self.generate_theme_from_parts(&start, &middle, &vowel, &end)
|
||||
}
|
||||
|
||||
// arabic inspired location names for cliff towns
|
||||
pub fn generate_cliff_town(mut self) -> String {
|
||||
let start = [
|
||||
"zor", "el", "mas", "yaz", "ra", "boh", "mah", "ah", "lam", "mak", "mol", "wa", "bisk",
|
||||
"moj", "bis", "ay", "sha", "rez", "bakh", "ta", "je", "ki", "mos", "asj", "meh",
|
||||
];
|
||||
let middle = [
|
||||
"d", "ph", "r", "st", "t", "s", "p", "th", "br", "tr", "m", "k", "cr", "dr", "pl",
|
||||
"ch", "l", "ap", "akr", "ak", "ar", "ath", "asp", "al", "aph", "aphr", "oph", "or",
|
||||
"ok", "on", "od", "om", "ep", "er", "em", "eph", "eth", "yph", "ach", "yp", "ik", "is",
|
||||
"iph", "ith", "pr", "as", "asph", "ps", "b", "n", "z", "x", "kr", "kt", "cht", "chr",
|
||||
"thr", "dr", "pr", "pl", "h", "in", "g",
|
||||
];
|
||||
let vowel = ["o", "e", "a", "i", "y", "ei", "ai", "io"];
|
||||
let end = [
|
||||
"wad", "tab", "med", "mad", "afa", "man", "oubi", "hir", "baz", "yen", "kh", "ah",
|
||||
"dek", "fir", "ish", "rad", "iri", "am", "if", "van", "rik", "kat", "akan", "ikan",
|
||||
"illah", "ulus", "fard",
|
||||
];
|
||||
self.generate_theme_from_parts(&start, &middle, &vowel, &end)
|
||||
}
|
||||
}
|
||||
|
@ -742,6 +742,51 @@ impl Site {
|
||||
site
|
||||
}
|
||||
|
||||
pub fn generate_cliff_town(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
|
||||
let mut rng = reseed(rng);
|
||||
|
||||
let mut site = Site {
|
||||
origin,
|
||||
name: NameGen::location(&mut rng).generate_cliff_town(),
|
||||
..Site::default()
|
||||
};
|
||||
|
||||
site.make_plaza(land, &mut rng);
|
||||
for _ in 0..30 {
|
||||
// CliffTower
|
||||
let size = (6.0 + rng.gen::<f32>().powf(5.0) * 1.0).round() as u32;
|
||||
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
|
||||
site.find_roadside_aabr(&mut rng, 6..(size + 1).pow(2), Extent2::broadcast(size))
|
||||
}) {
|
||||
let cliff_tower = plot::CliffTower::generate(
|
||||
land,
|
||||
&mut reseed(&mut rng),
|
||||
&site,
|
||||
door_tile,
|
||||
door_dir,
|
||||
aabr,
|
||||
);
|
||||
let cliff_tower_alt = cliff_tower.alt;
|
||||
let plot = site.create_plot(Plot {
|
||||
kind: PlotKind::CliffTower(cliff_tower),
|
||||
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(cliff_tower_alt),
|
||||
});
|
||||
} else {
|
||||
site.make_plaza(land, &mut rng);
|
||||
}
|
||||
}
|
||||
|
||||
site
|
||||
}
|
||||
|
||||
pub fn wpos_tile_pos(&self, wpos2d: Vec2<i32>) -> Vec2<i32> {
|
||||
(wpos2d - self.origin).map(|e| e.div_euclid(TILE_SIZE as i32))
|
||||
}
|
||||
@ -991,6 +1036,7 @@ impl Site {
|
||||
PlotKind::Dungeon(dungeon) => dungeon.render_collect(self, canvas),
|
||||
PlotKind::Gnarling(gnarling) => gnarling.render_collect(self, canvas),
|
||||
PlotKind::GiantTree(giant_tree) => giant_tree.render_collect(self, canvas),
|
||||
PlotKind::CliffTower(cliff_tower) => cliff_tower.render_collect(self, canvas),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
mod castle;
|
||||
mod cliff_tower;
|
||||
pub mod dungeon;
|
||||
mod giant_tree;
|
||||
mod gnarling;
|
||||
@ -6,8 +7,8 @@ mod house;
|
||||
mod workshop;
|
||||
|
||||
pub use self::{
|
||||
castle::Castle, dungeon::Dungeon, giant_tree::GiantTree, gnarling::GnarlingFortification,
|
||||
house::House, workshop::Workshop,
|
||||
castle::Castle, cliff_tower::CliffTower, dungeon::Dungeon, giant_tree::GiantTree,
|
||||
gnarling::GnarlingFortification, house::House, workshop::Workshop,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@ -52,4 +53,5 @@ pub enum PlotKind {
|
||||
Dungeon(Dungeon),
|
||||
Gnarling(GnarlingFortification),
|
||||
GiantTree(GiantTree),
|
||||
CliffTower(CliffTower),
|
||||
}
|
||||
|
890
world/src/site2/plot/cliff_tower.rs
Normal file
890
world/src/site2/plot/cliff_tower.rs
Normal file
@ -0,0 +1,890 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
util::{RandomField, Sampler, LOCALITY},
|
||||
Land,
|
||||
};
|
||||
use common::{
|
||||
generation::EntityInfo,
|
||||
terrain::{BlockKind, SpriteKind},
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use std::{mem, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
/// Represents house data generated by the `generate()` method
|
||||
pub struct CliffTower {
|
||||
/// Axis aligned bounding region for the house
|
||||
bounds: Aabr<i32>,
|
||||
/// Approximate altitude of the door tile
|
||||
pub(crate) alt: i32,
|
||||
}
|
||||
|
||||
impl CliffTower {
|
||||
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 bounds = Aabr {
|
||||
min: site.tile_wpos(tile_aabr.min),
|
||||
max: site.tile_wpos(tile_aabr.max),
|
||||
};
|
||||
Self {
|
||||
bounds,
|
||||
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Structure for CliffTower {
|
||||
fn render(&self, _site: &Site, _land: &Land, painter: &Painter) {
|
||||
let base = self.alt + 1;
|
||||
let center = self.bounds.center();
|
||||
let variant_pos = center.with_z(base);
|
||||
let variant = RandomField::new(0).get(variant_pos) as i32 % 10;
|
||||
// common superquadric degree for rooms
|
||||
let sq_type = 2.5;
|
||||
let storeys = 5 + (variant / 2);
|
||||
let mut length = 16 + (variant / 2);
|
||||
let mut width = 7 * length / 8;
|
||||
let mut height = 18 + variant / 2;
|
||||
let (mut stair_pos1, mut stair_pos2) = (center - 3, center + 3);
|
||||
let mut floor_level = base - 40;
|
||||
let brick = Fill::Sampling(Arc::new(|variant_pos| {
|
||||
Some(
|
||||
match (RandomField::new(0).get(Vec3::new(variant_pos.z, 0, 0))) % 15 {
|
||||
0 => Block::new(BlockKind::Rock, Rgb::new(51, 89, 118)),
|
||||
1 => Block::new(BlockKind::Rock, Rgb::new(57, 96, 126)),
|
||||
2 => Block::new(BlockKind::Rock, Rgb::new(59, 103, 136)),
|
||||
3 => Block::new(BlockKind::Rock, Rgb::new(61, 109, 145)),
|
||||
4 => Block::new(BlockKind::Rock, Rgb::new(42, 66, 87)),
|
||||
5 => Block::new(BlockKind::Rock, Rgb::new(47, 76, 101)),
|
||||
6 => Block::new(BlockKind::Rock, Rgb::new(50, 84, 110)),
|
||||
7 => Block::new(BlockKind::Rock, Rgb::new(52, 85, 112)),
|
||||
8 => Block::new(BlockKind::Rock, Rgb::new(51, 60, 66)),
|
||||
9 => Block::new(BlockKind::Rock, Rgb::new(58, 74, 87)),
|
||||
10 => Block::new(BlockKind::Rock, Rgb::new(53, 104, 111)),
|
||||
11 => Block::new(BlockKind::Rock, Rgb::new(52, 63, 72)),
|
||||
12 => Block::new(BlockKind::Rock, Rgb::new(52, 63, 72)),
|
||||
13 => Block::new(BlockKind::Rock, Rgb::new(74, 128, 168)),
|
||||
_ => Block::new(BlockKind::Rock, Rgb::new(69, 123, 162)),
|
||||
},
|
||||
)
|
||||
}));
|
||||
let wood = Fill::Brick(BlockKind::Wood, Rgb::new(106, 83, 51), 12);
|
||||
let color = Fill::Block(Block::air(SpriteKind::CliffDecorBlock));
|
||||
let window = Fill::Block(Block::air(SpriteKind::WindowArabic));
|
||||
let window2 = Fill::Block(Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap());
|
||||
for s in 0..storeys {
|
||||
let x_offset = RandomField::new(0).get((center - length).with_z(base)) as i32 % 10;
|
||||
let y_offset = RandomField::new(0).get((center + length).with_z(base)) as i32 % 10;
|
||||
let super_center = Vec2::new(center.x - 3 + x_offset / 2, center.y - 3 + y_offset / 2);
|
||||
let room1_type = RandomField::new(0).get((center - length).with_z(base)) as i32 % 2;
|
||||
let room2_type = RandomField::new(0).get((center - length - 1).with_z(base)) as i32 % 2;
|
||||
// CliffTower Hoodoo Overlay
|
||||
painter
|
||||
.cubic_bezier(
|
||||
super_center.with_z(floor_level + (height / 2)),
|
||||
(super_center - x_offset).with_z(floor_level + height),
|
||||
(super_center - y_offset).with_z(floor_level + (height) + (height / 2)),
|
||||
super_center.with_z(floor_level + (2 * height)),
|
||||
(length - 1) as f32,
|
||||
)
|
||||
.fill(brick.clone());
|
||||
// only inhabit towers with enough storeys to have entries above ground
|
||||
if storeys > 3 {
|
||||
// wood or rocky platforms
|
||||
// only spawn on upper storeys
|
||||
if floor_level > base + 35 {
|
||||
match RandomField::new(0).get((super_center - floor_level).with_z(base)) as i32
|
||||
% 2
|
||||
{
|
||||
0 => {
|
||||
painter
|
||||
.superquadric(
|
||||
Aabb {
|
||||
min: (super_center - (5 * (length / 3)) + 3)
|
||||
.with_z(floor_level),
|
||||
max: (super_center + (5 * (length / 3)) - 3)
|
||||
.with_z(floor_level + 2),
|
||||
},
|
||||
6.0,
|
||||
)
|
||||
.fill(wood.clone());
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.superquadric(
|
||||
Aabb {
|
||||
min: (super_center - (5 * (length / 3)) + 2)
|
||||
.with_z(floor_level + 1),
|
||||
max: (super_center + (5 * (length / 3)) - 1)
|
||||
.with_z(floor_level + 5),
|
||||
},
|
||||
6.0,
|
||||
),
|
||||
painter.superquadric(
|
||||
Aabb {
|
||||
min: (super_center - (5 * (length / 3)) + 2)
|
||||
.with_z(floor_level + 3),
|
||||
max: (super_center + (5 * (length / 3)) - 2)
|
||||
.with_z(floor_level + 5),
|
||||
},
|
||||
6.0,
|
||||
),
|
||||
))
|
||||
.fill(wood.clone());
|
||||
// lanterns & random sprites for wood platform corners
|
||||
for dir in SQUARE_4 {
|
||||
let corner_pos = super_center - (5 * (length / 4));
|
||||
let sprite_pos = (corner_pos + (dir * (10 * (length / 4))))
|
||||
.with_z(floor_level + 4);
|
||||
painter.sprite(
|
||||
sprite_pos,
|
||||
match (RandomField::new(0).get(sprite_pos)) % 10 {
|
||||
0 => SpriteKind::FireBowlGround,
|
||||
1 => SpriteKind::Bowl,
|
||||
3 => SpriteKind::VialEmpty,
|
||||
4 => SpriteKind::Crate,
|
||||
5 => SpriteKind::Pot,
|
||||
_ => SpriteKind::Lantern,
|
||||
},
|
||||
);
|
||||
}
|
||||
// planters for larger wood platforms
|
||||
if length > 11 {
|
||||
for r in 0..2 {
|
||||
for p in 0..((length / 2) - 2) {
|
||||
let planter_pos = Vec2::new(
|
||||
super_center.x - (2 * (length / 3))
|
||||
+ (p * (length / 3)),
|
||||
super_center.y - ((4 * (length / 3)) + 2)
|
||||
+ (r * ((8 * (length / 3)) + 4)),
|
||||
);
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(planter_pos.x - 1, planter_pos.y)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(
|
||||
planter_pos.x + 2,
|
||||
planter_pos.y + 1,
|
||||
)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
planter_pos.with_z(floor_level + 4),
|
||||
SpriteKind::Planter,
|
||||
(4 - (r * 4)) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
painter
|
||||
.superquadric(
|
||||
Aabb {
|
||||
min: (center - length + 1).with_z(floor_level),
|
||||
max: (center + length - 1).with_z(floor_level + 2),
|
||||
},
|
||||
sq_type,
|
||||
)
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.superquadric(
|
||||
Aabb {
|
||||
min: (center - length).with_z(floor_level + 1),
|
||||
max: (center + length).with_z(floor_level + 5),
|
||||
},
|
||||
sq_type,
|
||||
),
|
||||
painter.superquadric(
|
||||
Aabb {
|
||||
min: (center - length + 3).with_z(floor_level + 3),
|
||||
max: (center + length - 3).with_z(floor_level + 5),
|
||||
},
|
||||
sq_type,
|
||||
),
|
||||
))
|
||||
.fill(brick.clone());
|
||||
},
|
||||
}
|
||||
}
|
||||
// room
|
||||
painter
|
||||
.superquadric(
|
||||
Aabb {
|
||||
min: Vec2::new(super_center.x - length - 1, super_center.y - width - 1)
|
||||
.with_z(floor_level),
|
||||
max: Vec2::new(super_center.x + length + 1, super_center.y + width + 1)
|
||||
.with_z(floor_level + height),
|
||||
},
|
||||
sq_type,
|
||||
)
|
||||
.fill(brick.clone());
|
||||
// clear room - leave some floor
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.superquadric(
|
||||
Aabb {
|
||||
min: Vec2::new(
|
||||
super_center.x - length + 1,
|
||||
super_center.y + 1 - width,
|
||||
)
|
||||
.with_z(floor_level + 1),
|
||||
max: Vec2::new(
|
||||
super_center.x + length - 1,
|
||||
super_center.y - 1 + width,
|
||||
)
|
||||
.with_z(floor_level + height - 1),
|
||||
},
|
||||
sq_type,
|
||||
),
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length + 1, super_center.y + 1 - width)
|
||||
.with_z(floor_level + 1),
|
||||
max: Vec2::new(super_center.x + length - 1, super_center.y - 1 + width)
|
||||
.with_z(floor_level + 4),
|
||||
}),
|
||||
))
|
||||
.clear();
|
||||
// entries
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length, super_center.y - 2)
|
||||
.with_z(floor_level + 3),
|
||||
max: Vec2::new(super_center.x - length + 6, super_center.y + 2)
|
||||
.with_z(floor_level + 4),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x + length - 6, super_center.y - 2)
|
||||
.with_z(floor_level + 3),
|
||||
max: Vec2::new(super_center.x + length, super_center.y + 2)
|
||||
.with_z(floor_level + 4),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
// colored sills
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length - 1, super_center.y - 2)
|
||||
.with_z(floor_level + 3),
|
||||
max: Vec2::new(super_center.x - length, super_center.y + 2)
|
||||
.with_z(floor_level + 4),
|
||||
})
|
||||
.fill(color.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x + length, super_center.y - 2)
|
||||
.with_z(floor_level + 3),
|
||||
max: Vec2::new(super_center.x + length + 1, super_center.y + 2)
|
||||
.with_z(floor_level + 4),
|
||||
})
|
||||
.fill(color.clone());
|
||||
if floor_level > base {
|
||||
// clear entries
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length - 12, super_center.y - 2)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x + length + 12, super_center.y + 2)
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
// door sprites
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length + 1, super_center.y - 2)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x - length + 2, super_center.y + 2)
|
||||
.with_z(floor_level + 7),
|
||||
}),
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - length + 1, super_center.y - 1)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x - length + 2, super_center.y + 1)
|
||||
.with_z(floor_level + 7),
|
||||
}),
|
||||
))
|
||||
.fill(window.clone());
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x + length - 1, super_center.y - 2)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x + length, super_center.y + 2)
|
||||
.with_z(floor_level + 7),
|
||||
}),
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x + length - 1, super_center.y - 1)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x + length, super_center.y + 1)
|
||||
.with_z(floor_level + 7),
|
||||
}),
|
||||
))
|
||||
.fill(window.clone());
|
||||
// windows
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y - width)
|
||||
.with_z(floor_level + 5),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y - width + 3)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y - width + 1)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y - width + 3)
|
||||
.with_z(floor_level + 5),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y + width - 3)
|
||||
.with_z(floor_level + 5),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y + width + 1)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y + width - 3)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y + width)
|
||||
.with_z(floor_level + 5),
|
||||
})
|
||||
.fill(brick.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 3, super_center.y - width - 1)
|
||||
.with_z(floor_level + 5),
|
||||
max: Vec2::new(super_center.x + 3, super_center.y - width)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.fill(color.clone());
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 3, super_center.y + width + 1)
|
||||
.with_z(floor_level + 5),
|
||||
max: Vec2::new(super_center.x + 3, super_center.y + width + 2)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.fill(color.clone());
|
||||
// clear windows
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y - width - 12)
|
||||
.with_z(floor_level + 6),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y + width + 12)
|
||||
.with_z(floor_level + 9),
|
||||
})
|
||||
.clear();
|
||||
// window sprites
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y - width + 1)
|
||||
.with_z(floor_level + 6),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y - width + 2)
|
||||
.with_z(floor_level + 9),
|
||||
}),
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 1, super_center.y - width + 1)
|
||||
.with_z(floor_level + 6),
|
||||
max: Vec2::new(super_center.x + 1, super_center.y - width + 2)
|
||||
.with_z(floor_level + 9),
|
||||
}),
|
||||
))
|
||||
.fill(window2.clone());
|
||||
painter
|
||||
.prim(Primitive::without(
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 4, super_center.y + width - 1)
|
||||
.with_z(floor_level + 6),
|
||||
max: Vec2::new(super_center.x + 4, super_center.y + width)
|
||||
.with_z(floor_level + 9),
|
||||
}),
|
||||
painter.aabb(Aabb {
|
||||
min: Vec2::new(super_center.x - 1, super_center.y + width - 1)
|
||||
.with_z(floor_level + 6),
|
||||
max: Vec2::new(super_center.x + 1, super_center.y + width)
|
||||
.with_z(floor_level + 9),
|
||||
}),
|
||||
))
|
||||
.fill(window2.clone());
|
||||
}
|
||||
// room wall lamps
|
||||
for d in 0..2 {
|
||||
let door_lamp_pos = Vec2::new(
|
||||
super_center.x - length + 2 + (d * ((2 * length) - 4)),
|
||||
super_center.y,
|
||||
)
|
||||
.with_z(floor_level + 9);
|
||||
painter.rotated_sprite(
|
||||
door_lamp_pos,
|
||||
SpriteKind::WallLampSmall,
|
||||
2 + ((d * 4) as u8),
|
||||
);
|
||||
|
||||
let window_lamp_pos = Vec2::new(
|
||||
super_center.x,
|
||||
super_center.y - width + 2 + (d * ((2 * width) - 4)),
|
||||
)
|
||||
.with_z(floor_level + 9);
|
||||
painter.rotated_sprite(
|
||||
window_lamp_pos,
|
||||
SpriteKind::WallLampSmall,
|
||||
4 - ((d * 4) as u8),
|
||||
);
|
||||
}
|
||||
// furniture sprites in room1(living_room, workshop), room2(kitchen, bath)
|
||||
// dont spawn sprites on stairways
|
||||
let stairway_clear_1 = Aabb {
|
||||
min: (stair_pos1 - 5).with_z(floor_level + 3),
|
||||
max: (stair_pos1 + 5).with_z(floor_level + 5),
|
||||
};
|
||||
let stairway_clear_2 = Aabb {
|
||||
min: (stair_pos2 - 5).with_z(floor_level + 3),
|
||||
max: (stair_pos2 + 5).with_z(floor_level + 5),
|
||||
};
|
||||
if length > width {
|
||||
match room1_type {
|
||||
0 => {
|
||||
// living room
|
||||
// distribute small sprites
|
||||
let mut liv_sprites = vec![
|
||||
SpriteKind::DrawerSmall,
|
||||
SpriteKind::CoatRack,
|
||||
SpriteKind::TableArabicSmall,
|
||||
SpriteKind::CushionArabic,
|
||||
SpriteKind::JugArabic,
|
||||
SpriteKind::SpinningWheel,
|
||||
SpriteKind::TanningRack,
|
||||
SpriteKind::Loom,
|
||||
];
|
||||
for dir in LOCALITY {
|
||||
let pos = super_center + dir * (width / 3);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !liv_sprites.is_empty()
|
||||
{
|
||||
let sprite = liv_sprites.swap_remove(
|
||||
RandomField::new(0).get(pos.with_z(base)) as usize
|
||||
% liv_sprites.len(),
|
||||
);
|
||||
painter.sprite(pos.with_z(floor_level + 4), sprite);
|
||||
}
|
||||
}
|
||||
// bookshelfs
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x,
|
||||
super_center.y + width - 3 + (d * ((-2 * width) + 6)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 2, pos.y - 2 + (2 * d))
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 3, pos.y + 1 + (2 * d))
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 6),
|
||||
SpriteKind::BookshelfArabic,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
// canapes
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x - length + 10 + (d * ((2 * length) - 20)),
|
||||
super_center.y - width + 4 + (d * ((2 * width) - 8)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(
|
||||
pos.x - 1 - (3 * d),
|
||||
pos.y - 1 - (3 * d),
|
||||
)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(
|
||||
pos.x + 5 - (3 * d),
|
||||
pos.y + 5 - (3 * d),
|
||||
)
|
||||
.with_z(floor_level + 8),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
SpriteKind::CanapeArabic,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
// decor set / separe / table large
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x - length + 8 + (d * ((2 * length) - 16)),
|
||||
super_center.y + width - 8 + (d * ((-2 * width) + 16)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 2, pos.y - 1)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 3, pos.y + 2)
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.clear();
|
||||
painter.sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
match (RandomField::new(0).get(pos.with_z(floor_level - d)))
|
||||
% 3
|
||||
{
|
||||
0 => SpriteKind::TableArabicLarge,
|
||||
1 => SpriteKind::DecorSetArabic,
|
||||
_ => SpriteKind::SepareArabic,
|
||||
},
|
||||
)
|
||||
};
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// workshop
|
||||
for d in 0..2 {
|
||||
// forge tools
|
||||
let ft_pos = Vec2::new(
|
||||
super_center.x - 4 + (d * 6),
|
||||
super_center.y - width + 3 + (d * ((2 * width) - 6)),
|
||||
);
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(ft_pos.x - 2 + d, ft_pos.y - (3 * d))
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(ft_pos.x + 2 + d, ft_pos.y + 4 - (3 * d))
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
ft_pos.with_z(floor_level + 4),
|
||||
SpriteKind::ForgeTools,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
// hearth
|
||||
let pos = Vec2::new(
|
||||
super_center.x + length - 12 + (d * ((-2 * length) + 24)),
|
||||
super_center.y - width + 3 + (d * ((2 * width) - 6)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 2, pos.y - (4 * d))
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 3, pos.y + 5 - (4 * d))
|
||||
.with_z(floor_level + 6),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
SpriteKind::Hearth,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
// crafting stations
|
||||
let mut ws_sprites = vec![
|
||||
SpriteKind::CraftingBench,
|
||||
SpriteKind::Forge,
|
||||
SpriteKind::DismantlingBench,
|
||||
SpriteKind::Anvil,
|
||||
];
|
||||
for dir in LOCALITY {
|
||||
let pos = super_center + dir * (width / 3);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !ws_sprites.is_empty()
|
||||
{
|
||||
let sprite = ws_sprites.swap_remove(
|
||||
RandomField::new(0).get(pos.with_z(base)) as usize
|
||||
% ws_sprites.len(),
|
||||
);
|
||||
painter.sprite(pos.with_z(floor_level + 4), sprite);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match room2_type {
|
||||
0 => {
|
||||
// bath
|
||||
// wall tables with varying items
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x,
|
||||
super_center.y - width + 4 + (d * ((2 * width) - 8)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 2, pos.y - (d * 3))
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 3, pos.y + 4 - (d * 3))
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
SpriteKind::WallTableArabic,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 5),
|
||||
match (RandomField::new(0)
|
||||
.get((pos - d).with_z(floor_level)))
|
||||
% 4
|
||||
{
|
||||
0 => SpriteKind::Bowl,
|
||||
1 => SpriteKind::VialEmpty,
|
||||
2 => SpriteKind::JugArabic,
|
||||
_ => SpriteKind::JugAndBowlArabic,
|
||||
},
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
// distribute smaller sprites
|
||||
let mut ba_sprites = vec![
|
||||
SpriteKind::DrawerSmall,
|
||||
SpriteKind::CoatRack,
|
||||
SpriteKind::Crate,
|
||||
SpriteKind::TableArabicSmall,
|
||||
SpriteKind::SepareArabic,
|
||||
SpriteKind::DecorSetArabic,
|
||||
];
|
||||
for dir in LOCALITY {
|
||||
let pos = super_center + dir * (width / 3);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !ba_sprites.is_empty()
|
||||
{
|
||||
let sprite = ba_sprites.swap_remove(
|
||||
RandomField::new(0).get(pos.with_z(base)) as usize
|
||||
% ba_sprites.len(),
|
||||
);
|
||||
painter.sprite(pos.with_z(floor_level + 4), sprite)
|
||||
}
|
||||
}
|
||||
// fountains
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x - length + 8 + (d * ((2 * length) - 16)),
|
||||
super_center.y + width - 8 + (d * ((-2 * width) + 16)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: (pos - 1).with_z(floor_level + 4),
|
||||
max: (pos + 2).with_z(floor_level + 5),
|
||||
})
|
||||
.clear();
|
||||
painter.sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
SpriteKind::FountainArabic,
|
||||
)
|
||||
};
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// kitchen
|
||||
// cupboards / ovens / cushions / jugs
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x + 3 - (d * 6),
|
||||
super_center.y - width + 3,
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 1, pos.y)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 2, pos.y + 4)
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
match (RandomField::new(0).get(pos.with_z(floor_level))) % 2
|
||||
{
|
||||
0 => SpriteKind::CupboardArabic,
|
||||
_ => SpriteKind::OvenArabic,
|
||||
},
|
||||
4,
|
||||
);
|
||||
}
|
||||
}
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x + 3 - (d * 6),
|
||||
super_center.y + width - 3,
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 1, pos.y - 3)
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 2, pos.y + 1)
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
match (RandomField::new(0).get(pos.with_z(floor_level))) % 4
|
||||
{
|
||||
0 => SpriteKind::CupboardArabic,
|
||||
1 => SpriteKind::OvenArabic,
|
||||
2 => SpriteKind::CushionArabic,
|
||||
_ => SpriteKind::JugArabic,
|
||||
},
|
||||
0,
|
||||
);
|
||||
}
|
||||
}
|
||||
// wall tables with varying items
|
||||
for d in 0..2 {
|
||||
let pos = Vec2::new(
|
||||
super_center.x,
|
||||
super_center.y - width + 3 + (d * ((2 * width) - 6)),
|
||||
);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
{
|
||||
painter
|
||||
.aabb(Aabb {
|
||||
min: Vec2::new(pos.x - 2, pos.y - (3 * d))
|
||||
.with_z(floor_level + 4),
|
||||
max: Vec2::new(pos.x + 2, pos.y + 4 - (3 * d))
|
||||
.with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 4),
|
||||
SpriteKind::WallTableArabic,
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
painter.rotated_sprite(
|
||||
pos.with_z(floor_level + 5),
|
||||
match (RandomField::new(0).get(pos.with_z(floor_level))) % 5
|
||||
{
|
||||
0 => SpriteKind::MelonCut,
|
||||
1 => SpriteKind::JugAndBowlArabic,
|
||||
2 => SpriteKind::Bowl,
|
||||
3 => SpriteKind::JugArabic,
|
||||
_ => SpriteKind::VialEmpty,
|
||||
},
|
||||
0 + (4 * d) as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
// distribute small sprites
|
||||
let mut kit_sprites = vec![
|
||||
SpriteKind::DrawerSmall,
|
||||
SpriteKind::Crate,
|
||||
SpriteKind::VialEmpty,
|
||||
SpriteKind::Bowl,
|
||||
SpriteKind::TableArabicSmall,
|
||||
SpriteKind::JugArabic,
|
||||
SpriteKind::CookingPot,
|
||||
SpriteKind::Cauldron,
|
||||
];
|
||||
for dir in LOCALITY {
|
||||
let pos = super_center + dir * (width / 3);
|
||||
if !stairway_clear_1.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !stairway_clear_2.contains_point(pos.with_z(floor_level + 4))
|
||||
&& !kit_sprites.is_empty()
|
||||
{
|
||||
let sprite = kit_sprites.swap_remove(
|
||||
RandomField::new(0).get(pos.with_z(base)) as usize
|
||||
% kit_sprites.len(),
|
||||
);
|
||||
painter.sprite(pos.with_z(floor_level + 4), sprite);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
// stairways starting from 2nd storey
|
||||
if s > 0 {
|
||||
//clear stairway
|
||||
painter
|
||||
.cylinder(Aabb {
|
||||
min: (stair_pos1 - 3).with_z(floor_level - height + 4),
|
||||
max: (stair_pos1 + 3).with_z(floor_level + 7),
|
||||
})
|
||||
.clear();
|
||||
//stairway
|
||||
let stair_radius1 = 4.0;
|
||||
let stairs_clear1 = painter.prim(Primitive::Cylinder(Aabb {
|
||||
min: (stair_pos1 - stair_radius1 as i32).with_z(floor_level - height),
|
||||
max: (stair_pos1 + stair_radius1 as i32).with_z(floor_level + 4),
|
||||
}));
|
||||
painter
|
||||
.prim(Primitive::sampling(
|
||||
stairs_clear1,
|
||||
crate::site2::plot::dungeon::spiral_staircase(
|
||||
stair_pos1.with_z(floor_level + 4),
|
||||
stair_radius1,
|
||||
0.5,
|
||||
7.0,
|
||||
),
|
||||
))
|
||||
.fill(brick.clone());
|
||||
}
|
||||
// spawn mountaineers in each room
|
||||
let spawn_pos = super_center.with_z(floor_level + 4);
|
||||
let npc_amount = RandomField::new(0).get(spawn_pos) % 4;
|
||||
for _ in 0..npc_amount {
|
||||
let mut rng = rand::thread_rng();
|
||||
painter.spawn(
|
||||
EntityInfo::at(spawn_pos.map(|e| e as f32))
|
||||
.with_asset_expect("common.entity.village.mountaineer", &mut rng),
|
||||
);
|
||||
}
|
||||
}
|
||||
// vary next storey
|
||||
length += -1;
|
||||
width += -1;
|
||||
height += -1;
|
||||
floor_level += height;
|
||||
mem::swap(&mut length, &mut width);
|
||||
mem::swap(&mut stair_pos1, &mut stair_pos2);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user