Merge branch 'clifftown_relocation' into 'master'

clifftown_relocation

See merge request veloren/veloren!4194
This commit is contained in:
flo 2023-11-25 20:58:05 +00:00
commit e9ae0a4c9e
3 changed files with 111 additions and 60 deletions

View File

@ -439,7 +439,7 @@ impl Civs {
SiteKind::Dungeon => (8i32, 3.0),
SiteKind::Castle => (16i32, 5.0),
SiteKind::Refactor => (32i32, 10.0),
SiteKind::CliffTown => (64i32, 25.0),
SiteKind::CliffTown => (2i32, 1.0),
SiteKind::SavannahPit => (48i32, 25.0),
SiteKind::CoastalTown => (64i32, 35.0),
SiteKind::JungleRuin => (8i32, 3.0),
@ -546,6 +546,7 @@ impl Civs {
},
SiteKind::CliffTown => WorldSite::cliff_town(site2::Site::generate_cliff_town(
&Land::from_sim(ctx.sim),
index_ref,
&mut rng,
wpos,
)),
@ -1793,6 +1794,7 @@ fn town_attributes_of_site(loc: Vec2<i32>, sim: &WorldSim) -> Option<TownSiteAtt
let has_lake = lake_chunks > 1;
let vegetation_implies_potable_water = chunk.tree_density > 0.4
&& !matches!(chunk.get_biome(), common::terrain::BiomeKind::Swamp);
let has_many_rocks = chunk.rockiness > 1.2;
let warm_or_firewood = chunk.temp > CONFIG.snow_temp || tree_chunks > 2;
let has_potable_water =
{ has_river || (has_lake && chunk.alt > 100.0) || vegetation_implies_potable_water };
@ -1825,6 +1827,7 @@ fn town_attributes_of_site(loc: Vec2<i32>, sim: &WorldSim) -> Option<TownSiteAtt
heating: warm_or_firewood,
potable_water: has_potable_water,
building_materials: has_building_materials,
aquifer: has_many_rocks,
}
})
}
@ -1837,6 +1840,7 @@ pub struct TownSiteAttributes {
heating: bool,
potable_water: bool,
building_materials: bool,
aquifer: bool,
}
impl TownSiteAttributes {
@ -1942,7 +1946,8 @@ impl SiteKind {
let suitable_for_town = || -> bool {
let attributes = town_attributes_of_site(loc, sim);
attributes.map_or(false, |attributes| {
attributes.potable_water
// aquifer and has_many_rocks was added to make mesa clifftowns suitable for towns
(attributes.potable_water || (attributes.aquifer && matches!(self, SiteKind::CliffTown)))
&& attributes.building_materials
&& attributes.heating
// Because of how the algorithm for site2 towns work, they have to start on land.
@ -1971,9 +1976,9 @@ impl SiteKind {
},
SiteKind::Citadel => true,
SiteKind::CliffTown => {
(-0.6..0.4).contains(&chunk.temp)
&& chunk.near_cliffs()
&& !chunk.river.near_water()
chunk.temp >= CONFIG.desert_temp
&& chunk.cliff_height > 40.0
&& chunk.rockiness > 1.2
&& suitable_for_town()
},
SiteKind::SavannahPit => {

View File

@ -924,7 +924,12 @@ impl Site {
site
}
pub fn generate_cliff_town(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
pub fn generate_cliff_town(
land: &Land,
index: IndexRef,
rng: &mut impl Rng,
origin: Vec2<i32>,
) -> Self {
let mut rng = reseed(rng);
let mut site = Site {
origin,
@ -935,13 +940,14 @@ impl Site {
site.make_plaza(land, &mut rng);
for _ in 0..30 {
// CliffTower
let size = (8.0 + rng.gen::<f32>().powf(5.0) * 1.0).round() as u32;
let size = (9.0 + rng.gen::<f32>().powf(5.0) * 1.0).round() as u32;
let campfire = campfires < 4;
if let Some((aabr, door_tile, door_dir)) = attempt(32, || {
site.find_roadside_aabr(&mut rng, 8..(size + 1).pow(2), Extent2::broadcast(size))
}) {
let cliff_tower = plot::CliffTower::generate(
land,
index,
&mut reseed(&mut rng),
&site,
door_tile,

View File

@ -1,5 +1,6 @@
use super::*;
use crate::{
site2::util::gradient::WrapMode,
util::{RandomField, Sampler, DIAGONALS, LOCALITY},
Land,
};
@ -8,7 +9,7 @@ use common::{
terrain::{BlockKind, SpriteKind},
};
use rand::prelude::*;
use std::{f32::consts::TAU, mem, sync::Arc};
use std::{f32::consts::TAU, mem};
use vek::*;
/// Represents house data generated by the `generate()` method
@ -21,11 +22,14 @@ pub struct CliffTower {
pub(crate) alt: i32,
campfire: bool,
door_dir: Vec2<i32>,
surface_color: Rgb<f32>,
sub_surface_color: Rgb<f32>,
}
impl CliffTower {
pub fn generate(
land: &Land,
index: IndexRef,
_rng: &mut impl Rng,
site: &Site,
door_tile: Vec2<i32>,
@ -38,12 +42,20 @@ impl CliffTower {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
let (surface_color, sub_surface_color) =
if let Some(sample) = land.column_sample(bounds.center(), index) {
(sample.surface_color, sample.sub_surface_color)
} else {
(Rgb::new(161.0, 116.0, 86.0), Rgb::new(88.0, 64.0, 64.0))
};
Self {
door_tile: door_tile_pos,
bounds,
alt: land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32,
alt: land.get_alt_approx(door_tile_pos) as i32,
campfire,
door_dir,
surface_color,
sub_surface_color,
}
}
}
@ -54,9 +66,41 @@ impl Structure for CliffTower {
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_clifftower")]
fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
let base = self.alt + 1;
let base = self.alt;
let plot_center = self.bounds.center();
let door_dir = self.door_dir;
let surface_color = self.surface_color.map(|e| (e * 255.0) as u8);
let sub_surface_color = self.sub_surface_color.map(|e| (e * 255.0) as u8);
let gradient_center = Vec3::new(
plot_center.x as f32,
plot_center.y as f32,
(base + 1) as f32,
);
let gradient_var_1 = RandomField::new(0).get(plot_center.with_z(base)) as i32 % 8;
let gradient_var_2 = RandomField::new(0).get(plot_center.with_z(base + 1)) as i32 % 10;
let brick = Fill::Gradient(
util::gradient::Gradient::new(
gradient_center,
8.0 + gradient_var_1 as f32,
util::gradient::Shape::Point,
(surface_color, sub_surface_color),
)
.with_repeat(if gradient_var_2 > 5 {
WrapMode::Repeat
} else {
WrapMode::PingPong
}),
BlockKind::Rock,
);
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());
let rope = Fill::Block(Block::air(SpriteKind::Rope));
let tube_var = RandomField::new(0).get(plot_center.with_z(base)) as i32 % 6;
let radius = 10.0 + tube_var as f32;
let tubes = 3.0 + tube_var as f32;
@ -77,39 +121,12 @@ impl Structure for CliffTower {
let mut height = 18 + variant / 2;
let mut floor_level = base - 40;
let mut workshops = 0;
let mut ground_entry = 0;
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());
let rope = Fill::Block(Block::air(SpriteKind::Rope));
for _ in 0..storeys {
let mut ground_entries = 0;
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);
// CliffTower Hoodoo Overlay
painter
.cubic_bezier(
@ -120,8 +137,52 @@ impl Structure for CliffTower {
(length - 1) as f32,
)
.fill(brick.clone());
if s == (storeys - 1) {
for dir in LOCALITY {
let cone_pos = super_center + (dir * 2);
let cone_var =
4 + RandomField::new(0).get(cone_pos.with_z(base)) as i32 % 4;
painter
.cone_with_radius(
cone_pos.with_z(floor_level + (2 * height) + 5),
(length / 2) as f32,
(length + cone_var) as f32,
)
.fill(brick.clone());
}
}
// center tube with rooms
if n == tubes as i32 {
// ground_entries
if ground_entries < 1 && floor_level > (base - 6) {
for dir in CARDINALS {
let entry_pos_inner = plot_center + (dir * (2 * length) - 4);
let entry_pos_outer = plot_center + (dir * (3 * length) + 4);
painter
.line(
entry_pos_inner.with_z(floor_level + 6),
entry_pos_outer.with_z(base + 35),
6.0,
)
.clear();
}
let door_start = plot_center + door_dir * ((3 * (length / 2)) + 1);
painter
.line(
door_start.with_z(floor_level + 2),
self.door_tile.with_z(base),
4.0,
)
.fill(wood.clone());
painter
.line(
door_start.with_z(floor_level + 7),
self.door_tile.with_z(base + 6),
7.0,
)
.clear();
ground_entries += 1;
}
painter
.cubic_bezier(
plot_center.with_z(floor_level + (height / 2)),
@ -719,27 +780,6 @@ impl Structure for CliffTower {
})
.fill(rope.clone());
}
if floor_level > (base - 6) {
// ensure ground entry toward door_dir
if ground_entry < 1 {
let door_start = plot_center + door_dir * ((3 * (length / 2)) + 1);
let door_end = plot_center + door_dir * ((3 * length) - 1);
for n in 0..2 {
let door_stairs = painter.line(
door_start.with_z(floor_level + 1 + (n * 2)),
door_end.with_z(base + (n * 2)),
4.0 + (n as f32 / 2.0),
);
door_stairs.fill(wood.clone());
match n {
0 => door_stairs.fill(wood.clone()),
_ => door_stairs.clear(),
};
}
ground_entry += 1;
}
}
}
// vary next storey
length += -1;