1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-05 00:49:09 +02:00

Map objects now use shared_ptr (rmg)

This commit is contained in:
Ivan Savenko
2025-03-13 20:13:27 +00:00
parent dda5c9f13a
commit 84cf7b052d
19 changed files with 145 additions and 145 deletions

View File

@ -370,7 +370,7 @@ void ObstacleProxy::placeObject(rmg::Object & object, std::set<std::shared_ptr<C
{
for (auto * instance : object.instances())
{
instances.insert(instance->object());
instances.insert(instance->pointer());
}
}

View File

@ -19,13 +19,13 @@ MapProxy::MapProxy(RmgMap & map):
{
}
void MapProxy::insertObject(CGObjectInstance * obj)
void MapProxy::insertObject(std::shared_ptr<CGObjectInstance> obj)
{
Lock lock(mx);
map.getEditManager()->insertObject(obj);
}
void MapProxy::insertObjects(std::set<CGObjectInstance*>& objects)
void MapProxy::insertObjects(std::set<std::shared_ptr<CGObjectInstance>>& objects)
{
Lock lock(mx);
map.getEditManager()->insertObjects(objects);

View File

@ -24,8 +24,8 @@ class MapProxy
public:
MapProxy(RmgMap & map);
void insertObject(CGObjectInstance * obj);
void insertObjects(std::set<CGObjectInstance*>& objects);
void insertObject(std::shared_ptr<CGObjectInstance> obj);
void insertObjects(std::set<std::shared_ptr<CGObjectInstance>>& objects);
void removeObject(CGObjectInstance* obj);
void drawTerrain(vstd::RNG & generator, std::vector<int3> & tiles, TerrainId terrain);

View File

@ -21,7 +21,7 @@ VCMI_LIB_NAMESPACE_BEGIN
ObjectInfo::ObjectInfo(si32 ID, si32 subID):
primaryID(ID),
secondaryID(subID),
destroyObject([](CGObjectInstance * obj){}),
destroyObject([](CGObjectInstance & obj){}),
maxPerZone(std::numeric_limits<ui32>::max())
{
}

View File

@ -32,8 +32,8 @@ struct DLL_LINKAGE ObjectInfo
ui16 probability = 0;
ui32 maxPerZone = 1;
//ui32 maxPerMap; //unused
std::function<CGObjectInstance *()> generateObject;
std::function<void(CGObjectInstance *)> destroyObject;
std::function<std::shared_ptr<CGObjectInstance>()> generateObject;
std::function<void(CGObjectInstance &)> destroyObject;
void setAllTemplates(MapObjectID type, MapObjectSubID subtype);
void setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainId terrain);

View File

@ -27,12 +27,12 @@ VCMI_LIB_NAMESPACE_BEGIN
using namespace rmg;
Object::Instance::Instance(const Object& parent, CGObjectInstance & object): dParent(parent), dObject(object)
Object::Instance::Instance(const Object& parent, std::shared_ptr<CGObjectInstance> object): dParent(parent), dObject(object)
{
setPosition(dPosition);
}
Object::Instance::Instance(const Object& parent, CGObjectInstance & object, const int3 & position): Instance(parent, object)
Object::Instance::Instance(const Object& parent, std::shared_ptr<CGObjectInstance> object, const int3 & position): Instance(parent, object)
{
setPosition(position);
}
@ -41,10 +41,10 @@ const Area & Object::Instance::getBlockedArea() const
{
if(dBlockedAreaCache.empty())
{
std::set<int3> blockedArea = dObject.getBlockedPos();
std::set<int3> blockedArea = dObject->getBlockedPos();
dBlockedAreaCache.assign(rmg::Tileset(blockedArea.begin(), blockedArea.end()));
if(dObject.isVisitable() || dBlockedAreaCache.empty())
dBlockedAreaCache.add(dObject.visitablePos());
if(dObject->isVisitable() || dBlockedAreaCache.empty())
dBlockedAreaCache.add(dObject->visitablePos());
}
return dBlockedAreaCache;
}
@ -64,7 +64,7 @@ int3 Object::Instance::getPosition(bool isAbsolute) const
int3 Object::Instance::getVisitablePosition() const
{
return dObject.visitablePos();
return dObject->visitablePos();
}
const rmg::Area & Object::Instance::getAccessibleArea() const
@ -87,7 +87,7 @@ const rmg::Area & Object::Instance::getAccessibleArea() const
void Object::Instance::setPosition(const int3 & position)
{
dPosition = position;
dObject.setAnchorPos(dPosition + dParent.getPosition());
dObject->setAnchorPos(dPosition + dParent.getPosition());
dBlockedAreaCache.clear();
dAccessibleAreaCache.clear();
@ -96,45 +96,45 @@ void Object::Instance::setPosition(const int3 & position)
void Object::Instance::setPositionRaw(const int3 & position)
{
if(!dObject.anchorPos().isValid())
if(!dObject->anchorPos().isValid())
{
dObject.setAnchorPos(dPosition + dParent.getPosition());
dObject->setAnchorPos(dPosition + dParent.getPosition());
dBlockedAreaCache.clear();
dAccessibleAreaCache.clear();
dParent.clearCachedArea();
}
auto shift = position + dParent.getPosition() - dObject.anchorPos();
auto shift = position + dParent.getPosition() - dObject->anchorPos();
dAccessibleAreaCache.translate(shift);
dBlockedAreaCache.translate(shift);
dPosition = position;
dObject.setAnchorPos(dPosition + dParent.getPosition());
dObject->setAnchorPos(dPosition + dParent.getPosition());
}
void Object::Instance::setAnyTemplate(vstd::RNG & rng)
{
auto templates = dObject.getObjectHandler()->getTemplates();
auto templates = dObject->getObjectHandler()->getTemplates();
if(templates.empty())
throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.getObjTypeIndex()));
throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject->ID % dObject->getObjTypeIndex()));
dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
dObject->appearance = *RandomGeneratorUtil::nextItem(templates, rng);
dAccessibleAreaCache.clear();
setPosition(getPosition(false));
}
void Object::Instance::setTemplate(TerrainId terrain, vstd::RNG & rng)
{
auto templates = dObject.getObjectHandler()->getMostSpecificTemplates(terrain);
auto templates = dObject->getObjectHandler()->getMostSpecificTemplates(terrain);
if (templates.empty())
{
auto terrainName = LIBRARY->terrainTypeHandler->getById(terrain)->getNameTranslated();
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.getObjTypeIndex() % terrainName));
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject->ID % dObject->getObjTypeIndex() % terrainName));
}
dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng);
dObject->appearance = *RandomGeneratorUtil::nextItem(templates, rng);
dAccessibleAreaCache.clear();
setPosition(getPosition(false));
}
@ -142,9 +142,8 @@ void Object::Instance::setTemplate(TerrainId terrain, vstd::RNG & rng)
void Object::Instance::clear()
{
if (onCleared)
onCleared(&dObject);
onCleared(*dObject);
delete &dObject;
dBlockedAreaCache.clear();
dAccessibleAreaCache.clear();
dParent.clearCachedArea();
@ -153,37 +152,42 @@ void Object::Instance::clear()
bool Object::Instance::isVisitableFrom(const int3 & position) const
{
auto relPosition = position - getPosition(true);
return dObject.appearance->isVisitableFrom(relPosition.x, relPosition.y);
return dObject->appearance->isVisitableFrom(relPosition.x, relPosition.y);
}
bool Object::Instance::isBlockedVisitable() const
{
return dObject.isBlockedVisitable();
return dObject->isBlockedVisitable();
}
bool Object::Instance::isRemovable() const
{
return dObject.isRemovable();
return dObject->isRemovable();
}
CGObjectInstance & Object::Instance::object()
{
return *dObject;
}
std::shared_ptr<CGObjectInstance> Object::Instance::pointer() const
{
return dObject;
}
const CGObjectInstance & Object::Instance::object() const
{
return dObject;
return *dObject;
}
Object::Object(CGObjectInstance & object, const int3 & position):
Object::Object(std::shared_ptr<CGObjectInstance> object, const int3 & position):
guarded(false),
value(0)
{
addInstance(object, position);
}
Object::Object(CGObjectInstance & object):
Object::Object(std::shared_ptr<CGObjectInstance> object):
guarded(false),
value(0)
{
@ -195,7 +199,7 @@ Object::Object(const Object & object):
value(object.value)
{
for(const auto & i : object.dInstances)
addInstance(const_cast<CGObjectInstance &>(i.object()), i.getPosition());
addInstance(i.pointer(), i.getPosition());
setPosition(object.getPosition());
}
@ -231,7 +235,7 @@ void Object::addInstance(Instance & object)
visibleTopOffset.reset();
}
Object::Instance & Object::addInstance(CGObjectInstance & object)
Object::Instance & Object::addInstance(std::shared_ptr<CGObjectInstance> object)
{
dInstances.emplace_back(*this, object);
setGuardedIfMonster(dInstances.back());
@ -243,7 +247,7 @@ Object::Instance & Object::addInstance(CGObjectInstance & object)
return dInstances.back();
}
Object::Instance & Object::addInstance(CGObjectInstance & object, const int3 & position)
Object::Instance & Object::addInstance(std::shared_ptr<CGObjectInstance> object, const int3 & position)
{
dInstances.emplace_back(*this, object, position);
setGuardedIfMonster(dInstances.back());
@ -498,16 +502,16 @@ rmg::Area Object::Instance::getBorderAbove() const
void Object::Instance::finalize(RmgMap & map, vstd::RNG & 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()));
throw rmgException(boost::str(boost::format("Position of object %d at %s is outside the map") % dObject->id % getPosition(true).toString()));
//If no specific template was defined for this object, select any matching
if (!dObject.appearance)
if (!dObject->appearance)
{
const auto * terrainType = map.getTile(getPosition(true)).getTerrain();
auto templates = dObject.getObjectHandler()->getTemplates(terrainType->getId());
auto templates = dObject->getObjectHandler()->getTemplates(terrainType->getId());
if (templates.empty())
{
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.getObjTypeIndex() % getPosition(true).toString() % terrainType));
throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject->ID % dObject->getObjTypeIndex() % getPosition(true).toString() % terrainType));
}
else
{
@ -515,13 +519,13 @@ void Object::Instance::finalize(RmgMap & map, vstd::RNG & rng)
}
}
if (dObject.isVisitable() && !map.isOnMap(dObject.visitablePos()))
throw rmgException(boost::str(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject.visitablePos().toString() % dObject.id % dObject.anchorPos().toString()));
if (dObject->isVisitable() && !map.isOnMap(dObject->visitablePos()))
throw rmgException(boost::str(boost::format("Visitable tile %s of object %d at %s is outside the map") % dObject->visitablePos().toString() % dObject->id % dObject->anchorPos().toString()));
for(const auto & tile : dObject.getBlockedPos())
for(const auto & tile : dObject->getBlockedPos())
{
if(!map.isOnMap(tile))
throw rmgException(boost::str(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject.id % dObject.anchorPos().toString()));
throw rmgException(boost::str(boost::format("Tile %s of object %d at %s is outside the map") % tile.toString() % dObject->id % dObject->anchorPos().toString()));
}
for(const auto & tile : getBlockedArea().getTilesVector())
@ -529,7 +533,7 @@ void Object::Instance::finalize(RmgMap & map, vstd::RNG & rng)
map.setOccupied(tile, ETileType::USED);
}
map.getMapProxy()->insertObject(&dObject);
map.getMapProxy()->insertObject(dObject);
}
void Object::finalize(RmgMap & map, vstd::RNG & rng)

