From ce62ab3e66c91a1ef1ff4689fa834a459e04d2f1 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Sat, 30 Sep 2023 01:19:18 +0200 Subject: [PATCH] Select random object template instead of first --- lib/rmg/RmgObject.cpp | 21 +++++++++++---------- lib/rmg/RmgObject.h | 11 ++++++----- lib/rmg/modificators/ConnectionsPlacer.cpp | 4 ++-- lib/rmg/modificators/ObjectManager.cpp | 10 +++++----- lib/rmg/modificators/RiverPlacer.cpp | 2 +- lib/rmg/modificators/TownPlacer.cpp | 2 +- lib/rmg/modificators/WaterProxy.cpp | 4 ++-- 7 files changed, 28 insertions(+), 26 deletions(-) diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index 31e287e06..9934602a5 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -111,18 +111,18 @@ void Object::Instance::setPositionRaw(const int3 & position) dObject.pos = dPosition + dParent.getPosition(); } -void Object::Instance::setAnyTemplate() +void Object::Instance::setAnyTemplate(CRandomGenerator & rng) { auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(); if(templates.empty()) throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID)); - dObject.appearance = templates.front(); + dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng); dAccessibleAreaCache.clear(); setPosition(getPosition(false)); } -void Object::Instance::setTemplate(TerrainId terrain) +void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng) { auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain); if (templates.empty()) @@ -130,7 +130,8 @@ void Object::Instance::setTemplate(TerrainId terrain) auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated(); throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName)); } - dObject.appearance = templates.front(); + + dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng); dAccessibleAreaCache.clear(); setPosition(getPosition(false)); } @@ -280,10 +281,10 @@ void Object::setPosition(const int3 & position) i.setPositionRaw(i.getPosition()); } -void Object::setTemplate(const TerrainId & terrain) +void Object::setTemplate(const TerrainId & terrain, CRandomGenerator & rng) { for(auto& i : dInstances) - i.setTemplate(terrain); + i.setTemplate(terrain, rng); } const Area & Object::getArea() const @@ -325,7 +326,7 @@ void rmg::Object::setGuardedIfMonster(const Instance& object) } } -void Object::Instance::finalize(RmgMap & map) +void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng) { if(!map.isOnMap(getPosition(true))) throw rmgException(boost::str(boost::format("Position of object %d at %s is outside the map") % dObject.id % getPosition(true).toString())); @@ -341,7 +342,7 @@ void Object::Instance::finalize(RmgMap & map) } else { - setTemplate(terrainType->getId()); + setTemplate(terrainType->getId(), rng); } } @@ -362,14 +363,14 @@ void Object::Instance::finalize(RmgMap & map) map.getMapProxy()->insertObject(&dObject); } -void Object::finalize(RmgMap & map) +void Object::finalize(RmgMap & map, CRandomGenerator & rng) { if(dInstances.empty()) throw rmgException("Cannot finalize object without instances"); for(auto & dInstance : dInstances) { - dInstance.finalize(map); + dInstance.finalize(map, rng); } } diff --git a/lib/rmg/RmgObject.h b/lib/rmg/RmgObject.h index d444a90b4..2ba78a29a 100644 --- a/lib/rmg/RmgObject.h +++ b/lib/rmg/RmgObject.h @@ -17,6 +17,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CGObjectInstance; +class CRandomGenerator; class RmgMap; namespace rmg { @@ -35,8 +36,8 @@ public: int3 getVisitablePosition() const; bool isVisitableFrom(const int3 & tile) const; const Area & getAccessibleArea() const; - void setTemplate(TerrainId terrain); //cache invalidation - void setAnyTemplate(); //cache invalidation + void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation + void setAnyTemplate(CRandomGenerator &); //cache invalidation int3 getTopTile() const; int3 getPosition(bool isAbsolute = false) const; @@ -45,7 +46,7 @@ public: const CGObjectInstance & object() const; CGObjectInstance & object(); - void finalize(RmgMap & map); //cache invalidation + void finalize(RmgMap & map, CRandomGenerator &); //cache invalidation void clear(); private: @@ -73,7 +74,7 @@ public: const int3 & getPosition() const; void setPosition(const int3 & position); - void setTemplate(const TerrainId & terrain); + void setTemplate(const TerrainId & terrain, CRandomGenerator &); const Area & getArea() const; //lazy cache invalidation const int3 getVisibleTop() const; @@ -81,7 +82,7 @@ public: bool isGuarded() const; void setGuardedIfMonster(const Instance & object); - void finalize(RmgMap & map); + void finalize(RmgMap & map, CRandomGenerator &); void clear(); private: diff --git a/lib/rmg/modificators/ConnectionsPlacer.cpp b/lib/rmg/modificators/ConnectionsPlacer.cpp index 5526d2731..44b1e11d2 100644 --- a/lib/rmg/modificators/ConnectionsPlacer.cpp +++ b/lib/rmg/modificators/ConnectionsPlacer.cpp @@ -316,8 +316,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c auto * gate2 = factory->create(); rmg::Object rmgGate1(*gate1); rmg::Object rmgGate2(*gate2); - rmgGate1.setTemplate(zone.getTerrainType()); - rmgGate2.setTemplate(otherZone->getTerrainType()); + rmgGate1.setTemplate(zone.getTerrainType(), zone.getRand()); + rmgGate2.setTemplate(otherZone->getTerrainType(), zone.getRand()); bool guarded1 = manager.addGuard(rmgGate1, connection.getGuardStrength(), true); bool guarded2 = managerOther.addGuard(rmgGate2, connection.getGuardStrength(), true); int minDist = 3; diff --git a/lib/rmg/modificators/ObjectManager.cpp b/lib/rmg/modificators/ObjectManager.cpp index 02267aaa8..9d34b3833 100644 --- a/lib/rmg/modificators/ObjectManager.cpp +++ b/lib/rmg/modificators/ObjectManager.cpp @@ -354,7 +354,7 @@ bool ObjectManager::createRequiredObjects() for(const auto & objInfo : requiredObjects) { rmg::Object rmgObject(*objInfo.obj); - rmgObject.setTemplate(zone.getTerrainType()); + rmgObject.setTemplate(zone.getTerrainType(), zone.getRand()); bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY)); Zone::Lock lock(zone.areaMutex); @@ -394,7 +394,7 @@ bool ObjectManager::createRequiredObjects() auto possibleArea = zone.areaPossible(); rmg::Object rmgObject(*objInfo.obj); - rmgObject.setTemplate(zone.getTerrainType()); + rmgObject.setTemplate(zone.getTerrainType(), zone.getRand()); bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY)); auto path = placeAndConnectObject(zone.areaPossible(), rmgObject, [this, &rmgObject](const int3 & tile) @@ -480,7 +480,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD if (!monster->object().appearance) { //Needed to determine visitable offset - monster->setAnyTemplate(); + monster->setAnyTemplate(zone.getRand()); } object.getPosition(); auto visitableOffset = monster->object().getVisitableOffset(); @@ -492,7 +492,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD int3 parentOffset = monster->getPosition(true) - monster->getPosition(false); monster->setPosition(fixedPos - parentOffset); } - object.finalize(map); + object.finalize(map, zone.getRand()); Zone::Lock lock(zone.areaMutex); zone.areaPossible().subtract(object.getArea()); @@ -689,7 +689,7 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard }); auto & instance = object.addInstance(*guard); - instance.setAnyTemplate(); //terrain is irrelevant for monsters, but monsters need some template now + instance.setAnyTemplate(zone.getRand()); //terrain is irrelevant for monsters, but monsters need some template now //Fix HoTA monsters with offset template auto visitableOffset = instance.object().getVisitableOffset(); diff --git a/lib/rmg/modificators/RiverPlacer.cpp b/lib/rmg/modificators/RiverPlacer.cpp index 0738bdc72..d9c7af3e1 100644 --- a/lib/rmg/modificators/RiverPlacer.cpp +++ b/lib/rmg/modificators/RiverPlacer.cpp @@ -397,7 +397,7 @@ void RiverPlacer::connectRiver(const int3 & tile) { auto * obj = handler->create(templ); rmg::Object deltaObj(*obj, deltaPositions[pos]); - deltaObj.finalize(map); + deltaObj.finalize(map, zone.getRand()); } } } diff --git a/lib/rmg/modificators/TownPlacer.cpp b/lib/rmg/modificators/TownPlacer.cpp index 1f046588e..76bf3bbec 100644 --- a/lib/rmg/modificators/TownPlacer.cpp +++ b/lib/rmg/modificators/TownPlacer.cpp @@ -140,7 +140,7 @@ int3 TownPlacer::placeMainTown(ObjectManager & manager, CGTownInstance & town) { //towns are big objects and should be centered around visitable position rmg::Object rmgObject(town); - rmgObject.setTemplate(zone.getTerrainType()); + rmgObject.setTemplate(zone.getTerrainType(), zone.getRand()); int3 position(-1, -1, -1); { diff --git a/lib/rmg/modificators/WaterProxy.cpp b/lib/rmg/modificators/WaterProxy.cpp index 023a13af1..839511d7c 100644 --- a/lib/rmg/modificators/WaterProxy.cpp +++ b/lib/rmg/modificators/WaterProxy.cpp @@ -254,7 +254,7 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout auto * boat = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create()); rmg::Object rmgObject(*boat); - rmgObject.setTemplate(zone.getTerrainType()); + rmgObject.setTemplate(zone.getTerrainType(), zone.getRand()); auto waterAvailable = zone.areaPossible() + zone.freePaths(); rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles @@ -319,7 +319,7 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, bool shipyard->tempOwner = PlayerColor::NEUTRAL; rmg::Object rmgObject(*shipyard); - rmgObject.setTemplate(land.getTerrainType()); + rmgObject.setTemplate(land.getTerrainType(), zone.getRand()); bool guarded = manager->addGuard(rmgObject, guard); auto waterAvailable = zone.areaPossible() + zone.freePaths();