mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Place proper towns in underground (#743)
Implement feature of proper town selection in underground and surface * Some minor refactoring of rmg
This commit is contained in:
parent
d92356f085
commit
9d06e51631
@ -4,6 +4,7 @@
|
|||||||
"index" : 5,
|
"index" : 5,
|
||||||
"nativeTerrain": "subterra",
|
"nativeTerrain": "subterra",
|
||||||
"alignment" : "evil",
|
"alignment" : "evil",
|
||||||
|
"preferUndergroundPlacement": true,
|
||||||
"creatureBackground" :
|
"creatureBackground" :
|
||||||
{
|
{
|
||||||
"120px" : "TPCASDUN",
|
"120px" : "TPCASDUN",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"index" : 3,
|
"index" : 3,
|
||||||
"nativeTerrain": "lava",
|
"nativeTerrain": "lava",
|
||||||
"alignment" : "evil",
|
"alignment" : "evil",
|
||||||
|
"preferUndergroundPlacement": true,
|
||||||
"creatureBackground" :
|
"creatureBackground" :
|
||||||
{
|
{
|
||||||
"120px" : "TPCASINF",
|
"120px" : "TPCASINF",
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"index" : 4,
|
"index" : 4,
|
||||||
"nativeTerrain": "dirt",
|
"nativeTerrain": "dirt",
|
||||||
"alignment" : "evil",
|
"alignment" : "evil",
|
||||||
|
"preferUndergroundPlacement": true,
|
||||||
"creatureBackground" :
|
"creatureBackground" :
|
||||||
{
|
{
|
||||||
"120px" : "TPCASNEC",
|
"120px" : "TPCASNEC",
|
||||||
|
@ -73,6 +73,10 @@
|
|||||||
"type":"string",
|
"type":"string",
|
||||||
"description": "Native terrain for creatures. Creatures fighting on native terrain receive several bonuses"
|
"description": "Native terrain for creatures. Creatures fighting on native terrain receive several bonuses"
|
||||||
},
|
},
|
||||||
|
"preferUndergroundPlacement": {
|
||||||
|
"type":"bool",
|
||||||
|
"description": "Random map generator places player/cpu-owned towns underground if true is specified and on the ground otherwise. Parameter is unused for maps without underground. False by default."
|
||||||
|
},
|
||||||
"puzzleMap": {
|
"puzzleMap": {
|
||||||
"type":"object",
|
"type":"object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
|
@ -853,9 +853,9 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan
|
|||||||
CStopWatch sw;
|
CStopWatch sw;
|
||||||
|
|
||||||
// Gen map
|
// Gen map
|
||||||
CMapGenerator mapGenerator;
|
CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, scenarioOps->seedToBeUsed);
|
||||||
|
|
||||||
std::unique_ptr<CMap> randomMap = mapGenerator.generate(scenarioOps->mapGenOptions.get(), scenarioOps->seedToBeUsed);
|
std::unique_ptr<CMap> randomMap = mapGenerator.generate();
|
||||||
|
|
||||||
if(allowSavingRandomMap)
|
if(allowSavingRandomMap)
|
||||||
{
|
{
|
||||||
|
@ -211,6 +211,7 @@ CFaction::CFaction()
|
|||||||
town = nullptr;
|
town = nullptr;
|
||||||
index = 0;
|
index = 0;
|
||||||
alignment = EAlignment::NEUTRAL;
|
alignment = EAlignment::NEUTRAL;
|
||||||
|
preferUndergroundPlacement = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFaction::~CFaction()
|
CFaction::~CFaction()
|
||||||
@ -1099,6 +1100,9 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode
|
|||||||
int terrainNum = nativeTerrain.isNull()
|
int terrainNum = nativeTerrain.isNull()
|
||||||
? -1
|
? -1
|
||||||
: vstd::find_pos(GameConstants::TERRAIN_NAMES, nativeTerrain.String());
|
: vstd::find_pos(GameConstants::TERRAIN_NAMES, nativeTerrain.String());
|
||||||
|
|
||||||
|
auto preferUndergound = source["preferUndergroundPlacement"];
|
||||||
|
faction->preferUndergroundPlacement = preferUndergound.isNull() ? false : preferUndergound.Bool();
|
||||||
|
|
||||||
//Contructor is not called here, but operator=
|
//Contructor is not called here, but operator=
|
||||||
faction->nativeTerrain = terrainNum < 0
|
faction->nativeTerrain = terrainNum < 0
|
||||||
|
@ -207,6 +207,7 @@ public:
|
|||||||
|
|
||||||
ETerrainType nativeTerrain;
|
ETerrainType nativeTerrain;
|
||||||
EAlignment::EAlignment alignment;
|
EAlignment::EAlignment alignment;
|
||||||
|
bool preferUndergroundPlacement;
|
||||||
|
|
||||||
CTown * town; //NOTE: can be null
|
CTown * town; //NOTE: can be null
|
||||||
|
|
||||||
@ -399,8 +400,8 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
|
|||||||
void loadBuilding(CTown * town, const std::string & stringID, const JsonNode & source);
|
void loadBuilding(CTown * town, const std::string & stringID, const JsonNode & source);
|
||||||
void loadBuildings(CTown * town, const JsonNode & source);
|
void loadBuildings(CTown * town, const JsonNode & source);
|
||||||
|
|
||||||
std::shared_ptr<Bonus> createBonus(CBuilding * build, Bonus::BonusType type, int val, int subtype = -1);
|
std::shared_ptr<Bonus> createBonus(CBuilding * build, Bonus::BonusType type, int val, int subtype = -1);
|
||||||
std::shared_ptr<Bonus> createBonus(CBuilding * build, Bonus::BonusType type, int val, TPropagatorPtr & prop, int subtype = -1);
|
std::shared_ptr<Bonus> createBonus(CBuilding * build, Bonus::BonusType type, int val, TPropagatorPtr & prop, int subtype = -1);
|
||||||
std::shared_ptr<Bonus> createBonusImpl(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr & prop, const std::string & description, int subtype = -1);
|
std::shared_ptr<Bonus> createBonusImpl(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr & prop, const std::string & description, int subtype = -1);
|
||||||
|
|
||||||
/// loads CStructure's into town
|
/// loads CStructure's into town
|
||||||
|
@ -205,11 +205,6 @@ void CMapGenOptions::setMapTemplate(const CRmgTemplate * value)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTemplates() const
|
|
||||||
{
|
|
||||||
return VLC->tplh->getTemplates();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMapGenOptions::finalize(CRandomGenerator & rand)
|
void CMapGenOptions::finalize(CRandomGenerator & rand)
|
||||||
{
|
{
|
||||||
logGlobal->info("RMG settings: players %d, teams %d, computer players %d, computer teams %d, water %d, monsters %d",
|
logGlobal->info("RMG settings: players %d, teams %d, computer players %d, computer teams %d, water %d, monsters %d",
|
||||||
@ -394,59 +389,15 @@ bool CMapGenOptions::checkOptions() const
|
|||||||
|
|
||||||
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
|
const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const
|
||||||
{
|
{
|
||||||
// Find potential templates
|
int3 tplSize(width, height, (hasTwoLevels ? 2 : 1));
|
||||||
const auto & tpls = getAvailableTemplates();
|
|
||||||
std::list<const CRmgTemplate *> potentialTpls;
|
auto templates = VLC->tplh->getTemplates(tplSize, getPlayerCount(), countHumanPlayers(), compOnlyPlayerCount);
|
||||||
for(const auto & tplPair : tpls)
|
|
||||||
{
|
|
||||||
const auto & tpl = tplPair.second;
|
|
||||||
int3 tplSize(width, height, (hasTwoLevels ? 2 : 1));
|
|
||||||
if(tpl->matchesSize(tplSize))
|
|
||||||
{
|
|
||||||
bool isPlayerCountValid = false;
|
|
||||||
if (getPlayerCount() != RANDOM_SIZE)
|
|
||||||
{
|
|
||||||
if (tpl->getPlayers().isInRange(getPlayerCount()))
|
|
||||||
isPlayerCountValid = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Human players shouldn't be banned when playing with random player count
|
|
||||||
auto playerNumbers = tpl->getPlayers().getNumbers();
|
|
||||||
if(countHumanPlayers() <= *boost::min_element(playerNumbers))
|
|
||||||
{
|
|
||||||
isPlayerCountValid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPlayerCountValid)
|
|
||||||
{
|
|
||||||
bool isCpuPlayerCountValid = false;
|
|
||||||
if(compOnlyPlayerCount != RANDOM_SIZE)
|
|
||||||
{
|
|
||||||
if (tpl->getCpuPlayers().isInRange(compOnlyPlayerCount))
|
|
||||||
isCpuPlayerCountValid = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isCpuPlayerCountValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isCpuPlayerCountValid)
|
|
||||||
potentialTpls.push_back(tpl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select tpl
|
// Select tpl
|
||||||
if(potentialTpls.empty())
|
if(templates.empty())
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
|
||||||
else
|
return *RandomGeneratorUtil::nextItem(templates, rand);
|
||||||
{
|
|
||||||
return *RandomGeneratorUtil::nextItem(potentialTpls, rand);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CMapGenOptions::CPlayerSettings::CPlayerSettings() : color(0), startingTown(RANDOM_TOWN), playerType(EPlayerType::AI)
|
CMapGenOptions::CPlayerSettings::CPlayerSettings() : color(0), startingTown(RANDOM_TOWN), playerType(EPlayerType::AI)
|
||||||
|
@ -94,6 +94,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CMapGenOptions();
|
CMapGenOptions();
|
||||||
|
CMapGenOptions(const CMapGenOptions&) = delete;
|
||||||
|
|
||||||
si32 getWidth() const;
|
si32 getWidth() const;
|
||||||
void setWidth(si32 value);
|
void setWidth(si32 value);
|
||||||
@ -141,8 +142,6 @@ public:
|
|||||||
const CRmgTemplate * getMapTemplate() const;
|
const CRmgTemplate * getMapTemplate() const;
|
||||||
void setMapTemplate(const CRmgTemplate * value);
|
void setMapTemplate(const CRmgTemplate * value);
|
||||||
|
|
||||||
const std::map<std::string, CRmgTemplate *> & getAvailableTemplates() const;
|
|
||||||
|
|
||||||
/// Finalizes the options. All random sizes for various properties will be overwritten by numbers from
|
/// Finalizes the options. All random sizes for various properties will be overwritten by numbers from
|
||||||
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
|
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
|
||||||
/// this function fails.
|
/// this function fails.
|
||||||
|
@ -46,7 +46,7 @@ void CMapGenerator::foreachDirectNeighbour(const int3& pos, std::function<void(i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapGenerator::foreachDiagonaltNeighbour(const int3& pos, std::function<void(int3& pos)> foo)
|
void CMapGenerator::foreachDiagonalNeighbour(const int3& pos, std::function<void(int3& pos)> foo)
|
||||||
{
|
{
|
||||||
for (const int3 &dir : dirsDiagonal)
|
for (const int3 &dir : dirsDiagonal)
|
||||||
{
|
{
|
||||||
@ -57,11 +57,13 @@ void CMapGenerator::foreachDiagonaltNeighbour(const int3& pos, std::function<voi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CMapGenerator::CMapGenerator() :
|
CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
|
||||||
mapGenOptions(nullptr), randomSeed(0), editManager(nullptr),
|
mapGenOptions(mapGenOptions), randomSeed(RandomSeed),
|
||||||
zonesTotal(0), tiles(nullptr), prisonsRemaining(0),
|
zonesTotal(0), tiles(nullptr), prisonsRemaining(0),
|
||||||
monolithIndex(0)
|
monolithIndex(0)
|
||||||
{
|
{
|
||||||
|
rand.setSeed(this->randomSeed);
|
||||||
|
mapGenOptions.finalize(rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapGenerator::initTiles()
|
void CMapGenerator::initTiles()
|
||||||
@ -89,8 +91,8 @@ CMapGenerator::~CMapGenerator()
|
|||||||
{
|
{
|
||||||
if (tiles)
|
if (tiles)
|
||||||
{
|
{
|
||||||
int width = mapGenOptions->getWidth();
|
int width = mapGenOptions.getWidth();
|
||||||
int height = mapGenOptions->getHeight();
|
int height = mapGenOptions.getHeight();
|
||||||
for (int i=0; i < width; i++)
|
for (int i=0; i < width; i++)
|
||||||
{
|
{
|
||||||
for(int j=0; j < height; j++)
|
for(int j=0; j < height; j++)
|
||||||
@ -111,7 +113,7 @@ void CMapGenerator::initPrisonsRemaining()
|
|||||||
if (isAllowed)
|
if (isAllowed)
|
||||||
prisonsRemaining++;
|
prisonsRemaining++;
|
||||||
}
|
}
|
||||||
prisonsRemaining = std::max<int> (0, prisonsRemaining - 16 * mapGenOptions->getPlayerCount()); //so at least 16 heroes will be available for every player
|
prisonsRemaining = std::max<int> (0, prisonsRemaining - 16 * mapGenOptions.getPlayerCount()); //so at least 16 heroes will be available for every player
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapGenerator::initQuestArtsRemaining()
|
void CMapGenerator::initQuestArtsRemaining()
|
||||||
@ -123,26 +125,27 @@ void CMapGenerator::initQuestArtsRemaining()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CMap> CMapGenerator::generate(CMapGenOptions * mapGenOptions, int randomSeed)
|
const CMapGenOptions& CMapGenerator::getMapGenOptions() const
|
||||||
{
|
{
|
||||||
this->mapGenOptions = mapGenOptions;
|
return mapGenOptions;
|
||||||
this->randomSeed = randomSeed;
|
}
|
||||||
|
|
||||||
assert(mapGenOptions);
|
CMapEditManager* CMapGenerator::getEditManager() const
|
||||||
|
{
|
||||||
rand.setSeed(this->randomSeed);
|
if(!map)
|
||||||
mapGenOptions->finalize(rand);
|
return nullptr;
|
||||||
|
return map->getEditManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CMap> CMapGenerator::generate()
|
||||||
|
{
|
||||||
map = make_unique<CMap>();
|
map = make_unique<CMap>();
|
||||||
editManager = map->getEditManager();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
editManager->getUndoManager().setUndoRedoLimit(0);
|
map->getEditManager()->getUndoManager().setUndoRedoLimit(0);
|
||||||
//FIXME: somehow mapGenOption is nullptr at this point :?
|
//FIXME: somehow mapGenOption is nullptr at this point :?
|
||||||
addHeaderInfo();
|
addHeaderInfo();
|
||||||
initTiles();
|
initTiles();
|
||||||
|
|
||||||
initPrisonsRemaining();
|
initPrisonsRemaining();
|
||||||
initQuestArtsRemaining();
|
initQuestArtsRemaining();
|
||||||
genZones();
|
genZones();
|
||||||
@ -160,14 +163,13 @@ std::unique_ptr<CMap> CMapGenerator::generate(CMapGenOptions * mapGenOptions, in
|
|||||||
|
|
||||||
std::string CMapGenerator::getMapDescription() const
|
std::string CMapGenerator::getMapDescription() const
|
||||||
{
|
{
|
||||||
assert(mapGenOptions);
|
|
||||||
assert(map);
|
assert(map);
|
||||||
|
|
||||||
const std::string waterContentStr[3] = { "none", "normal", "islands" };
|
const std::string waterContentStr[3] = { "none", "normal", "islands" };
|
||||||
const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" };
|
const std::string monsterStrengthStr[3] = { "weak", "normal", "strong" };
|
||||||
|
|
||||||
int monsterStrengthIndex = mapGenOptions->getMonsterStrength() - EMonsterStrength::GLOBAL_WEAK; //does not start from 0
|
int monsterStrengthIndex = mapGenOptions.getMonsterStrength() - EMonsterStrength::GLOBAL_WEAK; //does not start from 0
|
||||||
const auto * mapTemplate = mapGenOptions->getMapTemplate();
|
const auto * mapTemplate = mapGenOptions.getMapTemplate();
|
||||||
|
|
||||||
if(!mapTemplate)
|
if(!mapTemplate)
|
||||||
throw rmgException("Map template for Random Map Generator is not found. Could not start the game.");
|
throw rmgException("Map template for Random Map Generator is not found. Could not start the game.");
|
||||||
@ -175,11 +177,11 @@ std::string CMapGenerator::getMapDescription() const
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
|
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
|
||||||
", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
|
", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapTemplate->getName() %
|
||||||
randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions->getPlayerCount()) %
|
randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions.getPlayerCount()) %
|
||||||
static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] %
|
static_cast<int>(mapGenOptions.getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions.getWaterContent()] %
|
||||||
monsterStrengthStr[monsterStrengthIndex]);
|
monsterStrengthStr[monsterStrengthIndex]);
|
||||||
|
|
||||||
for(const auto & pair : mapGenOptions->getPlayersSettings())
|
for(const auto & pair : mapGenOptions.getPlayersSettings())
|
||||||
{
|
{
|
||||||
const auto & pSettings = pair.second;
|
const auto & pSettings = pair.second;
|
||||||
if(pSettings.getPlayerType() == EPlayerType::HUMAN)
|
if(pSettings.getPlayerType() == EPlayerType::HUMAN)
|
||||||
@ -211,13 +213,13 @@ void CMapGenerator::addPlayerInfo()
|
|||||||
{
|
{
|
||||||
if (i == CPHUMAN)
|
if (i == CPHUMAN)
|
||||||
{
|
{
|
||||||
playerCount = mapGenOptions->getPlayerCount();
|
playerCount = mapGenOptions.getPlayerCount();
|
||||||
teamCount = mapGenOptions->getTeamCount();
|
teamCount = mapGenOptions.getTeamCount();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
playerCount = mapGenOptions->getCompOnlyPlayerCount();
|
playerCount = mapGenOptions.getCompOnlyPlayerCount();
|
||||||
teamCount = mapGenOptions->getCompOnlyTeamCount();
|
teamCount = mapGenOptions.getCompOnlyTeamCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playerCount == 0)
|
if(playerCount == 0)
|
||||||
@ -246,7 +248,7 @@ void CMapGenerator::addPlayerInfo()
|
|||||||
|
|
||||||
// Team numbers are assigned randomly to every player
|
// Team numbers are assigned randomly to every player
|
||||||
//TODO: allow customize teams in rmg template
|
//TODO: allow customize teams in rmg template
|
||||||
for(const auto & pair : mapGenOptions->getPlayersSettings())
|
for(const auto & pair : mapGenOptions.getPlayersSettings())
|
||||||
{
|
{
|
||||||
const auto & pSettings = pair.second;
|
const auto & pSettings = pair.second;
|
||||||
PlayerInfo player;
|
PlayerInfo player;
|
||||||
@ -262,36 +264,34 @@ void CMapGenerator::addPlayerInfo()
|
|||||||
logGlobal->error("Not enough places in team for %s player", ((j == CPUONLY) ? "CPU" : "CPU or human"));
|
logGlobal->error("Not enough places in team for %s player", ((j == CPUONLY) ? "CPU" : "CPU or human"));
|
||||||
assert (teamNumbers[j].size());
|
assert (teamNumbers[j].size());
|
||||||
}
|
}
|
||||||
auto itTeam = RandomGeneratorUtil::nextItem(teamNumbers[j], rand);
|
auto itTeam = RandomGeneratorUtil::nextItem(teamNumbers[j], rand);
|
||||||
player.team = TeamID(*itTeam);
|
player.team = TeamID(*itTeam);
|
||||||
teamNumbers[j].erase(itTeam);
|
teamNumbers[j].erase(itTeam);
|
||||||
map->players[pSettings.getColor().getNum()] = player;
|
map->players[pSettings.getColor().getNum()] = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->howManyTeams = (mapGenOptions->getTeamCount() == 0 ? mapGenOptions->getPlayerCount() : mapGenOptions->getTeamCount())
|
map->howManyTeams = (mapGenOptions.getTeamCount() == 0 ? mapGenOptions.getPlayerCount() : mapGenOptions.getTeamCount())
|
||||||
+ (mapGenOptions->getCompOnlyTeamCount() == 0 ? mapGenOptions->getCompOnlyPlayerCount() : mapGenOptions->getCompOnlyTeamCount());
|
+ (mapGenOptions.getCompOnlyTeamCount() == 0 ? mapGenOptions.getCompOnlyPlayerCount() : mapGenOptions.getCompOnlyTeamCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMapGenerator::genZones()
|
void CMapGenerator::genZones()
|
||||||
{
|
{
|
||||||
editManager->clearTerrain(&rand);
|
getEditManager()->clearTerrain(&rand);
|
||||||
editManager->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions->getWidth(), mapGenOptions->getHeight()));
|
getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight()));
|
||||||
editManager->drawTerrain(ETerrainType::GRASS, &rand);
|
getEditManager()->drawTerrain(ETerrainType::GRASS, &rand);
|
||||||
|
|
||||||
auto tmpl = mapGenOptions->getMapTemplate();
|
auto tmpl = mapGenOptions.getMapTemplate();
|
||||||
zones.clear();
|
zones.clear();
|
||||||
for(const auto & option : tmpl->getZones())
|
for(const auto & option : tmpl->getZones())
|
||||||
{
|
{
|
||||||
auto zone = std::make_shared<CRmgTemplateZone>();
|
auto zone = std::make_shared<CRmgTemplateZone>(this);
|
||||||
zone->setOptions(option.second.get());
|
zone->setOptions(option.second.get());
|
||||||
zones[zone->getId()] = zone;
|
zones[zone->getId()] = zone;
|
||||||
//todo: move to CRmgTemplateZone constructor
|
|
||||||
zone->setGenPtr(this);//immediately set gen pointer before taking any actions on zones
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CZonePlacer placer(this);
|
CZonePlacer placer(this);
|
||||||
placer.placeZones(mapGenOptions, &rand);
|
placer.placeZones(&rand);
|
||||||
placer.assignZones(mapGenOptions);
|
placer.assignZones();
|
||||||
|
|
||||||
logGlobal->info("Zones generated successfully");
|
logGlobal->info("Zones generated successfully");
|
||||||
}
|
}
|
||||||
@ -310,18 +310,19 @@ void CMapGenerator::fillZones()
|
|||||||
//place main town in the middle
|
//place main town in the middle
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
it.second->initTownType();
|
it.second->initTownType();
|
||||||
|
|
||||||
//make sure there are some free tiles in the zone
|
//make sure there are some free tiles in the zone
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
it.second->initFreeTiles();
|
it.second->initFreeTiles();
|
||||||
|
|
||||||
createDirectConnections(); //direct
|
createDirectConnections(); //direct
|
||||||
|
|
||||||
//make sure all connections are passable before creating borders
|
//make sure all connections are passable before creating borders
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
it.second->createBorder(); //once direct connections are done
|
it.second->createBorder(); //once direct connections are done
|
||||||
|
|
||||||
createConnections2(); //subterranean gates and monoliths
|
createConnections2(); //subterranean gates and monoliths
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones;
|
std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones;
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
{
|
{
|
||||||
@ -329,12 +330,13 @@ void CMapGenerator::fillZones()
|
|||||||
if (it.second->getType() == ETemplateZoneType::TREASURE)
|
if (it.second->getType() == ETemplateZoneType::TREASURE)
|
||||||
treasureZones.push_back(it.second);
|
treasureZones.push_back(it.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
//set apriopriate free/occupied tiles, including blocked underground rock
|
//set apriopriate free/occupied tiles, including blocked underground rock
|
||||||
createObstaclesCommon1();
|
createObstaclesCommon1();
|
||||||
//set back original terrain for underground zones
|
//set back original terrain for underground zones
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
it.second->createObstacles1();
|
it.second->createObstacles1();
|
||||||
|
|
||||||
createObstaclesCommon2();
|
createObstaclesCommon2();
|
||||||
//place actual obstacles matching zone terrain
|
//place actual obstacles matching zone terrain
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
@ -345,7 +347,7 @@ void CMapGenerator::fillZones()
|
|||||||
#define PRINT_MAP_BEFORE_ROADS false
|
#define PRINT_MAP_BEFORE_ROADS false
|
||||||
if (PRINT_MAP_BEFORE_ROADS) //enable to debug
|
if (PRINT_MAP_BEFORE_ROADS) //enable to debug
|
||||||
{
|
{
|
||||||
std::ofstream out("road debug");
|
std::ofstream out("road_debug.txt");
|
||||||
int levels = map->twoLevel ? 2 : 1;
|
int levels = map->twoLevel ? 2 : 1;
|
||||||
int width = map->width;
|
int width = map->width;
|
||||||
int height = map->height;
|
int height = map->height;
|
||||||
@ -413,8 +415,8 @@ void CMapGenerator::createObstaclesCommon1()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
editManager->getTerrainSelection().setSelection(rockTiles);
|
getEditManager()->getTerrainSelection().setSelection(rockTiles);
|
||||||
editManager->drawTerrain(ETerrainType::ROCK, &rand);
|
getEditManager()->drawTerrain(ETerrainType::ROCK, &rand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +485,7 @@ void CMapGenerator::findZonesForQuestArts()
|
|||||||
{
|
{
|
||||||
//we want to place arties in zones that were not yet filled (higher index)
|
//we want to place arties in zones that were not yet filled (higher index)
|
||||||
|
|
||||||
for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
|
for (auto connection : mapGenOptions.getMapTemplate()->getConnections())
|
||||||
{
|
{
|
||||||
auto zoneA = zones[connection.getZoneA()];
|
auto zoneA = zones[connection.getZoneA()];
|
||||||
auto zoneB = zones[connection.getZoneB()];
|
auto zoneB = zones[connection.getZoneB()];
|
||||||
@ -501,7 +503,7 @@ void CMapGenerator::findZonesForQuestArts()
|
|||||||
|
|
||||||
void CMapGenerator::createDirectConnections()
|
void CMapGenerator::createDirectConnections()
|
||||||
{
|
{
|
||||||
for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
|
for (auto connection : mapGenOptions.getMapTemplate()->getConnections())
|
||||||
{
|
{
|
||||||
auto zoneA = zones[connection.getZoneA()];
|
auto zoneA = zones[connection.getZoneA()];
|
||||||
auto zoneB = zones[connection.getZoneB()];
|
auto zoneB = zones[connection.getZoneB()];
|
||||||
@ -703,9 +705,9 @@ void CMapGenerator::createConnections2()
|
|||||||
void CMapGenerator::addHeaderInfo()
|
void CMapGenerator::addHeaderInfo()
|
||||||
{
|
{
|
||||||
map->version = EMapFormat::VCMI;
|
map->version = EMapFormat::VCMI;
|
||||||
map->width = mapGenOptions->getWidth();
|
map->width = mapGenOptions.getWidth();
|
||||||
map->height = mapGenOptions->getHeight();
|
map->height = mapGenOptions.getHeight();
|
||||||
map->twoLevel = mapGenOptions->getHasTwoLevels();
|
map->twoLevel = mapGenOptions.getHasTwoLevels();
|
||||||
map->name = VLC->generaltexth->allTexts[740];
|
map->name = VLC->generaltexth->allTexts[740];
|
||||||
map->description = getMapDescription();
|
map->description = getMapDescription();
|
||||||
map->difficulty = 1;
|
map->difficulty = 1;
|
||||||
|
@ -52,16 +52,16 @@ class DLL_LINKAGE CMapGenerator
|
|||||||
public:
|
public:
|
||||||
using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<CRmgTemplateZone>>;
|
using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<CRmgTemplateZone>>;
|
||||||
|
|
||||||
explicit CMapGenerator();
|
explicit CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed = std::time(nullptr));
|
||||||
~CMapGenerator(); // required due to std::unique_ptr
|
~CMapGenerator(); // required due to std::unique_ptr
|
||||||
|
|
||||||
std::unique_ptr<CMap> generate(CMapGenOptions * mapGenOptions, int RandomSeed = std::time(nullptr));
|
mutable std::unique_ptr<CMap> map;
|
||||||
|
|
||||||
CMapGenOptions * mapGenOptions;
|
|
||||||
std::unique_ptr<CMap> map;
|
|
||||||
CRandomGenerator rand;
|
CRandomGenerator rand;
|
||||||
int randomSeed;
|
|
||||||
CMapEditManager * editManager;
|
CMapEditManager* getEditManager() const;
|
||||||
|
const CMapGenOptions& getMapGenOptions() const;
|
||||||
|
|
||||||
|
std::unique_ptr<CMap> generate();
|
||||||
|
|
||||||
Zones & getZones();
|
Zones & getZones();
|
||||||
void createDirectConnections();
|
void createDirectConnections();
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
void findZonesForQuestArts();
|
void findZonesForQuestArts();
|
||||||
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
||||||
void foreachDirectNeighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
void foreachDirectNeighbour(const int3 &pos, std::function<void(int3& pos)> foo);
|
||||||
void foreachDiagonaltNeighbour(const int3& pos, std::function<void(int3& pos)> foo);
|
void foreachDiagonalNeighbour(const int3& pos, std::function<void(int3& pos)> foo);
|
||||||
|
|
||||||
bool isBlocked(const int3 &tile) const;
|
bool isBlocked(const int3 &tile) const;
|
||||||
bool shouldBeBlocked(const int3 &tile) const;
|
bool shouldBeBlocked(const int3 &tile) const;
|
||||||
@ -101,6 +101,9 @@ public:
|
|||||||
void setZoneID(const int3& tile, TRmgTemplateZoneId zid);
|
void setZoneID(const int3& tile, TRmgTemplateZoneId zid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int randomSeed;
|
||||||
|
CMapGenOptions& mapGenOptions;
|
||||||
|
|
||||||
std::list<rmg::ZoneConnection> connectionsLeft;
|
std::list<rmg::ZoneConnection> connectionsLeft;
|
||||||
Zones zones;
|
Zones zones;
|
||||||
std::map<TFaction, ui32> zonesPerFaction;
|
std::map<TFaction, ui32> zonesPerFaction;
|
||||||
|
@ -17,11 +17,6 @@
|
|||||||
|
|
||||||
using namespace rmg;
|
using namespace rmg;
|
||||||
|
|
||||||
const std::map<std::string, CRmgTemplate *> & CRmgTemplateStorage::getTemplates() const
|
|
||||||
{
|
|
||||||
return templates;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||||
{
|
{
|
||||||
//unused
|
//unused
|
||||||
@ -30,31 +25,20 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
|
|||||||
|
|
||||||
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data)
|
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||||
{
|
{
|
||||||
auto tpl = new CRmgTemplate();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
JsonDeserializer handler(nullptr, data);
|
JsonDeserializer handler(nullptr, data);
|
||||||
auto fullKey = normalizeIdentifier(scope, "core", name);
|
auto fullKey = normalizeIdentifier(scope, "core", name); //actually it's not used
|
||||||
tpl->setId(name);
|
templates[fullKey].setId(name);
|
||||||
tpl->serializeJson(handler);
|
templates[fullKey].serializeJson(handler);
|
||||||
tpl->validate();
|
templates[fullKey].validate();
|
||||||
templates[fullKey] = tpl;
|
|
||||||
}
|
}
|
||||||
catch(const std::exception & e)
|
catch(const std::exception & e)
|
||||||
{
|
{
|
||||||
logGlobal->error("Template %s has errors. Message: %s.", tpl->getName(), std::string(e.what()));
|
logGlobal->error("Template %s has errors. Message: %s.", name, std::string(e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CRmgTemplateStorage::CRmgTemplateStorage()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CRmgTemplateStorage::~CRmgTemplateStorage()
|
|
||||||
{
|
|
||||||
for (auto & pair : templates) delete pair.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<bool> CRmgTemplateStorage::getDefaultAllowed() const
|
std::vector<bool> CRmgTemplateStorage::getDefaultAllowed() const
|
||||||
{
|
{
|
||||||
//all templates are allowed
|
//all templates are allowed
|
||||||
@ -66,3 +50,54 @@ std::vector<JsonNode> CRmgTemplateStorage::loadLegacyData(size_t dataSize)
|
|||||||
return std::vector<JsonNode>();
|
return std::vector<JsonNode>();
|
||||||
//it would be cool to load old rmg.txt files
|
//it would be cool to load old rmg.txt files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CRmgTemplate * CRmgTemplateStorage::getTemplate(const std::string & templateName) const
|
||||||
|
{
|
||||||
|
auto iter = templates.find(templateName);
|
||||||
|
if(iter==templates.end())
|
||||||
|
return nullptr;
|
||||||
|
return &iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates() const
|
||||||
|
{
|
||||||
|
std::vector<const CRmgTemplate *> result;
|
||||||
|
for(auto i=templates.cbegin(); i!=templates.cend(); ++i)
|
||||||
|
{
|
||||||
|
result.push_back(&i->second);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const
|
||||||
|
{
|
||||||
|
std::vector<const CRmgTemplate *> result;
|
||||||
|
for(auto i=templates.cbegin(); i!=templates.cend(); ++i)
|
||||||
|
{
|
||||||
|
auto& tmpl = i->second;
|
||||||
|
|
||||||
|
if (!tmpl.matchesSize(filterSize))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (filterPlayers != -1)
|
||||||
|
{
|
||||||
|
if (!tmpl.getPlayers().isInRange(filterPlayers))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Human players shouldn't be banned when playing with random player count
|
||||||
|
if (filterHumanPlayers > *boost::min_element(tmpl.getPlayers().getNumbers()))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(filterCpuPlayers != -1)
|
||||||
|
{
|
||||||
|
if (!tmpl.getCpuPlayers().isInRange(filterCpuPlayers))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back(&i->second);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -11,27 +11,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../IHandlerBase.h"
|
#include "../IHandlerBase.h"
|
||||||
|
#include "../int3.h"
|
||||||
|
#include "CRmgTemplate.h"
|
||||||
|
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
class CRmgTemplate;
|
|
||||||
|
|
||||||
/// The CJsonRmgTemplateLoader loads templates from a JSON file.
|
/// The CJsonRmgTemplateLoader loads templates from a JSON file.
|
||||||
class DLL_LINKAGE CRmgTemplateStorage : public IHandlerBase
|
class DLL_LINKAGE CRmgTemplateStorage : public IHandlerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRmgTemplateStorage();
|
CRmgTemplateStorage() = default;
|
||||||
~CRmgTemplateStorage();
|
|
||||||
|
|
||||||
const std::map<std::string, CRmgTemplate *> & getTemplates() const;
|
|
||||||
|
|
||||||
std::vector<bool> getDefaultAllowed() const override;
|
std::vector<bool> getDefaultAllowed() const override;
|
||||||
std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
||||||
|
|
||||||
/// loads single object into game. Scope is namespace of this object, same as name of source mod
|
/// loads single object into game. Scope is namespace of this object, same as name of source mod
|
||||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||||
|
|
||||||
|
const CRmgTemplate * getTemplate(const std::string & templateName) const;
|
||||||
|
std::vector<const CRmgTemplate *> getTemplates() const;
|
||||||
|
std::vector<const CRmgTemplate *> getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, CRmgTemplate *> templates;
|
std::map<std::string, CRmgTemplate> templates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,27 +103,27 @@ void CTileInfo::setRoadType(ERoadType::ERoadType value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CRmgTemplateZone::CRmgTemplateZone()
|
CRmgTemplateZone::CRmgTemplateZone(CMapGenerator * Gen)
|
||||||
: ZoneOptions(),
|
: ZoneOptions(),
|
||||||
townType(ETownType::NEUTRAL),
|
townType(ETownType::NEUTRAL),
|
||||||
terrainType (ETerrainType::GRASS),
|
terrainType (ETerrainType::GRASS),
|
||||||
minGuardedValue(0),
|
minGuardedValue(0),
|
||||||
questArtZone(),
|
questArtZone(),
|
||||||
gen(nullptr)
|
gen(Gen)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CRmgTemplateZone::isUnderground() const
|
||||||
|
{
|
||||||
|
return getPos().z;
|
||||||
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::setOptions(const ZoneOptions * options)
|
void CRmgTemplateZone::setOptions(const ZoneOptions * options)
|
||||||
{
|
{
|
||||||
ZoneOptions::operator=(*options);
|
ZoneOptions::operator=(*options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::setGenPtr(CMapGenerator * Gen)
|
|
||||||
{
|
|
||||||
gen = Gen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplateZone::setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone)
|
void CRmgTemplateZone::setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone)
|
||||||
{
|
{
|
||||||
questArtZone = otherZone;
|
questArtZone = otherZone;
|
||||||
@ -384,7 +384,7 @@ void CRmgTemplateZone::fractalize()
|
|||||||
#define PRINT_FRACTALIZED_MAP false
|
#define PRINT_FRACTALIZED_MAP false
|
||||||
if (PRINT_FRACTALIZED_MAP) //enable to debug
|
if (PRINT_FRACTALIZED_MAP) //enable to debug
|
||||||
{
|
{
|
||||||
std::ofstream out(boost::to_string(boost::format("zone %d") % id));
|
std::ofstream out(boost::to_string(boost::format("zone_%d.txt") % id));
|
||||||
int levels = gen->map->twoLevel ? 2 : 1;
|
int levels = gen->map->twoLevel ? 2 : 1;
|
||||||
int width = gen->map->width;
|
int width = gen->map->width;
|
||||||
int height = gen->map->height;
|
int height = gen->map->height;
|
||||||
@ -618,7 +618,7 @@ bool CRmgTemplateZone::createRoad(const int3& src, const int3& dst)
|
|||||||
if (!directNeighbourFound)
|
if (!directNeighbourFound)
|
||||||
{
|
{
|
||||||
movementCost = 2.1f; //moving diagonally is penalized over moving two tiles straight
|
movementCost = 2.1f; //moving diagonally is penalized over moving two tiles straight
|
||||||
gen->foreachDiagonaltNeighbour(currentNode, foo);
|
gen->foreachDiagonalNeighbour(currentNode, foo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,7 +805,7 @@ bool CRmgTemplateZone::addMonster(int3 &pos, si32 strength, bool clearSurroundin
|
|||||||
//precalculate actual (randomized) monster strength based on this post
|
//precalculate actual (randomized) monster strength based on this post
|
||||||
//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
|
//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
|
||||||
|
|
||||||
int mapMonsterStrength = gen->mapGenOptions->getMonsterStrength();
|
int mapMonsterStrength = gen->getMapGenOptions().getMonsterStrength();
|
||||||
int monsterStrength = (zoneGuard ? 0 : zoneMonsterStrength) + mapMonsterStrength - 1; //array index from 0 to 4
|
int monsterStrength = (zoneGuard ? 0 : zoneMonsterStrength) + mapMonsterStrength - 1; //array index from 0 to 4
|
||||||
static const int value1[] = {2500, 1500, 1000, 500, 0};
|
static const int value1[] = {2500, 1500, 1000, 500, 0};
|
||||||
static const int value2[] = {7500, 7500, 7500, 5000, 5000};
|
static const int value2[] = {7500, 7500, 7500, 5000, 5000};
|
||||||
@ -1181,10 +1181,10 @@ void CRmgTemplateZone::initTownType ()
|
|||||||
if (playerInfo.canAnyonePlay())
|
if (playerInfo.canAnyonePlay())
|
||||||
{
|
{
|
||||||
player = PlayerColor(player_id);
|
player = PlayerColor(player_id);
|
||||||
townType = gen->mapGenOptions->getPlayersSettings().find(player)->second.getStartingTown();
|
townType = gen->getMapGenOptions().getPlayersSettings().find(player)->second.getStartingTown();
|
||||||
|
|
||||||
if (townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
|
if (townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
|
||||||
randomizeTownType();
|
randomizeTownType(true);
|
||||||
}
|
}
|
||||||
else //no player - randomize town
|
else //no player - randomize town
|
||||||
{
|
{
|
||||||
@ -1261,12 +1261,25 @@ void CRmgTemplateZone::initTownType ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::randomizeTownType ()
|
void CRmgTemplateZone::randomizeTownType(bool matchUndergroundType)
|
||||||
{
|
{
|
||||||
if (townTypes.size())
|
auto townTypesAllowed = (townTypes.size() ? townTypes : getDefaultTownTypes());
|
||||||
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
|
if(matchUndergroundType && gen->getMapGenOptions().getHasTwoLevels())
|
||||||
else
|
{
|
||||||
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed, we still need some
|
std::set<TFaction> townTypesVerify;
|
||||||
|
for(TFaction factionIdx : townTypesAllowed)
|
||||||
|
{
|
||||||
|
bool preferUnderground = (*VLC->townh)[factionIdx]->preferUndergroundPlacement;
|
||||||
|
if(isUnderground() ? preferUnderground : !preferUnderground)
|
||||||
|
{
|
||||||
|
townTypesVerify.insert(factionIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!townTypesVerify.empty())
|
||||||
|
townTypesAllowed = townTypesVerify;
|
||||||
|
}
|
||||||
|
|
||||||
|
townType = *RandomGeneratorUtil::nextItem(townTypesAllowed, gen->rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::initTerrainType ()
|
void CRmgTemplateZone::initTerrainType ()
|
||||||
@ -1278,7 +1291,7 @@ void CRmgTemplateZone::initTerrainType ()
|
|||||||
terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand);
|
terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand);
|
||||||
|
|
||||||
//TODO: allow new types of terrain?
|
//TODO: allow new types of terrain?
|
||||||
if (pos.z)
|
if (isUnderground())
|
||||||
{
|
{
|
||||||
if (terrainType != ETerrainType::LAVA)
|
if (terrainType != ETerrainType::LAVA)
|
||||||
terrainType = ETerrainType::SUBTERRANEAN;
|
terrainType = ETerrainType::SUBTERRANEAN;
|
||||||
@ -1295,8 +1308,8 @@ void CRmgTemplateZone::initTerrainType ()
|
|||||||
void CRmgTemplateZone::paintZoneTerrain (ETerrainType terrainType)
|
void CRmgTemplateZone::paintZoneTerrain (ETerrainType terrainType)
|
||||||
{
|
{
|
||||||
std::vector<int3> tiles(tileinfo.begin(), tileinfo.end());
|
std::vector<int3> tiles(tileinfo.begin(), tileinfo.end());
|
||||||
gen->editManager->getTerrainSelection().setSelection(tiles);
|
gen->getEditManager()->getTerrainSelection().setSelection(tiles);
|
||||||
gen->editManager->drawTerrain(terrainType, &gen->rand);
|
gen->getEditManager()->drawTerrain(terrainType, &gen->rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRmgTemplateZone::placeMines ()
|
bool CRmgTemplateZone::placeMines ()
|
||||||
@ -1493,7 +1506,7 @@ bool CRmgTemplateZone::createRequiredObjects()
|
|||||||
|
|
||||||
void CRmgTemplateZone::createTreasures()
|
void CRmgTemplateZone::createTreasures()
|
||||||
{
|
{
|
||||||
int mapMonsterStrength = gen->mapGenOptions->getMonsterStrength();
|
int mapMonsterStrength = gen->getMapGenOptions().getMonsterStrength();
|
||||||
int monsterStrength = zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
|
int monsterStrength = zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
|
||||||
|
|
||||||
static int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 };
|
static int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 };
|
||||||
@ -1570,8 +1583,8 @@ void CRmgTemplateZone::createObstacles1()
|
|||||||
accessibleTiles.push_back(tile);
|
accessibleTiles.push_back(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gen->editManager->getTerrainSelection().setSelection(accessibleTiles);
|
gen->getEditManager()->getTerrainSelection().setSelection(accessibleTiles);
|
||||||
gen->editManager->drawTerrain(terrainType, &gen->rand);
|
gen->getEditManager()->drawTerrain(terrainType, &gen->rand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1610,7 +1623,7 @@ void CRmgTemplateZone::createObstacles2()
|
|||||||
return p1.first > p2.first; //bigger obstacles first
|
return p1.first > p2.first; //bigger obstacles first
|
||||||
});
|
});
|
||||||
|
|
||||||
auto sel = gen->editManager->getTerrainSelection();
|
auto sel = gen->getEditManager()->getTerrainSelection();
|
||||||
sel.clearSelection();
|
sel.clearSelection();
|
||||||
|
|
||||||
auto tryToPlaceObstacleHere = [this, &possibleObstacles](int3& tile, int index)-> bool
|
auto tryToPlaceObstacleHere = [this, &possibleObstacles](int3& tile, int index)-> bool
|
||||||
@ -1705,8 +1718,8 @@ void CRmgTemplateZone::drawRoads()
|
|||||||
tiles.push_back(tile);
|
tiles.push_back(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
gen->editManager->getTerrainSelection().setSelection(tiles);
|
gen->getEditManager()->getTerrainSelection().setSelection(tiles);
|
||||||
gen->editManager->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);
|
gen->getEditManager()->drawRoad(ERoadType::COBBLESTONE_ROAD, &gen->rand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1903,7 +1916,7 @@ void CRmgTemplateZone::checkAndPlaceObject(CGObjectInstance* object, const int3
|
|||||||
object->appearance = templates.front();
|
object->appearance = templates.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
gen->editManager->insertObject(object);
|
gen->getEditManager()->insertObject(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::placeObject(CGObjectInstance* object, const int3 &pos, bool updateDistance)
|
void CRmgTemplateZone::placeObject(CGObjectInstance* object, const int3 &pos, bool updateDistance)
|
||||||
|
@ -89,11 +89,10 @@ struct DLL_LINKAGE CTreasurePileInfo
|
|||||||
class DLL_LINKAGE CRmgTemplateZone : public rmg::ZoneOptions
|
class DLL_LINKAGE CRmgTemplateZone : public rmg::ZoneOptions
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRmgTemplateZone();
|
CRmgTemplateZone(CMapGenerator * Gen);
|
||||||
|
|
||||||
void setOptions(const rmg::ZoneOptions * options);
|
void setOptions(const rmg::ZoneOptions * options);
|
||||||
|
bool isUnderground() const;
|
||||||
void setGenPtr(CMapGenerator * Gen);
|
|
||||||
|
|
||||||
float3 getCenter() const;
|
float3 getCenter() const;
|
||||||
void setCenter(const float3 &f);
|
void setCenter(const float3 &f);
|
||||||
@ -119,7 +118,7 @@ public:
|
|||||||
bool placeMines ();
|
bool placeMines ();
|
||||||
void initTownType ();
|
void initTownType ();
|
||||||
void paintZoneTerrain (ETerrainType terrainType);
|
void paintZoneTerrain (ETerrainType terrainType);
|
||||||
void randomizeTownType(); //helper function
|
void randomizeTownType(bool matchUndergroundType = false); //helper function
|
||||||
void initTerrainType ();
|
void initTerrainType ();
|
||||||
void createBorder();
|
void createBorder();
|
||||||
void fractalize();
|
void fractalize();
|
||||||
@ -170,7 +169,7 @@ private:
|
|||||||
|
|
||||||
std::vector<ObjectInfo> possibleObjects;
|
std::vector<ObjectInfo> possibleObjects;
|
||||||
int minGuardedValue;
|
int minGuardedValue;
|
||||||
|
|
||||||
//content info
|
//content info
|
||||||
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
|
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
|
||||||
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
|
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
|
||||||
|
@ -40,15 +40,15 @@ float CZonePlacer::getDistance (float distance) const
|
|||||||
return (distance ? distance * distance : 1e-6f);
|
return (distance ? distance * distance : 1e-6f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenerator * rand)
|
void CZonePlacer::placeZones(CRandomGenerator * rand)
|
||||||
{
|
{
|
||||||
logGlobal->info("Starting zone placement");
|
logGlobal->info("Starting zone placement");
|
||||||
|
|
||||||
width = mapGenOptions->getWidth();
|
width = gen->getMapGenOptions().getWidth();
|
||||||
height = mapGenOptions->getHeight();
|
height = gen->getMapGenOptions().getHeight();
|
||||||
|
|
||||||
auto zones = gen->getZones();
|
auto zones = gen->getZones();
|
||||||
bool underground = mapGenOptions->getHasTwoLevels();
|
bool underground = gen->getMapGenOptions().getHasTwoLevels();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gravity-based algorithm
|
gravity-based algorithm
|
||||||
@ -174,7 +174,7 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
|
|||||||
if (boost::optional<int> owner = zone.second->getOwner())
|
if (boost::optional<int> owner = zone.second->getOwner())
|
||||||
{
|
{
|
||||||
auto player = PlayerColor(*owner - 1);
|
auto player = PlayerColor(*owner - 1);
|
||||||
auto playerSettings = gen->mapGenOptions->getPlayersSettings();
|
auto playerSettings = gen->getMapGenOptions().getPlayersSettings();
|
||||||
si32 faction = CMapGenOptions::CPlayerSettings::RANDOM_TOWN;
|
si32 faction = CMapGenOptions::CPlayerSettings::RANDOM_TOWN;
|
||||||
if (vstd::contains(playerSettings, player))
|
if (vstd::contains(playerSettings, player))
|
||||||
faction = playerSettings[player].getStartingTown();
|
faction = playerSettings[player].getStartingTown();
|
||||||
@ -453,12 +453,12 @@ d = 0.01 * dx^3 - 0.1618 * dx^2 + 1 * dx + ...
|
|||||||
return dx * (1.0f + dx * (0.1f + dx * 0.01f)) + dy * (1.618f + dy * (-0.1618f + dy * 0.01618f));
|
return dx * (1.0f + dx * (0.1f + dx * 0.01f)) + dy * (1.618f + dy * (-0.1618f + dy * 0.01618f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
void CZonePlacer::assignZones()
|
||||||
{
|
{
|
||||||
logGlobal->info("Starting zone colouring");
|
logGlobal->info("Starting zone colouring");
|
||||||
|
|
||||||
auto width = mapGenOptions->getWidth();
|
auto width = gen->getMapGenOptions().getWidth();
|
||||||
auto height = mapGenOptions->getHeight();
|
auto height = gen->getMapGenOptions().getHeight();
|
||||||
|
|
||||||
//scale to Medium map to ensure smooth results
|
//scale to Medium map to ensure smooth results
|
||||||
scaleX = 72.f / width;
|
scaleX = 72.f / width;
|
||||||
@ -554,7 +554,7 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
|||||||
|
|
||||||
//TODO: similiar for islands
|
//TODO: similiar for islands
|
||||||
#define CREATE_FULL_UNDERGROUND true //consider linking this with water amount
|
#define CREATE_FULL_UNDERGROUND true //consider linking this with water amount
|
||||||
if (zone.second->getPos().z)
|
if (zone.second->isUnderground())
|
||||||
{
|
{
|
||||||
if (!CREATE_FULL_UNDERGROUND)
|
if (!CREATE_FULL_UNDERGROUND)
|
||||||
zone.second->discardDistantTiles((float)(zone.second->getSize() + 1));
|
zone.second->discardDistantTiles((float)(zone.second->getSize() + 1));
|
||||||
|
@ -34,12 +34,14 @@ public:
|
|||||||
float getDistance(float distance) const; //additional scaling without 0 divison
|
float getDistance(float distance) const; //additional scaling without 0 divison
|
||||||
~CZonePlacer();
|
~CZonePlacer();
|
||||||
|
|
||||||
|
void placeZones(CRandomGenerator * rand);
|
||||||
|
void assignZones();
|
||||||
|
|
||||||
|
private:
|
||||||
void prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, CRandomGenerator * rand);
|
void prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, CRandomGenerator * rand);
|
||||||
void attractConnectedZones(TZoneMap &zones, TForceVector &forces, TDistanceVector &distances);
|
void attractConnectedZones(TZoneMap &zones, TForceVector &forces, TDistanceVector &distances);
|
||||||
void separateOverlappingZones(TZoneMap &zones, TForceVector &forces, TDistanceVector &overlaps);
|
void separateOverlappingZones(TZoneMap &zones, TForceVector &forces, TDistanceVector &overlaps);
|
||||||
void moveOneZone(TZoneMap &zones, TForceVector &totalForces, TDistanceVector &distances, TDistanceVector &overlaps);
|
void moveOneZone(TZoneMap &zones, TForceVector &totalForces, TDistanceVector &distances, TDistanceVector &overlaps);
|
||||||
void placeZones(const CMapGenOptions * mapGenOptions, CRandomGenerator * rand);
|
|
||||||
void assignZones(const CMapGenOptions * mapGenOptions);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int width;
|
int width;
|
||||||
|
@ -59,9 +59,9 @@ TEST(MapFormat, Random)
|
|||||||
opt.setPlayerTypeForStandardPlayer(PlayerColor(2), EPlayerType::AI);
|
opt.setPlayerTypeForStandardPlayer(PlayerColor(2), EPlayerType::AI);
|
||||||
opt.setPlayerTypeForStandardPlayer(PlayerColor(3), EPlayerType::AI);
|
opt.setPlayerTypeForStandardPlayer(PlayerColor(3), EPlayerType::AI);
|
||||||
|
|
||||||
CMapGenerator gen;
|
CMapGenerator gen(opt, TEST_RANDOM_SEED);
|
||||||
|
|
||||||
std::unique_ptr<CMap> initialMap = gen.generate(&opt, TEST_RANDOM_SEED);
|
std::unique_ptr<CMap> initialMap = gen.generate();
|
||||||
initialMap->name = "Test";
|
initialMap->name = "Test";
|
||||||
SCOPED_TRACE("MapFormat_Random generated");
|
SCOPED_TRACE("MapFormat_Random generated");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user