View File

@ -32,8 +32,8 @@ public:
class Instance
{
public:
Instance(const Object& parent, CGObjectInstance & object);
Instance(const Object& parent, CGObjectInstance & object, const int3 & position);
Instance(const Object& parent, std::shared_ptr<CGObjectInstance> object);
Instance(const Object& parent, std::shared_ptr<CGObjectInstance> object, const int3 & position);
const Area & getBlockedArea() const;
@ -52,27 +52,28 @@ public:
void setPositionRaw(const int3 & position); //no cache invalidation
const CGObjectInstance & object() const;
CGObjectInstance & object();
std::shared_ptr<CGObjectInstance> pointer() const;
void finalize(RmgMap & map, vstd::RNG &); //cache invalidation
void clear();
std::function<void(CGObjectInstance *)> onCleared;
std::function<void(CGObjectInstance &)> onCleared;
private:
mutable Area dBlockedAreaCache;
int3 dPosition;
mutable Area dAccessibleAreaCache;
CGObjectInstance & dObject;
std::shared_ptr<CGObjectInstance> dObject;
const Object & dParent;
};
Object() = default;
Object(const Object & object);
Object(CGObjectInstance & object);
Object(CGObjectInstance & object, const int3 & position);
Object(std::shared_ptr<CGObjectInstance> object);
Object(std::shared_ptr<CGObjectInstance> object, const int3 & position);
void addInstance(Instance & object);
Instance & addInstance(CGObjectInstance & object);
Instance & addInstance(CGObjectInstance & object, const int3 & position);
Instance & addInstance(std::shared_ptr<CGObjectInstance> object);
Instance & addInstance(std::shared_ptr<CGObjectInstance> object, const int3 & position);
std::list<Instance*> & instances();
std::list<const Instance*> & instances() const;

