1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Map objects now use shared_ptr (game)

This commit is contained in:
Ivan Savenko
2025-03-13 19:42:18 +00:00
parent 2ca1748e96
commit 0ada2a5ebd
49 changed files with 487 additions and 613 deletions

View File

@ -625,18 +625,18 @@ void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack)
void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack)
{
CGHeroInstance *h = gs.getMap().heroesOnMap.back();
auto & h = gs.getMap().heroesOnMap.back();
if(h->getHeroTypeID() != pack.hid)
{
logNetwork->error("Something wrong with hero recruited!");
}
if(callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h))
if(callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroCreated, h.get()))
{
if(const CGTownInstance *t = gs.getTown(pack.tid))
callInterfaceIfPresent(cl, h->getOwner(), &IGameEventsReceiver::heroInGarrisonChange, t);
}
GAME->map().onObjectInstantAdd(h, h->getOwner());
GAME->map().onObjectInstantAdd(h.get(), h->getOwner());
}
void ApplyClientNetPackVisitor::visitGiveHero(GiveHero & pack)
@ -1054,7 +1054,7 @@ void ApplyClientNetPackVisitor::visitNewObject(NewObject & pack)
{
callAllInterfaces(cl, &CGameInterface::invalidatePaths);
const CGObjectInstance *obj = pack.newObject;
const CGObjectInstance * obj = pack.newObject.get();
GAME->map().onObjectFadeIn(obj, pack.initiator);
for(auto i=cl.playerint.begin(); i!=cl.playerint.end(); i++)

View File

@ -209,7 +209,7 @@ MapAudioPlayer::MapAudioPlayer()
for(const auto & obj : GAME->map().getMap()->objects)
{
if (obj)
addObject(obj);
addObject(obj.get());
}
}

View File

@ -103,7 +103,7 @@ const MapRendererBaseContext::MapObjectsList & MapRendererBaseContext::getObject
const CGObjectInstance * MapRendererBaseContext::getObject(ObjectInstanceID objectID) const
{
return GAME->map().getMap()->objects.at(objectID.getNum());
return GAME->map().getMap()->objects.at(objectID.getNum()).get();
}
const CGPath * MapRendererBaseContext::currentPath() const

View File

@ -25,7 +25,7 @@
static bool compareObjectBlitOrder(ObjectInstanceID left, ObjectInstanceID right)
{
//FIXME: remove mh access
return GAME->map().compareObjectBlitOrder(GAME->map().getMap()->objects[left.getNum()], GAME->map().getMap()->objects[right.getNum()]);
return GAME->map().compareObjectBlitOrder(GAME->map().getMap()->objects.at(left.getNum()).get(), GAME->map().getMap()->objects.at(right.getNum()).get());
}
MapRendererContextState::MapRendererContextState()
@ -36,7 +36,7 @@ MapRendererContextState::MapRendererContextState()
logGlobal->debug("Loading map objects");
for(const auto & obj : GAME->map().getMap()->objects)
addObject(obj);
addObject(obj.get());
logGlobal->debug("Done loading map objects");
}

View File

@ -139,7 +139,7 @@ const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool v
return nullptr;
}
const CGObjectInstance *ret = gs->getMap().objects[oid];
const CGObjectInstance *ret = gs->getMap().objects[oid].get();
if(!ret)
{
if(verbose)
@ -484,8 +484,8 @@ std::vector<const CGObjectInstance *> CGameInfoCallback::getAllVisitableObjs() c
{
std::vector<const CGObjectInstance *> ret;
for(auto & obj : gs->getMap().objects)
if(obj && obj->isVisitable() && obj->ID != Obj::EVENT && isVisible(obj))
ret.push_back(obj);
if(obj && obj->isVisitable() && obj->ID != Obj::EVENT && isVisible(obj.get()))
ret.push_back(obj.get());
return ret;
}
@ -784,7 +784,7 @@ std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo
if((hero->tempOwner == *getPlayerID()) ||
(isVisible(hero->visitablePos(), getPlayerID()) && !onlyOur) )
{
ret.push_back(hero);
ret.push_back(hero.get());
}
}
return ret;
@ -956,7 +956,7 @@ const CArtifactInstance * CGameInfoCallback::getArtInstance( ArtifactInstanceID
const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid ) const
{
return gs->getMap().objects.at(oid.num);
return gs->getMap().objects.at(oid.num).get();
}
const CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const

View File

