veloren_world/site2/plot/
camp.rs

1use super::*;
2use crate::{Land, assets::AssetHandle, site2::gen::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 = "use-dyn-lib")]
48    const UPDATE_FN: &'static [u8] = b"render_camp\0";
49
50    #[cfg_attr(feature = "be-dyn-lib", export_name = "render_camp")]
51    fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
52        let center = self.bounds.center();
53        let base = land.get_alt_approx(center) as i32;
54        let mut thread_rng = thread_rng();
55        let model_pos = center.with_z(base);
56        let temp = self.temp;
57        let camp_type = if temp >= CONFIG.tropical_temp {
58            CampType::Pirate
59        } else if temp <= (CONFIG.snow_temp) {
60            CampType::Snow
61        } else {
62            CampType::Forest
63        };
64        // models
65        lazy_static! {
66            pub static ref MODEL_PIRATE: AssetHandle<StructuresGroup> =
67                PrefabStructure::load_group("site_structures.camp.camp_pirate");
68            pub static ref MODEL_SNOW: AssetHandle<StructuresGroup> =
69                PrefabStructure::load_group("site_structures.camp.camp_snow");
70            pub static ref MODEL_FOREST: AssetHandle<StructuresGroup> =
71                PrefabStructure::load_group("site_structures.camp.camp_forest");
72        }
73        let prefab_structure = match camp_type {
74            CampType::Pirate => MODEL_PIRATE.read(),
75            CampType::Snow => MODEL_SNOW.read(),
76            CampType::Forest => MODEL_FOREST.read(),
77        }[0]
78        .clone();
79
80        painter
81            .prim(Primitive::Prefab(Box::new(prefab_structure.clone())))
82            .translate(model_pos)
83            .fill(Fill::Prefab(Box::new(prefab_structure), model_pos, 0));
84
85        // npcs
86        let npc_rng = thread_rng.gen_range(1..=5);
87        match camp_type {
88            CampType::Pirate => {
89                for p in 0..npc_rng {
90                    painter.spawn(
91                        EntityInfo::at((center + p).with_z(base + 2).as_()).with_asset_expect(
92                            "common.entity.spot.pirate",
93                            &mut thread_rng,
94                            None,
95                        ),
96                    )
97                }
98                let pet = if npc_rng < 3 {
99                    "common.entity.wild.peaceful.parrot"
100                } else {
101                    "common.entity.wild.peaceful.rat"
102                };
103                painter.spawn(
104                    EntityInfo::at(center.with_z(base + 2).as_()).with_asset_expect(
105                        pet,
106                        &mut thread_rng,
107                        None,
108                    ),
109                )
110            },
111            _ => {
112                if npc_rng > 2 {
113                    painter.spawn(
114                        EntityInfo::at((center - 1).with_z(base + 2).as_()).with_asset_expect(
115                            "common.entity.village.bowman",
116                            &mut thread_rng,
117                            None,
118                        ),
119                    );
120                }
121                if npc_rng < 4 {
122                    painter.spawn(
123                        EntityInfo::at((center + 1).with_z(base + 2).as_()).with_asset_expect(
124                            "common.entity.village.skinner",
125                            &mut thread_rng,
126                            None,
127                        ),
128                    )
129                }
130            },
131        };
132    }
133}