1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Create random obstacles that match terrain.

This commit is contained in:
DjWarmonger 2014-06-28 09:46:32 +02:00
parent 7aa8213cd5
commit 920f56969b
6 changed files with 89 additions and 19 deletions

View File

@ -15,7 +15,7 @@ SPELLS:
* New configuration format: http://wiki.vcmi.eu/index.php?title=Spell_Format
RANDOM MAP GENERATOR
* Towns form mods cna be used
* Towns from mods can be used
* Reading connections, terrains, towns and mines from template
* Zone placement
* Zone borders and connections, fractalized paths inside zones

View File

@ -178,16 +178,7 @@ std::set<int3> CGObjectInstance::getBlockedPos() const
std::set<int3> CGObjectInstance::getBlockedOffsets() const
{
std::set<int3> ret;
for(int w=0; w<getWidth(); ++w)
{
for(int h=0; h<getHeight(); ++h)
{
if (appearance.isBlockedAt(w, h))
ret.insert(int3(-w, -h, 0));
}
}
return ret;
return appearance.getBlockedOffsets();
}
void CGObjectInstance::setType(si32 ID, si32 subID)

View File

@ -308,6 +308,33 @@ bool ObjectTemplate::isBlockedAt(si32 X, si32 Y) const
return false;
}
std::set<int3> ObjectTemplate::getBlockedOffsets() const
{
std::set<int3> ret;
for(int w = 0; w < getWidth(); ++w)
{
for(int h = 0; h < getHeight(); ++h)
{
if (isBlockedAt(w, h))
ret.insert(int3(-w, -h, 0));
}
}
return ret;
}
int3 ObjectTemplate::getBlockMapOffset() const
{
for(int w = 0; w < getWidth(); ++w)
{
for(int h = 0; h < getHeight(); ++h)
{
if (isBlockedAt(w, h))
return int3(-w, -h, 0);
}
}
return int3(-1,-1,-1);
}
bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const
{
// visitDir uses format

View File

@ -15,6 +15,7 @@
class CBinaryReader;
class CLegacyConfigParser;
class JsonNode;
class int3;
class DLL_LINKAGE ObjectTemplate
{
@ -56,6 +57,8 @@ public:
bool isVisitableAt(si32 X, si32 Y) const;
bool isVisibleAt(si32 X, si32 Y) const;
bool isBlockedAt(si32 X, si32 Y) const;
std::set<int3> getBlockedOffsets() const;
int3 getBlockMapOffset() const; //bottom-right corner when firts blocked tile is
// Checks if object is visitable from certain direction. X and Y must be between -1..+1
bool isVisitableFrom(si8 X, si8 Y) const;

View File

@ -962,20 +962,49 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
{
//get all possible obstacles for this terrain
for (auto primaryID : VLC->objtypeh->knownObjects())
{
for (auto secondaryID : VLC->objtypeh->knownSubObjects(primaryID))
{
auto handler = VLC->objtypeh->getHandlerFor(primaryID, secondaryID);
if (handler->isStaticObject())
{
for (auto temp : handler->getTemplates())
{
if (temp.canBePlacedAt(terrainType) && temp.getBlockMapOffset().valid())
possibleObstacles.push_back(temp);
}
}
}
}
auto sel = gen->editManager->getTerrainSelection();
sel.clearSelection();
auto tryToPlaceObstacleHere = [this, gen](int3& tile)-> bool
{
auto temp = *RandomGeneratorUtil::nextItem(possibleObstacles, gen->rand);
int3 obstaclePos = tile + temp.getBlockMapOffset();
if (canObstacleBePlacedHere(gen, temp, obstaclePos)) //can be placed here
{
auto obj = VLC->objtypeh->getHandlerFor(temp.id, temp.subid)->create(temp);
placeObject(gen, obj, obstaclePos);
return true;
}
return false;
};
for (auto tile : tileinfo)
{
//test code - block all the map to show paths clearly
//if (gen->isPossible(tile))
// gen->setOccupied(tile, ETileType::BLOCKED);
if (gen->shouldBeBlocked(tile)) //fill tiles that should be blocked with obstacles
{
auto obj = new CGObjectInstance();
obj->ID = static_cast<Obj>(57);
obj->subID = 0;
placeObject(gen, obj, tile);
while (!tryToPlaceObstacleHere(tile));
}
else if (gen->isPossible(tile))
{
//try to place random obstacle once - if not possible, leave it clear
tryToPlaceObstacleHere(tile);
}
}
}
@ -1031,6 +1060,23 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dis
return result;
}
bool CRmgTemplateZone::canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos)
{
auto tilesBlockedByObject = temp.getBlockedOffsets();
bool allTilesAvailable = true;
for (auto blockingTile : tilesBlockedByObject)
{
int3 t = pos + blockingTile;
if (!gen->map->isInTheMap(t) || !(gen->isPossible(t) || gen->shouldBeBlocked(t)))
{
allTilesAvailable = false; //if at least one tile is not possible, object can't be placed here
break;
}
}
return allTilesAvailable;
}
bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos)
{
//we need object apperance to deduce free tiles

View File

@ -21,6 +21,7 @@ class CMapGenerator;
class CTileInfo;
class int3;
class CGObjectInstance;
class ObjectTemplate;
namespace ETemplateZoneType
{
@ -173,6 +174,7 @@ private:
ui16 totalDensity;
std::vector<CTreasureInfo> treasureInfo;
std::vector<ObjectInfo> possibleObjects;
std::vector<ObjectTemplate> possibleObstacles;
//content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
@ -189,6 +191,7 @@ private:
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos);
bool findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str);