From 6165bac5163ac27a2b1076c9398389e825270b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Tue, 6 Sep 2022 17:16:34 +0200 Subject: [PATCH] Some preliminary support for object erase. But this will need a major refactor to split basic map data from in-game data. --- lib/mapObjects/CGHeroInstance.cpp | 5 +++++ lib/mapObjects/CGHeroInstance.h | 1 + lib/mapObjects/CGTownInstance.cpp | 6 ++++++ lib/mapObjects/CGTownInstance.h | 1 + lib/mapObjects/CObjectHandler.cpp | 5 +++++ lib/mapObjects/CObjectHandler.h | 1 + lib/mapObjects/MiscObjects.cpp | 3 +++ lib/mapping/CMap.cpp | 26 ++++++++++++++++---------- lib/mapping/CMap.h | 1 + 9 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 2e40ea49d..51cc432b7 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1403,6 +1403,11 @@ void CGHeroInstance::afterAddToMap(CMap * map) if(ID == Obj::HERO) map->heroesOnMap.push_back(this); } +void CGHeroInstance::afterRemoveFromMap(CMap* map) +{ + if (ID == Obj::HERO) + vstd::erase_if_present(map->heroesOnMap, this); +} void CGHeroInstance::setHeroTypeName(const std::string & identifier) { diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 4263fb818..b0c2a122c 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -268,6 +268,7 @@ public: std::string getObjectName() const override; void afterAddToMap(CMap * map) override; + void afterRemoveFromMap(CMap* map) override; void updateFrom(const JsonNode & data) override; diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 843f21326..bb320caee 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -1441,6 +1441,12 @@ void CGTownInstance::afterAddToMap(CMap * map) map->towns.push_back(this); } +void CGTownInstance::afterRemoveFromMap(CMap* map) +{ + if (ID == Obj::TOWN) + vstd::erase_if_present(map->towns, this); +} + void CGTownInstance::reset() { CGTownInstance::merchantArtifacts.clear(); diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 5a0153f9c..ae59d80d2 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -342,6 +342,7 @@ public: std::string getObjectName() const override; void afterAddToMap(CMap * map) override; + void afterRemoveFromMap(CMap* map); static void reset(); inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const diff --git a/lib/mapObjects/CObjectHandler.cpp b/lib/mapObjects/CObjectHandler.cpp index 9f5d7b1da..26597a351 100644 --- a/lib/mapObjects/CObjectHandler.cpp +++ b/lib/mapObjects/CObjectHandler.cpp @@ -385,6 +385,11 @@ void CGObjectInstance::afterAddToMap(CMap * map) //nothing here } +void CGObjectInstance::afterRemoveFromMap(CMap* map) +{ + //nothing here +} + void CGObjectInstance::serializeJsonOptions(JsonSerializeFormat & handler) { //nothing here diff --git a/lib/mapObjects/CObjectHandler.h b/lib/mapObjects/CObjectHandler.h index 851796db8..be8890b9b 100644 --- a/lib/mapObjects/CObjectHandler.h +++ b/lib/mapObjects/CObjectHandler.h @@ -197,6 +197,7 @@ public: void setProperty(ui8 what, ui32 val) override final; virtual void afterAddToMap(CMap * map); + virtual void afterRemoveFromMap(CMap* map); ///Entry point of binary (de-)serialization template void serialize(Handler &h, const int version) diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index acf6d28ae..741ad4ba9 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -1425,6 +1425,9 @@ void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) void CGArtifact::afterAddToMap(CMap * map) { + //Artifacts from map objects are never removed + //FIXME: This should be revertible in map editor + if(ID == Obj::SPELL_SCROLL && storedArtifact && storedArtifact->id.getNum() < 0) map->addNewArtifactInstance(storedArtifact); } diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 93c5fab2e..01c851a20 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -594,6 +594,7 @@ void CMap::addNewArtifactInstance(CArtifactInstance * art) void CMap::eraseArtifactInstance(CArtifactInstance * art) { + //TODO: handle for artifacts removed in map editor assert(artInstances[art->id.getNum()] == art); artInstances[art->id.getNum()].dellNull(); } @@ -604,6 +605,20 @@ void CMap::addNewQuestInstance(CQuest* quest) quests.push_back(quest); } +void CMap::removeQuestInstance(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); + iter = quests.erase(iter); + for (int i = quest->qid; iter != quests.end(); ++i, ++iter) + { + (*iter)->qid = i; + } +} + void CMap::setUniqueInstanceName(CGObjectInstance* obj) { //this gives object unique name even if objects are removed later @@ -632,7 +647,6 @@ void CMap::addNewObject(CGObjectInstance * obj) addBlockVisTiles(obj); //TODO: how about deafeated heroes recruited again? - //TODO: How about objects restored with map editor? obj->afterAddToMap(this); } @@ -657,15 +671,7 @@ void CMap::removeObject(CGObjectInstance * obj) (*iter)->id = ObjectInstanceID(i); } - auto iterTown = std::find(towns.begin(), towns.end(), obj); - if(iterTown != towns.end()) - towns.erase(iterTown); - auto iterHero = std::find(allHeroes.begin(), allHeroes.end(), obj); - if(iterHero != allHeroes.end()) - allHeroes.erase(iterHero); - iterHero = std::find(heroesOnMap.begin(), heroesOnMap.end(), obj); - if(iterHero != heroesOnMap.end()) - heroesOnMap.erase(iterHero); + obj->afterRemoveFromMap(this); //TOOD: Clean artifact instances (mostly worn by hero?) and quests related to this object } diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index dd7f8bdfe..2b93ab8a7 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -361,6 +361,7 @@ public: void eraseArtifactInstance(CArtifactInstance * art); void addNewQuestInstance(CQuest * quest); + void removeQuestInstance(CQuest* quest); void setUniqueInstanceName(CGObjectInstance* obj); ///Use only this method when creating new map object instances