Skip to main content

veloren_world/site/plot/
troll_cave.rs

1use super::*;
2use crate::{
3    Land,
4    assets::AssetHandle,
5    site::generation::PrimitiveTransform,
6    util::{RandomField, sampler::Sampler},
7};
8use common::{
9    generation::EntityInfo,
10    terrain::{Structure as PrefabStructure, StructuresGroup},
11};
12use lazy_static::lazy_static;
13use rand::prelude::*;
14use vek::*;
15
16pub struct TrollCave {
17    bounds: Aabr<i32>,
18    pub(crate) alt: i32,
19    temp: f32,
20}
21impl TrollCave {
22    pub fn generate(
23        land: &Land,
24        _rng: &mut impl Rng,
25        site: &Site,
26        tile_aabr: Aabr<i32>,
27        site_temp: f32,
28    ) -> Self {
29        let bounds = Aabr {
30            min: site.tile_wpos(tile_aabr.min),
31            max: site.tile_wpos(tile_aabr.max),
32        };
33        let temp = site_temp;
34        Self {
35            bounds,
36            alt: land.get_alt_approx(site.tile_center_wpos(tile_aabr.center())) as i32 + 2,
37            temp,
38        }
39    }
40}
41
42impl Structure for TrollCave {
43    #[cfg(feature = "dyn-lib")]
44    #[unsafe(export_name = "as_dyn_structure_trollcave")]
45    fn as_dyn_outer(&self) -> Option<(&dyn Structure, &'static str)> {
46        Some((Self::as_dyn_impl(self), "as_dyn_structure_trollcave"))
47    }
48
49    fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
50        let center = self.bounds.center();
51        let base = land.get_alt_approx(center) as i32;
52        let mut rng = rand::rng();
53        let model_pos = center.with_z(base);
54        // model
55        lazy_static! {
56            pub static ref MODEL: AssetHandle<StructuresGroup> =
57                PrefabStructure::load_group("site_structures.troll_cave.troll_cave");
58        }
59        let rng_val = RandomField::new(0).get(model_pos) % 10;
60        let model = MODEL.read();
61        let model = model[rng_val as usize % model.len()].clone();
62        painter
63            .prim(Primitive::Prefab(Box::new(model.clone())))
64            .translate(model_pos)
65            .fill(Fill::Prefab(Box::new(model), model_pos, rng_val));
66        let temp = self.temp;
67        // npcs
68        let troll = if temp >= CONFIG.tropical_temp {
69            "common.entity.wild.aggressive.swamp_troll"
70        } else if temp <= (CONFIG.snow_temp) {
71            "common.entity.wild.aggressive.mountain_troll"
72        } else {
73            "common.entity.wild.aggressive.cave_troll"
74        };
75
76        // troll
77        painter.spawn(
78            EntityInfo::at(center.with_z(base - 15).as_()).with_asset_expect(troll, &mut rng, None),
79        );
80        // bat
81        painter.spawn(
82            EntityInfo::at((center - 2).with_z(base + 5).as_()).with_asset_expect(
83                "common.entity.wild.peaceful.bat",
84                &mut rng,
85                None,
86            ),
87        )
88    }
89}