View File

@ -277,7 +277,7 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
{
assert(zone.getModificator<ObjectManager>());
auto & manager = *zone.getModificator<ObjectManager>();
auto * monsterType = manager.chooseGuard(connection.getGuardStrength(), true);
auto monsterType = manager.chooseGuard(connection.getGuardStrength(), true);
rmg::Area border(zone.area()->getBorder());
border.unite(otherZone->area()->getBorder());
@ -302,7 +302,7 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
if(monsterType)
{
rmg::Object monster(*monsterType);
rmg::Object monster(monsterType);
monster.setPosition(guardPos);
manager.placeObject(monster, false, true);
//Place objects away from the monster in the other zone, too
@ -379,10 +379,10 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
auto & managerOther = *otherZone->getModificator<ObjectManager>();
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::SUBTERRANEAN_GATE, 0);
auto * gate1 = factory->create(map.mapInstance->cb, nullptr);
auto * gate2 = factory->create(map.mapInstance->cb, nullptr);
rmg::Object rmgGate1(*gate1);
rmg::Object rmgGate2(*gate2);
auto gate1 = factory->create(map.mapInstance->cb, nullptr);
auto gate2 = factory->create(map.mapInstance->cb, nullptr);
rmg::Object rmgGate1(gate1);
rmg::Object rmgGate2(gate2);
rmgGate1.setTemplate(zone.getTerrainType(), zone.getRand());
rmgGate2.setTemplate(otherZone->getTerrainType(), zone.getRand());
bool guarded1 = manager.addGuard(rmgGate1, connection.getGuardStrength(), true);
@ -447,8 +447,8 @@ void ConnectionsPlacer::placeMonolithConnection(const rmg::ZoneConnection & conn
bool allowRoad = shouldGenerateRoad(connection);
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, generator.getNextMonlithIndex());
auto * teleport1 = factory->create(map.mapInstance->cb, nullptr);
auto * teleport2 = factory->create(map.mapInstance->cb, nullptr);
auto teleport1 = factory->create(map.mapInstance->cb, nullptr);
auto teleport2 = factory->create(map.mapInstance->cb, nullptr);
RequiredObjectInfo obj1(teleport1, connection.getGuardStrength(), allowRoad);
RequiredObjectInfo obj2(teleport2, connection.getGuardStrength(), allowRoad);

View File

@ -49,9 +49,9 @@ void MinePlacer::init()
bool MinePlacer::placeMines(ObjectManager & manager)
{
std::vector<CGMine*> createdMines;
std::vector<std::shared_ptr<CGMine>> createdMines;
std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects;
std::vector<std::pair<std::shared_ptr<CGObjectInstance>, ui32>> requiredObjects;
for(const auto & mineInfo : zone.getMinesInfo())
{
@ -60,7 +60,7 @@ bool MinePlacer::placeMines(ObjectManager & manager)
{
auto mineHandler = LIBRARY->objtypeh->getHandlerFor(Obj::MINE, res);
const auto & rmginfo = mineHandler->getRMGInfo();
auto * mine = dynamic_cast<CGMine *>(mineHandler->create(map.mapInstance->cb, nullptr));
auto mine = std::dynamic_pointer_cast<CGMine>(mineHandler->create(map.mapInstance->cb, nullptr));
mine->producedResource = res;
mine->tempOwner = PlayerColor::NEUTRAL;
mine->producedQuantity = mine->defaultResProduction();
@ -73,7 +73,7 @@ bool MinePlacer::placeMines(ObjectManager & manager)
manager.addCloseObject(RequiredObjectInfo(mine, rmginfo.value));
}
else
requiredObjects.push_back(std::pair<CGObjectInstance*, ui32>(mine, rmginfo.value));
requiredObjects.emplace_back(mine, rmginfo.value);
}
}
@ -87,15 +87,15 @@ bool MinePlacer::placeMines(ObjectManager & manager)
//create extra resources
if(int extraRes = generator.getConfig().mineExtraResources)
{
for(auto * mine : createdMines)
for(auto mine : createdMines)
{
for(int rc = zone.getRand().nextInt(1, extraRes); rc > 0; --rc)
{
auto * resource = dynamic_cast<CGResource *>(LIBRARY->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create(map.mapInstance->cb, nullptr));
auto resource = std::dynamic_pointer_cast<CGResource>(LIBRARY->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create(map.mapInstance->cb, nullptr));
RequiredObjectInfo roi;
roi.obj = resource;
roi.nearbyTarget = mine;
roi.nearbyTarget = mine.get();
manager.addNearbyObject(roi);
}
}

View File

@ -82,7 +82,7 @@ void ObjectDistributor::distributeLimitedObjects()
{
ObjectInfo oi(primaryID, secondaryID);
oi.generateObject = [cb=map.mapInstance->cb, primaryID, secondaryID]() -> CGObjectInstance *
oi.generateObject = [cb=map.mapInstance->cb, primaryID, secondaryID]()
{
return LIBRARY->objtypeh->getHandlerFor(primaryID, secondaryID)->create(cb, nullptr);
};

View File

@ -406,7 +406,7 @@ bool ObjectManager::createMonoliths()
continue;
}
rmg::Object rmgObject(*objInfo.obj);
rmg::Object rmgObject(objInfo.obj);
rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
bool guarded = addGuard(rmgObject, objInfo.guardStrength, true);
@ -442,7 +442,7 @@ bool ObjectManager::createRequiredObjects()
RecursiveLock lock(externalAccessMutex); //In case someone adds more objects
for(const auto & objInfo : requiredObjects)
{
rmg::Object rmgObject(*objInfo.obj);
rmg::Object rmgObject(objInfo.obj);
rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY));
@ -466,10 +466,10 @@ bool ObjectManager::createRequiredObjects()
for(const auto & nearby : nearbyObjects)
{
if(nearby.nearbyTarget != nearby.obj)
if(nearby.nearbyTarget != nearby.obj.get())
continue;
rmg::Object rmgNearObject(*nearby.obj);
rmg::Object rmgNearObject(nearby.obj);
rmg::Area possibleArea(rmgObject.instances().front()->getBlockedArea().getBorderOutside());
possibleArea.intersect(zone.areaPossible().get());
if(possibleArea.empty())
@ -487,7 +487,7 @@ bool ObjectManager::createRequiredObjects()
{
Zone::Lock lock(zone.areaMutex);
rmg::Object rmgObject(*objInfo.obj);
rmg::Object rmgObject(objInfo.obj);
rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
bool guarded = addGuard(rmgObject, objInfo.guardStrength, (objInfo.obj->ID == Obj::MONOLITH_TWO_WAY));
auto path = placeAndConnectObject(zone.areaPossible().get(), rmgObject,
@ -517,7 +517,7 @@ bool ObjectManager::createRequiredObjects()
continue;
}
rmg::Object rmgNearObject(*nearby.obj);
rmg::Object rmgNearObject(nearby.obj);
std::set<int3> blockedArea = targetObject->getBlockedPos();
rmg::Area areaForObject(rmg::Area(rmg::Tileset(blockedArea.begin(), blockedArea.end())).getBorderOutside());
areaForObject.intersect(zone.areaPossible().get());
@ -549,7 +549,7 @@ bool ObjectManager::createRequiredObjects()
//TODO: implement guards
for (const auto &objInfo : instantObjects) //Unused ATM
{
rmg::Object rmgObject(*objInfo.obj);
rmg::Object rmgObject(objInfo.obj);
rmgObject.setPosition(objInfo.pos);
placeObject(rmgObject, false, false);
}
@ -722,7 +722,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
}
}
CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
std::shared_ptr<CGCreature> ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
{
//precalculate actual (randomized) monster strength based on this post
//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
@ -775,7 +775,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
auto guardFactory = LIBRARY->objtypeh->getHandlerFor(Obj::MONSTER, creId);
auto * guard = dynamic_cast<CGCreature *>(guardFactory->create(map.mapInstance->cb, nullptr));
auto guard = std::dynamic_pointer_cast<CGCreature>(guardFactory->create(map.mapInstance->cb, nullptr));
guard->character = CGCreature::HOSTILE;
auto * hlp = new CStackInstance(creId, amount);
//will be set during initialization
@ -785,7 +785,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard)
{
auto * guard = chooseGuard(strength, zoneGuard);
auto guard = chooseGuard(strength, zoneGuard);
if(!guard)
return false;
@ -805,10 +805,8 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
});
if(accessibleArea.empty())
{
delete guard;
return false;
}
auto guardTiles = accessibleArea.getTilesVector();
auto guardPos = *std::min_element(guardTiles.begin(), guardTiles.end(), [&object](const int3 & l, const int3 & r)
{
@ -822,7 +820,7 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
return false;
});
auto & instance = object.addInstance(*guard);
auto & instance = object.addInstance(guard);
instance.setAnyTemplate(zone.getRand()); //terrain is irrelevant for monsters, but monsters need some template now
//Fix HoTA monsters with offset template
@ -840,7 +838,7 @@ RequiredObjectInfo::RequiredObjectInfo():
createRoad(true)
{}
RequiredObjectInfo::RequiredObjectInfo(CGObjectInstance* obj, ui32 guardStrength, bool createRoad, CGObjectInstance* nearbyTarget):
RequiredObjectInfo::RequiredObjectInfo(std::shared_ptr<CGObjectInstance> obj, ui32 guardStrength, bool createRoad, CGObjectInstance* nearbyTarget):
obj(obj),
nearbyTarget(nearbyTarget),
guardStrength(guardStrength),

