mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-17 01:32:21 +02:00
Proof of concept with OH3 obstacles
This commit is contained in:
@ -121,6 +121,7 @@ set(lib_MAIN_SRCS
|
|||||||
mapObjects/IObjectInterface.cpp
|
mapObjects/IObjectInterface.cpp
|
||||||
mapObjects/MiscObjects.cpp
|
mapObjects/MiscObjects.cpp
|
||||||
mapObjects/ObjectTemplate.cpp
|
mapObjects/ObjectTemplate.cpp
|
||||||
|
mapObjects/ObstacleSetHandler.cpp
|
||||||
|
|
||||||
mapping/CDrawRoadsOperation.cpp
|
mapping/CDrawRoadsOperation.cpp
|
||||||
mapping/CMap.cpp
|
mapping/CMap.cpp
|
||||||
@ -482,6 +483,7 @@ set(lib_MAIN_HEADERS
|
|||||||
mapObjects/MapObjects.h
|
mapObjects/MapObjects.h
|
||||||
mapObjects/MiscObjects.h
|
mapObjects/MiscObjects.h
|
||||||
mapObjects/ObjectTemplate.h
|
mapObjects/ObjectTemplate.h
|
||||||
|
mapObjects/ObstacleSetHandler.h
|
||||||
|
|
||||||
mapping/CDrawRoadsOperation.h
|
mapping/CDrawRoadsOperation.h
|
||||||
mapping/CMapDefines.h
|
mapping/CMapDefines.h
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "rmg/CRmgTemplateStorage.h"
|
#include "rmg/CRmgTemplateStorage.h"
|
||||||
#include "mapObjectConstructors/CObjectClassesHandler.h"
|
#include "mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "mapObjects/CObjectHandler.h"
|
#include "mapObjects/CObjectHandler.h"
|
||||||
|
#include "mapObjects/ObstacleSetHandler.h"
|
||||||
#include "mapping/CMapEditManager.h"
|
#include "mapping/CMapEditManager.h"
|
||||||
#include "ScriptHandler.h"
|
#include "ScriptHandler.h"
|
||||||
#include "BattleFieldHandler.h"
|
#include "BattleFieldHandler.h"
|
||||||
@ -223,6 +224,7 @@ void LibClasses::init(bool onlyEssential)
|
|||||||
createHandler(arth, "Artifact", pomtime);
|
createHandler(arth, "Artifact", pomtime);
|
||||||
createHandler(creh, "Creature", pomtime);
|
createHandler(creh, "Creature", pomtime);
|
||||||
createHandler(townh, "Town", pomtime);
|
createHandler(townh, "Town", pomtime);
|
||||||
|
createHandler(biomeHandler, "Obstacle set", pomtime);
|
||||||
createHandler(objh, "Object", pomtime);
|
createHandler(objh, "Object", pomtime);
|
||||||
createHandler(objtypeh, "Object types information", pomtime);
|
createHandler(objtypeh, "Object types information", pomtime);
|
||||||
createHandler(spellh, "Spell", pomtime);
|
createHandler(spellh, "Spell", pomtime);
|
||||||
|
@ -23,6 +23,7 @@ class CSkillHandler;
|
|||||||
class CBuildingHandler;
|
class CBuildingHandler;
|
||||||
class CObjectHandler;
|
class CObjectHandler;
|
||||||
class CObjectClassesHandler;
|
class CObjectClassesHandler;
|
||||||
|
class ObstacleSetHandler;
|
||||||
class CTownHandler;
|
class CTownHandler;
|
||||||
class CGeneralTextHandler;
|
class CGeneralTextHandler;
|
||||||
class CModHandler;
|
class CModHandler;
|
||||||
@ -85,6 +86,7 @@ public:
|
|||||||
std::shared_ptr<CCreatureHandler> creh;
|
std::shared_ptr<CCreatureHandler> creh;
|
||||||
std::shared_ptr<CSpellHandler> spellh;
|
std::shared_ptr<CSpellHandler> spellh;
|
||||||
std::shared_ptr<CSkillHandler> skillh;
|
std::shared_ptr<CSkillHandler> skillh;
|
||||||
|
// TODO: Remove ObjectHandler altogether?
|
||||||
std::shared_ptr<CObjectHandler> objh;
|
std::shared_ptr<CObjectHandler> objh;
|
||||||
std::shared_ptr<CObjectClassesHandler> objtypeh;
|
std::shared_ptr<CObjectClassesHandler> objtypeh;
|
||||||
std::shared_ptr<CTownHandler> townh;
|
std::shared_ptr<CTownHandler> townh;
|
||||||
@ -99,6 +101,7 @@ public:
|
|||||||
std::shared_ptr<BattleFieldHandler> battlefieldsHandler;
|
std::shared_ptr<BattleFieldHandler> battlefieldsHandler;
|
||||||
std::shared_ptr<ObstacleHandler> obstacleHandler;
|
std::shared_ptr<ObstacleHandler> obstacleHandler;
|
||||||
std::shared_ptr<GameSettings> settingsHandler;
|
std::shared_ptr<GameSettings> settingsHandler;
|
||||||
|
std::shared_ptr<ObstacleSetHandler> biomeHandler;
|
||||||
|
|
||||||
#if SCRIPTING_ENABLED
|
#if SCRIPTING_ENABLED
|
||||||
std::shared_ptr<scripting::ScriptHandler> scriptHandler;
|
std::shared_ptr<scripting::ScriptHandler> scriptHandler;
|
||||||
|
@ -457,7 +457,46 @@ public:
|
|||||||
WHIRLPOOL = 111,
|
WHIRLPOOL = 111,
|
||||||
WINDMILL = 112,
|
WINDMILL = 112,
|
||||||
WITCH_HUT = 113,
|
WITCH_HUT = 113,
|
||||||
|
BRUSH = 114, // TODO: How does it look like?
|
||||||
|
BUSH = 115,
|
||||||
|
CACTUS = 116,
|
||||||
|
CANYON = 117,
|
||||||
|
CRATER = 118,
|
||||||
|
DEAD_VEGETATION = 119,
|
||||||
|
FLOWERS = 120,
|
||||||
|
FROZEN_LAKE = 121,
|
||||||
|
HEDGE = 122,
|
||||||
|
HILL = 123,
|
||||||
HOLE = 124,
|
HOLE = 124,
|
||||||
|
KELP = 125,
|
||||||
|
LAKE = 126,
|
||||||
|
LAVA_FLOW = 127,
|
||||||
|
LAVA_LAKE = 128,
|
||||||
|
MUSHROOMS = 129,
|
||||||
|
LOG = 130,
|
||||||
|
MANDRAKE = 131,
|
||||||
|
MOSS = 132,
|
||||||
|
MOUND = 133,
|
||||||
|
MOUNTAIN = 134,
|
||||||
|
OAK_TREES = 135,
|
||||||
|
OUTCROPPING = 136,
|
||||||
|
PINE_TREES = 137,
|
||||||
|
PLANT = 138,
|
||||||
|
ROCK = 147,
|
||||||
|
SAND_DUNE = 148,
|
||||||
|
SAND_PIT = 149,
|
||||||
|
SHRUB = 150,
|
||||||
|
SKULL = 151,
|
||||||
|
STALAGMITE = 152,
|
||||||
|
STUMP = 153,
|
||||||
|
TAR_PIT = 154,
|
||||||
|
TREES = 155,
|
||||||
|
VINE = 156,
|
||||||
|
VOLCANIC_VENT = 157,
|
||||||
|
VOLCANO = 158,
|
||||||
|
WILLOW_TREES = 159,
|
||||||
|
YUCCA_TREES = 160,
|
||||||
|
REEF = 161,
|
||||||
RANDOM_MONSTER_L5 = 162,
|
RANDOM_MONSTER_L5 = 162,
|
||||||
RANDOM_MONSTER_L6 = 163,
|
RANDOM_MONSTER_L6 = 163,
|
||||||
RANDOM_MONSTER_L7 = 164,
|
RANDOM_MONSTER_L7 = 164,
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "../mapObjects/MiscObjects.h"
|
#include "../mapObjects/MiscObjects.h"
|
||||||
#include "../mapObjects/CGHeroInstance.h"
|
#include "../mapObjects/CGHeroInstance.h"
|
||||||
#include "../mapObjects/CGTownInstance.h"
|
#include "../mapObjects/CGTownInstance.h"
|
||||||
|
#include "../mapObjects/ObstacleSetHandler.h"
|
||||||
#include "../modding/IdentifierStorage.h"
|
#include "../modding/IdentifierStorage.h"
|
||||||
#include "../modding/CModHandler.h"
|
#include "../modding/CModHandler.h"
|
||||||
#include "../modding/ModScope.h"
|
#include "../modding/ModScope.h"
|
||||||
@ -107,6 +108,8 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
|
|||||||
auto totalNumber = static_cast<size_t>(parser.readNumber()); // first line contains number of objects to read and nothing else
|
auto totalNumber = static_cast<size_t>(parser.readNumber()); // first line contains number of objects to read and nothing else
|
||||||
parser.endLine();
|
parser.endLine();
|
||||||
|
|
||||||
|
std::map<TerrainId, std::map<MapObjectID, std::map<MapObjectSubID, ObstacleSet>>> obstacleSets;
|
||||||
|
|
||||||
for (size_t i = 0; i < totalNumber; i++)
|
for (size_t i = 0; i < totalNumber; i++)
|
||||||
{
|
{
|
||||||
auto tmpl = std::make_shared<ObjectTemplate>();
|
auto tmpl = std::make_shared<ObjectTemplate>();
|
||||||
@ -116,7 +119,44 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
|
|||||||
|
|
||||||
std::pair key(tmpl->id, tmpl->subid);
|
std::pair key(tmpl->id, tmpl->subid);
|
||||||
legacyTemplates.insert(std::make_pair(key, tmpl));
|
legacyTemplates.insert(std::make_pair(key, tmpl));
|
||||||
|
|
||||||
|
// Populate ObstacleSetHandler on our way
|
||||||
|
if (!tmpl->isVisitable())
|
||||||
|
{
|
||||||
|
// Create obstacle sets. Group by terrain for now
|
||||||
|
|
||||||
|
for (auto terrain : tmpl->getAllowedTerrains())
|
||||||
|
{
|
||||||
|
auto &obstacleMap = obstacleSets[terrain][tmpl->id];
|
||||||
|
auto it = obstacleMap.find(tmpl->subid);
|
||||||
|
if (it == obstacleMap.end())
|
||||||
|
{
|
||||||
|
// FIXME: This means this set will be available only on one terrain
|
||||||
|
auto type = VLC->biomeHandler->convertObstacleClass(tmpl->id);
|
||||||
|
auto newIt = obstacleMap.insert(std::make_pair(tmpl->subid, ObstacleSet(type, terrain)));
|
||||||
|
newIt.first->second.addObstacle(tmpl);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
it->second.addObstacle(tmpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto terrain : obstacleSets)
|
||||||
|
{
|
||||||
|
for (auto obstacleType : terrain.second)
|
||||||
|
{
|
||||||
|
for (auto obstacleSet : obstacleType.second)
|
||||||
|
{
|
||||||
|
VLC->biomeHandler->addObstacleSet(obstacleSet.second);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logGlobal->info("Obstacle sets loaded: %d", count);
|
||||||
|
|
||||||
objects.resize(256);
|
objects.resize(256);
|
||||||
|
|
||||||
|
153
lib/mapObjects/ObstacleSetHandler.cpp
Normal file
153
lib/mapObjects/ObstacleSetHandler.cpp
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* ObstacleSetHandler.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "ObstacleSetHandler.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain):
|
||||||
|
type(type),
|
||||||
|
terrain(terrain)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObstacleSet::addObstacle(std::shared_ptr<const ObjectTemplate> obstacle)
|
||||||
|
{
|
||||||
|
obstacles.push_back(obstacle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain = TerrainId::ANY_TERRAIN):
|
||||||
|
allowedTypes(allowedTypes),
|
||||||
|
terrain(terrain)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain = TerrainId::ANY_TERRAIN):
|
||||||
|
allowedTypes({allowedType}),
|
||||||
|
terrain(terrain)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObstacleSetFilter::filter(const ObstacleSet &set) const
|
||||||
|
{
|
||||||
|
return (set.getTerrain() == terrain) || (terrain == TerrainId::ANY_TERRAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId ObstacleSetFilter::getTerrain() const
|
||||||
|
{
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainId ObstacleSet::getTerrain() const
|
||||||
|
{
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObstacleSet::EObstacleType ObstacleSet::getType() const
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<const ObjectTemplate>> ObstacleSet::getObstacles() const
|
||||||
|
{
|
||||||
|
return obstacles;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObstacleSet::EObstacleType ObstacleSetHandler::convertObstacleClass(MapObjectID id)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
case Obj::MOUNTAIN:
|
||||||
|
case Obj::SAND_DUNE:
|
||||||
|
case Obj::VOLCANIC_VENT:
|
||||||
|
case Obj::VOLCANO:
|
||||||
|
case Obj::REEF:
|
||||||
|
return ObstacleSet::MOUNTAINS;
|
||||||
|
case Obj::OAK_TREES:
|
||||||
|
case Obj::PINE_TREES:
|
||||||
|
case Obj::TREES:
|
||||||
|
case Obj::DEAD_VEGETATION:
|
||||||
|
case Obj::HEDGE:
|
||||||
|
case Obj::KELP:
|
||||||
|
case Obj::WILLOW_TREES:
|
||||||
|
case Obj::YUCCA_TREES:
|
||||||
|
return ObstacleSet::TREES;
|
||||||
|
case Obj::FROZEN_LAKE:
|
||||||
|
case Obj::LAKE:
|
||||||
|
case Obj::LAVA_FLOW:
|
||||||
|
case Obj::LAVA_LAKE:
|
||||||
|
return ObstacleSet::LAKES;
|
||||||
|
case Obj::CANYON:
|
||||||
|
case Obj::CRATER:
|
||||||
|
case Obj::SAND_PIT:
|
||||||
|
case Obj::TAR_PIT:
|
||||||
|
return ObstacleSet::CRATERS;
|
||||||
|
case Obj::HILL:
|
||||||
|
case Obj::MOUND:
|
||||||
|
case Obj::OUTCROPPING:
|
||||||
|
case Obj::ROCK:
|
||||||
|
case Obj::STALAGMITE:
|
||||||
|
return ObstacleSet::ROCKS;
|
||||||
|
case Obj::BUSH:
|
||||||
|
case Obj::CACTUS:
|
||||||
|
case Obj::FLOWERS:
|
||||||
|
case Obj::MUSHROOMS:
|
||||||
|
case Obj::LOG:
|
||||||
|
case Obj::MANDRAKE:
|
||||||
|
case Obj::MOSS:
|
||||||
|
case Obj::PLANT:
|
||||||
|
case Obj::SHRUB:
|
||||||
|
case Obj::STUMP:
|
||||||
|
case Obj::VINE:
|
||||||
|
return ObstacleSet::PLANTS;
|
||||||
|
case Obj::SKULL:
|
||||||
|
return ObstacleSet::ANIMALS;
|
||||||
|
default:
|
||||||
|
return ObstacleSet::OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const
|
||||||
|
{
|
||||||
|
return allowedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObstacleSetHandler::addObstacleSet(const ObstacleSet &os)
|
||||||
|
{
|
||||||
|
obstacleSets[os.getType()].push_back(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
TObstacleTypes ObstacleSetHandler::getObstacles( const ObstacleSetFilter &filter) const
|
||||||
|
{
|
||||||
|
// TODO: Handle multiple terrains for one obstacle set?
|
||||||
|
auto terrainType = filter.getTerrain();
|
||||||
|
|
||||||
|
TObstacleTypes result;
|
||||||
|
|
||||||
|
for (const auto &allowedType : filter.getAllowedTypes())
|
||||||
|
{
|
||||||
|
auto it = obstacleSets.find(allowedType);
|
||||||
|
if(it != obstacleSets.end())
|
||||||
|
{
|
||||||
|
for (const auto &os : it->second)
|
||||||
|
{
|
||||||
|
if (filter.filter(os))
|
||||||
|
{
|
||||||
|
result.push_back(os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
99
lib/mapObjects/ObstacleSetHandler.h
Normal file
99
lib/mapObjects/ObstacleSetHandler.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* ObstacleSetHandler.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 "../GameConstants.h"
|
||||||
|
#include "../constants/EntityIdentifiers.h"
|
||||||
|
#include "../IHandlerBase.h"
|
||||||
|
#include "../json/JsonNode.h"
|
||||||
|
#include "ObjectTemplate.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class DLL_LINKAGE ObstacleSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// TODO: Create string constants for these
|
||||||
|
|
||||||
|
enum EObstacleType
|
||||||
|
{
|
||||||
|
MOUNTAINS,
|
||||||
|
TREES,
|
||||||
|
LAKES, // Inluding dry or lava lakes
|
||||||
|
CRATERS, // Chasms, Canyons, etc.
|
||||||
|
ROCKS,
|
||||||
|
PLANTS, // Flowers, cacti, mushrooms, logs, shrubs, etc.
|
||||||
|
STRUCTURES, // Buildings, ruins, etc.
|
||||||
|
ANIMALS, // Living, or bones
|
||||||
|
OTHER // Crystals, shipwrecks, barrels, etc.
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit ObstacleSet(EObstacleType type, TerrainId terrain);
|
||||||
|
|
||||||
|
void addObstacle(std::shared_ptr<const ObjectTemplate> obstacle);
|
||||||
|
std::vector<std::shared_ptr<const ObjectTemplate>> getObstacles() const;
|
||||||
|
|
||||||
|
EObstacleType getType() const;
|
||||||
|
TerrainId getTerrain() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EObstacleType type;
|
||||||
|
TerrainId terrain;
|
||||||
|
std::vector<std::shared_ptr<const ObjectTemplate>> obstacles;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<ObstacleSet> TObstacleTypes;
|
||||||
|
|
||||||
|
class DLL_LINKAGE ObstacleSetFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain);
|
||||||
|
ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain);
|
||||||
|
|
||||||
|
bool filter(const ObstacleSet &set) const;
|
||||||
|
|
||||||
|
std::vector<ObstacleSet::EObstacleType> getAllowedTypes() const;
|
||||||
|
TerrainId getTerrain() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ObstacleSet::EObstacleType> allowedTypes;
|
||||||
|
// TODO: Filter by faction, alignment, surface/underground, etc.
|
||||||
|
const TerrainId terrain;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Instantiate ObstacleSetHandler
|
||||||
|
class DLL_LINKAGE ObstacleSetHandler : public IHandlerBase, boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ObstacleSetHandler() = default;
|
||||||
|
~ObstacleSetHandler() = default;
|
||||||
|
|
||||||
|
// FIXME: Not needed at all
|
||||||
|
std::vector<JsonNode> loadLegacyData() override {return {};};
|
||||||
|
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override {};
|
||||||
|
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override {};
|
||||||
|
|
||||||
|
ObstacleSet::EObstacleType convertObstacleClass(MapObjectID id);
|
||||||
|
|
||||||
|
// TODO: Populate obstacleSets with all the obstacle sets from the game data
|
||||||
|
|
||||||
|
void addObstacleSet(const ObstacleSet &set);
|
||||||
|
|
||||||
|
TObstacleTypes getObstacles(const ObstacleSetFilter &filter) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::map<ObstacleSet::EObstacleType, std::vector<ObstacleSet>> obstacleSets;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -15,6 +15,7 @@
|
|||||||
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
||||||
#include "../mapObjects/CGObjectInstance.h"
|
#include "../mapObjects/CGObjectInstance.h"
|
||||||
#include "../mapObjects/ObjectTemplate.h"
|
#include "../mapObjects/ObjectTemplate.h"
|
||||||
|
#include "../mapObjects/ObstacleSetHandler.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -46,6 +47,170 @@ void ObstacleProxy::collectPossibleObstacles(TerrainId terrain)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
|
||||||
|
{
|
||||||
|
// FIXME: All the mountains have same ID and mostly same subID, how to differentiate them?
|
||||||
|
|
||||||
|
bool isPrepared = false;
|
||||||
|
|
||||||
|
possibleObstacles.clear();
|
||||||
|
|
||||||
|
// TODO: Where to parse these sets?
|
||||||
|
|
||||||
|
std::vector<ObstacleSet> obstacleSets;
|
||||||
|
|
||||||
|
size_t selectedSets = 0;
|
||||||
|
size_t smallSets = 0;
|
||||||
|
const size_t MINIMUM_SETS = 6;
|
||||||
|
const size_t MAXIMUM_SETS = 9;
|
||||||
|
const size_t MIN_SMALL_SETS = 3;
|
||||||
|
const size_t MAX_SMALL_SETS = 5;
|
||||||
|
|
||||||
|
TObstacleTypes mountainSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::MOUNTAINS, terrain));
|
||||||
|
|
||||||
|
if (!mountainSets.empty())
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(*RandomGeneratorUtil::nextItem(mountainSets, rand));
|
||||||
|
selectedSets++;
|
||||||
|
logGlobal->info("Mountain set added");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->warn("No mountain sets found for terrain %s", terrain.encode(terrain.getNum()));
|
||||||
|
// FIXME: Do we ever want to generate obstacles without any mountains?
|
||||||
|
}
|
||||||
|
|
||||||
|
TObstacleTypes treeSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::TREES, terrain));
|
||||||
|
|
||||||
|
// 1 or 2 tree sets
|
||||||
|
size_t treeSetsCount = std::min<size_t>(treeSets.size(), rand.nextInt(1, 2));
|
||||||
|
for (size_t i = 0; i < treeSetsCount; i++)
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(*RandomGeneratorUtil::nextItem(treeSets, rand));
|
||||||
|
selectedSets++;
|
||||||
|
}
|
||||||
|
logGlobal->info("Added %d tree sets", treeSetsCount);
|
||||||
|
|
||||||
|
// Some obstacle types may be completely missing from water, but it's not a problem
|
||||||
|
TObstacleTypes largeSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter({ObstacleSet::EObstacleType::LAKES, ObstacleSet::EObstacleType::CRATERS},
|
||||||
|
terrain));
|
||||||
|
|
||||||
|
// We probably don't want to have lakes and craters at the same time, choose one of them
|
||||||
|
|
||||||
|
if (!largeSets.empty())
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(*RandomGeneratorUtil::nextItem(largeSets, rand));
|
||||||
|
selectedSets++;
|
||||||
|
|
||||||
|
// TODO: Convert to string
|
||||||
|
logGlobal->info("Added large set of type %s", obstacleSets.back().getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
TObstacleTypes rockSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::ROCKS, terrain));
|
||||||
|
|
||||||
|
size_t rockSetsCount = std::min<size_t>(rockSets.size(), rand.nextInt(1, 2));
|
||||||
|
for (size_t i = 0; i < rockSetsCount; i++)
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(*RandomGeneratorUtil::nextItem(rockSets, rand));
|
||||||
|
selectedSets++;
|
||||||
|
}
|
||||||
|
logGlobal->info("Added %d rock sets", rockSetsCount);
|
||||||
|
|
||||||
|
TObstacleTypes plantSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::PLANTS, terrain));
|
||||||
|
|
||||||
|
// 1 or 2 sets (3 - rock sets)
|
||||||
|
size_t plantSetsCount = std::min<size_t>(plantSets.size(), rand.nextInt(1, std::max<size_t>(3 - rockSetsCount, 2)));
|
||||||
|
for (size_t i = 0; i < plantSetsCount; i++)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(*RandomGeneratorUtil::nextItem(plantSets, rand));
|
||||||
|
selectedSets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logGlobal->info("Added %d plant sets", plantSetsCount);
|
||||||
|
|
||||||
|
//3 to 5 of total small sets (rocks, plants, structures, animals and others)
|
||||||
|
//This gives total of 6 to 9 different sets
|
||||||
|
|
||||||
|
size_t maxSmallSets = std::min<size_t>(MAX_SMALL_SETS, std::max(MIN_SMALL_SETS, MAXIMUM_SETS - selectedSets));
|
||||||
|
|
||||||
|
size_t smallSetsCount = rand.nextInt(MIN_SMALL_SETS, maxSmallSets);
|
||||||
|
|
||||||
|
TObstacleTypes smallObstacleSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter({ObstacleSet::EObstacleType::STRUCTURES, ObstacleSet::EObstacleType::ANIMALS},
|
||||||
|
terrain));
|
||||||
|
RandomGeneratorUtil::randomShuffle(smallObstacleSets, rand);
|
||||||
|
|
||||||
|
TObstacleTypes otherSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::OTHER,
|
||||||
|
terrain));
|
||||||
|
RandomGeneratorUtil::randomShuffle(otherSets, rand);
|
||||||
|
|
||||||
|
while (smallSetsCount > 0)
|
||||||
|
{
|
||||||
|
if (!smallObstacleSets.empty())
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(smallObstacleSets.back());
|
||||||
|
smallObstacleSets.pop_back();
|
||||||
|
selectedSets++;
|
||||||
|
smallSetsCount--;
|
||||||
|
logGlobal->info("Added small set of type %s", obstacleSets.back().getType());
|
||||||
|
}
|
||||||
|
else if(otherSets.empty())
|
||||||
|
{
|
||||||
|
logGlobal->warn("No other sets found for terrain %s", terrain.encode(terrain.getNum()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smallSetsCount > 0)
|
||||||
|
{
|
||||||
|
// Fill with whatever's left
|
||||||
|
if (!otherSets.empty())
|
||||||
|
{
|
||||||
|
obstacleSets.push_back(otherSets.back());
|
||||||
|
otherSets.pop_back();
|
||||||
|
selectedSets++;
|
||||||
|
smallSetsCount--;
|
||||||
|
|
||||||
|
logGlobal->info("Added set of other obstacles");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy this set to our possible obstacles
|
||||||
|
|
||||||
|
if (selectedSets >= MINIMUM_SETS)
|
||||||
|
{
|
||||||
|
obstaclesBySize.clear();
|
||||||
|
for (const auto & os : obstacleSets)
|
||||||
|
{
|
||||||
|
for (const auto & temp : os.getObstacles())
|
||||||
|
{
|
||||||
|
if(temp->getBlockMapOffset().valid())
|
||||||
|
{
|
||||||
|
obstaclesBySize[temp->getBlockedOffsets().size()].push_back(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto & o : obstaclesBySize)
|
||||||
|
{
|
||||||
|
possibleObstacles.emplace_back(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::sort(possibleObstacles, [](const ObstaclePair &p1, const ObstaclePair &p2) -> bool
|
||||||
|
{
|
||||||
|
return p1.first > p2.first; //bigger obstacles first
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false; // Proceed with old method
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPrepared;
|
||||||
|
}
|
||||||
|
|
||||||
void ObstacleProxy::addBlockedTile(const int3& tile)
|
void ObstacleProxy::addBlockedTile(const int3& tile)
|
||||||
{
|
{
|
||||||
blockedArea.add(tile);
|
blockedArea.add(tile);
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
virtual ~ObstacleProxy() = default;
|
virtual ~ObstacleProxy() = default;
|
||||||
|
|
||||||
void collectPossibleObstacles(TerrainId terrain);
|
void collectPossibleObstacles(TerrainId terrain);
|
||||||
|
bool prepareBiome(TerrainId terrain, CRandomGenerator & rand);
|
||||||
|
|
||||||
void addBlockedTile(const int3 & tile);
|
void addBlockedTile(const int3 & tile);
|
||||||
|
|
||||||
|
@ -34,7 +34,16 @@ void ObstaclePlacer::process()
|
|||||||
if(!manager)
|
if(!manager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!prepareBiome(zone.getTerrainType(), zone.getRand()))
|
||||||
|
{
|
||||||
|
logGlobal->warn("Failed to prepare biome, using all possible obstacles");
|
||||||
|
// Use all if we fail to create proper biome
|
||||||
collectPossibleObstacles(zone.getTerrainType());
|
collectPossibleObstacles(zone.getTerrainType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->info("Biome prepared successfully for zone %d", zone.getId());
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto area = zone.area();
|
auto area = zone.area();
|
||||||
|
Reference in New Issue
Block a user