diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 117fdd5eb..9abbd724b 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -15,6 +15,7 @@ #include "../../lib/UnlockGuard.h" #include "../../lib/CConfigHandler.h" #include "../../lib/mapObjects/MapObjects.h" +#include "../../lib/mapObjects/CQuest.h" #include "../../lib/mapping/CMapDefines.h" #include "../../lib/gameState/QuestInfo.h" #include "../../lib/IGameSettings.h" diff --git a/AI/Nullkiller/Goals/CompleteQuest.cpp b/AI/Nullkiller/Goals/CompleteQuest.cpp index f43e6fec3..77314215f 100644 --- a/AI/Nullkiller/Goals/CompleteQuest.cpp +++ b/AI/Nullkiller/Goals/CompleteQuest.cpp @@ -12,6 +12,7 @@ #include "../Behaviors/CaptureObjectsBehavior.h" #include "../AIGateway.h" #include "../../../lib/GameLibrary.h" +#include "../../../lib/mapObjects/CQuest.h" #include "../../../lib/texts/CGeneralTextHandler.h" namespace NKAI diff --git a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp index ab29a7177..b49c0b107 100644 --- a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp @@ -12,6 +12,7 @@ #include "QuestAction.h" #include "../../AIGateway.h" #include "../../Goals/CompleteQuest.h" +#include "../../../lib/mapObjects/CQuest.h" namespace NKAI { diff --git a/AI/Nullkiller/Pathfinding/GraphPaths.cpp b/AI/Nullkiller/Pathfinding/GraphPaths.cpp index e8d68c79b..1ff94b136 100644 --- a/AI/Nullkiller/Pathfinding/GraphPaths.cpp +++ b/AI/Nullkiller/Pathfinding/GraphPaths.cpp @@ -12,6 +12,7 @@ #include "AIPathfinderConfig.h" #include "../../../lib/CRandomGenerator.h" #include "../../../CCallback.h" +#include "../../../lib/mapObjects/CQuest.h" #include "../../../lib/mapping/CMap.h" #include "../Engine/Nullkiller.h" #include "../../../lib/logging/VisualLogger.h" @@ -82,11 +83,11 @@ void GraphPaths::calculatePaths(const CGHeroInstance * targetHero, const Nullkil || node.obj->ID == Obj::BORDER_GATE) { auto questObj = dynamic_cast(node.obj); - auto questInfo = QuestInfo(questObj->quest, node.obj, pos.coord); + auto questInfo = QuestInfo(questObj->getQuest(), node.obj, pos.coord); if(node.obj->ID == Obj::QUEST_GUARD - && questObj->quest->mission == Rewardable::Limiter{} - && questObj->quest->killTarget == ObjectInstanceID::NONE) + && questObj->getQuest()->mission == Rewardable::Limiter{} + && questObj->getQuest()->killTarget == ObjectInstanceID::NONE) { continue; } diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp index ebb482a1a..39d08ac2f 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp @@ -14,6 +14,7 @@ #include "../Actions/WhirlpoolAction.h" #include "../../Goals/Invalid.h" #include "AIPreviousNodeRule.h" +#include "../../../../lib/mapObjects/CQuest.h" #include "../../../../lib/pathfinder/PathfinderOptions.h" #include "../../../../lib/pathfinder/CPathfinder.h" @@ -165,12 +166,12 @@ namespace AIPathfinding { const AIPathNode * destinationNode = nodeStorage->getAINode(destination.node); auto questObj = dynamic_cast(destination.nodeObject); - auto questInfo = QuestInfo(questObj->quest, destination.nodeObject, destination.coord); + auto questInfo = QuestInfo(questObj->getQuest(), destination.nodeObject, destination.coord); QuestAction questAction(questInfo); if(destination.nodeObject->ID == Obj::QUEST_GUARD - && questObj->quest->mission == Rewardable::Limiter{} - && questObj->quest->killTarget == ObjectInstanceID::NONE) + && questObj->getQuest()->mission == Rewardable::Limiter{} + && questObj->getQuest()->killTarget == ObjectInstanceID::NONE) { return false; } diff --git a/AI/VCAI/Goals/CompleteQuest.h b/AI/VCAI/Goals/CompleteQuest.h index 895281f86..1b16283b2 100644 --- a/AI/VCAI/Goals/CompleteQuest.h +++ b/AI/VCAI/Goals/CompleteQuest.h @@ -10,7 +10,6 @@ #pragma once #include "CGoal.h" -#include "../../../lib/GameLibrary.h" #include "../../../lib/gameState/QuestInfo.h" namespace Goals diff --git a/AI/VCAI/Pathfinding/PathfindingManager.cpp b/AI/VCAI/Pathfinding/PathfindingManager.cpp index 34c9cc521..1398121ba 100644 --- a/AI/VCAI/Pathfinding/PathfindingManager.cpp +++ b/AI/VCAI/Pathfinding/PathfindingManager.cpp @@ -224,7 +224,7 @@ Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet if(questObj) { - auto questInfo = QuestInfo(questObj->quest, topObj, topObj->visitablePos()); + auto questInfo = QuestInfo(questObj->getQuest(), topObj, topObj->visitablePos()); return sptr(Goals::CompleteQuest(questInfo)); } diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 49ef49236..938855050 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -29,6 +29,7 @@ #include "../../lib/bonuses/Updaters.h" #include "../../lib/bonuses/Propagators.h" #include "../../lib/entities/building/CBuilding.h" +#include "../../lib/mapObjects/CQuest.h" #include "../../lib/networkPacks/PacksForClient.h" #include "../../lib/networkPacks/PacksForClientBattle.h" #include "../../lib/networkPacks/PacksForServer.h" diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index 0b41f95d0..3cab374b2 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -32,6 +32,7 @@ #include "../../CCallback.h" #include "../../lib/CConfigHandler.h" +#include "../../lib/CPlayerState.h" #include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGTownInstance.h" @@ -553,7 +554,7 @@ void AdventureMapShortcuts::moveHeroDirectional(const Point & direction) bool AdventureMapShortcuts::optionCanViewQuests() { - return optionInMapView() && !GAME->map().getMap()->quests.empty(); + return optionInMapView() && !GAME->interface()->cb->getPlayerState(GAME->interface()->playerID)->quests.empty(); } bool AdventureMapShortcuts::optionCanToggleLevel() diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index ea0407ea2..cf2acb989 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -592,7 +592,7 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const cb->setObjPropertyID(id, ObjProperty::SEERHUT_VISITED, h->getOwner()); AddQuest aq; - aq.quest = QuestInfo (quest, this, visitablePos()); + aq.quest = QuestInfo(quest.get(), this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply(aq); //TODO: merge with setObjProperty? } @@ -869,7 +869,7 @@ void CGBorderGuard::onHeroVisit(const CGHeroInstance * h) const h->showInfoDialog(18); AddQuest aq; - aq.quest = QuestInfo (quest, this, visitablePos()); + aq.quest = QuestInfo (quest.get(), this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply(aq); //TODO: add this quest only once OR check for multiple instances later @@ -894,7 +894,7 @@ void CGBorderGate::onHeroVisit(const CGHeroInstance * h) const //TODO: passabili h->showInfoDialog(18); AddQuest aq; - aq.quest = QuestInfo (quest, this, visitablePos()); + aq.quest = QuestInfo (quest.get(), this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply(aq); } diff --git a/lib/mapObjects/CQuest.h b/lib/mapObjects/CQuest.h index 903397ba9..9c1c61791 100644 --- a/lib/mapObjects/CQuest.h +++ b/lib/mapObjects/CQuest.h @@ -118,14 +118,25 @@ public: class DLL_LINKAGE IQuestObject : public virtual Serializeable { -public: - CQuest * quest = new CQuest(); + friend class CMapLoaderH3M; + friend class TreasurePlacer; // RMG + friend class Inspector; // Map editor + +protected: + std::shared_ptr quest; + +public: + IQuestObject() + :quest(std::make_shared()) + {} - ///Information about quest should remain accessible even if IQuestObject removed from map - ///All CQuest objects are freed in CMap destructor virtual ~IQuestObject() = default; virtual void getVisitText (MetaString &text, std::vector &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const = 0; virtual bool checkQuest (const CGHeroInstance * h) const; + const CQuest * getQuest() const + { + return quest.get(); + } template void serialize(Handler &h) { diff --git a/lib/mapObjects/MapObjects.h b/lib/mapObjects/MapObjects.h index 7a54592ae..1ea66d139 100644 --- a/lib/mapObjects/MapObjects.h +++ b/lib/mapObjects/MapObjects.h @@ -21,4 +21,3 @@ #include "CGPandoraBox.h" #include "CRewardableObject.h" #include "MiscObjects.h" -#include "CQuest.h" diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 2f028f369..2be449548 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -194,9 +194,6 @@ CMap::~CMap() for(auto obj : objects) obj.dellNull(); - for(auto quest : quests) - quest.dellNull(); - for(auto artInstance : artInstances) artInstance.dellNull(); @@ -527,17 +524,15 @@ void CMap::removeArtifactInstance(CArtifactSet & set, const ArtifactPosition & s art->addPlacementMap(partsMap); } -void CMap::addNewQuestInstance(CQuest* quest) +void CMap::addNewQuestInstance(std::shared_ptr quest) { quest->qid = static_cast(quests.size()); quests.emplace_back(quest); } -void CMap::removeQuestInstance(CQuest * quest) - +void CMap::removeQuestInstance(std::shared_ptr quest) { //TODO: should be called only by map editor. - //During game, completed quests or quests from removed objects stay forever //Shift indexes auto iter = std::next(quests.begin(), quest->qid); @@ -548,6 +543,13 @@ void CMap::removeQuestInstance(CQuest * quest) } } +void CMap::clearQuestInstance(const CQuest * quest) +{ + assert(quests.at(quest->qid).get() == quest); + + quests.at(quest->qid) = nullptr; +} + void CMap::setUniqueInstanceName(CGObjectInstance * obj) { //this gives object unique name even if objects are removed later diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index 80b7e6690..7d3096c0e 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -59,7 +59,11 @@ struct DLL_LINKAGE Rumor /// The map contains the map header, the tiles of the terrain, objects, heroes, towns, rumors... class DLL_LINKAGE CMap : public CMapHeader, public GameCallbackHolder { + friend class CSerializer; + std::unique_ptr gameSettings; + + std::vector< std::shared_ptr > quests; public: explicit CMap(IGameCallback *cb); ~CMap(); @@ -86,8 +90,9 @@ public: void putArtifactInstance(CArtifactSet & set, CArtifactInstance * art, const ArtifactPosition & slot); void removeArtifactInstance(CArtifactSet & set, const ArtifactPosition & slot); - void addNewQuestInstance(CQuest * quest); - void removeQuestInstance(CQuest * quest); + void addNewQuestInstance(std::shared_ptr quest); + void removeQuestInstance(std::shared_ptr quest); + void clearQuestInstance(const CQuest * quest); void setUniqueInstanceName(CGObjectInstance * obj); ///Use only this method when creating new map object instances @@ -130,7 +135,6 @@ public: std::vector< ConstTransitivePtr > objects; std::vector< ConstTransitivePtr > towns; std::vector< ConstTransitivePtr > artInstances; - std::vector< ConstTransitivePtr > quests; std::vector< ConstTransitivePtr > allHeroes; //indexed by [hero_type_id]; on map, disposed, prisons, etc. //Helper lists diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index b661c411f..ef1a7e415 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -34,6 +34,7 @@ #include "../mapObjectConstructors/CommonConstructors.h" #include "../mapObjects/CGCreature.h" #include "../mapObjects/CGResource.h" +#include "../mapObjects/CQuest.h" #include "../mapObjects/MapObjects.h" #include "../mapObjects/ObjectTemplate.h" #include "../modding/ModScope.h" diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 3ac0d954b..21e462601 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1247,7 +1247,7 @@ void RemoveObject::applyGs(CGameState *gs) const auto * quest = dynamic_cast(obj); if (quest) { - gs->getMap().quests[quest->quest->qid] = nullptr; + gs->getMap().clearQuestInstance(quest->getQuest()); for (auto &player : gs->players) { vstd::erase_if(player.second.quests, [obj](const QuestInfo & q){ diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index 67450a538..6f5c489ff 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -522,7 +522,7 @@ void TreasurePlacer::addSeerHuts() { auto * seer = dynamic_cast(obj); // Artifact can be used again - ArtifactID artid = seer->quest->mission.artifacts.front(); + ArtifactID artid = seer->getQuest()->mission.artifacts.front(); qap->addRandomArtifact(artid); qap->removeQuestArtifact(artid); }; diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index 2acba7963..f7b36b80e 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -29,8 +29,9 @@ void CSerializer::addStdVecItems(CGameState *gs, GameLibrary *lib) [](const CGHeroInstance &h){ return h.getHeroType()->getId(); }); registerVectoredType(&gs->getMap().artInstances, [](const CArtifactInstance &artInst){ return artInst.getId(); }); - registerVectoredType(&gs->getMap().quests, - [](const CQuest &q){ return q.qid; }); +// TODO +// registerVectoredType(&gs->getMap().quests, +// [](const CQuest &q){ return q.qid; }); smartVectorMembersSerialization = true; } diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index 4d2b39147..8091129ce 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -454,13 +454,13 @@ void Inspector::updateProperties(CGEvent * o) void Inspector::updateProperties(CGSeerHut * o) { - if(!o || !o->quest) return; + if(!o || !o->getQuest()) return; - addProperty(QObject::tr("First visit text"), o->quest->firstVisitText, new MessageDelegate, false); - addProperty(QObject::tr("Next visit text"), o->quest->nextVisitText, new MessageDelegate, false); - addProperty(QObject::tr("Completed text"), o->quest->completedText, new MessageDelegate, false); - addProperty(QObject::tr("Repeat quest"), o->quest->repeatedQuest, false); - addProperty(QObject::tr("Time limit"), o->quest->lastDay, false); + addProperty(QObject::tr("First visit text"), o->getQuest()->firstVisitText, new MessageDelegate, false); + addProperty(QObject::tr("Next visit text"), o->getQuest()->nextVisitText, new MessageDelegate, false); + addProperty(QObject::tr("Completed text"), o->getQuest()->completedText, new MessageDelegate, false); + addProperty(QObject::tr("Repeat quest"), o->getQuest()->repeatedQuest, false); + addProperty(QObject::tr("Time limit"), o->getQuest()->lastDay, false); { //Quest auto * delegate = new QuestDelegate(controller, *o->quest); @@ -470,10 +470,10 @@ void Inspector::updateProperties(CGSeerHut * o) void Inspector::updateProperties(CGQuestGuard * o) { - if(!o || !o->quest) return; + if(!o || !o->getQuest()) return; addProperty(QObject::tr("Reward"), PropertyEditorPlaceholder(), nullptr, true); - addProperty(QObject::tr("Repeat quest"), o->quest->repeatedQuest, true); + addProperty(QObject::tr("Repeat quest"), o->getQuest()->repeatedQuest, true); } void Inspector::updateProperties() diff --git a/mapeditor/inspector/inspector.h b/mapeditor/inspector/inspector.h index 7f78fea81..5aac96de6 100644 --- a/mapeditor/inspector/inspector.h +++ b/mapeditor/inspector/inspector.h @@ -18,6 +18,7 @@ #include "../lib/GameConstants.h" #include "../lib/mapObjects/CGCreature.h" #include "../lib/mapObjects/CGResource.h" +#include "../lib/mapObjects/CQuest.h" #include "../lib/mapObjects/MapObjects.h" #include "../lib/mapObjects/FlaggableMapObject.h" #include "../lib/mapObjects/CRewardableObject.h"