View File

@ -32,9 +32,9 @@ struct DistanceMaximizeFunctor
struct RequiredObjectInfo
{
RequiredObjectInfo();
RequiredObjectInfo(CGObjectInstance* obj, ui32 guardStrength = 0, bool createRoad = false, CGObjectInstance* nearbyTarget = nullptr);
RequiredObjectInfo(std::shared_ptr<CGObjectInstance> obj, ui32 guardStrength = 0, bool createRoad = false, CGObjectInstance* nearbyTarget = nullptr);
CGObjectInstance* obj;
std::shared_ptr<CGObjectInstance> obj;
CGObjectInstance* nearbyTarget;
int3 pos;
ui32 guardStrength;
@ -71,7 +71,7 @@ public:
rmg::Path placeAndConnectObject(const rmg::Area & searchArea, rmg::Object & obj, si32 min_dist, bool isGuarded, bool onlyStraight, OptimizeType optimizer) const;
rmg::Path placeAndConnectObject(const rmg::Area & searchArea, rmg::Object & obj, const std::function<float(const int3)> & weightFunction, bool isGuarded, bool onlyStraight, OptimizeType optimizer) const;
CGCreature * chooseGuard(si32 strength, bool zoneGuard = false);
std::shared_ptr<CGCreature> chooseGuard(si32 strength, bool zoneGuard = false);
bool addGuard(rmg::Object & object, si32 strength, bool zoneGuard = false);
void placeObject(rmg::Object & object, bool guarded, bool updateDistance, bool createRoad = false);

View File

@ -137,7 +137,7 @@ bool ObstaclePlacer::isInTheMap(const int3& tile)
return map.isOnMap(tile);
}
void ObstaclePlacer::placeObject(rmg::Object & object, std::set<CGObjectInstance*> &)
void ObstaclePlacer::placeObject(rmg::Object & object, std::set<std::shared_ptr<CGObjectInstance>> &)
{
manager->placeObject(object, false, false);
}

