1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-15 13:33:36 +02:00

Wood & ore mines will be placed close to zone center.

This commit is contained in:
DjWarmonger 2014-12-20 22:13:10 +01:00
parent 485b2ac688
commit fee2184996
2 changed files with 76 additions and 19 deletions

View File

@ -605,6 +605,10 @@ void CRmgTemplateZone::addRequiredObject(CGObjectInstance * obj, si32 strength)
{
requiredObjects.push_back(std::make_pair(obj, strength));
}
void CRmgTemplateZone::addCloseObject(CGObjectInstance * obj, si32 strength)
{
closeObjects.push_back(std::make_pair(obj, strength));
}
bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength, bool clearSurroundingTiles, bool zoneGuard)
{
@ -1109,11 +1113,8 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
static const Res::ERes woodOre[] = {Res::ERes::WOOD, Res::ERes::ORE};
static const Res::ERes preciousResources[] = {Res::ERes::GEMS, Res::ERes::CRYSTAL, Res::ERes::MERCURY, Res::ERes::SULFUR};
//TODO: factory / copy constructor?
for (const auto & res : woodOre)
{
//TODO: these 2 should be close to town (within 12 tiles radius)
for (int i = 0; i < mines[res]; i++)
{
auto mine = new CGMine();
@ -1121,7 +1122,7 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
mine->subID = static_cast<si32>(res);
mine->producedResource = res;
mine->producedQuantity = mine->defaultResProduction();
addRequiredObject(mine, 1500);
addCloseObject(mine, 1500);
}
}
for (const auto & res : preciousResources)
@ -1166,6 +1167,49 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
guardObject (gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true);
//paths to required objects constitute main paths of zone. otherwise they just may lead to middle and create dead zones
}
for (const auto &obj : closeObjects)
{
std::vector<int3> tiles(possibleTiles.begin(), possibleTiles.end()); //new tiles vector after each object has been placed
// smallest distance to zone center, greatest distance to nearest object
auto isCloser = [this, gen](const int3 & lhs, const int3 & rhs) -> bool
{
return (this->pos.dist2dSQ(lhs) * 0.5f - gen->getNearestObjectDistance(lhs)) < (this->pos.dist2dSQ(rhs) * 0.5f - gen->getNearestObjectDistance(rhs));
};
boost::sort (tiles, isCloser);
setTemplateForObject(gen, obj.first);
auto tilesBlockedByObject = obj.first->getBlockedOffsets();
bool result = false;
for (auto tile : tiles)
{
//object must be accessible from at least one surounding tile
if (!isAccessibleFromAnywhere(gen, obj.first->appearance, tile, tilesBlockedByObject))
continue;
//avoid borders
if (gen->isPossible(tile))
{
if (areAllTilesAvailable(gen, obj.first, tile, tilesBlockedByObject))
{
placeObject(gen, obj.first, tile);
guardObject(gen, obj.first, obj.second, (obj.first->ID == Obj::MONOLITH_TWO_WAY), true);
result = true;
break;
}
}
}
if (!result)
{
logGlobal->errorStream() << boost::format("Failed to fill zone %d due to lack of space") % id;
//TODO CLEANUP!
return false;
}
}
return true;
}
@ -1441,17 +1485,36 @@ bool CRmgTemplateZone::isAccessibleFromAnywhere (CMapGenerator* gen, ObjectTempl
return accessible;
}
bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos)
void CRmgTemplateZone::setTemplateForObject(CMapGenerator* gen, CGObjectInstance* obj)
{
//we need object apperance to deduce free tiles
if (obj->appearance.id == Obj::NO_OBJ)
{
auto templates = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID)->getTemplates(gen->map->getTile(getPos()).terType);
if (templates.empty())
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") %obj->ID %obj->subID %pos));
throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % obj->ID %obj->subID %pos));
obj->appearance = templates.front();
}
}
bool CRmgTemplateZone::areAllTilesAvailable(CMapGenerator* gen, CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const
{
for (auto blockingTile : tilesBlockedByObject)
{
int3 t = tile + blockingTile;
if (!gen->map->isInTheMap(t) || !gen->isPossible(t))
{
//if at least one tile is not possible, object can't be placed here
return false;
}
}
return true;
}
bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos)
{
//we need object apperance to deduce free tile
setTemplateForObject(gen, obj);
//si32 min_dist = sqrt(tileinfo.size()/density);
int best_distance = 0;
@ -1474,17 +1537,7 @@ bool CRmgTemplateZone::findPlaceForObject(CMapGenerator* gen, CGObjectInstance*
//avoid borders
if (gen->isPossible(tile) && (dist >= min_dist) && (dist > best_distance))
{
bool allTilesAvailable = true;
for (auto blockingTile : tilesBlockedByObject)
{
int3 t = tile + blockingTile;
if (!gen->map->isInTheMap(t) || !gen->isPossible(t))
{
allTilesAvailable = false; //if at least one tile is not possible, object can't be placed here
break;
}
}
if (allTilesAvailable)
if (areAllTilesAvailable(gen, obj, tile, tilesBlockedByObject))
{
best_distance = dist;
pos = tile;

View File

@ -150,6 +150,7 @@ public:
void discardDistantTiles (CMapGenerator* gen, float distance);
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0);
bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
bool createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo);
bool fill (CMapGenerator* gen);
@ -198,6 +199,7 @@ private:
//content info
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects;
std::vector<CGObjectInstance*> objects;
//placement info
@ -214,6 +216,8 @@ private:
bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos);
bool findPlaceForTreasurePile(CMapGenerator* gen, float min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void setTemplateForObject(CMapGenerator* gen, CGObjectInstance* obj);
bool areAllTilesAvailable(CMapGenerator* gen, CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false, bool addToFreePaths = false);