Merge branch 'christof/ron_based_spots' into 'master'

enable spot addition via ron file

See merge request veloren/veloren!3824
This commit is contained in:
Christof Petig 2023-03-18 00:16:56 +00:00
commit a66888c3de
3 changed files with 98 additions and 0 deletions

View File

@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Camera zoom can now be locked, to prevent accidental zooming while rolling in combat. It comes
with a keybind to enable/disable the setting, and an Auto/Toggle behavior setting. Auto behavior
will only lock the camera zoom while movement and combat inputs are also being pressed.
- Custom spots can be added without recompilation (only ron and vox files)
### Changed
- Bats move slower and use a simple proportional controller to maintain altitude

View File

@ -0,0 +1,13 @@
[
// example entry, increase freq to activate
(
// ron file pointing to voxel model and defining special colors
base_structures: "spots_general.mage_tower",
// maximum occurance per each 1000km^2 world area
freq: 0.0,
// placement requirements
condition: All([Typical, MaxGradient(0.2), Biome([Forest, Taiga])]),
// whether to prevent trees etc. around this spot
spawn: false,
),
]

View File

@ -4,10 +4,12 @@ use crate::{
Canvas,
};
use common::{
assets::{Asset, AssetExt, AssetHandle, RonLoader},
generation::EntityInfo,
terrain::{BiomeKind, Structure, TerrainChunkSize},
vol::RectVolSize,
};
use lazy_static::lazy_static;
use rand::prelude::*;
use rand_chacha::ChaChaRng;
use std::ops::Range;
@ -68,6 +70,7 @@ pub enum Spot {
SaurokTotem,
JungleOutpost,
MageTower,
RonFile(&'static SpotProperties),
}
impl Spot {
@ -75,6 +78,15 @@ impl Spot {
use BiomeKind::*;
// Trees/spawn: false => *No* trees around the spot
// Themed Spots -> Act as an introduction to themes of sites
for s in RON_PROPERTIES.0.iter() {
Self::generate_spots(
Spot::RonFile(s),
world,
s.freq,
|g, c| s.condition.is_valid(g, c),
s.spawn,
);
}
Self::generate_spots(
Spot::WitchHouse,
world,
@ -773,6 +785,11 @@ pub fn apply_spots_to(canvas: &mut Canvas, _dynamic_rng: &mut impl Rng) {
entity_radius: 2.0,
entities: &[],
},
Spot::RonFile(properties) => SpotConfig {
base_structures: Some(&properties.base_structures),
entity_radius: 1.0,
entities: &[],
},
};
// Blit base structure
if let Some(base_structures) = spot_config.base_structures {
@ -818,3 +835,70 @@ pub fn apply_spots_to(canvas: &mut Canvas, _dynamic_rng: &mut impl Rng) {
}
}
}
#[derive(serde::Deserialize, Clone, Debug)]
enum SpotCondition {
MaxGradient(f32),
Biome(Vec<BiomeKind>),
NearCliffs,
NearRiver,
IsWay,
IsUnderwater,
/// no cliffs, no river, no way
Typical,
/// implies IsUnderwater
MinWaterDepth(f32),
Not(Box<SpotCondition>),
All(Vec<SpotCondition>),
Any(Vec<SpotCondition>),
}
impl SpotCondition {
fn is_valid(&self, g: f32, c: &SimChunk) -> bool {
c.sites.is_empty()
&& match self {
SpotCondition::MaxGradient(value) => g < *value,
SpotCondition::Biome(biomes) => biomes.contains(&c.get_biome()),
SpotCondition::NearCliffs => c.near_cliffs(),
SpotCondition::NearRiver => c.river.near_water(),
SpotCondition::IsWay => c.path.0.is_way(),
SpotCondition::IsUnderwater => c.is_underwater(),
SpotCondition::Typical => {
!c.near_cliffs() && !c.river.near_water() && !c.path.0.is_way()
},
SpotCondition::MinWaterDepth(depth) => {
SpotCondition::IsUnderwater.is_valid(g, c) && c.water_alt > c.alt + depth
},
SpotCondition::Not(condition) => !condition.is_valid(g, c),
SpotCondition::All(conditions) => conditions.iter().all(|cond| cond.is_valid(g, c)),
SpotCondition::Any(conditions) => conditions.iter().any(|cond| cond.is_valid(g, c)),
}
}
}
#[derive(serde::Deserialize, Clone, Debug)]
pub struct SpotProperties {
base_structures: String,
freq: f32,
condition: SpotCondition,
spawn: bool,
}
#[derive(serde::Deserialize, Clone, Debug)]
#[serde(transparent)]
struct RonSpots(Vec<SpotProperties>);
impl Asset for RonSpots {
type Loader = RonLoader;
const EXTENSION: &'static str = "ron";
}
lazy_static! {
static ref RON_PROPERTIES: RonSpots = {
let spots: AssetHandle<RonSpots> = AssetExt::load_expect("world.manifests.spots");
RonSpots(spots.read().0.to_vec())
};
}