View File

@ -31,7 +31,7 @@ public:
std::pair<bool, bool> verifyCoverage(const int3 & t) const override;
void placeObject(rmg::Object & object, std::set<CGObjectInstance*> & instances) override;
void placeObject(rmg::Object & object, std::set<std::shared_ptr<CGObjectInstance>> & instances) override;
void postProcess(const rmg::Object & object) override;

View File

@ -403,8 +403,8 @@ void RiverPlacer::connectRiver(const int3 & tile)
{
if(templ->animationFile == targetTemplateName)
{
auto * obj = handler->create(map.mapInstance->cb, templ);
rmg::Object deltaObj(*obj, deltaPositions[pos]);
auto obj = handler->create(map.mapInstance->cb, templ);
rmg::Object deltaObj(obj, deltaPositions[pos]);
deltaObj.finalize(map, zone.getRand());
}
}

View File

@ -101,7 +101,7 @@ void TownPlacer::placeTowns(ObjectManager & manager)
auto townFactory = LIBRARY->objtypeh->getHandlerFor(Obj::TOWN, zone.getTownType());
CGTownInstance * town = dynamic_cast<CGTownInstance *>(townFactory->create(map.mapInstance->cb, nullptr));
auto town = std::dynamic_pointer_cast<CGTownInstance>(townFactory->create(map.mapInstance->cb, nullptr));
town->tempOwner = player;
town->addBuilding(BuildingID::FORT);
town->addBuilding(BuildingID::DEFAULT);
@ -110,7 +110,7 @@ void TownPlacer::placeTowns(ObjectManager & manager)
for(auto spellID : LIBRARY->spellh->getDefaultAllowed()) //add all regular spells to town
town->possibleSpells.push_back(spellID);
auto position = placeMainTown(manager, *town);
auto position = placeMainTown(manager, town);
totalTowns++;
//register MAIN town of zone only
@ -166,7 +166,7 @@ void TownPlacer::placeTowns(ObjectManager & manager)
}
}
int3 TownPlacer::placeMainTown(ObjectManager & manager, CGTownInstance & town)
int3 TownPlacer::placeMainTown(ObjectManager & manager, std::shared_ptr<CGTownInstance> town)
{
//towns are big objects and should be centered around visitable position
rmg::Object rmgObject(town);
@ -267,7 +267,7 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player
}
auto townFactory = LIBRARY->objtypeh->getHandlerFor(Obj::TOWN, subType);
auto * town = dynamic_cast<CGTownInstance *>(townFactory->create(map.mapInstance->cb, nullptr));
auto town = std::dynamic_pointer_cast<CGTownInstance>(townFactory->create(map.mapInstance->cb, nullptr));
town->ID = Obj::TOWN;
town->tempOwner = player;
@ -284,7 +284,7 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player
//register MAIN town of zone
map.registerZone(town->getFactionID());
//first town in zone goes in the middle
placeMainTown(manager, *town);
placeMainTown(manager, town);
}
else
{

View File

@ -32,7 +32,7 @@ protected:
FactionID getTownTypeFromHint(size_t hintIndex);
void placeTowns(ObjectManager & manager);
bool placeMines(ObjectManager & manager);
int3 placeMainTown(ObjectManager & manager, CGTownInstance & town);
int3 placeMainTown(ObjectManager & manager, std::shared_ptr<CGTownInstance> town);
protected:
int totalTowns = 0;

View File

@ -138,7 +138,7 @@ void TreasurePlacer::addCommonObjects()
void TreasurePlacer::setBasicProperties(ObjectInfo & oi, CompoundMapObjectID objid) const
{
oi.generateObject = [this, objid]() -> CGObjectInstance *
oi.generateObject = [this, objid]() -> std::shared_ptr<CGObjectInstance>
{
return LIBRARY->objtypeh->getHandlerFor(objid)->create(map.mapInstance->cb, nullptr);
};
@ -176,11 +176,11 @@ void TreasurePlacer::addPrisons()
continue;
}
oi.generateObject = [i, this, prisonHeroPlacer]() -> CGObjectInstance*
oi.generateObject = [i, this, prisonHeroPlacer]() -> std::shared_ptr<CGObjectInstance>
{
HeroTypeID hid = prisonHeroPlacer->drawRandomHero();
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PRISON, 0);
auto* obj = dynamic_cast<CGHeroInstance*>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGHeroInstance>(factory->create(map.mapInstance->cb, nullptr));
obj->setHeroType(hid); //will be initialized later
obj->exp = generator.getConfig().prisonExperience[i];
@ -188,11 +188,11 @@ void TreasurePlacer::addPrisons()
return obj;
};
oi.destroyObject = [prisonHeroPlacer](CGObjectInstance* obj)
oi.destroyObject = [prisonHeroPlacer](CGObjectInstance& obj)
{
// Hero can be used again
auto* hero = dynamic_cast<CGHeroInstance*>(obj);
prisonHeroPlacer->restoreDrawnHero(hero->getHeroTypeID());
auto & hero = dynamic_cast<CGHeroInstance&>(obj);
prisonHeroPlacer->restoreDrawnHero(hero.getHeroTypeID());
};
oi.setTemplates(Obj::PRISON, 0, zone.getTerrainType());
@ -245,9 +245,9 @@ void TreasurePlacer::addDwellings()
oi.value = static_cast<ui32>(cre->getAIValue() * cre->getGrowth() * (1 + (nativeZonesCount / map.getTotalZoneCount()) + (nativeZonesCount / 2)));
oi.probability = 40;
oi.generateObject = [this, secondaryID, dwellingType]() -> CGObjectInstance *
oi.generateObject = [this, secondaryID, dwellingType]() -> std::shared_ptr<CGObjectInstance>
{
auto * obj = LIBRARY->objtypeh->getHandlerFor(dwellingType, secondaryID)->create(map.mapInstance->cb, nullptr);
auto obj = LIBRARY->objtypeh->getHandlerFor(dwellingType, secondaryID)->create(map.mapInstance->cb, nullptr);
obj->tempOwner = PlayerColor::NEUTRAL;
return obj;
};
@ -267,10 +267,10 @@ void TreasurePlacer::addScrolls()
for(int i = 0; i < generator.getConfig().scrollValues.size(); i++)
{
oi.generateObject = [i, this]() -> CGObjectInstance *
oi.generateObject = [i, this]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::SPELL_SCROLL, 0);
auto * obj = dynamic_cast<CGArtifact *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGArtifact>(factory->create(map.mapInstance->cb, nullptr));
std::vector<SpellID> out;
for(auto spellID : LIBRARY->spellh->getDefaultAllowed())
@ -307,10 +307,10 @@ void TreasurePlacer::addPandoraBoxesWithGold()
ObjectInfo oi(Obj::PANDORAS_BOX, 0);
for(int i = 1; i < 5; i++)
{
oi.generateObject = [this, i]() -> CGObjectInstance *
oi.generateObject = [this, i]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.resources[EGameResID::GOLD] = i * 5000;
@ -332,10 +332,10 @@ void TreasurePlacer::addPandoraBoxesWithExperience()
ObjectInfo oi(Obj::PANDORAS_BOX, 0);
for(int i = 1; i < 5; i++)
{
oi.generateObject = [this, i]() -> CGObjectInstance *
oi.generateObject = [this, i]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.heroExperience = i * 5000;
@ -362,10 +362,10 @@ void TreasurePlacer::addPandoraBoxesWithCreatures()
ObjectInfo oi(Obj::PANDORAS_BOX, 0);
oi.generateObject = [this, creature, creaturesAmount]() -> CGObjectInstance *
oi.generateObject = [this, creature, creaturesAmount]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.creatures.emplace_back(creature, creaturesAmount);
@ -388,10 +388,10 @@ void TreasurePlacer::addPandoraBoxesWithSpells()
//Pandora with 12 spells of certain level
for(int i = 1; i <= GameConstants::SPELL_LEVELS; i++)
{
oi.generateObject = [i, this]() -> CGObjectInstance *
oi.generateObject = [i, this]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
std::vector <const CSpell *> spells;
for(auto spellID : LIBRARY->spellh->getDefaultAllowed())
@ -421,10 +421,10 @@ void TreasurePlacer::addPandoraBoxesWithSpells()
//Pandora with 15 spells of certain school
for(int i = 0; i < 4; i++)
{
oi.generateObject = [i, this]() -> CGObjectInstance *
oi.generateObject = [i, this]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
std::vector <const CSpell *> spells;
for(auto spellID : LIBRARY->spellh->getDefaultAllowed())
@ -453,10 +453,10 @@ void TreasurePlacer::addPandoraBoxesWithSpells()
// Pandora box with 60 random spells
oi.generateObject = [this]() -> CGObjectInstance *
oi.generateObject = [this]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0);
auto * obj = dynamic_cast<CGPandoraBox *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGPandoraBox>(factory->create(map.mapInstance->cb, nullptr));
std::vector <const CSpell *> spells;
for(auto spellID : LIBRARY->spellh->getDefaultAllowed())
@ -518,11 +518,11 @@ void TreasurePlacer::addSeerHuts()
obj->quest->mission.artifacts.push_back(artid);
qap->addQuestArtifact(artid);
};
auto destroyObject = [qap](CGObjectInstance * obj)
auto destroyObject = [qap](CGObjectInstance & obj)
{
auto * seer = dynamic_cast<CGSeerHut *>(obj);
auto & seer = dynamic_cast<CGSeerHut &>(obj);
// Artifact can be used again
ArtifactID artid = seer->getQuest()->mission.artifacts.front();
ArtifactID artid = seer.getQuest()->mission.artifacts.front();
qap->addRandomArtifact(artid);
qap->removeQuestArtifact(artid);
};
@ -538,17 +538,16 @@ void TreasurePlacer::addSeerHuts()
int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType());
// FIXME: Remove duplicated code for gold, exp and creaure reward
oi.generateObject = [cb=map.mapInstance->cb, creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> CGObjectInstance *
oi.generateObject = [cb=map.mapInstance->cb, creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
auto * obj = dynamic_cast<CGSeerHut *>(factory->create(cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGSeerHut>(factory->create(cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.creatures.emplace_back(creature->getId(), creaturesAmount);
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
obj->configuration.info.push_back(reward);
setRandomArtifact(obj);
setRandomArtifact(obj.get());
return obj;
};
@ -583,17 +582,16 @@ void TreasurePlacer::addSeerHuts()
oi.probability = 10;
oi.maxPerZone = 1;
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance *
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
auto * obj = dynamic_cast<CGSeerHut *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGSeerHut>(factory->create(map.mapInstance->cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.heroExperience = generator.getConfig().questRewardValues[i];
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
obj->configuration.info.push_back(reward);
setRandomArtifact(obj);
setRandomArtifact(obj.get());
return obj;
};
@ -602,17 +600,17 @@ void TreasurePlacer::addSeerHuts()
if(!oi.templates.empty())
possibleSeerHuts.push_back(oi);
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance *
oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> std::shared_ptr<CGObjectInstance>
{
auto factory = LIBRARY->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
auto * obj = dynamic_cast<CGSeerHut *>(factory->create(map.mapInstance->cb, nullptr));
auto obj = std::dynamic_pointer_cast<CGSeerHut>(factory->create(map.mapInstance->cb, nullptr));
Rewardable::VisitInfo reward;
reward.reward.resources[EGameResID::GOLD] = generator.getConfig().questRewardValues[i];
reward.visitType = Rewardable::EEventType::EVENT_FIRST_VISIT;
obj->configuration.info.push_back(reward);
setRandomArtifact(obj);
setRandomArtifact(obj.get());
return obj;
};
@ -748,15 +746,14 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
accessibleArea.add(int3());
}
CGObjectInstance * object = nullptr;
std::shared_ptr<CGObjectInstance> object = nullptr;
if (oi->generateObject)
{
object = oi->generateObject();
if(oi->templates.empty())
{
logGlobal->warn("Deleting randomized object with no templates: %s", object->getObjectName());
oi->destroyObject(object);
delete object;
oi->destroyObject(*object);
continue;
}
}
@ -785,7 +782,7 @@ rmg::Object TreasurePlacer::constructTreasurePile(const std::vector<ObjectInfo*>
});
}
auto & instance = rmgObject.addInstance(*object);
auto & instance = rmgObject.addInstance(object);
rmgObject.setValue(rmgObject.getValue() + oi->value);
instance.onCleared = oi->destroyObject;

View File

@ -250,8 +250,8 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout
for(auto subObj : subObjects)
{
//making a temporary object
std::unique_ptr<CGObjectInstance> obj(LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, subObj)->create(map.mapInstance->cb, nullptr));
if(auto * testBoat = dynamic_cast<CGBoat *>(obj.get()))
auto obj(LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, subObj)->create(map.mapInstance->cb, nullptr));
if(auto testBoat = dynamic_cast<CGBoat *>(obj.get()))
{
if(testBoat->layer == EPathfindingLayer::SAIL)
sailingBoatTypes.insert(subObj);
@ -261,9 +261,9 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout
if(sailingBoatTypes.empty())
return false;
auto * boat = dynamic_cast<CGBoat *>(LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create(map.mapInstance->cb, nullptr));
auto boat = std::dynamic_pointer_cast<CGBoat>(LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create(map.mapInstance->cb, nullptr));
rmg::Object rmgObject(*boat);
rmg::Object rmgObject(boat);
rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
auto waterAvailable = zone.areaForRoads();
@ -325,10 +325,10 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, bool
return false;
int subtype = chooseRandomAppearance(zone.getRand(), Obj::SHIPYARD, land.getTerrainType());
auto * shipyard = dynamic_cast<CGShipyard *>(LIBRARY->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create(map.mapInstance->cb, nullptr));
auto shipyard = std::dynamic_pointer_cast<CGShipyard>(LIBRARY->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create(map.mapInstance->cb, nullptr));
shipyard->tempOwner = PlayerColor::NEUTRAL;
rmg::Object rmgObject(*shipyard);
rmg::Object rmgObject(shipyard);
rmgObject.setTemplate(land.getTerrainType(), zone.getRand());
bool guarded = manager->addGuard(rmgObject, guard);