@ -700,7 +700,6 @@ set(lib_MAIN_HEADERS
CGameInfoCallback.h
CGameInterface.h
ConditionalWait.h
ConstTransitivePtr.h
Color.h
CPlayerState.h
CRandomGenerator.h

View File

@ -1,80 +0,0 @@
/*
* ConstTransitivePtr.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
class CGameHandler;
VCMI_LIB_NAMESPACE_BEGIN
template <typename T>
class ConstTransitivePtr
{
T *ptr = nullptr;
ConstTransitivePtr(const T *Ptr)
: ptr(const_cast<T*>(Ptr))
{}
public:
ConstTransitivePtr(T *Ptr = nullptr)
: ptr(Ptr)
{}
ConstTransitivePtr(std::nullptr_t)
{}
const T& operator*() const
{
return *ptr;
}
T& operator*()
{
return *ptr;
}
operator const T*() const
{
return ptr;
}
T* get()
{
return ptr;
}
const T* get() const
{
return ptr;
}
operator T*()
{
return ptr;
}
T *operator->()
{
return ptr;
}
const T *operator->() const
{
return ptr;
}
const T*operator=(T *t)
{
return ptr = t;
}
void dellNull()
{
delete ptr;
ptr = nullptr;
}
template <typename Handler> void serialize(Handler &h)
{
h & ptr;
}
friend class ::CGameHandler;
};
VCMI_LIB_NAMESPACE_END

View File

@ -256,7 +256,7 @@ CArtifactInstance * CNonConstInfoCallback::getArtInstance(const ArtifactInstance
CGObjectInstance * CNonConstInfoCallback::getObjInstance(const ObjectInstanceID & oid)
{
return gs->getMap().objects.at(oid.num);
return gs->getMap().objects.at(oid.num).get();
}
CArmedInstance * CNonConstInfoCallback::getArmyInstance(const ObjectInstanceID & oid)

View File

@ -327,13 +327,12 @@ std::set<HeroTypeID> CampaignState::getReservedHeroes() const
return result;
}
const CGHeroInstance * CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const
std::shared_ptr<CGHeroInstance> CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const
{
std::function<bool(const JsonNode & node)> isOwned = [&](const JsonNode & node)
{
auto * h = CampaignState::crossoverDeserialize(node, nullptr);
auto h = CampaignState::crossoverDeserialize(node, nullptr);
bool result = h->tempOwner == owner;
vstd::clear_pointer(h);
return result;
};
auto ownedHeroes = scenarioHeroPool.at(scenarioId) | boost::adaptors::filtered(isOwned);
@ -475,10 +474,10 @@ JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) const
return node;
}
CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) const
std::shared_ptr<CGHeroInstance> CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) const
{
JsonDeserializer handler(nullptr, const_cast<JsonNode&>(node));
auto * hero = new CGHeroInstance(map ? map->cb : nullptr);
auto hero = std::make_shared<CGHeroInstance>(map ? map->cb : nullptr);
hero->ID = Obj::HERO;
hero->serializeJsonOptions(handler);
if (map)

View File

@ -350,7 +350,7 @@ public:
std::set<HeroTypeID> getReservedHeroes() const;
/// Returns strongest hero from specified scenario, or null if none found
const CGHeroInstance * strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const;
std::shared_ptr<CGHeroInstance> strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const;
/// Returns heroes that can be instantiated as hero placeholders by power
const std::vector<JsonNode> & getHeroesByPower(CampaignScenarioID scenarioId) const;
@ -360,7 +360,7 @@ public:
const JsonNode & getHeroByType(HeroTypeID heroID) const;
JsonNode crossoverSerialize(CGHeroInstance * hero) const;
CGHeroInstance * crossoverDeserialize(const JsonNode & node, CMap * map) const;
std::shared_ptr<CGHeroInstance> crossoverDeserialize(const JsonNode & node, CMap * map) const;
std::string campaignSet;

View File

@ -233,7 +233,7 @@ void CGameState::updateEntity(Metatype metatype, int32_t index, const JsonNode &
//index is hero type
if(index >= 0 && index < map->allHeroes.size())
{
CGHeroInstance * hero = map->allHeroes.at(index);
const auto & hero = map->allHeroes.at(index);
hero->updateFrom(data);
}
else
@ -471,7 +471,7 @@ void CGameState::initRandomFactionsForPlayers()
void CGameState::randomizeMapObjects()
{
logGlobal->debug("\tRandomizing objects");
for(CGObjectInstance *object : map->objects)
for(const auto & object : map->objects)
{
if(!object)
continue;
@ -495,10 +495,10 @@ void CGameState::randomizeMapObjects()
void CGameState::initOwnedObjects()
{
for(CGObjectInstance *object : map->objects)
for(const auto & object : map->objects)
{
if (object && object->getOwner().isValidPlayer())
getPlayerState(object->getOwner())->addOwnedObject(object);
getPlayerState(object->getOwner())->addOwnedObject(object.get());
}
}
@ -528,8 +528,8 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy
}
auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex());
CGObjectInstance * obj = handler->create(callback, handler->getTemplates().front());
CGHeroInstance * hero = dynamic_cast<CGHeroInstance *>(obj);
auto object = handler->create(callback, handler->getTemplates().front());
auto hero = std::dynamic_pointer_cast<CGHeroInstance>(object);
hero->ID = Obj::HERO;
hero->setHeroType(heroTypeId);
@ -587,9 +587,7 @@ void CGameState::initHeroes()
logGlobal->warn("Hero with uninitialized owner!");
continue;
}
hero->initHero(getRandomGenerator());
map->allHeroes[hero->getHeroTypeID().getNum()] = hero;
}
// generate boats for all heroes on water
@ -600,8 +598,8 @@ void CGameState::initHeroes()
if (tile.isWater())
{
auto handler = LIBRARY->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum());
auto boat = dynamic_cast<CGBoat*>(handler->create(callback, nullptr));
handler->configureObject(boat, gs->getRandomGenerator());
auto boat = std::dynamic_pointer_cast<CGBoat>(handler->create(callback, nullptr));
handler->configureObject(boat.get(), gs->getRandomGenerator());
boat->setAnchorPos(hero->anchorPos());
boat->appearance = handler->getTemplates().front();
@ -609,7 +607,7 @@ void CGameState::initHeroes()
map->objects.emplace_back(boat);
hero->attachToBoat(boat);
hero->attachToBoat(boat.get());
}
}
@ -619,7 +617,6 @@ void CGameState::initHeroes()
{
auto * hero = dynamic_cast<CGHeroInstance*>(obj.get());
hero->initHero(getRandomGenerator());
map->allHeroes[hero->getHeroTypeID().getNum()] = hero;
}
}
@ -629,20 +626,18 @@ void CGameState::initHeroes()
if(!vstd::contains(heroesToCreate, ph->getHeroTypeID()))
continue;
ph->initHero(getRandomGenerator());
heroesPool->addHeroToPool(ph);
heroesPool->addHeroToPool(ph.get());
heroesToCreate.erase(ph->getHeroTypeID());
map->allHeroes[ph->getHeroTypeID().getNum()] = ph;
}
for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool
{
auto * vhi = new CGHeroInstance(callback);
auto vhi = std::make_shared<CGHeroInstance>(callback);
vhi->initHero(getRandomGenerator(), htype);
int typeID = htype.getNum();
map->allHeroes[typeID] = vhi;
heroesPool->addHeroToPool(vhi);
heroesPool->addHeroToPool(vhi.get());
}
for(auto & elem : map->disposedHeroes)
@ -663,7 +658,7 @@ void CGameState::initFogOfWar()
fow.resize(boost::extents[layers][map->width][map->height]);
std::fill(fow.data(), fow.data() + fow.num_elements(), 0);
for(CGObjectInstance *obj : map->objects)
for(const auto & obj : map->objects)
{
if(!obj || !vstd::contains(elem.second.players, obj->tempOwner)) continue; //not a flagged object
@ -918,14 +913,13 @@ void CGameState::initMapObjects()
{
logGlobal->debug("\tObject initialization");
// objCaller->preInit();
for(CGObjectInstance *obj : map->objects)
for(auto & obj : map->objects)
{
if(obj)
obj->initObj(getRandomGenerator());
}
logGlobal->debug("\tObject initialization done");
for(CGObjectInstance *obj : map->objects)
for(auto & obj : map->objects)
{
if(!obj)
continue;
@ -935,7 +929,7 @@ void CGameState::initMapObjects()
case Obj::QUEST_GUARD:
case Obj::SEER_HUT:
{
auto * q = dynamic_cast<CGSeerHut *>(obj);
auto * q = dynamic_cast<CGSeerHut *>(obj.get());
assert (q);
q->setObjToKill();
}
@ -1001,9 +995,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
for (auto hero : map->heroesOnMap)
{
if (hero->getVisitedTown())
{
assert (hero->getVisitedTown()->getVisitingHero() == hero);
}
assert(hero->getVisitedTown()->getVisitingHero() == hero.get());
}
}
@ -1577,7 +1569,7 @@ void CGameState::buildBonusSystemTree()
buildGlobalTeamPlayerTree();
attachArmedObjects();
for(CGTownInstance *t : map->towns)
for(auto & t : map->towns)
{
t->deserializationFix();
}
@ -1607,9 +1599,9 @@ void CGameState::buildGlobalTeamPlayerTree()
void CGameState::attachArmedObjects()
{
for(CGObjectInstance *obj : map->objects)
for(auto & obj : map->objects)
{
if(auto * armed = dynamic_cast<CArmedInstance *>(obj))
if(auto * armed = dynamic_cast<CArmedInstance *>(obj.get()))
{
armed->whatShouldBeAttached().attachTo(armed->whereShouldBeAttached(this));
}

View File

@ -34,7 +34,7 @@
VCMI_LIB_NAMESPACE_BEGIN
CampaignHeroReplacement::CampaignHeroReplacement(CGHeroInstance * hero, const ObjectInstanceID & heroPlaceholderId):
CampaignHeroReplacement::CampaignHeroReplacement(std::shared_ptr<CGHeroInstance> hero, const ObjectInstanceID & heroPlaceholderId):
hero(hero),
heroPlaceholderId(heroPlaceholderId)
{
@ -227,7 +227,7 @@ void CGameStateCampaign::placeCampaignHeroes()
// remove same heroes on the map which will be added through crossover heroes
// INFO: we will remove heroes because later it may be possible that the API doesn't allow having heroes
// with the same hero type id
std::vector<CGHeroInstance *> removedHeroes;
std::vector<std::shared_ptr<CGObjectInstance>> removedHeroes;
std::set<HeroTypeID> reservedHeroes = campaignState->getReservedHeroes();
std::set<HeroTypeID> heroesToRemove;
@ -248,10 +248,7 @@ void CGameStateCampaign::placeCampaignHeroes()
auto * hero = gameState->getUsedHero(heroID);
if(hero)
{
removedHeroes.push_back(hero);
gameState->map->heroesOnMap -= hero;
gameState->map->objects[hero->id.getNum()] = nullptr;
gameState->map->removeBlockVisTiles(hero, true);
removedHeroes.push_back(gameState->map->eraseObject(hero->id));
}
}
@ -259,8 +256,9 @@ void CGameStateCampaign::placeCampaignHeroes()
replaceHeroesPlaceholders();
// now add removed heroes again with unused type ID
for(auto * hero : removedHeroes)
for(auto object : removedHeroes)
{
auto hero = dynamic_cast<CGHeroInstance*>(object.get());
HeroTypeID heroTypeId;
if(hero->ID == Obj::HERO)
{
@ -285,7 +283,7 @@ void CGameStateCampaign::placeCampaignHeroes()
}
hero->setHeroType(heroTypeId);
gameState->map->getEditManager()->insertObject(hero);
gameState->map->getEditManager()->insertObject(object);
}
}
@ -363,26 +361,18 @@ void CGameStateCampaign::replaceHeroesPlaceholders()
if (!campaignHeroReplacement.heroPlaceholderId.hasValue())
continue;
auto * heroPlaceholder = dynamic_cast<CGHeroPlaceholder *>(gameState->getObjInstance(campaignHeroReplacement.heroPlaceholderId));
auto heroPlaceholder = gameState->map->objects.at(campaignHeroReplacement.heroPlaceholderId.getNum());
auto heroToPlace = campaignHeroReplacement.hero;
CGHeroInstance *heroToPlace = campaignHeroReplacement.hero;
heroToPlace->id = campaignHeroReplacement.heroPlaceholderId;
if(heroPlaceholder->tempOwner.isValidPlayer())
heroToPlace->tempOwner = heroPlaceholder->tempOwner;
// FIXME: consider whether to move these actions to CMap::replaceObject method
heroToPlace->setAnchorPos(heroPlaceholder->anchorPos());
heroToPlace->setHeroType(heroToPlace->getHeroTypeID());
heroToPlace->appearance = heroToPlace->getObjectHandler()->getTemplates().front();
gameState->map->removeBlockVisTiles(heroPlaceholder, true);
gameState->map->objects[heroPlaceholder->id.getNum()] = nullptr;
gameState->map->instanceNames.erase(heroPlaceholder->instanceName);
gameState->map->heroesOnMap.emplace_back(heroToPlace);
gameState->map->objects[heroToPlace->id.getNum()] = heroToPlace;
gameState->map->addBlockVisTiles(heroToPlace);
gameState->map->instanceNames[heroToPlace->instanceName] = heroToPlace;
delete heroPlaceholder;
gameState->map->replaceObject(campaignHeroReplacement.heroPlaceholderId, heroToPlace);
}
}
@ -413,7 +403,7 @@ void CGameStateCampaign::transferMissingArtifacts(const CampaignTravel & travelO
if (campaignHeroReplacement.heroPlaceholderId.hasValue())
continue;
auto * donorHero = campaignHeroReplacement.hero;
auto donorHero = campaignHeroReplacement.hero;
if (!donorHero)
throw std::runtime_error("Failed to find hero to take artifacts from! Scenario: " + gameState->map->name.toString());
@ -440,7 +430,8 @@ void CGameStateCampaign::transferMissingArtifacts(const CampaignTravel & travelO
logGlobal->error("Cannot transfer artifact - no receiver hero!");
}
delete donorHero;
// FIXME: erase entry from array? clear entire campaignHeroReplacements?
//campaignHeroReplacement.hero.reset();
}
}
@ -484,7 +475,7 @@ void CGameStateCampaign::generateCampaignHeroesToReplace()
continue;
}
CGHeroInstance * hero = campaignState->crossoverDeserialize(node, gameState->map.get());
auto hero = campaignState->crossoverDeserialize(node, gameState->map.get());
logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated());
@ -509,7 +500,7 @@ void CGameStateCampaign::generateCampaignHeroesToReplace()
if (nodeListIter == nodeList.end())
break;
CGHeroInstance * hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map.get());
auto hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map.get());
nodeListIter++;
logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated());
@ -520,7 +511,7 @@ void CGameStateCampaign::generateCampaignHeroesToReplace()
// Add remaining heroes without placeholders - to transfer their artifacts to placed heroes
for (;nodeListIter != nodeList.end(); ++nodeListIter)
{
CGHeroInstance * hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map.get());
auto hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map.get());
campaignHeroReplacements.emplace_back(hero, ObjectInstanceID::NONE);
}
}
@ -645,7 +636,7 @@ void CGameStateCampaign::initTowns()
for (int g=0; g<gameState->map->towns.size(); ++g)
{
CGTownInstance * town = gameState->map->towns[g];
auto town = gameState->map->towns[g];
PlayerState * owner = gameState->getPlayerState(town->getOwner());
if (!owner)

View File

@ -23,8 +23,8 @@ class CMap;
struct CampaignHeroReplacement
{
CampaignHeroReplacement(CGHeroInstance * hero, const ObjectInstanceID & heroPlaceholderId);
CGHeroInstance * hero;
CampaignHeroReplacement(std::shared_ptr<CGHeroInstance> hero, const ObjectInstanceID & heroPlaceholderId);
std::shared_ptr<CGHeroInstance> hero;
ObjectInstanceID heroPlaceholderId;
std::vector<ArtifactPosition> transferrableArtifacts;
};

View File

@ -188,34 +188,6 @@ std::string StatisticDataSet::writeCsv()
return filePath.string();
}
std::vector<const CGMine *> Statistic::getMines(const CGameState * gs, const PlayerState * ps)
{
std::vector<const CGMine *> tmp;
std::vector<const CGObjectInstance *> ownedObjects;
for(const CGObjectInstance * obj : gs->getMap().objects)
{
if(obj && obj->tempOwner == ps->color)
ownedObjects.push_back(obj);
}
/// This is code from CPlayerSpecificInfoCallback::getMyObjects
/// I'm really need to find out about callback interface design...
for(const auto * object : ownedObjects)
{
//Mines
if ( object->ID == Obj::MINE )
{
const auto * mine = dynamic_cast<const CGMine *>(object);
assert(mine);
tmp.push_back(mine);
}
}
return tmp;
}
//calculates total number of artifacts that belong to given player
int Statistic::getNumberOfArts(const PlayerState * ps)
{
@ -267,15 +239,8 @@ int Statistic::getIncome(const CGameState * gs, const PlayerState * ps)
int totalIncome = 0;
//Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->getHeroes())
totalIncome += h->dailyIncome()[EGameResID::GOLD];
//Add town income of all towns
for(const auto & t : ps->getTowns())
totalIncome += t->dailyIncome()[EGameResID::GOLD];
for(const CGMine * mine : getMines(gs, ps))
totalIncome += mine->dailyIncome()[EGameResID::GOLD];
for(const auto & object : ps->getOwnedObjects())
totalIncome += object->asOwnable()->dailyIncome()[EGameResID::GOLD];
return totalIncome;
}
@ -366,9 +331,16 @@ std::map<EGameResID, int> Statistic::getNumMines(const CGameState * gs, const Pl
for(auto & res : EGameResID::ALL_RESOURCES())
tmp[res] = 0;
for(const CGMine * mine : getMines(gs, ps))
tmp[mine->producedResource]++;
for(const auto * object : ps->getOwnedObjects())
{
//Mines
if ( object->ID == Obj::MINE )
{
const auto * mine = dynamic_cast<const CGMine *>(object);
assert(mine);
tmp[mine->producedResource]++;
}
}
return tmp;
}

View File

@ -148,7 +148,6 @@ public:
class DLL_LINKAGE Statistic
{
static std::vector<const CGMine *> getMines(const CGameState * gs, const PlayerState * ps);
public:
static int getNumberOfArts(const PlayerState * ps);
static int getNumberOfDwellings(const PlayerState * ps);

View File

@ -116,7 +116,7 @@ public:
/// Creates object and set up core properties (like ID/subID). Object is NOT initialized
/// to allow creating objects before game start (e.g. map loading)
virtual CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
virtual std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const = 0;
/// Configures object properties. Should be re-entrable, resetting state of the object if necessarily
/// This should set remaining properties, including randomized or depending on map

View File

@ -27,16 +27,16 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
randomizeObject(castedObject, rng);
}
CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const final
{
ObjectType * result = createObject(cb);
auto result = createObject(cb);
preInitObject(result);
preInitObject(result.get());
if(tmpl)
result->appearance = tmpl;
initializeObject(result);
initializeObject(result.get());
return result;
}
@ -44,9 +44,9 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler
protected:
virtual void initializeObject(ObjectType * object) const {}
virtual void randomizeObject(ObjectType * object, vstd::RNG & rng) const {}
virtual ObjectType * createObject(IGameCallback * cb) const
virtual std::shared_ptr<ObjectType> createObject(IGameCallback * cb) const
{
return new ObjectType(cb);
return std::make_shared<ObjectType>(cb);
}
};

View File

@ -37,10 +37,10 @@ bool CRewardableConstructor::hasNameTextID() const
return !objectInfo.getParameters()["name"].isNull();
}
CGObjectInstance * CRewardableConstructor::create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const
std::shared_ptr<CGObjectInstance> CRewardableConstructor::create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl) const
{
auto * ret = new CRewardableObject(cb);
preInitObject(ret);
auto ret = std::make_shared<CRewardableObject>(cb);
preInitObject(ret.get());
ret->appearance = tmpl;
ret->blockVisit = blockVisit;
return ret;

View File

@ -25,7 +25,7 @@ class DLL_LINKAGE CRewardableConstructor : public AObjectTypeHandler
public:
bool hasNameTextID() const override;
CGObjectInstance * create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
std::shared_ptr<CGObjectInstance> create(IGameCallback * cb, std::shared_ptr<const ObjectTemplate> tmpl = nullptr) const override;
void configureObject(CGObjectInstance * object, vstd::RNG & rng) const override;

View File

@ -320,7 +320,7 @@ bool MarketInstanceConstructor::hasDescription() const
return !descriptionTextID.empty();
}
CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
std::shared_ptr<CGMarket> MarketInstanceConstructor::createObject(IGameCallback * cb) const
{
if(marketModes.size() == 1)
{
@ -328,13 +328,13 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const
{
case EMarketMode::ARTIFACT_RESOURCE:
case EMarketMode::RESOURCE_ARTIFACT:
return new CGBlackMarket(cb);
return std::make_shared<CGBlackMarket>(cb);
case EMarketMode::RESOURCE_SKILL:
return new CGUniversity(cb);
return std::make_shared<CGUniversity>(cb);
}
}
return new CGMarket(cb);
return std::make_shared<CGMarket>(cb);
}
const std::set<EMarketMode> & MarketInstanceConstructor::availableModes() const

View File

@ -137,7 +137,7 @@ class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
void initTypeData(const JsonNode & config) override;
public:
CGMarket * createObject(IGameCallback * cb) const override;
std::shared_ptr<CGMarket> createObject(IGameCallback * cb) const override;
void randomizeObject(CGMarket * object, vstd::RNG & rng) const override;
const std::set<EMarketMode> & availableModes() const;

View File

@ -1604,13 +1604,12 @@ std::string CGHeroInstance::getHeroTypeName() const
void CGHeroInstance::afterAddToMap(CMap * map)
{
if(ID != Obj::PRISON)
map->heroesOnMap.emplace_back(this);
map->heroAddedToMap(this);
}
void CGHeroInstance::afterRemoveFromMap(CMap* map)
{
if (ID == Obj::PRISON)
vstd::erase_if_present(map->heroesOnMap, this);
map->heroRemovedFromMap(this);
}
void CGHeroInstance::setHeroTypeName(const std::string & identifier)

View File

@ -1058,12 +1058,12 @@ void CGTownInstance::onTownCaptured(const PlayerColor & winner) const
void CGTownInstance::afterAddToMap(CMap * map)
{
map->towns.emplace_back(this);
map->townAddedToMap(this);
}
void CGTownInstance::afterRemoveFromMap(CMap * map)
{
vstd::erase_if_present(map->towns, this);
map->townRemovedFromMap(this);
}
void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler)

View File

@ -948,10 +948,10 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
std::vector<const CGObjectInstance *> eyes;
for (auto object : cb->gameState()->getMap().objects)
for (const auto & object : cb->gameState()->getMap().objects)
{
if (object && object->ID == Obj::EYE_OF_MAGI && object->subID == this->subID)
eyes.push_back(object);
eyes.push_back(object.get());
}
if (!eyes.empty())

View File

@ -191,9 +191,6 @@ CMap::~CMap()
{
getEditManager()->getUndoManager().clearAll();
for(auto obj : objects)
obj.dellNull();
resetStaticData();
}
@ -260,7 +257,7 @@ CGHeroInstance * CMap::getHero(HeroTypeID heroID)
{
for(auto & elem : heroesOnMap)
if(elem->getHeroTypeID() == heroID)
return elem;
return elem.get();
return nullptr;
}
@ -377,16 +374,16 @@ const CGObjectInstance * CMap::getObjectiveObjectFrom(const int3 & pos, Obj type
logGlobal->error("Will try to find closest matching object");
CGObjectInstance * bestMatch = nullptr;
for (CGObjectInstance * object : objects)
for (const auto & object : objects)
{
if (object && object->ID == type)
{
if (bestMatch == nullptr)
bestMatch = object;
bestMatch = object.get();
else
{
if (object->anchorPos().dist2dSQ(pos) < bestMatch->anchorPos().dist2dSQ(pos))
bestMatch = object;// closer than one we already found
bestMatch = object.get();// closer than one we already found
}
}
}
@ -424,32 +421,32 @@ void CMap::checkForObjectives()
cond.objectID = getObjectiveObjectFrom(cond.position, Obj::TOWN)->id;
break;
case EventCondition::CONTROL:
if (isInTheMap(cond.position))
cond.objectID = getObjectiveObjectFrom(cond.position, cond.objectType.as<MapObjectID>())->id;
if (cond.objectID != ObjectInstanceID::NONE)
{
const auto * town = dynamic_cast<const CGTownInstance *>(objects[cond.objectID].get());
if (town)
event.onFulfill.replaceRawString(town->getNameTranslated());
const auto * hero = dynamic_cast<const CGHeroInstance *>(objects[cond.objectID].get());
if (hero)
event.onFulfill.replaceRawString(hero->getNameTranslated());
}
break;
case EventCondition::DESTROY:
if (isInTheMap(cond.position))
cond.objectID = getObjectiveObjectFrom(cond.position, cond.objectType.as<MapObjectID>())->id;
if (cond.objectID != ObjectInstanceID::NONE)
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(objects[cond.objectID].get());
if (hero)
event.onFulfill.replaceRawString(hero->getNameTranslated());
}
break;
// case EventCondition::CONTROL:
// if (isInTheMap(cond.position))
// cond.objectID = getObjectiveObjectFrom(cond.position, cond.objectType.as<MapObjectID>())->id;
//
// if (cond.objectID != ObjectInstanceID::NONE)
// {
// const auto * town = dynamic_cast<const CGTownInstance *>(objects[cond.objectID].get());
// if (town)
// event.onFulfill.replaceRawString(town->getNameTranslated());
// const auto * hero = dynamic_cast<const CGHeroInstance *>(objects[cond.objectID].get());
// if (hero)
// event.onFulfill.replaceRawString(hero->getNameTranslated());
// }
// break;
//
// case EventCondition::DESTROY:
// if (isInTheMap(cond.position))
// cond.objectID = getObjectiveObjectFrom(cond.position, cond.objectType.as<MapObjectID>())->id;
//
// if (cond.objectID != ObjectInstanceID::NONE)
// {
// const auto * hero = dynamic_cast<const CGHeroInstance *>(objects[cond.objectID].get());
// if (hero)
// event.onFulfill.replaceRawString(hero->getNameTranslated());
// }
// break;
case EventCondition::TRANSPORT:
cond.objectID = getObjectiveObjectFrom(cond.position, Obj::TOWN)->id;
break;
@ -527,63 +524,89 @@ void CMap::clearQuestInstance(const CQuest * quest)
quests.at(quest->qid) = nullptr;
}
void CMap::setUniqueInstanceName(CGObjectInstance * obj)
{
//this gives object unique name even if objects are removed later
//void CMap::setUniqueInstanceName(CGObjectInstance * obj)
//{
// //this gives object unique name even if objects are removed later
//
// auto uid = uidCounter++;
//
// boost::format fmt("%s_%d");
// fmt % obj->getTypeName() % uid;
// obj->instanceName = fmt.str();
//}
auto uid = uidCounter++;
//void CMap::addNewObject(CGObjectInstance * obj)
//{
// if(obj->id != ObjectInstanceID(static_cast<si32>(objects.size())))
// throw std::runtime_error("Invalid object instance id");
//
// if(obj->instanceName.empty())
// throw std::runtime_error("Object instance name missing");
//
// if (vstd::contains(instanceNames, obj->instanceName))
// throw std::runtime_error("Object instance name duplicated: "+obj->instanceName);
//
// objects.emplace_back(obj);
// instanceNames[obj->instanceName] = obj;
// addBlockVisTiles(obj);
//
// //TODO: how about defeated heroes recruited again?
//
// obj->afterAddToMap(this);
//}
//
//void CMap::moveObject(CGObjectInstance * obj, const int3 & pos)
//{
// removeBlockVisTiles(obj);
// obj->setAnchorPos(pos);
// addBlockVisTiles(obj);
//}
//
//void CMap::removeObject(CGObjectInstance * obj)
//{
// removeBlockVisTiles(obj);
// instanceNames.erase(obj->instanceName);
//
// //update indices
//
// auto iter = std::next(objects.begin(), obj->id.getNum());
// iter = objects.erase(iter);
// for(int i = obj->id.getNum(); iter != objects.end(); ++i, ++iter)
// {
// (*iter)->id = ObjectInstanceID(i);
// }
//
// obj->afterRemoveFromMap(this);
//
// //TODO: Clean artifact instances (mostly worn by hero?) and quests related to this object
// //This causes crash with undo/redo in editor
//}
boost::format fmt("%s_%d");
fmt % obj->getTypeName() % uid;
obj->instanceName = fmt.str();
}
void CMap::addNewObject(CGObjectInstance * obj)
{
if(obj->id != ObjectInstanceID(static_cast<si32>(objects.size())))
throw std::runtime_error("Invalid object instance id");
if(obj->instanceName.empty())
throw std::runtime_error("Object instance name missing");
if (vstd::contains(instanceNames, obj->instanceName))
throw std::runtime_error("Object instance name duplicated: "+obj->instanceName);
objects.emplace_back(obj);
instanceNames[obj->instanceName] = obj;
addBlockVisTiles(obj);
//TODO: how about defeated heroes recruited again?
obj->afterAddToMap(this);
}
void CMap::moveObject(CGObjectInstance * obj, const int3 & pos)
{
removeBlockVisTiles(obj);
obj->setAnchorPos(pos);
addBlockVisTiles(obj);
}
void CMap::removeObject(CGObjectInstance * obj)
{
removeBlockVisTiles(obj);
instanceNames.erase(obj->instanceName);
//update indices
auto iter = std::next(objects.begin(), obj->id.getNum());
iter = objects.erase(iter);
for(int i = obj->id.getNum(); iter != objects.end(); ++i, ++iter)
{
(*iter)->id = ObjectInstanceID(i);
}
obj->afterRemoveFromMap(this);
//TODO: Clean artifact instances (mostly worn by hero?) and quests related to this object
//This causes crash with undo/redo in editor
}
//void CMap::replaceObject(ObjectInstanceID oldObjectID, const std::shared_ptr<CGObjectInstance> & newObject)
//{
// auto oldObject = objects.at(oldObjectID.getNum());
//
// newObject->id = oldObjectID;
//
// removeBlockVisTiles(oldObject.get(), true);
// instanceNames.erase(oldObject->instanceName);
//
// objects.at(oldObjectID.getNum()) = newObject;
// addBlockVisTiles(newObject.get());
// instanceNames[newObject->instanceName] = newObject;
//
// oldObject->afterRemoveFromMap(this);
// newObject->afterAddToMap(this);
//}
//
//void CMap::eraseObject(ObjectInstanceID oldObjectID)
//{
// auto oldObject = objects.at(oldObjectID.getNum());
//
// objects.at(oldObjectID) = nullptr;
// removeBlockVisTiles(oldObject.get(), true);
// oldObject->afterRemoveFromMap(this);
//}
bool CMap::isWaterMap() const
{
@ -709,7 +732,7 @@ void CMap::reindexObjects()
{
// Only reindex at editor / RMG operations
std::sort(objects.begin(), objects.end(), [](const CGObjectInstance * lhs, const CGObjectInstance * rhs)
std::sort(objects.begin(), objects.end(), [](const auto & lhs, const auto & rhs)
{
// Obstacles first, then visitable, at the end - removable

View File

@ -13,7 +13,6 @@
#include "CMapDefines.h"
#include "CMapHeader.h"
#include "../ConstTransitivePtr.h"
#include "../GameCallbackHolder.h"
#include "../networkPacks/TradeItem.h"
@ -101,11 +100,28 @@ public:
void removeQuestInstance(std::shared_ptr<CQuest> quest);
void clearQuestInstance(const CQuest * quest);
void setUniqueInstanceName(CGObjectInstance * obj);
void setUniqueInstanceName(ObjectInstanceID target){};
///Use only this method when creating new map object instances
void addNewObject(CGObjectInstance * obj);
void moveObject(CGObjectInstance * obj, const int3 & dst);
void removeObject(CGObjectInstance * obj);
void addNewObject(std::shared_ptr<CGObjectInstance> obj){}
void moveObject(ObjectInstanceID target, const int3 & dst){}
/// Remove objects and shifts object indicies.
/// Only for use in map editor / RMG
std::shared_ptr<CGObjectInstance> removeObject(ObjectInstanceID oldObject){return nullptr;}
/// Replaced map object with specified ID with new object
/// Old object must exist and will be removed from map
/// Returns pointer to old object, which can be manipulated or dropped
std::shared_ptr<CGObjectInstance> replaceObject(ObjectInstanceID oldObject, const std::shared_ptr<CGObjectInstance> & newObject){return nullptr;}
/// Erases object from map without shifting indices
/// Returns pointer to old object, which can be manipulated or dropped
std::shared_ptr<CGObjectInstance> eraseObject(ObjectInstanceID oldObject){return nullptr;}
void heroAddedToMap(const CGHeroInstance * hero) {}
void heroRemovedFromMap(const CGHeroInstance * hero) {}
void townAddedToMap(const CGTownInstance * town) {}
void townRemovedFromMap(const CGTownInstance * town) {}
bool isWaterMap() const;
bool calculateWaterContent();
@ -130,7 +146,6 @@ public:
void reindexObjects();
std::vector<Rumor> rumors;
std::vector<ConstTransitivePtr<CGHeroInstance> > predefinedHeroes;
std::set<SpellID> allowedSpells;
std::set<ArtifactID> allowedArtifact;
std::set<SecondarySkill> allowedAbilities;
@ -139,13 +154,14 @@ public:
int grailRadius;
//Central lists of items in game. Position of item in the vectors below is their (instance) id.
std::vector< ConstTransitivePtr<CGObjectInstance> > objects;
std::vector< ConstTransitivePtr<CGTownInstance> > towns;
std::vector< ConstTransitivePtr<CGHeroInstance> > allHeroes; //indexed by [hero_type_id]; on map, disposed, prisons, etc.
std::vector< std::shared_ptr<CGObjectInstance> > objects;
std::vector< std::shared_ptr<CGTownInstance> > towns;
std::vector< std::shared_ptr<CGHeroInstance> > allHeroes; //indexed by [hero_type_id]; on map, disposed, prisons, etc.
//Helper lists
std::vector< ConstTransitivePtr<CGHeroInstance> > heroesOnMap;
std::vector< std::shared_ptr<CGHeroInstance> > heroesOnMap;
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > teleportChannels;
std::vector<std::shared_ptr<CGHeroInstance> > predefinedHeroes;
/// associative list to identify which hero/creature id belongs to which object id(index for objects)
std::map<si32, ObjectInstanceID> questIdentifierToId;
@ -153,7 +169,7 @@ public:
std::unique_ptr<CMapEditManager> editManager;
boost::multi_array<int3, 3> guardingCreaturePositions;
std::map<std::string, ConstTransitivePtr<CGObjectInstance> > instanceNames;
std::map<std::string, std::shared_ptr<CGObjectInstance> > instanceNames;
bool waterMap;

View File

@ -147,15 +147,15 @@ void CMapEditManager::drawRiver(RiverId riverType, vstd::RNG* customGen)
terrainSel.clearSelection();
}
void CMapEditManager::insertObject(CGObjectInstance * obj)
void CMapEditManager::insertObject(std::shared_ptr<CGObjectInstance> obj)
{
execute(std::make_unique<CInsertObjectOperation>(map, obj));
}
void CMapEditManager::insertObjects(std::set<CGObjectInstance*>& objects)
void CMapEditManager::insertObjects(std::set<std::shared_ptr<CGObjectInstance>>& objects)
{
auto composedOperation = std::make_unique<CComposedOperation>(map);
for(auto * obj : objects)
for(auto obj : objects)
{
composedOperation->addOperation(std::make_unique<CInsertObjectOperation>(map, obj));
}
@ -172,10 +172,10 @@ void CMapEditManager::removeObject(CGObjectInstance * obj)
execute(std::make_unique<CRemoveObjectOperation>(map, obj));
}
void CMapEditManager::removeObjects(std::set<CGObjectInstance*> & objects)
void CMapEditManager::removeObjects(std::set<CGObjectInstance *> & objects)
{
auto composedOperation = std::make_unique<CComposedOperation>(map);
for(auto * obj : objects)
for(auto obj : objects)
{
composedOperation->addOperation(std::make_unique<CRemoveObjectOperation>(map, obj));
}

View File

@ -83,11 +83,11 @@ public:
/// Draws rivers at the current terrain selection. The selection will be cleared automatically.
void drawRiver(RiverId riverType, vstd::RNG * gen);
void insertObject(CGObjectInstance * obj);
void insertObjects(std::set<CGObjectInstance *> & objects);
void moveObject(CGObjectInstance * obj, const int3 & pos);
void removeObject(CGObjectInstance * obj);
void removeObjects(std::set<CGObjectInstance *> & objects);
void insertObject(std::shared_ptr<CGObjectInstance> obj);
void insertObjects(std::set<std::shared_ptr<CGObjectInstance>> & objects);
void moveObject(CGObjectInstance* obj, const int3 & pos);
void removeObject(CGObjectInstance* obj);
void removeObjects(std::set<CGObjectInstance*> & objects);
CTerrainSelection & getTerrainSelection();
CObjectSelection & getObjectSelection();

View File

@ -579,7 +579,7 @@ std::string CClearTerrainOperation::getLabel() const
return "Clear Terrain";
}
CInsertObjectOperation::CInsertObjectOperation(CMap* map, CGObjectInstance* obj)
CInsertObjectOperation::CInsertObjectOperation(CMap* map, std::shared_ptr<CGObjectInstance> obj)
: CMapOperation(map), obj(obj)
{
@ -591,7 +591,7 @@ void CInsertObjectOperation::execute()
do
{
map->setUniqueInstanceName(obj);
map->setUniqueInstanceName(obj->id);
} while(vstd::contains(map->instanceNames, obj->instanceName));
map->addNewObject(obj);
@ -599,7 +599,7 @@ void CInsertObjectOperation::execute()
void CInsertObjectOperation::undo()
{
map->removeObject(obj);
map->removeObject(obj->id);
}
void CInsertObjectOperation::redo()
@ -612,7 +612,7 @@ std::string CInsertObjectOperation::getLabel() const
return "Insert Object";
}
CMoveObjectOperation::CMoveObjectOperation(CMap* map, CGObjectInstance* obj, const int3& targetPosition)
CMoveObjectOperation::CMoveObjectOperation(CMap* map, CGObjectInstance * obj, const int3& targetPosition)
: CMapOperation(map),
obj(obj),
initialPos(obj->anchorPos()),
@ -622,12 +622,12 @@ CMoveObjectOperation::CMoveObjectOperation(CMap* map, CGObjectInstance* obj, con
void CMoveObjectOperation::execute()
{
map->moveObject(obj, targetPos);
map->moveObject(obj->id, targetPos);
}
void CMoveObjectOperation::undo()
{
map->moveObject(obj, initialPos);
map->moveObject(obj->id, initialPos);
}
void CMoveObjectOperation::redo()
@ -640,46 +640,23 @@ std::string CMoveObjectOperation::getLabel() const
return "Move Object";
}
CRemoveObjectOperation::CRemoveObjectOperation(CMap* map, CGObjectInstance* obj)
: CMapOperation(map), obj(obj)
CRemoveObjectOperation::CRemoveObjectOperation(CMap* map, CGObjectInstance * obj)
: CMapOperation(map), targetedObject(obj)
{
}
CRemoveObjectOperation::~CRemoveObjectOperation()
{
//when operation is destroyed and wasn't undone, the object is lost forever
if(!obj)
{
return;
}
//do not destroy an object that belongs to map
if(!vstd::contains(map->instanceNames, obj->instanceName))
{
delete obj;
obj = nullptr;
}
}
void CRemoveObjectOperation::execute()
{
map->removeObject(obj);
removedObject = map->removeObject(targetedObject->id);
}
void CRemoveObjectOperation::undo()
{
try
{
//set new id, but do not rename object
obj->id = ObjectInstanceID(static_cast<si32>(map->objects.size()));
map->addNewObject(obj);
}
catch(const std::exception& e)
{
logGlobal->error(e.what());
}
assert(removedObject != nullptr);
//set new id, but do not rename object
removedObject->id = ObjectInstanceID(static_cast<si32>(map->objects.size()));
map->addNewObject(removedObject);
}
void CRemoveObjectOperation::redo()

View File

@ -124,7 +124,7 @@ public:
class CInsertObjectOperation : public CMapOperation
{
public:
CInsertObjectOperation(CMap * map, CGObjectInstance * obj);
CInsertObjectOperation(CMap * map, std::shared_ptr<CGObjectInstance> obj);
void execute() override;
void undo() override;
@ -132,7 +132,7 @@ public:
std::string getLabel() const override;
private:
CGObjectInstance * obj;
std::shared_ptr<CGObjectInstance> obj;
};
/// The CMoveObjectOperation class moves object to another position
@ -157,7 +157,6 @@ class CRemoveObjectOperation : public CMapOperation
{
public:
CRemoveObjectOperation(CMap* map, CGObjectInstance * obj);
~CRemoveObjectOperation();
void execute() override;
void undo() override;
@ -165,7 +164,8 @@ public:
std::string getLabel() const override;
private:
CGObjectInstance* obj;
CGObjectInstance * targetedObject;
std::shared_ptr<CGObjectInstance> removedObject;
};
VCMI_LIB_NAMESPACE_END

View File

@ -1067,11 +1067,11 @@ void CMapLoaderH3M::readObjectTemplates()
}
}
CGObjectInstance * CMapLoaderH3M::readEvent(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readEvent(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
{
auto * object = new CGEvent(map->cb);
auto object = std::make_shared<CGEvent>(map->cb);
readBoxContent(object, mapPosition, idToBeGiven);
readBoxContent(object.get(), mapPosition, idToBeGiven);
reader->readBitmaskPlayers(object->availableFor, false);
object->computerActivate = reader->readBool();
@ -1084,20 +1084,20 @@ CGObjectInstance * CMapLoaderH3M::readEvent(const int3 & mapPosition, const Obje
else
object->humanActivate = true;
readBoxHotaContent(object, mapPosition, idToBeGiven);
readBoxHotaContent(object.get(), mapPosition, idToBeGiven);
return object;
}
CGObjectInstance * CMapLoaderH3M::readPandora(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readPandora(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven)
{
auto * object = new CGPandoraBox(map->cb);
readBoxContent(object, mapPosition, idToBeGiven);
auto object = std::make_shared<CGPandoraBox>(map->cb);
readBoxContent(object.get(), mapPosition, idToBeGiven);
if(features.levelHOTA5)
reader->skipZero(1); // Unknown value, always 0 so far
readBoxHotaContent(object, mapPosition, idToBeGiven);
readBoxHotaContent(object.get(), mapPosition, idToBeGiven);
return object;
}
@ -1179,9 +1179,9 @@ void CMapLoaderH3M::readBoxHotaContent(CGPandoraBox * object, const int3 & mapPo
}
}
CGObjectInstance * CMapLoaderH3M::readMonster(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readMonster(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
{
auto * object = new CGCreature(map->cb);
auto object = std::make_shared<CGCreature>(map->cb);
if(features.levelAB)
{
@ -1243,18 +1243,18 @@ CGObjectInstance * CMapLoaderH3M::readMonster(const int3 & mapPosition, const Ob
return object;
}
CGObjectInstance * CMapLoaderH3M::readSign(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readSign(const int3 & mapPosition)
{
auto * object = new CGSignBottle(map->cb);
auto object = std::make_shared<CGSignBottle>(map->cb);
object->message.appendTextID(readLocalizedString(TextIdentifier("sign", mapPosition.x, mapPosition.y, mapPosition.z, "message")));
reader->skipZero(4);
return object;
}
CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = readGeneric(position, objectTemplate);
auto * rewardable = dynamic_cast<CRewardableObject*>(object);
auto object = readGeneric(position, objectTemplate);
auto rewardable = std::dynamic_pointer_cast<CRewardableObject>(object);
// AB and later maps have allowed abilities defined in H3M
if(features.levelAB)
@ -1301,7 +1301,7 @@ CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::share
return object;
}
CGObjectInstance * CMapLoaderH3M::readScholar(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readScholar(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
enum class ScholarBonusType : int8_t {
RANDOM = -1,
@ -1310,8 +1310,8 @@ CGObjectInstance * CMapLoaderH3M::readScholar(const int3 & position, std::shared
SPELL = 2,
};
auto * object = readGeneric(position, objectTemplate);
auto * rewardable = dynamic_cast<CRewardableObject*>(object);
auto object = readGeneric(position, objectTemplate);
auto rewardable = std::dynamic_pointer_cast<CRewardableObject>(object);
uint8_t bonusTypeRaw = reader->readInt8Checked(-1, 2);
auto bonusType = static_cast<ScholarBonusType>(bonusTypeRaw);
@ -1369,12 +1369,12 @@ CGObjectInstance * CMapLoaderH3M::readScholar(const int3 & position, std::shared
return object;
}
CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGarrison(const int3 & mapPosition)
{
auto * object = new CGGarrison(map->cb);
auto object = std::make_shared<CGGarrison>(map->cb);
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
readCreatureSet(object, 7);
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
readCreatureSet(object.get(), 7);
if(features.levelAB)
object->removableUnits = reader->readBool();
else
@ -1384,12 +1384,12 @@ CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition)
return object;
}
CGObjectInstance * CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
ArtifactID artID = ArtifactID::NONE; //random, set later
auto * object = new CGArtifact(map->cb);
auto object = std::make_shared<CGArtifact>(map->cb);
readMessageAndGuards(object->message, object, mapPosition);
readMessageAndGuards(object->message, object.get(), mapPosition);
//specific artifact
if(objectTemplate->id == Obj::ARTIFACT)
@ -1410,21 +1410,21 @@ CGObjectInstance * CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::sh
return object;
}
CGObjectInstance * CMapLoaderH3M::readScroll(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readScroll(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = new CGArtifact(map->cb);
readMessageAndGuards(object->message, object, mapPosition);
auto object = std::make_shared<CGArtifact>(map->cb);
readMessageAndGuards(object->message, object.get(), mapPosition);
SpellID spellID = reader->readSpell32();
object->storedArtifact = map->createArtifact(ArtifactID::SPELL_SCROLL, spellID.getNum());
return object;
}
CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readResource(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = new CGResource(map->cb);
auto object = std::make_shared<CGResource>(map->cb);
readMessageAndGuards(object->message, object, mapPosition);
readMessageAndGuards(object->message, object.get(), mapPosition);
object->amount = reader->readUInt32();
@ -1440,16 +1440,16 @@ CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::sh
return object;
}
CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readMine(const int3 & mapPosition)
{
auto * object = new CGMine(map->cb);
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
auto object = std::make_shared<CGMine>(map->cb);
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
return object;
}
CGObjectInstance * CMapLoaderH3M::readAbandonedMine(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readAbandonedMine(const int3 & mapPosition)
{
auto * object = new CGMine(map->cb);
auto object = std::make_shared<CGMine>(map->cb);
object->setOwner(PlayerColor::NEUTRAL);
reader->readBitmaskResources(object->abandonedMineResources, false);
@ -1470,18 +1470,18 @@ CGObjectInstance * CMapLoaderH3M::readAbandonedMine(const int3 & mapPosition)
return object;
}
CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readDwelling(const int3 & position)
{
auto * object = new CGDwelling(map->cb);
setOwnerAndValidate(position, object, reader->readPlayer32());
auto object = std::make_shared<CGDwelling>(map->cb);
setOwnerAndValidate(position, object.get(), reader->readPlayer32());
return object;
}
CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = new CGDwelling(map->cb);
auto object = std::make_shared<CGDwelling>(map->cb);
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
object->randomizationInfo = CGDwellingRandomizationInfo();
@ -1512,10 +1512,10 @@ CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, s
return object;
}
CGObjectInstance * CMapLoaderH3M::readShrine(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readShrine(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = readGeneric(position, objectTemplate);
auto * rewardable = dynamic_cast<CRewardableObject*>(object);
auto object = readGeneric(position, objectTemplate);
auto rewardable = std::dynamic_pointer_cast<CRewardableObject>(object);
SpellID spell = reader->readSpell32();
@ -1536,11 +1536,11 @@ CGObjectInstance * CMapLoaderH3M::readShrine(const int3 & position, std::shared_
return object;
}
CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition)
{
auto * object = new CGHeroPlaceholder(map->cb);
auto object = std::make_shared<CGHeroPlaceholder>(map->cb);
setOwnerAndValidate(mapPosition, object, reader->readPlayer());
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer());
HeroTypeID htid = reader->readHero(); //hero type id
@ -1586,51 +1586,51 @@ CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition)
return object;
}
CGObjectInstance * CMapLoaderH3M::readGrail(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGrail(const int3 & mapPosition)
{
map->grailPos = mapPosition;
map->grailRadius = reader->readInt32();
return nullptr;
}
CGObjectInstance * CMapLoaderH3M::readHotaBattleLocation(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readHotaBattleLocation(const int3 & mapPosition)
{
// Battle location for arena mode in HotA
logGlobal->warn("Map '%s': Arena mode is not supported!", mapName);
return nullptr;
}
CGObjectInstance * CMapLoaderH3M::readGeneric(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readGeneric(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(LIBRARY->objtypeh->knownSubObjects(objectTemplate->id).count(objectTemplate->subid))
return LIBRARY->objtypeh->getHandlerFor(objectTemplate->id, objectTemplate->subid)->create(map->cb, objectTemplate);
logGlobal->warn("Map '%s': Unrecognized object %d:%d ('%s') at %s found!", mapName, objectTemplate->id.toEnum(), objectTemplate->subid, objectTemplate->animationFile.getOriginalName(), mapPosition.toString());
return new CGObjectInstance(map->cb);
return std::make_shared<CGObjectInstance>(map->cb);
}
CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & mapPosition)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readQuestGuard(const int3 & mapPosition)
{
auto * guard = new CGQuestGuard(map->cb);
readQuest(guard, mapPosition);
auto guard = std::make_shared<CGQuestGuard>(map->cb);
readQuest(guard.get(), mapPosition);
return guard;
}
CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = readGeneric(mapPosition, objectTemplate);
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
auto object = readGeneric(mapPosition, objectTemplate);
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
return object;
}
CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readLighthouse(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = readGeneric(mapPosition, objectTemplate);
setOwnerAndValidate(mapPosition, object, reader->readPlayer32());
auto object = readGeneric(mapPosition, objectTemplate);
setOwnerAndValidate(mapPosition, object.get(), reader->readPlayer32());
return object;
}
CGObjectInstance * CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(features.levelHOTA3)
{
@ -1669,7 +1669,7 @@ CGObjectInstance * CMapLoaderH3M::readBank(const int3 & mapPosition, std::shared
return readGeneric(mapPosition, objectTemplate);
}
CGObjectInstance * CMapLoaderH3M::readRewardWithArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readRewardWithArtifact(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(features.levelHOTA5)
{
@ -1697,7 +1697,7 @@ CGObjectInstance * CMapLoaderH3M::readRewardWithArtifact(const int3 & mapPositio
return readGeneric(mapPosition, objectTemplate);
}
CGObjectInstance * CMapLoaderH3M::readBlackMarket(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readBlackMarket(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(features.levelHOTA5)
{
@ -1718,7 +1718,7 @@ CGObjectInstance * CMapLoaderH3M::readBlackMarket(const int3 & mapPosition, std:
return readGeneric(mapPosition, objectTemplate);
}
CGObjectInstance * CMapLoaderH3M::readUniversity(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readUniversity(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(features.levelHOTA5)
{
@ -1735,7 +1735,7 @@ CGObjectInstance * CMapLoaderH3M::readUniversity(const int3 & mapPosition, std::
return readGeneric(mapPosition, objectTemplate);
}
CGObjectInstance * CMapLoaderH3M::readRewardWithArtifactAndResources(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readRewardWithArtifactAndResources(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
if(features.levelHOTA5)
{
@ -1761,7 +1761,7 @@ CGObjectInstance * CMapLoaderH3M::readRewardWithArtifactAndResources(const int3
return readGeneric(mapPosition, objectTemplate);
}
CGObjectInstance * CMapLoaderH3M::readObject(MapObjectID id, MapObjectSubID subid, std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readObject(MapObjectID id, MapObjectSubID subid, std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
{
switch(id.toEnum())
{
@ -1935,7 +1935,7 @@ void CMapLoaderH3M::readObjects()
auto originalSubID = originalTemplate->subid;
reader->skipZero(5);
CGObjectInstance * newObject = readObject(originalID, originalSubID, remappedTemplate, mapPosition, objectInstanceID);
auto newObject = readObject(originalID, originalSubID, remappedTemplate, mapPosition, objectInstanceID);
if(!newObject)
continue;
@ -1967,7 +1967,7 @@ void CMapLoaderH3M::readObjects()
std::sort(
map->heroesOnMap.begin(),
map->heroesOnMap.end(),
[](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b)
[](const std::shared_ptr<CGHeroInstance> & a, const std::shared_ptr<CGHeroInstance> & b)
{
return a->subID < b->subID;
}
@ -2037,9 +2037,9 @@ void CMapLoaderH3M::setOwnerAndValidate(const int3 & mapPosition, CGObjectInstan
object->setOwner(owner);
}
CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID)
{
auto * object = new CGHeroInstance(map->cb);
auto object = std::make_shared<CGHeroInstance>(map->cb);
if(features.levelAB)
{
@ -2057,13 +2057,12 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
if(elem->subID == object->subID)
{
logGlobal->debug("Hero %d will be taken from the predefined heroes list.", object->subID);
delete object;
object = elem;
break;
}
}
setOwnerAndValidate(mapPosition, object, owner);
setOwnerAndValidate(mapPosition, object.get(), owner);
for(auto & elem : map->disposedHeroes)
{
@ -2119,12 +2118,12 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
bool hasGarison = reader->readBool();
if(hasGarison)
readCreatureSet(object, 7);
readCreatureSet(object.get(), 7);
object->formation = static_cast<EArmyFormation>(reader->readInt8Checked(0, 1));
assert(object->formation == EArmyFormation::LOOSE || object->formation == EArmyFormation::TIGHT);
loadArtifactsOfHero(object);
loadArtifactsOfHero(object.get());
object->patrol.patrolRadius = reader->readUInt8();
object->patrol.patrolling = (object->patrol.patrolRadius != 0xff);
@ -2218,9 +2217,9 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec
return object;
}
CGObjectInstance * CMapLoaderH3M::readSeerHut(const int3 & position, const ObjectInstanceID & idToBeGiven)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readSeerHut(const int3 & position, const ObjectInstanceID & idToBeGiven)
{
auto * hut = new CGSeerHut(map->cb);
auto hut = std::make_shared<CGSeerHut>(map->cb);
uint32_t questsCount = 1;
@ -2232,7 +2231,7 @@ CGObjectInstance * CMapLoaderH3M::readSeerHut(const int3 & position, const Objec
logGlobal->warn("Map '%s': Seer Hut at %s - %d quests are not implemented!", mapName, position.toString(), questsCount);
for(size_t i = 0; i < questsCount; ++i)
readSeerHutQuest(hut, position, idToBeGiven);
readSeerHutQuest(hut.get(), position, idToBeGiven);
if(features.levelHOTA3)
{
@ -2243,7 +2242,7 @@ CGObjectInstance * CMapLoaderH3M::readSeerHut(const int3 & position, const Objec
logGlobal->warn("Map '%s': Seer Hut at %s - %d repeatable quests are not implemented!", mapName, position.toString(), repeateableQuestsCount);
for(size_t i = 0; i < repeateableQuestsCount; ++i)
readSeerHutQuest(hut, position, idToBeGiven);
readSeerHutQuest(hut.get(), position, idToBeGiven);
}
reader->skipZero(2);
@ -2506,13 +2505,13 @@ EQuestMission CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & positi
return missionId;
}
CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
std::shared_ptr<CGObjectInstance> CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate)
{
auto * object = new CGTownInstance(map->cb);
auto object = std::make_shared<CGTownInstance>(map->cb);
if(features.levelAB)
object->identifier = reader->readUInt32();
setOwnerAndValidate(position, object, reader->readPlayer());
setOwnerAndValidate(position, object.get(), reader->readPlayer());
std::optional<FactionID> faction;
if (objectTemplate->id == Obj::TOWN)
@ -2524,7 +2523,7 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
bool hasGarrison = reader->readBool();
if(hasGarrison)
readCreatureSet(object, 7);
readCreatureSet(object.get(), 7);
object->formation = static_cast<EArmyFormation>(reader->readInt8Checked(0, 1));
assert(object->formation == EArmyFormation::LOOSE || object->formation == EArmyFormation::TIGHT);

View File

@ -187,38 +187,37 @@ private:
void readObjects();
/// Reads single object from input stream based on template
CGObjectInstance * readObject(MapObjectID id, MapObjectSubID subid, std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readEvent(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readMonster(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readHero(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readSeerHut(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
CGObjectInstance * readSign(const int3 & position);
CGObjectInstance * readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readScholar(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readGarrison(const int3 & mapPosition);
CGObjectInstance * readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
CGObjectInstance * readScroll(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
CGObjectInstance * readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
CGObjectInstance * readMine(const int3 & position);
CGObjectInstance * readAbandonedMine(const int3 & position);
CGObjectInstance * readPandora(const int3 & position, const ObjectInstanceID & idToBeGiven);
CGObjectInstance * readDwelling(const int3 & position);
CGObjectInstance * readDwellingRandom(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
CGObjectInstance * readShrine(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readHeroPlaceholder(const int3 & position);
CGObjectInstance * readGrail(const int3 & position);
CGObjectInstance * readHotaBattleLocation(const int3 & position);
CGObjectInstance * readQuestGuard(const int3 & position);
CGObjectInstance * readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readLighthouse(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readGeneric(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readBank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readRewardWithArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readRewardWithArtifactAndResources(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readBlackMarket(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
CGObjectInstance * readUniversity(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readObject(MapObjectID id, MapObjectSubID subid, std::shared_ptr<const ObjectTemplate> objectTemplate, const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readEvent(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readMonster(const int3 & objectPosition, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readHero(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readSeerHut(const int3 & initialPos, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readTown(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
std::shared_ptr<CGObjectInstance> readSign(const int3 & position);
std::shared_ptr<CGObjectInstance> readWitchHut(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readScholar(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readGarrison(const int3 & mapPosition);
std::shared_ptr<CGObjectInstance> readArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
std::shared_ptr<CGObjectInstance> readScroll(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
std::shared_ptr<CGObjectInstance> readResource(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
std::shared_ptr<CGObjectInstance> readMine(const int3 & position);
std::shared_ptr<CGObjectInstance> readAbandonedMine(const int3 & position);
std::shared_ptr<CGObjectInstance> readPandora(const int3 & position, const ObjectInstanceID & idToBeGiven);
std::shared_ptr<CGObjectInstance> readDwelling(const int3 & position);
std::shared_ptr<CGObjectInstance> readDwellingRandom(const int3 & position, std::shared_ptr<const ObjectTemplate> objTempl);
std::shared_ptr<CGObjectInstance> readShrine(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readHeroPlaceholder(const int3 & position);
std::shared_ptr<CGObjectInstance> readGrail(const int3 & position);
std::shared_ptr<CGObjectInstance> readHotaBattleLocation(const int3 & position);
std::shared_ptr<CGObjectInstance> readQuestGuard(const int3 & position);
std::shared_ptr<CGObjectInstance> readShipyard(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readLighthouse(const int3 & mapPosition, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readGeneric(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readBank(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readRewardWithArtifact(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readRewardWithArtifactAndResources(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readBlackMarket(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
std::shared_ptr<CGObjectInstance> readUniversity(const int3 & position, std::shared_ptr<const ObjectTemplate> objectTemplate);
/**
* Reads a creature set.

View File

@ -1084,7 +1084,7 @@ void CMapLoaderJson::MapObjectLoader::configure()
//artifact instance serialization requires access to Map object, handle it here for now
//todo: find better solution for artifact instance serialization
if(auto * art = dynamic_cast<CGArtifact *>(instance))
if(auto art = std::dynamic_pointer_cast<CGArtifact>(instance))
{
ArtifactID artID = ArtifactID::NONE;
SpellID spellID = SpellID::NONE;
@ -1108,7 +1108,7 @@ void CMapLoaderJson::MapObjectLoader::configure()
art->storedArtifact = owner->map->createArtifact(artID, spellID.getNum());
}
if(auto * hero = dynamic_cast<CGHeroInstance *>(instance))
if(auto hero = std::dynamic_pointer_cast<CGHeroInstance>(instance))
{
auto o = handler.enterStruct("options");
hero->serializeJsonArtifacts(handler, "artifacts", owner->map);
@ -1134,7 +1134,7 @@ void CMapLoaderJson::readObjects()
for(auto & ptr : loaders)
ptr->configure();
std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const ConstTransitivePtr<CGHeroInstance> & a, const ConstTransitivePtr<CGHeroInstance> & b)
std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const std::shared_ptr<CGHeroInstance> & a, const std::shared_ptr<CGHeroInstance> & b)
{
return a->getObjTypeIndex() < b->getObjTypeIndex();
});
@ -1305,7 +1305,7 @@ void CMapSaverJson::writeObjects()
JsonSerializer handler(mapObjectResolver.get(), data);
for(CGObjectInstance * obj : map->objects)
for(const auto & obj : map->objects)
{
//logGlobal->trace("\t%s", obj->instanceName);
auto temp = handler.enterStruct(obj->instanceName);

View File

@ -180,7 +180,7 @@ public:
{
MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type & json);
CMapLoaderJson * owner;
CGObjectInstance * instance;
std::shared_ptr<CGObjectInstance> instance;
ObjectInstanceID id;
std::string jsonKey;//full id defined by map creator
JsonNode & configuration;

View File

@ -244,8 +244,8 @@ int ObstacleProxy::getWeightedObjects(const int3 & tile, vstd::RNG & rand, IGame
for(const auto & temp : shuffledObstacles)
{
auto handler = LIBRARY->objtypeh->getHandlerFor(temp->id, temp->subid);
auto * obj = handler->create(nullptr, temp);
allObjects.emplace_back(*obj);
auto obj = handler->create(nullptr, temp);
allObjects.emplace_back(obj);
rmg::Object * rmgObject = &allObjects.back();
for(const auto & offset : obj->getBlockedOffsets())
{
@ -311,12 +311,12 @@ int ObstacleProxy::getWeightedObjects(const int3 & tile, vstd::RNG & rand, IGame
return maxWeight;
}
std::set<CGObjectInstance*> ObstacleProxy::createObstacles(vstd::RNG & rand, IGameCallback * cb)
std::set<std::shared_ptr<CGObjectInstance>> ObstacleProxy::createObstacles(vstd::RNG & rand, IGameCallback * cb)
{
//reverse order, since obstacles begin in bottom-right corner, while the map coordinates begin in top-left
auto blockedTiles = blockedArea.getTilesVector();
int tilePos = 0;
std::set<CGObjectInstance*> objs;
std::set<std::shared_ptr<CGObjectInstance>> objs;
while(!blockedArea.empty() && tilePos < blockedArea.getTilesVector().size())
{
@ -356,7 +356,7 @@ std::set<CGObjectInstance*> ObstacleProxy::createObstacles(vstd::RNG & rand, IGa
//FIXME: Only editor placer obstacles directly
void ObstacleProxy::finalInsertion(CMapEditManager * manager, std::set<CGObjectInstance*> & instances)
void ObstacleProxy::finalInsertion(CMapEditManager * manager, std::set<std::shared_ptr<CGObjectInstance>> & instances)
{
manager->insertObjects(instances); //insert as one operation - for undo purposes
}
@ -366,11 +366,11 @@ std::pair<bool, bool> ObstacleProxy::verifyCoverage(const int3 & t) const
return {blockedArea.contains(t), false};
}
void ObstacleProxy::placeObject(rmg::Object & object, std::set<CGObjectInstance*> & instances)
void ObstacleProxy::placeObject(rmg::Object & object, std::set<std::shared_ptr<CGObjectInstance>> & instances)
{
for (auto * instance : object.instances())
{
instances.insert(&instance->object());
instances.insert(instance->object());
}
}
@ -384,7 +384,7 @@ bool EditorObstaclePlacer::isInTheMap(const int3& tile)
return map->isInTheMap(tile);
}
std::set<CGObjectInstance*> EditorObstaclePlacer::placeObstacles(vstd::RNG & rand)
std::set<std::shared_ptr<CGObjectInstance>> EditorObstaclePlacer::placeObstacles(vstd::RNG & rand)
{
auto obstacles = createObstacles(rand, map->cb);
finalInsertion(map->getEditManager(), obstacles);

View File

@ -41,13 +41,13 @@ public:
virtual std::pair<bool, bool> verifyCoverage(const int3 & t) const;
virtual void placeObject(rmg::Object & object, std::set<CGObjectInstance*> & instances);
virtual void placeObject(rmg::Object & object, std::set<std::shared_ptr<CGObjectInstance>> & instances);
virtual std::set<CGObjectInstance*> createObstacles(vstd::RNG & rand, IGameCallback * cb);
virtual std::set<std::shared_ptr<CGObjectInstance>> createObstacles(vstd::RNG & rand, IGameCallback * cb);
virtual bool isInTheMap(const int3& tile) = 0;
void finalInsertion(CMapEditManager * manager, std::set<CGObjectInstance*> & instances);
void finalInsertion(CMapEditManager * manager, std::set<std::shared_ptr<CGObjectInstance>> & instances);
virtual void postProcess(const rmg::Object& object) {};
@ -70,7 +70,7 @@ public:
bool isInTheMap(const int3& tile) override;
std::set<CGObjectInstance*> placeObstacles(vstd::RNG& rand);
std::set<std::shared_ptr<CGObjectInstance>> placeObstacles(vstd::RNG& rand);
private:
CMap* map;

View File

@ -992,9 +992,8 @@ void FoWChange::applyGs(CGameState *gs)
if (mode == ETileVisibility::HIDDEN) //do not hide too much
{
std::unordered_set<int3> tilesRevealed;
for (auto & elem : gs->getMap().objects)
for (auto & o : gs->getMap().objects)
{
const CGObjectInstance *o = elem;
if (o)
{
switch(o->ID.toEnum())
@ -1074,7 +1073,7 @@ void ChangeObjectVisitors::applyGs(CGameState *gs)
break;
case VISITOR_CLEAR:
// remove visit info from all heroes, including those that are not present on map
for (CGHeroInstance * hero : gs->getMap().allHeroes)
for (auto hero : gs->getMap().allHeroes)
if (hero)
hero->visitedObjects.erase(object);
@ -1119,9 +1118,9 @@ void PlayerEndsGame::applyGs(CGameState *gs)
if(p->human && gs->getStartInfo()->campState)
{
std::vector<CGHeroInstance *> crossoverHeroes;
for (CGHeroInstance * hero : gs->getMap().heroesOnMap)
for (auto hero : gs->getMap().heroesOnMap)
if (hero->tempOwner == player)
crossoverHeroes.push_back(hero);
crossoverHeroes.push_back(hero.get());
gs->getStartInfo()->campState->setCurrentMapAsConquered(crossoverHeroes);
}
@ -1203,7 +1202,7 @@ void RemoveObject::applyGs(CGameState *gs)
{
auto * beatenHero = dynamic_cast<CGHeroInstance *>(obj);
assert(beatenHero);
gs->getMap().heroesOnMap -= beatenHero;
gs->getMap().eraseObject(beatenHero->id);
auto * siegeNode = beatenHero->whereShouldBeAttachedOnSiege(gs);
@ -1237,8 +1236,7 @@ void RemoveObject::applyGs(CGameState *gs)
if(beatenHero->boat)
{
beatenHero->detachFrom(const_cast<CGBoat&>(*beatenHero->boat));
gs->getMap().instanceNames.erase(beatenHero->boat->instanceName);
gs->getMap().objects[beatenHero->boat->id.getNum()].dellNull();
gs->getMap().eraseObject(beatenHero->boat->id);
beatenHero->boat = nullptr;
}
return;
@ -1257,7 +1255,7 @@ void RemoveObject::applyGs(CGameState *gs)
}
gs->getMap().instanceNames.erase(obj->instanceName);
gs->getMap().objects[objectID.getNum()].dellNull();
gs->getMap().eraseObject(objectID);
gs->getMap().calculateGuardingGreaturePositions();//FIXME: excessive, update only affected tiles
}
@ -1445,13 +1443,14 @@ void HeroRecruited::applyGs(CGameState *gs)
h->pos = tile;
h->updateAppearance();
assert(h->id == ObjectInstanceID());
if(h->id == ObjectInstanceID())
{
h->id = ObjectInstanceID(static_cast<si32>(gs->getMap().objects.size()));
gs->getMap().objects.emplace_back(h);
}
else
gs->getMap().objects[h->id.getNum()] = h;
// else
// gs->getMap().replaceObject(h->id, h);
gs->getMap().heroesOnMap.emplace_back(h);
p->addOwnedObject(h);
@ -1499,12 +1498,11 @@ void NewObject::applyGs(CGameState *gs)
{
newObject->id = ObjectInstanceID(static_cast<si32>(gs->getMap().objects.size()));
gs->getMap().objects.emplace_back(newObject);
gs->getMap().addBlockVisTiles(newObject);
gs->getMap().addNewObject(newObject);
gs->getMap().calculateGuardingGreaturePositions();
// attach newly spawned wandering monster to global bonus system node
auto newArmy = dynamic_cast<CArmedInstance*>(newObject);
auto newArmy = std::dynamic_pointer_cast<CArmedInstance>(newObject);
if (newArmy)
newArmy->whatShouldBeAttached().attachTo(newArmy->whereShouldBeAttached(gs));
@ -1518,27 +1516,6 @@ void NewArtifact::applyGs(CGameState *gs)
pa.applyGs(gs);
}
struct ObjectRetriever
{
const CArmedInstance * operator()(const ConstTransitivePtr<CGHeroInstance> &h) const
{
return h;
}
const CArmedInstance * operator()(const ConstTransitivePtr<CStackInstance> &s) const
{
return s->armyObj;
}
};
template<typename T>
struct GetBase
{
template <typename TArg>
T * operator()(TArg &arg) const
{
return arg;
}
};
void ChangeStackCount::applyGs(CGameState *gs)
{
auto * srcObj = gs->getArmyInstance(army);
@ -1953,7 +1930,7 @@ void NewTurn::applyGs(CGameState *gs)
for(auto & creatureSet : availableCreatures) //set available creatures in towns
creatureSet.applyGs(gs);
for(CGTownInstance* t : gs->getMap().towns)
for(auto & t : gs->getMap().towns)
{
t->built = 0;
t->spellResearchCounterDay = 0;

View File

@ -806,7 +806,7 @@ struct DLL_LINKAGE NewObject : public CPackForClient
void applyGs(CGameState * gs) override;
/// Object ID to create
CGObjectInstance * newObject;
std::shared_ptr<CGObjectInstance> newObject;
/// Which player initiated creation of this object
PlayerColor initiator;

View File

@ -40,6 +40,17 @@ public:
mem.iser & ret;
return ret;
}
template <typename T>
static std::shared_ptr<T> deepCopyShared(const T &data)
{
CMemorySerializer mem;
mem.oser & &data;
std::shared_ptr<T> ret;
mem.iser & ret;
return ret;
}
};
VCMI_LIB_NAMESPACE_END

View File

@ -23,15 +23,14 @@ CSerializer::~CSerializer() = default;
void CSerializer::addStdVecItems(CGameState *gs, GameLibrary *lib)
{
registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->getMap().objects,
[](const CGObjectInstance &obj){ return obj.id; });
// registerVectoredType<CGObjectInstance, ObjectInstanceID>(&gs->getMap().objects,
// [](const CGObjectInstance &obj){ return obj.id; });
registerVectoredType<CGHeroInstance, HeroTypeID>(&gs->getMap().allHeroes,
[](const CGHeroInstance &h){ return h.getHeroType()->getId(); });
// registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->getMap().artInstances,
// [](const CArtifactInstance &artInst){ return artInst.getId(); });
// TODO
// registerVectoredType<CQuest, si32>(&gs->getMap().quests,
// [](const CQuest &q){ return q.qid; });
registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->getMap().artInstances,
[](const CArtifactInstance &artInst){ return artInst.getId(); });
registerVectoredType<CQuest, si32>(&gs->getMap().quests,
[](const CQuest &q){ return q.qid; });
smartVectorMembersSerialization = true;
}

View File

@ -9,7 +9,6 @@
*/
#pragma once
#include "../ConstTransitivePtr.h"
#include "../GameConstants.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -39,10 +38,10 @@ struct TypeComparer
template <typename ObjType, typename IdType>
struct VectorizedObjectInfo
{
const std::vector<ConstTransitivePtr<ObjType> > *vector; //pointer to the appropriate vector
const std::vector<std::shared_ptr<ObjType> > *vector; //pointer to the appropriate vector
std::function<IdType(const ObjType &)> idRetriever;
VectorizedObjectInfo(const std::vector< ConstTransitivePtr<ObjType> > *Vector, std::function<IdType(const ObjType &)> IdGetter)
VectorizedObjectInfo(const std::vector< std::shared_ptr<ObjType> > *Vector, std::function<IdType(const ObjType &)> IdGetter)
:vector(Vector), idRetriever(IdGetter)
{
}
@ -69,7 +68,7 @@ class DLL_LINKAGE CSerializer : boost::noncopyable
vectors[&typeid(T)] = VectorizedObjectInfo<T, U>(Vector, idRetriever);
}
template <typename T, typename U>
void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const std::function<U(const T&)> &idRetriever)
void registerVectoredType(const std::vector<std::shared_ptr<T> > *Vector, const std::function<U(const T&)> &idRetriever)
{
vectors[&typeid(T)] = VectorizedObjectInfo<T, U>(Vector, idRetriever);
}

