mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
- Option to configure monster types spawning in a zone
- 25% chance to get neutral faction in zone with no town
This commit is contained in:
@@ -767,10 +767,19 @@ std::vector<bool> CTownHandler::getDefaultAllowed() const
|
||||
}
|
||||
return allowedFactions;
|
||||
}
|
||||
std::set<TFaction> CTownHandler::getAllowedFactions() const
|
||||
std::set<TFaction> CTownHandler::getAllowedFactions(bool withTown /*=true*/) const
|
||||
{
|
||||
std::set<TFaction> allowedFactions;
|
||||
auto allowed = getDefaultAllowed();
|
||||
std::vector<bool> allowed;
|
||||
if (withTown)
|
||||
allowed = getDefaultAllowed();
|
||||
else
|
||||
{
|
||||
for (auto town : factions)
|
||||
{
|
||||
allowed.push_back (true);
|
||||
}
|
||||
}
|
||||
for (size_t i=0; i<allowed.size(); i++)
|
||||
if (allowed[i])
|
||||
allowedFactions.insert(i);
|
||||
|
@@ -266,7 +266,7 @@ public:
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
std::vector<bool> getDefaultAllowed() const override;
|
||||
std::set<TFaction> getAllowedFactions() const;
|
||||
std::set<TFaction> getAllowedFactions(bool withTown = true) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@@ -299,7 +299,7 @@ namespace ETownType
|
||||
enum ETownType
|
||||
{
|
||||
ANY = -1,
|
||||
CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX
|
||||
CASTLE, RAMPART, TOWER, INFERNO, NECROPOLIS, DUNGEON, STRONGHOLD, FORTRESS, CONFLUX, NEUTRAL
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@ void CJsonRmgTemplateLoader::loadTemplates()
|
||||
|
||||
// Parse zones
|
||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone *> zones;
|
||||
for(const auto & zonePair : templateNode["zones"].Struct())
|
||||
for (const auto & zonePair : templateNode["zones"].Struct())
|
||||
{
|
||||
auto zone = new CRmgTemplateZone();
|
||||
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
|
||||
@@ -56,7 +56,7 @@ void CJsonRmgTemplateLoader::loadTemplates()
|
||||
const auto & zoneNode = zonePair.second;
|
||||
zone->setType(parseZoneType(zoneNode["type"].String()));
|
||||
zone->setSize(zoneNode["size"].Float());
|
||||
if(!zoneNode["owner"].isNull()) zone->setOwner(zoneNode["owner"].Float());
|
||||
if (!zoneNode["owner"].isNull()) zone->setOwner(zoneNode["owner"].Float());
|
||||
|
||||
zone->setPlayerTowns(parseTemplateZoneTowns(zoneNode["playerTowns"]));
|
||||
zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
|
||||
@@ -65,23 +65,30 @@ void CJsonRmgTemplateLoader::loadTemplates()
|
||||
zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), zone->getDefaultTerrainTypes()));
|
||||
zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
std::set<TFaction> allowedTownTypes;
|
||||
if (zoneNode["allowedTowns"].isNull())
|
||||
if (zoneNode[i ? "allowedTowns" : "allowedMonsters"].isNull())
|
||||
{
|
||||
if (i)
|
||||
allowedTownTypes = zone->getDefaultTownTypes();
|
||||
else
|
||||
allowedTownTypes = VLC->townh->getAllowedFactions(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const JsonNode & allowedTown : zoneNode["allowedTowns"].Vector())
|
||||
for (const JsonNode & allowedTown : zoneNode[i ? "allowedTowns" : "allowedMonsters"].Vector())
|
||||
{
|
||||
//complain if the town type is not present in our game
|
||||
boost::optional<si32> id = VLC->modh->identifiers.getIdentifier("faction", allowedTown, false);
|
||||
if (id.is_initialized())
|
||||
allowedTownTypes.insert (id.get());
|
||||
allowedTownTypes.insert(id.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (!zoneNode["bannedTowns"].isNull())
|
||||
if (!zoneNode[i ? "bannedTowns" : "bannedMonsters"].isNull())
|
||||
{
|
||||
for (const JsonNode & bannedTown : zoneNode["bannedTowns"].Vector())
|
||||
for (const JsonNode & bannedTown : zoneNode[i ? "bannedTowns" : "bannedMonsters"].Vector())
|
||||
{
|
||||
//erase unindentified towns silently
|
||||
boost::optional<si32> id = VLC->modh->identifiers.getIdentifier("faction", bannedTown, true);
|
||||
@@ -89,8 +96,11 @@ void CJsonRmgTemplateLoader::loadTemplates()
|
||||
vstd::erase_if_present(allowedTownTypes, id.get());
|
||||
}
|
||||
}
|
||||
assert(allowedTownTypes.size());
|
||||
zone->setTownTypes (allowedTownTypes);
|
||||
if (i)
|
||||
zone->setTownTypes(allowedTownTypes);
|
||||
else
|
||||
zone->setMonsterTypes(allowedTownTypes);
|
||||
}
|
||||
|
||||
const std::string monsterStrength = zoneNode["monsters"].String();
|
||||
if (monsterStrength == "weak")
|
||||
|
@@ -136,7 +136,7 @@ CRmgTemplateZone::CRmgTemplateZone() :
|
||||
size(1),
|
||||
townsAreSameType(false),
|
||||
matchTerrainToTown(true),
|
||||
townType(0),
|
||||
townType(ETownType::NEUTRAL),
|
||||
terrainType (ETerrainType::GRASS),
|
||||
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
|
||||
totalDensity(0)
|
||||
@@ -228,6 +228,10 @@ void CRmgTemplateZone::setTownTypes(const std::set<TFaction> & value)
|
||||
{
|
||||
townTypes = value;
|
||||
}
|
||||
void CRmgTemplateZone::setMonsterTypes(const std::set<TFaction> & value)
|
||||
{
|
||||
monsterTypes = value;
|
||||
}
|
||||
|
||||
std::set<TFaction> CRmgTemplateZone::getDefaultTownTypes() const
|
||||
{
|
||||
@@ -635,6 +639,8 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength,
|
||||
{
|
||||
if (cre->special)
|
||||
continue;
|
||||
if (!vstd::contains(monsterTypes, cre->faction))
|
||||
continue;
|
||||
if ((cre->AIValue * (cre->ammMin + cre->ammMax) / 2 < strength) && (strength < cre->AIValue * 100)) //at least one full monster. size between minimum size of given stack and 100
|
||||
{
|
||||
possibleCreatures.push_back(cre->idNumber);
|
||||
@@ -950,7 +956,12 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
|
||||
if (this->townsAreSameType)
|
||||
town->subID = townType;
|
||||
else
|
||||
{
|
||||
if (townTypes.size())
|
||||
town->subID = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
|
||||
else
|
||||
town->subID = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed
|
||||
}
|
||||
|
||||
town->tempOwner = player;
|
||||
if (hasFort)
|
||||
@@ -992,7 +1003,12 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
|
||||
townType = gen->mapGenOptions->getPlayersSettings().find(player)->second.getStartingTown();
|
||||
|
||||
if (townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
|
||||
{
|
||||
if (townTypes.size())
|
||||
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
|
||||
else
|
||||
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed
|
||||
}
|
||||
|
||||
auto town = new CGTownInstance();
|
||||
town->ID = Obj::TOWN;
|
||||
@@ -1044,12 +1060,29 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
|
||||
|
||||
addNewTowns (neutralTowns.getCastleCount(), true, PlayerColor::NEUTRAL);
|
||||
addNewTowns (neutralTowns.getTownCount(), false, PlayerColor::NEUTRAL);
|
||||
|
||||
if (!totalTowns) //if there's no town present, get random faction for dwellings and pandoras
|
||||
{
|
||||
//25% chance for neutral
|
||||
if (gen->rand.nextInt(1, 100) <= 25)
|
||||
{
|
||||
townType = ETownType::NEUTRAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (townTypes.size())
|
||||
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
|
||||
else if (monsterTypes.size())
|
||||
townType = *RandomGeneratorUtil::nextItem(monsterTypes, gen->rand); //this happens in Clash of Dragons in treasure zones, where all towns are banned
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::initTerrainType (CMapGenerator* gen)
|
||||
{
|
||||
|
||||
if (matchTerrainToTown)
|
||||
if (matchTerrainToTown && townType != ETownType::NEUTRAL)
|
||||
terrainType = VLC->townh->factions[townType]->nativeTerrain;
|
||||
else
|
||||
terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand);
|
||||
@@ -1945,12 +1978,15 @@ void CRmgTemplateZone::addAllPossibleObjects (CMapGenerator* gen)
|
||||
|
||||
for (auto creature : VLC->creh->creatures)
|
||||
{
|
||||
if (!creature->special && VLC->townh->factions[creature->faction]->nativeTerrain == terrainType)
|
||||
if (!creature->special && creature->faction == townType)
|
||||
{
|
||||
int actualTier = creature->level > 7 ? 6 : creature->level-1;
|
||||
int creaturesAmount = tierValues[actualTier] / creature->AIValue;
|
||||
float creaturesAmount = tierValues[actualTier] / creature->AIValue;
|
||||
if (creaturesAmount <= 5)
|
||||
{
|
||||
creaturesAmount = boost::math::round(creaturesAmount); //allow single monsters
|
||||
if (creaturesAmount < 1)
|
||||
continue;
|
||||
}
|
||||
else if (creaturesAmount <= 12)
|
||||
{
|
||||
@@ -1958,11 +1994,11 @@ void CRmgTemplateZone::addAllPossibleObjects (CMapGenerator* gen)
|
||||
}
|
||||
else if (creaturesAmount <= 50)
|
||||
{
|
||||
creaturesAmount = boost::math::round((float)creaturesAmount / 5) * 5;
|
||||
creaturesAmount = boost::math::round(creaturesAmount / 5) * 5;
|
||||
}
|
||||
else if (creaturesAmount <= 12)
|
||||
{
|
||||
creaturesAmount = boost::math::round((float)creaturesAmount / 10) * 10;
|
||||
creaturesAmount = boost::math::round(creaturesAmount / 10) * 10;
|
||||
}
|
||||
|
||||
oi.generateObject = [creature, creaturesAmount]() -> CGObjectInstance *
|
||||
|
@@ -129,6 +129,7 @@ public:
|
||||
void setTownsAreSameType(bool value);
|
||||
const std::set<TFaction> & getTownTypes() const; /// Default: all
|
||||
void setTownTypes(const std::set<TFaction> & value);
|
||||
void setMonsterTypes(const std::set<TFaction> & value);
|
||||
std::set<TFaction> getDefaultTownTypes() const;
|
||||
bool getMatchTerrainToTown() const; /// Default: true
|
||||
void setMatchTerrainToTown(bool value);
|
||||
@@ -186,6 +187,7 @@ private:
|
||||
CTownInfo playerTowns, neutralTowns;
|
||||
bool townsAreSameType;
|
||||
std::set<TFaction> townTypes;
|
||||
std::set<TFaction> monsterTypes;
|
||||
bool matchTerrainToTown;
|
||||
std::set<ETerrainType> terrainTypes;
|
||||
std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone
|
||||
|
Reference in New Issue
Block a user