diff --git a/lib/rmg/CRmgTemplateStorage.cpp b/lib/rmg/CRmgTemplateStorage.cpp index dd72b8341..95f457998 100644 --- a/lib/rmg/CRmgTemplateStorage.cpp +++ b/lib/rmg/CRmgTemplateStorage.cpp @@ -133,7 +133,6 @@ void CJsonRmgTemplateLoader::loadTemplates() //treasures if (!zoneNode["treasure"].isNull()) { - int totalDensity = 0; //TODO: parse vector of different treasure settings if (zoneNode["treasure"].getType() == JsonNode::DATA_STRUCT) { @@ -143,8 +142,6 @@ void CJsonRmgTemplateLoader::loadTemplates() ti.min = treasureInfo["min"].Float(); ti.max = treasureInfo["max"].Float(); ti.density = treasureInfo["density"].Float(); //TODO: use me - totalDensity += ti.density; - ti.threshold = totalDensity; zone->addTreasureInfo(ti); } } @@ -156,12 +153,9 @@ void CJsonRmgTemplateLoader::loadTemplates() ti.min = treasureInfo["min"].Float(); ti.max = treasureInfo["max"].Float(); ti.density = treasureInfo["density"].Float(); - totalDensity += ti.density; - ti.threshold = totalDensity; zone->addTreasureInfo(ti); } } - zone->setTotalDensity (totalDensity); } zones[zone->getId()] = zone; @@ -191,7 +185,6 @@ void CJsonRmgTemplateLoader::loadTemplates() { zone->addTreasureInfo(treasureInfo); } - zone->setTotalDensity (zones[zoneNode["treasureLikeZone"].Float()]->getTotalDensity()); } if (!zoneNode["minesLikeZone"].isNull()) diff --git a/lib/rmg/CRmgTemplateZone.cpp b/lib/rmg/CRmgTemplateZone.cpp index 44c663fb6..07709135f 100644 --- a/lib/rmg/CRmgTemplateZone.cpp +++ b/lib/rmg/CRmgTemplateZone.cpp @@ -138,8 +138,7 @@ CRmgTemplateZone::CRmgTemplateZone() : matchTerrainToTown(true), townType(ETownType::NEUTRAL), terrainType (ETerrainType::GRASS), - zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL), - totalDensity(0) + zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL) { terrainTypes = getDefaultTerrainTypes(); } @@ -303,16 +302,6 @@ void CRmgTemplateZone::setMonsterStrength (EMonsterStrength::EMonsterStrength va zoneMonsterStrength = val; } -void CRmgTemplateZone::setTotalDensity (ui16 val) -{ - totalDensity = val; -} - -ui16 CRmgTemplateZone::getTotalDensity () const -{ - return totalDensity; -} - void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info) { treasureInfo.push_back(info); @@ -420,7 +409,11 @@ void CRmgTemplateZone::fractalize(CMapGenerator* gen) std::set tilesToIgnore; //will be erased in this iteration //the more treasure density, the greater distance between paths. Scaling is experimental. + int totalDensity = 0; + for (auto ti : treasureInfo) + totalDensity =+ ti.density; const float minDistance = std::sqrt(totalDensity * 3); + for (auto tile : tileinfo) { if (gen->isFree(tile)) @@ -686,7 +679,7 @@ bool CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength, return true; } -bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float minDistance) +bool CRmgTemplateZone::createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo) { CTreasurePileInfo info; @@ -695,25 +688,9 @@ bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos, float int3 guardPos (-1,-1,-1); info.nextTreasurePos = pos; - //default values - int maxValue = 5000; - int minValue = 1500; + int maxValue = treasureInfo.max; + int minValue = treasureInfo.min; - if (treasureInfo.size()) - { - //roulette wheel - int r = gen->rand.nextInt (1, totalDensity); - - for (auto t : treasureInfo) - { - if (r <= t.threshold) - { - maxValue = t.max; - minValue = t.min; - break; - } - } - } ui32 desiredValue = gen->rand.nextInt(minValue, maxValue); //quantize value to let objects with value equal to max spawn too @@ -1194,30 +1171,43 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen) void CRmgTemplateZone::createTreasures(CMapGenerator* gen) { - //treasure density is proportional to map siz,e but must be scaled bakc to map size - //also, normalize it to zone count - higher count means relative smaller zones + auto valueComparator = [](const CTreasureInfo & lhs, const CTreasureInfo & rhs) -> bool + { + return lhs.max > rhs.max; + }; - //this is squared distance for optimization purposes - const double minDistance = std::max((600.f * size * size * gen->getZones().size()) / - (gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2); - //distance lower than 2 causes objects to overlap and crash + //place biggest treasures first at large distance, place smaller ones inbetween + boost::sort(treasureInfo, valueComparator); - do { - - //optimization - don't check tiles which are not allowed - vstd::erase_if (possibleTiles, [gen](const int3 &tile) -> bool - { - return !gen->isPossible(tile); - }); + int totalDensity = 0; + for (auto t : treasureInfo) + { + totalDensity += t.density; - int3 pos; - if ( ! findPlaceForTreasurePile(gen, minDistance, pos)) - { - break; - } - createTreasurePile (gen, pos, minDistance); + //treasure density is inversely proportional to zone size but must be scaled back to map size + //also, normalize it to zone count - higher count means relatively smaller zones - } while(true); + //this is squared distance for optimization purposes + const double minDistance = std::max((600.f * size * size * gen->getZones().size()) / + (gen->mapGenOptions->getWidth() * gen->mapGenOptions->getHeight() * totalDensity * (gen->map->twoLevel ? 2 : 1)), 2); + //distance lower than 2 causes objects to overlap and crash + + do { + //optimization - don't check tiles which are not allowed + vstd::erase_if(possibleTiles, [gen](const int3 &tile) -> bool + { + return !gen->isPossible(tile); + }); + + int3 pos; + if (!findPlaceForTreasurePile(gen, minDistance, pos)) + { + break; + } + createTreasurePile(gen, pos, minDistance, t); + + } while (true); + } } void CRmgTemplateZone::createObstacles(CMapGenerator* gen) diff --git a/lib/rmg/CRmgTemplateZone.h b/lib/rmg/CRmgTemplateZone.h index 2ce38b095..28021160e 100644 --- a/lib/rmg/CRmgTemplateZone.h +++ b/lib/rmg/CRmgTemplateZone.h @@ -63,7 +63,6 @@ public: ui32 min; ui32 max; ui16 density; - ui16 threshold; //how much must RNG roll to pick that zone }; struct DLL_LINKAGE ObjectInfo @@ -152,7 +151,7 @@ public: void addRequiredObject(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); + bool createTreasurePile(CMapGenerator* gen, int3 &pos, float minDistance, const CTreasureInfo& treasureInfo); bool fill (CMapGenerator* gen); bool placeMines (CMapGenerator* gen); void initTownType (CMapGenerator* gen); @@ -166,8 +165,6 @@ public: bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone, std::set* clearedTiles = nullptr); std::vector getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object); - void setTotalDensity (ui16 val); - ui16 getTotalDensity () const; void addConnection(TRmgTemplateZoneId otherZone); std::vector getConnections() const; void addTreasureInfo(CTreasureInfo & info); @@ -196,7 +193,6 @@ private: ETerrainType terrainType; EMonsterStrength::EMonsterStrength zoneMonsterStrength; - ui16 totalDensity; std::vector treasureInfo; std::vector possibleObjects;