View File

@ -201,11 +201,11 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
//try to find unoccupied boat to summon
const CGBoat * nearest = nullptr;
double dist = 0;
for(const CGObjectInstance * obj : env->getMap()->objects)
for(const auto & obj : env->getMap()->objects)
{
if(obj && obj->ID == Obj::BOAT)
{
const auto * b = dynamic_cast<const CGBoat *>(obj);
const auto * b = dynamic_cast<const CGBoat *>(obj.get());
if(b->hero || b->layer != EPathfindingLayer::SAIL)
continue; //we're looking for unoccupied boat
@ -726,12 +726,12 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
const auto & fowMap = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner())->fogOfWarMap;
for(const CGObjectInstance * obj : env->getMap()->objects)
for(const auto & obj : env->getMap()->objects)
{
//deleted object remain as empty pointer
if(obj && filterObject(obj, spellLevel))
if(obj && filterObject(obj.get(), spellLevel))
{
ObjectPosInfo posInfo(obj);
ObjectPosInfo posInfo(obj.get());
if(fowMap[posInfo.pos.z][posInfo.pos.x][posInfo.pos.y] == 0)
pack.objectPositions.push_back(posInfo);

View File

@ -657,7 +657,7 @@ void CGameHandler::onNewTurn()
addStatistics(gameState()->statistic); // write at end of turn
}
for (CGTownInstance *t : gs->getMap().towns)
for (const auto & t : gs->getMap().towns)
{
PlayerColor player = t->tempOwner;
@ -671,7 +671,7 @@ void CGameHandler::onNewTurn()
}
}
for (CGTownInstance *t : gs->getMap().towns)
for (const auto & t : gs->getMap().towns)
{
if (t->hasBonusOfType (BonusType::DARKNESS))
{
@ -2682,7 +2682,7 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->getTypeId());
if(dstSlot != ArtifactPosition::PRE_FIRST)
{
artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
artFittingSet.putArtifact(dstSlot, artifact);
slots.emplace_back(srcSlot, dstSlot);
// TODO Shouldn't be here. Possibly in callback after equipping the artifact
@ -3570,8 +3570,8 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
//player lost -> all his objects become unflagged (neutral)
for (auto obj : gs->getMap().objects) //unflag objs
{
if (obj.get() && obj->tempOwner == player)
setOwner(obj, PlayerColor::NEUTRAL);
if (obj && obj->tempOwner == player)
setOwner(obj.get(), PlayerColor::NEUTRAL);
}
//eliminating one player may cause victory of another:
@ -4059,11 +4059,6 @@ void CGameHandler::synchronizeArtifactHandlerLists()
sendAndApply(uahl);
}
bool CGameHandler::isValidObject(const CGObjectInstance *obj) const
{
return vstd::contains(gs->getMap().objects, obj);
}
bool CGameHandler::isBlockedByQueries(const CPackForServer *pack, PlayerColor player)
{
if (dynamic_cast<const PlayerMessage *>(pack) != nullptr)
@ -4093,7 +4088,7 @@ void CGameHandler::removeAfterVisit(const ObjectInstanceID & id)
{
if (auto someVistQuery = std::dynamic_pointer_cast<MapObjectVisitQuery>(query))
{
if(someVistQuery->visitedObject->id == id)
if (someVistQuery->visitedObject == id)
{
someVistQuery->removeObjectAfterVisit = true;
return;
@ -4154,8 +4149,8 @@ const CGHeroInstance * CGameHandler::getVisitingHero(const CGObjectInstance *obj
for(const auto & query : queries->allQueries())
{
auto visit = std::dynamic_pointer_cast<const VisitQuery>(query);
if (visit && visit->visitedObject == obj)
return visit->visitingHero;
if (visit && visit->visitedObject == obj->id)
return getHero(visit->visitingHero);
}
return nullptr;
}
@ -4167,8 +4162,8 @@ const CGObjectInstance * CGameHandler::getVisitingObject(const CGHeroInstance *h
for(const auto & query : queries->allQueries())
{
auto visit = std::dynamic_pointer_cast<const VisitQuery>(query);
if (visit && visit->visitingHero == hero)
return visit->visitedObject;
if (visit && visit->visitingHero == hero->id)
return getObjInstance(visit->visitedObject);
}
return nullptr;
}
@ -4184,7 +4179,7 @@ bool CGameHandler::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, con
if (auto topQuery = queries->topQuery(hero->getOwner()))
if (auto visit = std::dynamic_pointer_cast<const VisitQuery>(topQuery))
return !(visit->visitedObject == obj && visit->visitingHero == hero);
return !(visit->visitedObject == obj->id && visit->visitingHero == hero->id);
return true;
}
@ -4247,7 +4242,7 @@ scripting::Pool * CGameHandler::getGlobalContextPool() const
#endif
CGObjectInstance * CGameHandler::createNewObject(const int3 & visitablePosition, MapObjectID objectID, MapObjectSubID subID)
std::shared_ptr<CGObjectInstance> CGameHandler::createNewObject(const int3 & visitablePosition, MapObjectID objectID, MapObjectSubID subID)
{
TerrainId terrainType = ETerrainId::NONE;
@ -4259,8 +4254,8 @@ CGObjectInstance * CGameHandler::createNewObject(const int3 & visitablePosition,
auto handler = LIBRARY->objtypeh->getHandlerFor(objectID, subID);
CGObjectInstance * o = handler->create(gs->callback, nullptr);
handler->configureObject(o, getRandomGenerator());
auto o = handler->create(gs->callback, nullptr);
handler->configureObject(o.get(), getRandomGenerator());
assert(o->ID == objectID);
assert(!handler->getTemplates(terrainType).empty());
@ -4284,7 +4279,7 @@ void CGameHandler::createWanderingMonster(const int3 & visitablePosition, Creatu
{
auto createdObject = createNewObject(visitablePosition, Obj::MONSTER, creature);
auto * cre = dynamic_cast<CGCreature *>(createdObject);
auto cre = std::dynamic_pointer_cast<CGCreature>(createdObject);
assert(cre);
cre->notGrowingTeam = cre->neverFlees = false;
cre->character = 2;
@ -4307,7 +4302,7 @@ void CGameHandler::createHole(const int3 & visitablePosition, PlayerColor initia
newObject(createdObject, initiator);
}
void CGameHandler::newObject(CGObjectInstance * object, PlayerColor initiator)
void CGameHandler::newObject(std::shared_ptr<CGObjectInstance> object, PlayerColor initiator)
{
object->initObj(gs->getRandomGenerator());

View File

@ -87,18 +87,17 @@ public:
events::EventBus * eventBus() const override;
CVCMIServer & gameLobby() const;
bool isValidObject(const CGObjectInstance *obj) const;
bool isBlockedByQueries(const CPackForServer *pack, PlayerColor player);
bool isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
// Helpers to create new object of specified type
CGObjectInstance * createNewObject(const int3 & visitablePosition, MapObjectID objectID, MapObjectSubID subID);
std::shared_ptr<CGObjectInstance> createNewObject(const int3 & visitablePosition, MapObjectID objectID, MapObjectSubID subID);
void createWanderingMonster(const int3 & visitablePosition, CreatureID creature);
void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) override;
void createHole(const int3 & visitablePosition, PlayerColor initiator);
void newObject(CGObjectInstance * object, PlayerColor initiator);
void newObject(std::shared_ptr<CGObjectInstance> object, PlayerColor initiator);
explicit CGameHandler(CVCMIServer * lobby);
~CGameHandler();

View File

@ -507,7 +507,7 @@ RumorState NewTurnProcessor::pickNewRumor()
std::tuple<EWeekType, CreatureID> NewTurnProcessor::pickWeekType(bool newMonth)
{
for (const CGTownInstance *t : gameHandler->gameState()->getMap().towns)
for (const auto & t : gameHandler->gameState()->getMap().towns)
{
if (t->hasBuilt(BuildingID::GRAIL, ETownType::INFERNO))
return { EWeekType::DEITYOFFIRE, CreatureID::IMP };
@ -666,8 +666,8 @@ NewTurn NewTurnProcessor::generateNewTurnPack()
if (newWeek)
{
for (CGTownInstance *t : gameHandler->gameState()->getMap().towns)
n.availableCreatures.push_back(generateTownGrowth(t, n.specialWeek, n.creatureid, firstTurn));
for (const auto & t : gameHandler->gameState()->getMap().towns)
n.availableCreatures.push_back(generateTownGrowth(t.get(), n.specialWeek, n.creatureid, firstTurn));
}
if (newWeek)
@ -695,17 +695,17 @@ void NewTurnProcessor::onNewTurn()
if (newWeek)
{
for (CGTownInstance *t : gameHandler->gameState()->getMap().towns)
for (const auto & t : gameHandler->gameState()->getMap().towns)
if (t->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
gameHandler->setPortalDwelling(t, true, (n.specialWeek == EWeekType::PLAGUE ? true : false)); //set creatures for Portal of Summoning
gameHandler->setPortalDwelling(t.get(), true, (n.specialWeek == EWeekType::PLAGUE ? true : false)); //set creatures for Portal of Summoning
}
if (newWeek && !firstTurn)
{
for (CGTownInstance *t : gameHandler->gameState()->getMap().towns)
for (const auto & t : gameHandler->gameState()->getMap().towns)
{
if (!t->getOwner().isValidPlayer())
updateNeutralTownGarrison(t, 1 + gameHandler->getDate(Date::DAY) / 7);
updateNeutralTownGarrison(t.get(), 1 + gameHandler->getDate(Date::DAY) / 7);
}
}

View File

@ -10,6 +10,7 @@
#include "StdInc.h"
#include "VisitQueries.h"
#include "../../lib/gameState/CGameState.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/mapObjects/TownBuildingInstance.h"
@ -18,8 +19,8 @@
VisitQuery::VisitQuery(CGameHandler * owner, const CGObjectInstance * Obj, const CGHeroInstance * Hero)
: CQuery(owner)
, visitedObject(Obj)
, visitingHero(Hero)
, visitedObject(Obj->id)
, visitingHero(Hero->id)
{
addPlayer(Hero->tempOwner);
}
@ -33,9 +34,12 @@ bool VisitQuery::blocksPack(const CPackForServer * pack) const
void MapObjectVisitQuery::onExposure(QueryPtr topQuery)
{
auto object = gh->gameState()->getObjInstance(visitedObject);
auto hero = gh->gameState()->getHero(visitingHero);
//Object may have been removed and deleted.
if(gh->isValidObject(visitedObject))
topQuery->notifyObjectAboutRemoval(visitedObject, visitingHero);
if (object)
topQuery->notifyObjectAboutRemoval(object, hero);
owner->popIfTop(*this);
}
@ -48,11 +52,13 @@ MapObjectVisitQuery::MapObjectVisitQuery(CGameHandler * owner, const CGObjectIns
void MapObjectVisitQuery::onRemoval(PlayerColor color)
{
gh->objectVisitEnded(visitingHero, players.front());
auto hero = gh->gameState()->getHero(visitingHero);
gh->objectVisitEnded(hero, players.front());
//Can object visit affect 2 players and what would be desired behavior?
if(removeObjectAfterVisit)
gh->removeObject(visitedObject, color);
gh->removeObject(hero, color);
}
TownBuildingVisitQuery::TownBuildingVisitQuery(CGameHandler * owner, const CGTownInstance * Obj, std::vector<const CGHeroInstance *> heroes, std::vector<BuildingID> buildingToVisit)
@ -67,7 +73,10 @@ TownBuildingVisitQuery::TownBuildingVisitQuery(CGameHandler * owner, const CGTow
void TownBuildingVisitQuery::onExposure(QueryPtr topQuery)
{
topQuery->notifyObjectAboutRemoval(visitedObject, visitingHero);
auto object = gh->gameState()->getObjInstance(visitedObject);
auto hero = gh->gameState()->getHero(visitingHero);
topQuery->notifyObjectAboutRemoval(object, hero);
onAdded(players.front());
}
@ -76,9 +85,9 @@ void TownBuildingVisitQuery::onAdded(PlayerColor color)
{
while (!visitedBuilding.empty() && owner->topQuery(color).get() == this)
{
visitingHero = visitedBuilding.back().hero;
visitingHero = visitedBuilding.back().hero->id;
const auto * building = visitedTown->rewardableBuildings.at(visitedBuilding.back().building);
building->onHeroVisit(visitingHero);
building->onHeroVisit(visitedBuilding.back().hero);
visitedBuilding.pop_back();
}

View File

@ -23,8 +23,8 @@ protected:
VisitQuery(CGameHandler * owner, const CGObjectInstance * Obj, const CGHeroInstance * Hero);
public:
const CGObjectInstance * visitedObject;
const CGHeroInstance * visitingHero;
ObjectInstanceID visitedObject;
ObjectInstanceID visitingHero;
bool blocksPack(const CPackForServer * pack) const final;
};

View File

@ -226,8 +226,8 @@ TEST_F(CGameStateTest, DISABLED_issue2765)
{
startTestGame();
CGHeroInstance * attacker = map->heroesOnMap[0];
CGHeroInstance * defender = map->heroesOnMap[1];
auto attacker = map->heroesOnMap[0];
auto defender = map->heroesOnMap[1];
ASSERT_NE(attacker->tempOwner, defender->tempOwner);
@ -239,7 +239,7 @@ TEST_F(CGameStateTest, DISABLED_issue2765)
gameCallback->sendAndApply(na);
}
startTestBattle(attacker, defender);
startTestBattle(attacker.get(), defender.get());
{
battle::UnitInfo info;
@ -270,11 +270,11 @@ TEST_F(CGameStateTest, DISABLED_issue2765)
ASSERT_NE(def, nullptr);
ASSERT_NE(att, def);
EXPECT_NE(att->getMyHero(), defender);
EXPECT_NE(def->getMyHero(), attacker);
EXPECT_NE(att->getMyHero(), defender.get());
EXPECT_NE(def->getMyHero(), attacker.get());
EXPECT_EQ(att->getMyHero(), attacker) << att->nodeName();
EXPECT_EQ(def->getMyHero(), defender) << def->nodeName();
EXPECT_EQ(att->getMyHero(), attacker.get()) << att->nodeName();
EXPECT_EQ(def->getMyHero(), defender.get()) << def->nodeName();
{
using namespace ::testing;
@ -308,8 +308,8 @@ TEST_F(CGameStateTest, DISABLED_battleResurrection)
{
startTestGame();
CGHeroInstance * attacker = map->heroesOnMap[0];
CGHeroInstance * defender = map->heroesOnMap[1];
auto attacker = map->heroesOnMap[0];
auto defender = map->heroesOnMap[1];
ASSERT_NE(attacker->tempOwner, defender->tempOwner);
@ -327,7 +327,7 @@ TEST_F(CGameStateTest, DISABLED_battleResurrection)
gameCallback->sendAndApply(na);
}
startTestBattle(attacker, defender);
startTestBattle(attacker.get(), defender.get());
uint32_t unitId = gameState->currentBattles.front()->battleNextUnitId();
@ -380,7 +380,7 @@ TEST_F(CGameStateTest, DISABLED_battleResurrection)
const CSpell * spell = SpellID(SpellID::RESURRECTION).toSpell();
ASSERT_NE(spell, nullptr);
spells::BattleCast cast(gameState->currentBattles.front().get(), attacker, spells::Mode::HERO, spell);
spells::BattleCast cast(gameState->currentBattles.front().get(), attacker.get(), spells::Mode::HERO, spell);
spells::Target target;
target.emplace_back(unit);

View File

@ -232,7 +232,7 @@ void MapComparer::compareObjects()
auto actualObject = it->second;
compareObject(actualObject, expectedObject);
compareObject(actualObject.get(), expectedObject.get());
}
}
}