-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathenemy_factory.cpp
110 lines (104 loc) · 4.27 KB
/
enemy_factory.cpp
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
#include "stdafx.h"
#include "enemy_factory.h"
#include "name_generator.h"
#include "technology.h"
#include "attack_trigger.h"
#include "external_enemies.h"
#include "immigrant_info.h"
#include "settlement_info.h"
#include "enemy_info.h"
#include "tribe_alignment.h"
#include "sunlight_info.h"
#include "conquer_condition.h"
#include "lasting_effect.h"
#include "creature_group.h"
#include "name_generator.h"
#include "enemy_id.h"
#include "collective_builder.h"
#include "model.h"
#include "collective.h"
#include "village_control.h"
#include "game.h"
#include "immigration.h"
EnemyFactory::EnemyFactory(RandomGen& r, NameGenerator* n, map<EnemyId, EnemyInfo> enemies, map<BuildingId, BuildingInfo> buildingInfo,
vector<ExternalEnemy> externalEnemies)
: random(r), nameGenerator(n), enemies(std::move(enemies)), buildingInfo(std::move(buildingInfo)),
externalEnemies(std::move(externalEnemies)) {
}
PCollective EnemyInfo::buildCollective(ContentFactory* contentFactory) const {
if (settlement.locationName)
settlement.collective->setLocationName(*settlement.locationName);
if (auto race = settlement.race)
settlement.collective->setRaceName(*race);
if (discoverable)
settlement.collective->setDiscoverable();
PCollective collective = settlement.collective->build(contentFactory);
collective->setImmigration(makeOwner<Immigration>(collective.get(), immigrants));
auto control = VillageControl::create(collective.get(), behaviour);
if (villainType)
collective->setVillainType(*villainType);
if (id)
collective->setEnemyId(*id);
collective->setControl(std::move(control));
return collective;
}
vector<EnemyId> EnemyFactory::getAllIds() const {
return getKeys(enemies);
}
EnemyInfo EnemyFactory::get(EnemyId id) const {
CHECK(enemies.count(id)) << "Enemy not found: \"" << id.data() << "\"";
auto ret = enemies.at(id);
ret.setId(id);
if (ret.levelConnection) {
for (auto& level : ret.levelConnection->levels)
if (auto extra = level.enemy.getReferenceMaybe<LevelConnection::ExtraEnemy>())
extra->enemyInfo = vector<EnemyInfo>(random.get(extra->numLevels), get(extra->enemy));
if (auto extra = ret.levelConnection->topLevel.getReferenceMaybe<LevelConnection::ExtraEnemy>())
extra->enemyInfo = vector<EnemyInfo>(random.get(extra->numLevels), get(extra->enemy));
}
updateCreateOnBones(ret);
ret.updateBuildingInfo(buildingInfo);
if (ret.settlement.locationNameGen)
ret.settlement.locationName = nameGenerator->getNext(*ret.settlement.locationNameGen);
return ret;
}
void EnemyFactory::updateCreateOnBones(EnemyInfo& info) const {
if (info.createOnBones && random.chance(info.createOnBones->probability)) {
EnemyInfo enemy = get(random.choose(info.createOnBones->enemies));
info.levelConnection = enemy.levelConnection;
info.biome = enemy.biome;
bool makeRuins = Random.roll(2);
if (makeRuins) {
if (auto builtin = info.settlement.type.getReferenceMaybe<MapLayoutTypes::Builtin>())
builtin->buildingId = BuildingId("RUINS");
} else {
info.settlement.furniture = enemy.settlement.furniture;
info.settlement.outsideFeatures = enemy.settlement.outsideFeatures;
info.settlement.shopItems = enemy.settlement.shopItems;
}
if (info.levelConnection) {
auto processLevel = [&](LevelConnection::EnemyLevelInfo& enemy) {
if (auto extra = enemy.getReferenceMaybe<LevelConnection::ExtraEnemy>())
for (auto& enemy : extra->enemyInfo) {
if (makeRuins) {
if (auto builtin = enemy.settlement.type.getReferenceMaybe<MapLayoutTypes::Builtin>())
builtin->buildingId = BuildingId("RUINS");
enemy.settlement.furniture.reset();
enemy.settlement.outsideFeatures.reset();
}
enemy.settlement.corpses = enemy.settlement.inhabitants;
enemy.settlement.inhabitants = InhabitantsInfo();
}
};
for (auto& level : info.levelConnection->levels)
processLevel(level.enemy);
processLevel(info.levelConnection->topLevel);
}
info.settlement.type = enemy.settlement.type;
info.settlement.corpses = enemy.settlement.inhabitants;
info.settlement.shopkeeperDead = true;
}
}
vector<ExternalEnemy> EnemyFactory::getExternalEnemies() const {
return externalEnemies;
}