Skip to main content

veloren_world/site/plot/
camp.rs

1use super::*;
2use crate::{Land, assets::AssetHandle, site::generation::PrimitiveTransform};
3use common::{
4    generation::EntityInfo,
5    terrain::{Structure as PrefabStructure, StructuresGroup},
6};
7use lazy_static::lazy_static;
8
9use rand::prelude::*;
10use vek::*;
11
12pub struct Camp {
13    bounds: Aabr<i32>,
14    pub(crate) alt: i32,
15    temp: f32,
16}
17
18#[derive(Copy, Clone)]
19enum CampType {
20    Pirate,
21    Snow,
22    Forest,
23}
24
25impl Camp {
26    pub fn generate(
27        land: &Land,
28        _rng: &mut impl Rng,
29        site: &Site,
30        tile_aabr: Aabr<i32>,
31        site_temp: f32,
32    ) -> Self {
33        let bounds = Aabr {
34            min: site.tile_wpos(tile_aabr.min),
35            max: site.tile_wpos(tile_aabr.max),
36        };
37        let temp = site_temp;
38        Self {
39            bounds,
40            alt: land.get_alt_approx(site.tile_center_wpos(tile_aabr.center())) as i32 + 2,
41            temp,
42        }
43    }
44}
45
46impl Structure for Camp {
47    #[cfg(feature = "dyn-lib")]
48    #[unsafe(export_name = "as_dyn_structure_camp")]
49    fn as_dyn_outer(&self) -> Option<(&dyn Structure, &'static str)> {
50        Some((Self::as_dyn_impl(self), "as_dyn_structure_camp"))
51    }
52
53    fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
54        let center = self.bounds.center();
55        let base = land.get_alt_approx(center) as i32;
56        let mut rng = rand::rng();
57        let model_pos = center.with_z(base);
58        let temp = self.temp;
59        let camp_type = if temp >= CONFIG.tropical_temp {
60            CampType::Pirate
61        } else if temp <= (CONFIG.snow_temp) {
62            CampType::Snow
63        } else {
64            CampType::Forest
65        };
66        // models
67        lazy_static! {
68            pub static ref MODEL_PIRATE: AssetHandle<StructuresGroup> =
69                PrefabStructure::load_group("site_structures.camp.camp_pirate");
70            pub static ref MODEL_SNOW: AssetHandle<StructuresGroup> =
71                PrefabStructure::load_group("site_structures.camp.camp_snow");
72            pub static ref MODEL_FOREST: AssetHandle<StructuresGroup> =
73                PrefabStructure::load_group("site_structures.camp.camp_forest");
74        }
75        let prefab_structure = match camp_type {
76            CampType::Pirate => MODEL_PIRATE.read(),
77            CampType::Snow => MODEL_SNOW.read(),
78            CampType::Forest => MODEL_FOREST.read(),
79        }[0]
80        .clone();
81
82        painter
83            .prim(Primitive::Prefab(Box::new(prefab_structure.clone())))
84            .translate(model_pos)
85            .fill(Fill::Prefab(Box::new(prefab_structure), model_pos, 0));
86
87        // npcs
88        let npc_rng = rng.random_range(1..=5);
89        match camp_type {
90            CampType::Pirate => {
91                for p in 0..npc_rng {
92                    painter.spawn(
93                        EntityInfo::at((center + p).with_z(base + 2).as_()).with_asset_expect(
94                            "common.entity.spot.pirate",
95                            &mut rng,
96                            None,
97                        ),
98                    )
99                }
100                let pet = if npc_rng < 3 {
101                    "common.entity.wild.peaceful.parrot"
102                } else {
103                    "common.entity.wild.peaceful.rat"
104                };
105                painter.spawn(
106                    EntityInfo::at(center.with_z(base + 2).as_())
107                        .with_asset_expect(pet, &mut rng, None),
108                )
109            },
110            _ => {
111                if npc_rng > 2 {
112                    painter.spawn(
113                        EntityInfo::at((center - 1).with_z(base + 2).as_()).with_asset_expect(
114                            "common.entity.village.bowman",
115                            &mut rng,
116                            None,
117                        ),
118                    );
119                }
120                if npc_rng < 4 {
121                    painter.spawn(
122                        EntityInfo::at((center + 1).with_z(base + 2).as_()).with_asset_expect(
123                            "common.entity.village.skinner",
124                            &mut rng,
125                            None,
126                        ),
127                    )
128                }
129            },
130        };
131    }
132}