Browse Source

Quests in map now use shared_ptr instead of const ptr

Ivan Savenko 9 months ago
parent
commit
797646cc05

+ 1 - 0
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"

+ 1 - 0
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

+ 1 - 0
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
 {

+ 4 - 3
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<const IQuestObject *>(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;
 				}

+ 4 - 3
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<const IQuestObject *>(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;
 		}

+ 0 - 1
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

+ 1 - 1
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));
 			}

+ 1 - 0
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"

+ 2 - 1
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()

+ 3 - 3
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);
 	}

+ 14 - 3
lib/mapObjects/CQuest.h

@@ -118,14 +118,25 @@ public:
 
 class DLL_LINKAGE IQuestObject : public virtual Serializeable
 {
+	friend class CMapLoaderH3M;
+	friend class TreasurePlacer; // RMG
+	friend class Inspector; // Map editor
+
+protected:
+	std::shared_ptr<CQuest> quest;
+
 public:
-	CQuest * quest = new CQuest();
+	IQuestObject()
+		:quest(std::make_shared<CQuest>())
+	{}
 
-	///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<Component> &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const = 0;
 	virtual bool checkQuest (const CGHeroInstance * h) const;
+	const CQuest * getQuest() const
+	{
+		return quest.get();
+	}
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 0 - 1
lib/mapObjects/MapObjects.h

@@ -21,4 +21,3 @@
 #include "CGPandoraBox.h"
 #include "CRewardableObject.h"
 #include "MiscObjects.h"
-#include "CQuest.h"

+ 9 - 7
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<CQuest> quest)
 {
 	quest->qid = static_cast<si32>(quests.size());
 	quests.emplace_back(quest);
 }
 
-void CMap::removeQuestInstance(CQuest * quest)
-
+void CMap::removeQuestInstance(std::shared_ptr<CQuest> 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

+ 7 - 3
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> gameSettings;
+
+	std::vector< std::shared_ptr<CQuest> > 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<CQuest> quest);
+	void removeQuestInstance(std::shared_ptr<CQuest> 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<CGObjectInstance> > objects;
 	std::vector< ConstTransitivePtr<CGTownInstance> > towns;
 	std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances;
-	std::vector< ConstTransitivePtr<CQuest> > quests;
 	std::vector< ConstTransitivePtr<CGHeroInstance> > allHeroes; //indexed by [hero_type_id]; on map, disposed, prisons, etc.
 
 	//Helper lists

+ 1 - 0
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"

+ 1 - 1
lib/networkPacks/NetPacksLib.cpp

@@ -1247,7 +1247,7 @@ void RemoveObject::applyGs(CGameState *gs)
 	const auto * quest = dynamic_cast<const IQuestObject *>(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){

+ 1 - 1
lib/rmg/modificators/TreasurePlacer.cpp

@@ -522,7 +522,7 @@ void TreasurePlacer::addSeerHuts()
 		{
 			auto * seer = dynamic_cast<CGSeerHut *>(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);
 		};

+ 3 - 2
lib/serializer/CSerializer.cpp

@@ -29,8 +29,9 @@ void CSerializer::addStdVecItems(CGameState *gs, GameLibrary *lib)
 		[](const CGHeroInstance &h){ return h.getHeroType()->getId(); });
 	registerVectoredType<CArtifactInstance, ArtifactInstanceID>(&gs->getMap().artInstances,
 		[](const CArtifactInstance &artInst){ return artInst.getId(); });
-	registerVectoredType<CQuest, si32>(&gs->getMap().quests,
-		[](const CQuest &q){ return q.qid; });
+// TODO
+//	registerVectoredType<CQuest, si32>(&gs->getMap().quests,
+//		[](const CQuest &q){ return q.qid; });
 
 	smartVectorMembersSerialization = true;
 }

+ 8 - 8
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()

+ 1 - 0
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"