1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use super::*;
use crate::{assets::AssetHandle, site2::gen::PrimitiveTransform, Land};
use common::{
    generation::EntityInfo,
    terrain::{Structure as PrefabStructure, StructuresGroup},
};
use lazy_static::lazy_static;

use rand::prelude::*;
use vek::*;

pub struct Camp {
    bounds: Aabr<i32>,
    pub(crate) alt: i32,
    temp: f32,
}

#[derive(Copy, Clone)]
enum CampType {
    Pirate,
    Snow,
    Forest,
}

impl Camp {
    pub fn generate(
        land: &Land,
        _rng: &mut impl Rng,
        site: &Site,
        tile_aabr: Aabr<i32>,
        site_temp: f32,
    ) -> Self {
        let bounds = Aabr {
            min: site.tile_wpos(tile_aabr.min),
            max: site.tile_wpos(tile_aabr.max),
        };
        let temp = site_temp;
        Self {
            bounds,
            alt: land.get_alt_approx(site.tile_center_wpos(tile_aabr.center())) as i32 + 2,
            temp,
        }
    }
}

impl Structure for Camp {
    #[cfg(feature = "use-dyn-lib")]
    const UPDATE_FN: &'static [u8] = b"render_camp\0";

    #[cfg_attr(feature = "be-dyn-lib", export_name = "render_camp")]
    fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
        let center = self.bounds.center();
        let base = land.get_alt_approx(center) as i32;
        let mut thread_rng = thread_rng();
        let model_pos = center.with_z(base);
        let temp = self.temp;
        let camp_type = if temp >= CONFIG.tropical_temp {
            CampType::Pirate
        } else if temp <= (CONFIG.snow_temp) {
            CampType::Snow
        } else {
            CampType::Forest
        };
        // models
        lazy_static! {
            pub static ref MODEL_PIRATE: AssetHandle<StructuresGroup> =
                PrefabStructure::load_group("site_structures.camp.camp_pirate");
            pub static ref MODEL_SNOW: AssetHandle<StructuresGroup> =
                PrefabStructure::load_group("site_structures.camp.camp_snow");
            pub static ref MODEL_FOREST: AssetHandle<StructuresGroup> =
                PrefabStructure::load_group("site_structures.camp.camp_forest");
        }
        let prefab_structure = match camp_type {
            CampType::Pirate => MODEL_PIRATE.read(),
            CampType::Snow => MODEL_SNOW.read(),
            CampType::Forest => MODEL_FOREST.read(),
        }[0]
        .clone();

        painter
            .prim(Primitive::Prefab(Box::new(prefab_structure.clone())))
            .translate(model_pos)
            .fill(Fill::Prefab(Box::new(prefab_structure), model_pos, 0));

        // npcs
        let npc_rng = thread_rng.gen_range(1..=5);
        match camp_type {
            CampType::Pirate => {
                for p in 0..npc_rng {
                    painter.spawn(
                        EntityInfo::at((center + p).with_z(base + 2).as_()).with_asset_expect(
                            "common.entity.spot.pirate",
                            &mut thread_rng,
                            None,
                        ),
                    )
                }
                let pet = if npc_rng < 3 {
                    "common.entity.wild.peaceful.parrot"
                } else {
                    "common.entity.wild.peaceful.rat"
                };
                painter.spawn(
                    EntityInfo::at(center.with_z(base + 2).as_()).with_asset_expect(
                        pet,
                        &mut thread_rng,
                        None,
                    ),
                )
            },
            _ => {
                if npc_rng > 2 {
                    painter.spawn(
                        EntityInfo::at((center - 1).with_z(base + 2).as_()).with_asset_expect(
                            "common.entity.village.bowman",
                            &mut thread_rng,
                            None,
                        ),
                    );
                }
                if npc_rng < 4 {
                    painter.spawn(
                        EntityInfo::at((center + 1).with_z(base + 2).as_()).with_asset_expect(
                            "common.entity.village.skinner",
                            &mut thread_rng,
                            None,
                        ),
                    )
                }
            },
        };
    }
}