mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added large caves, cave scatter, removed old caves
This commit is contained in:
parent
10757d0325
commit
41229b4665
10
assets/common/cave_scatter.ron
Normal file
10
assets/common/cave_scatter.ron
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[
|
||||||
|
(25, Velorite),
|
||||||
|
(50, VeloriteFrag),
|
||||||
|
(15, WhiteFlower),
|
||||||
|
(80, ShortGrass),
|
||||||
|
(150, Mushroom),
|
||||||
|
(5, Chest),
|
||||||
|
(2, Crate),
|
||||||
|
(1, Scarecrow),
|
||||||
|
]
|
@ -1,5 +1,4 @@
|
|||||||
pub mod armor;
|
pub mod armor;
|
||||||
pub mod lottery;
|
|
||||||
pub mod tool;
|
pub mod tool;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
@ -9,6 +8,7 @@ use crate::{
|
|||||||
assets::{self, Asset},
|
assets::{self, Asset},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
terrain::{Block, BlockKind},
|
terrain::{Block, BlockKind},
|
||||||
|
lottery::Lottery,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
@ -161,7 +161,7 @@ impl Item {
|
|||||||
BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")),
|
BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")),
|
||||||
BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.food.coconut")),
|
BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.food.coconut")),
|
||||||
BlockKind::Chest => {
|
BlockKind::Chest => {
|
||||||
let chosen = assets::load_expect::<lottery::Lottery<_>>("common.loot_table");
|
let chosen = assets::load_expect::<Lottery<String>>("common.loot_table");
|
||||||
let chosen = chosen.choose();
|
let chosen = chosen.choose();
|
||||||
|
|
||||||
Some(assets::load_expect_cloned(chosen))
|
Some(assets::load_expect_cloned(chosen))
|
||||||
|
@ -39,5 +39,6 @@ pub mod terrain;
|
|||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod vol;
|
pub mod vol;
|
||||||
pub mod volumes;
|
pub mod volumes;
|
||||||
|
pub mod lottery;
|
||||||
|
|
||||||
pub use loadout_builder::LoadoutBuilder;
|
pub use loadout_builder::LoadoutBuilder;
|
||||||
|
@ -1,25 +1,19 @@
|
|||||||
use crate::assets::{self, Asset};
|
use crate::assets::{self, Asset};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||||
use std::{fs::File, io::BufReader};
|
use std::{fs::File, io::BufReader};
|
||||||
|
|
||||||
// Generate a random float between 0 and 1
|
|
||||||
pub fn rand() -> f32 {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
rng.gen()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Lottery<T> {
|
pub struct Lottery<T> {
|
||||||
items: Vec<(f32, T)>,
|
items: Vec<(f32, T)>,
|
||||||
total: f32,
|
total: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Asset for Lottery<String> {
|
impl<T: DeserializeOwned + Send + Sync> Asset for Lottery<T> {
|
||||||
const ENDINGS: &'static [&'static str] = &["ron"];
|
const ENDINGS: &'static [&'static str] = &["ron"];
|
||||||
|
|
||||||
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
||||||
ron::de::from_reader::<BufReader<File>, Vec<(f32, String)>>(buf_reader)
|
ron::de::from_reader::<BufReader<File>, Vec<(f32, T)>>(buf_reader)
|
||||||
.map(|items| Lottery::from_rates(items.into_iter()))
|
.map(|items| Lottery::from_rates(items.into_iter()))
|
||||||
.map_err(assets::Error::parse_error)
|
.map_err(assets::Error::parse_error)
|
||||||
}
|
}
|
||||||
@ -37,8 +31,8 @@ impl<T> Lottery<T> {
|
|||||||
Self { items, total }
|
Self { items, total }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose(&self) -> &T {
|
pub fn choose_seeded(&self, seed: u32) -> &T {
|
||||||
let x = rand() * self.total;
|
let x = ((seed % 65536) as f32 / 65536.0) * self.total;
|
||||||
&self.items[self
|
&self.items[self
|
||||||
.items
|
.items
|
||||||
.binary_search_by(|(y, _)| y.partial_cmp(&x).unwrap())
|
.binary_search_by(|(y, _)| y.partial_cmp(&x).unwrap())
|
||||||
@ -46,6 +40,10 @@ impl<T> Lottery<T> {
|
|||||||
.1
|
.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn choose(&self) -> &T {
|
||||||
|
self.choose_seeded(thread_rng().gen())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &(f32, T)> { self.items.iter() }
|
pub fn iter(&self) -> impl Iterator<Item = &(f32, T)> { self.items.iter() }
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::{client::Client, Server, SpawnPoint, StateExt};
|
|||||||
use common::{
|
use common::{
|
||||||
assets,
|
assets,
|
||||||
comp::{
|
comp::{
|
||||||
self, item::lottery::Lottery, object, Alignment, Body, Damage, DamageSource, Group,
|
self, object, Alignment, Body, Damage, DamageSource, Group,
|
||||||
HealthChange, HealthSource, Player, Pos, Stats,
|
HealthChange, HealthSource, Player, Pos, Stats,
|
||||||
},
|
},
|
||||||
msg::{PlayerListUpdate, ServerMsg},
|
msg::{PlayerListUpdate, ServerMsg},
|
||||||
@ -12,6 +12,7 @@ use common::{
|
|||||||
sys::combat::BLOCK_ANGLE,
|
sys::combat::BLOCK_ANGLE,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
vol::{ReadVol, Vox},
|
vol::{ReadVol, Vox},
|
||||||
|
lottery::Lottery,
|
||||||
};
|
};
|
||||||
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
use specs::{join::Join, saveload::MarkerAllocator, Entity as EcsEntity, WorldExt};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
@ -182,7 +183,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
item_drops.remove(entity);
|
item_drops.remove(entity);
|
||||||
item_drop.0
|
item_drop.0
|
||||||
} else {
|
} else {
|
||||||
let chosen = assets::load_expect::<Lottery<_>>("common.loot_table");
|
let chosen = assets::load_expect::<Lottery<String>>("common.loot_table");
|
||||||
let chosen = chosen.choose();
|
let chosen = chosen.choose();
|
||||||
|
|
||||||
assets::load_expect_cloned(chosen)
|
assets::load_expect_cloned(chosen)
|
||||||
|
@ -164,8 +164,6 @@ impl<'a> BlockGen<'a> {
|
|||||||
//tree_density,
|
//tree_density,
|
||||||
//forest_kind,
|
//forest_kind,
|
||||||
//close_structures,
|
//close_structures,
|
||||||
cave_xy,
|
|
||||||
cave_alt,
|
|
||||||
marble,
|
marble,
|
||||||
marble_small,
|
marble_small,
|
||||||
rock,
|
rock,
|
||||||
@ -370,23 +368,6 @@ impl<'a> BlockGen<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.and_then(|block| {
|
|
||||||
// Caves
|
|
||||||
// Underground
|
|
||||||
let cave = cave_xy.powf(2.0)
|
|
||||||
* (wposf.z as f32 - cave_alt)
|
|
||||||
.div(40.0)
|
|
||||||
.powf(4.0)
|
|
||||||
.neg()
|
|
||||||
.add(1.0)
|
|
||||||
> 0.9993;
|
|
||||||
|
|
||||||
if cave && wposf.z as f32 > water_height + 3.0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(block)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
// Water
|
// Water
|
||||||
if (wposf.z as f32) < water_height {
|
if (wposf.z as f32) < water_height {
|
||||||
@ -422,14 +403,7 @@ pub struct ZCache<'a> {
|
|||||||
|
|
||||||
impl<'a> ZCache<'a> {
|
impl<'a> ZCache<'a> {
|
||||||
pub fn get_z_limits(&self, block_gen: &mut BlockGen, index: &Index) -> (f32, f32, f32) {
|
pub fn get_z_limits(&self, block_gen: &mut BlockGen, index: &Index) -> (f32, f32, f32) {
|
||||||
let cave_depth =
|
let min = self.sample.alt - (self.sample.chaos.min(1.0) * 16.0);
|
||||||
if self.sample.cave_xy.abs() > 0.9 && self.sample.water_level <= self.sample.alt {
|
|
||||||
(self.sample.alt - self.sample.cave_alt + 8.0).max(0.0)
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
|
|
||||||
let min = self.sample.alt - (self.sample.chaos.min(1.0) * 16.0 + cave_depth);
|
|
||||||
let min = min - 4.0;
|
let min = min - 4.0;
|
||||||
|
|
||||||
let cliff = BlockGen::get_cliff_height(
|
let cliff = BlockGen::get_cliff_height(
|
||||||
|
@ -214,7 +214,8 @@ impl Civs {
|
|||||||
|
|
||||||
// TODO: Move this
|
// TODO: Move this
|
||||||
fn generate_cave(&self, ctx: &mut GenCtx<impl Rng>) {
|
fn generate_cave(&self, ctx: &mut GenCtx<impl Rng>) {
|
||||||
let mut pos = ctx.sim
|
let mut pos = ctx
|
||||||
|
.sim
|
||||||
.get_size()
|
.get_size()
|
||||||
.map(|sz| ctx.rng.gen_range(0, sz as i32) as f32);
|
.map(|sz| ctx.rng.gen_range(0, sz as i32) as f32);
|
||||||
let mut vel = pos
|
let mut vel = pos
|
||||||
@ -225,14 +226,16 @@ impl Civs {
|
|||||||
let path = (-100..100)
|
let path = (-100..100)
|
||||||
.filter_map(|i: i32| {
|
.filter_map(|i: i32| {
|
||||||
let depth = (i.abs() as f32 / 100.0 * std::f32::consts::PI / 2.0).cos();
|
let depth = (i.abs() as f32 / 100.0 * std::f32::consts::PI / 2.0).cos();
|
||||||
vel = (vel + Vec2::new(
|
vel = (vel
|
||||||
ctx.rng.gen_range(-0.25, 0.25),
|
+ Vec2::new(
|
||||||
ctx.rng.gen_range(-0.25, 0.25),
|
ctx.rng.gen_range(-0.35, 0.35),
|
||||||
))
|
ctx.rng.gen_range(-0.35, 0.35),
|
||||||
.try_normalized()
|
))
|
||||||
.unwrap_or_else(Vec2::unit_y);
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
let old_pos = pos.map(|e| e as i32);
|
let old_pos = pos.map(|e| e as i32);
|
||||||
pos = (pos + vel * 0.5).clamped(Vec2::zero(), ctx.sim.get_size().map(|e| e as f32 - 1.0));
|
pos = (pos + vel * 0.5)
|
||||||
|
.clamped(Vec2::zero(), ctx.sim.get_size().map(|e| e as f32 - 1.0));
|
||||||
Some((pos.map(|e| e as i32), depth)).filter(|(pos, _)| *pos != old_pos)
|
Some((pos.map(|e| e as i32), depth)).filter(|(pos, _)| *pos != old_pos)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -256,15 +259,12 @@ impl Civs {
|
|||||||
ctx.sim.get_mut(locs[2].0).unwrap().cave.0.neighbors |=
|
ctx.sim.get_mut(locs[2].0).unwrap().cave.0.neighbors |=
|
||||||
1 << ((to_next_idx as u8 + 4) % 8);
|
1 << ((to_next_idx as u8 + 4) % 8);
|
||||||
let mut chunk = ctx.sim.get_mut(locs[1].0).unwrap();
|
let mut chunk = ctx.sim.get_mut(locs[1].0).unwrap();
|
||||||
chunk.cave.0.neighbors |=
|
chunk.cave.0.neighbors |= (1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
||||||
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
let depth = locs[1].1 * 250.0 - 20.0;
|
||||||
let depth = locs[1].1 * 250.0;
|
chunk.cave.1.alt =
|
||||||
chunk.cave.1.alt = chunk.alt - depth + ctx.rng.gen_range(-4.0, 4.0) * (depth > 10.0) as i32 as f32;
|
chunk.alt - depth + ctx.rng.gen_range(-4.0, 4.0) * (depth > 10.0) as i32 as f32;
|
||||||
chunk.cave.1.width = ctx.rng.gen_range(12.0, 32.0);
|
chunk.cave.1.width = ctx.rng.gen_range(6.0, 32.0);
|
||||||
chunk.cave.0.offset = Vec2::new(
|
chunk.cave.0.offset = Vec2::new(ctx.rng.gen_range(-16, 17), ctx.rng.gen_range(-16, 17));
|
||||||
ctx.rng.gen_range(-16, 17),
|
|
||||||
ctx.rng.gen_range(-16, 17),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,10 +492,8 @@ impl Civs {
|
|||||||
let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
|
let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
|
||||||
chunk.path.0.neighbors |=
|
chunk.path.0.neighbors |=
|
||||||
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
||||||
chunk.path.0.offset = Vec2::new(
|
chunk.path.0.offset =
|
||||||
ctx.rng.gen_range(-16, 17),
|
Vec2::new(ctx.rng.gen_range(-16, 17), ctx.rng.gen_range(-16, 17));
|
||||||
ctx.rng.gen_range(-16, 17),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take note of the track
|
// Take note of the track
|
||||||
|
@ -2,8 +2,8 @@ use crate::{
|
|||||||
all::ForestKind,
|
all::ForestKind,
|
||||||
block::StructureMeta,
|
block::StructureMeta,
|
||||||
sim::{
|
sim::{
|
||||||
local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx,
|
local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, Cave, Path, RiverKind, SimChunk,
|
||||||
Path, Cave, RiverKind, SimChunk, WorldSim,
|
WorldSim,
|
||||||
},
|
},
|
||||||
util::Sampler,
|
util::Sampler,
|
||||||
Index, CONFIG,
|
Index, CONFIG,
|
||||||
@ -1038,34 +1038,6 @@ where
|
|||||||
(alt, ground, sub_surface_color)
|
(alt, ground, sub_surface_color)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Caves
|
|
||||||
let cave_at = |wposf: Vec2<f64>| {
|
|
||||||
(sim.gen_ctx.cave_0_nz.get(
|
|
||||||
Vec3::new(wposf.x, wposf.y, alt as f64 * 8.0)
|
|
||||||
.div(800.0)
|
|
||||||
.into_array(),
|
|
||||||
) as f32)
|
|
||||||
.powf(2.0)
|
|
||||||
.neg()
|
|
||||||
.add(1.0)
|
|
||||||
.mul((1.32 - chaos).min(1.0))
|
|
||||||
};
|
|
||||||
let cave_xy = cave_at(wposf);
|
|
||||||
let cave_alt = alt - 24.0
|
|
||||||
+ (sim
|
|
||||||
.gen_ctx
|
|
||||||
.cave_1_nz
|
|
||||||
.get(Vec2::new(wposf.x, wposf.y).div(48.0).into_array()) as f32)
|
|
||||||
* 8.0
|
|
||||||
+ (sim
|
|
||||||
.gen_ctx
|
|
||||||
.cave_1_nz
|
|
||||||
.get(Vec2::new(wposf.x, wposf.y).div(500.0).into_array()) as f32)
|
|
||||||
.add(1.0)
|
|
||||||
.mul(0.5)
|
|
||||||
.powf(15.0)
|
|
||||||
.mul(150.0);
|
|
||||||
|
|
||||||
let near_ocean = max_river.and_then(|(_, _, river_data, _)| {
|
let near_ocean = max_river.and_then(|(_, _, river_data, _)| {
|
||||||
if (river_data.is_lake() || river_data.river_kind == Some(RiverKind::Ocean))
|
if (river_data.is_lake() || river_data.river_kind == Some(RiverKind::Ocean))
|
||||||
&& ((alt <= water_level.max(CONFIG.sea_level + 5.0) && !is_cliffs) || !near_cliffs)
|
&& ((alt <= water_level.max(CONFIG.sea_level + 5.0) && !is_cliffs) || !near_cliffs)
|
||||||
@ -1118,8 +1090,6 @@ where
|
|||||||
},
|
},
|
||||||
forest_kind: sim_chunk.forest_kind,
|
forest_kind: sim_chunk.forest_kind,
|
||||||
close_structures: self.gen_close_structures(wpos),
|
close_structures: self.gen_close_structures(wpos),
|
||||||
cave_xy,
|
|
||||||
cave_alt,
|
|
||||||
marble,
|
marble,
|
||||||
marble_small,
|
marble_small,
|
||||||
rock,
|
rock,
|
||||||
@ -1153,8 +1123,6 @@ pub struct ColumnSample<'a> {
|
|||||||
pub tree_density: f32,
|
pub tree_density: f32,
|
||||||
pub forest_kind: ForestKind,
|
pub forest_kind: ForestKind,
|
||||||
pub close_structures: [Option<StructureData>; 9],
|
pub close_structures: [Option<StructureData>; 9],
|
||||||
pub cave_xy: f32,
|
|
||||||
pub cave_alt: f32,
|
|
||||||
pub marble: f32,
|
pub marble: f32,
|
||||||
pub marble_small: f32,
|
pub marble_small: f32,
|
||||||
pub rock: f32,
|
pub rock: f32,
|
||||||
|
@ -3,6 +3,16 @@ use common::store::{Id, Store};
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Index {
|
pub struct Index {
|
||||||
|
pub seed: u32,
|
||||||
pub time: f32,
|
pub time: f32,
|
||||||
pub sites: Store<Site>,
|
pub sites: Store<Site>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Index {
|
||||||
|
pub fn new(seed: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
seed,
|
||||||
|
..Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
column::ColumnSample,
|
column::ColumnSample,
|
||||||
util::{RandomField, Sampler},
|
util::{RandomField, Sampler},
|
||||||
|
Index,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{Block, BlockKind},
|
terrain::{Block, BlockKind},
|
||||||
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
|
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
|
||||||
|
lottery::Lottery,
|
||||||
|
assets,
|
||||||
};
|
};
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -13,6 +16,7 @@ pub fn apply_paths_to<'a>(
|
|||||||
wpos2d: Vec2<i32>,
|
wpos2d: Vec2<i32>,
|
||||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
||||||
|
index: &Index,
|
||||||
) {
|
) {
|
||||||
for y in 0..vol.size_xy().y as i32 {
|
for y in 0..vol.size_xy().y as i32 {
|
||||||
for x in 0..vol.size_xy().x as i32 {
|
for x in 0..vol.size_xy().x as i32 {
|
||||||
@ -100,6 +104,7 @@ pub fn apply_caves_to<'a>(
|
|||||||
wpos2d: Vec2<i32>,
|
wpos2d: Vec2<i32>,
|
||||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
||||||
|
index: &Index,
|
||||||
) {
|
) {
|
||||||
for y in 0..vol.size_xy().y as i32 {
|
for y in 0..vol.size_xy().y as i32 {
|
||||||
for x in 0..vol.size_xy().x as i32 {
|
for x in 0..vol.size_xy().x as i32 {
|
||||||
@ -120,14 +125,26 @@ pub fn apply_caves_to<'a>(
|
|||||||
.filter(|(dist, _, cave, _)| *dist < cave.width)
|
.filter(|(dist, _, cave, _)| *dist < cave.width)
|
||||||
{
|
{
|
||||||
let cave_x = (cave_dist / cave.width).min(1.0);
|
let cave_x = (cave_dist / cave.width).min(1.0);
|
||||||
let height = (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
|
||||||
|
|
||||||
for z in (cave.alt - height) as i32..(cave.alt + height) as i32 {
|
// Relative units
|
||||||
let _ = vol.set(
|
let cave_floor = 0.0 - 0.5 * (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
||||||
Vec3::new(offs.x, offs.y, z),
|
let cave_height = (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
||||||
Block::empty(),
|
|
||||||
);
|
// Abs units
|
||||||
|
let cave_base = (cave.alt + cave_floor) as i32;
|
||||||
|
let cave_roof = (cave.alt + cave_height) as i32;
|
||||||
|
|
||||||
|
for z in cave_base..cave_roof {
|
||||||
|
let _ = vol.set(Vec3::new(offs.x, offs.y, z), Block::empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scatter things in caves
|
||||||
|
if RandomField::new(index.seed).chance(wpos2d.into(), 0.002) && cave_base < surface_z as i32 - 25 {
|
||||||
|
let kind = *assets::load_expect::<Lottery<BlockKind>>("common.cave_scatter")
|
||||||
|
.choose_seeded(RandomField::new(index.seed + 1).get(wpos2d.into()));
|
||||||
|
let _ = vol.set(Vec3::new(offs.x, offs.y, cave_base), Block::new(kind, Rgb::zero()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ pub struct World {
|
|||||||
impl World {
|
impl World {
|
||||||
pub fn generate(seed: u32, opts: sim::WorldOpts) -> Self {
|
pub fn generate(seed: u32, opts: sim::WorldOpts) -> Self {
|
||||||
let mut sim = sim::WorldSim::generate(seed, opts);
|
let mut sim = sim::WorldSim::generate(seed, opts);
|
||||||
let mut index = Index::default();
|
let mut index = Index::new(seed);
|
||||||
let civs = civ::Civs::generate(seed, &mut sim, &mut index);
|
let civs = civ::Civs::generate(seed, &mut sim, &mut index);
|
||||||
|
|
||||||
sim2::simulate(&mut index, &mut sim);
|
sim2::simulate(&mut index, &mut sim);
|
||||||
@ -176,8 +176,8 @@ impl World {
|
|||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
// Apply layers (paths, caves, etc.)
|
// Apply layers (paths, caves, etc.)
|
||||||
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk);
|
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk, &self.index);
|
||||||
layer::apply_caves_to(chunk_wpos2d, sample_get, &mut chunk);
|
layer::apply_caves_to(chunk_wpos2d, sample_get, &mut chunk, &self.index);
|
||||||
|
|
||||||
// Apply site generation
|
// Apply site generation
|
||||||
sim_chunk.sites.iter().for_each(|site| {
|
sim_chunk.sites.iter().for_each(|site| {
|
||||||
|
@ -2,8 +2,8 @@ mod diffusion;
|
|||||||
mod erosion;
|
mod erosion;
|
||||||
mod location;
|
mod location;
|
||||||
mod map;
|
mod map;
|
||||||
mod way;
|
|
||||||
mod util;
|
mod util;
|
||||||
|
mod way;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
use self::erosion::Compute;
|
use self::erosion::Compute;
|
||||||
@ -15,12 +15,12 @@ pub use self::{
|
|||||||
},
|
},
|
||||||
location::Location,
|
location::Location,
|
||||||
map::{MapConfig, MapDebug},
|
map::{MapConfig, MapDebug},
|
||||||
way::{Way, Path, Cave},
|
|
||||||
util::{
|
util::{
|
||||||
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors,
|
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors,
|
||||||
uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
|
uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
|
||||||
NEIGHBOR_DELTA,
|
NEIGHBOR_DELTA,
|
||||||
},
|
},
|
||||||
|
way::{Cave, Path, Way},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -1703,7 +1703,7 @@ impl WorldSim {
|
|||||||
/// Return the distance to the nearest way in blocks, along with the
|
/// Return the distance to the nearest way in blocks, along with the
|
||||||
/// closest point on the way, the way metadata, and the tangent vector
|
/// closest point on the way, the way metadata, and the tangent vector
|
||||||
/// of that way.
|
/// of that way.
|
||||||
pub fn get_nearest_way<M: Clone + Lerp<Output=M>>(
|
pub fn get_nearest_way<M: Clone + Lerp<Output = M>>(
|
||||||
&self,
|
&self,
|
||||||
wpos: Vec2<i32>,
|
wpos: Vec2<i32>,
|
||||||
get_way: impl Fn(&SimChunk) -> Option<(Way, M)>,
|
get_way: impl Fn(&SimChunk) -> Option<(Way, M)>,
|
||||||
@ -1722,7 +1722,8 @@ impl WorldSim {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ctrl| {
|
.filter_map(|ctrl| {
|
||||||
let (way, meta) = get_way(self.get(chunk_pos + *ctrl)?)?;
|
let (way, meta) = get_way(self.get(chunk_pos + *ctrl)?)?;
|
||||||
let ctrl_pos = get_chunk_centre(chunk_pos + *ctrl).map(|e| e as f32) + way.offset.map(|e| e as f32);
|
let ctrl_pos = get_chunk_centre(chunk_pos + *ctrl).map(|e| e as f32)
|
||||||
|
+ way.offset.map(|e| e as f32);
|
||||||
|
|
||||||
let chunk_connections = way.neighbors.count_ones();
|
let chunk_connections = way.neighbors.count_ones();
|
||||||
if chunk_connections == 0 {
|
if chunk_connections == 0 {
|
||||||
|
@ -467,7 +467,15 @@ impl Floor {
|
|||||||
if room.boss {
|
if room.boss {
|
||||||
let boss_spawn_tile = room.area.center();
|
let boss_spawn_tile = room.area.center();
|
||||||
// Don't spawn the boss in a pillar
|
// Don't spawn the boss in a pillar
|
||||||
let boss_spawn_tile = boss_spawn_tile + if tile_is_pillar { 1 } else { 0 };
|
let boss_tile_is_pillar = room
|
||||||
|
.pillars
|
||||||
|
.map(|pillar_space| {
|
||||||
|
boss_spawn_tile
|
||||||
|
.map(|e| e.rem_euclid(pillar_space) == 0)
|
||||||
|
.reduce_and()
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
let boss_spawn_tile = boss_spawn_tile + if boss_tile_is_pillar { 1 } else { 0 };
|
||||||
|
|
||||||
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
Loading…
Reference in New Issue
Block a user