1
0
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:
DjWarmonger
2014-10-30 13:03:53 +01:00
parent 530a3e69bf
commit ce83db0f43
6 changed files with 90 additions and 33 deletions

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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
};
}

View File

@@ -65,12 +65,19 @@ 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);
@@ -79,9 +86,9 @@ void CJsonRmgTemplateLoader::loadTemplates()
}
}
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());
if (i)
zone->setTownTypes(allowedTownTypes);
else
zone->setMonsterTypes(allowedTownTypes);
}
const std::string monsterStrength = zoneNode["monsters"].String();
if (monsterStrength == "weak")

View File

@@ -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 *

View File

@@ -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