veloren_common/
spot.rs

1use common_assets::{Asset, AssetCombined, AssetHandle, Concatenate, RonLoader};
2use lazy_static::lazy_static;
3
4use crate::terrain::BiomeKind;
5use strum::EnumIter;
6
7/// Spots are localised structures that spawn in the world. Conceptually, they
8/// fit somewhere between the tree generator and the site generator: an attempt
9/// to marry the simplicity of the former with the capability of the latter.
10/// They are not globally visible to the game: this means that they do not
11/// appear on the map, and cannot interact with rtsim (much).
12///
13/// To add a new spot, one must:
14///
15/// 1. Add a new variant to the [`Spot`] enum.
16/// 2. Add a new entry to [`veloren-world::layer::spot::SpotGenerate::generate`]
17///    that tells the system where to generate your new spot.
18/// 3. Add a new arm to the `match` expression in
19///    [`veloren-world::layer::spot::apply_spots_to`] that tells the generator
20///    how to generate a spot, including the base structure that composes the
21///    spot and the entities that should be spawned there.
22///
23/// Only add spots with randomly spawned NPCs here. Spots that only use
24/// EntitySpawner blocks can be added in assets/world/manifests/spots.ron
25#[derive(Copy, Clone, Debug, EnumIter, PartialEq)]
26pub enum Spot {
27    DwarvenGrave,
28    SaurokAltar,
29    MyrmidonTemple,
30    GnarlingTotem,
31    WitchHouse,
32    GnomeSpring,
33    WolfBurrow,
34    Igloo,
35    //BanditCamp,
36    //EnchantedRock,
37    //TowerRuin,
38    //WellOfLight,
39    //MerchantOutpost,
40    //RuinedHuntingCabin, <-- Bears!
41    // *Random world objects*
42    LionRock,
43    TreeStumpForest,
44    DesertBones,
45    Arch,
46    AirshipCrash,
47    FruitTree,
48    Shipwreck,
49    Shipwreck2,
50    FallenTree,
51    GraveSmall,
52    JungleTemple,
53    SaurokTotem,
54    JungleOutpost,
55    #[strum(disabled)]
56    RonFile(&'static SpotProperties),
57}
58
59#[derive(serde::Deserialize, Clone, Debug, PartialEq)]
60pub enum SpotCondition {
61    MaxGradient(f32),
62    Biome(Vec<BiomeKind>),
63    NearCliffs,
64    NearRiver,
65    IsWay,
66    IsUnderwater,
67
68    /// no cliffs, no river, no way
69    Typical,
70    /// implies IsUnderwater
71    MinWaterDepth(f32),
72
73    Not(Box<SpotCondition>),
74    All(Vec<SpotCondition>),
75    Any(Vec<SpotCondition>),
76}
77
78#[derive(serde::Deserialize, Clone, Debug, PartialEq)]
79pub struct SpotProperties {
80    pub base_structures: String,
81    pub freq: f32,
82    pub condition: SpotCondition,
83    pub spawn: bool,
84}
85
86#[derive(serde::Deserialize, Clone, Debug)]
87#[serde(transparent)]
88pub struct RonSpots(pub Vec<SpotProperties>);
89
90impl Asset for RonSpots {
91    type Loader = RonLoader;
92
93    const EXTENSION: &'static str = "ron";
94}
95
96impl Concatenate for RonSpots {
97    fn concatenate(self, b: Self) -> Self { Self(self.0.concatenate(b.0)) }
98}
99
100lazy_static! {
101    pub static ref RON_SPOT_PROPERTIES: RonSpots = {
102        let spots: AssetHandle<RonSpots> =
103            RonSpots::load_expect_combined_static("world.manifests.spots");
104        RonSpots(spots.read().0.to_vec())
105    };
106}