mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
parent
205bb09880
commit
aaa07e4d2e
@ -88,24 +88,22 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
||||
for(pos.z = 0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
switch(tile->terType)
|
||||
if(!tile->terType.isPassable())
|
||||
continue;
|
||||
|
||||
if(tile->terType.isWater())
|
||||
{
|
||||
case ETerrainType::ROCK:
|
||||
break;
|
||||
|
||||
case ETerrainType::WATER:
|
||||
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
if(useWaterWalking)
|
||||
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
else
|
||||
{
|
||||
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1428,4 +1426,4 @@ std::string AIPath::toString() const
|
||||
str << node.targetHero->name << "[" << std::hex << node.chainMask << std::dec << "]" << "->" << node.coord.toString() << "; ";
|
||||
|
||||
return str.str();
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ int ChainActor::maxMovePoints(CGPathNode::ELayer layer)
|
||||
{
|
||||
#if AI_TRACE_LEVEL > 0
|
||||
if(!hero)
|
||||
throw std::exception("Asking movement points for static actor");
|
||||
throw std::logic_error("Asking movement points for static actor");
|
||||
#endif
|
||||
|
||||
return hero->maxMovePointsCached(layer, tiCache.get());
|
||||
|
@ -46,24 +46,22 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
switch(tile->terType)
|
||||
if(!tile->terType.isPassable())
|
||||
continue;
|
||||
|
||||
if(tile->terType.isWater())
|
||||
{
|
||||
case ETerrainType::ROCK:
|
||||
break;
|
||||
|
||||
case ETerrainType::WATER:
|
||||
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
if(useWaterWalking)
|
||||
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
else
|
||||
{
|
||||
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -347,11 +347,6 @@ public:
|
||||
h & visitableObjs;
|
||||
h & alreadyVisited;
|
||||
h & reservedObjs;
|
||||
if (version < 788 && !h.saving)
|
||||
{
|
||||
TResources saving;
|
||||
h & saving; //mind the ambiguity
|
||||
}
|
||||
h & status;
|
||||
h & battlename;
|
||||
h & heroesUnableToExplore;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "../lib/StringConstants.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
#include "../lib/VCMIDirs.h"
|
||||
#include "../lib/Terrain.h"
|
||||
|
||||
#define VCMI_SOUND_NAME(x)
|
||||
#define VCMI_SOUND_FILE(y) #y,
|
||||
@ -92,20 +93,34 @@ CSoundHandler::CSoundHandler():
|
||||
soundBase::pickup04, soundBase::pickup05, soundBase::pickup06, soundBase::pickup07
|
||||
};
|
||||
|
||||
horseSounds = // must be the same order as terrains (see ETerrainType);
|
||||
{
|
||||
soundBase::horseDirt, soundBase::horseSand, soundBase::horseGrass,
|
||||
soundBase::horseSnow, soundBase::horseSwamp, soundBase::horseRough,
|
||||
soundBase::horseSubterranean, soundBase::horseLava,
|
||||
soundBase::horseWater, soundBase::horseRock
|
||||
};
|
||||
|
||||
battleIntroSounds =
|
||||
{
|
||||
soundBase::battle00, soundBase::battle01,
|
||||
soundBase::battle02, soundBase::battle03, soundBase::battle04,
|
||||
soundBase::battle05, soundBase::battle06, soundBase::battle07
|
||||
};
|
||||
|
||||
//predefine terrain set
|
||||
//TODO: need refactoring - support custom sounds for new terrains and load from json
|
||||
int h3mTerrId = 0;
|
||||
for(auto snd :
|
||||
{
|
||||
soundBase::horseDirt, soundBase::horseSand, soundBase::horseGrass,
|
||||
soundBase::horseSnow, soundBase::horseSwamp, soundBase::horseRough,
|
||||
soundBase::horseSubterranean, soundBase::horseLava,
|
||||
soundBase::horseWater, soundBase::horseRock
|
||||
})
|
||||
{
|
||||
horseSounds[Terrain::createTerrainTypeH3M(h3mTerrId++)] = snd;
|
||||
}
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
//since all sounds are hardcoded, let's keep it
|
||||
if(vstd::contains(horseSounds, terrain))
|
||||
continue;
|
||||
|
||||
horseSounds[terrain] = horseSounds.at(Terrain::createTerrainTypeH3M(Terrain::Manager::getInfo(terrain).horseSoundId));
|
||||
}
|
||||
};
|
||||
|
||||
void CSoundHandler::init()
|
||||
@ -341,26 +356,22 @@ CMusicHandler::CMusicHandler():
|
||||
return true;
|
||||
});
|
||||
|
||||
int battleMusicID = 0;
|
||||
int AIThemeID = 0;
|
||||
|
||||
for(const ResourceID & file : mp3files)
|
||||
{
|
||||
if(boost::algorithm::istarts_with(file.getName(), "MUSIC/Combat"))
|
||||
addEntryToSet("battle", battleMusicID++, file.getName());
|
||||
addEntryToSet("battle", file.getName(), file.getName());
|
||||
else if(boost::algorithm::istarts_with(file.getName(), "MUSIC/AITheme"))
|
||||
addEntryToSet("enemy-turn", AIThemeID++, file.getName());
|
||||
addEntryToSet("enemy-turn", file.getName(), file.getName());
|
||||
}
|
||||
|
||||
JsonNode terrains(ResourceID("config/terrains.json"));
|
||||
for (auto entry : terrains.Struct())
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
int terrIndex = vstd::find_pos(GameConstants::TERRAIN_NAMES, entry.first);
|
||||
addEntryToSet("terrain", terrIndex, "Music/" + entry.second["music"].String());
|
||||
auto & entry = Terrain::Manager::getInfo(terrain);
|
||||
addEntryToSet("terrain", terrain, "Music/" + entry.musicFilename);
|
||||
}
|
||||
}
|
||||
|
||||
void CMusicHandler::addEntryToSet(std::string set, int musicID, std::string musicURI)
|
||||
void CMusicHandler::addEntryToSet(const std::string & set, const std::string & musicID, const std::string & musicURI)
|
||||
{
|
||||
musicsSet[set][musicID] = musicURI;
|
||||
}
|
||||
@ -388,7 +399,7 @@ void CMusicHandler::release()
|
||||
CAudioBase::release();
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusic(std::string musicURI, bool loop)
|
||||
void CMusicHandler::playMusic(const std::string & musicURI, bool loop)
|
||||
{
|
||||
if (current && current->isTrack(musicURI))
|
||||
return;
|
||||
@ -396,7 +407,7 @@ void CMusicHandler::playMusic(std::string musicURI, bool loop)
|
||||
queueNext(this, "", musicURI, loop);
|
||||
}
|
||||
|
||||
void CMusicHandler::playMusicFromSet(std::string whichSet, bool loop)
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop)
|
||||
{
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
@ -412,8 +423,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, bool loop)
|
||||
queueNext(this, whichSet, "", loop);
|
||||
}
|
||||
|
||||
|
||||
void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loop)
|
||||
void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop)
|
||||
{
|
||||
auto selectedSet = musicsSet.find(whichSet);
|
||||
if (selectedSet == musicsSet.end())
|
||||
@ -425,7 +435,7 @@ void CMusicHandler::playMusicFromSet(std::string whichSet, int entryID, bool loo
|
||||
auto selectedEntry = selectedSet->second.find(entryID);
|
||||
if (selectedEntry == selectedSet->second.end())
|
||||
{
|
||||
logGlobal->error("Error: playing non-existing entry %d from set: %s", entryID, whichSet);
|
||||
logGlobal->error("Error: playing non-existing entry %s from set: %s", entryID, whichSet);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -452,7 +462,7 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
|
||||
}
|
||||
}
|
||||
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped)
|
||||
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -552,7 +562,7 @@ bool MusicEntry::play()
|
||||
|
||||
if (!setName.empty())
|
||||
{
|
||||
auto set = owner->musicsSet[setName];
|
||||
const auto & set = owner->musicsSet[setName];
|
||||
load(RandomGeneratorUtil::nextItem(set, CRandomGenerator::getDefault())->second);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ struct _Mix_Music;
|
||||
struct SDL_RWops;
|
||||
typedef struct _Mix_Music Mix_Music;
|
||||
struct Mix_Chunk;
|
||||
class Terrain;
|
||||
|
||||
class CAudioBase {
|
||||
protected:
|
||||
@ -81,8 +82,8 @@ public:
|
||||
|
||||
// Sets
|
||||
std::vector<soundBase::soundID> pickupSounds;
|
||||
std::vector<soundBase::soundID> horseSounds;
|
||||
std::vector<soundBase::soundID> battleIntroSounds;
|
||||
std::map<Terrain, soundBase::soundID> horseSounds;
|
||||
};
|
||||
|
||||
// Helper //now it looks somewhat useless
|
||||
@ -118,6 +119,7 @@ public:
|
||||
class CMusicHandler: public CAudioBase
|
||||
{
|
||||
private:
|
||||
|
||||
//update volume on configuration change
|
||||
SettingsListener listener;
|
||||
void onVolumeChange(const JsonNode &volumeNode);
|
||||
@ -125,26 +127,27 @@ private:
|
||||
std::unique_ptr<MusicEntry> current;
|
||||
std::unique_ptr<MusicEntry> next;
|
||||
|
||||
void queueNext(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
|
||||
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped);
|
||||
void queueNext(std::unique_ptr<MusicEntry> queued);
|
||||
|
||||
std::map<std::string, std::map<int, std::string> > musicsSet;
|
||||
std::map<std::string, std::map<std::string, std::string>> musicsSet;
|
||||
public:
|
||||
|
||||
CMusicHandler();
|
||||
|
||||
/// add entry with URI musicURI in set. Track will have ID musicID
|
||||
void addEntryToSet(std::string set, int musicID, std::string musicURI);
|
||||
void addEntryToSet(const std::string & set, const std::string & entryID, const std::string & musicURI);
|
||||
|
||||
void init() override;
|
||||
void release() override;
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
/// play track by URI, if loop = true music will be looped
|
||||
void playMusic(std::string musicURI, bool loop);
|
||||
void playMusic(const std::string & musicURI, bool loop);
|
||||
/// play random track from this set
|
||||
void playMusicFromSet(std::string musicSet, bool loop);
|
||||
void playMusicFromSet(const std::string & musicSet, bool loop);
|
||||
/// play specific track from set
|
||||
void playMusicFromSet(std::string musicSet, int entryID, bool loop);
|
||||
void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop);
|
||||
void stopMusic(int fade_ms=1000);
|
||||
void musicFinishedCallback();
|
||||
|
||||
|
@ -1351,12 +1351,6 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
|
||||
|
||||
template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
|
||||
{
|
||||
if(version < 774 && !h.saving)
|
||||
{
|
||||
bool observerInDuelMode = false;
|
||||
h & observerInDuelMode;
|
||||
}
|
||||
|
||||
h & wanderingHeroes;
|
||||
h & towns;
|
||||
h & sleepingHeroes;
|
||||
@ -2742,8 +2736,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
|
||||
{
|
||||
path.convert(0);
|
||||
ETerrainType currentTerrain = ETerrainType::BORDER; // not init yet
|
||||
ETerrainType newTerrain;
|
||||
Terrain currentTerrain = Terrain("BORDER"); // not init yet
|
||||
Terrain newTerrain;
|
||||
int sh = -1;
|
||||
|
||||
auto canStop = [&](CGPathNode * node) -> bool
|
||||
@ -2779,7 +2773,9 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
destinationTeleportPos = int3(-1);
|
||||
}
|
||||
if(i != path.nodes.size() - 1)
|
||||
{
|
||||
sh = CCS->soundh->playSound(CCS->soundh->horseSounds[currentTerrain], -1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2797,7 +2793,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path)
|
||||
#endif
|
||||
{
|
||||
newTerrain = cb->getTile(CGHeroInstance::convertPosition(currentCoord, false))->terType;
|
||||
if (newTerrain != currentTerrain)
|
||||
if(newTerrain != currentTerrain)
|
||||
{
|
||||
CCS->soundh->stopSound(sh);
|
||||
sh = CCS->soundh->playSound(CCS->soundh->horseSounds[newTerrain], -1);
|
||||
|
@ -274,12 +274,6 @@ void CClient::serialize(BinarySerializer & h, const int version)
|
||||
void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
{
|
||||
assert(!h.saving);
|
||||
if(version < 787)
|
||||
{
|
||||
bool hotSeat = false;
|
||||
h & hotSeat;
|
||||
}
|
||||
|
||||
ui8 players = 0;
|
||||
h & players;
|
||||
|
||||
@ -337,11 +331,7 @@ void CClient::serialize(BinaryDeserializer & h, const int version)
|
||||
|
||||
{
|
||||
JsonNode scriptsState;
|
||||
if(version >= 800)
|
||||
{
|
||||
h & scriptsState;
|
||||
}
|
||||
|
||||
h & scriptsState;
|
||||
clientScripts->serializeState(h.saving, scriptsState);
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ CBattleInterface::~CBattleInterface()
|
||||
|
||||
if (adventureInt && adventureInt->selection)
|
||||
{
|
||||
int terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType;
|
||||
auto & terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType;
|
||||
CCS->musich->playMusicFromSet("terrain", terrain, true);
|
||||
}
|
||||
animsAreDisplayed.setn(false);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "../lib/CGameState.h"
|
||||
#include "../lib/CHeroHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
#include "../lib/CModHandler.h"
|
||||
#include "Graphics.h"
|
||||
#include "../lib/mapping/CMap.h"
|
||||
#include "../lib/CConfigHandler.h"
|
||||
@ -29,6 +30,9 @@
|
||||
#include "CMT.h"
|
||||
#include "CMusicHandler.h"
|
||||
#include "../lib/CRandomGenerator.h"
|
||||
#include "../lib/Terrain.h"
|
||||
#include "../lib/filesystem/ResourceID.h"
|
||||
#include "../lib/JsonDetail.h"
|
||||
|
||||
#define ADVOPT (conf.go()->ac)
|
||||
|
||||
@ -142,79 +146,68 @@ EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface
|
||||
|
||||
void CMapHandler::initTerrainGraphics()
|
||||
{
|
||||
static const std::vector<std::string> TERRAIN_FILES =
|
||||
static const std::map<std::string, std::string> ROAD_FILES =
|
||||
{
|
||||
"DIRTTL",
|
||||
"SANDTL",
|
||||
"GRASTL",
|
||||
"SNOWTL",
|
||||
"SWMPTL",
|
||||
|
||||
"ROUGTL",
|
||||
"SUBBTL",
|
||||
"LAVATL",
|
||||
"WATRTL",
|
||||
"ROCKTL"
|
||||
{ROAD_NAMES[1], "dirtrd"},
|
||||
{ROAD_NAMES[2], "gravrd"},
|
||||
{ROAD_NAMES[3], "cobbrd"}
|
||||
};
|
||||
|
||||
static const std::vector<std::string> ROAD_FILES =
|
||||
static const std::map<std::string, std::string> RIVER_FILES =
|
||||
{
|
||||
"dirtrd",
|
||||
"gravrd",
|
||||
"cobbrd"
|
||||
{RIVER_NAMES[1], "clrrvr"},
|
||||
{RIVER_NAMES[2], "icyrvr"},
|
||||
{RIVER_NAMES[3], "mudrvr"},
|
||||
{RIVER_NAMES[4], "lavrvr"}
|
||||
};
|
||||
|
||||
|
||||
static const std::vector<std::string> RIVER_FILES =
|
||||
auto loadFlipped = [](TFlippedAnimations & animation, TFlippedCache & cache, const std::map<std::string, std::string> & files)
|
||||
{
|
||||
"clrrvr",
|
||||
"icyrvr",
|
||||
"mudrvr",
|
||||
"lavrvr"
|
||||
};
|
||||
|
||||
auto loadFlipped = [](int types, TFlippedAnimations & animation, TFlippedCache & cache, const std::vector<std::string> & files)
|
||||
{
|
||||
animation.resize(types);
|
||||
cache.resize(types);
|
||||
|
||||
//no rotation and basic setup
|
||||
for(int i = 0; i < types; i++)
|
||||
for(auto & type : files)
|
||||
{
|
||||
animation[i][0] = make_unique<CAnimation>(files[i]);
|
||||
animation[i][0]->preload();
|
||||
const size_t views = animation[i][0]->size(0);
|
||||
cache[i].resize(views);
|
||||
animation[type.first][0] = make_unique<CAnimation>(type.second);
|
||||
animation[type.first][0]->preload();
|
||||
const size_t views = animation[type.first][0]->size(0);
|
||||
cache[type.first].resize(views);
|
||||
|
||||
for(int j = 0; j < views; j++)
|
||||
cache[i][j][0] = animation[i][0]->getImage(j);
|
||||
cache[type.first][j][0] = animation[type.first][0]->getImage(j);
|
||||
}
|
||||
|
||||
for(int rotation = 1; rotation < 4; rotation++)
|
||||
{
|
||||
for(int i = 0; i < types; i++)
|
||||
for(auto & type : files)
|
||||
{
|
||||
animation[i][rotation] = make_unique<CAnimation>(files[i]);
|
||||
animation[i][rotation]->preload();
|
||||
const size_t views = animation[i][rotation]->size(0);
|
||||
animation[type.first][rotation] = make_unique<CAnimation>(type.second);
|
||||
animation[type.first][rotation]->preload();
|
||||
const size_t views = animation[type.first][rotation]->size(0);
|
||||
|
||||
for(int j = 0; j < views; j++)
|
||||
{
|
||||
auto image = animation[i][rotation]->getImage(j);
|
||||
auto image = animation[type.first][rotation]->getImage(j);
|
||||
|
||||
if(rotation == 2 || rotation == 3)
|
||||
image->horizontalFlip();
|
||||
if(rotation == 1 || rotation == 3)
|
||||
image->verticalFlip();
|
||||
|
||||
cache[i][j][rotation] = image;
|
||||
cache[type.first][j][rotation] = image;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
loadFlipped(GameConstants::TERRAIN_TYPES, terrainAnimations, terrainImages, TERRAIN_FILES);
|
||||
loadFlipped(3, roadAnimations, roadImages, ROAD_FILES);
|
||||
loadFlipped(4, riverAnimations, riverImages, RIVER_FILES);
|
||||
|
||||
std::map<std::string, std::string> terrainFiles;
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
terrainFiles[terrain] = Terrain::Manager::getInfo(terrain).tilesFilename;
|
||||
}
|
||||
|
||||
loadFlipped(terrainAnimations, terrainImages, terrainFiles);
|
||||
loadFlipped(roadAnimations, roadImages, ROAD_FILES);
|
||||
loadFlipped(riverAnimations, riverImages, RIVER_FILES);
|
||||
|
||||
// Create enough room for the whole map and its frame
|
||||
|
||||
@ -626,6 +619,9 @@ void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const T
|
||||
Rect destRect(realTileRect);
|
||||
|
||||
ui8 rotation = tinfo.extTileFlags % 4;
|
||||
|
||||
if(parent->terrainImages[tinfo.terType].size()<=tinfo.terView)
|
||||
return;
|
||||
|
||||
drawElement(EMapCacheType::TERRAIN, parent->terrainImages[tinfo.terType][tinfo.terView][rotation], nullptr, targetSurf, &destRect);
|
||||
}
|
||||
@ -802,21 +798,21 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra
|
||||
|
||||
void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const
|
||||
{
|
||||
if (tinfoUpper && tinfoUpper->roadType != ERoadType::NO_ROAD)
|
||||
if (tinfoUpper && tinfoUpper->roadType != ROAD_NAMES[0])
|
||||
{
|
||||
ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4;
|
||||
Rect source(0, tileSize / 2, tileSize, tileSize / 2);
|
||||
Rect dest(realPos.x, realPos.y, tileSize, tileSize / 2);
|
||||
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType - 1][tinfoUpper->roadDir][rotation],
|
||||
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType][tinfoUpper->roadDir][rotation],
|
||||
&source, targetSurf, &dest);
|
||||
}
|
||||
|
||||
if(tinfo.roadType != ERoadType::NO_ROAD) //print road from this tile
|
||||
if(tinfo.roadType != ROAD_NAMES[0]) //print road from this tile
|
||||
{
|
||||
ui8 rotation = (tinfo.extTileFlags >> 4) % 4;
|
||||
Rect source(0, 0, tileSize, halfTileSizeCeil);
|
||||
Rect dest(realPos.x, realPos.y + tileSize / 2, tileSize, tileSize / 2);
|
||||
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType - 1][tinfo.roadDir][rotation],
|
||||
drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType][tinfo.roadDir][rotation],
|
||||
&source, targetSurf, &dest);
|
||||
}
|
||||
}
|
||||
@ -825,7 +821,7 @@ void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const Terrain
|
||||
{
|
||||
Rect destRect(realTileRect);
|
||||
ui8 rotation = (tinfo.extTileFlags >> 2) % 4;
|
||||
drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType-1][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect);
|
||||
drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect);
|
||||
}
|
||||
|
||||
void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const
|
||||
@ -876,7 +872,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn
|
||||
if(isVisible || info->showAllTerrain)
|
||||
{
|
||||
drawTileTerrain(targetSurf, tinfo, tile);
|
||||
if (tinfo.riverType)
|
||||
if(tinfo.riverType != RIVER_NAMES[0])
|
||||
drawRiver(targetSurf, tinfo);
|
||||
drawRoad(targetSurf, tinfo, tinfoUpper);
|
||||
}
|
||||
@ -1326,13 +1322,13 @@ bool CMapHandler::canStartHeroMovement()
|
||||
|
||||
void CMapHandler::updateWater() //shift colors in palettes of water tiles
|
||||
{
|
||||
for(auto & elem : terrainImages[7])
|
||||
for(auto & elem : terrainImages["lava"])
|
||||
{
|
||||
for(auto img : elem)
|
||||
img->shiftPalette(246, 9);
|
||||
}
|
||||
|
||||
for(auto & elem : terrainImages[8])
|
||||
for(auto & elem : terrainImages["water"])
|
||||
{
|
||||
for(auto img : elem)
|
||||
{
|
||||
@ -1341,7 +1337,7 @@ void CMapHandler::updateWater() //shift colors in palettes of water tiles
|
||||
}
|
||||
}
|
||||
|
||||
for(auto & elem : riverImages[0])
|
||||
for(auto & elem : riverImages["clrrvr"])
|
||||
{
|
||||
for(auto img : elem)
|
||||
{
|
||||
@ -1350,7 +1346,7 @@ void CMapHandler::updateWater() //shift colors in palettes of water tiles
|
||||
}
|
||||
}
|
||||
|
||||
for(auto & elem : riverImages[2])
|
||||
for(auto & elem : riverImages["mudrvr"])
|
||||
{
|
||||
for(auto img : elem)
|
||||
{
|
||||
@ -1360,7 +1356,7 @@ void CMapHandler::updateWater() //shift colors in palettes of water tiles
|
||||
}
|
||||
}
|
||||
|
||||
for(auto & elem : riverImages[3])
|
||||
for(auto & elem : riverImages["lavrvr"])
|
||||
{
|
||||
for(auto img : elem)
|
||||
img->shiftPalette(240, 9);
|
||||
|
@ -354,8 +354,8 @@ public:
|
||||
//terrain graphics
|
||||
|
||||
//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
|
||||
typedef std::vector<std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
|
||||
typedef std::vector<std::vector<std::array<std::shared_ptr<IImage>, 4>>> TFlippedCache;//[type, view type, rotation]
|
||||
typedef std::map<std::string, std::array<std::shared_ptr<CAnimation>, 4>> TFlippedAnimations; //[type, rotation]
|
||||
typedef std::map<std::string, std::vector<std::array<std::shared_ptr<IImage>, 4>>> TFlippedCache;//[type, view type, rotation]
|
||||
|
||||
TFlippedAnimations terrainAnimations;//[terrain type, rotation]
|
||||
TFlippedCache terrainImages;//[terrain type, view type, rotation]
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/CModHandler.h"
|
||||
#include "../../lib/CTownHandler.h"
|
||||
#include "../../lib/Terrain.h"
|
||||
#include "../../lib/filesystem/Filesystem.h"
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||
@ -494,41 +495,30 @@ void CMinimapInstance::showAll(SDL_Surface * to)
|
||||
}
|
||||
}
|
||||
|
||||
std::map<int, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors(std::string from)
|
||||
std::map<Terrain, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors()
|
||||
{
|
||||
std::map<int, std::pair<SDL_Color, SDL_Color> > ret;
|
||||
std::map<Terrain, std::pair<SDL_Color, SDL_Color> > ret;
|
||||
|
||||
const JsonNode config(ResourceID(from, EResType::TEXT));
|
||||
|
||||
for(auto &m : config.Struct())
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
auto index = boost::find(GameConstants::TERRAIN_NAMES, m.first);
|
||||
if (index == std::end(GameConstants::TERRAIN_NAMES))
|
||||
{
|
||||
logGlobal->error("Error: unknown terrain in terrains.json: %s", m.first);
|
||||
continue;
|
||||
}
|
||||
int terrainID = static_cast<int>(index - std::begin(GameConstants::TERRAIN_NAMES));
|
||||
|
||||
const JsonVector &unblockedVec = m.second["minimapUnblocked"].Vector();
|
||||
auto & m = Terrain::Manager::getInfo(terrain);
|
||||
SDL_Color normal =
|
||||
{
|
||||
ui8(unblockedVec[0].Float()),
|
||||
ui8(unblockedVec[1].Float()),
|
||||
ui8(unblockedVec[2].Float()),
|
||||
ui8(m.minimapUnblocked[0]),
|
||||
ui8(m.minimapUnblocked[1]),
|
||||
ui8(m.minimapUnblocked[2]),
|
||||
ui8(255)
|
||||
};
|
||||
|
||||
const JsonVector &blockedVec = m.second["minimapBlocked"].Vector();
|
||||
SDL_Color blocked =
|
||||
{
|
||||
ui8(blockedVec[0].Float()),
|
||||
ui8(blockedVec[1].Float()),
|
||||
ui8(blockedVec[2].Float()),
|
||||
ui8(m.minimapBlocked[0]),
|
||||
ui8(m.minimapBlocked[1]),
|
||||
ui8(m.minimapBlocked[2]),
|
||||
ui8(255)
|
||||
};
|
||||
|
||||
ret.insert(std::make_pair(terrainID, std::make_pair(normal, blocked)));
|
||||
ret[terrain] = std::make_pair(normal, blocked);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -536,7 +526,7 @@ std::map<int, std::pair<SDL_Color, SDL_Color> > CMinimap::loadColors(std::string
|
||||
CMinimap::CMinimap(const Rect & position)
|
||||
: CIntObject(LCLICK | RCLICK | HOVER | MOVE, position.topLeft()),
|
||||
level(0),
|
||||
colors(loadColors("config/terrains.json"))
|
||||
colors(loadColors())
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
pos.w = position.w;
|
||||
|
@ -30,6 +30,7 @@ struct InfoAboutTown;
|
||||
class CHeroTooltip;
|
||||
class CTownTooltip;
|
||||
class CTextBox;
|
||||
class Terrain;
|
||||
|
||||
/// Base UI Element for hero\town lists
|
||||
class CList : public CIntObject
|
||||
@ -216,7 +217,7 @@ protected:
|
||||
int level;
|
||||
|
||||
//to initialize colors
|
||||
std::map<int, std::pair<SDL_Color, SDL_Color> > loadColors(std::string from);
|
||||
std::map<Terrain, std::pair<SDL_Color, SDL_Color> > loadColors();
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
@ -227,7 +228,7 @@ protected:
|
||||
|
||||
public:
|
||||
// terrainID -> (normal color, blocked color)
|
||||
const std::map<int, std::pair<SDL_Color, SDL_Color> > colors;
|
||||
const std::map<Terrain, std::pair<SDL_Color, SDL_Color> > colors;
|
||||
|
||||
CMinimap(const Rect & position);
|
||||
|
||||
|
@ -265,7 +265,7 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
|
||||
{-1, 1, 2, 23, -1, 3, 22, 21, 12}
|
||||
}; //table of magic values TODO meaning, change variable name
|
||||
|
||||
for (int i=0; i < (int)currentPath->nodes.size()-1; ++i)
|
||||
for (int i = 0; i < -1 + (int)currentPath->nodes.size(); ++i)
|
||||
{
|
||||
const int3 &curPos = currentPath->nodes[i].coord, &nextPos = currentPath->nodes[i+1].coord;
|
||||
if(curPos.z != adventureInt->position.z)
|
||||
|
@ -80,5 +80,9 @@
|
||||
"skills" :
|
||||
[
|
||||
"config/skills.json"
|
||||
],
|
||||
"terrains":
|
||||
[
|
||||
"config/terrains.json"
|
||||
]
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
"obstacles" : [
|
||||
{
|
||||
"id" : 0,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -24,7 +24,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 1,
|
||||
"allowedTerrain" : [0, 1, 5, 6],
|
||||
"allowedTerrain" : ["dirt", "sand", "rough", "subterra"],
|
||||
"specialBattlefields" : [0],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -34,7 +34,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 2,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 2,
|
||||
@ -44,7 +44,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 3,
|
||||
"allowedTerrain" : [0, 5],
|
||||
"allowedTerrain" : ["dirt", "rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -54,7 +54,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 4,
|
||||
"allowedTerrain" : [0, 5, 6],
|
||||
"allowedTerrain" : ["dirt", "rough", "subterra"],
|
||||
"specialBattlefields" : [0, 1],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -64,7 +64,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 5,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 2,
|
||||
@ -74,7 +74,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 6,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -84,7 +84,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 7,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -94,7 +94,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 8,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -104,7 +104,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 9,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -114,7 +114,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 10,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -124,7 +124,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 11,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -134,7 +134,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 12,
|
||||
"allowedTerrain" : [0, 5],
|
||||
"allowedTerrain" : ["dirt", "rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -144,7 +144,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 13,
|
||||
"allowedTerrain" : [0, 5],
|
||||
"allowedTerrain" : ["dirt", "rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -154,7 +154,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 14,
|
||||
"allowedTerrain" : [0, 5],
|
||||
"allowedTerrain" : ["dirt", "rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -164,7 +164,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 15,
|
||||
"allowedTerrain" : [0, 5],
|
||||
"allowedTerrain" : ["dirt", "rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -174,7 +174,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 16,
|
||||
"allowedTerrain" : [1],
|
||||
"allowedTerrain" : ["sand"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 4,
|
||||
@ -184,7 +184,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 17,
|
||||
"allowedTerrain" : [1],
|
||||
"allowedTerrain" : ["sand"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -194,7 +194,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 18,
|
||||
"allowedTerrain" : [1],
|
||||
"allowedTerrain" : ["sand"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 2,
|
||||
@ -204,7 +204,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 19,
|
||||
"allowedTerrain" : [2, 4],
|
||||
"allowedTerrain" : ["grass", "swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -214,7 +214,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 20,
|
||||
"allowedTerrain" : [2, 4],
|
||||
"allowedTerrain" : ["grass", "swamp"],
|
||||
"specialBattlefields" : [2],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -224,7 +224,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 21,
|
||||
"allowedTerrain" : [2, 4],
|
||||
"allowedTerrain" : ["grass", "swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 1,
|
||||
"height" : 1,
|
||||
@ -234,7 +234,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 22,
|
||||
"allowedTerrain" : [2],
|
||||
"allowedTerrain" : ["grass"],
|
||||
"specialBattlefields" : [2],
|
||||
"width" : 6,
|
||||
"height" : 2,
|
||||
@ -244,7 +244,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 23,
|
||||
"allowedTerrain" : [2],
|
||||
"allowedTerrain" : ["grass"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 7,
|
||||
"height" : 1,
|
||||
@ -254,7 +254,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 24,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 1,
|
||||
@ -264,7 +264,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 25,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 1,
|
||||
@ -274,7 +274,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 26,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -284,7 +284,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 27,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 1,
|
||||
@ -294,7 +294,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 28,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 1,
|
||||
@ -304,7 +304,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 29,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -314,7 +314,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 30,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -324,7 +324,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 31,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -334,7 +334,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 32,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 7,
|
||||
"height" : 2,
|
||||
@ -344,7 +344,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 33,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 5,
|
||||
@ -354,7 +354,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 34,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -364,7 +364,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 35,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 8,
|
||||
"height" : 3,
|
||||
@ -374,7 +374,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 36,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 2,
|
||||
"height" : 1,
|
||||
@ -384,7 +384,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 37,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 1,
|
||||
@ -394,7 +394,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 38,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 4,
|
||||
@ -404,7 +404,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 39,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 3,
|
||||
@ -414,7 +414,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 40,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 2,
|
||||
"height" : 2,
|
||||
@ -424,7 +424,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 41,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 4,
|
||||
"height" : 3,
|
||||
@ -434,7 +434,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 42,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -444,7 +444,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 43,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -454,7 +454,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 44,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -464,7 +464,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 45,
|
||||
"allowedTerrain" : [6],
|
||||
"allowedTerrain" : ["subterra"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -474,7 +474,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 46,
|
||||
"allowedTerrain" : [6],
|
||||
"allowedTerrain" : ["subterra"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -484,7 +484,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 47,
|
||||
"allowedTerrain" : [6],
|
||||
"allowedTerrain" : ["subterra"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 3,
|
||||
@ -494,7 +494,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 48,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 3,
|
||||
@ -504,7 +504,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 49,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 2,
|
||||
@ -514,7 +514,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 50,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 3,
|
||||
@ -524,7 +524,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 51,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 2,
|
||||
@ -534,7 +534,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 52,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 4,
|
||||
"height" : 4,
|
||||
@ -544,7 +544,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 53,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 3,
|
||||
@ -554,7 +554,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 54,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 5,
|
||||
"height" : 3,
|
||||
@ -564,7 +564,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 55,
|
||||
"allowedTerrain" : [8],
|
||||
"allowedTerrain" : ["water"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 3,
|
||||
"height" : 3,
|
||||
@ -926,7 +926,7 @@
|
||||
"absoluteObstacles" : [
|
||||
{
|
||||
"id" : 0,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 124,
|
||||
"height" : 254,
|
||||
@ -935,7 +935,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 1,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 256,
|
||||
"height" : 254,
|
||||
@ -944,7 +944,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 2,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 168,
|
||||
"height" : 212,
|
||||
@ -953,7 +953,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 3,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 124,
|
||||
"height" : 254,
|
||||
@ -962,7 +962,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 4,
|
||||
"allowedTerrain" : [0],
|
||||
"allowedTerrain" : ["dirt"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 146,
|
||||
"height" : 254,
|
||||
@ -971,7 +971,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 5,
|
||||
"allowedTerrain" : [2],
|
||||
"allowedTerrain" : ["grass"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 173,
|
||||
"height" : 221,
|
||||
@ -980,7 +980,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 6,
|
||||
"allowedTerrain" : [2],
|
||||
"allowedTerrain" : ["grass"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 180,
|
||||
"height" : 264,
|
||||
@ -989,7 +989,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 7,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 166,
|
||||
"height" : 255,
|
||||
@ -998,7 +998,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 8,
|
||||
"allowedTerrain" : [3],
|
||||
"allowedTerrain" : ["snow"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 302,
|
||||
"height" : 172,
|
||||
@ -1007,7 +1007,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 9,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 300,
|
||||
"height" : 170,
|
||||
@ -1016,7 +1016,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 10,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 278,
|
||||
"height" : 171,
|
||||
@ -1025,7 +1025,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 11,
|
||||
"allowedTerrain" : [4],
|
||||
"allowedTerrain" : ["swamp"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 256,
|
||||
"height" : 254,
|
||||
@ -1034,7 +1034,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 12,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 124,
|
||||
"height" : 254,
|
||||
@ -1043,7 +1043,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 13,
|
||||
"allowedTerrain" : [7],
|
||||
"allowedTerrain" : ["lava"],
|
||||
"specialBattlefields" : [],
|
||||
"width" : 256,
|
||||
"height" : 128,
|
||||
@ -1052,7 +1052,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 14,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 186,
|
||||
"height" : 212,
|
||||
@ -1061,7 +1061,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 15,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 347,
|
||||
"height" : 174,
|
||||
@ -1070,7 +1070,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 16,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 294,
|
||||
"height" : 169,
|
||||
@ -1079,7 +1079,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 17,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 165,
|
||||
"height" : 257,
|
||||
@ -1088,7 +1088,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 18,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 208,
|
||||
"height" : 268,
|
||||
@ -1097,7 +1097,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 19,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 252,
|
||||
"height" : 254,
|
||||
@ -1106,7 +1106,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 20,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 278,
|
||||
"height" : 128,
|
||||
@ -1115,7 +1115,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 21,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 208,
|
||||
"height" : 268,
|
||||
@ -1124,7 +1124,7 @@
|
||||
},
|
||||
{
|
||||
"id" : 22,
|
||||
"allowedTerrain" : [5],
|
||||
"allowedTerrain" : ["rough"],
|
||||
"specialBattlefields" : [1],
|
||||
"width" : 168,
|
||||
"height" : 212,
|
||||
|
@ -2,7 +2,7 @@
|
||||
"terrain" :
|
||||
{
|
||||
"undergroundAllow" : ["lava"], //others to be replaced by subterranena
|
||||
"groundProhibit" : ["subterranean"] //to be replaced by dirt
|
||||
"groundProhibit" : ["subterra"] //to be replaced by dirt
|
||||
},
|
||||
"waterZone" :
|
||||
{
|
||||
@ -31,7 +31,7 @@
|
||||
"extraResourcesLimit" : 3
|
||||
},
|
||||
"minGuardStrength" : 2000,
|
||||
"defaultRoadType" : "cobblestone_road",
|
||||
"defaultRoadType" : "pc", //pd - dirt, pg - gravel, pc - cobblestone
|
||||
"treasureValueLimit" : 20000, //generate pandora with gold for treasure above this limit
|
||||
"prisons" :
|
||||
{
|
||||
|
@ -4,69 +4,92 @@
|
||||
"moveCost" : 100,
|
||||
"minimapUnblocked" : [ 82, 56, 8 ],
|
||||
"minimapBlocked" : [ 57, 40, 8 ],
|
||||
"music" : "Dirt.mp3"
|
||||
"music" : "Dirt.mp3",
|
||||
"tiles" : "DIRTTL",
|
||||
"code" : "dt"
|
||||
},
|
||||
"sand" :
|
||||
{
|
||||
"moveCost" : 150,
|
||||
"minimapUnblocked" : [ 222, 207, 140 ],
|
||||
"minimapBlocked" : [ 165, 158, 107 ],
|
||||
"music" : "Sand.mp3"
|
||||
"music" : "Sand.mp3",
|
||||
"tiles" : "SANDTL",
|
||||
"code" : "sa"
|
||||
},
|
||||
"grass" :
|
||||
{
|
||||
"moveCost" : 100,
|
||||
"minimapUnblocked" : [ 0, 65, 0 ],
|
||||
"minimapBlocked" : [ 0, 48, 0 ],
|
||||
"music" : "Grass.mp3"
|
||||
"music" : "Grass.mp3",
|
||||
"tiles" : "GRASTL",
|
||||
"code" : "gr"
|
||||
},
|
||||
"snow" :
|
||||
{
|
||||
"moveCost" : 150,
|
||||
"minimapUnblocked" : [ 181, 199, 198 ],
|
||||
"minimapBlocked" : [ 140, 158, 156 ],
|
||||
"music" : "Snow.mp3"
|
||||
"music" : "Snow.mp3",
|
||||
"tiles" : "SNOWTL",
|
||||
"code" : "sn"
|
||||
},
|
||||
"swamp" :
|
||||
{
|
||||
"moveCost" : 175,
|
||||
"minimapUnblocked" : [ 74, 134, 107 ],
|
||||
"minimapBlocked" : [ 33, 89, 66 ],
|
||||
"music" : "Swamp.mp3"
|
||||
"music" : "Swamp.mp3",
|
||||
"tiles" : "SWMPTL",
|
||||
"code" : "sw"
|
||||
},
|
||||
"rough" :
|
||||
{
|
||||
"moveCost" : 125,
|
||||
"minimapUnblocked" : [ 132, 113, 49 ],
|
||||
"minimapBlocked" : [ 99, 81, 33 ],
|
||||
"music" : "Rough.mp3"
|
||||
"music" : "Rough.mp3",
|
||||
"tiles" : "ROUGTL",
|
||||
"code" : "rg"
|
||||
},
|
||||
"subterra" :
|
||||
{
|
||||
"moveCost" : 100,
|
||||
"minimapUnblocked" : [ 132, 48, 0 ],
|
||||
"minimapBlocked" : [ 90, 8, 0 ],
|
||||
"music" : "Underground.mp3"
|
||||
"music" : "Underground.mp3",
|
||||
"tiles" : "SUBBTL",
|
||||
"type" : "SUB",
|
||||
"code" : "sb"
|
||||
},
|
||||
"lava" :
|
||||
{
|
||||
"moveCost" : 100,
|
||||
"minimapUnblocked" : [ 74, 73, 74 ],
|
||||
"minimapBlocked" : [ 41, 40, 41 ],
|
||||
"music" : "Lava.mp3"
|
||||
"music" : "Lava.mp3",
|
||||
"tiles" : "LAVATL",
|
||||
"code" : "lv"
|
||||
},
|
||||
"water" :
|
||||
{
|
||||
"moveCost" : 100,
|
||||
"minimapUnblocked" : [ 8, 81, 148 ],
|
||||
"minimapBlocked" : [ 8, 81, 148 ],
|
||||
"music" : "Water.mp3"
|
||||
"music" : "Water.mp3",
|
||||
"tiles" : "WATRTL",
|
||||
"type" : "WATER",
|
||||
"code" : "wt"
|
||||
},
|
||||
"rock" :
|
||||
{
|
||||
"moveCost" : -1,
|
||||
"minimapUnblocked" : [ 0, 0, 0 ],
|
||||
"minimapBlocked" : [ 0, 0, 0 ],
|
||||
"music" : "Underground.mp3" // Impossible in H3
|
||||
"music" : "Underground.mp3", // Impossible in H3
|
||||
"tiles" : "ROCKTL",
|
||||
"type" : "ROCK",
|
||||
"code" : "rc"
|
||||
}
|
||||
}
|
||||
|
@ -102,19 +102,8 @@ public:
|
||||
h & constituentOf;
|
||||
h & aClass;
|
||||
h & id;
|
||||
if(version >= 759)
|
||||
{
|
||||
h & identifier;
|
||||
}
|
||||
|
||||
if(version >= 771)
|
||||
{
|
||||
h & warMachine;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
fillWarMachine();
|
||||
}
|
||||
h & identifier;
|
||||
h & warMachine;
|
||||
}
|
||||
|
||||
CArtifact();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "CGameState.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "Terrain.h"
|
||||
#include "StringConstants.h"
|
||||
#include "serializer/JsonDeserializer.h"
|
||||
#include "serializer/JsonUpdater.h"
|
||||
@ -282,13 +283,13 @@ std::string CCreature::nodeName() const
|
||||
return "\"" + namePl + "\"";
|
||||
}
|
||||
|
||||
bool CCreature::isItNativeTerrain(ETerrainType::EETerrainType terrain) const
|
||||
bool CCreature::isItNativeTerrain(const Terrain & terrain) const
|
||||
{
|
||||
auto native = getNativeTerrain();
|
||||
return native == terrain || native == ETerrainType::ANY_TERRAIN;
|
||||
return native == terrain || native == Terrain::ANY;
|
||||
}
|
||||
|
||||
ETerrainType::EETerrainType CCreature::getNativeTerrain() const
|
||||
Terrain CCreature::getNativeTerrain() const
|
||||
{
|
||||
const std::string cachingStringBlocksRetaliation = "type_NO_TERRAIN_PENALTY";
|
||||
static const auto selectorBlocksRetaliation = Selector::type()(Bonus::NO_TERRAIN_PENALTY);
|
||||
@ -296,8 +297,8 @@ ETerrainType::EETerrainType CCreature::getNativeTerrain() const
|
||||
//this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses
|
||||
//and in the CGHeroInstance::getNativeTerrain() to setup mevement bonuses or/and penalties.
|
||||
return hasBonus(selectorBlocksRetaliation, selectorBlocksRetaliation)
|
||||
? ETerrainType::ANY_TERRAIN
|
||||
: (ETerrainType::EETerrainType)(*VLC->townh)[faction]->nativeTerrain;
|
||||
? Terrain::ANY
|
||||
: (Terrain)(*VLC->townh)[faction]->nativeTerrain;
|
||||
}
|
||||
|
||||
void CCreature::updateFrom(const JsonNode & data)
|
||||
@ -1340,11 +1341,6 @@ void CCreatureHandler::removeBonusesFromAllCreatures()
|
||||
allCreatures.removeBonuses(Selector::all);
|
||||
}
|
||||
|
||||
void CCreatureHandler::restoreAllCreaturesNodeType794()
|
||||
{
|
||||
allCreatures.setNodeType(CBonusSystemNode::ENodeTypes::ALL_CREATURES);
|
||||
}
|
||||
|
||||
void CCreatureHandler::buildBonusTreeForTiers()
|
||||
{
|
||||
for(CCreature * c : objects)
|
||||
|
@ -24,6 +24,7 @@ class CLegacyConfigParser;
|
||||
class CCreatureHandler;
|
||||
class CCreature;
|
||||
class JsonSerializeFormat;
|
||||
class Terrain;
|
||||
|
||||
class DLL_LINKAGE CCreature : public Creature, public CBonusSystemNode
|
||||
{
|
||||
@ -118,14 +119,14 @@ public:
|
||||
|
||||
ArtifactID warMachine;
|
||||
|
||||
bool isItNativeTerrain(ETerrainType::EETerrainType terrain) const;
|
||||
bool isItNativeTerrain(const Terrain & terrain) const;
|
||||
/**
|
||||
Returns creature native terrain considering some terrain bonuses.
|
||||
@param considerBonus is used to avoid Dead Lock when this method is called inside getAllBonuses
|
||||
considerBonus = true is called from Pathfinder and fills actual nativeTerrain considering bonus(es).
|
||||
considerBonus = false is called on Battle init and returns already prepared nativeTerrain without Bonus system calling.
|
||||
*/
|
||||
ETerrainType::EETerrainType getNativeTerrain() const;
|
||||
Terrain getNativeTerrain() const;
|
||||
int32_t getIndex() const override;
|
||||
int32_t getIconIndex() const override;
|
||||
const std::string & getName() const override;
|
||||
@ -211,18 +212,8 @@ public:
|
||||
|
||||
h & doubleWide;
|
||||
h & special;
|
||||
if(version>=759)
|
||||
{
|
||||
h & identifier;
|
||||
}
|
||||
if(version >= 771)
|
||||
{
|
||||
h & warMachine;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
fillWarMachine();
|
||||
}
|
||||
h & identifier;
|
||||
h & warMachine;
|
||||
}
|
||||
|
||||
CCreature();
|
||||
@ -281,7 +272,6 @@ public:
|
||||
void addBonusForTier(int tier, const std::shared_ptr<Bonus> & b); //tier must be <1-7>
|
||||
void addBonusForAllCreatures(const std::shared_ptr<Bonus> & b); //due to CBonusSystem::addNewBonus(const std::shared_ptr<Bonus>& b);
|
||||
void removeBonusesFromAllCreatures();
|
||||
void restoreAllCreaturesNodeType794(); //restore ALL_CREATURES node type for old saves
|
||||
|
||||
CCreatureHandler();
|
||||
~CCreatureHandler();
|
||||
|
@ -574,7 +574,7 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
||||
{
|
||||
const TerrainTile *tile = getTile(t->bestLocation(), false);
|
||||
|
||||
if(!tile || tile->terType != ETerrainType::WATER)
|
||||
if(!tile || tile->terType.isLand())
|
||||
return EBuildingState::NO_WATER; //lack of water
|
||||
}
|
||||
|
||||
|
@ -963,8 +963,8 @@ void CGameState::initGrailPosition()
|
||||
const TerrainTile &t = map->getTile(int3(i, j, k));
|
||||
if(!t.blocked
|
||||
&& !t.visitable
|
||||
&& t.terType != ETerrainType::WATER
|
||||
&& t.terType != ETerrainType::ROCK
|
||||
&& t.terType.isLand()
|
||||
&& t.terType.isPassable()
|
||||
&& (int)map->grailPos.dist2dSQ(int3(i, j, k)) <= (map->grailRadius * map->grailRadius))
|
||||
allowedPos.push_back(int3(i,j,k));
|
||||
}
|
||||
@ -1940,31 +1940,31 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & ra
|
||||
if(map->isCoastalTile(tile)) //coastal tile is always ground
|
||||
return BFieldType::SAND_SHORE;
|
||||
|
||||
switch(t.terType)
|
||||
{
|
||||
case ETerrainType::DIRT:
|
||||
if(t.terType == Terrain("dirt"))
|
||||
return BFieldType(rand.nextInt(3, 5));
|
||||
case ETerrainType::SAND:
|
||||
if(t.terType == Terrain("sand"))
|
||||
return BFieldType::SAND_MESAS; //TODO: coast support
|
||||
case ETerrainType::GRASS:
|
||||
if(t.terType == Terrain("grass"))
|
||||
return BFieldType(rand.nextInt(6, 7));
|
||||
case ETerrainType::SNOW:
|
||||
if(t.terType == Terrain("snow"))
|
||||
return BFieldType(rand.nextInt(10, 11));
|
||||
case ETerrainType::SWAMP:
|
||||
if(t.terType == Terrain("swamp"))
|
||||
return BFieldType::SWAMP_TREES;
|
||||
case ETerrainType::ROUGH:
|
||||
if(t.terType == Terrain("rough"))
|
||||
return BFieldType::ROUGH;
|
||||
case ETerrainType::SUBTERRANEAN:
|
||||
if(t.terType.isUnderground())
|
||||
return BFieldType::SUBTERRANEAN;
|
||||
case ETerrainType::LAVA:
|
||||
if(t.terType == Terrain("lava"))
|
||||
return BFieldType::LAVA;
|
||||
case ETerrainType::WATER:
|
||||
if(t.terType.isWater())
|
||||
return BFieldType::SHIP;
|
||||
case ETerrainType::ROCK:
|
||||
if(!t.terType.isPassable())
|
||||
return BFieldType::ROCKLANDS;
|
||||
default:
|
||||
return BFieldType::NONE;
|
||||
}
|
||||
|
||||
//TODO: STUB, support new battlegrounds
|
||||
return BFieldType::DIRT_HILLS;
|
||||
|
||||
return BFieldType::NONE;
|
||||
}
|
||||
|
||||
UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
|
||||
@ -2145,7 +2145,7 @@ void CGameState::updateRumor()
|
||||
rumorId = *RandomGeneratorUtil::nextItem(sRumorTypes, rand);
|
||||
if(rumorId == RumorState::RUMOR_GRAIL)
|
||||
{
|
||||
rumorExtra = getTile(map->grailPos)->terType;
|
||||
rumorExtra = getTile(map->grailPos)->terType.id();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -227,14 +227,7 @@ public:
|
||||
h & hpool;
|
||||
h & globalEffects;
|
||||
h & rand;
|
||||
if(version >= 755) //save format backward compatibility
|
||||
{
|
||||
h & rumor;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
rumor = RumorState();
|
||||
}
|
||||
h & rumor;
|
||||
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "CModHandler.h"
|
||||
#include "GameConstants.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
size_t Unicode::getCharacterSize(char firstByte)
|
||||
{
|
||||
@ -309,6 +310,7 @@ void CGeneralTextHandler::readToVector(std::string sourceName, std::vector<std::
|
||||
|
||||
CGeneralTextHandler::CGeneralTextHandler()
|
||||
{
|
||||
std::vector<std::string> h3mTerrainNames;
|
||||
readToVector("DATA/VCDESC.TXT", victoryConditions);
|
||||
readToVector("DATA/LCDESC.TXT", lossCondtions);
|
||||
readToVector("DATA/TCOMMAND.TXT", tcommands);
|
||||
@ -317,7 +319,7 @@ CGeneralTextHandler::CGeneralTextHandler()
|
||||
readToVector("DATA/ADVEVENT.TXT", advobtxt);
|
||||
readToVector("DATA/XTRAINFO.TXT", xtrainfo);
|
||||
readToVector("DATA/RESTYPES.TXT", restypes);
|
||||
readToVector("DATA/TERRNAME.TXT", terrainNames);
|
||||
readToVector("DATA/TERRNAME.TXT", h3mTerrainNames);
|
||||
readToVector("DATA/RANDSIGN.TXT", randsign);
|
||||
readToVector("DATA/CRGEN1.TXT", creGens);
|
||||
readToVector("DATA/CRGEN4.TXT", creGens4);
|
||||
@ -331,6 +333,17 @@ CGeneralTextHandler::CGeneralTextHandler()
|
||||
readToVector("DATA/HEROSCRN.TXT", heroscrn);
|
||||
readToVector("DATA/TENTCOLR.TXT", tentColors);
|
||||
readToVector("DATA/SKILLLEV.TXT", levels);
|
||||
|
||||
for(int i = 0; i < h3mTerrainNames.size(); ++i)
|
||||
{
|
||||
terrainNames[Terrain::createTerrainTypeH3M(i)] = h3mTerrainNames[i];
|
||||
}
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
if(!Terrain::Manager::getInfo(terrain).terrainText.empty())
|
||||
terrainNames[terrain] = Terrain::Manager::getInfo(terrain).terrainText;
|
||||
}
|
||||
|
||||
|
||||
static const char * QE_MOD_COMMANDS = "DATA/QECOMMANDS.TXT";
|
||||
if (CResourceHandler::get()->existsResource(ResourceID(QE_MOD_COMMANDS, EResType::TEXT)))
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
std::vector<std::string> advobtxt;
|
||||
std::vector<std::string> xtrainfo;
|
||||
std::vector<std::string> restypes; //names of resources
|
||||
std::vector<std::string> terrainNames;
|
||||
std::map<std::string, std::string> terrainNames;
|
||||
std::vector<std::string> randsign;
|
||||
std::vector<std::pair<std::string,std::string>> mines; //first - name; second - event description
|
||||
std::vector<std::string> seerEmpty;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "CCreatureHandler.h"
|
||||
#include "CModHandler.h"
|
||||
#include "CTownHandler.h"
|
||||
#include "Terrain.h"
|
||||
#include "mapObjects/CObjectHandler.h" //for hero specialty
|
||||
#include "CSkillHandler.h"
|
||||
#include <math.h>
|
||||
@ -176,7 +177,7 @@ std::vector<BattleHex> CObstacleInfo::getBlocked(BattleHex hex) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CObstacleInfo::isAppropriate(ETerrainType terrainType, int specialBattlefield) const
|
||||
bool CObstacleInfo::isAppropriate(Terrain terrainType, int specialBattlefield) const
|
||||
{
|
||||
if(specialBattlefield != -1)
|
||||
return vstd::contains(allowedSpecialBfields, specialBattlefield);
|
||||
@ -376,9 +377,9 @@ CHeroHandler::CHeroHandler()
|
||||
{
|
||||
loadObstacles();
|
||||
loadTerrains();
|
||||
for (int i = 0; i < GameConstants::TERRAIN_TYPES; ++i)
|
||||
for(int i = 0; i < Terrain::Manager::terrains().size(); ++i)
|
||||
{
|
||||
VLC->modh->identifiers.registerObject("core", "terrain", GameConstants::TERRAIN_NAMES[i], i);
|
||||
VLC->modh->identifiers.registerObject("core", "terrain", Terrain::Manager::terrains()[i], i);
|
||||
}
|
||||
loadBallistics();
|
||||
loadExperience();
|
||||
@ -826,7 +827,8 @@ void CHeroHandler::loadObstacles()
|
||||
obi.defName = obs["defname"].String();
|
||||
obi.width = static_cast<si32>(obs["width"].Float());
|
||||
obi.height = static_cast<si32>(obs["height"].Float());
|
||||
obi.allowedTerrains = obs["allowedTerrain"].convertTo<std::vector<ETerrainType> >();
|
||||
for(auto & t : obs["allowedTerrain"].Vector())
|
||||
obi.allowedTerrains.emplace_back(t.String());
|
||||
obi.allowedSpecialBfields = obs["specialBattlefields"].convertTo<std::vector<BFieldType> >();
|
||||
obi.blockedTiles = obs["blockedTiles"].convertTo<std::vector<si16> >();
|
||||
obi.isAbsoluteObstacle = absolute;
|
||||
@ -1029,11 +1031,10 @@ ui64 CHeroHandler::reqExp (ui32 level) const
|
||||
|
||||
void CHeroHandler::loadTerrains()
|
||||
{
|
||||
const JsonNode config(ResourceID("config/terrains.json"));
|
||||
|
||||
terrCosts.reserve(GameConstants::TERRAIN_TYPES);
|
||||
for(const std::string & name : GameConstants::TERRAIN_NAMES)
|
||||
terrCosts.push_back((int)config[name]["moveCost"].Float());
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
terrCosts[terrain] = Terrain::Manager::getInfo(terrain).moveCost;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<bool> CHeroHandler::getDefaultAllowed() const
|
||||
|
@ -26,6 +26,7 @@ struct BattleHex;
|
||||
class JsonNode;
|
||||
class CRandomGenerator;
|
||||
class JsonSerializeFormat;
|
||||
class Terrain;
|
||||
|
||||
struct SSpecialtyInfo
|
||||
{ si32 type;
|
||||
@ -119,15 +120,7 @@ public:
|
||||
h & initialArmy;
|
||||
h & heroClass;
|
||||
h & secSkillsInit;
|
||||
if(version >= 781)
|
||||
{
|
||||
h & specialty;
|
||||
}
|
||||
else
|
||||
{
|
||||
h & specDeprecated;
|
||||
h & specialtyDeprecated;
|
||||
}
|
||||
h & specialty;
|
||||
h & spells;
|
||||
h & haveSpellBook;
|
||||
h & sex;
|
||||
@ -141,14 +134,8 @@ public:
|
||||
h & iconSpecLarge;
|
||||
h & portraitSmall;
|
||||
h & portraitLarge;
|
||||
if(version >= 759)
|
||||
{
|
||||
h & identifier;
|
||||
}
|
||||
if(version >= 790)
|
||||
{
|
||||
h & battleImage;
|
||||
}
|
||||
h & identifier;
|
||||
h & battleImage;
|
||||
}
|
||||
};
|
||||
|
||||
@ -211,16 +198,7 @@ public:
|
||||
h & identifier;
|
||||
h & name;
|
||||
h & faction;
|
||||
if(version >= 800)
|
||||
{
|
||||
h & id;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui8 old_id = 0;
|
||||
h & old_id;
|
||||
id = HeroClassID(old_id);
|
||||
}
|
||||
h & id;
|
||||
h & defaultTavernChance;
|
||||
h & primarySkillInitial;
|
||||
h & primarySkillLowLevel;
|
||||
@ -248,7 +226,7 @@ struct DLL_LINKAGE CObstacleInfo
|
||||
{
|
||||
si32 ID;
|
||||
std::string defName;
|
||||
std::vector<ETerrainType> allowedTerrains;
|
||||
std::vector<Terrain> allowedTerrains;
|
||||
std::vector<BFieldType> allowedSpecialBfields;
|
||||
|
||||
ui8 isAbsoluteObstacle; //there may only one such obstacle in battle and its position is always the same
|
||||
@ -257,7 +235,7 @@ struct DLL_LINKAGE CObstacleInfo
|
||||
|
||||
std::vector<BattleHex> getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex'
|
||||
|
||||
bool isAppropriate(ETerrainType terrainType, int specialBattlefield = -1) const;
|
||||
bool isAppropriate(Terrain terrainType, int specialBattlefield = -1) const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -315,7 +293,7 @@ public:
|
||||
CHeroClassHandler classes;
|
||||
|
||||
//default costs of going through terrains. -1 means terrain is impassable
|
||||
std::vector<int> terrCosts;
|
||||
std::map<Terrain, int> terrCosts;
|
||||
|
||||
struct SBallisticsLevelInfo
|
||||
{
|
||||
|
@ -163,6 +163,7 @@ set(lib_SRCS
|
||||
StartInfo.cpp
|
||||
ResourceSet.cpp
|
||||
ScriptHandler.cpp
|
||||
Terrain.cpp
|
||||
VCMIDirs.cpp
|
||||
VCMI_Lib.cpp
|
||||
|
||||
@ -385,6 +386,7 @@ set(lib_HEADERS
|
||||
ScopeGuard.h
|
||||
StartInfo.h
|
||||
StringConstants.h
|
||||
Terrain.h
|
||||
UnlockGuard.h
|
||||
VCMIDirs.h
|
||||
vcmi_endian.h
|
||||
|
@ -303,32 +303,9 @@ public:
|
||||
h & ALL_CREATURES_GET_DOUBLE_MONTHS;
|
||||
h & MAX_HEROES_AVAILABLE_PER_PLAYER;
|
||||
h & MAX_HEROES_ON_MAP_PER_PLAYER;
|
||||
if(version >= 756)
|
||||
{
|
||||
h & WINNING_HERO_WITH_NO_TROOPS_RETREATS;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
WINNING_HERO_WITH_NO_TROOPS_RETREATS = true;
|
||||
}
|
||||
|
||||
if(version >= 776)
|
||||
{
|
||||
h & BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE = true;
|
||||
}
|
||||
|
||||
if(version >= 791)
|
||||
{
|
||||
h & NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS = false;
|
||||
}
|
||||
h & WINNING_HERO_WITH_NO_TROOPS_RETREATS;
|
||||
h & BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE;
|
||||
h & NO_RANDOM_SPECIAL_WEEKS_AND_MONTHS;
|
||||
}
|
||||
} settings;
|
||||
|
||||
|
@ -46,24 +46,19 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState
|
||||
for(pos.z=0; pos.z < sizes.z; ++pos.z)
|
||||
{
|
||||
const TerrainTile * tile = &gs->map->getTile(pos);
|
||||
switch(tile->terType)
|
||||
if(tile->terType.isWater())
|
||||
{
|
||||
case ETerrainType::ROCK:
|
||||
break;
|
||||
|
||||
case ETerrainType::WATER:
|
||||
resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility<ELayer::SAIL>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
if(useWaterWalking)
|
||||
resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility<ELayer::WATER>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
if(tile->terType.isLand())
|
||||
{
|
||||
resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility<ELayer::LAND>(pos, tile, fow, player, gs));
|
||||
if(useFlying)
|
||||
resetTile(pos, ELayer::AIR, PathfinderUtil::evaluateAccessibility<ELayer::AIR>(pos, tile, fow, player, gs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1012,8 +1007,7 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const
|
||||
|
||||
TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl)
|
||||
{
|
||||
noTerrainPenalty.reserve(ETerrainType::ROCK);
|
||||
for(int i = 0; i < ETerrainType::ROCK; i++)
|
||||
for(int i = 0; i < Terrain::Manager::terrains().size(); ++i)
|
||||
{
|
||||
noTerrainPenalty.push_back(static_cast<bool>(
|
||||
bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(i)))));
|
||||
@ -1179,7 +1173,7 @@ void CPathfinderHelper::getNeighbours(
|
||||
continue;
|
||||
|
||||
const TerrainTile & hlpt = map->getTile(hlp);
|
||||
if(hlpt.terType == ETerrainType::ROCK)
|
||||
if(!hlpt.terType.isPassable())
|
||||
continue;
|
||||
|
||||
// //we cannot visit things from blocked tiles
|
||||
@ -1189,18 +1183,18 @@ void CPathfinderHelper::getNeighbours(
|
||||
// }
|
||||
|
||||
/// Following condition let us avoid diagonal movement over coast when sailing
|
||||
if(srct.terType == ETerrainType::WATER && limitCoastSailing && hlpt.terType == ETerrainType::WATER && dir.x && dir.y) //diagonal move through water
|
||||
if(srct.terType.isWater() && limitCoastSailing && hlpt.terType.isWater() && dir.x && dir.y) //diagonal move through water
|
||||
{
|
||||
int3 hlp1 = tile,
|
||||
hlp2 = tile;
|
||||
hlp1.x += dir.x;
|
||||
hlp2.y += dir.y;
|
||||
|
||||
if(map->getTile(hlp1).terType != ETerrainType::WATER || map->getTile(hlp2).terType != ETerrainType::WATER)
|
||||
if(map->getTile(hlp1).terType.isLand() || map->getTile(hlp2).terType.isLand())
|
||||
continue;
|
||||
}
|
||||
|
||||
if(indeterminate(onLand) || onLand == (hlpt.terType != ETerrainType::WATER))
|
||||
if(indeterminate(onLand) || onLand == hlpt.terType.isLand())
|
||||
{
|
||||
vec.push_back(hlp);
|
||||
}
|
||||
@ -1238,7 +1232,7 @@ int CPathfinderHelper::getMovementCost(
|
||||
{
|
||||
ret = static_cast<int>(ret * (100.0 + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)) / 100.0);
|
||||
}
|
||||
else if(dt->terType == ETerrainType::WATER)
|
||||
else if(dt->terType.isWater())
|
||||
{
|
||||
if(hero->boat && ct->hasFavorableWinds() && dt->hasFavorableWinds())
|
||||
ret = static_cast<int>(ret * 0.666);
|
||||
@ -1266,7 +1260,7 @@ int CPathfinderHelper::getMovementCost(
|
||||
{
|
||||
std::vector<int3> vec;
|
||||
vec.reserve(8); //optimization
|
||||
getNeighbours(*dt, dst, vec, ct->terType != ETerrainType::WATER, true);
|
||||
getNeighbours(*dt, dst, vec, ct->terType.isLand(), true);
|
||||
for(auto & elem : vec)
|
||||
{
|
||||
int fcost = getMovementCost(dst, elem, nullptr, nullptr, left, false);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "IGameCallback.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "int3.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
#include <boost/heap/fibonacci_heap.hpp>
|
||||
|
||||
@ -521,7 +522,7 @@ struct DLL_LINKAGE TurnInfo
|
||||
TConstBonusListPtr bonuses;
|
||||
mutable int maxMovePointsLand;
|
||||
mutable int maxMovePointsWater;
|
||||
ETerrainType::EETerrainType nativeTerrain;
|
||||
Terrain nativeTerrain;
|
||||
|
||||
TurnInfo(const CGHeroInstance * Hero, const int Turn = 0);
|
||||
bool isLayerAvailable(const EPathfindingLayer layer) const;
|
||||
|
@ -67,14 +67,6 @@ public:
|
||||
h & dwellings;
|
||||
h & quests;
|
||||
h & visitedObjects;
|
||||
|
||||
if(version < 760)
|
||||
{
|
||||
//was: h & getBonusList();
|
||||
BonusList junk;
|
||||
h & junk;
|
||||
}
|
||||
|
||||
h & status;
|
||||
h & daysWithoutCastle;
|
||||
h & enteredLosingCheatCode;
|
||||
|
@ -35,12 +35,9 @@ public:
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & description;
|
||||
if(version >= 785)
|
||||
{
|
||||
h & iconSmall;
|
||||
h & iconMedium;
|
||||
h & iconLarge;
|
||||
}
|
||||
h & iconSmall;
|
||||
h & iconMedium;
|
||||
h & iconLarge;
|
||||
h & effects;
|
||||
}
|
||||
};
|
||||
@ -78,10 +75,7 @@ public:
|
||||
h & id;
|
||||
h & identifier;
|
||||
h & name;
|
||||
if(version >= 785)
|
||||
{
|
||||
h & gainChance;
|
||||
}
|
||||
h & gainChance;
|
||||
h & levels;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ CStack::CStack(const CStackInstance * Base, PlayerColor O, int I, ui8 Side, Slot
|
||||
slot(S),
|
||||
side(Side),
|
||||
initialPosition(),
|
||||
nativeTerrain(ETerrainType::WRONG)
|
||||
nativeTerrain()
|
||||
{
|
||||
health.init(); //???
|
||||
}
|
||||
@ -40,7 +40,7 @@ CStack::CStack(const CStackInstance * Base, PlayerColor O, int I, ui8 Side, Slot
|
||||
CStack::CStack()
|
||||
: CBonusSystemNode(STACK_BATTLE),
|
||||
CUnitState(),
|
||||
nativeTerrain(ETerrainType::WRONG)
|
||||
nativeTerrain()
|
||||
{
|
||||
base = nullptr;
|
||||
type = nullptr;
|
||||
@ -328,11 +328,11 @@ bool CStack::canBeHealed() const
|
||||
bool CStack::isOnNativeTerrain() const
|
||||
{
|
||||
//this code is called from CreatureTerrainLimiter::limit on battle start
|
||||
auto res = nativeTerrain == ETerrainType::ANY_TERRAIN || nativeTerrain == battle->getTerrainType();
|
||||
auto res = nativeTerrain == Terrain::ANY || nativeTerrain == battle->getTerrainType();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CStack::isOnTerrain(int terrain) const
|
||||
bool CStack::isOnTerrain(const Terrain & terrain) const
|
||||
{
|
||||
return battle->getTerrainType() == terrain;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "CCreatureHandler.h" //todo: remove
|
||||
#include "battle/BattleHex.h"
|
||||
#include "mapObjects/CGHeroInstance.h" // for commander serialization
|
||||
#include "Terrain.h"
|
||||
|
||||
#include "battle/CUnitState.h"
|
||||
|
||||
@ -28,7 +29,7 @@ public:
|
||||
|
||||
ui32 ID; //unique ID of stack
|
||||
const CCreature * type;
|
||||
ETerrainType::EETerrainType nativeTerrain; //tmp variable to save native terrain value on battle init
|
||||
Terrain nativeTerrain; //tmp variable to save native terrain value on battle init
|
||||
ui32 baseAmount;
|
||||
|
||||
PlayerColor owner; //owner - player color (255 for neutrals)
|
||||
@ -50,7 +51,7 @@ public:
|
||||
|
||||
bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines
|
||||
bool isOnNativeTerrain() const;
|
||||
bool isOnTerrain(int terrain) const;
|
||||
bool isOnTerrain(const Terrain & terrain) const;
|
||||
|
||||
ui32 level() const;
|
||||
si32 magicResistance() const override; //include aura of resistance
|
||||
|
@ -26,6 +26,10 @@
|
||||
|
||||
const int NAMES_PER_TOWN=16; // number of town names per faction in H3 files. Json can define any number
|
||||
|
||||
const Terrain CTownHandler::defaultGoodTerrain{"grass"};
|
||||
const Terrain CTownHandler::defaultEvilTerrain{"lava"};
|
||||
const Terrain CTownHandler::defaultNeutralTerrain{"rough"};
|
||||
|
||||
const std::map<std::string, CBuilding::EBuildMode> CBuilding::MODES =
|
||||
{
|
||||
{ "normal", CBuilding::BUILD_NORMAL },
|
||||
@ -77,135 +81,11 @@ si32 CBuilding::getDistance(BuildingID buildID) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CBuilding::deserializeFix()
|
||||
{
|
||||
//default value for mode was broken, have to fix it here for old saves (v777 and older)
|
||||
switch(mode)
|
||||
{
|
||||
case BUILD_NORMAL:
|
||||
case BUILD_AUTO:
|
||||
case BUILD_SPECIAL:
|
||||
case BUILD_GRAIL:
|
||||
break;
|
||||
|
||||
default:
|
||||
mode = BUILD_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CBuilding::addNewBonus(std::shared_ptr<Bonus> b, BonusList & bonusList)
|
||||
{
|
||||
bonusList.push_back(b);
|
||||
}
|
||||
|
||||
const JsonNode & CBuilding::getCurrentFactionForUpdateRoutine() const
|
||||
{
|
||||
const auto & faction = town->faction->identifier;
|
||||
const auto & factionsContent = (*VLC->modh->content)["factions"];
|
||||
const auto & coreData = factionsContent.modData.at("core");
|
||||
const auto & coreFactions = coreData.modData;
|
||||
const auto & currentFaction = coreFactions[faction];
|
||||
|
||||
if(currentFaction.isNull())
|
||||
{
|
||||
const auto index = faction.find(':');
|
||||
const std::string factionDir = index == std::string::npos ? faction : faction.substr(0, index);
|
||||
const auto it = factionsContent.modData.find(factionDir);
|
||||
|
||||
if(it == factionsContent.modData.end())
|
||||
{
|
||||
logMod->warn("Warning: Update old save failed: Faction: '%s' is not found.", factionDir);
|
||||
return currentFaction;
|
||||
}
|
||||
const std::string modFaction = index == std::string::npos ? faction : faction.substr(index + 1);
|
||||
return it->second.modData[modFaction];
|
||||
}
|
||||
return currentFaction;
|
||||
}
|
||||
|
||||
void CBuilding::update792()
|
||||
{
|
||||
subId = BuildingSubID::NONE;
|
||||
height = ETowerHeight::HEIGHT_NO_TOWER;
|
||||
|
||||
if(!bid.IsSpecialOrGrail() || town == nullptr || town->faction == nullptr || town->faction->identifier.empty())
|
||||
return;
|
||||
|
||||
const auto buildingName = CTownHandler::getMappedValue<std::string, BuildingID>(bid, std::string(), MappedKeys::BUILDING_TYPES_TO_NAMES);
|
||||
|
||||
if(buildingName.empty())
|
||||
return;
|
||||
|
||||
auto & currentFaction = getCurrentFactionForUpdateRoutine();
|
||||
|
||||
if(!currentFaction.isNull() && currentFaction.getType() == JsonNode::JsonType::DATA_STRUCT)
|
||||
{
|
||||
const auto & buildings = currentFaction["town"]["buildings"];
|
||||
const auto & currentBuilding = buildings[buildingName];
|
||||
|
||||
subId = CTownHandler::getMappedValue<BuildingSubID::EBuildingSubID>(currentBuilding["type"], BuildingSubID::NONE, MappedKeys::SPECIAL_BUILDINGS);
|
||||
height = subId == BuildingSubID::LOOKOUT_TOWER || bid == BuildingID::GRAIL
|
||||
? CTownHandler::getMappedValue<CBuilding::ETowerHeight>(currentBuilding["height"], CBuilding::HEIGHT_NO_TOWER, CBuilding::TOWER_TYPES)
|
||||
: height = CBuilding::HEIGHT_NO_TOWER;
|
||||
}
|
||||
}
|
||||
|
||||
void CBuilding::update794()
|
||||
{
|
||||
if(bid == BuildingID::TAVERN || subId == BuildingSubID::BROTHERHOOD_OF_SWORD)
|
||||
{
|
||||
VLC->townh->addBonusesForVanilaBuilding(this);
|
||||
return;
|
||||
}
|
||||
if(!bid.IsSpecialOrGrail())
|
||||
return;
|
||||
|
||||
VLC->townh->addBonusesForVanilaBuilding(this);
|
||||
|
||||
if(!buildingBonuses.empty() //addBonusesForVanilaBuilding has done all work
|
||||
|| town->faction == nullptr //or faction data is not valid
|
||||
|| town->faction->identifier.empty())
|
||||
return;
|
||||
|
||||
const auto buildingName = CTownHandler::getMappedValue<std::string, BuildingID>(bid, std::string(), MappedKeys::BUILDING_TYPES_TO_NAMES, false);
|
||||
|
||||
if(buildingName.empty())
|
||||
return;
|
||||
|
||||
auto & currentFaction = getCurrentFactionForUpdateRoutine();
|
||||
|
||||
if(currentFaction.isNull() || currentFaction.getType() != JsonNode::JsonType::DATA_STRUCT)
|
||||
return;
|
||||
|
||||
const auto & buildings = currentFaction["town"]["buildings"];
|
||||
const auto & currentBuilding = buildings[buildingName];
|
||||
|
||||
CTownHandler::loadSpecialBuildingBonuses(currentBuilding["bonuses"], buildingBonuses, this);
|
||||
CTownHandler::loadSpecialBuildingBonuses(currentBuilding["onVisitBonuses"], onVisitBonuses, this);
|
||||
|
||||
if(!onVisitBonuses.empty())
|
||||
{
|
||||
if(subId == BuildingSubID::NONE)
|
||||
subId = BuildingSubID::CUSTOM_VISITING_BONUS;
|
||||
|
||||
for(auto & bonus : onVisitBonuses)
|
||||
bonus->sid = Bonus::getSid32(town->faction->index, bid);
|
||||
}
|
||||
const auto & overriddenBids = currentBuilding["overrides"];
|
||||
|
||||
if(overriddenBids.isNull())
|
||||
return;
|
||||
|
||||
auto scope = town->getBuildingScope();
|
||||
|
||||
for(auto b : overriddenBids.Vector())
|
||||
{
|
||||
auto bid = BuildingID(VLC->modh->identifiers.getIdentifier(scope, b).get());
|
||||
overrideBids.insert(bid);
|
||||
}
|
||||
}
|
||||
|
||||
CFaction::CFaction()
|
||||
{
|
||||
town = nullptr;
|
||||
@ -1062,9 +942,9 @@ void CTownHandler::loadPuzzle(CFaction &faction, const JsonNode &source)
|
||||
assert(faction.puzzleMap.size() == GameConstants::PUZZLE_MAP_PIECES);
|
||||
}
|
||||
|
||||
ETerrainType::EETerrainType CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const
|
||||
Terrain CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const
|
||||
{
|
||||
ETerrainType::EETerrainType terrain = defaultGoodTerrain;
|
||||
Terrain terrain = defaultGoodTerrain;
|
||||
|
||||
switch(alignment)
|
||||
{
|
||||
@ -1095,19 +975,15 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode
|
||||
faction->alignment = EAlignment::NEUTRAL;
|
||||
else
|
||||
faction->alignment = static_cast<EAlignment::EAlignment>(alignment);
|
||||
|
||||
auto nativeTerrain = source["nativeTerrain"];
|
||||
int terrainNum = nativeTerrain.isNull()
|
||||
? -1
|
||||
: vstd::find_pos(GameConstants::TERRAIN_NAMES, nativeTerrain.String());
|
||||
|
||||
auto preferUndergound = source["preferUndergroundPlacement"];
|
||||
faction->preferUndergroundPlacement = preferUndergound.isNull() ? false : preferUndergound.Bool();
|
||||
|
||||
//Contructor is not called here, but operator=
|
||||
faction->nativeTerrain = terrainNum < 0
|
||||
auto nativeTerrain = source["nativeTerrain"];
|
||||
faction->nativeTerrain = nativeTerrain.isNull()
|
||||
? getDefaultTerrainForAlignment(faction->alignment)
|
||||
: static_cast<ETerrainType::EETerrainType>(terrainNum);
|
||||
: Terrain(nativeTerrain.String());
|
||||
|
||||
if (!source["town"].isNull())
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "LogicalExpression.h"
|
||||
#include "battle/BattleHex.h"
|
||||
#include "HeroBonus.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
class CLegacyConfigParser;
|
||||
class JsonNode;
|
||||
@ -111,8 +112,6 @@ public:
|
||||
}
|
||||
|
||||
void addNewBonus(std::shared_ptr<Bonus> b, BonusList & bonusList);
|
||||
void update792();
|
||||
void update794();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -126,33 +125,14 @@ public:
|
||||
h & requirements;
|
||||
h & upgrade;
|
||||
h & mode;
|
||||
|
||||
if(version >= 792)
|
||||
{
|
||||
h & subId;
|
||||
h & height;
|
||||
}
|
||||
if(!h.saving && version < 793)
|
||||
update792(); //adjust height, subId
|
||||
|
||||
if(version >= 794)
|
||||
{
|
||||
h & overrideBids;
|
||||
h & buildingBonuses;
|
||||
h & onVisitBonuses;
|
||||
}
|
||||
else if(!h.saving)
|
||||
update794(); //populate overrideBids, buildingBonuses, onVisitBonuses
|
||||
|
||||
if(!h.saving)
|
||||
deserializeFix();
|
||||
h & subId;
|
||||
h & height;
|
||||
h & overrideBids;
|
||||
h & buildingBonuses;
|
||||
h & onVisitBonuses;
|
||||
}
|
||||
|
||||
friend class CTownHandler;
|
||||
|
||||
private:
|
||||
void deserializeFix();
|
||||
const JsonNode & getCurrentFactionForUpdateRoutine() const;
|
||||
};
|
||||
|
||||
/// This is structure used only by client
|
||||
@ -205,7 +185,7 @@ public:
|
||||
|
||||
TFaction index;
|
||||
|
||||
ETerrainType nativeTerrain;
|
||||
Terrain nativeTerrain;
|
||||
EAlignment::EAlignment alignment;
|
||||
bool preferUndergroundPlacement;
|
||||
|
||||
@ -356,14 +336,7 @@ public:
|
||||
h & warMachine;
|
||||
h & clientInfo;
|
||||
h & moatDamage;
|
||||
if(version >= 758)
|
||||
{
|
||||
h & moatHexes;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
moatHexes = defaultMoatHexes();
|
||||
}
|
||||
h & moatHexes;
|
||||
h & defaultTavernChance;
|
||||
}
|
||||
|
||||
@ -385,9 +358,9 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
|
||||
std::vector<BuildingRequirementsHelper> requirementsToLoad;
|
||||
std::vector<BuildingRequirementsHelper> overriddenBidsToLoad; //list of buildings, which bonuses should be overridden.
|
||||
|
||||
const static ETerrainType::EETerrainType defaultGoodTerrain = ETerrainType::EETerrainType::GRASS;
|
||||
const static ETerrainType::EETerrainType defaultEvilTerrain = ETerrainType::EETerrainType::LAVA;
|
||||
const static ETerrainType::EETerrainType defaultNeutralTerrain = ETerrainType::EETerrainType::ROUGH;
|
||||
const static Terrain defaultGoodTerrain;
|
||||
const static Terrain defaultEvilTerrain;
|
||||
const static Terrain defaultNeutralTerrain;
|
||||
|
||||
static TPropagatorPtr & emptyPropagator();
|
||||
|
||||
@ -418,7 +391,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase<FactionID, Faction, CFactio
|
||||
|
||||
void loadPuzzle(CFaction & faction, const JsonNode & source);
|
||||
|
||||
ETerrainType::EETerrainType getDefaultTerrainForAlignment(EAlignment::EAlignment aligment) const;
|
||||
Terrain getDefaultTerrainForAlignment(EAlignment::EAlignment aligment) const;
|
||||
void loadRandomFaction();
|
||||
|
||||
|
||||
@ -450,15 +423,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & objects;
|
||||
|
||||
if(version >= 770)
|
||||
{
|
||||
h & randomTown;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
loadRandomFaction();
|
||||
}
|
||||
h & randomTown;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -236,38 +236,6 @@ std::ostream & operator<<(std::ostream & os, const EActionType actionType)
|
||||
else return os << it->second;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const ETerrainType terrainType)
|
||||
{
|
||||
static const std::map<ETerrainType::EETerrainType, std::string> terrainTypeToString =
|
||||
{
|
||||
#define DEFINE_ELEMENT(element) {ETerrainType::element, #element}
|
||||
DEFINE_ELEMENT(WRONG),
|
||||
DEFINE_ELEMENT(BORDER),
|
||||
DEFINE_ELEMENT(DIRT),
|
||||
DEFINE_ELEMENT(SAND),
|
||||
DEFINE_ELEMENT(GRASS),
|
||||
DEFINE_ELEMENT(SNOW),
|
||||
DEFINE_ELEMENT(SWAMP),
|
||||
DEFINE_ELEMENT(ROUGH),
|
||||
DEFINE_ELEMENT(SUBTERRANEAN),
|
||||
DEFINE_ELEMENT(LAVA),
|
||||
DEFINE_ELEMENT(WATER),
|
||||
DEFINE_ELEMENT(ROCK)
|
||||
#undef DEFINE_ELEMENT
|
||||
};
|
||||
|
||||
auto it = terrainTypeToString.find(terrainType.num);
|
||||
if (it == terrainTypeToString.end()) return os << "<Unknown type>";
|
||||
else return os << it->second;
|
||||
}
|
||||
|
||||
std::string ETerrainType::toString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << *this;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const EPathfindingLayer pathfindingLayer)
|
||||
{
|
||||
static const std::map<EPathfindingLayer::EEPathfindingLayer, std::string> pathfinderLayerToString
|
||||
|
@ -61,7 +61,6 @@ namespace GameConstants
|
||||
|
||||
const int SKILL_QUANTITY=28;
|
||||
const int PRIMARY_SKILLS=4;
|
||||
const int TERRAIN_TYPES=10;
|
||||
const int RESOURCE_QUANTITY=8;
|
||||
const int HEROES_PER_TYPE=8; //amount of heroes of each type
|
||||
|
||||
@ -678,21 +677,8 @@ enum class ETeleportChannelType
|
||||
};
|
||||
|
||||
|
||||
namespace ERiverType
|
||||
{
|
||||
enum ERiverType
|
||||
{
|
||||
NO_RIVER, CLEAR_RIVER, ICY_RIVER, MUDDY_RIVER, LAVA_RIVER
|
||||
};
|
||||
}
|
||||
|
||||
namespace ERoadType
|
||||
{
|
||||
enum ERoadType
|
||||
{
|
||||
NO_ROAD, DIRT_ROAD, GRAVEL_ROAD, COBBLESTONE_ROAD
|
||||
};
|
||||
}
|
||||
static std::vector<std::string> RIVER_NAMES {"", "rw", "ri", "rm", "rl"};
|
||||
static std::vector<std::string> ROAD_NAMES {"", "pd", "pg", "pc"};
|
||||
|
||||
class Obj
|
||||
{
|
||||
@ -912,36 +898,6 @@ enum class EActionType : int32_t
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const EActionType actionType);
|
||||
|
||||
class DLL_LINKAGE ETerrainType
|
||||
{
|
||||
public:
|
||||
enum EETerrainType
|
||||
{
|
||||
ANY_TERRAIN = -3,
|
||||
WRONG = -2, BORDER = -1, DIRT, SAND, GRASS, SNOW, SWAMP,
|
||||
ROUGH, SUBTERRANEAN, LAVA, WATER, ROCK // ROCK is also intended to be max value.
|
||||
};
|
||||
|
||||
ETerrainType(EETerrainType _num = WRONG) : num(_num)
|
||||
{}
|
||||
|
||||
ETerrainType& operator=(EETerrainType _num)
|
||||
{
|
||||
num = _num;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_LIKE_CLASS_COMMON(ETerrainType, EETerrainType)
|
||||
|
||||
EETerrainType num;
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const ETerrainType terrainType);
|
||||
|
||||
ID_LIKE_OPERATORS(ETerrainType, ETerrainType::EETerrainType)
|
||||
|
||||
class DLL_LINKAGE EDiggingStatus
|
||||
{
|
||||
public:
|
||||
|
@ -2078,13 +2078,8 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
|
||||
return nodeType == dest->getNodeType();
|
||||
}
|
||||
|
||||
CreatureTerrainLimiter::CreatureTerrainLimiter(int TerrainType)
|
||||
: terrainType(TerrainType)
|
||||
{
|
||||
}
|
||||
|
||||
CreatureTerrainLimiter::CreatureTerrainLimiter()
|
||||
: terrainType(-1)
|
||||
: terrainType()
|
||||
{
|
||||
|
||||
}
|
||||
@ -2094,7 +2089,7 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const
|
||||
const CStack *stack = retrieveStackBattle(&context.node);
|
||||
if(stack)
|
||||
{
|
||||
if(terrainType == -1)//terrainType not specified = native
|
||||
if(terrainType.isNative())//terrainType not specified = native
|
||||
return !stack->isOnNativeTerrain();
|
||||
return !stack->isOnTerrain(terrainType);
|
||||
}
|
||||
@ -2105,7 +2100,7 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const
|
||||
std::string CreatureTerrainLimiter::toString() const
|
||||
{
|
||||
boost::format fmt("CreatureTerrainLimiter(terrainType=%s)");
|
||||
fmt % (terrainType >= 0 ? GameConstants::TERRAIN_NAMES[terrainType] : "native");
|
||||
fmt % (terrainType.isNative() ? "native" : static_cast<std::string>(terrainType));
|
||||
return fmt.str();
|
||||
}
|
||||
|
||||
@ -2114,8 +2109,8 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
|
||||
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
|
||||
|
||||
root["type"].String() = "CREATURE_TERRAIN_LIMITER";
|
||||
if(terrainType >= 0)
|
||||
root["parameters"].Vector().push_back(JsonUtils::stringNode(GameConstants::TERRAIN_NAMES[terrainType]));
|
||||
if(!terrainType.isNative())
|
||||
root["parameters"].Vector().push_back(JsonUtils::stringNode(terrainType));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "GameConstants.h"
|
||||
#include "JsonNode.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
class CCreature;
|
||||
struct Bonus;
|
||||
@ -438,36 +439,15 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>
|
||||
h & val;
|
||||
h & sid;
|
||||
h & description;
|
||||
if(version >= 783)
|
||||
{
|
||||
h & additionalInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
additionalInfo.resize(1, -1);
|
||||
h & additionalInfo[0];
|
||||
}
|
||||
h & additionalInfo;
|
||||
h & turnsRemain;
|
||||
h & valType;
|
||||
if(version >= 784)
|
||||
{
|
||||
h & stacking;
|
||||
}
|
||||
h & stacking;
|
||||
h & effectRange;
|
||||
h & limiter;
|
||||
h & propagator;
|
||||
if(version >= 781)
|
||||
{
|
||||
h & updater;
|
||||
}
|
||||
if(version >= 801)
|
||||
{
|
||||
h & propagationUpdater;
|
||||
}
|
||||
if(version < 801 && !h.saving) //Opposite Side bonuses are introduced
|
||||
{
|
||||
updateOppositeBonuses();
|
||||
}
|
||||
h & updater;
|
||||
h & propagationUpdater;
|
||||
}
|
||||
|
||||
template <typename Ptr>
|
||||
@ -999,10 +979,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & static_cast<ILimiter&>(*this);
|
||||
if(version >= 786)
|
||||
{
|
||||
h & limiters;
|
||||
}
|
||||
h & limiters;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1081,9 +1058,9 @@ public:
|
||||
class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain
|
||||
{
|
||||
public:
|
||||
int terrainType;
|
||||
Terrain terrainType;
|
||||
CreatureTerrainLimiter();
|
||||
CreatureTerrainLimiter(int TerrainType);
|
||||
CreatureTerrainLimiter(const Terrain& terrain);
|
||||
|
||||
int limit(const BonusLimitationContext &context) const override;
|
||||
virtual std::string toString() const override;
|
||||
|
@ -49,7 +49,7 @@ void CPrivilegedInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
|
||||
for (int yd = 0; yd < gs->map->height; yd++)
|
||||
{
|
||||
tinfo = getTile(int3 (xd,yd,zd));
|
||||
if (tinfo->terType != ETerrainType::WATER && tinfo->terType != ETerrainType::ROCK && !tinfo->blocked) //land and free
|
||||
if (tinfo->terType.isLand() && tinfo->terType.isPassable() && !tinfo->blocked) //land and free
|
||||
tiles.push_back (int3 (xd,yd,zd));
|
||||
}
|
||||
}
|
||||
@ -116,8 +116,8 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> &
|
||||
{
|
||||
for (int yd = 0; yd < gs->map->height; yd++)
|
||||
{
|
||||
if ((getTile (int3 (xd,yd,zd))->terType == ETerrainType::WATER && water)
|
||||
|| (getTile (int3 (xd,yd,zd))->terType != ETerrainType::WATER && land))
|
||||
if ((getTile (int3 (xd,yd,zd))->terType.isWater() && water)
|
||||
|| (getTile (int3 (xd,yd,zd))->terType.isLand() && land))
|
||||
tiles.insert(int3(xd,yd,zd));
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
};
|
||||
|
||||
//Internal class for string -> JsonNode conversion
|
||||
class JsonParser
|
||||
class DLL_LINKAGE JsonParser
|
||||
{
|
||||
std::string errors; // Contains description of all encountered errors
|
||||
constString input; // Input data
|
||||
|
@ -59,6 +59,15 @@ JsonNode::JsonNode(const ResourceID & fileURI):
|
||||
*this = parser.parse(fileURI.getName());
|
||||
}
|
||||
|
||||
JsonNode::JsonNode(const std::string & idx, const ResourceID & fileURI):
|
||||
type(JsonType::DATA_NULL)
|
||||
{
|
||||
auto file = CResourceHandler::get(idx)->load(fileURI)->readAll();
|
||||
|
||||
JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second);
|
||||
*this = parser.parse(fileURI.getName());
|
||||
}
|
||||
|
||||
JsonNode::JsonNode(ResourceID && fileURI, bool &isValidSyntax):
|
||||
type(JsonType::DATA_NULL)
|
||||
{
|
||||
@ -711,7 +720,8 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
|
||||
{
|
||||
VLC->modh->identifiers.requestIdentifier("terrain", parameters[0], [=](si32 terrain)
|
||||
{
|
||||
terrainLimiter->terrainType = terrain;
|
||||
//TODO: support limiters
|
||||
//terrainLimiter->terrainType = terrain;
|
||||
});
|
||||
}
|
||||
return terrainLimiter;
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
//Create tree from JSON file
|
||||
explicit JsonNode(ResourceID && fileURI);
|
||||
explicit JsonNode(const ResourceID & fileURI);
|
||||
explicit JsonNode(const std::string& idx, const ResourceID & fileURI);
|
||||
explicit JsonNode(ResourceID && fileURI, bool & isValidSyntax);
|
||||
//Copy c-tor
|
||||
JsonNode(const JsonNode ©);
|
||||
@ -127,10 +128,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & meta;
|
||||
if(version >= 782)
|
||||
{
|
||||
h & flags;
|
||||
}
|
||||
h & flags;
|
||||
h & type;
|
||||
switch(type)
|
||||
{
|
||||
@ -152,10 +150,7 @@ public:
|
||||
h & data.Struct;
|
||||
break;
|
||||
case JsonType::DATA_INTEGER:
|
||||
if(version >= 770)
|
||||
{
|
||||
h & data.Integer;
|
||||
}
|
||||
h & data.Integer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -699,13 +699,13 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs)
|
||||
|
||||
DLL_LINKAGE void NewObject::applyGs(CGameState *gs)
|
||||
{
|
||||
ETerrainType terrainType;
|
||||
Terrain terrainType;
|
||||
|
||||
if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not
|
||||
{
|
||||
CGObjectInstance testObject = CGObjectInstance();
|
||||
testObject.pos = pos;
|
||||
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(ETerrainType::WATER).front();
|
||||
testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(Terrain("water")).front();
|
||||
|
||||
const int3 previousXAxisTile = int3(pos.x - 1, pos.y, pos.z);
|
||||
assert(gs->isInTheMap(previousXAxisTile) && (testObject.visitablePos() == previousXAxisTile));
|
||||
@ -722,7 +722,7 @@ DLL_LINKAGE void NewObject::applyGs(CGameState *gs)
|
||||
{
|
||||
case Obj::BOAT:
|
||||
o = new CGBoat();
|
||||
terrainType = ETerrainType::WATER; //TODO: either boat should only spawn on water, or all water objects should be handled this way
|
||||
terrainType = Terrain("water"); //TODO: either boat should only spawn on water, or all water objects should be handled this way
|
||||
break;
|
||||
case Obj::MONSTER: //probably more options will be needed
|
||||
o = new CGCreature();
|
||||
|
@ -59,13 +59,13 @@ namespace PathfinderUtil
|
||||
break;
|
||||
|
||||
case ELayer::WATER:
|
||||
if(tinfo->blocked || tinfo->terType != ETerrainType::WATER)
|
||||
if(tinfo->blocked || tinfo->terType.isLand())
|
||||
return CGPathNode::BLOCKED;
|
||||
|
||||
break;
|
||||
|
||||
case ELayer::AIR:
|
||||
if(tinfo->blocked || tinfo->terType == ETerrainType::WATER)
|
||||
if(tinfo->blocked || tinfo->terType.isLand())
|
||||
return CGPathNode::FLYABLE;
|
||||
|
||||
break;
|
||||
|
@ -56,19 +56,7 @@ struct DLL_LINKAGE PlayerSettings
|
||||
h & color;
|
||||
h & handicap;
|
||||
h & name;
|
||||
if(version < 787)
|
||||
{
|
||||
ui8 oldConnectedId = 0;
|
||||
h & oldConnectedId;
|
||||
if(oldConnectedId)
|
||||
{
|
||||
connectedPlayerIDs.insert(oldConnectedId);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h & connectedPlayerIDs;
|
||||
}
|
||||
h & connectedPlayerIDs;
|
||||
h & team;
|
||||
h & compOnly;
|
||||
}
|
||||
|
@ -16,10 +16,6 @@
|
||||
///
|
||||
namespace GameConstants
|
||||
{
|
||||
const std::string TERRAIN_NAMES [TERRAIN_TYPES] = {
|
||||
"dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock"
|
||||
};
|
||||
|
||||
const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = {
|
||||
"wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold", "mithril"
|
||||
};
|
||||
|
204
lib/Terrain.cpp
Normal file
204
lib/Terrain.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Terrain.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 "Terrain.h"
|
||||
#include "VCMI_Lib.h"
|
||||
#include "CModHandler.h"
|
||||
|
||||
//regular expression to change id for string at config
|
||||
//("allowedTerrain"\s*:\s*\[.*)9(.*\],\n)
|
||||
//\1"rock"\2
|
||||
|
||||
const Terrain Terrain::ANY("ANY");
|
||||
|
||||
Terrain Terrain::createTerrainTypeH3M(int tId)
|
||||
{
|
||||
static std::array<std::string, 10> terrainsH3M
|
||||
{
|
||||
"dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock"
|
||||
};
|
||||
return Terrain(terrainsH3M.at(tId));
|
||||
}
|
||||
|
||||
Terrain Terrain::createTerrainByCode(const std::string & typeCode)
|
||||
{
|
||||
for(const auto & terrain : Manager::terrains())
|
||||
{
|
||||
if(Manager::getInfo(terrain).typeCode == typeCode)
|
||||
return terrain;
|
||||
}
|
||||
return Terrain::ANY;
|
||||
}
|
||||
|
||||
Terrain::Manager::Manager()
|
||||
{
|
||||
auto allConfigs = VLC->modh->getActiveMods();
|
||||
allConfigs.insert(allConfigs.begin(), "core");
|
||||
for(auto & mod : allConfigs)
|
||||
{
|
||||
if(!CResourceHandler::get(mod)->existsResource(ResourceID("config/terrains.json")))
|
||||
continue;
|
||||
|
||||
JsonNode terrs(mod, ResourceID("config/terrains.json"));
|
||||
for(auto & terr : terrs.Struct())
|
||||
{
|
||||
Terrain::Info info;
|
||||
info.moveCost = terr.second["moveCost"].Integer();
|
||||
const JsonVector &unblockedVec = terr.second["minimapUnblocked"].Vector();
|
||||
info.minimapUnblocked =
|
||||
{
|
||||
ui8(unblockedVec[0].Float()),
|
||||
ui8(unblockedVec[1].Float()),
|
||||
ui8(unblockedVec[2].Float())
|
||||
};
|
||||
|
||||
const JsonVector &blockedVec = terr.second["minimapBlocked"].Vector();
|
||||
info.minimapBlocked =
|
||||
{
|
||||
ui8(blockedVec[0].Float()),
|
||||
ui8(blockedVec[1].Float()),
|
||||
ui8(blockedVec[2].Float())
|
||||
};
|
||||
info.musicFilename = terr.second["music"].String();
|
||||
info.tilesFilename = terr.second["tiles"].String();
|
||||
|
||||
if(terr.second["type"].isNull())
|
||||
{
|
||||
info.type = Terrain::Info::Type::Land;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto s = terr.second["type"].String();
|
||||
if(s == "LAND") info.type = Terrain::Info::Type::Land;
|
||||
if(s == "WATER") info.type = Terrain::Info::Type::Water;
|
||||
if(s == "SUB") info.type = Terrain::Info::Type::Subterranean;
|
||||
if(s == "ROCK") info.type = Terrain::Info::Type::Rock;
|
||||
}
|
||||
|
||||
if(terr.second["horseSoundId"].isNull())
|
||||
{
|
||||
info.horseSoundId = 9; //rock sound as default
|
||||
}
|
||||
else
|
||||
{
|
||||
info.horseSoundId = terr.second["horseSoundId"].Integer();
|
||||
}
|
||||
|
||||
if(!terr.second["text"].isNull())
|
||||
{
|
||||
info.terrainText = terr.second["text"].String();
|
||||
}
|
||||
|
||||
if(terr.second["code"].isNull())
|
||||
{
|
||||
info.typeCode = terr.first.substr(0, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.typeCode = terr.second["code"].String();
|
||||
assert(info.typeCode.length() == 2);
|
||||
}
|
||||
|
||||
|
||||
terrainInfo[Terrain(terr.first)] = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Terrain::Manager & Terrain::Manager::get()
|
||||
{
|
||||
static Terrain::Manager manager;
|
||||
return manager;
|
||||
}
|
||||
|
||||
std::vector<Terrain> Terrain::Manager::terrains()
|
||||
{
|
||||
std::vector<Terrain> _terrains;
|
||||
for(const auto & info : Terrain::Manager::get().terrainInfo)
|
||||
_terrains.push_back(info.first);
|
||||
return _terrains;
|
||||
}
|
||||
|
||||
const Terrain::Info & Terrain::Manager::getInfo(const Terrain & terrain)
|
||||
{
|
||||
return Terrain::Manager::get().terrainInfo.at(terrain);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & os, const Terrain terrainType)
|
||||
{
|
||||
return os << static_cast<const std::string &>(terrainType);
|
||||
}
|
||||
|
||||
Terrain::operator std::string() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
Terrain::Terrain(const std::string & _name) : name(_name)
|
||||
{}
|
||||
|
||||
Terrain& Terrain::operator=(const Terrain & _name)
|
||||
{
|
||||
name = _name.name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Terrain& Terrain::operator=(const std::string & _name)
|
||||
{
|
||||
name = _name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Terrain & l, const Terrain & r)
|
||||
{
|
||||
return l.name == r.name;
|
||||
}
|
||||
|
||||
bool operator!=(const Terrain & l, const Terrain & r)
|
||||
{
|
||||
return l.name != r.name;
|
||||
}
|
||||
|
||||
bool operator<(const Terrain & l, const Terrain & r)
|
||||
{
|
||||
return l.name < r.name;
|
||||
}
|
||||
|
||||
int Terrain::id() const
|
||||
{
|
||||
if(name == "ANY") return -3;
|
||||
if(name == "WRONG") return -2;
|
||||
if(name == "BORDER") return -1;
|
||||
|
||||
auto _terrains = Terrain::Manager::terrains();
|
||||
auto iter = std::find(_terrains.begin(), _terrains.end(), *this);
|
||||
return iter - _terrains.begin();
|
||||
}
|
||||
|
||||
bool Terrain::isLand() const
|
||||
{
|
||||
return !isWater();
|
||||
}
|
||||
bool Terrain::isWater() const
|
||||
{
|
||||
return Terrain::Manager::getInfo(*this).type == Terrain::Info::Type::Water;
|
||||
}
|
||||
bool Terrain::isPassable() const
|
||||
{
|
||||
return Terrain::Manager::getInfo(*this).type != Terrain::Info::Type::Rock;
|
||||
}
|
||||
bool Terrain::isUnderground() const
|
||||
{
|
||||
return Terrain::Manager::getInfo(*this).type == Terrain::Info::Type::Subterranean;
|
||||
}
|
||||
bool Terrain::isNative() const
|
||||
{
|
||||
return name.empty();
|
||||
}
|
93
lib/Terrain.h
Normal file
93
lib/Terrain.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Terrain.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
|
||||
|
||||
#include "ConstTransitivePtr.h"
|
||||
#include "JsonNode.h"
|
||||
|
||||
class DLL_LINKAGE Terrain
|
||||
{
|
||||
public:
|
||||
|
||||
friend class Manager;
|
||||
|
||||
struct Info
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
Land, Water, Subterranean, Rock
|
||||
};
|
||||
|
||||
int moveCost;
|
||||
std::array<int, 3> minimapBlocked;
|
||||
std::array<int, 3> minimapUnblocked;
|
||||
std::string musicFilename;
|
||||
std::string tilesFilename;
|
||||
std::string terrainText;
|
||||
std::string typeCode;
|
||||
int horseSoundId;
|
||||
Type type;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE Manager
|
||||
{
|
||||
public:
|
||||
static std::vector<Terrain> terrains();
|
||||
static const Info & getInfo(const Terrain &);
|
||||
|
||||
private:
|
||||
static Manager & get();
|
||||
Manager();
|
||||
|
||||
std::map<Terrain, Info> terrainInfo;
|
||||
};
|
||||
|
||||
/*enum EETerrainType
|
||||
{
|
||||
ANY_TERRAIN = -3,
|
||||
WRONG = -2, BORDER = -1, DIRT, SAND, GRASS, SNOW, SWAMP,
|
||||
ROUGH, SUBTERRANEAN, LAVA, WATER, ROCK // ROCK is also intended to be max value.
|
||||
};*/
|
||||
|
||||
Terrain(const std::string & _type = "");
|
||||
static Terrain createTerrainTypeH3M(int tId);
|
||||
static Terrain createTerrainByCode(const std::string & typeCode);
|
||||
|
||||
int id() const; //TODO: has to be completely removed
|
||||
|
||||
Terrain& operator=(const Terrain & _type);
|
||||
Terrain& operator=(const std::string & _type);
|
||||
|
||||
DLL_LINKAGE friend bool operator==(const Terrain & l, const Terrain & r);
|
||||
DLL_LINKAGE friend bool operator!=(const Terrain & l, const Terrain & r);
|
||||
DLL_LINKAGE friend bool operator<(const Terrain & l, const Terrain & r);
|
||||
|
||||
static const Terrain ANY;
|
||||
|
||||
bool isLand() const;
|
||||
bool isWater() const;
|
||||
bool isPassable() const; //ROCK
|
||||
bool isUnderground() const;
|
||||
bool isNative() const;
|
||||
|
||||
operator std::string() const;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & name;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const Terrain terrainType);
|
@ -288,15 +288,3 @@ void LibClasses::setContent(std::shared_ptr<CContentHandler> content)
|
||||
{
|
||||
modh->content = content;
|
||||
}
|
||||
|
||||
void LibClasses::restoreAllCreaturesNodeType794()
|
||||
{
|
||||
creh->restoreAllCreaturesNodeType794();
|
||||
}
|
||||
|
||||
void LibClasses::update800()
|
||||
{
|
||||
vstd::clear_pointer(scriptHandler);
|
||||
scriptHandler = new scripting::ScriptHandler();
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,6 @@ class DLL_LINKAGE LibClasses : public Services
|
||||
void makeNull(); //sets all handler pointers to null
|
||||
std::shared_ptr<CContentHandler> getContent() const;
|
||||
void setContent(std::shared_ptr<CContentHandler> content);
|
||||
void restoreAllCreaturesNodeType794();
|
||||
|
||||
public:
|
||||
bool IS_AI_ENABLED; //unused?
|
||||
@ -91,33 +90,20 @@ public:
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
if(version >= 800)
|
||||
h & scriptHandler;//must be first (or second after modh), it can modify factories other handlers depends on
|
||||
if(!h.saving)
|
||||
{
|
||||
h & scriptHandler;//must be first (or second after modh), it can modify factories other handlers depends on
|
||||
if(!h.saving)
|
||||
{
|
||||
scriptsLoaded();
|
||||
}
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
update800();
|
||||
scriptsLoaded();
|
||||
}
|
||||
|
||||
h & heroh;
|
||||
h & arth;
|
||||
h & creh;
|
||||
if(!h.saving && version < 794)
|
||||
restoreAllCreaturesNodeType794();
|
||||
|
||||
h & townh;
|
||||
h & objh;
|
||||
h & objtypeh;
|
||||
h & spellh;
|
||||
if(version >= 777)
|
||||
{
|
||||
h & skillh;
|
||||
}
|
||||
h & skillh;
|
||||
if(!h.saving)
|
||||
{
|
||||
//modh will be changed and modh->content will be empty after deserialization
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "../filesystem/Filesystem.h"
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../Terrain.h"
|
||||
|
||||
//TODO: remove
|
||||
#include "../IGameCallback.h"
|
||||
@ -186,7 +187,7 @@ struct RangeGenerator
|
||||
std::function<int()> myRand;
|
||||
};
|
||||
|
||||
BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town)
|
||||
BattleInfo * BattleInfo::setupBattle(int3 tile, Terrain terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town)
|
||||
{
|
||||
CMP_stack cmpst;
|
||||
auto curB = new BattleInfo();
|
||||
@ -610,7 +611,7 @@ CStack * BattleInfo::getStack(int stackID, bool onlyAlive)
|
||||
|
||||
BattleInfo::BattleInfo()
|
||||
: round(-1), activeStack(-1), town(nullptr), tile(-1,-1,-1),
|
||||
battlefieldType(BFieldType::NONE), terrainType(ETerrainType::WRONG),
|
||||
battlefieldType(BFieldType::NONE), terrainType(),
|
||||
tacticsSide(0), tacticDistance(0)
|
||||
{
|
||||
setBattle(this);
|
||||
@ -644,7 +645,7 @@ BFieldType BattleInfo::getBattlefieldType() const
|
||||
return battlefieldType;
|
||||
}
|
||||
|
||||
ETerrainType BattleInfo::getTerrainType() const
|
||||
Terrain BattleInfo::getTerrainType() const
|
||||
{
|
||||
return terrainType;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
class CStack;
|
||||
class CStackInstance;
|
||||
class CStackBasicDescriptor;
|
||||
class Terrain;
|
||||
|
||||
class DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallback, public IBattleState
|
||||
{
|
||||
@ -36,7 +37,7 @@ public:
|
||||
SiegeInfo si;
|
||||
|
||||
BFieldType battlefieldType; //like !!BA:B
|
||||
ETerrainType terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy)
|
||||
Terrain terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy)
|
||||
|
||||
ui8 tacticsSide; //which side is requested to play tactics phase
|
||||
ui8 tacticDistance; //how many hexes we can go forward (1 = only hexes adjacent to margin line)
|
||||
@ -72,7 +73,7 @@ public:
|
||||
battle::Units getUnitsIf(battle::UnitFilter predicate) const override;
|
||||
|
||||
BFieldType getBattlefieldType() const override;
|
||||
ETerrainType getTerrainType() const override;
|
||||
Terrain getTerrainType() const override;
|
||||
|
||||
ObstacleCList getAllObstacles() const override;
|
||||
|
||||
@ -137,7 +138,7 @@ public:
|
||||
const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player
|
||||
|
||||
void localInit();
|
||||
static BattleInfo * setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town);
|
||||
static BattleInfo * setupBattle(int3 tile, Terrain terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town);
|
||||
|
||||
ui8 whatSide(PlayerColor player) const;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "BattleProxy.h"
|
||||
#include "Unit.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
///BattleProxy
|
||||
|
||||
@ -46,7 +47,7 @@ BFieldType BattleProxy::getBattlefieldType() const
|
||||
return subject->battleGetBattlefieldType();
|
||||
}
|
||||
|
||||
ETerrainType BattleProxy::getTerrainType() const
|
||||
Terrain BattleProxy::getTerrainType() const
|
||||
{
|
||||
return subject->battleTerrainType();
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
battle::Units getUnitsIf(battle::UnitFilter predicate) const override;
|
||||
|
||||
BFieldType getBattlefieldType() const override;
|
||||
ETerrainType getTerrainType() const override;
|
||||
Terrain getTerrainType() const override;
|
||||
|
||||
ObstacleCList getAllObstacles() const override;
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../mapObjects/CGTownInstance.h"
|
||||
|
||||
ETerrainType CBattleInfoEssentials::battleTerrainType() const
|
||||
Terrain CBattleInfoEssentials::battleTerrainType() const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ETerrainType::WRONG);
|
||||
RETURN_IF_NOT_BATTLE(Terrain());
|
||||
return getBattle()->getTerrainType();
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
BattlePerspective::BattlePerspective battleGetMySide() const;
|
||||
const IBonusBearer * getBattleNode() const;
|
||||
|
||||
ETerrainType battleTerrainType() const override;
|
||||
Terrain battleTerrainType() const override;
|
||||
BFieldType battleGetBattlefieldType() const override;
|
||||
int32_t battleGetEnchanterCounter(ui8 side) const;
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
struct CObstacleInstance;
|
||||
class BFieldType;
|
||||
class ETerrainType;
|
||||
class Terrain;
|
||||
|
||||
namespace battle
|
||||
{
|
||||
@ -34,7 +34,7 @@ class DLL_LINKAGE IBattleInfoCallback
|
||||
public:
|
||||
virtual scripting::Pool * getContextPool() const = 0;
|
||||
|
||||
virtual ETerrainType battleTerrainType() const = 0;
|
||||
virtual Terrain battleTerrainType() const = 0;
|
||||
virtual BFieldType battleGetBattlefieldType() const = 0;
|
||||
|
||||
///return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
virtual battle::Units getUnitsIf(battle::UnitFilter predicate) const = 0;
|
||||
|
||||
virtual BFieldType getBattlefieldType() const = 0;
|
||||
virtual ETerrainType getTerrainType() const = 0;
|
||||
virtual Terrain getTerrainType() const = 0;
|
||||
|
||||
virtual ObstacleCList getAllObstacles() const = 0;
|
||||
|
||||
|
@ -79,28 +79,28 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f
|
||||
int64_t ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
|
||||
//if there is road both on dest and src tiles - use road movement cost
|
||||
if(dest.roadType != ERoadType::NO_ROAD && from.roadType != ERoadType::NO_ROAD)
|
||||
if(dest.roadType != ROAD_NAMES[0] && from.roadType != ROAD_NAMES[0])
|
||||
{
|
||||
int road = std::min(dest.roadType,from.roadType); //used road ID
|
||||
switch(road)
|
||||
int roadPos = std::min(vstd::find_pos(ROAD_NAMES, dest.roadType), vstd::find_pos(ROAD_NAMES, from.roadType)); //used road ID
|
||||
switch(roadPos)
|
||||
{
|
||||
case ERoadType::DIRT_ROAD:
|
||||
case 1:
|
||||
ret = 75;
|
||||
break;
|
||||
case ERoadType::GRAVEL_ROAD:
|
||||
case 2:
|
||||
ret = 65;
|
||||
break;
|
||||
case ERoadType::COBBLESTONE_ROAD:
|
||||
case 3:
|
||||
ret = 50;
|
||||
break;
|
||||
default:
|
||||
logGlobal->error("Unknown road type: %d", road);
|
||||
logGlobal->error("Unknown road type: %d", roadPos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ti->nativeTerrain != from.terType //the terrain is not native
|
||||
&& ti->nativeTerrain != ETerrainType::ANY_TERRAIN //no special creature bonus
|
||||
&& !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType) //no special movement bonus
|
||||
&& ti->nativeTerrain != Terrain::ANY //no special creature bonus
|
||||
&& !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType.id()) //no special movement bonus
|
||||
)
|
||||
{
|
||||
static const CSelector selectorPATHFINDING = Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::PATHFINDING);
|
||||
@ -114,7 +114,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f
|
||||
return (ui32)ret;
|
||||
}
|
||||
|
||||
ETerrainType::EETerrainType CGHeroInstance::getNativeTerrain() const
|
||||
Terrain CGHeroInstance::getNativeTerrain() const
|
||||
{
|
||||
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
||||
// This is clearly bug in H3 however intended behaviour is not clear.
|
||||
@ -122,18 +122,18 @@ ETerrainType::EETerrainType CGHeroInstance::getNativeTerrain() const
|
||||
// will always have best penalty without any influence from player-defined stacks order
|
||||
|
||||
// TODO: What should we do if all hero stacks are neutral creatures?
|
||||
ETerrainType::EETerrainType nativeTerrain = ETerrainType::BORDER;
|
||||
Terrain nativeTerrain("BORDER");
|
||||
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
ETerrainType::EETerrainType stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar.
|
||||
Terrain stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar.
|
||||
|
||||
if(stackNativeTerrain == ETerrainType::BORDER)
|
||||
if(stackNativeTerrain == Terrain("BORDER"))
|
||||
continue;
|
||||
if(nativeTerrain == ETerrainType::BORDER)
|
||||
if(nativeTerrain == Terrain("BORDER"))
|
||||
nativeTerrain = stackNativeTerrain;
|
||||
else if(nativeTerrain != stackNativeTerrain)
|
||||
return ETerrainType::BORDER;
|
||||
return Terrain("BORDER");
|
||||
}
|
||||
return nativeTerrain;
|
||||
}
|
||||
@ -560,23 +560,6 @@ void CGHeroInstance::recreateSecondarySkillsBonuses()
|
||||
updateSkillBonus(SecondarySkill(skill_info.first), skill_info.second);
|
||||
}
|
||||
|
||||
void CGHeroInstance::recreateSpecialtyBonuses(std::vector<HeroSpecial *> & specialtyDeprecated)
|
||||
{
|
||||
auto HeroSpecialToSpecialtyBonus = [](HeroSpecial & hs) -> SSpecialtyBonus
|
||||
{
|
||||
SSpecialtyBonus sb;
|
||||
sb.growsWithLevel = hs.growsWithLevel;
|
||||
sb.bonuses = hs.getBonusList();
|
||||
return sb;
|
||||
};
|
||||
|
||||
for(HeroSpecial * hs : specialtyDeprecated)
|
||||
{
|
||||
for(std::shared_ptr<Bonus> b : SpecialtyBonusToBonuses(HeroSpecialToSpecialtyBonus(*hs), type->ID.getNum()))
|
||||
addNewBonus(b);
|
||||
}
|
||||
}
|
||||
|
||||
void CGHeroInstance::updateSkillBonus(SecondarySkill which, int val)
|
||||
{
|
||||
removeBonuses(Selector::source(Bonus::SECONDARY_SKILL, which));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CGHeroInstance.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -89,15 +89,7 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & patrolling;
|
||||
if(version >= 755) //save format backward compatibility
|
||||
{
|
||||
h & initialPos;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
patrolling = false;
|
||||
initialPos = int3();
|
||||
}
|
||||
h & initialPos;
|
||||
h & patrolRadius;
|
||||
}
|
||||
} patrol;
|
||||
@ -163,7 +155,7 @@ public:
|
||||
bool needsLastStack()const override;
|
||||
|
||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
ETerrainType::EETerrainType getNativeTerrain() const;
|
||||
Terrain getNativeTerrain() const;
|
||||
ui32 getLowestCreatureSpeed() const;
|
||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||
@ -287,7 +279,6 @@ protected:
|
||||
|
||||
private:
|
||||
void levelUpAutomatically(CRandomGenerator & rand);
|
||||
void recreateSpecialtyBonuses(std::vector<HeroSpecial*> & specialtyDeprecated);
|
||||
|
||||
public:
|
||||
std::string getHeroTypeName() const;
|
||||
@ -316,18 +307,8 @@ public:
|
||||
h & visitedTown;
|
||||
h & boat;
|
||||
h & type;
|
||||
if(version < 781)
|
||||
{
|
||||
std::vector<HeroSpecial*> specialtyDeprecated;
|
||||
h & specialtyDeprecated;
|
||||
if(!h.saving)
|
||||
recreateSpecialtyBonuses(specialtyDeprecated);
|
||||
}
|
||||
h & commander;
|
||||
h & visitedObjects;
|
||||
BONUS_TREE_DESERIALIZATION_FIX
|
||||
//visitied town pointer will be restored by map serialization method
|
||||
if(version < 777 && !h.saving)
|
||||
recreateSecondarySkillsBonuses();
|
||||
}
|
||||
};
|
||||
|
@ -796,28 +796,6 @@ void CGTownInstance::addTownBonuses()
|
||||
}
|
||||
}
|
||||
|
||||
void CGTownInstance::fixBonusingDuplicates() //For versions 794-800
|
||||
{
|
||||
std::map<BuildingID::EBuildingID, int> bids;
|
||||
|
||||
for(auto i = 0; i != bonusingBuildings.size(); i++)
|
||||
{
|
||||
auto bid = bonusingBuildings[i]->getBuildingType();
|
||||
if(!bids.count(bid))
|
||||
bids.insert({ bid, 0 });
|
||||
else
|
||||
bids[bid]++;
|
||||
}
|
||||
for(auto & pair : bids)
|
||||
{
|
||||
if(!pair.second)
|
||||
continue;
|
||||
|
||||
for(auto i = 0; i < pair.second; i++)
|
||||
deleteTownBonus(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
void CGTownInstance::deleteTownBonus(BuildingID::EBuildingID bid)
|
||||
{
|
||||
size_t i = 0;
|
||||
@ -875,90 +853,6 @@ void CGTownInstance::initObj(CRandomGenerator & rand) ///initialize town structu
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void CGTownInstance::updateBonusingBuildings() //update to version 792
|
||||
{
|
||||
if(this->town->faction != nullptr)
|
||||
{
|
||||
//firstly, update subtype for the Bonusing objects, which are already stored in the bonusing list
|
||||
for(auto building : bonusingBuildings) //no garrison bonuses here, only week and visiting bonuses
|
||||
{
|
||||
switch(this->town->faction->index)
|
||||
{
|
||||
case ETownType::CASTLE:
|
||||
building->setBuildingSubtype(BuildingSubID::STABLES);
|
||||
break;
|
||||
|
||||
case ETownType::DUNGEON:
|
||||
if(building->getBuildingType() == BuildingID::SPECIAL_2)
|
||||
building->setBuildingSubtype(BuildingSubID::MANA_VORTEX);
|
||||
else if(building->getBuildingType() == BuildingID::SPECIAL_4)
|
||||
building->setBuildingSubtype(BuildingSubID::EXPERIENCE_VISITING_BONUS);
|
||||
break;
|
||||
|
||||
case ETownType::TOWER:
|
||||
building->setBuildingSubtype(BuildingSubID::KNOWLEDGE_VISITING_BONUS);
|
||||
break;
|
||||
|
||||
case ETownType::STRONGHOLD:
|
||||
building->setBuildingSubtype(BuildingSubID::ATTACK_VISITING_BONUS);
|
||||
break;
|
||||
|
||||
case ETownType::INFERNO:
|
||||
building->setBuildingSubtype(BuildingSubID::SPELL_POWER_VISITING_BONUS);
|
||||
break;
|
||||
|
||||
case ETownType::FORTRESS:
|
||||
building->setBuildingSubtype(BuildingSubID::DEFENSE_VISITING_BONUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//secondly, supplement bonusing buildings list and active bonuses; subtypes for these objects are already set in update792
|
||||
for(auto & kvp : town->buildings)
|
||||
{
|
||||
auto & building = kvp.second;
|
||||
|
||||
if(building->subId == BuildingSubID::PORTAL_OF_SUMMONING)
|
||||
{
|
||||
if(!hasBuiltInOldWay(ETownType::DUNGEON, BuildingID::PORTAL_OF_SUMMON))
|
||||
creatures.resize(GameConstants::CREATURES_PER_TOWN + 1);
|
||||
continue;
|
||||
}
|
||||
if(!building->IsVisitingBonus() && !building->IsWeekBonus()) //it's not bonusing => nothing to handle
|
||||
continue;
|
||||
|
||||
if(getBonusingBuilding(building->subId) != nullptr) //it's already added => already handled
|
||||
continue;
|
||||
|
||||
///'hasBuilt' checking for bonuses is in the onHeroVisit handler
|
||||
if(building->IsWeekBonus())
|
||||
tryAddOnePerWeekBonus(building->subId);
|
||||
|
||||
if(building->IsVisitingBonus())
|
||||
tryAddVisitingBonus(building->subId);
|
||||
}
|
||||
recreateBuildingsBonuses(); ///Clear all bonuses and recreate
|
||||
}
|
||||
|
||||
void CGTownInstance::updateTown794()
|
||||
{
|
||||
for(auto builtBuilding : builtBuildings)
|
||||
{
|
||||
auto building = town->buildings.at(builtBuilding);
|
||||
|
||||
for(auto overriddenBid : building->overrideBids)
|
||||
overriddenBuildings.insert(overriddenBid);
|
||||
}
|
||||
for(auto & kvp : town->buildings)
|
||||
{
|
||||
auto & building = kvp.second;
|
||||
//The building acts as a visiting bonus and it has not been overridden.
|
||||
if(building->IsVisitingBonus() && overriddenBuildings.find(kvp.first) == overriddenBuildings.end())
|
||||
tryAddVisitingBonus(building->subId);
|
||||
}
|
||||
recreateBuildingsBonuses();
|
||||
}
|
||||
|
||||
bool CGTownInstance::hasBuiltInOldWay(ETownType::ETownType type, BuildingID bid) const
|
||||
{
|
||||
return (this->town->faction != nullptr && this->town->faction->index == type && hasBuilt(bid));
|
||||
|
@ -130,9 +130,7 @@ public:
|
||||
{
|
||||
h & bID;
|
||||
h & indexOnTV;
|
||||
|
||||
if(version >= 792)
|
||||
h & bType;
|
||||
h & bType;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -267,16 +265,7 @@ public:
|
||||
return false;
|
||||
});
|
||||
|
||||
if(!h.saving && version < 793)
|
||||
updateBonusingBuildings();
|
||||
|
||||
if(version >= 794)
|
||||
h & overriddenBuildings;
|
||||
else if(!h.saving)
|
||||
updateTown794();
|
||||
|
||||
if(!h.saving && (version >= 794 && version < 801))
|
||||
fixBonusingDuplicates();
|
||||
h & overriddenBuildings;
|
||||
|
||||
if(!h.saving)
|
||||
this->setNodeType(CBonusSystemNode::TOWN);
|
||||
@ -367,7 +356,6 @@ private:
|
||||
void setOwner(const PlayerColor owner) const;
|
||||
void onTownCaptured(const PlayerColor winner) const;
|
||||
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
|
||||
void updateBonusingBuildings();
|
||||
bool hasBuiltInOldWay(ETownType::ETownType type, BuildingID bid) const;
|
||||
bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
|
||||
bool isBonusingBuildingAdded(BuildingID::EBuildingID bid) const;
|
||||
@ -375,6 +363,4 @@ private:
|
||||
void tryAddVisitingBonus(BuildingSubID::EBuildingSubID subID);
|
||||
void initOverriddenBids();
|
||||
void addTownBonuses();
|
||||
void updateTown794(); //populate overriddenBuildings and vanila bonuses for old saves
|
||||
void fixBonusingDuplicates(); //For versions 794-800.
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* CObjectClassesHandler.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
@ -195,7 +195,7 @@ void CObjectClassesHandler::loadObjectEntry(const std::string & identifier, cons
|
||||
else
|
||||
handler->init(entry);
|
||||
|
||||
if (handler->getTemplates().empty())
|
||||
//if (handler->getTemplates().empty())
|
||||
{
|
||||
auto range = legacyTemplates.equal_range(std::make_pair(obj->id, id));
|
||||
for (auto & templ : boost::make_iterator_range(range.first, range.second))
|
||||
@ -569,14 +569,14 @@ std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates() const
|
||||
return templates;
|
||||
}
|
||||
|
||||
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(si32 terrainType) const// FIXME: replace with ETerrainType
|
||||
std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(const Terrain & terrainType) const
|
||||
{
|
||||
std::vector<ObjectTemplate> templates = getTemplates();
|
||||
std::vector<ObjectTemplate> filtered;
|
||||
|
||||
std::copy_if(templates.begin(), templates.end(), std::back_inserter(filtered), [&](const ObjectTemplate & obj)
|
||||
{
|
||||
return obj.canBePlacedAt(ETerrainType(terrainType));
|
||||
return obj.canBePlacedAt(terrainType);
|
||||
});
|
||||
// H3 defines allowed terrains in a weird way - artifacts, monsters and resources have faulty masks here
|
||||
// Perhaps we should re-define faulty templates and remove this workaround (already done for resources)
|
||||
@ -586,7 +586,7 @@ std::vector<ObjectTemplate> AObjectTypeHandler::getTemplates(si32 terrainType) c
|
||||
return filtered;
|
||||
}
|
||||
|
||||
boost::optional<ObjectTemplate> AObjectTypeHandler::getOverride(si32 terrainType, const CGObjectInstance * object) const
|
||||
boost::optional<ObjectTemplate> AObjectTypeHandler::getOverride(const Terrain & terrainType, const CGObjectInstance * object) const
|
||||
{
|
||||
std::vector<ObjectTemplate> ret = getTemplates(terrainType);
|
||||
for (auto & tmpl : ret)
|
||||
|
@ -178,11 +178,11 @@ public:
|
||||
|
||||
/// returns all templates matching parameters
|
||||
std::vector<ObjectTemplate> getTemplates() const;
|
||||
std::vector<ObjectTemplate> getTemplates(si32 terrainType) const;
|
||||
std::vector<ObjectTemplate> getTemplates(const Terrain & terrainType) const;
|
||||
|
||||
/// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle)
|
||||
/// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server)
|
||||
boost::optional<ObjectTemplate> getOverride(si32 terrainType, const CGObjectInstance * object) const;
|
||||
boost::optional<ObjectTemplate> getOverride(const Terrain & terrainType, const CGObjectInstance * object) const;
|
||||
|
||||
const RandomMapInfo & getRMGInfo();
|
||||
|
||||
@ -210,19 +210,10 @@ public:
|
||||
h & templates;
|
||||
h & rmgInfo;
|
||||
h & objectName;
|
||||
if(version >= 759)
|
||||
{
|
||||
h & typeName;
|
||||
h & subTypeName;
|
||||
}
|
||||
if(version >= 778)
|
||||
{
|
||||
h & sounds;
|
||||
}
|
||||
if(version >= 789)
|
||||
{
|
||||
h & aiValue;
|
||||
}
|
||||
h & typeName;
|
||||
h & subTypeName;
|
||||
h & sounds;
|
||||
h & aiValue;
|
||||
}
|
||||
};
|
||||
|
||||
@ -253,19 +244,10 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
|
||||
h & handlerName;
|
||||
h & base;
|
||||
h & subObjects;
|
||||
if(version >= 759)
|
||||
{
|
||||
h & identifier;
|
||||
h & subIds;
|
||||
}
|
||||
if(version >= 778)
|
||||
{
|
||||
h & sounds;
|
||||
}
|
||||
if(version >= 789)
|
||||
{
|
||||
h & groupDefaultAiValue;
|
||||
}
|
||||
h & identifier;
|
||||
h & subIds;
|
||||
h & sounds;
|
||||
h & groupDefaultAiValue;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -419,7 +419,7 @@ int3 IBoatGenerator::bestLocation() const
|
||||
{
|
||||
if(const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map
|
||||
{
|
||||
if(tile->terType == ETerrainType::WATER && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
|
||||
if(tile->terType.isWater() && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat
|
||||
return o->pos + offset;
|
||||
}
|
||||
}
|
||||
|
@ -213,13 +213,9 @@ public:
|
||||
///Entry point of binary (de-)serialization
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
if(version >= 759)
|
||||
{
|
||||
h & instanceName;
|
||||
h & typeName;
|
||||
h & subTypeName;
|
||||
}
|
||||
|
||||
h & instanceName;
|
||||
h & typeName;
|
||||
h & subTypeName;
|
||||
h & pos;
|
||||
h & ID;
|
||||
h & subID;
|
||||
|
@ -87,14 +87,7 @@ public:
|
||||
h & isCustomFirst;
|
||||
h & isCustomNext;
|
||||
h & isCustomComplete;
|
||||
if(version >= 757)
|
||||
{
|
||||
h & completedOption;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
completedOption = 1;
|
||||
}
|
||||
h & completedOption;
|
||||
}
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler, const std::string & fieldName);
|
||||
|
@ -269,11 +269,6 @@ public:
|
||||
h & onVisited;
|
||||
h & onEmpty;
|
||||
h & visitMode;
|
||||
if(version < 778)
|
||||
{
|
||||
ui16 soundID = 0;
|
||||
h & soundID;
|
||||
}
|
||||
h & selectMode;
|
||||
h & selectedReward;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "CObjectHandler.h"
|
||||
#include "../CModHandler.h"
|
||||
#include "../JsonNode.h"
|
||||
#include "../Terrain.h"
|
||||
|
||||
#include "CRewardableConstructor.h"
|
||||
|
||||
@ -143,7 +144,17 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
|
||||
for (size_t i=0; i<9; i++)
|
||||
{
|
||||
if (terrStr[8-i] == '1')
|
||||
allowedTerrains.insert(ETerrainType((si32)i));
|
||||
allowedTerrains.insert(Terrain::createTerrainTypeH3M(i));
|
||||
}
|
||||
|
||||
//assuming that object can be placed on other land terrains
|
||||
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water")))
|
||||
{
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
if(terrain.isLand() && terrain.isPassable())
|
||||
allowedTerrains.insert(terrain);
|
||||
}
|
||||
}
|
||||
|
||||
id = Obj(boost::lexical_cast<int>(strings[5]));
|
||||
@ -205,7 +216,17 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
|
||||
for (size_t i=0; i<9; i++)
|
||||
{
|
||||
if (((terrMask >> i) & 1 ) != 0)
|
||||
allowedTerrains.insert(ETerrainType((si32)i));
|
||||
allowedTerrains.insert(Terrain::createTerrainTypeH3M(i));
|
||||
}
|
||||
|
||||
//assuming that object can be placed on other land terrains
|
||||
if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water")))
|
||||
{
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
{
|
||||
if(terrain.isLand() && terrain.isPassable())
|
||||
allowedTerrains.insert(terrain);
|
||||
}
|
||||
}
|
||||
|
||||
id = Obj(reader.readUInt32());
|
||||
@ -247,15 +268,16 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain)
|
||||
if(withTerrain && !node["allowedTerrains"].isNull())
|
||||
{
|
||||
for (auto & entry : node["allowedTerrains"].Vector())
|
||||
allowedTerrains.insert(ETerrainType(vstd::find_pos(GameConstants::TERRAIN_NAMES, entry.String())));
|
||||
allowedTerrains.insert(entry.String());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i=0; i< GameConstants::TERRAIN_TYPES; i++)
|
||||
allowedTerrains.insert(ETerrainType((si32)i));
|
||||
|
||||
allowedTerrains.erase(ETerrainType::ROCK);
|
||||
allowedTerrains.erase(ETerrainType::WATER);
|
||||
for(auto & i : Terrain::Manager::terrains())
|
||||
{
|
||||
if(!i.isPassable() || i.isWater())
|
||||
continue;
|
||||
allowedTerrains.insert(i);
|
||||
}
|
||||
}
|
||||
|
||||
if(withTerrain && allowedTerrains.empty())
|
||||
@ -329,14 +351,14 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const
|
||||
if(withTerrain)
|
||||
{
|
||||
//assumed that ROCK and WATER terrains are not included
|
||||
if(allowedTerrains.size() < (GameConstants::TERRAIN_TYPES - 2))
|
||||
if(allowedTerrains.size() < (Terrain::Manager::terrains().size() - 2))
|
||||
{
|
||||
JsonVector & data = node["allowedTerrains"].Vector();
|
||||
|
||||
for(auto type : allowedTerrains)
|
||||
{
|
||||
JsonNode value(JsonNode::JsonType::DATA_STRING);
|
||||
value.String() = GameConstants::TERRAIN_NAMES[type.num];
|
||||
value.String() = type;
|
||||
data.push_back(value);
|
||||
}
|
||||
}
|
||||
@ -511,7 +533,7 @@ bool ObjectTemplate::isVisitableFromTop() const
|
||||
//return isVisitableFrom (0, 1);
|
||||
}
|
||||
|
||||
bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
|
||||
bool ObjectTemplate::canBePlacedAt(Terrain terrain) const
|
||||
{
|
||||
return allowedTerrains.count(terrain) != 0;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ class CBinaryReader;
|
||||
class CLegacyConfigParser;
|
||||
class JsonNode;
|
||||
class int3;
|
||||
class Terrain;
|
||||
|
||||
class DLL_LINKAGE ObjectTemplate
|
||||
{
|
||||
@ -30,7 +31,7 @@ class DLL_LINKAGE ObjectTemplate
|
||||
/// directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7)
|
||||
ui8 visitDir;
|
||||
/// list of terrains on which this object can be placed
|
||||
std::set<ETerrainType> allowedTerrains;
|
||||
std::set<Terrain> allowedTerrains;
|
||||
|
||||
void afterLoadFixup();
|
||||
|
||||
@ -70,7 +71,7 @@ public:
|
||||
bool isVisitableFromTop() const;
|
||||
|
||||
// Checks if object can be placed on specific terrain
|
||||
bool canBePlacedAt(ETerrainType terrain) const;
|
||||
bool canBePlacedAt(Terrain terrain) const;
|
||||
|
||||
ObjectTemplate();
|
||||
//custom copy constructor is required
|
||||
@ -96,10 +97,7 @@ public:
|
||||
h & subid;
|
||||
h & printPriority;
|
||||
h & visitDir;
|
||||
if(version >= 770)
|
||||
{
|
||||
h & editorAnimationFile;
|
||||
}
|
||||
h & editorAnimationFile;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -422,17 +422,6 @@ std::vector<CGHeroInstance *> CCampaignScenario::getLostCrossoverHeroes()
|
||||
return lostCrossoverHeroes;
|
||||
}
|
||||
|
||||
std::vector<JsonNode> CCampaignScenario::update787(std::vector<CGHeroInstance *> & heroes)
|
||||
{
|
||||
static_assert(MINIMAL_SERIALIZATION_VERSION < 787, "No longer needed CCampaignScenario::update787");
|
||||
std::vector<JsonNode> heroesNew;
|
||||
for(auto hero : heroes)
|
||||
{
|
||||
heroesNew.push_back(CCampaignState::crossoverSerialize(hero));
|
||||
}
|
||||
return heroesNew;
|
||||
}
|
||||
|
||||
void CCampaignState::setCurrentMapAsConquered(const std::vector<CGHeroInstance *> & heroes)
|
||||
{
|
||||
camp->scenarios[*currentMap].crossoverHeroes.clear();
|
||||
|
@ -146,8 +146,7 @@ public:
|
||||
// FIXME: due to usage of JsonNode I can't make these methods const
|
||||
const CGHeroInstance * strongestHero(PlayerColor owner);
|
||||
std::vector<CGHeroInstance *> getLostCrossoverHeroes(); /// returns a list of crossover heroes which started the scenario, but didn't complete it
|
||||
std::vector<JsonNode> update787(std::vector<CGHeroInstance *> & heroes);
|
||||
|
||||
|
||||
CCampaignScenario();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int formatVersion)
|
||||
@ -163,19 +162,8 @@ public:
|
||||
h & prolog;
|
||||
h & epilog;
|
||||
h & travelOptions;
|
||||
if(formatVersion < 787)
|
||||
{
|
||||
std::vector<CGHeroInstance *> crossoverHeroesOld, placedCrossoverHeroesOld;
|
||||
h & crossoverHeroesOld;
|
||||
h & placedCrossoverHeroesOld;
|
||||
crossoverHeroes = update787(crossoverHeroesOld);
|
||||
placedCrossoverHeroes = update787(placedCrossoverHeroesOld);
|
||||
}
|
||||
else
|
||||
{
|
||||
h & crossoverHeroes;
|
||||
h & placedCrossoverHeroes;
|
||||
}
|
||||
h & crossoverHeroes;
|
||||
h & placedCrossoverHeroes;
|
||||
h & keepHeroes;
|
||||
}
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ static bool ruleIsAny(const std::string & rule)
|
||||
#endif
|
||||
|
||||
///CDrawRoadsOperation
|
||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen):
|
||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen):
|
||||
CMapOperation(map),terrainSel(terrainSel), roadType(roadType), gen(gen)
|
||||
{
|
||||
|
||||
@ -225,7 +225,7 @@ void CDrawRoadsOperation::flipPattern(RoadPattern& pattern, int flip) const
|
||||
|
||||
bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const
|
||||
{
|
||||
return tile.roadType != ERoadType::NO_ROAD; //TODO: this method should be virtual for river support
|
||||
return tile.roadType != ROAD_NAMES[0]; //TODO: this method should be virtual for river support
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::updateTiles(std::set<int3> & invalidated)
|
||||
@ -263,7 +263,7 @@ bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const
|
||||
{
|
||||
//TODO: this method should be virtual for river support
|
||||
|
||||
return map->getTile(pos).roadType != ERoadType::NO_ROAD;
|
||||
return map->getTile(pos).roadType != ROAD_NAMES[0];
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ struct TerrainTile;
|
||||
class CDrawRoadsOperation : public CMapOperation
|
||||
{
|
||||
public:
|
||||
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen);
|
||||
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen);
|
||||
void execute() override;
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
@ -53,6 +53,6 @@ private:
|
||||
bool tileHasSomething(const int3 & pos) const;
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
ERoadType::ERoadType roadType;
|
||||
std::string roadType;
|
||||
CRandomGenerator * gen;
|
||||
};
|
||||
|
@ -123,8 +123,8 @@ CCastleEvent::CCastleEvent() : town(nullptr)
|
||||
|
||||
}
|
||||
|
||||
TerrainTile::TerrainTile() : terType(ETerrainType::BORDER), terView(0), riverType(ERiverType::NO_RIVER),
|
||||
riverDir(0), roadType(ERoadType::NO_ROAD), roadDir(0), extTileFlags(0), visitable(false),
|
||||
TerrainTile::TerrainTile() : terType("BORDER"), terView(0), riverType(RIVER_NAMES[0]),
|
||||
riverDir(0), roadType(ROAD_NAMES[0]), roadDir(0), extTileFlags(0), visitable(false),
|
||||
blocked(false)
|
||||
{
|
||||
|
||||
@ -132,13 +132,13 @@ TerrainTile::TerrainTile() : terType(ETerrainType::BORDER), terView(0), riverTyp
|
||||
|
||||
bool TerrainTile::entrableTerrain(const TerrainTile * from) const
|
||||
{
|
||||
return entrableTerrain(from ? from->terType != ETerrainType::WATER : true, from ? from->terType == ETerrainType::WATER : true);
|
||||
return entrableTerrain(from ? from->terType.isLand() : true, from ? from->terType.isWater() : true);
|
||||
}
|
||||
|
||||
bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const
|
||||
{
|
||||
return terType != ETerrainType::ROCK
|
||||
&& ((allowSea && terType == ETerrainType::WATER) || (allowLand && terType != ETerrainType::WATER));
|
||||
return terType.isPassable()
|
||||
&& ((allowSea && terType.isWater()) || (allowLand && terType.isLand()));
|
||||
}
|
||||
|
||||
bool TerrainTile::isClear(const TerrainTile * from) const
|
||||
@ -164,7 +164,7 @@ CGObjectInstance * TerrainTile::topVisitableObj(bool excludeTop) const
|
||||
|
||||
EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const
|
||||
{
|
||||
if(terType == ETerrainType::WATER || terType == ETerrainType::ROCK)
|
||||
if(terType.isWater() || !terType.isPassable())
|
||||
return EDiggingStatus::WRONG_TERRAIN;
|
||||
|
||||
int allowedBlocked = excludeTop ? 1 : 0;
|
||||
@ -181,7 +181,7 @@ bool TerrainTile::hasFavorableWinds() const
|
||||
|
||||
bool TerrainTile::isWater() const
|
||||
{
|
||||
return terType == ETerrainType::WATER;
|
||||
return terType.isWater();
|
||||
}
|
||||
|
||||
void CMapHeader::setupEvents()
|
||||
|
@ -110,11 +110,7 @@ struct DLL_LINKAGE PlayerInfo
|
||||
h & posOfMainTown;
|
||||
h & team;
|
||||
h & generateHero;
|
||||
|
||||
if(version >= 770)
|
||||
{
|
||||
h & mainHeroInstance;
|
||||
}
|
||||
h & mainHeroInstance;
|
||||
}
|
||||
};
|
||||
|
||||
@ -164,16 +160,9 @@ struct DLL_LINKAGE EventCondition
|
||||
h & objectType;
|
||||
h & position;
|
||||
h & condition;
|
||||
//(!!!) should be `version >= 759` here, but do not try to "fix" it
|
||||
if(version > 759)
|
||||
{
|
||||
h & objectSubtype;
|
||||
h & objectInstanceName;
|
||||
}
|
||||
if(version >= 770)
|
||||
{
|
||||
h & metaType;
|
||||
}
|
||||
h & objectSubtype;
|
||||
h & objectInstanceName;
|
||||
h & metaType;
|
||||
}
|
||||
};
|
||||
|
||||
@ -495,9 +484,6 @@ public:
|
||||
h & CGTownInstance::merchantArtifacts;
|
||||
h & CGTownInstance::universitySkills;
|
||||
|
||||
if(formatVersion >= 759)
|
||||
{
|
||||
h & instanceNames;
|
||||
}
|
||||
h & instanceNames;
|
||||
}
|
||||
};
|
||||
|
@ -80,11 +80,11 @@ struct DLL_LINKAGE TerrainTile
|
||||
EDiggingStatus getDiggingStatus(const bool excludeTop = true) const;
|
||||
bool hasFavorableWinds() const;
|
||||
|
||||
ETerrainType terType;
|
||||
Terrain terType;
|
||||
ui8 terView;
|
||||
ERiverType::ERiverType riverType;
|
||||
std::string riverType;
|
||||
ui8 riverDir;
|
||||
ERoadType::ERoadType roadType;
|
||||
std::string roadType;
|
||||
ui8 roadDir;
|
||||
/// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road);
|
||||
/// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect
|
||||
|
@ -243,13 +243,13 @@ void CMapEditManager::clearTerrain(CRandomGenerator * gen)
|
||||
execute(make_unique<CClearTerrainOperation>(map, gen ? gen : &(this->gen)));
|
||||
}
|
||||
|
||||
void CMapEditManager::drawTerrain(ETerrainType terType, CRandomGenerator * gen)
|
||||
void CMapEditManager::drawTerrain(Terrain terType, CRandomGenerator * gen)
|
||||
{
|
||||
execute(make_unique<CDrawTerrainOperation>(map, terrainSel, terType, gen ? gen : &(this->gen)));
|
||||
terrainSel.clearSelection();
|
||||
}
|
||||
|
||||
void CMapEditManager::drawRoad(ERoadType::ERoadType roadType, CRandomGenerator* gen)
|
||||
void CMapEditManager::drawRoad(const std::string & roadType, CRandomGenerator* gen)
|
||||
{
|
||||
execute(make_unique<CDrawRoadsOperation>(map, terrainSel, roadType, gen ? gen : &(this->gen)));
|
||||
terrainSel.clearSelection();
|
||||
@ -534,7 +534,7 @@ void CTerrainViewPatternConfig::flipPattern(TerrainViewPattern & pattern, int fl
|
||||
}
|
||||
|
||||
|
||||
CDrawTerrainOperation::CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, ETerrainType terType, CRandomGenerator * gen)
|
||||
CDrawTerrainOperation::CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, Terrain terType, CRandomGenerator * gen)
|
||||
: CMapOperation(map), terrainSel(terrainSel), terType(terType), gen(gen)
|
||||
{
|
||||
|
||||
@ -760,21 +760,17 @@ void CDrawTerrainOperation::updateTerrainViews()
|
||||
}
|
||||
}
|
||||
|
||||
ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(ETerrainType terType) const
|
||||
ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(Terrain terType) const
|
||||
{
|
||||
switch(terType)
|
||||
{
|
||||
case ETerrainType::DIRT:
|
||||
if(terType == Terrain("dirt"))
|
||||
return ETerrainGroup::DIRT;
|
||||
case ETerrainType::SAND:
|
||||
if(terType == Terrain("sand"))
|
||||
return ETerrainGroup::SAND;
|
||||
case ETerrainType::WATER:
|
||||
if(terType.isWater())
|
||||
return ETerrainGroup::WATER;
|
||||
case ETerrainType::ROCK:
|
||||
if(!terType.isPassable())
|
||||
return ETerrainGroup::ROCK;
|
||||
default:
|
||||
return ETerrainGroup::NORMAL;
|
||||
}
|
||||
return ETerrainGroup::NORMAL;
|
||||
}
|
||||
|
||||
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const std::vector<TerrainViewPattern> * pattern, int recDepth) const
|
||||
@ -811,7 +807,7 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
int cy = pos.y + (i / 3) - 1;
|
||||
int3 currentPos(cx, cy, pos.z);
|
||||
bool isAlien = false;
|
||||
ETerrainType terType;
|
||||
Terrain terType;
|
||||
if(!map->isInTheMap(currentPos))
|
||||
{
|
||||
// position is not in the map, so take the ter type from the neighbor tile
|
||||
@ -949,17 +945,11 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
}
|
||||
}
|
||||
|
||||
bool CDrawTerrainOperation::isSandType(ETerrainType terType) const
|
||||
bool CDrawTerrainOperation::isSandType(Terrain terType) const
|
||||
{
|
||||
switch(terType)
|
||||
{
|
||||
case ETerrainType::WATER:
|
||||
case ETerrainType::SAND:
|
||||
case ETerrainType::ROCK:
|
||||
if(terType.isWater() || terType == Terrain("sand") || !terType.isPassable())
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDrawTerrainOperation::invalidateTerrainViews(const int3 & centerPos)
|
||||
@ -986,7 +976,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
|
||||
auto valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById("n1")).result;
|
||||
|
||||
// Special validity check for rock & water
|
||||
if(valid && (terType == ETerrainType::WATER || terType == ETerrainType::ROCK))
|
||||
if(valid && (terType.isWater() || !terType.isPassable()))
|
||||
{
|
||||
static const std::string patternIds[] = { "s1", "s2" };
|
||||
for(auto & patternId : patternIds)
|
||||
@ -996,7 +986,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
|
||||
}
|
||||
}
|
||||
// Additional validity check for non rock OR water
|
||||
else if(!valid && (terType != ETerrainType::WATER && terType != ETerrainType::ROCK))
|
||||
else if(!valid && (terType.isLand() && terType.isPassable()))
|
||||
{
|
||||
static const std::string patternIds[] = { "n2", "n3" };
|
||||
for(auto & patternId : patternIds)
|
||||
@ -1040,7 +1030,7 @@ void CTerrainViewPatternUtils::printDebuggingInfoAboutTile(const CMap * map, int
|
||||
{
|
||||
auto debugTile = map->getTile(debugPos);
|
||||
|
||||
std::string terType = debugTile.terType.toString().substr(0, 6);
|
||||
std::string terType = static_cast<std::string>(debugTile.terType).substr(0, 6);
|
||||
line += terType;
|
||||
line.insert(line.end(), PADDED_LENGTH - terType.size(), ' ');
|
||||
}
|
||||
@ -1059,12 +1049,12 @@ CClearTerrainOperation::CClearTerrainOperation(CMap * map, CRandomGenerator * ge
|
||||
{
|
||||
CTerrainSelection terrainSel(map);
|
||||
terrainSel.selectRange(MapRect(int3(0, 0, 0), map->width, map->height));
|
||||
addOperation(make_unique<CDrawTerrainOperation>(map, terrainSel, ETerrainType::WATER, gen));
|
||||
addOperation(make_unique<CDrawTerrainOperation>(map, terrainSel, Terrain("water"), gen));
|
||||
if(map->twoLevel)
|
||||
{
|
||||
terrainSel.clearSelection();
|
||||
terrainSel.selectRange(MapRect(int3(0, 0, 1), map->width, map->height));
|
||||
addOperation(make_unique<CDrawTerrainOperation>(map, terrainSel, ETerrainType::ROCK, gen));
|
||||
addOperation(make_unique<CDrawTerrainOperation>(map, terrainSel, Terrain("rock"), gen));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "Terrain.h"
|
||||
|
||||
class CGObjectInstance;
|
||||
class CTerrainViewPatternConfig;
|
||||
@ -168,10 +169,10 @@ public:
|
||||
void clearTerrain(CRandomGenerator * gen = nullptr);
|
||||
|
||||
/// Draws terrain at the current terrain selection. The selection will be cleared automatically.
|
||||
void drawTerrain(ETerrainType terType, CRandomGenerator * gen = nullptr);
|
||||
void drawTerrain(Terrain terType, CRandomGenerator * gen = nullptr);
|
||||
|
||||
/// Draws roads at the current terrain selection. The selection will be cleared automatically.
|
||||
void drawRoad(ERoadType::ERoadType roadType, CRandomGenerator * gen = nullptr);
|
||||
void drawRoad(const std::string & roadType, CRandomGenerator * gen = nullptr);
|
||||
|
||||
void insertObject(CGObjectInstance * obj);
|
||||
|
||||
@ -353,7 +354,7 @@ private:
|
||||
class CDrawTerrainOperation : public CMapOperation
|
||||
{
|
||||
public:
|
||||
CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, ETerrainType terType, CRandomGenerator * gen);
|
||||
CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, Terrain terType, CRandomGenerator * gen);
|
||||
|
||||
void execute() override;
|
||||
void undo() override;
|
||||
@ -384,16 +385,16 @@ private:
|
||||
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
|
||||
|
||||
void updateTerrainViews();
|
||||
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
||||
ETerrainGroup::ETerrainGroup getTerrainGroup(Terrain terType) const;
|
||||
/// Validates the terrain view of the given position and with the given pattern. The first method wraps the
|
||||
/// second method to validate the terrain view with the given pattern in all four flip directions(horizontal, vertical).
|
||||
ValidationResult validateTerrainView(const int3 & pos, const std::vector<TerrainViewPattern> * pattern, int recDepth = 0) const;
|
||||
ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
|
||||
/// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
|
||||
bool isSandType(ETerrainType terType) const;
|
||||
bool isSandType(Terrain terType) const;
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
ETerrainType terType;
|
||||
Terrain terType;
|
||||
CRandomGenerator * gen;
|
||||
std::set<int3> invalidatedTerViews;
|
||||
};
|
||||
|
@ -935,14 +935,14 @@ void CMapLoaderH3M::readTerrain()
|
||||
for(int z = 0; z < map->height; z++)
|
||||
{
|
||||
auto & tile = map->getTile(int3(z, c, a));
|
||||
tile.terType = ETerrainType(reader.readUInt8());
|
||||
tile.terType = Terrain::createTerrainTypeH3M(reader.readUInt8());
|
||||
tile.terView = reader.readUInt8();
|
||||
tile.riverType = static_cast<ERiverType::ERiverType>(reader.readUInt8());
|
||||
tile.riverType = RIVER_NAMES[reader.readUInt8()];
|
||||
tile.riverDir = reader.readUInt8();
|
||||
tile.roadType = static_cast<ERoadType::ERoadType>(reader.readUInt8());
|
||||
tile.roadType = ROAD_NAMES[reader.readUInt8()];
|
||||
tile.roadDir = reader.readUInt8();
|
||||
tile.extTileFlags = reader.readUInt8();
|
||||
tile.blocked = ((tile.terType == ETerrainType::ROCK || tile.terType == ETerrainType::BORDER ) ? true : false); //underground tiles are always blocked
|
||||
tile.blocked = ((!tile.terType.isPassable() || tile.terType == Terrain("BORDER") ) ? true : false); //underground tiles are always blocked
|
||||
tile.visitable = 0;
|
||||
}
|
||||
}
|
||||
|
@ -323,20 +323,6 @@ namespace TriggeredEventsDetail
|
||||
|
||||
namespace TerrainDetail
|
||||
{
|
||||
static const std::array<std::string, 10> terrainCodes =
|
||||
{
|
||||
"dt", "sa", "gr", "sn", "sw", "rg", "sb", "lv", "wt", "rc"
|
||||
};
|
||||
static const std::array<std::string, 4> roadCodes =
|
||||
{
|
||||
"", "pd", "pg", "pc"
|
||||
};
|
||||
|
||||
static const std::array<std::string, 5> riverCodes =
|
||||
{
|
||||
"", "rw", "ri", "rm", "rl"
|
||||
};
|
||||
|
||||
static const std::array<char, 4> flipCodes =
|
||||
{
|
||||
'_', '-', '|', '+'
|
||||
@ -959,13 +945,7 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
|
||||
using namespace TerrainDetail;
|
||||
{//terrain type
|
||||
const std::string typeCode = src.substr(0, 2);
|
||||
|
||||
int rawType = vstd::find_pos(terrainCodes, typeCode);
|
||||
|
||||
if(rawType < 0)
|
||||
throw std::runtime_error("Invalid terrain type code in "+src);
|
||||
|
||||
tile.terType = ETerrainType(rawType);
|
||||
tile.terType = Terrain::createTerrainByCode(typeCode);
|
||||
}
|
||||
int startPos = 2; //0+typeCode fixed length
|
||||
{//terrain view
|
||||
@ -992,20 +972,18 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
|
||||
{//road type
|
||||
const std::string typeCode = src.substr(startPos, 2);
|
||||
startPos+=2;
|
||||
int rawType = vstd::find_pos(roadCodes, typeCode);
|
||||
if(rawType < 0)
|
||||
if(vstd::find_pos(ROAD_NAMES, typeCode) < 0)
|
||||
{
|
||||
rawType = vstd::find_pos(riverCodes, typeCode);
|
||||
if(rawType < 0)
|
||||
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
|
||||
throw std::runtime_error("Invalid river type in "+src);
|
||||
else
|
||||
{
|
||||
tile.riverType = ERiverType::ERiverType(rawType);
|
||||
tile.riverType = typeCode;
|
||||
hasRoad = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
tile.roadType = ERoadType::ERoadType(rawType);
|
||||
tile.roadType = typeCode;
|
||||
}
|
||||
if(hasRoad)
|
||||
{//road dir
|
||||
@ -1033,10 +1011,9 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile
|
||||
{//river type
|
||||
const std::string typeCode = src.substr(startPos, 2);
|
||||
startPos+=2;
|
||||
int rawType = vstd::find_pos(riverCodes, typeCode);
|
||||
if(rawType < 0)
|
||||
if(vstd::find_pos(RIVER_NAMES, typeCode) < 0)
|
||||
throw std::runtime_error("Invalid river type in "+src);
|
||||
tile.riverType = ERiverType::ERiverType(rawType);
|
||||
tile.riverType = typeCode;
|
||||
}
|
||||
{//river dir
|
||||
int pos = startPos;
|
||||
@ -1298,13 +1275,13 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile)
|
||||
out.setf(std::ios::dec, std::ios::basefield);
|
||||
out.unsetf(std::ios::showbase);
|
||||
|
||||
out << terrainCodes.at(int(tile.terType)) << (int)tile.terView << flipCodes[tile.extTileFlags % 4];
|
||||
out << Terrain::Manager::getInfo(tile.terType).typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4];
|
||||
|
||||
if(tile.roadType != ERoadType::NO_ROAD)
|
||||
out << roadCodes.at(int(tile.roadType)) << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
|
||||
if(tile.roadType != ROAD_NAMES[0])
|
||||
out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4];
|
||||
|
||||
if(tile.riverType != ERiverType::NO_RIVER)
|
||||
out << riverCodes.at(int(tile.riverType)) << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
|
||||
if(tile.riverType != RIVER_NAMES[0])
|
||||
out << tile.riverType << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4];
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
@ -69,17 +69,6 @@ CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) :
|
||||
|
||||
void CMapGenerator::loadConfig()
|
||||
{
|
||||
static std::map<std::string, ETerrainType> terrainMap
|
||||
{
|
||||
{"dirt", ETerrainType::DIRT},
|
||||
{"sand", ETerrainType::SAND},
|
||||
{"grass", ETerrainType::GRASS},
|
||||
{"snow", ETerrainType::SNOW},
|
||||
{"swamp", ETerrainType::SWAMP},
|
||||
{"subterranean", ETerrainType::SUBTERRANEAN},
|
||||
{"lava", ETerrainType::LAVA},
|
||||
{"rough", ETerrainType::ROUGH}
|
||||
};
|
||||
static const std::map<std::string, Res::ERes> resMap
|
||||
{
|
||||
{"wood", Res::ERes::WOOD},
|
||||
@ -90,23 +79,17 @@ void CMapGenerator::loadConfig()
|
||||
{"sulfur", Res::ERes::SULFUR},
|
||||
{"gold", Res::ERes::GOLD},
|
||||
};
|
||||
static std::map<std::string, ERoadType::ERoadType> roadTypeMap
|
||||
{
|
||||
{"dirt_road", ERoadType::DIRT_ROAD},
|
||||
{"gravel_road", ERoadType::GRAVEL_ROAD},
|
||||
{"cobblestone_road", ERoadType::COBBLESTONE_ROAD}
|
||||
};
|
||||
static const ResourceID path("config/randomMap.json");
|
||||
JsonNode randomMapJson(path);
|
||||
for(auto& s : randomMapJson["terrain"]["undergroundAllow"].Vector())
|
||||
{
|
||||
if(!s.isNull())
|
||||
config.terrainUndergroundAllowed.push_back(terrainMap[s.String()]);
|
||||
config.terrainUndergroundAllowed.emplace_back(s.String());
|
||||
}
|
||||
for(auto& s : randomMapJson["terrain"]["groundProhibit"].Vector())
|
||||
{
|
||||
if(!s.isNull())
|
||||
config.terrainGroundProhibit.push_back(terrainMap[s.String()]);
|
||||
config.terrainGroundProhibit.emplace_back(s.String());
|
||||
}
|
||||
config.shipyardGuard = randomMapJson["waterZone"]["shipyard"]["value"].Integer();
|
||||
for(auto & treasure : randomMapJson["waterZone"]["treasure"].Vector())
|
||||
@ -119,7 +102,7 @@ void CMapGenerator::loadConfig()
|
||||
}
|
||||
config.mineExtraResources = randomMapJson["mines"]["extraResourcesLimit"].Integer();
|
||||
config.minGuardStrength = randomMapJson["minGuardStrength"].Integer();
|
||||
config.defaultRoadType = roadTypeMap[randomMapJson["defaultRoadType"].String()];
|
||||
config.defaultRoadType = randomMapJson["defaultRoadType"].String();
|
||||
config.treasureValueLimit = randomMapJson["treasureValueLimit"].Integer();
|
||||
for(auto & i : randomMapJson["prisons"]["experience"].Vector())
|
||||
config.prisonExperience.push_back(i.Integer());
|
||||
@ -357,7 +340,7 @@ void CMapGenerator::genZones()
|
||||
{
|
||||
getEditManager()->clearTerrain(&rand);
|
||||
getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight()));
|
||||
getEditManager()->drawTerrain(ETerrainType::GRASS, &rand);
|
||||
getEditManager()->drawTerrain(Terrain("grass"), &rand);
|
||||
|
||||
auto tmpl = mapGenOptions.getMapTemplate();
|
||||
zones.clear();
|
||||
@ -530,14 +513,14 @@ void CMapGenerator::fillZones()
|
||||
|
||||
void CMapGenerator::createObstaclesCommon1()
|
||||
{
|
||||
if (map->twoLevel) //underground
|
||||
if(map->twoLevel) //underground
|
||||
{
|
||||
//negative approach - create rock tiles first, then make sure all accessible tiles have no rock
|
||||
std::vector<int3> rockTiles;
|
||||
|
||||
for (int x = 0; x < map->width; x++)
|
||||
for(int x = 0; x < map->width; x++)
|
||||
{
|
||||
for (int y = 0; y < map->height; y++)
|
||||
for(int y = 0; y < map->height; y++)
|
||||
{
|
||||
int3 tile(x, y, 1);
|
||||
if (shouldBeBlocked(tile))
|
||||
@ -547,21 +530,29 @@ void CMapGenerator::createObstaclesCommon1()
|
||||
}
|
||||
}
|
||||
getEditManager()->getTerrainSelection().setSelection(rockTiles);
|
||||
getEditManager()->drawTerrain(ETerrainType::ROCK, &rand);
|
||||
|
||||
//collect all rock terrain types
|
||||
std::vector<Terrain> rockTerrains;
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
if(!terrain.isPassable())
|
||||
rockTerrains.push_back(terrain);
|
||||
auto rockTerrain = *RandomGeneratorUtil::nextItem(rockTerrains, rand);
|
||||
|
||||
getEditManager()->drawTerrain(rockTerrain, &rand);
|
||||
}
|
||||
}
|
||||
|
||||
void CMapGenerator::createObstaclesCommon2()
|
||||
{
|
||||
if (map->twoLevel)
|
||||
if(map->twoLevel)
|
||||
{
|
||||
//finally mark rock tiles as occupied, spawn no obstacles there
|
||||
for (int x = 0; x < map->width; x++)
|
||||
for(int x = 0; x < map->width; x++)
|
||||
{
|
||||
for (int y = 0; y < map->height; y++)
|
||||
for(int y = 0; y < map->height; y++)
|
||||
{
|
||||
int3 tile(x, y, 1);
|
||||
if (map->getTile(tile).terType == ETerrainType::ROCK)
|
||||
if(!map->getTile(tile).terType.isPassable())
|
||||
{
|
||||
setOccupied(tile, ETileType::USED);
|
||||
}
|
||||
@ -904,7 +895,7 @@ void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
|
||||
tiles[tile.x][tile.y][tile.z].setOccupied(state);
|
||||
}
|
||||
|
||||
void CMapGenerator::setRoad(const int3& tile, ERoadType::ERoadType roadType)
|
||||
void CMapGenerator::setRoad(const int3& tile, const std::string & roadType)
|
||||
{
|
||||
checkIsOnMap(tile);
|
||||
|
||||
|
@ -26,8 +26,6 @@ class JsonNode;
|
||||
class CMapGenerator;
|
||||
class CTileInfo;
|
||||
|
||||
//#define _BETA
|
||||
|
||||
typedef std::vector<JsonNode> JsonVector;
|
||||
|
||||
class rmgException : public std::exception
|
||||
@ -54,14 +52,14 @@ class DLL_LINKAGE CMapGenerator
|
||||
public:
|
||||
struct Config
|
||||
{
|
||||
std::vector<ETerrainType> terrainUndergroundAllowed;
|
||||
std::vector<ETerrainType> terrainGroundProhibit;
|
||||
std::vector<Terrain> terrainUndergroundAllowed;
|
||||
std::vector<Terrain> terrainGroundProhibit;
|
||||
std::vector<CTreasureInfo> waterTreasure;
|
||||
int shipyardGuard;
|
||||
int mineExtraResources;
|
||||
std::map<Res::ERes, int> mineValues;
|
||||
int minGuardStrength;
|
||||
ERoadType::ERoadType defaultRoadType;
|
||||
std::string defaultRoadType;
|
||||
int treasureValueLimit;
|
||||
std::vector<int> prisonExperience, prisonValues;
|
||||
std::vector<int> scrollValues;
|
||||
@ -101,7 +99,7 @@ public:
|
||||
bool isRoad(const int3 &tile) const;
|
||||
|
||||
void setOccupied(const int3 &tile, ETileType::ETileType state);
|
||||
void setRoad(const int3 &tile, ERoadType::ERoadType roadType);
|
||||
void setRoad(const int3 &tile, const std::string & roadType);
|
||||
|
||||
CTileInfo getTile(const int3 & tile) const;
|
||||
bool isAllowedSpell(SpellID sid) const;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../CTownHandler.h"
|
||||
#include "../Terrain.h"
|
||||
#include "../serializer/JsonSerializeFormat.h"
|
||||
#include "../StringConstants.h"
|
||||
|
||||
@ -66,12 +67,12 @@ class TerrainEncoder
|
||||
public:
|
||||
static si32 decode(const std::string & identifier)
|
||||
{
|
||||
return vstd::find_pos(GameConstants::TERRAIN_NAMES, identifier);
|
||||
return vstd::find_pos(Terrain::Manager::terrains(), identifier);
|
||||
}
|
||||
|
||||
static std::string encode(const si32 index)
|
||||
{
|
||||
return (index >=0 && index < GameConstants::TERRAIN_TYPES) ? GameConstants::TERRAIN_NAMES[index] : "<INVALID TERRAIN>";
|
||||
return (index >=0 && index < Terrain::Manager::terrains().size()) ? static_cast<std::string>(Terrain::Manager::terrains()[index]) : "<INVALID TERRAIN>";
|
||||
}
|
||||
};
|
||||
|
||||
@ -89,18 +90,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
const std::set<ETerrainType> ZoneOptions::DEFAULT_TERRAIN_TYPES =
|
||||
{
|
||||
ETerrainType::DIRT,
|
||||
ETerrainType::SAND,
|
||||
ETerrainType::GRASS,
|
||||
ETerrainType::SNOW,
|
||||
ETerrainType::SWAMP,
|
||||
ETerrainType::ROUGH,
|
||||
ETerrainType::SUBTERRANEAN,
|
||||
ETerrainType::LAVA
|
||||
};
|
||||
|
||||
const TRmgTemplateZoneId ZoneOptions::NO_ZONE = -1;
|
||||
|
||||
ZoneOptions::CTownInfo::CTownInfo()
|
||||
@ -149,7 +138,6 @@ ZoneOptions::ZoneOptions()
|
||||
playerTowns(),
|
||||
neutralTowns(),
|
||||
matchTerrainToTown(true),
|
||||
terrainTypes(DEFAULT_TERRAIN_TYPES),
|
||||
townsAreSameType(false),
|
||||
townTypes(),
|
||||
monsterTypes(),
|
||||
@ -161,7 +149,9 @@ ZoneOptions::ZoneOptions()
|
||||
terrainTypeLikeZone(NO_ZONE),
|
||||
treasureLikeZone(NO_ZONE)
|
||||
{
|
||||
|
||||
for(auto & terr : Terrain::Manager::terrains())
|
||||
if(terr.isLand() && terr.isPassable())
|
||||
terrainTypes.insert(terr);
|
||||
}
|
||||
|
||||
ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other)
|
||||
@ -224,15 +214,15 @@ boost::optional<int> ZoneOptions::getOwner() const
|
||||
return owner;
|
||||
}
|
||||
|
||||
const std::set<ETerrainType> & ZoneOptions::getTerrainTypes() const
|
||||
const std::set<Terrain> & ZoneOptions::getTerrainTypes() const
|
||||
{
|
||||
return terrainTypes;
|
||||
}
|
||||
|
||||
void ZoneOptions::setTerrainTypes(const std::set<ETerrainType> & value)
|
||||
void ZoneOptions::setTerrainTypes(const std::set<Terrain> & value)
|
||||
{
|
||||
assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() &&
|
||||
value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end());
|
||||
//assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() &&
|
||||
// value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end());
|
||||
terrainTypes = value;
|
||||
}
|
||||
|
||||
@ -339,7 +329,31 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
|
||||
#undef SERIALIZE_ZONE_LINK
|
||||
|
||||
if(terrainTypeLikeZone == NO_ZONE)
|
||||
handler.serializeIdArray<ETerrainType, TerrainEncoder>("terrainTypes", terrainTypes, DEFAULT_TERRAIN_TYPES);
|
||||
{
|
||||
JsonNode node;
|
||||
if(handler.saving)
|
||||
{
|
||||
node.setType(JsonNode::JsonType::DATA_VECTOR);
|
||||
for(auto & ttype : terrainTypes)
|
||||
{
|
||||
JsonNode n;
|
||||
n.String() = ttype;
|
||||
node.Vector().push_back(n);
|
||||
}
|
||||
}
|
||||
handler.serializeRaw("terrainTypes", node, boost::none);
|
||||
if(!handler.saving)
|
||||
{
|
||||
if(!node.Vector().empty())
|
||||
{
|
||||
terrainTypes.clear();
|
||||
for(auto ttype : node.Vector())
|
||||
{
|
||||
terrainTypes.emplace(ttype.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handler.serializeBool("townsAreSameType", townsAreSameType, false);
|
||||
handler.serializeIdArray<TFaction, FactionID>("allowedMonsters", monsterTypes, VLC->townh->getAllowedFactions(false));
|
||||
|
@ -13,9 +13,11 @@
|
||||
#include "../int3.h"
|
||||
#include "../GameConstants.h"
|
||||
#include "../ResourceSet.h"
|
||||
#include "../Terrain.h"
|
||||
#include "CMapGenOptions.h"
|
||||
|
||||
class JsonSerializeFormat;
|
||||
class Terrain;
|
||||
|
||||
namespace ETemplateZoneType
|
||||
{
|
||||
@ -65,7 +67,6 @@ private:
|
||||
class DLL_LINKAGE ZoneOptions
|
||||
{
|
||||
public:
|
||||
static const std::set<ETerrainType> DEFAULT_TERRAIN_TYPES;
|
||||
static const TRmgTemplateZoneId NO_ZONE;
|
||||
|
||||
class DLL_LINKAGE CTownInfo
|
||||
@ -101,8 +102,8 @@ public:
|
||||
void setSize(int value);
|
||||
boost::optional<int> getOwner() const;
|
||||
|
||||
const std::set<ETerrainType> & getTerrainTypes() const;
|
||||
void setTerrainTypes(const std::set<ETerrainType> & value);
|
||||
const std::set<Terrain> & getTerrainTypes() const;
|
||||
void setTerrainTypes(const std::set<Terrain> & value);
|
||||
|
||||
std::set<TFaction> getDefaultTownTypes() const;
|
||||
const std::set<TFaction> & getTownTypes() const;
|
||||
@ -134,7 +135,7 @@ protected:
|
||||
CTownInfo playerTowns;
|
||||
CTownInfo neutralTowns;
|
||||
bool matchTerrainToTown;
|
||||
std::set<ETerrainType> terrainTypes;
|
||||
std::set<Terrain> terrainTypes;
|
||||
bool townsAreSameType;
|
||||
|
||||
std::set<TFaction> townTypes;
|
||||
|
@ -36,7 +36,7 @@ void CRmgTemplateZone::addRoadNode(const int3& node)
|
||||
roadNodes.insert(node);
|
||||
}
|
||||
|
||||
CTileInfo::CTileInfo():nearestObjectDistance(float(INT_MAX)), terrain(ETerrainType::WRONG),roadType(ERoadType::NO_ROAD)
|
||||
CTileInfo::CTileInfo():nearestObjectDistance(float(INT_MAX)), terrain()
|
||||
{
|
||||
occupied = ETileType::POSSIBLE; //all tiles are initially possible to place objects or passages
|
||||
}
|
||||
@ -69,7 +69,7 @@ bool CTileInfo::isFree() const
|
||||
|
||||
bool CTileInfo::isRoad() const
|
||||
{
|
||||
return roadType != ERoadType::NO_ROAD;
|
||||
return roadType != ROAD_NAMES[0];
|
||||
}
|
||||
|
||||
bool CTileInfo::isUsed() const
|
||||
@ -86,17 +86,17 @@ ETileType::ETileType CTileInfo::getTileType() const
|
||||
return occupied;
|
||||
}
|
||||
|
||||
ETerrainType CTileInfo::getTerrainType() const
|
||||
Terrain CTileInfo::getTerrainType() const
|
||||
{
|
||||
return terrain;
|
||||
}
|
||||
|
||||
void CTileInfo::setTerrainType(ETerrainType value)
|
||||
void CTileInfo::setTerrainType(Terrain value)
|
||||
{
|
||||
terrain = value;
|
||||
}
|
||||
|
||||
void CTileInfo::setRoadType(ERoadType::ERoadType value)
|
||||
void CTileInfo::setRoadType(const std::string & value)
|
||||
{
|
||||
roadType = value;
|
||||
// setOccupied(ETileType::FREE);
|
||||
@ -106,7 +106,7 @@ void CTileInfo::setRoadType(ERoadType::ERoadType value)
|
||||
CRmgTemplateZone::CRmgTemplateZone(CMapGenerator * Gen)
|
||||
: ZoneOptions(),
|
||||
townType(ETownType::NEUTRAL),
|
||||
terrainType (ETerrainType::GRASS),
|
||||
terrainType (Terrain("grass")),
|
||||
minGuardedValue(0),
|
||||
questArtZone(),
|
||||
gen(Gen)
|
||||
@ -989,7 +989,7 @@ bool CRmgTemplateZone::createRoad(const int3& src, const int3& dst)
|
||||
std::map<int3, int3> cameFrom; // The map of navigated nodes.
|
||||
std::map<int3, float> distances;
|
||||
|
||||
gen->setRoad (src, ERoadType::NO_ROAD); //just in case zone guard already has road under it. Road under nodes will be added at very end
|
||||
gen->setRoad (src, ROAD_NAMES[0]); //just in case zone guard already has road under it. Road under nodes will be added at very end
|
||||
|
||||
cameFrom[src] = int3(-1, -1, -1); //first node points to finish condition
|
||||
pq.push(std::make_pair(src, 0.f));
|
||||
@ -1012,8 +1012,8 @@ bool CRmgTemplateZone::createRoad(const int3& src, const int3& dst)
|
||||
while (cameFrom[backTracking].valid())
|
||||
{
|
||||
// add node to path
|
||||
roads.insert (backTracking);
|
||||
gen->setRoad (backTracking, ERoadType::COBBLESTONE_ROAD);
|
||||
roads.insert(backTracking);
|
||||
gen->setRoad(backTracking, gen->getConfig().defaultRoadType);
|
||||
//logGlobal->trace("Setting road at tile %s", backTracking);
|
||||
// do the same for the predecessor
|
||||
backTracking = cameFrom[backTracking];
|
||||
@ -1250,6 +1250,17 @@ void CRmgTemplateZone::addToConnectLater(const int3& src)
|
||||
tilesToConnectLater.insert(src);
|
||||
}
|
||||
|
||||
int CRmgTemplateZone::chooseRandomAppearance(si32 ObjID) const
|
||||
{
|
||||
auto factories = VLC->objtypeh->knownSubObjects(ObjID);
|
||||
vstd::erase_if(factories, [this, ObjID](si32 f)
|
||||
{
|
||||
return VLC->objtypeh->getHandlerFor(ObjID, f)->getTemplates(terrainType).empty();
|
||||
});
|
||||
|
||||
return *RandomGeneratorUtil::nextItem(factories, gen->rand);
|
||||
}
|
||||
|
||||
bool CRmgTemplateZone::addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles, bool zoneGuard)
|
||||
{
|
||||
//precalculate actual (randomized) monster strength based on this post
|
||||
@ -1731,33 +1742,51 @@ void CRmgTemplateZone::initTerrainType ()
|
||||
{
|
||||
if (type==ETemplateZoneType::WATER)
|
||||
{
|
||||
terrainType = ETerrainType::WATER;
|
||||
//collect all water terrain types
|
||||
std::vector<Terrain> waterTerrains;
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
if(terrain.isWater())
|
||||
waterTerrains.push_back(terrain);
|
||||
|
||||
terrainType = *RandomGeneratorUtil::nextItem(waterTerrains, gen->rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (matchTerrainToTown && townType != ETownType::NEUTRAL)
|
||||
{
|
||||
terrainType = (*VLC->townh)[townType]->nativeTerrain;
|
||||
}
|
||||
else
|
||||
{
|
||||
terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand);
|
||||
}
|
||||
|
||||
//TODO: allow new types of terrain?
|
||||
{
|
||||
if(isUnderground())
|
||||
{
|
||||
if(!vstd::contains(gen->getConfig().terrainUndergroundAllowed, terrainType))
|
||||
terrainType = ETerrainType::SUBTERRANEAN;
|
||||
{
|
||||
//collect all underground terrain types
|
||||
std::vector<Terrain> undegroundTerrains;
|
||||
for(auto & terrain : Terrain::Manager::terrains())
|
||||
if(terrain.isUnderground())
|
||||
undegroundTerrains.push_back(terrain);
|
||||
|
||||
terrainType = *RandomGeneratorUtil::nextItem(undegroundTerrains, gen->rand);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vstd::contains(gen->getConfig().terrainGroundProhibit, terrainType))
|
||||
terrainType = ETerrainType::DIRT;
|
||||
if(vstd::contains(gen->getConfig().terrainGroundProhibit, terrainType) || terrainType.isUnderground())
|
||||
terrainType = Terrain("dirt");
|
||||
}
|
||||
}
|
||||
}
|
||||
paintZoneTerrain (terrainType);
|
||||
}
|
||||
|
||||
void CRmgTemplateZone::paintZoneTerrain (ETerrainType terrainType)
|
||||
void CRmgTemplateZone::paintZoneTerrain (Terrain terrainType)
|
||||
{
|
||||
std::vector<int3> tiles(tileinfo.begin(), tileinfo.end());
|
||||
gen->getEditManager()->getTerrainSelection().setSelection(tiles);
|
||||
@ -1837,6 +1866,9 @@ bool CRmgTemplateZone::createRequiredObjects()
|
||||
for(const auto &object : requiredObjects)
|
||||
{
|
||||
auto obj = object.first;
|
||||
if (!obj->appearance.canBePlacedAt(terrainType))
|
||||
continue;
|
||||
|
||||
int3 pos;
|
||||
while (true)
|
||||
{
|
||||
@ -1845,6 +1877,7 @@ bool CRmgTemplateZone::createRequiredObjects()
|
||||
logGlobal->error("Failed to fill zone %d due to lack of space", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tryToPlaceObjectAndConnectToPath(obj, pos) == EObjectPlacingResult::SUCCESS)
|
||||
{
|
||||
//paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones
|
||||
@ -1858,6 +1891,9 @@ bool CRmgTemplateZone::createRequiredObjects()
|
||||
for (const auto &obj : closeObjects)
|
||||
{
|
||||
setTemplateForObject(obj.first);
|
||||
if (!obj.first->appearance.canBePlacedAt(terrainType))
|
||||
continue;
|
||||
|
||||
auto tilesBlockedByObject = obj.first->getBlockedOffsets();
|
||||
|
||||
bool finished = false;
|
||||
@ -2069,8 +2105,8 @@ int3 CRmgTemplateZone::createShipyard(const std::set<int3> & lake, si32 guardStr
|
||||
|
||||
bool CRmgTemplateZone::createShipyard(const int3 & position, si32 guardStrength)
|
||||
{
|
||||
auto subObjects = VLC->objtypeh->knownSubObjects(Obj::SHIPYARD);
|
||||
auto shipyard = (CGShipyard*) VLC->objtypeh->getHandlerFor(Obj::SHIPYARD, *RandomGeneratorUtil::nextItem(subObjects, gen->rand))->create(ObjectTemplate());
|
||||
int subtype = chooseRandomAppearance(Obj::SHIPYARD);
|
||||
auto shipyard = (CGShipyard*) VLC->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create(ObjectTemplate());
|
||||
shipyard->tempOwner = PlayerColor::NEUTRAL;
|
||||
|
||||
setTemplateForObject(shipyard);
|
||||
@ -2569,7 +2605,8 @@ void CRmgTemplateZone::checkAndPlaceObject(CGObjectInstance* object, const int3
|
||||
if (object->appearance.id == Obj::NO_OBJ)
|
||||
{
|
||||
auto terrainType = gen->map->getTile(pos).terType;
|
||||
auto templates = VLC->objtypeh->getHandlerFor(object->ID, object->subID)->getTemplates(terrainType);
|
||||
auto h = VLC->objtypeh->getHandlerFor(object->ID, object->subID);
|
||||
auto templates = h->getTemplates(terrainType);
|
||||
if (templates.empty())
|
||||
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % object->ID % object->subID % pos.toString() % terrainType));
|
||||
|
||||
@ -3239,7 +3276,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
||||
if (!creaturesAmount)
|
||||
continue;
|
||||
|
||||
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
||||
int randomAppearance = chooseRandomAppearance(Obj::SEER_HUT);
|
||||
|
||||
oi.generateObject = [creature, creaturesAmount, randomAppearance, this, generateArtInfo]() -> CGObjectInstance *
|
||||
{
|
||||
@ -3270,7 +3307,7 @@ void CRmgTemplateZone::addAllPossibleObjects()
|
||||
static int seerLevels = std::min(gen->getConfig().questValues.size(), gen->getConfig().questRewardValues.size());
|
||||
for(int i = 0; i < seerLevels; i++) //seems that code for exp and gold reward is similiar
|
||||
{
|
||||
int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
|
||||
int randomAppearance = chooseRandomAppearance(Obj::SEER_HUT);
|
||||
|
||||
oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
|
||||
oi.value = gen->getConfig().questValues[i];
|
||||
@ -3332,7 +3369,7 @@ ObjectInfo::ObjectInfo()
|
||||
|
||||
}
|
||||
|
||||
void ObjectInfo::setTemplate (si32 type, si32 subtype, ETerrainType terrainType)
|
||||
void ObjectInfo::setTemplate (si32 type, si32 subtype, Terrain terrainType)
|
||||
{
|
||||
auto templHandler = VLC->objtypeh->getHandlerFor(type, subtype);
|
||||
if(!templHandler)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "CRmgTemplate.h"
|
||||
#include "../mapObjects/ObjectTemplate.h"
|
||||
#include <boost/heap/priority_queue.hpp> //A*
|
||||
#include "Terrain.h"
|
||||
|
||||
class CMapGenerator;
|
||||
class CTileInfo;
|
||||
@ -48,16 +49,16 @@ public:
|
||||
bool isUsed() const;
|
||||
bool isRoad() const;
|
||||
void setOccupied(ETileType::ETileType value);
|
||||
ETerrainType getTerrainType() const;
|
||||
Terrain getTerrainType() const;
|
||||
ETileType::ETileType getTileType() const;
|
||||
void setTerrainType(ETerrainType value);
|
||||
void setTerrainType(Terrain value);
|
||||
|
||||
void setRoadType(ERoadType::ERoadType value);
|
||||
void setRoadType(const std::string & value);
|
||||
private:
|
||||
float nearestObjectDistance;
|
||||
ETileType::ETileType occupied;
|
||||
ETerrainType terrain;
|
||||
ERoadType::ERoadType roadType;
|
||||
Terrain terrain;
|
||||
std::string roadType;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE ObjectInfo
|
||||
@ -69,7 +70,7 @@ struct DLL_LINKAGE ObjectInfo
|
||||
//ui32 maxPerMap; //unused
|
||||
std::function<CGObjectInstance *()> generateObject;
|
||||
|
||||
void setTemplate (si32 type, si32 subtype, ETerrainType terrain);
|
||||
void setTemplate (si32 type, si32 subtype, Terrain terrain);
|
||||
|
||||
ObjectInfo();
|
||||
|
||||
@ -120,7 +121,7 @@ public:
|
||||
bool fill ();
|
||||
bool placeMines ();
|
||||
void initTownType ();
|
||||
void paintZoneTerrain (ETerrainType terrainType);
|
||||
void paintZoneTerrain (Terrain terrainType);
|
||||
void randomizeTownType(bool matchUndergroundType = false); //helper function
|
||||
void initTerrainType ();
|
||||
void createBorder();
|
||||
@ -192,7 +193,7 @@ private:
|
||||
|
||||
//template info
|
||||
si32 townType;
|
||||
ETerrainType terrainType;
|
||||
Terrain terrainType;
|
||||
std::weak_ptr<CRmgTemplateZone> questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
|
||||
|
||||
std::vector<ObjectInfo> possibleObjects;
|
||||
@ -230,6 +231,7 @@ private:
|
||||
bool canObstacleBePlacedHere(ObjectTemplate &temp, int3 &pos);
|
||||
void setTemplateForObject(CGObjectInstance* obj);
|
||||
void checkAndPlaceObject(CGObjectInstance* object, const int3 &pos);
|
||||
int chooseRandomAppearance(si32 ObjID) const;
|
||||
|
||||
bool isGuardNeededForTreasure(int value);
|
||||
};
|
||||
|
@ -184,28 +184,26 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const
|
||||
zonesToPlace.push_back(zone);
|
||||
else
|
||||
{
|
||||
switch ((*VLC->townh)[faction]->nativeTerrain)
|
||||
auto & tt = (*VLC->townh)[faction]->nativeTerrain;
|
||||
if(tt == Terrain("dirt"))
|
||||
{
|
||||
case ETerrainType::GRASS:
|
||||
case ETerrainType::SWAMP:
|
||||
case ETerrainType::SNOW:
|
||||
case ETerrainType::SAND:
|
||||
case ETerrainType::ROUGH:
|
||||
//surface
|
||||
zonesOnLevel[0]++;
|
||||
levels[zone.first] = 0;
|
||||
break;
|
||||
case ETerrainType::LAVA:
|
||||
case ETerrainType::SUBTERRANEAN:
|
||||
//underground
|
||||
zonesOnLevel[1]++;
|
||||
levels[zone.first] = 1;
|
||||
break;
|
||||
case ETerrainType::DIRT:
|
||||
default:
|
||||
//any / random
|
||||
zonesToPlace.push_back(zone);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tt.isUnderground())
|
||||
{
|
||||
//underground
|
||||
zonesOnLevel[1]++;
|
||||
levels[zone.first] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//surface
|
||||
zonesOnLevel[0]++;
|
||||
levels[zone.first] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -564,7 +562,7 @@ void CZonePlacer::assignZones()
|
||||
|
||||
//make sure that terrain inside zone is not a rock
|
||||
//FIXME: reorder actions?
|
||||
zone.second->paintZoneTerrain (ETerrainType::SUBTERRANEAN);
|
||||
zone.second->paintZoneTerrain (Terrain("subterra"));
|
||||
}
|
||||
}
|
||||
logGlobal->info("Finished zone colouring");
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include "../ConstTransitivePtr.h"
|
||||
#include "../GameConstants.h"
|
||||
|
||||
const ui32 SERIALIZATION_VERSION = 801;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 753;
|
||||
const ui32 SERIALIZATION_VERSION = 802;
|
||||
const ui32 MINIMAL_SERIALIZATION_VERSION = 802;
|
||||
const std::string SAVEGAME_MAGIC = "VCMISVG";
|
||||
|
||||
class CHero;
|
||||
|
@ -1018,54 +1018,3 @@ std::vector<bool> CSpellHandler::getDefaultAllowed() const
|
||||
|
||||
return allowedSpells;
|
||||
}
|
||||
|
||||
void CSpellHandler::update780()
|
||||
{
|
||||
static_assert(MINIMAL_SERIALIZATION_VERSION < 780, "No longer needed CSpellHandler::update780");
|
||||
|
||||
auto spellsContent = (*VLC->modh->content)["spells"];
|
||||
|
||||
const ContentTypeHandler::ModInfo & coreData = spellsContent.modData.at("core");
|
||||
|
||||
const JsonNode & coreSpells = coreData.modData;
|
||||
|
||||
const int levelsCount = GameConstants::SPELL_SCHOOL_LEVELS;
|
||||
|
||||
for(CSpell * spell : objects)
|
||||
{
|
||||
auto identifier = spell->identifier;
|
||||
size_t colonPos = identifier.find(':');
|
||||
if(colonPos != std::string::npos)
|
||||
continue;
|
||||
|
||||
const JsonNode & actualConfig = coreSpells[spell->identifier];
|
||||
|
||||
if(actualConfig.getType() != JsonNode::JsonType::DATA_STRUCT)
|
||||
{
|
||||
logGlobal->error("Spell not found %s", spell->identifier);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(actualConfig["targetCondition"].getType() == JsonNode::JsonType::DATA_STRUCT && !actualConfig["targetCondition"].Struct().empty())
|
||||
{
|
||||
spell->targetCondition = actualConfig["targetCondition"];
|
||||
}
|
||||
|
||||
for(int levelIndex = 0; levelIndex < levelsCount; levelIndex++)
|
||||
{
|
||||
const JsonNode & levelNode = actualConfig["levels"][SpellConfig::LEVEL_NAMES[levelIndex]];
|
||||
|
||||
logGlobal->debug(levelNode.toJson());
|
||||
|
||||
CSpell::LevelInfo & levelObject = spell->levels[levelIndex];
|
||||
|
||||
if(levelNode["battleEffects"].getType() == JsonNode::JsonType::DATA_STRUCT && !levelNode["battleEffects"].Struct().empty())
|
||||
{
|
||||
levelObject.battleEffects = levelNode["battleEffects"];
|
||||
|
||||
logGlobal->trace("Updated special effects for level %d of spell %s", levelIndex, spell->identifier);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -83,14 +83,7 @@ public:
|
||||
{
|
||||
h & resourceName;
|
||||
h & verticalPosition;
|
||||
if(version >= 754)
|
||||
{
|
||||
h & pause;
|
||||
}
|
||||
else if(!h.saving)
|
||||
{
|
||||
pause = 0;
|
||||
}
|
||||
h & pause;
|
||||
}
|
||||
};
|
||||
|
||||
@ -120,10 +113,7 @@ public:
|
||||
h & projectile;
|
||||
h & hit;
|
||||
h & cast;
|
||||
if(version >= 762)
|
||||
{
|
||||
h & affect;
|
||||
}
|
||||
h & affect;
|
||||
}
|
||||
|
||||
std::string selectProjectile(const double angle) const;
|
||||
@ -158,32 +148,11 @@ public:
|
||||
h & AIValue;
|
||||
h & smartTarget;
|
||||
h & range;
|
||||
|
||||
if(version >= 773)
|
||||
{
|
||||
h & effects;
|
||||
h & cumulativeEffects;
|
||||
}
|
||||
else
|
||||
{
|
||||
//all old effects treated as not cumulative, special cases handled by CSpell::serialize
|
||||
std::vector<Bonus> old;
|
||||
h & old;
|
||||
|
||||
if(!h.saving)
|
||||
{
|
||||
effects.clear();
|
||||
cumulativeEffects.clear();
|
||||
for(const Bonus & oldBonus : old)
|
||||
effects.push_back(std::make_shared<Bonus>(oldBonus));
|
||||
}
|
||||
}
|
||||
|
||||
h & effects;
|
||||
h & cumulativeEffects;
|
||||
h & clearTarget;
|
||||
h & clearAffected;
|
||||
|
||||
if(version >= 780)
|
||||
h & battleEffects;
|
||||
h & battleEffects;
|
||||
}
|
||||
};
|
||||
|
||||
@ -316,27 +285,7 @@ public:
|
||||
h & damage;
|
||||
h & offensive;
|
||||
h & targetType;
|
||||
|
||||
if(version >= 780)
|
||||
{
|
||||
h & targetCondition;
|
||||
}
|
||||
else
|
||||
{
|
||||
BTVector immunities;
|
||||
BTVector absoluteImmunities;
|
||||
BTVector limiters;
|
||||
BTVector absoluteLimiters;
|
||||
|
||||
h & immunities;
|
||||
h & limiters;
|
||||
h & absoluteImmunities;
|
||||
h & absoluteLimiters;
|
||||
|
||||
if(!h.saving)
|
||||
targetCondition = convertTargetCondition(immunities, absoluteImmunities, limiters, absoluteLimiters);
|
||||
}
|
||||
|
||||
h & targetCondition;
|
||||
h & iconImmune;
|
||||
h & defaultProbability;
|
||||
h & special;
|
||||
@ -348,16 +297,6 @@ public:
|
||||
h & levels;
|
||||
h & school;
|
||||
h & animationInfo;
|
||||
|
||||
//backward compatibility
|
||||
//can not be added to level structure as level structure does not know spell id
|
||||
if(!h.saving && version < 773)
|
||||
{
|
||||
if(id == SpellID::DISRUPTING_RAY || id == SpellID::ACID_BREATH_DEFENSE)
|
||||
for(auto & level : levels)
|
||||
std::swap(level.effects, level.cumulativeEffects);
|
||||
}
|
||||
|
||||
}
|
||||
friend class CSpellHandler;
|
||||
friend class Graphics;
|
||||
@ -442,11 +381,6 @@ public:
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & objects;
|
||||
if(!h.saving && version < 780)
|
||||
{
|
||||
update780();
|
||||
}
|
||||
|
||||
if(!h.saving)
|
||||
{
|
||||
afterLoadFinalization();
|
||||
@ -456,6 +390,4 @@ public:
|
||||
protected:
|
||||
const std::vector<std::string> & getTypeNames() const override;
|
||||
CSpell * loadFromJson(const std::string & scope, const JsonNode & json, const std::string & identifier, size_t index) override;
|
||||
private:
|
||||
void update780();
|
||||
};
|
||||
|
@ -84,9 +84,7 @@ int BattleCbProxy::getTerrainType(lua_State * L)
|
||||
if(!S.tryGet(1, object))
|
||||
return S.retVoid();
|
||||
|
||||
auto ret = object->battleTerrainType();
|
||||
|
||||
return LuaStack::quickRetInt(L, static_cast<si32>(ret.num));
|
||||
return LuaStack::quickRetStr(L, object->battleTerrainType());
|
||||
}
|
||||
|
||||
int BattleCbProxy::getUnitByPos(lua_State * L)
|
||||
|
@ -1911,7 +1911,7 @@ void CGameHandler::newTurn()
|
||||
hth.id = h->id;
|
||||
auto ti = make_unique<TurnInfo>(h, 1);
|
||||
// TODO: this code executed when bonuses of previous day not yet updated (this happen in NewTurn::applyGs). See issue 2356
|
||||
hth.move = h->maxMovePointsCached(gs->map->getTile(h->getPosition(false)).terType != ETerrainType::WATER, ti.get());
|
||||
hth.move = h->maxMovePointsCached(gs->map->getTile(h->getPosition(false)).terType.isLand(), ti.get());
|
||||
hth.mana = h->getManaNewTurn();
|
||||
|
||||
n.heroes.insert(hth);
|
||||
@ -2215,9 +2215,9 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const
|
||||
battleResult.set(nullptr);
|
||||
|
||||
const auto t = getTile(tile);
|
||||
ETerrainType terrain = t->terType;
|
||||
Terrain terrain = t->terType;
|
||||
if (gs->map->isCoastalTile(tile)) //coastal tile is always ground
|
||||
terrain = ETerrainType::SAND;
|
||||
terrain = Terrain("sand");
|
||||
|
||||
BFieldType terType = gs->battleGetBattlefieldType(tile, getRandomGenerator());
|
||||
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
|
||||
@ -2314,7 +2314,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
const int3 guardPos = gs->guardingCreaturePosition(hmpos);
|
||||
|
||||
const bool embarking = !h->boat && !t.visitableObjects.empty() && t.visitableObjects.back()->ID == Obj::BOAT;
|
||||
const bool disembarking = h->boat && t.terType != ETerrainType::WATER && !t.blocked;
|
||||
const bool disembarking = h->boat && t.terType.isLand() && !t.blocked;
|
||||
|
||||
//result structure for start - movement failed, no move points used
|
||||
TryMoveHero tmh;
|
||||
@ -2336,11 +2336,11 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
|
||||
|
||||
//it's a rock or blocked and not visitable tile
|
||||
//OR hero is on land and dest is water and (there is not present only one object - boat)
|
||||
if (((t.terType == ETerrainType::ROCK || (t.blocked && !t.visitable && !canFly))
|
||||
if (((!t.terType.isPassable() || (t.blocked && !t.visitable && !canFly))
|
||||
&& complain("Cannot move hero, destination tile is blocked!"))
|
||||
|| ((!h->boat && !canWalkOnSea && !canFly && t.terType == ETerrainType::WATER && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != Obj::BOAT && t.visitableObjects.back()->ID != Obj::HERO))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
||||
|| ((!h->boat && !canWalkOnSea && !canFly && t.terType.isWater() && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != Obj::BOAT && t.visitableObjects.back()->ID != Obj::HERO))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|
||||
&& complain("Cannot move hero, destination tile is on water!"))
|
||||
|| ((h->boat && t.terType != ETerrainType::WATER && t.blocked)
|
||||
|| ((h->boat && t.terType.isLand() && t.blocked)
|
||||
&& complain("Cannot disembark hero, tile is blocked!"))
|
||||
|| ((distance(h->pos, dst) >= 1.5 && !teleporting)
|
||||
&& complain("Tiles are not neighboring!"))
|
||||
|
@ -272,21 +272,14 @@ public:
|
||||
h & QID;
|
||||
h & states;
|
||||
h & finishingBattle;
|
||||
h & getRandomGenerator();
|
||||
|
||||
if(version >= 761)
|
||||
{
|
||||
h & getRandomGenerator();
|
||||
}
|
||||
|
||||
if(version >= 800)
|
||||
{
|
||||
JsonNode scriptsState;
|
||||
if(h.saving)
|
||||
serverScripts->serializeState(h.saving, scriptsState);
|
||||
h & scriptsState;
|
||||
if(!h.saving)
|
||||
serverScripts->serializeState(h.saving, scriptsState);
|
||||
}
|
||||
JsonNode scriptsState;
|
||||
if(h.saving)
|
||||
serverScripts->serializeState(h.saving, scriptsState);
|
||||
h & scriptsState;
|
||||
if(!h.saving)
|
||||
serverScripts->serializeState(h.saving, scriptsState);
|
||||
}
|
||||
|
||||
void sendMessageToAll(const std::string &message);
|
||||
@ -314,11 +307,6 @@ public:
|
||||
h & loserHero;
|
||||
h & victor;
|
||||
h & loser;
|
||||
if(version < 774 && !h.saving)
|
||||
{
|
||||
bool duel;
|
||||
h & duel;
|
||||
}
|
||||
h & remainingBattleQueriesCount;
|
||||
}
|
||||
};
|
||||
|
@ -193,7 +193,7 @@ public:
|
||||
|
||||
const auto t = gameCallback->getTile(tile);
|
||||
|
||||
ETerrainType terrain = t->terType;
|
||||
Terrain terrain = t->terType;
|
||||
BFieldType terType = BFieldType::GRASS_HILLS;
|
||||
|
||||
//send info about battles
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e2239ee6043f73722e7aa812a459f54a28552929
|
||||
Subproject commit 4bab34d2084259cba67f3bfb51217c10d606e175
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user