mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Redone RMG template serialization using JSON serializer, added tests
This commit is contained in:
parent
7d27d144a5
commit
9d108d59db
28
include/vstd/ContainerUtils.h
Normal file
28
include/vstd/ContainerUtils.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* ContainerUtils.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace vstd
|
||||||
|
{
|
||||||
|
template<typename K, typename V>
|
||||||
|
std::map<V, K> invertMap(const std::map<K, V> & m)
|
||||||
|
{
|
||||||
|
std::map<V,K> other;
|
||||||
|
std::transform(m.cbegin(), m.cend(), std::inserter(other, other.begin()), [](const std::pair<K, V> & p)
|
||||||
|
{
|
||||||
|
return std::make_pair(p.second, p.first);
|
||||||
|
});
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -165,6 +165,9 @@ set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(lib_HEADERS
|
set(lib_HEADERS
|
||||||
|
${CMAKE_HOME_DIRECTORY}/include/vstd/CLoggerBase.h
|
||||||
|
${CMAKE_HOME_DIRECTORY}/include/vstd/ContainerUtils.h
|
||||||
|
${CMAKE_HOME_DIRECTORY}/include/vstd/RNG.h
|
||||||
StdInc.h
|
StdInc.h
|
||||||
../Global.h
|
../Global.h
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@
|
|||||||
<Unit filename="../Global.h" />
|
<Unit filename="../Global.h" />
|
||||||
<Unit filename="../Version.h" />
|
<Unit filename="../Version.h" />
|
||||||
<Unit filename="../include/vstd/CLoggerBase.h" />
|
<Unit filename="../include/vstd/CLoggerBase.h" />
|
||||||
|
<Unit filename="../include/vstd/ContainerUtils.h" />
|
||||||
<Unit filename="../include/vstd/RNG.h" />
|
<Unit filename="../include/vstd/RNG.h" />
|
||||||
<Unit filename="AI_Base.h" />
|
<Unit filename="AI_Base.h" />
|
||||||
<Unit filename="CArtHandler.cpp" />
|
<Unit filename="CArtHandler.cpp" />
|
||||||
|
@ -406,8 +406,8 @@ const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand
|
|||||||
for(const auto & tplPair : tpls)
|
for(const auto & tplPair : tpls)
|
||||||
{
|
{
|
||||||
const auto & tpl = tplPair.second;
|
const auto & tpl = tplPair.second;
|
||||||
CRmgTemplate::CSize tplSize(width, height, hasTwoLevels);
|
int3 tplSize(width, height, (hasTwoLevels ? 2 : 1));
|
||||||
if(tplSize >= tpl->getMinSize() && tplSize <= tpl->getMaxSize())
|
if(tpl->matchesSize(tplSize))
|
||||||
{
|
{
|
||||||
bool isPlayerCountValid = false;
|
bool isPlayerCountValid = false;
|
||||||
if (getPlayerCount() != RANDOM_SIZE)
|
if (getPlayerCount() != RANDOM_SIZE)
|
||||||
|
@ -149,6 +149,7 @@ std::unique_ptr<CMap> CMapGenerator::generate(CMapGenOptions * mapGenOptions, in
|
|||||||
map->calculateGuardingGreaturePositions(); //clear map so that all tiles are unguarded
|
map->calculateGuardingGreaturePositions(); //clear map so that all tiles are unguarded
|
||||||
fillZones();
|
fillZones();
|
||||||
//updated guarded tiles will be calculated in CGameState::initMapObjects()
|
//updated guarded tiles will be calculated in CGameState::initMapObjects()
|
||||||
|
zones.clear();
|
||||||
}
|
}
|
||||||
catch (rmgException &e)
|
catch (rmgException &e)
|
||||||
{
|
{
|
||||||
@ -277,8 +278,8 @@ void CMapGenerator::genZones()
|
|||||||
zones.clear();
|
zones.clear();
|
||||||
for(const auto & option : tmpl->getZones())
|
for(const auto & option : tmpl->getZones())
|
||||||
{
|
{
|
||||||
auto zone = new CRmgTemplateZone();
|
auto zone = std::make_shared<CRmgTemplateZone>();
|
||||||
zone->setOptions(option.second);
|
zone->setOptions(option.second.get());
|
||||||
zones[zone->getId()] = zone;
|
zones[zone->getId()] = zone;
|
||||||
//todo: move to CRmgTemplateZone constructor
|
//todo: move to CRmgTemplateZone constructor
|
||||||
zone->setGenPtr(this);//immediately set gen pointer before taking any actions on zones
|
zone->setGenPtr(this);//immediately set gen pointer before taking any actions on zones
|
||||||
@ -317,7 +318,7 @@ void CMapGenerator::fillZones()
|
|||||||
|
|
||||||
createConnections2(); //subterranean gates and monoliths
|
createConnections2(); //subterranean gates and monoliths
|
||||||
|
|
||||||
std::vector<CRmgTemplateZone*> treasureZones;
|
std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones;
|
||||||
for (auto it : zones)
|
for (auto it : zones)
|
||||||
{
|
{
|
||||||
it.second->fill();
|
it.second->fill();
|
||||||
@ -716,7 +717,7 @@ void CMapGenerator::checkIsOnMap(const int3& tile) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> CMapGenerator::getZones() const
|
CMapGenerator::Zones & CMapGenerator::getZones()
|
||||||
{
|
{
|
||||||
return zones;
|
return zones;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ public:
|
|||||||
class DLL_LINKAGE CMapGenerator
|
class DLL_LINKAGE CMapGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<CRmgTemplateZone>>;
|
||||||
|
|
||||||
explicit CMapGenerator();
|
explicit CMapGenerator();
|
||||||
~CMapGenerator(); // required due to std::unique_ptr
|
~CMapGenerator(); // required due to std::unique_ptr
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ public:
|
|||||||
int randomSeed;
|
int randomSeed;
|
||||||
CMapEditManager * editManager;
|
CMapEditManager * editManager;
|
||||||
|
|
||||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
|
Zones & getZones();
|
||||||
void createDirectConnections();
|
void createDirectConnections();
|
||||||
void createConnections2();
|
void createConnections2();
|
||||||
void findZonesForQuestArts();
|
void findZonesForQuestArts();
|
||||||
@ -100,7 +102,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<rmg::ZoneConnection> connectionsLeft;
|
std::list<rmg::ZoneConnection> connectionsLeft;
|
||||||
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
|
Zones zones;
|
||||||
std::map<TFaction, ui32> zonesPerFaction;
|
std::map<TFaction, ui32> zonesPerFaction;
|
||||||
ui32 zonesTotal; //zones that have their main town only
|
ui32 zonesTotal; //zones that have their main town only
|
||||||
|
|
||||||
|
@ -9,15 +9,93 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
|
#include <vstd/ContainerUtils.h>
|
||||||
#include "CRmgTemplate.h"
|
#include "CRmgTemplate.h"
|
||||||
|
|
||||||
#include "../mapping/CMap.h"
|
#include "../mapping/CMap.h"
|
||||||
#include "../VCMI_Lib.h"
|
#include "../VCMI_Lib.h"
|
||||||
#include "../CTownHandler.h"
|
#include "../CTownHandler.h"
|
||||||
|
#include "../serializer/JsonSerializeFormat.h"
|
||||||
|
#include "../StringConstants.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
si32 decodeZoneId(const std::string & json)
|
||||||
|
{
|
||||||
|
return boost::lexical_cast<si32>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string encodeZoneId(si32 id)
|
||||||
|
{
|
||||||
|
return boost::lexical_cast<std::string>(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CTreasureInfo::CTreasureInfo()
|
||||||
|
: min(0),
|
||||||
|
max(0),
|
||||||
|
density(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTreasureInfo::operator==(const CTreasureInfo & other) const
|
||||||
|
{
|
||||||
|
return (min == other.min) && (max == other.max) && (density == other.density);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTreasureInfo::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
handler.serializeInt("min", min, 0);
|
||||||
|
handler.serializeInt("max", max, 0);
|
||||||
|
handler.serializeInt("density", density, 0);
|
||||||
|
}
|
||||||
|
|
||||||
namespace rmg
|
namespace rmg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class TerrainEncoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static si32 decode(const std::string & identifier)
|
||||||
|
{
|
||||||
|
return vstd::find_pos(GameConstants::TERRAIN_NAMES, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string encode(const si32 index)
|
||||||
|
{
|
||||||
|
return (index >=0 && index < GameConstants::TERRAIN_TYPES) ? GameConstants::TERRAIN_NAMES[index] : "<INVALID TERRAIN>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ZoneEncoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static si32 decode(const std::string & json)
|
||||||
|
{
|
||||||
|
return boost::lexical_cast<si32>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string encode(si32 id)
|
||||||
|
{
|
||||||
|
return boost::lexical_cast<std::string>(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FactionEncoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static si32 decode(const std::string & json)
|
||||||
|
{
|
||||||
|
return VLC->townh->decodeFaction(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string encode(si32 id)
|
||||||
|
{
|
||||||
|
return VLC->townh->encodeFaction(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const std::set<ETerrainType> ZoneOptions::DEFAULT_TERRAIN_TYPES =
|
const std::set<ETerrainType> ZoneOptions::DEFAULT_TERRAIN_TYPES =
|
||||||
{
|
{
|
||||||
ETerrainType::DIRT,
|
ETerrainType::DIRT,
|
||||||
@ -30,6 +108,8 @@ const std::set<ETerrainType> ZoneOptions::DEFAULT_TERRAIN_TYPES =
|
|||||||
ETerrainType::LAVA
|
ETerrainType::LAVA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TRmgTemplateZoneId ZoneOptions::NO_ZONE = -1;
|
||||||
|
|
||||||
ZoneOptions::CTownInfo::CTownInfo()
|
ZoneOptions::CTownInfo::CTownInfo()
|
||||||
: townCount(0),
|
: townCount(0),
|
||||||
castleCount(0),
|
castleCount(0),
|
||||||
@ -44,49 +124,30 @@ int ZoneOptions::CTownInfo::getTownCount() const
|
|||||||
return townCount;
|
return townCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::CTownInfo::setTownCount(int value)
|
|
||||||
{
|
|
||||||
if(value < 0)
|
|
||||||
throw std::runtime_error("Negative value for town count not allowed.");
|
|
||||||
townCount = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZoneOptions::CTownInfo::getCastleCount() const
|
int ZoneOptions::CTownInfo::getCastleCount() const
|
||||||
{
|
{
|
||||||
return castleCount;
|
return castleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::CTownInfo::setCastleCount(int value)
|
|
||||||
{
|
|
||||||
if(value < 0)
|
|
||||||
throw std::runtime_error("Negative value for castle count not allowed.");
|
|
||||||
castleCount = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZoneOptions::CTownInfo::getTownDensity() const
|
int ZoneOptions::CTownInfo::getTownDensity() const
|
||||||
{
|
{
|
||||||
return townDensity;
|
return townDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::CTownInfo::setTownDensity(int value)
|
|
||||||
{
|
|
||||||
if(value < 0)
|
|
||||||
throw std::runtime_error("Negative value for town density not allowed.");
|
|
||||||
townDensity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZoneOptions::CTownInfo::getCastleDensity() const
|
int ZoneOptions::CTownInfo::getCastleDensity() const
|
||||||
{
|
{
|
||||||
return castleDensity;
|
return castleDensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::CTownInfo::setCastleDensity(int value)
|
void ZoneOptions::CTownInfo::serializeJson(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
if(value < 0)
|
handler.serializeInt("towns", townCount, 0);
|
||||||
throw std::runtime_error("Negative value for castle density not allowed.");
|
handler.serializeInt("castles", castleCount, 0);
|
||||||
castleDensity = value;
|
handler.serializeInt("townDensity", townDensity, 0);
|
||||||
|
handler.serializeInt("castleDensity", castleDensity, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZoneOptions::ZoneOptions()
|
ZoneOptions::ZoneOptions()
|
||||||
: id(0),
|
: id(0),
|
||||||
type(ETemplateZoneType::PLAYER_START),
|
type(ETemplateZoneType::PLAYER_START),
|
||||||
@ -102,7 +163,10 @@ ZoneOptions::ZoneOptions()
|
|||||||
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
|
zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
|
||||||
mines(),
|
mines(),
|
||||||
treasureInfo(),
|
treasureInfo(),
|
||||||
connections()
|
connections(),
|
||||||
|
minesLikeZone(NO_ZONE),
|
||||||
|
terrainTypeLikeZone(NO_ZONE),
|
||||||
|
treasureLikeZone(NO_ZONE)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -124,6 +188,9 @@ ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other)
|
|||||||
mines = other.mines;
|
mines = other.mines;
|
||||||
treasureInfo = other.treasureInfo;
|
treasureInfo = other.treasureInfo;
|
||||||
connections = other.connections;
|
connections = other.connections;
|
||||||
|
minesLikeZone = other.minesLikeZone;
|
||||||
|
terrainTypeLikeZone = other.terrainTypeLikeZone;
|
||||||
|
treasureLikeZone = other.treasureLikeZone;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,10 +210,6 @@ ETemplateZoneType::ETemplateZoneType ZoneOptions::getType() const
|
|||||||
{
|
{
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
void ZoneOptions::setType(ETemplateZoneType::ETemplateZoneType value)
|
|
||||||
{
|
|
||||||
type = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZoneOptions::getSize() const
|
int ZoneOptions::getSize() const
|
||||||
{
|
{
|
||||||
@ -155,8 +218,6 @@ int ZoneOptions::getSize() const
|
|||||||
|
|
||||||
void ZoneOptions::setSize(int value)
|
void ZoneOptions::setSize(int value)
|
||||||
{
|
{
|
||||||
if(value <= 0)
|
|
||||||
throw std::runtime_error(boost::to_string(boost::format("Zone %d size needs to be greater than 0.") % id));
|
|
||||||
size = value;
|
size = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,43 +226,6 @@ boost::optional<int> ZoneOptions::getOwner() const
|
|||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::setOwner(boost::optional<int> value)
|
|
||||||
{
|
|
||||||
if(value && !(*value >= 0 && *value <= PlayerColor::PLAYER_LIMIT_I))
|
|
||||||
throw std::runtime_error(boost::to_string(boost::format ("Owner of zone %d has to be in range 0 to max player count.") % id));
|
|
||||||
owner = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ZoneOptions::CTownInfo & ZoneOptions::getPlayerTowns() const
|
|
||||||
{
|
|
||||||
return playerTowns;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneOptions::setPlayerTowns(const CTownInfo & value)
|
|
||||||
{
|
|
||||||
playerTowns = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ZoneOptions::CTownInfo & ZoneOptions::getNeutralTowns() const
|
|
||||||
{
|
|
||||||
return neutralTowns;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneOptions::setNeutralTowns(const CTownInfo & value)
|
|
||||||
{
|
|
||||||
neutralTowns = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZoneOptions::getMatchTerrainToTown() const
|
|
||||||
{
|
|
||||||
return matchTerrainToTown;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneOptions::setMatchTerrainToTown(bool value)
|
|
||||||
{
|
|
||||||
matchTerrainToTown = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::set<ETerrainType> & ZoneOptions::getTerrainTypes() const
|
const std::set<ETerrainType> & ZoneOptions::getTerrainTypes() const
|
||||||
{
|
{
|
||||||
return terrainTypes;
|
return terrainTypes;
|
||||||
@ -214,16 +238,6 @@ void ZoneOptions::setTerrainTypes(const std::set<ETerrainType> & value)
|
|||||||
terrainTypes = value;
|
terrainTypes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneOptions::getTownsAreSameType() const
|
|
||||||
{
|
|
||||||
return townsAreSameType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneOptions::setTownsAreSameType(bool value)
|
|
||||||
{
|
|
||||||
townsAreSameType = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<TFaction> ZoneOptions::getDefaultTownTypes() const
|
std::set<TFaction> ZoneOptions::getDefaultTownTypes() const
|
||||||
{
|
{
|
||||||
std::set<TFaction> defaultTowns;
|
std::set<TFaction> defaultTowns;
|
||||||
@ -250,15 +264,9 @@ void ZoneOptions::setMonsterTypes(const std::set<TFaction> & value)
|
|||||||
monsterTypes = value;
|
monsterTypes = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength val)
|
void ZoneOptions::setMinesInfo(const std::map<TResource, ui16> & value)
|
||||||
{
|
{
|
||||||
assert (vstd::iswithin(val, EMonsterStrength::ZONE_WEAK, EMonsterStrength::ZONE_STRONG));
|
mines = value;
|
||||||
zoneMonsterStrength = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneOptions::setMinesAmount(TResource res, ui16 amount)
|
|
||||||
{
|
|
||||||
mines[res] = amount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<TResource, ui16> ZoneOptions::getMinesInfo() const
|
std::map<TResource, ui16> ZoneOptions::getMinesInfo() const
|
||||||
@ -266,9 +274,9 @@ std::map<TResource, ui16> ZoneOptions::getMinesInfo() const
|
|||||||
return mines;
|
return mines;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneOptions::addTreasureInfo(const CTreasureInfo & info)
|
void ZoneOptions::setTreasureInfo(const std::vector<CTreasureInfo> & value)
|
||||||
{
|
{
|
||||||
treasureInfo.push_back(info);
|
treasureInfo = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const
|
const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const
|
||||||
@ -276,11 +284,102 @@ const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const
|
|||||||
return treasureInfo;
|
return treasureInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRmgTemplateZoneId ZoneOptions::getMinesLikeZone() const
|
||||||
|
{
|
||||||
|
return minesLikeZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRmgTemplateZoneId ZoneOptions::getTerrainTypeLikeZone() const
|
||||||
|
{
|
||||||
|
return terrainTypeLikeZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRmgTemplateZoneId ZoneOptions::getTreasureLikeZone() const
|
||||||
|
{
|
||||||
|
return treasureLikeZone;
|
||||||
|
}
|
||||||
|
|
||||||
void ZoneOptions::addConnection(TRmgTemplateZoneId otherZone)
|
void ZoneOptions::addConnection(TRmgTemplateZoneId otherZone)
|
||||||
{
|
{
|
||||||
connections.push_back (otherZone);
|
connections.push_back (otherZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TRmgTemplateZoneId> ZoneOptions::getConnections() const
|
||||||
|
{
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> zoneTypes =
|
||||||
|
{
|
||||||
|
"playerStart",
|
||||||
|
"cpuStart",
|
||||||
|
"treasure",
|
||||||
|
"junction"
|
||||||
|
};
|
||||||
|
|
||||||
|
handler.serializeEnum("type", type, zoneTypes);
|
||||||
|
handler.serializeInt("size", size, 1);
|
||||||
|
handler.serializeInt("owner", owner);
|
||||||
|
handler.serializeStruct("playerTowns", playerTowns);
|
||||||
|
handler.serializeStruct("neutralTowns", neutralTowns);
|
||||||
|
handler.serializeBool("matchTerrainToTown", matchTerrainToTown, true);
|
||||||
|
|
||||||
|
#define SERIALIZE_ZONE_LINK(fieldName) handler.serializeInt(#fieldName, fieldName, NO_ZONE);
|
||||||
|
|
||||||
|
SERIALIZE_ZONE_LINK(minesLikeZone);
|
||||||
|
SERIALIZE_ZONE_LINK(terrainTypeLikeZone);
|
||||||
|
SERIALIZE_ZONE_LINK(treasureLikeZone);
|
||||||
|
|
||||||
|
#undef SERIALIZE_ZONE_LINK
|
||||||
|
|
||||||
|
if(terrainTypeLikeZone == NO_ZONE)
|
||||||
|
handler.serializeIdArray<ETerrainType, TerrainEncoder>("terrainTypes", terrainTypes, DEFAULT_TERRAIN_TYPES);
|
||||||
|
|
||||||
|
handler.serializeBool("townsAreSameType", townsAreSameType, false);
|
||||||
|
handler.serializeIdArray<TFaction, FactionEncoder>("allowedMonsters", monsterTypes, VLC->townh->getAllowedFactions(false));
|
||||||
|
handler.serializeIdArray<TFaction, FactionEncoder>("allowedTowns", townTypes, VLC->townh->getAllowedFactions(true));
|
||||||
|
|
||||||
|
{
|
||||||
|
//TODO: add support for std::map to serializeEnum
|
||||||
|
static const std::vector<std::string> STRENGTH =
|
||||||
|
{
|
||||||
|
"weak",
|
||||||
|
"normal",
|
||||||
|
"strong"
|
||||||
|
};
|
||||||
|
|
||||||
|
si32 rawStrength = 0;
|
||||||
|
if(handler.saving)
|
||||||
|
{
|
||||||
|
rawStrength = static_cast<decltype(rawStrength)>(zoneMonsterStrength);
|
||||||
|
rawStrength++;
|
||||||
|
}
|
||||||
|
handler.serializeEnum("monsters", rawStrength, STRENGTH);
|
||||||
|
if(!handler.saving)
|
||||||
|
{
|
||||||
|
rawStrength--;
|
||||||
|
zoneMonsterStrength = static_cast<decltype(zoneMonsterStrength)>(rawStrength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(treasureLikeZone == NO_ZONE)
|
||||||
|
{
|
||||||
|
auto treasureData = handler.enterArray("treasure");
|
||||||
|
treasureData.serializeStruct(treasureInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((minesLikeZone == NO_ZONE) && (!handler.saving || !mines.empty()))
|
||||||
|
{
|
||||||
|
auto minesData = handler.enterStruct("mines");
|
||||||
|
|
||||||
|
for(TResource idx = 0; idx < (GameConstants::RESOURCE_QUANTITY - 1); idx++)
|
||||||
|
{
|
||||||
|
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], mines[idx], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZoneConnection::ZoneConnection()
|
ZoneConnection::ZoneConnection()
|
||||||
: zoneA(-1),
|
: zoneA(-1),
|
||||||
@ -290,157 +389,60 @@ ZoneConnection::ZoneConnection()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRmgTemplateZoneId ZoneConnection::getZoneA() const
|
TRmgTemplateZoneId ZoneConnection::getZoneA() const
|
||||||
{
|
{
|
||||||
return zoneA;
|
return zoneA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneConnection::setZoneA(TRmgTemplateZoneId value)
|
|
||||||
{
|
|
||||||
zoneA = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRmgTemplateZoneId ZoneConnection::getZoneB() const
|
TRmgTemplateZoneId ZoneConnection::getZoneB() const
|
||||||
{
|
{
|
||||||
return zoneB;
|
return zoneB;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneConnection::setZoneB(TRmgTemplateZoneId value)
|
|
||||||
{
|
|
||||||
zoneB = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ZoneConnection::getGuardStrength() const
|
int ZoneConnection::getGuardStrength() const
|
||||||
{
|
{
|
||||||
return guardStrength;
|
return guardStrength;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneConnection::setGuardStrength(int value)
|
void ZoneConnection::serializeJson(JsonSerializeFormat & handler)
|
||||||
{
|
{
|
||||||
if(value < 0) throw std::runtime_error("Negative value for guard strength not allowed.");
|
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("a", zoneA, -1);
|
||||||
guardStrength = value;
|
handler.serializeId<TRmgTemplateZoneId, TRmgTemplateZoneId, ZoneEncoder>("b", zoneB, -1);
|
||||||
|
handler.serializeInt("guard", guardStrength, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace rmg;//todo: remove
|
using namespace rmg;//todo: remove
|
||||||
|
|
||||||
|
|
||||||
CRmgTemplate::CSize::CSize() : width(CMapHeader::MAP_SIZE_MIDDLE), height(CMapHeader::MAP_SIZE_MIDDLE), under(true)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CRmgTemplate::CSize::CSize(int width, int height, bool under) : under(under)
|
|
||||||
{
|
|
||||||
setWidth(width);
|
|
||||||
setHeight(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CRmgTemplate::CSize::getWidth() const
|
|
||||||
{
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::CSize::setWidth(int value)
|
|
||||||
{
|
|
||||||
if(value <= 0) throw std::runtime_error("Width > 0 failed.");
|
|
||||||
width = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CRmgTemplate::CSize::getHeight() const
|
|
||||||
{
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::CSize::setHeight(int value)
|
|
||||||
{
|
|
||||||
if(value <= 0) throw std::runtime_error("Height > 0 failed.");
|
|
||||||
height = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRmgTemplate::CSize::getUnder() const
|
|
||||||
{
|
|
||||||
return under;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::CSize::setUnder(bool value)
|
|
||||||
{
|
|
||||||
under = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRmgTemplate::CSize::operator<=(const CSize & value) const
|
|
||||||
{
|
|
||||||
if(width < value.width && height < value.height)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(width == value.width && height == value.height)
|
|
||||||
{
|
|
||||||
return under ? value.under : true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRmgTemplate::CSize::operator>=(const CSize & value) const
|
|
||||||
{
|
|
||||||
if(width > value.width && height > value.height)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(width == value.width && height == value.height)
|
|
||||||
{
|
|
||||||
return under ? true : !value.under;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CRmgTemplate::CRmgTemplate()
|
CRmgTemplate::CRmgTemplate()
|
||||||
|
: minSize(72, 72, 2),
|
||||||
|
maxSize(72, 72, 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CRmgTemplate::~CRmgTemplate()
|
CRmgTemplate::~CRmgTemplate()
|
||||||
{
|
{
|
||||||
for (auto & pair : zones) delete pair.second;
|
}
|
||||||
|
|
||||||
|
bool CRmgTemplate::matchesSize(const int3 & value) const
|
||||||
|
{
|
||||||
|
const int64_t square = value.x * value.y * value.z;
|
||||||
|
const int64_t minSquare = minSize.x * minSize.y * minSize.z;
|
||||||
|
const int64_t maxSquare = maxSize.x * maxSize.y * maxSize.z;
|
||||||
|
|
||||||
|
return minSquare <= square && square <= maxSquare;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::setId(const std::string & value)
|
||||||
|
{
|
||||||
|
id = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & CRmgTemplate::getName() const
|
const std::string & CRmgTemplate::getName() const
|
||||||
{
|
{
|
||||||
return name;
|
return name.empty() ? id : name;
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::setName(const std::string & value)
|
|
||||||
{
|
|
||||||
name = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CRmgTemplate::CSize & CRmgTemplate::getMinSize() const
|
|
||||||
{
|
|
||||||
return minSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::setMinSize(const CSize & value)
|
|
||||||
{
|
|
||||||
minSize = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CRmgTemplate::CSize & CRmgTemplate::getMaxSize() const
|
|
||||||
{
|
|
||||||
return maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::setMaxSize(const CSize & value)
|
|
||||||
{
|
|
||||||
maxSize = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getPlayers() const
|
const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getPlayers() const
|
||||||
@ -448,41 +450,21 @@ const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getPlayers() const
|
|||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplate::setPlayers(const CPlayerCountRange & value)
|
|
||||||
{
|
|
||||||
players = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getCpuPlayers() const
|
const CRmgTemplate::CPlayerCountRange & CRmgTemplate::getCpuPlayers() const
|
||||||
{
|
{
|
||||||
return cpuPlayers;
|
return cpuPlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplate::setCpuPlayers(const CPlayerCountRange & value)
|
const CRmgTemplate::Zones & CRmgTemplate::getZones() const
|
||||||
{
|
|
||||||
cpuPlayers = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<TRmgTemplateZoneId, ZoneOptions *> & CRmgTemplate::getZones() const
|
|
||||||
{
|
{
|
||||||
return zones;
|
return zones;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplate::setZones(const std::map<TRmgTemplateZoneId, ZoneOptions *> & value)
|
const std::vector<ZoneConnection> & CRmgTemplate::getConnections() const
|
||||||
{
|
|
||||||
zones = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::list<ZoneConnection> & CRmgTemplate::getConnections() const
|
|
||||||
{
|
{
|
||||||
return connections;
|
return connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplate::setConnections(const std::list<ZoneConnection> & value)
|
|
||||||
{
|
|
||||||
connections = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CRmgTemplate::validate() const
|
void CRmgTemplate::validate() const
|
||||||
{
|
{
|
||||||
//TODO add some validation checks, throw on failure
|
//TODO add some validation checks, throw on failure
|
||||||
@ -516,3 +498,212 @@ std::set<int> CRmgTemplate::CPlayerCountRange::getNumbers() const
|
|||||||
}
|
}
|
||||||
return numbers;
|
return numbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CRmgTemplate::CPlayerCountRange::toString() const
|
||||||
|
{
|
||||||
|
if(range.size() == 1)
|
||||||
|
{
|
||||||
|
const auto & p = range.front();
|
||||||
|
if((p.first == p.second) && (p.first == 0))
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ret;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for(auto & p : range)
|
||||||
|
{
|
||||||
|
if(!first)
|
||||||
|
ret +=",";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if(p.first == p.second)
|
||||||
|
{
|
||||||
|
ret += boost::lexical_cast<std::string>(p.first);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret += boost::to_string(boost::format("%d-%d") % p.first % p.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::CPlayerCountRange::fromString(const std::string & value)
|
||||||
|
{
|
||||||
|
range.clear();
|
||||||
|
|
||||||
|
if(value.empty())
|
||||||
|
{
|
||||||
|
addNumber(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<std::string> commaParts;
|
||||||
|
boost::split(commaParts, value, boost::is_any_of(","));
|
||||||
|
for(const auto & commaPart : commaParts)
|
||||||
|
{
|
||||||
|
std::vector<std::string> rangeParts;
|
||||||
|
boost::split(rangeParts, commaPart, boost::is_any_of("-"));
|
||||||
|
if(rangeParts.size() == 2)
|
||||||
|
{
|
||||||
|
auto lower = boost::lexical_cast<int>(rangeParts[0]);
|
||||||
|
auto upper = boost::lexical_cast<int>(rangeParts[1]);
|
||||||
|
addRange(lower, upper);
|
||||||
|
}
|
||||||
|
else if(rangeParts.size() == 1)
|
||||||
|
{
|
||||||
|
auto val = boost::lexical_cast<int>(rangeParts.front());
|
||||||
|
addNumber(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::serializeJson(JsonSerializeFormat & handler)
|
||||||
|
{
|
||||||
|
handler.serializeString("name", name);
|
||||||
|
serializeSize(handler, minSize, "minSize");
|
||||||
|
serializeSize(handler, maxSize, "maxSize");
|
||||||
|
serializePlayers(handler, players, "players");
|
||||||
|
serializePlayers(handler, cpuPlayers, "cpu");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto connectionsData = handler.enterArray("connections");
|
||||||
|
connectionsData.serializeStruct(connections);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto zonesData = handler.enterStruct("zones");
|
||||||
|
if(handler.saving)
|
||||||
|
{
|
||||||
|
for(auto & idAndZone : zones)
|
||||||
|
{
|
||||||
|
auto guard = handler.enterStruct(encodeZoneId(idAndZone.first));
|
||||||
|
idAndZone.second->serializeJson(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(auto & idAndZone : zonesData->getCurrent().Struct())
|
||||||
|
{
|
||||||
|
auto guard = handler.enterStruct(idAndZone.first);
|
||||||
|
auto zone = std::make_shared<ZoneOptions>();
|
||||||
|
zone->setId(decodeZoneId(idAndZone.first));
|
||||||
|
zone->serializeJson(handler);
|
||||||
|
zones[zone->getId()] = zone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!handler.saving)
|
||||||
|
afterLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::afterLoad()
|
||||||
|
{
|
||||||
|
for(auto & idAndZone : zones)
|
||||||
|
{
|
||||||
|
auto zone = idAndZone.second;
|
||||||
|
if(zone->getMinesLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
const auto otherZone = zones.at(zone->getMinesLikeZone());
|
||||||
|
zone->setMinesInfo(otherZone->getMinesInfo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(zone->getTerrainTypeLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
const auto otherZone = zones.at(zone->getTerrainTypeLikeZone());
|
||||||
|
zone->setTerrainTypes(otherZone->getTerrainTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(zone->getTreasureLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
const auto otherZone = zones.at(zone->getTreasureLikeZone());
|
||||||
|
zone->setTreasureInfo(otherZone->getTreasureInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto & connection : connections)
|
||||||
|
{
|
||||||
|
auto id1 = connection.getZoneA();
|
||||||
|
auto id2 = connection.getZoneB();
|
||||||
|
|
||||||
|
auto zone1 = zones.at(id1);
|
||||||
|
auto zone2 = zones.at(id2);
|
||||||
|
|
||||||
|
zone1->addConnection(id2);
|
||||||
|
zone2->addConnection(id1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName)
|
||||||
|
{
|
||||||
|
static const std::map<std::string, int3> sizeMapping =
|
||||||
|
{
|
||||||
|
{"s", { 36, 36, 1}},
|
||||||
|
{"s+u", { 36, 36, 2}},
|
||||||
|
{"m", { 72, 72, 1}},
|
||||||
|
{"m+u", { 72, 72, 2}},
|
||||||
|
{"l", {108, 108, 1}},
|
||||||
|
{"l+u", {108, 108, 2}},
|
||||||
|
{"xl", {144, 144, 1}},
|
||||||
|
{"xl+u", {144, 144, 2}},
|
||||||
|
{"h", {180, 180, 1}},
|
||||||
|
{"h+u", {180, 180, 2}},
|
||||||
|
{"xh", {216, 216, 1}},
|
||||||
|
{"xh+u", {216, 216, 2}},
|
||||||
|
{"g", {252, 252, 1}},
|
||||||
|
{"g+u", {252, 252, 2}}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::map<int3, std::string> sizeReverseMapping = vstd::invertMap(sizeMapping);
|
||||||
|
|
||||||
|
std::string encodedValue;
|
||||||
|
|
||||||
|
if(handler.saving)
|
||||||
|
{
|
||||||
|
auto iter = sizeReverseMapping.find(value);
|
||||||
|
if(iter == sizeReverseMapping.end())
|
||||||
|
encodedValue = boost::str(boost::format("%dx%dx%d") % value.x % value.y % value.z);
|
||||||
|
else
|
||||||
|
encodedValue = iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.serializeString(fieldName, encodedValue);
|
||||||
|
|
||||||
|
if(!handler.saving)
|
||||||
|
{
|
||||||
|
auto iter = sizeMapping.find(encodedValue);
|
||||||
|
|
||||||
|
if(iter == sizeMapping.end())
|
||||||
|
{
|
||||||
|
std::vector<std::string> parts;
|
||||||
|
boost::split(parts, encodedValue, boost::is_any_of("x"));
|
||||||
|
|
||||||
|
value.x = (boost::lexical_cast<int>(parts.at(0)));
|
||||||
|
value.y = (boost::lexical_cast<int>(parts.at(1)));
|
||||||
|
value.z = (boost::lexical_cast<int>(parts.at(2)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = iter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRmgTemplate::serializePlayers(JsonSerializeFormat & handler, CPlayerCountRange & value, const std::string & fieldName)
|
||||||
|
{
|
||||||
|
std::string encodedValue;
|
||||||
|
|
||||||
|
if(handler.saving)
|
||||||
|
encodedValue = value.toString();
|
||||||
|
|
||||||
|
handler.serializeString(fieldName, encodedValue);
|
||||||
|
|
||||||
|
if(!handler.saving)
|
||||||
|
value.fromString(encodedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../int3.h"
|
||||||
#include "../GameConstants.h"
|
#include "../GameConstants.h"
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
#include "CMapGenOptions.h"
|
#include "CMapGenOptions.h"
|
||||||
@ -33,6 +34,11 @@ public:
|
|||||||
ui32 min;
|
ui32 min;
|
||||||
ui32 max;
|
ui32 max;
|
||||||
ui16 density;
|
ui16 density;
|
||||||
|
CTreasureInfo();
|
||||||
|
|
||||||
|
bool operator ==(const CTreasureInfo & other) const;
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace rmg
|
namespace rmg
|
||||||
@ -44,12 +50,10 @@ public:
|
|||||||
ZoneConnection();
|
ZoneConnection();
|
||||||
|
|
||||||
TRmgTemplateZoneId getZoneA() const;
|
TRmgTemplateZoneId getZoneA() const;
|
||||||
void setZoneA(TRmgTemplateZoneId value);
|
|
||||||
TRmgTemplateZoneId getZoneB() const;
|
TRmgTemplateZoneId getZoneB() const;
|
||||||
void setZoneB(TRmgTemplateZoneId value);
|
int getGuardStrength() const;
|
||||||
int getGuardStrength() const; /// Default: 0
|
|
||||||
void setGuardStrength(int value);
|
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
private:
|
private:
|
||||||
TRmgTemplateZoneId zoneA;
|
TRmgTemplateZoneId zoneA;
|
||||||
TRmgTemplateZoneId zoneB;
|
TRmgTemplateZoneId zoneB;
|
||||||
@ -60,23 +64,25 @@ class DLL_LINKAGE ZoneOptions
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const std::set<ETerrainType> DEFAULT_TERRAIN_TYPES;
|
static const std::set<ETerrainType> DEFAULT_TERRAIN_TYPES;
|
||||||
|
static const TRmgTemplateZoneId NO_ZONE;
|
||||||
|
|
||||||
class DLL_LINKAGE CTownInfo
|
class DLL_LINKAGE CTownInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CTownInfo();
|
CTownInfo();
|
||||||
|
|
||||||
int getTownCount() const; /// Default: 0
|
int getTownCount() const;
|
||||||
void setTownCount(int value);
|
int getCastleCount() const;
|
||||||
int getCastleCount() const; /// Default: 0
|
int getTownDensity() const;
|
||||||
void setCastleCount(int value);
|
int getCastleDensity() const;
|
||||||
int getTownDensity() const; /// Default: 0
|
|
||||||
void setTownDensity(int value);
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
int getCastleDensity() const; /// Default: 0
|
|
||||||
void setCastleDensity(int value);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int townCount, castleCount, townDensity, castleDensity;
|
int townCount;
|
||||||
|
int castleCount;
|
||||||
|
int townDensity;
|
||||||
|
int castleDensity;
|
||||||
};
|
};
|
||||||
|
|
||||||
ZoneOptions();
|
ZoneOptions();
|
||||||
@ -86,44 +92,34 @@ public:
|
|||||||
TRmgTemplateZoneId getId() const;
|
TRmgTemplateZoneId getId() const;
|
||||||
void setId(TRmgTemplateZoneId value);
|
void setId(TRmgTemplateZoneId value);
|
||||||
|
|
||||||
ETemplateZoneType::ETemplateZoneType getType() const; /// Default: ETemplateZoneType::PLAYER_START
|
ETemplateZoneType::ETemplateZoneType getType() const;
|
||||||
void setType(ETemplateZoneType::ETemplateZoneType value);
|
int getSize() const;
|
||||||
|
|
||||||
int getSize() const; /// Default: 1
|
|
||||||
void setSize(int value);
|
void setSize(int value);
|
||||||
|
|
||||||
boost::optional<int> getOwner() const;
|
boost::optional<int> getOwner() const;
|
||||||
void setOwner(boost::optional<int> value);
|
|
||||||
|
|
||||||
const CTownInfo & getPlayerTowns() const;
|
const std::set<ETerrainType> & getTerrainTypes() const;
|
||||||
void setPlayerTowns(const CTownInfo & value);
|
|
||||||
const CTownInfo & getNeutralTowns() const;
|
|
||||||
void setNeutralTowns(const CTownInfo & value);
|
|
||||||
|
|
||||||
bool getMatchTerrainToTown() const; /// Default: true
|
|
||||||
void setMatchTerrainToTown(bool value);
|
|
||||||
|
|
||||||
const std::set<ETerrainType> & getTerrainTypes() const; /// Default: all
|
|
||||||
void setTerrainTypes(const std::set<ETerrainType> & value);
|
void setTerrainTypes(const std::set<ETerrainType> & value);
|
||||||
|
|
||||||
bool getTownsAreSameType() const; /// Default: false
|
|
||||||
void setTownsAreSameType(bool value);
|
|
||||||
|
|
||||||
std::set<TFaction> getDefaultTownTypes() const;
|
std::set<TFaction> getDefaultTownTypes() const;
|
||||||
|
const std::set<TFaction> & getTownTypes() const;
|
||||||
|
|
||||||
const std::set<TFaction> & getTownTypes() const; /// Default: all
|
|
||||||
void setTownTypes(const std::set<TFaction> & value);
|
void setTownTypes(const std::set<TFaction> & value);
|
||||||
void setMonsterTypes(const std::set<TFaction> & value);
|
void setMonsterTypes(const std::set<TFaction> & value);
|
||||||
|
|
||||||
void setMonsterStrength(EMonsterStrength::EMonsterStrength val);
|
void setMinesInfo(const std::map<TResource, ui16> & value);
|
||||||
|
|
||||||
void setMinesAmount (TResource res, ui16 amount);
|
|
||||||
std::map<TResource, ui16> getMinesInfo() const;
|
std::map<TResource, ui16> getMinesInfo() const;
|
||||||
|
|
||||||
void addTreasureInfo(const CTreasureInfo & info);
|
void setTreasureInfo(const std::vector<CTreasureInfo> & value);
|
||||||
const std::vector<CTreasureInfo> & getTreasureInfo() const;
|
const std::vector<CTreasureInfo> & getTreasureInfo() const;
|
||||||
|
|
||||||
|
TRmgTemplateZoneId getMinesLikeZone() const;
|
||||||
|
TRmgTemplateZoneId getTerrainTypeLikeZone() const;
|
||||||
|
TRmgTemplateZoneId getTreasureLikeZone() const;
|
||||||
|
|
||||||
void addConnection(TRmgTemplateZoneId otherZone);
|
void addConnection(TRmgTemplateZoneId otherZone);
|
||||||
|
std::vector<TRmgTemplateZoneId> getConnections() const;
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TRmgTemplateZoneId id;
|
TRmgTemplateZoneId id;
|
||||||
@ -146,6 +142,10 @@ protected:
|
|||||||
std::vector<CTreasureInfo> treasureInfo;
|
std::vector<CTreasureInfo> treasureInfo;
|
||||||
|
|
||||||
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
|
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
|
||||||
|
|
||||||
|
TRmgTemplateZoneId minesLikeZone;
|
||||||
|
TRmgTemplateZoneId terrainTypeLikeZone;
|
||||||
|
TRmgTemplateZoneId treasureLikeZone;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -154,27 +154,9 @@ protected:
|
|||||||
class DLL_LINKAGE CRmgTemplate
|
class DLL_LINKAGE CRmgTemplate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class CSize
|
using Zones = std::map<TRmgTemplateZoneId, std::shared_ptr<rmg::ZoneOptions>>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
CSize();
|
|
||||||
CSize(int width, int height, bool under);
|
|
||||||
|
|
||||||
int getWidth() const; /// Default: CMapHeader::MAP_SIZE_MIDDLE
|
class DLL_LINKAGE CPlayerCountRange
|
||||||
void setWidth(int value);
|
|
||||||
int getHeight() const; /// Default: CMapHeader::MAP_SIZE_MIDDLE
|
|
||||||
void setHeight(int value);
|
|
||||||
bool getUnder() const; /// Default: true
|
|
||||||
void setUnder(bool value);
|
|
||||||
bool operator<=(const CSize & value) const;
|
|
||||||
bool operator>=(const CSize & value) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int width, height;
|
|
||||||
bool under;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CPlayerCountRange
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void addRange(int lower, int upper);
|
void addRange(int lower, int upper);
|
||||||
@ -182,34 +164,39 @@ public:
|
|||||||
bool isInRange(int count) const;
|
bool isInRange(int count) const;
|
||||||
std::set<int> getNumbers() const;
|
std::set<int> getNumbers() const;
|
||||||
|
|
||||||
|
std::string toString() const;
|
||||||
|
void fromString(const std::string & value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<std::pair<int, int> > range;
|
std::vector<std::pair<int, int> > range;
|
||||||
};
|
};
|
||||||
|
|
||||||
CRmgTemplate();
|
CRmgTemplate();
|
||||||
~CRmgTemplate();
|
~CRmgTemplate();
|
||||||
|
|
||||||
|
bool matchesSize(const int3 & value) const;
|
||||||
|
|
||||||
|
void setId(const std::string & value);
|
||||||
const std::string & getName() const;
|
const std::string & getName() const;
|
||||||
void setName(const std::string & value);
|
|
||||||
const CSize & getMinSize() const;
|
|
||||||
void setMinSize(const CSize & value);
|
|
||||||
const CSize & getMaxSize() const;
|
|
||||||
void setMaxSize(const CSize & value);
|
|
||||||
const CPlayerCountRange & getPlayers() const;
|
const CPlayerCountRange & getPlayers() const;
|
||||||
void setPlayers(const CPlayerCountRange & value);
|
|
||||||
const CPlayerCountRange & getCpuPlayers() const;
|
const CPlayerCountRange & getCpuPlayers() const;
|
||||||
void setCpuPlayers(const CPlayerCountRange & value);
|
const Zones & getZones() const;
|
||||||
const std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> & getZones() const;
|
const std::vector<rmg::ZoneConnection> & getConnections() const;
|
||||||
void setZones(const std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> & value);
|
|
||||||
const std::list<rmg::ZoneConnection> & getConnections() const;
|
|
||||||
void setConnections(const std::list<rmg::ZoneConnection> & value);
|
|
||||||
|
|
||||||
void validate() const; /// Tests template on validity and throws exception on failure
|
void validate() const; /// Tests template on validity and throws exception on failure
|
||||||
|
|
||||||
|
void serializeJson(JsonSerializeFormat & handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string id;
|
||||||
std::string name;
|
std::string name;
|
||||||
CSize minSize, maxSize;
|
int3 minSize, maxSize;
|
||||||
CPlayerCountRange players, cpuPlayers;
|
CPlayerCountRange players, cpuPlayers;
|
||||||
std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> zones;
|
Zones zones;
|
||||||
std::list<rmg::ZoneConnection> connections;
|
std::vector<rmg::ZoneConnection> connections;
|
||||||
|
|
||||||
|
void afterLoad();
|
||||||
|
void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName);
|
||||||
|
void serializePlayers(JsonSerializeFormat & handler, CPlayerCountRange & value, const std::string & fieldName);
|
||||||
};
|
};
|
||||||
|
@ -9,16 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CRmgTemplateStorage.h"
|
|
||||||
|
|
||||||
#include "../filesystem/Filesystem.h"
|
#include "CRmgTemplateStorage.h"
|
||||||
#include "../JsonNode.h"
|
#include "CRmgTemplate.h"
|
||||||
#include "../mapping/CMap.h"
|
|
||||||
#include "../VCMI_Lib.h"
|
#include "../serializer/JsonDeserializer.h"
|
||||||
#include "../CModHandler.h"
|
|
||||||
#include "../CTownHandler.h"
|
|
||||||
#include "../GameConstants.h"
|
|
||||||
#include "../StringConstants.h"
|
|
||||||
|
|
||||||
using namespace rmg;
|
using namespace rmg;
|
||||||
|
|
||||||
@ -38,198 +33,12 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
|
|||||||
auto tpl = new CRmgTemplate();
|
auto tpl = new CRmgTemplate();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto & templateNode = data;
|
JsonDeserializer handler(nullptr, data);
|
||||||
if (!templateNode["name"].isNull())
|
auto fullKey = normalizeIdentifier(scope, "core", name);
|
||||||
tpl->setName(templateNode["name"].String()); //name can be customised. Allow duplicated names for different template versions.
|
tpl->setId(name);
|
||||||
else
|
tpl->serializeJson(handler);
|
||||||
tpl->setName(name); //identifier becomes default name
|
|
||||||
|
|
||||||
// Parse main template data
|
|
||||||
tpl->setMinSize(parseMapTemplateSize(templateNode["minSize"].String()));
|
|
||||||
tpl->setMaxSize(parseMapTemplateSize(templateNode["maxSize"].String()));
|
|
||||||
tpl->setPlayers(parsePlayers(templateNode["players"].String()));
|
|
||||||
tpl->setCpuPlayers(parsePlayers(templateNode["cpu"].String()));
|
|
||||||
|
|
||||||
// Parse zones
|
|
||||||
std::map<TRmgTemplateZoneId, ZoneOptions *> zones;
|
|
||||||
for (const auto & zonePair : templateNode["zones"].Struct())
|
|
||||||
{
|
|
||||||
auto zone = new ZoneOptions();
|
|
||||||
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
|
|
||||||
zone->setId(zoneId);
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
zone->setPlayerTowns(parseTemplateZoneTowns(zoneNode["playerTowns"]));
|
|
||||||
zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
|
|
||||||
if (!zoneNode["matchTerrainToTown"].isNull()) //default : true
|
|
||||||
zone->setMatchTerrainToTown(zoneNode["matchTerrainToTown"].Bool());
|
|
||||||
zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), ZoneOptions::DEFAULT_TERRAIN_TYPES));
|
|
||||||
|
|
||||||
if (!zoneNode["townsAreSameType"].isNull()) //default : false
|
|
||||||
zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
std::set<TFaction> allowedTownTypes;
|
|
||||||
if (i)
|
|
||||||
{
|
|
||||||
if (zoneNode["allowedTowns"].isNull())
|
|
||||||
allowedTownTypes = zone->getDefaultTownTypes();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (zoneNode["allowedMonsters"].isNull())
|
|
||||||
allowedTownTypes = VLC->townh->getAllowedFactions(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allowedTownTypes.empty())
|
|
||||||
{
|
|
||||||
for (const JsonNode & allowedTown : zoneNode[i ? "allowedTowns" : "allowedMonsters"].Vector())
|
|
||||||
{
|
|
||||||
//complain if the town type is not present in our game
|
|
||||||
if (auto id = VLC->modh->identifiers.getIdentifier("faction", allowedTown, false))
|
|
||||||
allowedTownTypes.insert(id.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zoneNode[i ? "bannedTowns" : "bannedMonsters"].isNull())
|
|
||||||
{
|
|
||||||
for (const JsonNode & bannedTown : zoneNode[i ? "bannedTowns" : "bannedMonsters"].Vector())
|
|
||||||
{
|
|
||||||
//erase unindentified towns silently
|
|
||||||
if (auto id = VLC->modh->identifiers.getIdentifier("faction", bannedTown, true))
|
|
||||||
vstd::erase_if_present(allowedTownTypes, id.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i)
|
|
||||||
zone->setTownTypes(allowedTownTypes);
|
|
||||||
else
|
|
||||||
zone->setMonsterTypes(allowedTownTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string monsterStrength = zoneNode["monsters"].String();
|
|
||||||
if (monsterStrength == "weak")
|
|
||||||
zone->setMonsterStrength(EMonsterStrength::ZONE_WEAK);
|
|
||||||
else if (monsterStrength == "normal")
|
|
||||||
zone->setMonsterStrength(EMonsterStrength::ZONE_NORMAL);
|
|
||||||
else if (monsterStrength == "strong")
|
|
||||||
zone->setMonsterStrength(EMonsterStrength::ZONE_STRONG);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete zone;
|
|
||||||
throw (std::runtime_error("incorrect monster power"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zoneNode["mines"].isNull())
|
|
||||||
{
|
|
||||||
auto mines = zoneNode["mines"].Struct();
|
|
||||||
//FIXME: maybe there is a smarter way to parse it already?
|
|
||||||
zone->setMinesAmount(Res::WOOD, mines["wood"].Float());
|
|
||||||
zone->setMinesAmount(Res::ORE, mines["ore"].Float());
|
|
||||||
zone->setMinesAmount(Res::GEMS, mines["gems"].Float());
|
|
||||||
zone->setMinesAmount(Res::CRYSTAL, mines["crystal"].Float());
|
|
||||||
zone->setMinesAmount(Res::SULFUR, mines["sulfur"].Float());
|
|
||||||
zone->setMinesAmount(Res::MERCURY, mines["mercury"].Float());
|
|
||||||
zone->setMinesAmount(Res::GOLD, mines["gold"].Float());
|
|
||||||
//TODO: Mithril
|
|
||||||
}
|
|
||||||
|
|
||||||
//treasures
|
|
||||||
if (!zoneNode["treasure"].isNull())
|
|
||||||
{
|
|
||||||
//TODO: parse vector of different treasure settings
|
|
||||||
if (zoneNode["treasure"].getType() == JsonNode::JsonType::DATA_STRUCT)
|
|
||||||
{
|
|
||||||
auto treasureInfo = zoneNode["treasure"].Struct();
|
|
||||||
{
|
|
||||||
CTreasureInfo ti;
|
|
||||||
ti.min = treasureInfo["min"].Float();
|
|
||||||
ti.max = treasureInfo["max"].Float();
|
|
||||||
ti.density = treasureInfo["density"].Float(); //TODO: use me
|
|
||||||
zone->addTreasureInfo(ti);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (zoneNode["treasure"].getType() == JsonNode::JsonType::DATA_VECTOR)
|
|
||||||
{
|
|
||||||
for (auto treasureInfo : zoneNode["treasure"].Vector())
|
|
||||||
{
|
|
||||||
CTreasureInfo ti;
|
|
||||||
ti.min = treasureInfo["min"].Float();
|
|
||||||
ti.max = treasureInfo["max"].Float();
|
|
||||||
ti.density = treasureInfo["density"].Float();
|
|
||||||
zone->addTreasureInfo(ti);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
zones[zone->getId()] = zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy settings from already parsed zones
|
|
||||||
for (const auto & zonePair : templateNode["zones"].Struct())
|
|
||||||
{
|
|
||||||
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
|
|
||||||
auto zone = zones[zoneId];
|
|
||||||
|
|
||||||
const auto & zoneNode = zonePair.second;
|
|
||||||
|
|
||||||
if (!zoneNode["terrainTypeLikeZone"].isNull())
|
|
||||||
{
|
|
||||||
int id = zoneNode["terrainTypeLikeZone"].Float();
|
|
||||||
zone->setTerrainTypes(zones[id]->getTerrainTypes());
|
|
||||||
zone->setMatchTerrainToTown(zones[id]->getMatchTerrainToTown());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zoneNode["townTypeLikeZone"].isNull())
|
|
||||||
zone->setTownTypes (zones[zoneNode["townTypeLikeZone"].Float()]->getTownTypes());
|
|
||||||
|
|
||||||
if (!zoneNode["treasureLikeZone"].isNull())
|
|
||||||
{
|
|
||||||
for (auto treasureInfo : zones[zoneNode["treasureLikeZone"].Float()]->getTreasureInfo())
|
|
||||||
{
|
|
||||||
zone->addTreasureInfo(treasureInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zoneNode["minesLikeZone"].isNull())
|
|
||||||
{
|
|
||||||
for (auto mineInfo : zones[zoneNode["minesLikeZone"].Float()]->getMinesInfo())
|
|
||||||
{
|
|
||||||
zone->setMinesAmount (mineInfo.first, mineInfo.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tpl->setZones(zones);
|
|
||||||
|
|
||||||
// Parse connections
|
|
||||||
std::list<ZoneConnection> connections;
|
|
||||||
for(const auto & connPair : templateNode["connections"].Vector())
|
|
||||||
{
|
|
||||||
ZoneConnection conn;
|
|
||||||
conn.setZoneA(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["a"].String()))->second->getId());
|
|
||||||
conn.setZoneB(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["b"].String()))->second->getId());
|
|
||||||
conn.setGuardStrength(connPair["guard"].Float());
|
|
||||||
connections.push_back(conn);
|
|
||||||
}
|
|
||||||
tpl->setConnections(connections);
|
|
||||||
{
|
|
||||||
auto zones = tpl->getZones();
|
|
||||||
for (auto con : tpl->getConnections())
|
|
||||||
{
|
|
||||||
auto idA = con.getZoneA();
|
|
||||||
auto idB = con.getZoneB();
|
|
||||||
zones[idA]->addConnection(idB);
|
|
||||||
zones[idB]->addConnection(idA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tpl->validate();
|
tpl->validate();
|
||||||
templates[tpl->getName()] = tpl;
|
templates[fullKey] = tpl;
|
||||||
}
|
}
|
||||||
catch(const std::exception & e)
|
catch(const std::exception & e)
|
||||||
{
|
{
|
||||||
@ -237,142 +46,8 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CRmgTemplate::CSize CRmgTemplateStorage::parseMapTemplateSize(const std::string & text) const
|
|
||||||
{
|
|
||||||
CRmgTemplate::CSize size;
|
|
||||||
if(text.empty()) return size;
|
|
||||||
|
|
||||||
std::vector<std::string> parts;
|
|
||||||
boost::split(parts, text, boost::is_any_of("+"));
|
|
||||||
static const std::map<std::string, int> mapSizeMapping =
|
|
||||||
{
|
|
||||||
{"s", CMapHeader::MAP_SIZE_SMALL},
|
|
||||||
{"m", CMapHeader::MAP_SIZE_MIDDLE},
|
|
||||||
{"l", CMapHeader::MAP_SIZE_LARGE},
|
|
||||||
{"xl", CMapHeader::MAP_SIZE_XLARGE},
|
|
||||||
};
|
|
||||||
auto it = mapSizeMapping.find(parts[0]);
|
|
||||||
if(it == mapSizeMapping.end())
|
|
||||||
{
|
|
||||||
// Map size is given as a number representation
|
|
||||||
const std::string numericalRep = parts[0];
|
|
||||||
parts.clear();
|
|
||||||
boost::split(parts, numericalRep, boost::is_any_of("x"));
|
|
||||||
assert(parts.size() == 3);
|
|
||||||
size.setWidth(boost::lexical_cast<int>(parts[0]));
|
|
||||||
size.setHeight(boost::lexical_cast<int>(parts[1]));
|
|
||||||
size.setUnder(boost::lexical_cast<int>(parts[2]) == 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size.setWidth(it->second);
|
|
||||||
size.setHeight(it->second);
|
|
||||||
size.setUnder(parts.size() > 1 ? parts[1] == std::string("u") : false);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
ETemplateZoneType::ETemplateZoneType CRmgTemplateStorage::parseZoneType(const std::string & type) const
|
|
||||||
{
|
|
||||||
static const std::map<std::string, ETemplateZoneType::ETemplateZoneType> zoneTypeMapping =
|
|
||||||
{
|
|
||||||
{"playerStart", ETemplateZoneType::PLAYER_START},
|
|
||||||
{"cpuStart", ETemplateZoneType::CPU_START},
|
|
||||||
{"treasure", ETemplateZoneType::TREASURE},
|
|
||||||
{"junction", ETemplateZoneType::JUNCTION},
|
|
||||||
};
|
|
||||||
auto it = zoneTypeMapping.find(type);
|
|
||||||
if(it == zoneTypeMapping.end()) throw std::runtime_error("Zone type unknown.");
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZoneOptions::CTownInfo CRmgTemplateStorage::parseTemplateZoneTowns(const JsonNode & node) const
|
|
||||||
{
|
|
||||||
ZoneOptions::CTownInfo towns;
|
|
||||||
towns.setTownCount(node["towns"].Float());
|
|
||||||
towns.setCastleCount(node["castles"].Float());
|
|
||||||
towns.setTownDensity(node["townDensity"].Float());
|
|
||||||
towns.setCastleDensity(node["castleDensity"].Float());
|
|
||||||
return towns;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<TFaction> CRmgTemplateStorage::parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const
|
|
||||||
{
|
|
||||||
std::set<TFaction> townTypes;
|
|
||||||
for(const auto & townTypeNode : townTypesVector)
|
|
||||||
{
|
|
||||||
auto townTypeStr = townTypeNode.String();
|
|
||||||
if(townTypeStr == "all") return defaultTownTypes;
|
|
||||||
|
|
||||||
bool foundFaction = false;
|
|
||||||
for(auto factionPtr : VLC->townh->factions)
|
|
||||||
{
|
|
||||||
if(factionPtr->town != nullptr && townTypeStr == factionPtr->name)
|
|
||||||
{
|
|
||||||
townTypes.insert(factionPtr->index);
|
|
||||||
foundFaction = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundFaction) throw std::runtime_error("Given faction is invalid.");
|
|
||||||
}
|
|
||||||
return townTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<ETerrainType> CRmgTemplateStorage::parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const
|
|
||||||
{
|
|
||||||
std::set<ETerrainType> terTypes;
|
|
||||||
if (terTypeStrings.empty()) //nothing was specified
|
|
||||||
return defaultTerrainTypes;
|
|
||||||
|
|
||||||
for(const auto & node : terTypeStrings)
|
|
||||||
{
|
|
||||||
const auto & terTypeStr = node.String();
|
|
||||||
if(terTypeStr == "all") return defaultTerrainTypes;
|
|
||||||
auto pos = vstd::find_pos(GameConstants::TERRAIN_NAMES, terTypeStr);
|
|
||||||
if (pos != -1)
|
|
||||||
{
|
|
||||||
terTypes.insert(ETerrainType(pos));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Terrain type is invalid.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return terTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRmgTemplate::CPlayerCountRange CRmgTemplateStorage::parsePlayers(const std::string & players) const
|
|
||||||
{
|
|
||||||
CRmgTemplate::CPlayerCountRange playerRange;
|
|
||||||
if(players.empty())
|
|
||||||
{
|
|
||||||
playerRange.addNumber(0);
|
|
||||||
return playerRange;
|
|
||||||
}
|
|
||||||
std::vector<std::string> commaParts;
|
|
||||||
boost::split(commaParts, players, boost::is_any_of(","));
|
|
||||||
for(const auto & commaPart : commaParts)
|
|
||||||
{
|
|
||||||
std::vector<std::string> rangeParts;
|
|
||||||
boost::split(rangeParts, commaPart, boost::is_any_of("-"));
|
|
||||||
if(rangeParts.size() == 2)
|
|
||||||
{
|
|
||||||
auto lower = boost::lexical_cast<int>(rangeParts[0]);
|
|
||||||
auto upper = boost::lexical_cast<int>(rangeParts[1]);
|
|
||||||
playerRange.addRange(lower, upper);
|
|
||||||
}
|
|
||||||
else if(rangeParts.size() == 1)
|
|
||||||
{
|
|
||||||
auto val = boost::lexical_cast<int>(rangeParts.front());
|
|
||||||
playerRange.addNumber(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return playerRange;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRmgTemplateStorage::CRmgTemplateStorage()
|
CRmgTemplateStorage::CRmgTemplateStorage()
|
||||||
{
|
{
|
||||||
//TODO: load all
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CRmgTemplateStorage::~CRmgTemplateStorage()
|
CRmgTemplateStorage::~CRmgTemplateStorage()
|
||||||
|
@ -10,12 +10,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CRmgTemplate.h"
|
|
||||||
#include "../IHandlerBase.h"
|
#include "../IHandlerBase.h"
|
||||||
|
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
|
class CRmgTemplate;
|
||||||
typedef std::vector<JsonNode> JsonVector;
|
|
||||||
|
|
||||||
/// 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
|
||||||
@ -34,14 +32,6 @@ public:
|
|||||||
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;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRmgTemplate::CSize parseMapTemplateSize(const std::string & text) const;
|
|
||||||
rmg::ZoneOptions::CTownInfo parseTemplateZoneTowns(const JsonNode & node) const;
|
|
||||||
ETemplateZoneType::ETemplateZoneType parseZoneType(const std::string & type) const;
|
|
||||||
std::set<TFaction> parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const;
|
|
||||||
std::set<ETerrainType> parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const;
|
|
||||||
CRmgTemplate::CPlayerCountRange parsePlayers(const std::string & players) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::map<std::string, CRmgTemplate *> templates;
|
std::map<std::string, CRmgTemplate *> templates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ CRmgTemplateZone::CRmgTemplateZone()
|
|||||||
townType(ETownType::NEUTRAL),
|
townType(ETownType::NEUTRAL),
|
||||||
terrainType (ETerrainType::GRASS),
|
terrainType (ETerrainType::GRASS),
|
||||||
minGuardedValue(0),
|
minGuardedValue(0),
|
||||||
questArtZone(nullptr),
|
questArtZone(),
|
||||||
gen(nullptr)
|
gen(nullptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -124,16 +124,11 @@ void CRmgTemplateZone::setGenPtr(CMapGenerator * Gen)
|
|||||||
gen = Gen;
|
gen = Gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRmgTemplateZone::setQuestArtZone(CRmgTemplateZone * otherZone)
|
void CRmgTemplateZone::setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone)
|
||||||
{
|
{
|
||||||
questArtZone = otherZone;
|
questArtZone = otherZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TRmgTemplateZoneId> CRmgTemplateZone::getConnections() const
|
|
||||||
{
|
|
||||||
return connections;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<int3>* CRmgTemplateZone::getFreePaths()
|
std::set<int3>* CRmgTemplateZone::getFreePaths()
|
||||||
{
|
{
|
||||||
return &freePaths;
|
return &freePaths;
|
||||||
@ -2488,7 +2483,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
|||||||
|
|
||||||
//seer huts with creatures or generic rewards
|
//seer huts with creatures or generic rewards
|
||||||
|
|
||||||
if (questArtZone) //we won't be placing seer huts if there is no zone left to place arties
|
if(questArtZone.lock()) //we won't be placing seer huts if there is no zone left to place arties
|
||||||
{
|
{
|
||||||
static const int genericSeerHuts = 8;
|
static const int genericSeerHuts = 8;
|
||||||
int seerHutsPerType = 0;
|
int seerHutsPerType = 0;
|
||||||
@ -2549,7 +2544,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
|||||||
|
|
||||||
gen->banQuestArt(artid);
|
gen->banQuestArt(artid);
|
||||||
|
|
||||||
this->questArtZone->possibleObjects.push_back (generateArtInfo(artid));
|
this->questArtZone.lock()->possibleObjects.push_back (generateArtInfo(artid));
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
@ -2587,7 +2582,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
|||||||
|
|
||||||
gen->banQuestArt(artid);
|
gen->banQuestArt(artid);
|
||||||
|
|
||||||
this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
|
this->questArtZone.lock()->possibleObjects.push_back(generateArtInfo(artid));
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
@ -2610,7 +2605,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
|||||||
|
|
||||||
gen->banQuestArt(artid);
|
gen->banQuestArt(artid);
|
||||||
|
|
||||||
this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
|
this->questArtZone.lock()->possibleObjects.push_back(generateArtInfo(artid));
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
@ -136,8 +136,7 @@ public:
|
|||||||
std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object);
|
std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object);
|
||||||
bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;
|
bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;
|
||||||
|
|
||||||
void setQuestArtZone(CRmgTemplateZone * otherZone);
|
void setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone);
|
||||||
std::vector<TRmgTemplateZoneId> getConnections() const;
|
|
||||||
std::set<int3>* getFreePaths();
|
std::set<int3>* getFreePaths();
|
||||||
|
|
||||||
ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
|
ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
|
||||||
@ -166,7 +165,7 @@ private:
|
|||||||
|
|
||||||
si32 townType;
|
si32 townType;
|
||||||
ETerrainType terrainType;
|
ETerrainType terrainType;
|
||||||
CRmgTemplateZone * questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
|
std::weak_ptr<CRmgTemplateZone> questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
|
||||||
|
|
||||||
std::vector<ObjectInfo> possibleObjects;
|
std::vector<ObjectInfo> possibleObjects;
|
||||||
int minGuardedValue;
|
int minGuardedValue;
|
||||||
|
@ -18,11 +18,6 @@
|
|||||||
|
|
||||||
class CRandomGenerator;
|
class CRandomGenerator;
|
||||||
|
|
||||||
CPlacedZone::CPlacedZone(const CRmgTemplateZone * zone)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CZonePlacer::CZonePlacer(CMapGenerator * Gen)
|
CZonePlacer::CZonePlacer(CMapGenerator * Gen)
|
||||||
: width(0), height(0), scaleX(0), scaleY(0), mapSize(0), gravityConstant(0), stiffnessConstant(0),
|
: width(0), height(0), scaleX(0), scaleY(0), mapSize(0), gravityConstant(0), stiffnessConstant(0),
|
||||||
gen(Gen)
|
gen(Gen)
|
||||||
@ -78,7 +73,7 @@ void CZonePlacer::placeZones(const CMapGenOptions * mapGenOptions, CRandomGenera
|
|||||||
float bestTotalDistance = 1e10;
|
float bestTotalDistance = 1e10;
|
||||||
float bestTotalOverlap = 1e10;
|
float bestTotalOverlap = 1e10;
|
||||||
|
|
||||||
std::map<CRmgTemplateZone *, float3> bestSolution;
|
std::map<std::shared_ptr<CRmgTemplateZone>, float3> bestSolution;
|
||||||
|
|
||||||
TForceVector forces;
|
TForceVector forces;
|
||||||
TForceVector totalForces; // both attraction and pushback, overcomplicated?
|
TForceVector totalForces; // both attraction and pushback, overcomplicated?
|
||||||
@ -359,7 +354,7 @@ void CZonePlacer::moveOneZone(TZoneMap &zones, TForceVector &totalForces, TDista
|
|||||||
{
|
{
|
||||||
float maxRatio = 0;
|
float maxRatio = 0;
|
||||||
const int maxDistanceMovementRatio = zones.size() * zones.size(); //experimental - the more zones, the greater total distance expected
|
const int maxDistanceMovementRatio = zones.size() * zones.size(); //experimental - the more zones, the greater total distance expected
|
||||||
CRmgTemplateZone * misplacedZone = nullptr;
|
std::shared_ptr<CRmgTemplateZone> misplacedZone;
|
||||||
|
|
||||||
float totalDistance = 0;
|
float totalDistance = 0;
|
||||||
float totalOverlap = 0;
|
float totalOverlap = 0;
|
||||||
@ -379,7 +374,7 @@ void CZonePlacer::moveOneZone(TZoneMap &zones, TForceVector &totalForces, TDista
|
|||||||
|
|
||||||
if (maxRatio > maxDistanceMovementRatio && misplacedZone)
|
if (maxRatio > maxDistanceMovementRatio && misplacedZone)
|
||||||
{
|
{
|
||||||
CRmgTemplateZone * targetZone = nullptr;
|
std::shared_ptr<CRmgTemplateZone> targetZone;
|
||||||
float3 ourCenter = misplacedZone->getCenter();
|
float3 ourCenter = misplacedZone->getCenter();
|
||||||
|
|
||||||
if (totalDistance > totalOverlap)
|
if (totalDistance > totalOverlap)
|
||||||
@ -471,7 +466,7 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
|||||||
|
|
||||||
auto zones = gen->getZones();
|
auto zones = gen->getZones();
|
||||||
|
|
||||||
typedef std::pair<CRmgTemplateZone *, float> Dpair;
|
typedef std::pair<std::shared_ptr<CRmgTemplateZone>, float> Dpair;
|
||||||
std::vector <Dpair> distances;
|
std::vector <Dpair> distances;
|
||||||
distances.reserve(zones.size());
|
distances.reserve(zones.size());
|
||||||
|
|
||||||
@ -483,7 +478,7 @@ void CZonePlacer::assignZones(const CMapGenOptions * mapGenOptions)
|
|||||||
return lhs.second / lhs.first->getSize() < rhs.second / rhs.first->getSize();
|
return lhs.second / lhs.first->getSize() < rhs.second / rhs.first->getSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto moveZoneToCenterOfMass = [](CRmgTemplateZone * zone) -> void
|
auto moveZoneToCenterOfMass = [](std::shared_ptr<CRmgTemplateZone> zone) -> void
|
||||||
{
|
{
|
||||||
int3 total(0, 0, 0);
|
int3 total(0, 0, 0);
|
||||||
auto tiles = zone->getTileInfo();
|
auto tiles = zone->getTileInfo();
|
||||||
|
@ -20,22 +20,10 @@ class CRandomGenerator;
|
|||||||
class CRmgTemplateZone;
|
class CRmgTemplateZone;
|
||||||
class CMapGenerator;
|
class CMapGenerator;
|
||||||
|
|
||||||
typedef std::vector<std::pair<TRmgTemplateZoneId, CRmgTemplateZone*>> TZoneVector;
|
typedef std::vector<std::pair<TRmgTemplateZoneId, std::shared_ptr<CRmgTemplateZone>>> TZoneVector;
|
||||||
typedef std::map <TRmgTemplateZoneId, CRmgTemplateZone*> TZoneMap;
|
typedef std::map <TRmgTemplateZoneId, std::shared_ptr<CRmgTemplateZone>> TZoneMap;
|
||||||
typedef std::map <CRmgTemplateZone *, float3> TForceVector;
|
typedef std::map <std::shared_ptr<CRmgTemplateZone>, float3> TForceVector;
|
||||||
typedef std::map <CRmgTemplateZone *, float> TDistanceVector;
|
typedef std::map <std::shared_ptr<CRmgTemplateZone>, float> TDistanceVector;
|
||||||
|
|
||||||
class CPlacedZone
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit CPlacedZone(const CRmgTemplateZone * Zone);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//const CRmgTemplateZone * zone;
|
|
||||||
|
|
||||||
//TODO exact outline data of zone
|
|
||||||
//TODO perhaps further zone data, guards, obstacles, etc...
|
|
||||||
};
|
|
||||||
|
|
||||||
class CZonePlacer
|
class CZonePlacer
|
||||||
{
|
{
|
||||||
|
@ -232,6 +232,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
///Anything int64-convertible <-> Json integer
|
///Anything int64-convertible <-> Json integer
|
||||||
|
///no default value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void serializeInt(const std::string & fieldName, T & value)
|
void serializeInt(const std::string & fieldName, T & value)
|
||||||
{
|
{
|
||||||
@ -239,12 +240,21 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
///Anything int64-convertible <-> Json integer
|
///Anything int64-convertible <-> Json integer
|
||||||
|
///custom default value
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
void serializeInt(const std::string & fieldName, T & value, const U & defaultValue)
|
void serializeInt(const std::string & fieldName, T & value, const U & defaultValue)
|
||||||
{
|
{
|
||||||
doSerializeInternal<T, U, si64>(fieldName, value, defaultValue);
|
doSerializeInternal<T, U, si64>(fieldName, value, defaultValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///Anything int64-convertible <-> Json integer
|
||||||
|
///default value is boost::none
|
||||||
|
template <typename T>
|
||||||
|
void serializeInt(const std::string & fieldName, boost::optional<T> & value)
|
||||||
|
{
|
||||||
|
dispatchOptional<T, si64>(fieldName, value);
|
||||||
|
};
|
||||||
|
|
||||||
///si32-convertible identifier <-> Json string
|
///si32-convertible identifier <-> Json string
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
void serializeId(const std::string & fieldName, T & value, const U & defaultValue, const TDecoder & decoder, const TEncoder & encoder)
|
void serializeId(const std::string & fieldName, T & value, const U & defaultValue, const TDecoder & decoder, const TEncoder & encoder)
|
||||||
@ -253,14 +263,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
///si32-convertible identifier <-> Json string
|
///si32-convertible identifier <-> Json string
|
||||||
template <typename T, typename U>
|
template <typename T, typename U, typename E = T>
|
||||||
void serializeId(const std::string & fieldName, T & value, const U & defaultValue)
|
void serializeId(const std::string & fieldName, T & value, const U & defaultValue)
|
||||||
{
|
{
|
||||||
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, &T::decode, &T::encode);
|
doSerializeInternal<T, U, si32>(fieldName, value, defaultValue, &E::decode, &E::encode);
|
||||||
}
|
}
|
||||||
|
|
||||||
///si32-convertible identifier vector <-> Json array of string
|
///si32-convertible identifier vector <-> Json array of string
|
||||||
template <typename T, typename U = T>
|
template <typename T, typename E = T>
|
||||||
void serializeIdArray(const std::string & fieldName, std::vector<T> & value)
|
void serializeIdArray(const std::string & fieldName, std::vector<T> & value)
|
||||||
{
|
{
|
||||||
std::vector<si32> temp;
|
std::vector<si32> temp;
|
||||||
@ -276,7 +286,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeInternal(fieldName, temp, &U::decode, &U::encode);
|
serializeInternal(fieldName, temp, &E::decode, &E::encode);
|
||||||
if(!saving)
|
if(!saving)
|
||||||
{
|
{
|
||||||
value.clear();
|
value.clear();
|
||||||
@ -320,6 +330,43 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///si32-convertible identifier set <-> Json array of string
|
||||||
|
template <typename T, typename U = T>
|
||||||
|
void serializeIdArray(const std::string & fieldName, std::set<T> & value, const std::set<T> & defaultValue)
|
||||||
|
{
|
||||||
|
std::vector<si32> temp;
|
||||||
|
|
||||||
|
if(saving && value != defaultValue)
|
||||||
|
{
|
||||||
|
temp.reserve(value.size());
|
||||||
|
|
||||||
|
for(const T & vitem : value)
|
||||||
|
{
|
||||||
|
si32 item = static_cast<si32>(vitem);
|
||||||
|
temp.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeInternal(fieldName, temp, &U::decode, &U::encode);
|
||||||
|
if(!saving)
|
||||||
|
{
|
||||||
|
if(temp.empty())
|
||||||
|
{
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.clear();
|
||||||
|
|
||||||
|
for(const si32 item : temp)
|
||||||
|
{
|
||||||
|
T vitem = static_cast<T>(item);
|
||||||
|
value.insert(vitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///bitmask <-> Json array of string
|
///bitmask <-> Json array of string
|
||||||
template <typename T, int Size>
|
template <typename T, int Size>
|
||||||
void serializeIdArray(const std::string & fieldName, T & value, const T & defaultValue, const TDecoder & decoder, const TEncoder & encoder)
|
void serializeIdArray(const std::string & fieldName, T & value, const T & defaultValue, const TDecoder & decoder, const TEncoder & encoder)
|
||||||
@ -397,6 +444,7 @@ protected:
|
|||||||
virtual void pushStruct(const std::string & fieldName) = 0;
|
virtual void pushStruct(const std::string & fieldName) = 0;
|
||||||
virtual void pushArray(const std::string & fieldName) = 0;
|
virtual void pushArray(const std::string & fieldName) = 0;
|
||||||
virtual void pushArrayElement(const size_t index) = 0;
|
virtual void pushArrayElement(const size_t index) = 0;
|
||||||
|
virtual void pushField(const std::string & fieldName) = 0;
|
||||||
|
|
||||||
virtual void resizeCurrent(const size_t newSize, JsonNode::JsonType type){};
|
virtual void resizeCurrent(const size_t newSize, JsonNode::JsonType type){};
|
||||||
|
|
||||||
@ -406,9 +454,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
const IInstanceResolver * instanceResolver;
|
const IInstanceResolver * instanceResolver;
|
||||||
|
|
||||||
template <typename VType, typename DVType, typename IType, typename... Args>
|
template <typename VType, typename DVType, typename IType, typename... Args>
|
||||||
void doSerializeInternal(const std::string & fieldName, VType & value, const boost::optional<DVType> & defaultValue, Args ... args)
|
void doSerializeInternal(const std::string & fieldName, VType & value, const boost::optional<DVType> & defaultValue, Args ... args)
|
||||||
{
|
{
|
||||||
const boost::optional<IType> tempDefault = defaultValue ? boost::optional<IType>(static_cast<IType>(defaultValue.get())) : boost::none;
|
const boost::optional<IType> tempDefault = defaultValue ? boost::optional<IType>(static_cast<IType>(defaultValue.get())) : boost::none;
|
||||||
IType temp = static_cast<IType>(value);
|
IType temp = static_cast<IType>(value);
|
||||||
|
|
||||||
@ -416,7 +464,39 @@ private:
|
|||||||
|
|
||||||
if(!saving)
|
if(!saving)
|
||||||
value = static_cast<VType>(temp);
|
value = static_cast<VType>(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename VType, typename IType, typename... Args>
|
||||||
|
void dispatchOptional(const std::string & fieldName, boost::optional<VType> & value, Args ... args)
|
||||||
|
{
|
||||||
|
if(saving)
|
||||||
|
{
|
||||||
|
if(value)
|
||||||
|
{
|
||||||
|
IType temp = static_cast<IType>(value.get());
|
||||||
|
pushField(fieldName);
|
||||||
|
serializeInternal(temp, args...);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pushField(fieldName);
|
||||||
|
|
||||||
|
if(getCurrent().getType() == JsonNode::JsonType::DATA_NULL)
|
||||||
|
{
|
||||||
|
value = boost::none;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IType temp = IType();
|
||||||
|
serializeInternal(temp, args...);
|
||||||
|
value = boost::make_optional(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
friend class JsonSerializeHelper;
|
friend class JsonSerializeHelper;
|
||||||
friend class JsonStructSerializer;
|
friend class JsonStructSerializer;
|
||||||
|
@ -69,14 +69,12 @@ void JsonSerializer::serializeInternal(const std::string & fieldName, std::vecto
|
|||||||
|
|
||||||
void JsonSerializer::serializeInternal(std::string & value)
|
void JsonSerializer::serializeInternal(std::string & value)
|
||||||
{
|
{
|
||||||
if(value != "")
|
currentObject->String() = value;
|
||||||
currentObject->String() = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonSerializer::serializeInternal(int64_t & value)
|
void JsonSerializer::serializeInternal(int64_t & value)
|
||||||
{
|
{
|
||||||
if(value != 0)
|
currentObject->Integer() = value;
|
||||||
currentObject->Integer() = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value)
|
void JsonSerializer::serializeLIC(const std::string & fieldName, const TDecoder & decoder, const TEncoder & encoder, const std::vector<bool> & standard, std::vector<bool> & value)
|
||||||
|
@ -54,6 +54,11 @@ protected:
|
|||||||
pushObject(&(currentObject->Vector().at(index)));
|
pushObject(&(currentObject->Vector().at(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pushField(const std::string & fieldName) override
|
||||||
|
{
|
||||||
|
pushObject(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void pushObject(const std::string & fieldName)
|
void pushObject(const std::string & fieldName)
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,8 @@ bool JsonComparer::isEmpty(const JsonNode & value)
|
|||||||
return !value.Bool();
|
return !value.Bool();
|
||||||
case JsonNode::JsonType::DATA_FLOAT:
|
case JsonNode::JsonType::DATA_FLOAT:
|
||||||
return value.Float() == 0;
|
return value.Float() == 0;
|
||||||
|
case JsonNode::JsonType::DATA_INTEGER:
|
||||||
|
return value.Integer() == 0;
|
||||||
case JsonNode::JsonType::DATA_STRING:
|
case JsonNode::JsonType::DATA_STRING:
|
||||||
return value.String() == "";
|
return value.String() == "";
|
||||||
case JsonNode::JsonType::DATA_VECTOR:
|
case JsonNode::JsonType::DATA_VECTOR:
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
<Unit filename="mock/mock_spells_Problem.h" />
|
<Unit filename="mock/mock_spells_Problem.h" />
|
||||||
<Unit filename="mock/mock_spells_Spell.h" />
|
<Unit filename="mock/mock_spells_Spell.h" />
|
||||||
<Unit filename="mock/mock_vstd_RNG.h" />
|
<Unit filename="mock/mock_vstd_RNG.h" />
|
||||||
|
<Unit filename="rmg/CRmgTemplateTest.cpp" />
|
||||||
<Unit filename="spells/AbilityCasterTest.cpp" />
|
<Unit filename="spells/AbilityCasterTest.cpp" />
|
||||||
<Unit filename="spells/TargetConditionTest.cpp" />
|
<Unit filename="spells/TargetConditionTest.cpp" />
|
||||||
<Unit filename="spells/effects/CatapultTest.cpp" />
|
<Unit filename="spells/effects/CatapultTest.cpp" />
|
||||||
@ -137,6 +138,7 @@
|
|||||||
<Unit filename="spells/targetConditions/SpellEffectConditionTest.cpp" />
|
<Unit filename="spells/targetConditions/SpellEffectConditionTest.cpp" />
|
||||||
<Unit filename="spells/targetConditions/TargetConditionItemFixture.cpp" />
|
<Unit filename="spells/targetConditions/TargetConditionItemFixture.cpp" />
|
||||||
<Unit filename="spells/targetConditions/TargetConditionItemFixture.h" />
|
<Unit filename="spells/targetConditions/TargetConditionItemFixture.h" />
|
||||||
|
<Unit filename="testdata/rmg/1.json" />
|
||||||
<Extensions>
|
<Extensions>
|
||||||
<code_completion />
|
<code_completion />
|
||||||
<envvars />
|
<envvars />
|
||||||
|
@ -9,15 +9,15 @@
|
|||||||
*/
|
*/
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
|
|
||||||
#include "../lib/JsonDetail.h"
|
#include "../../lib/JsonDetail.h"
|
||||||
|
|
||||||
#include "../lib/filesystem/CMemoryBuffer.h"
|
#include "../../lib/filesystem/CMemoryBuffer.h"
|
||||||
#include "../lib/filesystem/Filesystem.h"
|
#include "../../lib/filesystem/Filesystem.h"
|
||||||
|
|
||||||
#include "../lib/mapping/CMap.h"
|
#include "../../lib/mapping/CMap.h"
|
||||||
#include "../lib/rmg/CMapGenOptions.h"
|
#include "../../lib/rmg/CMapGenOptions.h"
|
||||||
#include "../lib/rmg/CMapGenerator.h"
|
#include "../../lib/rmg/CMapGenerator.h"
|
||||||
#include "../lib/mapping/MapFormatJson.h"
|
#include "../../lib/mapping/MapFormatJson.h"
|
||||||
|
|
||||||
#include "../lib/VCMIDirs.h"
|
#include "../lib/VCMIDirs.h"
|
||||||
|
|
||||||
|
@ -144,7 +144,6 @@ void checkEqual(const TerrainTile & actual, const TerrainTile & expected)
|
|||||||
|
|
||||||
VCMI_REQUIRE_FIELD_EQUAL(visitable);
|
VCMI_REQUIRE_FIELD_EQUAL(visitable);
|
||||||
VCMI_REQUIRE_FIELD_EQUAL(blocked);
|
VCMI_REQUIRE_FIELD_EQUAL(blocked);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//MapComparer
|
//MapComparer
|
||||||
|
116
test/rmg/CRmgTemplateTest.cpp
Normal file
116
test/rmg/CRmgTemplateTest.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* CRmgTemplateTest.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "StdInc.h"
|
||||||
|
|
||||||
|
#include "../../lib/JsonNode.h"
|
||||||
|
#include "../../lib/filesystem/ResourceID.h"
|
||||||
|
|
||||||
|
#include "../../lib/rmg/CRmgTemplate.h"
|
||||||
|
|
||||||
|
#include "../../lib/serializer/JsonSerializer.h"
|
||||||
|
#include "../../lib/serializer/JsonDeserializer.h"
|
||||||
|
|
||||||
|
#include "../JsonComparer.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
using namespace ::rmg;
|
||||||
|
using namespace ::testing;
|
||||||
|
|
||||||
|
class CRmgTemplateTest : public Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::string TEST_DATA_PATH = "test/rmg/";
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void testLoadSave(const std::string & id, const JsonNode & config)
|
||||||
|
{
|
||||||
|
std::shared_ptr<CRmgTemplate> subject = std::make_shared<CRmgTemplate>();
|
||||||
|
subject->setId(id);
|
||||||
|
|
||||||
|
{
|
||||||
|
JsonDeserializer handler(nullptr, config);
|
||||||
|
subject->serializeJson(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(subject->getName().empty());
|
||||||
|
|
||||||
|
for(const auto & idAndZone : subject->getZones())
|
||||||
|
{
|
||||||
|
auto thisZone = idAndZone.second;
|
||||||
|
if(thisZone->getMinesLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
auto otherZoneId = thisZone->getMinesLikeZone();
|
||||||
|
|
||||||
|
const auto otherZone = subject->getZones().at(otherZoneId);
|
||||||
|
GTEST_ASSERT_NE(otherZone, nullptr);
|
||||||
|
EXPECT_THAT(thisZone->getMinesInfo(), ContainerEq(otherZone->getMinesInfo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(thisZone->getTerrainTypeLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
auto otherZoneId = thisZone->getTerrainTypeLikeZone();
|
||||||
|
|
||||||
|
const auto otherZone = subject->getZones().at(otherZoneId);
|
||||||
|
GTEST_ASSERT_NE(otherZone, nullptr);
|
||||||
|
EXPECT_THAT(thisZone->getTerrainTypes(), ContainerEq(otherZone->getTerrainTypes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(thisZone->getTreasureLikeZone() != ZoneOptions::NO_ZONE)
|
||||||
|
{
|
||||||
|
auto otherZoneId = thisZone->getTreasureLikeZone();
|
||||||
|
|
||||||
|
const auto otherZone = subject->getZones().at(otherZoneId);
|
||||||
|
GTEST_ASSERT_NE(otherZone, nullptr);
|
||||||
|
EXPECT_THAT(thisZone->getTreasureInfo(), ContainerEq(otherZone->getTreasureInfo()));;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto & connection : subject->getConnections())
|
||||||
|
{
|
||||||
|
auto id1 = connection.getZoneA();
|
||||||
|
auto id2 = connection.getZoneB();
|
||||||
|
|
||||||
|
auto zone1 = subject->getZones().at(id1);
|
||||||
|
auto zone2 = subject->getZones().at(id2);
|
||||||
|
|
||||||
|
EXPECT_THAT(zone1->getConnections(), Contains(id2));
|
||||||
|
EXPECT_THAT(zone2->getConnections(), Contains(id1));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode actual(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
|
||||||
|
{
|
||||||
|
JsonSerializer handler(nullptr, actual);
|
||||||
|
subject->serializeJson(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonComparer cmp(false);
|
||||||
|
cmp.compare(id, actual, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CRmgTemplateTest, SerializeCycle)
|
||||||
|
{
|
||||||
|
const std::string testFilePath = TEST_DATA_PATH + "1.json";
|
||||||
|
ResourceID testFileRes(testFilePath);
|
||||||
|
JsonNode testData(testFileRes);
|
||||||
|
|
||||||
|
ASSERT_FALSE((testData.Struct().empty()));
|
||||||
|
|
||||||
|
for(const auto & idAndConfig : testData.Struct())
|
||||||
|
testLoadSave(idAndConfig.first, idAndConfig.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,8 +13,8 @@
|
|||||||
#include "mock/mock_BonusBearer.h"
|
#include "mock/mock_BonusBearer.h"
|
||||||
#include "mock/mock_spells_Spell.h"
|
#include "mock/mock_spells_Spell.h"
|
||||||
|
|
||||||
#include "../../../lib/NetPacksBase.h"
|
#include "../../lib/NetPacksBase.h"
|
||||||
#include "../../../lib/spells/AbilityCaster.h"
|
#include "../../lib/spells/AbilityCaster.h"
|
||||||
|
|
||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
#include <vstd/RNG.h>
|
#include <vstd/RNG.h>
|
||||||
|
|
||||||
#include "../../../lib/NetPacksBase.h"
|
#include "../../lib/NetPacksBase.h"
|
||||||
#include "../../../lib/spells/TargetCondition.h"
|
#include "../../lib/spells/TargetCondition.h"
|
||||||
#include "../../../lib/serializer/JsonDeserializer.h"
|
#include "../../lib/serializer/JsonDeserializer.h"
|
||||||
|
|
||||||
#include "mock/mock_spells_Mechanics.h"
|
#include "mock/mock_spells_Mechanics.h"
|
||||||
#include "mock/mock_BonusBearer.h"
|
#include "mock/mock_BonusBearer.h"
|
||||||
|
216
test/testdata/rmg/1.json
vendored
Normal file
216
test/testdata/rmg/1.json
vendored
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
{
|
||||||
|
"2SM2a" :
|
||||||
|
{
|
||||||
|
"minSize" : "s", "maxSize" : "s+u",
|
||||||
|
"players" : "2",
|
||||||
|
"zones" :
|
||||||
|
{
|
||||||
|
"1" :
|
||||||
|
{
|
||||||
|
"type" : "playerStart",
|
||||||
|
"size" : 11,
|
||||||
|
"owner" : 1,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"playerTowns" : { "castles" : 1 },
|
||||||
|
"mines" : { "wood" : 1, "ore" : 1 },
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 10000, "max" : 15000, "density" : 1 },
|
||||||
|
{ "min" : 3000, "max" : 6000, "density" : 6 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"2" :
|
||||||
|
{
|
||||||
|
"type" : "playerStart",
|
||||||
|
"size" : 59,
|
||||||
|
"owner" : 2,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"playerTowns" : { "castles" : 7 },
|
||||||
|
"minesLikeZone" : 1,
|
||||||
|
"treasureLikeZone" : 1
|
||||||
|
},
|
||||||
|
"3" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 11,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"neutralTowns" : { "towns" : 1 },
|
||||||
|
"matchTerrainToTown" : false,
|
||||||
|
"mines" : { "mercury" : 1, "sulfur" : 1, "gold" : 1 },
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 15000, "max" : 20000, "density" : 1 },
|
||||||
|
{ "min" : 10000, "max" : 15000, "density" : 6 },
|
||||||
|
{ "min" : 3000, "max" : 6000, "density" : 9 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"4" :
|
||||||
|
{
|
||||||
|
"type" : "junction",
|
||||||
|
"size" : 11,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"neutralTowns" : { "towns" : 1 },
|
||||||
|
"matchTerrainToTown" : false,
|
||||||
|
"mines" : { "crystal" : 1, "gems" : 1, "gold" : 1 },
|
||||||
|
"treasureLikeZone" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connections" :
|
||||||
|
[
|
||||||
|
{ "a" : "1", "b" : "3", "guard" : 3000 },
|
||||||
|
{ "a" : "2", "b" : "3", "guard" : 12500 },
|
||||||
|
{ "a" : "2", "b" : "4", "guard" : 123456 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"Midnight Mix" :
|
||||||
|
{
|
||||||
|
"name" : "test name",
|
||||||
|
"minSize" : "l", "maxSize" : "l",
|
||||||
|
"players" : "1,2-4",
|
||||||
|
"cpu" : "1,2",
|
||||||
|
"zones" :
|
||||||
|
{
|
||||||
|
"1" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 12,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "castles" : 1 },
|
||||||
|
"allowedMonsters" : [ "castle", "rampart", "tower", "inferno", "necropolis", "dungeon", "stronghold", "fortress", "neutral" ],
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "snow", "swamp", "rough", "subterra", "lava" ],
|
||||||
|
"mines" : { "gold" : 1 },
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 8000, "max" : 9300, "density" : 4 },
|
||||||
|
{ "min" : 6000, "max" : 8000, "density" : 8 },
|
||||||
|
{ "min" : 800, "max" : 800, "density" : 4 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"2" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 12,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "castles" : 1 },
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "snow", "swamp", "rough", "subterra", "lava" ],
|
||||||
|
"minesLikeZone" : 1,
|
||||||
|
"treasureLikeZone" : 1
|
||||||
|
},
|
||||||
|
"4" :
|
||||||
|
{
|
||||||
|
"type" : "playerStart",
|
||||||
|
"size" : 12,
|
||||||
|
"owner" : 1,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"playerTowns" : { "castles" : 1 },
|
||||||
|
"allowedTowns" : [ "castle", "rampart", "tower", "inferno", "dungeon", "stronghold", "fortress" ],
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "snow", "swamp", "rough", "subterra", "lava" ],
|
||||||
|
"mines" : { "wood" : 1, "mercury" : 3, "ore" : 5, "sulfur" : 7, "crystal" : 10, "gems" : 34 },
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 4500, "max" : 6000, "density" : 1 },
|
||||||
|
{ "min" : 3500, "max" : 4500, "density" : 4 },
|
||||||
|
{ "min" : 300, "max" : 2000, "density" : 12 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"5" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 10,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "towns" : 1 },
|
||||||
|
"matchTerrainToTown" : false,
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "subterra", "lava" ],
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 6000, "max" : 7999, "density" : 6 },
|
||||||
|
{ "min" : 4000, "max" : 6000, "density" : 8 },
|
||||||
|
{ "min" : 1200, "max" : 2000, "density" : 5 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"6" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 10,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "towns" : 5 },
|
||||||
|
"townsAreSameType" : true,
|
||||||
|
"terrainTypeLikeZone" : 5,
|
||||||
|
"treasureLikeZone" : 5
|
||||||
|
},
|
||||||
|
"7" :
|
||||||
|
{
|
||||||
|
"type" : "playerStart",
|
||||||
|
"size" : 12,
|
||||||
|
"owner" : 2,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"playerTowns" : { "castles" : 1 },
|
||||||
|
"allowedTowns" : [ "castle", "rampart", "tower", "inferno", "dungeon", "stronghold", "fortress" ],
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "snow", "swamp", "rough", "subterra", "lava" ],
|
||||||
|
"minesLikeZone" : 4,
|
||||||
|
"treasureLikeZone" : 4
|
||||||
|
},
|
||||||
|
"8" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 10,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "towns" : 1 },
|
||||||
|
"terrainTypeLikeZone" : 5,
|
||||||
|
"treasureLikeZone" : 5
|
||||||
|
},
|
||||||
|
"10" :
|
||||||
|
{
|
||||||
|
"type" : "playerStart",
|
||||||
|
"size" : 12,
|
||||||
|
"owner" : 3,
|
||||||
|
"monsters" : "normal",
|
||||||
|
"playerTowns" : { "castles" : 1 },
|
||||||
|
"allowedTowns" : [ "castle", "rampart", "tower", "inferno", "dungeon", "stronghold", "fortress" ],
|
||||||
|
"allowedMonsters" : [ "castle", "rampart", "tower", "inferno", "necropolis", "dungeon", "stronghold", "fortress", "neutral" ],
|
||||||
|
"terrainTypes" : [ "dirt", "grass", "snow", "swamp", "rough", "subterra", "lava" ],
|
||||||
|
"minesLikeZone" : 4,
|
||||||
|
"treasureLikeZone" : 4
|
||||||
|
},
|
||||||
|
"11" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 10,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "towns" : 1 },
|
||||||
|
"terrainTypeLikeZone" : 5,
|
||||||
|
"treasureLikeZone" : 5
|
||||||
|
},
|
||||||
|
"13" :
|
||||||
|
{
|
||||||
|
"type" : "treasure",
|
||||||
|
"size" : 25,
|
||||||
|
"monsters" : "strong",
|
||||||
|
"neutralTowns" : { "castles" : 1 },
|
||||||
|
"allowedTowns" : [ "tower" ],
|
||||||
|
"terrainTypes" : [ "snow" ],
|
||||||
|
"mines" : { "mercury" : 1, "sulfur" : 1, "crystal" : 1, "gems" : 1, "gold" : 4 },
|
||||||
|
"treasure" :
|
||||||
|
[
|
||||||
|
{ "min" : 6000, "max" : 40000, "density" : 8 },
|
||||||
|
{ "min" : 9000, "max" : 9500, "density" : 8 },
|
||||||
|
{ "min" : 2500, "max" : 3000, "density" : 4 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connections" :
|
||||||
|
[
|
||||||
|
{ "a" : "1", "b" : "5", "guard" : 9000 },
|
||||||
|
{ "a" : "4", "b" : "5", "guard" : 5000 },
|
||||||
|
{ "a" : "4", "b" : "6", "guard" : 5000 },
|
||||||
|
{ "a" : "5", "b" : "6", "guard" : 5000 },
|
||||||
|
{ "a" : "1", "b" : "8", "guard" : 9000 },
|
||||||
|
{ "a" : "7", "b" : "8", "guard" : 5000 },
|
||||||
|
{ "a" : "10", "b" : "11", "guard" : 5000 },
|
||||||
|
{ "a" : "1", "b" : "2", "guard" : 10000 },
|
||||||
|
{ "a" : "1", "b" : "13", "guard" : 20000 },
|
||||||
|
{ "a" : "2", "b" : "13", "guard" : 20000 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user