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