1 #include "UndergroundSectorModel.h"
2
3 #include "JsonUtility.h"
4 #include "Random.h"
5
UndergroundSectorModel(uint8_t sectorId_,uint8_t sectorZ_,uint8_t adjacentSectors_,std::array<uint8_t,NUM_DIF_LEVELS> numTroops_,std::array<uint8_t,NUM_DIF_LEVELS> numElites_,std::array<uint8_t,NUM_DIF_LEVELS> numCreatures_,std::array<uint8_t,NUM_DIF_LEVELS> numTroopsVariance_,std::array<uint8_t,NUM_DIF_LEVELS> numElitesVariance_,std::array<uint8_t,NUM_DIF_LEVELS> numCreaturesVariance_)6 UndergroundSectorModel::UndergroundSectorModel(uint8_t sectorId_, uint8_t sectorZ_, uint8_t adjacentSectors_,
7 std::array<uint8_t, NUM_DIF_LEVELS> numTroops_, std::array<uint8_t, NUM_DIF_LEVELS> numElites_, std::array<uint8_t, NUM_DIF_LEVELS> numCreatures_,
8 std::array<uint8_t, NUM_DIF_LEVELS> numTroopsVariance_, std::array<uint8_t, NUM_DIF_LEVELS> numElitesVariance_, std::array<uint8_t, NUM_DIF_LEVELS> numCreaturesVariance_)
9 : sectorId(sectorId_), sectorZ(sectorZ_), adjacentSectors(adjacentSectors_),
10 numTroops(numTroops_), numElites(numElites_), numCreatures(numCreatures_),
11 numTroopsVariance(numTroopsVariance_), numElitesVariance(numElitesVariance_), numCreaturesVariance(numCreaturesVariance_) {}
12
createUndergroundSectorInfo(uint8_t difficultyLevel) const13 UNDERGROUND_SECTORINFO* UndergroundSectorModel::createUndergroundSectorInfo(uint8_t difficultyLevel) const
14 {
15 UNDERGROUND_SECTORINFO* const u = new UNDERGROUND_SECTORINFO{};
16
17 u->ubSectorX = SECTORX(sectorId);
18 u->ubSectorY = SECTORY(sectorId);
19 u->ubSectorZ = sectorZ;
20 u->ubAdjacentSectors = adjacentSectors;
21
22 u->ubNumTroops = numTroops[difficultyLevel - 1] + Random(numTroopsVariance[difficultyLevel - 1] );
23 u->ubNumElites = numElites[difficultyLevel - 1] + Random(numElitesVariance[difficultyLevel - 1] );
24 u->ubNumCreatures = numCreatures[difficultyLevel - 1] + Random(numCreaturesVariance[difficultyLevel - 1]);
25
26 return u;
27 }
28
deserialize(const rapidjson::Value & obj)29 UndergroundSectorModel* UndergroundSectorModel::deserialize(const rapidjson::Value& obj)
30 {
31 uint8_t sectorId = JsonUtility::parseSectorID(obj["sector"].GetString());
32 uint8_t sectorZ = obj["sectorLevel"].GetUint();
33 if (sectorZ == 0 || sectorZ > 3)
34 {
35 ST::string err = "Sector level must be between 1 and 3";
36 throw std::runtime_error(err.to_std_string());
37 }
38
39 uint8_t adjacencyFlag = NO_ADJACENT_SECTOR;
40 if (obj.HasMember("adjacentSectors") && obj["adjacentSectors"].IsArray())
41 {
42 auto adjacencies = obj["adjacentSectors"].GetArray();
43 for (auto& el : adjacencies)
44 {
45 ST::string adj = el.GetString();
46 if (adj.size() != 1)
47 {
48 ST::string err = ST::format("'{}' is not a valid adjacency direction.", adj);
49 throw std::runtime_error(err.to_std_string());
50 }
51 switch (adj[0])
52 {
53 case DIRECTION_NORTH:
54 adjacencyFlag |= NORTH_ADJACENT_SECTOR;
55 break;
56 case DIRECTION_EAST:
57 adjacencyFlag |= EAST_ADJACENT_SECTOR;
58 break;
59 case DIRECTION_SOUTH:
60 adjacencyFlag |= SOUTH_ADJACENT_SECTOR;
61 break;
62 case DIRECTION_WEST:
63 adjacencyFlag |= WEST_ADJACENT_SECTOR;
64 break;
65 default:
66 ST::string err = ST::format("{} is not a valid direction.", adj[0]);
67 throw std::runtime_error(err.to_std_string());
68 }
69 }
70 }
71
72 return new UndergroundSectorModel(
73 sectorId, sectorZ, adjacencyFlag,
74 JsonUtility::readIntArrayByDiff(obj, "numTroops"),
75 JsonUtility::readIntArrayByDiff(obj, "numElites"),
76 JsonUtility::readIntArrayByDiff(obj, "numCreatures"),
77 JsonUtility::readIntArrayByDiff(obj, "numTroopsVariance"),
78 JsonUtility::readIntArrayByDiff(obj, "numElitesVariance"),
79 JsonUtility::readIntArrayByDiff(obj, "numCreaturesVariance")
80 );
81 }
82
validateData(const std::vector<const UndergroundSectorModel * > & ugSectors)83 void UndergroundSectorModel::validateData(const std::vector<const UndergroundSectorModel*>& ugSectors)
84 {
85 // check for existence of hard-coded references
86 // the list below is based on the occurrences of FindUnderGroundSector in codebase
87 std::array<uint8_t, 3> basementSectors[] = {
88 { 13, 5, 1 }, // Draassen mine
89 { 9, 8, 1 }, // Cambria mine
90 { 14, 10, 1 }, // Alma mine
91 { 4, 8, 2 } // Grumm mine
92 };
93 for (auto basementLoc : basementSectors)
94 {
95 uint8_t sectorId = SECTOR(basementLoc[0], basementLoc[1]);
96 uint8_t sectorZ = basementLoc[2];
97 auto iter = std::find_if(ugSectors.begin(), ugSectors.end(), [sectorId, sectorZ](const UndergroundSectorModel* s) { return (s->sectorId == sectorId && s->sectorZ == sectorZ); });
98 if (iter == ugSectors.end())
99 {
100 ST::string err = ST::format("An underground sector is expected at ({},{},{}), but is not defined.", basementLoc[0], basementLoc[1], basementLoc[2]);
101 throw std::runtime_error(err.to_std_string());
102 }
103 }
104 }