From a15366f5a525ba198a76f77cf0b0bb6d0707d5a3 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 1 Jan 2024 16:37:48 +0200 Subject: [PATCH] Make IObjectInterface::cb non-static --- AI/Nullkiller/Analyzers/ArmyManager.cpp | 2 +- .../Analyzers/DangerHitMapAnalyzer.cpp | 2 +- AI/Nullkiller/Engine/FuzzyHelper.cpp | 2 +- AI/Nullkiller/Goals/CompleteQuest.cpp | 2 +- AI/Nullkiller/Pathfinding/Actors.h | 2 +- AI/VCAI/FuzzyHelper.cpp | 2 +- AI/VCAI/Goals/CompleteQuest.cpp | 2 +- client/Client.cpp | 10 +-- client/ClientCommandManager.cpp | 4 +- client/windows/CMapOverview.cpp | 4 +- client/windows/CQuestLog.cpp | 4 +- cmake_modules/VCMI_lib.cmake | 1 + lib/GameCallbackHolder.h | 24 ++++++ lib/JsonRandom.cpp | 72 ++++++++-------- lib/JsonRandom.h | 60 ++++++++----- lib/campaign/CampaignState.cpp | 12 +-- lib/campaign/CampaignState.h | 7 +- lib/gameState/CGameState.cpp | 30 +++---- lib/gameState/CGameState.h | 5 +- lib/gameState/CGameStateCampaign.cpp | 6 +- .../AObjectTypeHandler.h | 3 +- .../CBankInstanceConstructor.cpp | 82 +++--------------- .../CBankInstanceConstructor.h | 6 +- .../CDefaultObjectTypeHandler.h | 8 +- .../CRewardableConstructor.cpp | 4 +- .../CRewardableConstructor.h | 2 +- .../CommonConstructors.cpp | 13 +-- .../CommonConstructors.h | 2 +- .../DwellingInstanceConstructor.cpp | 6 +- lib/mapObjectConstructors/IObjectInfo.h | 5 -- lib/mapObjects/CArmedInstance.cpp | 7 +- lib/mapObjects/CArmedInstance.h | 4 +- lib/mapObjects/CBank.cpp | 6 +- lib/mapObjects/CBank.h | 2 +- lib/mapObjects/CGCreature.h | 2 + lib/mapObjects/CGDwelling.cpp | 5 +- lib/mapObjects/CGDwelling.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 9 +- lib/mapObjects/CGHeroInstance.h | 4 +- lib/mapObjects/CGMarket.cpp | 6 +- lib/mapObjects/CGMarket.h | 6 +- lib/mapObjects/CGObjectInstance.cpp | 3 +- lib/mapObjects/CGObjectInstance.h | 2 +- lib/mapObjects/CGPandoraBox.cpp | 2 +- lib/mapObjects/CGPandoraBox.h | 4 + lib/mapObjects/CGTownBuilding.cpp | 27 +++++- lib/mapObjects/CGTownBuilding.h | 11 ++- lib/mapObjects/CGTownInstance.cpp | 3 +- lib/mapObjects/CGTownInstance.h | 2 +- lib/mapObjects/CQuest.cpp | 28 +++--- lib/mapObjects/CQuest.h | 23 +++-- lib/mapObjects/CRewardableObject.cpp | 3 +- lib/mapObjects/CRewardableObject.h | 2 +- lib/mapObjects/IObjectInterface.cpp | 6 +- lib/mapObjects/IObjectInterface.h | 5 +- lib/mapObjects/MiscObjects.cpp | 7 +- lib/mapObjects/MiscObjects.h | 42 ++++++++- lib/mapping/CMap.cpp | 5 +- lib/mapping/CMap.h | 5 +- lib/mapping/CMapService.cpp | 8 +- lib/mapping/CMapService.h | 13 +-- lib/mapping/MapFormatH3M.cpp | 46 +++++----- lib/mapping/MapFormatH3M.h | 2 +- lib/mapping/MapFormatJson.cpp | 22 ++--- lib/mapping/MapFormatJson.h | 2 +- lib/mapping/ObstacleProxy.cpp | 2 +- lib/networkPacks/NetPacksLib.cpp | 2 +- lib/rewardable/Info.cpp | 86 ++++++++++--------- lib/rewardable/Limiter.cpp | 6 +- lib/rmg/CMapGenerator.cpp | 4 +- lib/rmg/CMapGenerator.h | 3 +- lib/rmg/RmgMap.cpp | 4 +- lib/rmg/RmgMap.h | 2 +- lib/rmg/modificators/ConnectionsPlacer.cpp | 8 +- lib/rmg/modificators/MinePlacer.cpp | 4 +- lib/rmg/modificators/ObjectDistributor.cpp | 4 +- lib/rmg/modificators/ObjectManager.cpp | 2 +- lib/rmg/modificators/QuestArtifactPlacer.cpp | 2 +- lib/rmg/modificators/RiverPlacer.cpp | 2 +- lib/rmg/modificators/TownPlacer.cpp | 4 +- lib/rmg/modificators/TreasurePlacer.cpp | 36 ++++---- lib/rmg/modificators/WaterProxy.cpp | 6 +- lib/serializer/BinaryDeserializer.h | 23 +++-- lib/spells/ISpellMechanics.cpp | 15 +--- lib/spells/ISpellMechanics.h | 7 -- mapeditor/mainwindow.cpp | 4 +- mapeditor/mapview.cpp | 2 +- mapeditor/windownewmap.cpp | 4 +- server/CGameHandler.cpp | 5 +- 89 files changed, 502 insertions(+), 445 deletions(-) create mode 100644 lib/GameCallbackHolder.h diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 07861de89..c1827547f 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -128,7 +128,7 @@ class TemporaryArmy : public CArmedInstance public: void armyChanged() override {} TemporaryArmy() - :CArmedInstance(true) + :CArmedInstance(nullptr, true) { } }; diff --git a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp index ef8c24d17..cf61d56e4 100644 --- a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp @@ -165,7 +165,7 @@ void DangerHitMapAnalyzer::calculateTileOwners() auto addTownHero = [&](const CGTownInstance * town) { - auto townHero = new CGHeroInstance(); + auto townHero = new CGHeroInstance(nullptr); CRandomGenerator rng; auto visitablePos = town->visitablePos(); diff --git a/AI/Nullkiller/Engine/FuzzyHelper.cpp b/AI/Nullkiller/Engine/FuzzyHelper.cpp index 5252f89c3..25ca12951 100644 --- a/AI/Nullkiller/Engine/FuzzyHelper.cpp +++ b/AI/Nullkiller/Engine/FuzzyHelper.cpp @@ -30,7 +30,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) ui64 totalStrength = 0; ui8 totalChance = 0; - for(auto config : bankInfo->getPossibleGuards()) + for(auto config : bankInfo->getPossibleGuards(bank->cb)) { totalStrength += config.second.totalStrength * config.first; totalChance += config.first; diff --git a/AI/Nullkiller/Goals/CompleteQuest.cpp b/AI/Nullkiller/Goals/CompleteQuest.cpp index d0e981a78..f0db766bf 100644 --- a/AI/Nullkiller/Goals/CompleteQuest.cpp +++ b/AI/Nullkiller/Goals/CompleteQuest.cpp @@ -98,7 +98,7 @@ std::string CompleteQuest::questToString() const return "inactive quest"; MetaString ms; - q.quest->getRolloverText(ms, false); + q.quest->getRolloverText(q.obj->cb, ms, false); return ms.toString(); } diff --git a/AI/Nullkiller/Pathfinding/Actors.h b/AI/Nullkiller/Pathfinding/Actors.h index eef4bee39..505f7995b 100644 --- a/AI/Nullkiller/Pathfinding/Actors.h +++ b/AI/Nullkiller/Pathfinding/Actors.h @@ -31,7 +31,7 @@ public: virtual bool needsLastStack() const override; std::shared_ptr getActorAction() const; - HeroExchangeArmy(): CArmedInstance(true), requireBuyArmy(false) {} + HeroExchangeArmy(): CArmedInstance(nullptr, true), requireBuyArmy(false) {} }; struct ExchangeResult diff --git a/AI/VCAI/FuzzyHelper.cpp b/AI/VCAI/FuzzyHelper.cpp index a47cbafa0..776c3b98f 100644 --- a/AI/VCAI/FuzzyHelper.cpp +++ b/AI/VCAI/FuzzyHelper.cpp @@ -72,7 +72,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) ui64 totalStrength = 0; ui8 totalChance = 0; - for(auto config : bankInfo->getPossibleGuards()) + for(auto config : bankInfo->getPossibleGuards(bank->cb)) { totalStrength += config.second.totalStrength * config.first; totalChance += config.first; diff --git a/AI/VCAI/Goals/CompleteQuest.cpp b/AI/VCAI/Goals/CompleteQuest.cpp index cb78ee8db..976b029c5 100644 --- a/AI/VCAI/Goals/CompleteQuest.cpp +++ b/AI/VCAI/Goals/CompleteQuest.cpp @@ -103,7 +103,7 @@ std::string CompleteQuest::questToString() const return "inactive quest"; MetaString ms; - q.quest->getRolloverText(ms, false); + q.quest->getRolloverText(q.obj->cb, ms, false); return ms.toString(); } diff --git a/client/Client.cpp b/client/Client.cpp index f34c8f6cc..e78f96c03 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -139,14 +139,10 @@ CClient::CClient() waitingRequest.clear(); applier = std::make_shared>(); registerTypesClientPacks(*applier); - IObjectInterface::cb = this; gs = nullptr; } -CClient::~CClient() -{ - IObjectInterface::cb = nullptr; -} +CClient::~CClient() = default; const Services * CClient::services() const { @@ -178,7 +174,7 @@ void CClient::newGame(CGameState * initializedGameState) CSH->th->update(); CMapService mapService; gs = initializedGameState ? initializedGameState : new CGameState(); - gs->preInit(VLC); + gs->preInit(VLC, this); logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); if(!initializedGameState) { @@ -200,7 +196,7 @@ void CClient::loadGame(CGameState * initializedGameState) logNetwork->info("Game state was transferred over network, loading."); gs = initializedGameState; - gs->preInit(VLC); + gs->preInit(VLC, this); gs->updateOnLoad(CSH->si.get()); logNetwork->info("Game loaded, initialize interfaces."); diff --git a/client/ClientCommandManager.cpp b/client/ClientCommandManager.cpp index a4878dccf..7007733c4 100644 --- a/client/ClientCommandManager.cpp +++ b/client/ClientCommandManager.cpp @@ -203,7 +203,7 @@ void ClientCommandManager::handleConvertTextCommand() try { // load and drop loaded map - we only need loader to run over all maps - mapService.loadMap(mapName); + mapService.loadMap(mapName, nullptr); } catch(std::exception & e) { @@ -216,7 +216,7 @@ void ClientCommandManager::handleConvertTextCommand() { auto state = CampaignHandler::getCampaign(campaignName.getName()); for (auto const & part : state->allScenarios()) - state->getMap(part); + state->getMap(part, nullptr); } VLC->generaltexth->dumpAllTexts(); diff --git a/client/windows/CMapOverview.cpp b/client/windows/CMapOverview.cpp index e9cec639f..68a96bc3a 100644 --- a/client/windows/CMapOverview.cpp +++ b/client/windows/CMapOverview.cpp @@ -104,7 +104,7 @@ std::vector CMapOverviewWidget::createMinimaps(ResourcePath resource) co std::unique_ptr map; try { - map = mapService.loadMap(resource); + map = mapService.loadMap(resource, nullptr); } catch (const std::exception & e) { @@ -169,7 +169,7 @@ CMapOverviewWidget::CMapOverviewWidget(CMapOverview& parent): lf >> *(mapHeader) >> startInfo; if(startInfo->campState) - campaignMap = startInfo->campState->getMap(*startInfo->campState->currentScenario()); + campaignMap = startInfo->campState->getMap(*startInfo->campState->currentScenario(), nullptr); res = ResourcePath(startInfo->fileURI, EResType::MAP); } if(!campaignMap) diff --git a/client/windows/CQuestLog.cpp b/client/windows/CQuestLog.cpp index cd6480d8e..b6a53430f 100644 --- a/client/windows/CQuestLog.cpp +++ b/client/windows/CQuestLog.cpp @@ -160,7 +160,7 @@ void CQuestLog::recreateLabelList() } MetaString text; - quests[i].quest->getRolloverText (text, false); + quests[i].quest->getRolloverText (quests[i].obj->cb, text, false); if (quests[i].obj) { if (auto seersHut = dynamic_cast(quests[i].obj)) @@ -236,7 +236,7 @@ void CQuestLog::selectQuest(int which, int labelId) MetaString text; std::vector components; - currentQuest->quest->getVisitText(text, components, true); + currentQuest->quest->getVisitText(currentQuest->obj->cb, text, components, true); if(description->slider) description->slider->scrollToMin(); // scroll text to start position description->setText(text.toString()); //TODO: use special log entry text diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 2709974d3..62172e968 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -619,6 +619,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/CThreadHelper.h ${MAIN_LIB_DIR}/CTownHandler.h ${MAIN_LIB_DIR}/FunctionList.h + ${MAIN_LIB_DIR}/GameCallbackHolder.h ${MAIN_LIB_DIR}/GameConstants.h ${MAIN_LIB_DIR}/GameSettings.h ${MAIN_LIB_DIR}/IBonusTypeHandler.h diff --git a/lib/GameCallbackHolder.h b/lib/GameCallbackHolder.h new file mode 100644 index 000000000..1fb5312f2 --- /dev/null +++ b/lib/GameCallbackHolder.h @@ -0,0 +1,24 @@ +/* + * GameCallbackHolder.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 + +VCMI_LIB_NAMESPACE_BEGIN + +class IGameCallback; + +class DLL_LINKAGE GameCallbackHolder +{ +public: + IGameCallback * const cb; + + GameCallbackHolder(IGameCallback *cb): + cb(cb) + {} +}; diff --git a/lib/JsonRandom.cpp b/lib/JsonRandom.cpp index 1044cf08c..7a35d7bb7 100644 --- a/lib/JsonRandom.cpp +++ b/lib/JsonRandom.cpp @@ -31,9 +31,7 @@ VCMI_LIB_NAMESPACE_BEGIN -namespace JsonRandom -{ - si32 loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue) + si32 JsonRandom::loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue) { if (value.empty() || value[0] != '@') { @@ -51,7 +49,7 @@ namespace JsonRandom return variables.at(variableID); } - si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue) + si32 JsonRandom::loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue) { if(value.isNull()) return defaultValue; @@ -79,7 +77,7 @@ namespace JsonRandom } template - IdentifierType decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) + IdentifierType JsonRandom::decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) { if (value.empty() || value[0] != '@') return IdentifierType(*VLC->identifiers()->getIdentifier(modScope, IdentifierType::entityType(), value)); @@ -88,7 +86,7 @@ namespace JsonRandom } template - IdentifierType decodeKey(const JsonNode & value, const Variables & variables) + IdentifierType JsonRandom::decodeKey(const JsonNode & value, const Variables & variables) { if (value.String().empty() || value.String()[0] != '@') return IdentifierType(*VLC->identifiers()->getIdentifier(IdentifierType::entityType(), value)); @@ -97,19 +95,19 @@ namespace JsonRandom } template<> - PlayerColor decodeKey(const JsonNode & value, const Variables & variables) + PlayerColor JsonRandom::decodeKey(const JsonNode & value, const Variables & variables) { return PlayerColor(*VLC->identifiers()->getIdentifier("playerColor", value)); } template<> - PrimarySkill decodeKey(const JsonNode & value, const Variables & variables) + PrimarySkill JsonRandom::decodeKey(const JsonNode & value, const Variables & variables) { return PrimarySkill(*VLC->identifiers()->getIdentifier("primarySkill", value)); } template<> - PrimarySkill decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) + PrimarySkill JsonRandom::decodeKey(const std::string & modScope, const std::string & value, const Variables & variables) { if (value.empty() || value[0] != '@') return PrimarySkill(*VLC->identifiers()->getIdentifier(modScope, "primarySkill", value)); @@ -120,13 +118,13 @@ namespace JsonRandom /// Method that allows type-specific object filtering /// Default implementation is to accept all input objects template - std::set filterKeysTyped(const JsonNode & value, const std::set & valuesSet) + std::set JsonRandom::filterKeysTyped(const JsonNode & value, const std::set & valuesSet) { return valuesSet; } template<> - std::set filterKeysTyped(const JsonNode & value, const std::set & valuesSet) + std::set JsonRandom::filterKeysTyped(const JsonNode & value, const std::set & valuesSet) { assert(value.isStruct()); @@ -164,7 +162,7 @@ namespace JsonRandom if(!allowedClasses.empty() && !allowedClasses.count(art->aClass)) continue; - if(!IObjectInterface::cb->isAllowed(art->getId())) + if(!cb->isAllowed(art->getId())) continue; if(!allowedPositions.empty()) @@ -186,7 +184,7 @@ namespace JsonRandom } template<> - std::set filterKeysTyped(const JsonNode & value, const std::set & valuesSet) + std::set JsonRandom::filterKeysTyped(const JsonNode & value, const std::set & valuesSet) { std::set result = valuesSet; @@ -213,7 +211,7 @@ namespace JsonRandom } template - std::set filterKeys(const JsonNode & value, const std::set & valuesSet, const Variables & variables) + std::set JsonRandom::filterKeys(const JsonNode & value, const std::set & valuesSet, const Variables & variables) { if(value.isString()) return { decodeKey(value, variables) }; @@ -257,7 +255,7 @@ namespace JsonRandom return valuesSet; } - TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + TResources JsonRandom::loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { TResources ret; @@ -275,7 +273,7 @@ namespace JsonRandom return ret; } - TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + TResources JsonRandom::loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::set defaultResources{ GameResID::WOOD, @@ -296,7 +294,7 @@ namespace JsonRandom return ret; } - PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + PrimarySkill JsonRandom::loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::set defaultSkills{ PrimarySkill::ATTACK, @@ -308,7 +306,7 @@ namespace JsonRandom return *RandomGeneratorUtil::nextItem(potentialPicks, rng); } - std::vector loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::vector JsonRandom::loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::vector ret(GameConstants::PRIMARY_SKILLS, 0); std::set defaultSkills{ @@ -340,18 +338,18 @@ namespace JsonRandom return ret; } - SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + SecondarySkill JsonRandom::loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::set defaultSkills; for(const auto & skill : VLC->skillh->objects) - if (IObjectInterface::cb->isAllowed(skill->getId())) + if (cb->isAllowed(skill->getId())) defaultSkills.insert(skill->getId()); std::set potentialPicks = filterKeys(value, defaultSkills, variables); return *RandomGeneratorUtil::nextItem(potentialPicks, rng); } - std::map loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::map JsonRandom::loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::map ret; if(value.isStruct()) @@ -366,7 +364,7 @@ namespace JsonRandom { std::set defaultSkills; for(const auto & skill : VLC->skillh->objects) - if (IObjectInterface::cb->isAllowed(skill->getId())) + if (cb->isAllowed(skill->getId())) defaultSkills.insert(skill->getId()); for(const auto & element : value.Vector()) @@ -381,19 +379,19 @@ namespace JsonRandom return ret; } - ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + ArtifactID JsonRandom::loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::set allowedArts; for(const auto & artifact : VLC->arth->objects) - if (IObjectInterface::cb->isAllowed(artifact->getId()) && VLC->arth->legalArtifact(artifact->getId())) + if (cb->isAllowed(artifact->getId()) && VLC->arth->legalArtifact(artifact->getId())) allowedArts.insert(artifact->getId()); std::set potentialPicks = filterKeys(value, allowedArts, variables); - return IObjectInterface::cb->gameState()->pickRandomArtifact(rng, potentialPicks); + return cb->gameState()->pickRandomArtifact(rng, potentialPicks); } - std::vector loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::vector JsonRandom::loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::vector ret; for (const JsonNode & entry : value.Vector()) @@ -403,11 +401,11 @@ namespace JsonRandom return ret; } - SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + SpellID JsonRandom::loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::set defaultSpells; for(const auto & spell : VLC->spellh->objects) - if (IObjectInterface::cb->isAllowed(spell->getId()) && !spell->isSpecial()) + if (cb->isAllowed(spell->getId()) && !spell->isSpecial()) defaultSpells.insert(spell->getId()); std::set potentialPicks = filterKeys(value, defaultSpells, variables); @@ -420,7 +418,7 @@ namespace JsonRandom return *RandomGeneratorUtil::nextItem(potentialPicks, rng); } - std::vector loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::vector JsonRandom::loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::vector ret; for (const JsonNode & entry : value.Vector()) @@ -430,7 +428,7 @@ namespace JsonRandom return ret; } - std::vector loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::vector JsonRandom::loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::vector ret; std::set defaultPlayers; @@ -446,7 +444,7 @@ namespace JsonRandom return ret; } - std::vector loadHeroes(const JsonNode & value, CRandomGenerator & rng) + std::vector JsonRandom::loadHeroes(const JsonNode & value, CRandomGenerator & rng) { std::vector ret; for(auto & entry : value.Vector()) @@ -456,7 +454,7 @@ namespace JsonRandom return ret; } - std::vector loadHeroClasses(const JsonNode & value, CRandomGenerator & rng) + std::vector JsonRandom::loadHeroClasses(const JsonNode & value, CRandomGenerator & rng) { std::vector ret; for(auto & entry : value.Vector()) @@ -466,7 +464,7 @@ namespace JsonRandom return ret; } - CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + CStackBasicDescriptor JsonRandom::loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { CStackBasicDescriptor stack; @@ -495,7 +493,7 @@ namespace JsonRandom return stack; } - std::vector loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) + std::vector JsonRandom::loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables) { std::vector ret; for (const JsonNode & node : value.Vector()) @@ -505,7 +503,7 @@ namespace JsonRandom return ret; } - std::vector evaluateCreatures(const JsonNode & value, const Variables & variables) + std::vector JsonRandom::evaluateCreatures(const JsonNode & value, const Variables & variables) { std::vector ret; for (const JsonNode & node : value.Vector()) @@ -532,7 +530,7 @@ namespace JsonRandom return ret; } - std::vector DLL_LINKAGE loadBonuses(const JsonNode & value) + std::vector JsonRandom::loadBonuses(const JsonNode & value) { std::vector ret; for (const JsonNode & entry : value.Vector()) @@ -543,6 +541,4 @@ namespace JsonRandom return ret; } -} - VCMI_LIB_NAMESPACE_END diff --git a/lib/JsonRandom.h b/lib/JsonRandom.h index 804c87e3e..613350941 100644 --- a/lib/JsonRandom.h +++ b/lib/JsonRandom.h @@ -11,6 +11,7 @@ #include "GameConstants.h" #include "ResourceSet.h" +#include "GameCallbackHolder.h" VCMI_LIB_NAMESPACE_BEGIN @@ -22,10 +23,29 @@ struct Bonus; struct Component; class CStackBasicDescriptor; -namespace JsonRandom +class DLL_LINKAGE JsonRandom : public GameCallbackHolder { +public: using Variables = std::map; +private: + template + std::set filterKeys(const JsonNode & value, const std::set & valuesSet, const Variables & variables); + + template + std::set filterKeysTyped(const JsonNode & value, const std::set & valuesSet); + + template + IdentifierType decodeKey(const std::string & modScope, const std::string & value, const Variables & variables); + + template + IdentifierType decodeKey(const JsonNode & value, const Variables & variables); + + si32 loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue); + +public: + using GameCallbackHolder::GameCallbackHolder; + struct DLL_LINKAGE RandomStackInfo { std::vector allowedCreatures; @@ -33,30 +53,30 @@ namespace JsonRandom si32 maxAmount; }; - DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue = 0); + si32 loadValue(const JsonNode & value, CRandomGenerator & rng, const Variables & variables, si32 defaultValue = 0); - DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::map loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + TResources loadResources(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + TResources loadResource(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + PrimarySkill loadPrimary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector loadPrimaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + SecondarySkill loadSecondary(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::map loadSecondaries(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector loadArtifacts(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector loadSpells(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector evaluateCreatures(const JsonNode & value, const Variables & variables); + CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector loadCreatures(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector evaluateCreatures(const JsonNode & value, const Variables & variables); - DLL_LINKAGE std::vector loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); - DLL_LINKAGE std::vector loadHeroes(const JsonNode & value, CRandomGenerator & rng); - DLL_LINKAGE std::vector loadHeroClasses(const JsonNode & value, CRandomGenerator & rng); + std::vector loadColors(const JsonNode & value, CRandomGenerator & rng, const Variables & variables); + std::vector loadHeroes(const JsonNode & value, CRandomGenerator & rng); + std::vector loadHeroClasses(const JsonNode & value, CRandomGenerator & rng); - DLL_LINKAGE std::vector loadBonuses(const JsonNode & value); -} + static std::vector loadBonuses(const JsonNode & value); +}; VCMI_LIB_NAMESPACE_END diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index 98623a509..65468b42e 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -224,7 +224,7 @@ std::set CampaignState::getReservedHeroes() const const CGHeroInstance * CampaignState::strongestHero(CampaignScenarioID scenarioId, const PlayerColor & owner) const { - std::function isOwned = [owner](const JsonNode & node) + std::function isOwned = [&](const JsonNode & node) { auto * h = CampaignState::crossoverDeserialize(node, nullptr); bool result = h->tempOwner == owner; @@ -316,7 +316,7 @@ std::optional CampaignState::getBonusID(CampaignScenarioID which) const return chosenCampaignBonuses.at(which); } -std::unique_ptr CampaignState::getMap(CampaignScenarioID scenarioId) const +std::unique_ptr CampaignState::getMap(CampaignScenarioID scenarioId, IGameCallback * cb) const { // FIXME: there is certainly better way to handle maps inside campaigns if(scenarioId == CampaignScenarioID::NONE) @@ -327,7 +327,7 @@ std::unique_ptr CampaignState::getMap(CampaignScenarioID scenarioId) const boost::to_lower(scenarioName); scenarioName += ':' + std::to_string(scenarioId.getNum()); const auto & mapContent = mapPieces.find(scenarioId)->second; - return mapService.loadMap(mapContent.data(), mapContent.size(), scenarioName, getModName(), getEncoding()); + return mapService.loadMap(mapContent.data(), mapContent.size(), scenarioName, getModName(), getEncoding(), cb); } std::unique_ptr CampaignState::getMapHeader(CampaignScenarioID scenarioId) const @@ -355,7 +355,7 @@ std::shared_ptr CampaignState::getMapInfo(CampaignScenarioID scenarioI return mapInfo; } -JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) +JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) const { JsonNode node; JsonSerializer handler(nullptr, node); @@ -363,10 +363,10 @@ JsonNode CampaignState::crossoverSerialize(CGHeroInstance * hero) return node; } -CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) +CGHeroInstance * CampaignState::crossoverDeserialize(const JsonNode & node, CMap * map) const { JsonDeserializer handler(nullptr, const_cast(node)); - auto * hero = new CGHeroInstance(); + auto * hero = new CGHeroInstance(map->cb); hero->ID = Obj::HERO; hero->serializeJsonOptions(handler); if (map) diff --git a/lib/campaign/CampaignState.h b/lib/campaign/CampaignState.h index f9e52e756..a1181a337 100644 --- a/lib/campaign/CampaignState.h +++ b/lib/campaign/CampaignState.h @@ -27,6 +27,7 @@ class CMapHeader; class CMapInfo; class JsonNode; class Point; +class IGameCallback; class DLL_LINKAGE CampaignRegions { @@ -277,7 +278,7 @@ public: /// Returns true if all available scenarios have been completed and campaign is finished bool isCampaignFinished() const; - std::unique_ptr getMap(CampaignScenarioID scenarioId) const; + std::unique_ptr getMap(CampaignScenarioID scenarioId, IGameCallback * cb) const; std::unique_ptr getMapHeader(CampaignScenarioID scenarioId) const; std::shared_ptr getMapInfo(CampaignScenarioID scenarioId) const; @@ -298,8 +299,8 @@ public: /// May return empty JsonNode if such hero was not found const JsonNode & getHeroByType(HeroTypeID heroID) const; - static JsonNode crossoverSerialize(CGHeroInstance * hero); - static CGHeroInstance * crossoverDeserialize(const JsonNode & node, CMap * map); + JsonNode crossoverSerialize(CGHeroInstance * hero) const; + CGHeroInstance * crossoverDeserialize(const JsonNode & node, CMap * map) const; std::string campaignSet; diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 5529df727..8ebd2885d 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -169,14 +169,16 @@ CGameState::~CGameState() initialOpts.dellNull(); } -void CGameState::preInit(Services * services) +void CGameState::preInit(Services * services, IGameCallback * callback) { this->services = services; + this->callback = callback; } void CGameState::init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap) { - preInitAuto(); + assert(services); + assert(callback); logGlobal->info("\tUsing random seed: %d", si->seedToBeUsed); getRandomGenerator().setSeed(si->seedToBeUsed); scenarioOps = CMemorySerializer::deepCopy(*si).release(); @@ -284,21 +286,13 @@ void CGameState::updateEntity(Metatype metatype, int32_t index, const JsonNode & void CGameState::updateOnLoad(StartInfo * si) { - preInitAuto(); + assert(services); + assert(callback); scenarioOps->playerInfos = si->playerInfos; for(auto & i : si->playerInfos) gs->players[i.first].human = i.second.isControlledByHuman(); } -void CGameState::preInitAuto() -{ - if(services == nullptr) - { - logGlobal->error("Game state preinit missing"); - preInit(VLC); - } -} - void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking) { if(scenarioOps->createRandomMap()) @@ -307,7 +301,7 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan CStopWatch sw; // Gen map - CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, scenarioOps->seedToBeUsed); + CMapGenerator mapGenerator(*scenarioOps->mapGenOptions, callback, scenarioOps->seedToBeUsed); progressTracking.include(mapGenerator); std::unique_ptr randomMap = mapGenerator.generate(); @@ -370,7 +364,7 @@ void CGameState::initNewGame(const IMapService * mapService, bool allowSavingRan { logGlobal->info("Open map file: %s", scenarioOps->mapname); const ResourcePath mapURI(scenarioOps->mapname, EResType::MAP); - map = mapService->loadMap(mapURI).release(); + map = mapService->loadMap(mapURI, callback).release(); } } @@ -561,7 +555,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy } auto handler = VLC->objtypeh->getHandlerFor(Obj::HERO, heroTypeId.toHeroType()->heroClass->getIndex()); - CGObjectInstance * obj = handler->create(handler->getTemplates().front()); + CGObjectInstance * obj = handler->create(callback, handler->getTemplates().front()); CGHeroInstance * hero = dynamic_cast(obj); hero->ID = Obj::HERO; @@ -635,7 +629,7 @@ void CGameState::initHeroes() if (tile.terType->isWater()) { auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum()); - CGBoat * boat = dynamic_cast(handler->create()); + CGBoat * boat = dynamic_cast(handler->create(callback, nullptr)); handler->configureObject(boat, gs->getRandomGenerator()); boat->pos = hero->pos; @@ -673,7 +667,7 @@ void CGameState::initHeroes() for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool { - auto * vhi = new CGHeroInstance(); + auto * vhi = new CGHeroInstance(callback); vhi->initHero(getRandomGenerator(), htype); int typeID = htype.getNum(); @@ -936,7 +930,7 @@ void CGameState::initMapObjects() } } } - CGSubterraneanGate::postInit(); //pairing subterranean gates + CGSubterraneanGate::postInit(callback); //pairing subterranean gates map->calculateGuardingGreaturePositions(); //calculate once again when all the guards are placed and initialized } diff --git a/lib/gameState/CGameState.h b/lib/gameState/CGameState.h index a3cd40ff1..b1f4eb74e 100644 --- a/lib/gameState/CGameState.h +++ b/lib/gameState/CGameState.h @@ -97,10 +97,12 @@ public: /// list of players currently making turn. Usually - just one, except for simturns std::set actingPlayers; + IGameCallback * callback; + CGameState(); virtual ~CGameState(); - void preInit(Services * services); + void preInit(Services * services, IGameCallback * callback); void init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator &, bool allowSavingRandomMap = true); void updateOnLoad(StartInfo * si); @@ -193,7 +195,6 @@ public: private: // ----- initialization ----- - void preInitAuto(); void initNewGame(const IMapService * mapService, bool allowSavingRandomMap, Load::ProgressAccumulator & progressTracking); void checkMapChecksum(); void initGlobalBonuses(); diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index e93b53b13..f7614751d 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -402,7 +402,7 @@ std::vector CGameStateCampaign::generateCampaignHeroesT continue; } - CGHeroInstance * hero = CampaignState::crossoverDeserialize(node, gameState->map); + CGHeroInstance * hero = campaignState->crossoverDeserialize(node, gameState->map); logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated()); @@ -427,7 +427,7 @@ std::vector CGameStateCampaign::generateCampaignHeroesT if (nodeListIter == nodeList.end()) break; - CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map); + CGHeroInstance * hero = campaignState->crossoverDeserialize(*nodeListIter, gameState->map); nodeListIter++; logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated()); @@ -599,7 +599,7 @@ bool CGameStateCampaign::playerHasStartingHero(PlayerColor playerColor) const std::unique_ptr CGameStateCampaign::getCurrentMap() const { - return gameState->scenarioOps->campState->getMap(CampaignScenarioID::NONE); + return gameState->scenarioOps->campState->getMap(CampaignScenarioID::NONE, gameState->callback); } VCMI_LIB_NAMESPACE_END diff --git a/lib/mapObjectConstructors/AObjectTypeHandler.h b/lib/mapObjectConstructors/AObjectTypeHandler.h index 863f0e7fb..4222ff29d 100644 --- a/lib/mapObjectConstructors/AObjectTypeHandler.h +++ b/lib/mapObjectConstructors/AObjectTypeHandler.h @@ -19,6 +19,7 @@ class ObjectTemplate; class CGObjectInstance; class CRandomGenerator; class IObjectInfo; +class IGameCallback; /// Class responsible for creation of objects of specific type & subtype class DLL_LINKAGE AObjectTypeHandler : public boost::noncopyable @@ -109,7 +110,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(std::shared_ptr tmpl = nullptr) const = 0; + virtual CGObjectInstance * create(IGameCallback * cb, std::shared_ptr 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 diff --git a/lib/mapObjectConstructors/CBankInstanceConstructor.cpp b/lib/mapObjectConstructors/CBankInstanceConstructor.cpp index f61641a85..e2a4c3b03 100644 --- a/lib/mapObjectConstructors/CBankInstanceConstructor.cpp +++ b/lib/mapObjectConstructors/CBankInstanceConstructor.cpp @@ -37,15 +37,16 @@ void CBankInstanceConstructor::initTypeData(const JsonNode & input) BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const { BankConfig bc; + JsonRandom randomizer(nullptr); JsonRandom::Variables emptyVariables; bc.chance = static_cast(level["chance"].Float()); - bc.guards = JsonRandom::loadCreatures(level["guards"], rng, emptyVariables); + bc.guards = randomizer.loadCreatures(level["guards"], rng, emptyVariables); bc.resources = ResourceSet(level["reward"]["resources"]); - bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng, emptyVariables); - bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng, emptyVariables); - bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, emptyVariables); + bc.creatures = randomizer.loadCreatures(level["reward"]["creatures"], rng, emptyVariables); + bc.artifacts = randomizer.loadArtifacts(level["reward"]["artifacts"], rng, emptyVariables); + bc.spells = randomizer.loadSpells(level["reward"]["spells"], rng, emptyVariables); return bc; } @@ -82,80 +83,16 @@ CBankInfo::CBankInfo(const JsonVector & Config) : assert(!Config.empty()); } -static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount) -{ - army.totalStrength += crea->getFightValue() * amount; - - bool walker = true; - if(crea->hasBonusOfType(BonusType::SHOOTER)) - { - army.shootersStrength += crea->getFightValue() * amount; - walker = false; - } - if(crea->hasBonusOfType(BonusType::FLYING)) - { - army.flyersStrength += crea->getFightValue() * amount; - walker = false; - } - if(walker) - army.walkersStrength += crea->getFightValue() * amount; -} - -IObjectInfo::CArmyStructure CBankInfo::minGuards() const -{ - JsonRandom::Variables emptyVariables; - - std::vector armies; - for(auto configEntry : config) - { - auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables); - IObjectInfo::CArmyStructure army; - for(auto & stack : stacks) - { - assert(!stack.allowedCreatures.empty()); - auto weakest = boost::range::min_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b) - { - return a->getFightValue() < b->getFightValue(); - }); - addStackToArmy(army, *weakest, stack.minAmount); - } - armies.push_back(army); - } - return *boost::range::min_element(armies); -} - -IObjectInfo::CArmyStructure CBankInfo::maxGuards() const -{ - JsonRandom::Variables emptyVariables; - - std::vector armies; - for(auto configEntry : config) - { - auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"], emptyVariables); - IObjectInfo::CArmyStructure army; - for(auto & stack : stacks) - { - assert(!stack.allowedCreatures.empty()); - auto strongest = boost::range::max_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b) - { - return a->getFightValue() < b->getFightValue(); - }); - addStackToArmy(army, *strongest, stack.maxAmount); - } - armies.push_back(army); - } - return *boost::range::max_element(armies); -} - -TPossibleGuards CBankInfo::getPossibleGuards() const +TPossibleGuards CBankInfo::getPossibleGuards(IGameCallback * cb) const { JsonRandom::Variables emptyVariables; + JsonRandom randomizer(cb); TPossibleGuards out; for(const JsonNode & configEntry : config) { const JsonNode & guardsInfo = configEntry["guards"]; - auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables); + auto stacks = randomizer.evaluateCreatures(guardsInfo, emptyVariables); IObjectInfo::CArmyStructure army; @@ -191,12 +128,13 @@ std::vector> CBankInfo::getPossibleResourcesReward() std::vector> CBankInfo::getPossibleCreaturesReward() const { JsonRandom::Variables emptyVariables; + JsonRandom randomizer(nullptr); std::vector> aproximateReward; for(const JsonNode & configEntry : config) { const JsonNode & guardsInfo = configEntry["reward"]["creatures"]; - auto stacks = JsonRandom::evaluateCreatures(guardsInfo, emptyVariables); + auto stacks = randomizer.evaluateCreatures(guardsInfo, emptyVariables); for(auto stack : stacks) { diff --git a/lib/mapObjectConstructors/CBankInstanceConstructor.h b/lib/mapObjectConstructors/CBankInstanceConstructor.h index e683f01df..a8883b2d7 100644 --- a/lib/mapObjectConstructors/CBankInstanceConstructor.h +++ b/lib/mapObjectConstructors/CBankInstanceConstructor.h @@ -55,14 +55,10 @@ class DLL_LINKAGE CBankInfo : public IObjectInfo public: CBankInfo(const JsonVector & Config); - TPossibleGuards getPossibleGuards() const; + TPossibleGuards getPossibleGuards(IGameCallback * cb) const; std::vector> getPossibleResourcesReward() const; std::vector> getPossibleCreaturesReward() const; - // These functions should try to evaluate minimal possible/max possible guards to give provide information on possible thread to AI - CArmyStructure minGuards() const override; - CArmyStructure maxGuards() const override; - bool givesResources() const override; bool givesArtifacts() const override; bool givesCreatures() const override; diff --git a/lib/mapObjectConstructors/CDefaultObjectTypeHandler.h b/lib/mapObjectConstructors/CDefaultObjectTypeHandler.h index 15c545906..c56e5eee5 100644 --- a/lib/mapObjectConstructors/CDefaultObjectTypeHandler.h +++ b/lib/mapObjectConstructors/CDefaultObjectTypeHandler.h @@ -27,9 +27,9 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler randomizeObject(castedObject, rng); } - CGObjectInstance * create(std::shared_ptr tmpl = nullptr) const final + CGObjectInstance * create(IGameCallback * cb, std::shared_ptr tmpl) const final { - ObjectType * result = createObject(); + ObjectType * result = createObject(cb); preInitObject(result); @@ -44,9 +44,9 @@ class CDefaultObjectTypeHandler : public AObjectTypeHandler protected: virtual void initializeObject(ObjectType * object) const {} virtual void randomizeObject(ObjectType * object, CRandomGenerator & rng) const {} - virtual ObjectType * createObject() const + virtual ObjectType * createObject(IGameCallback * cb) const { - return new ObjectType(); + return new ObjectType(cb); } }; diff --git a/lib/mapObjectConstructors/CRewardableConstructor.cpp b/lib/mapObjectConstructors/CRewardableConstructor.cpp index c8b802586..551db2330 100644 --- a/lib/mapObjectConstructors/CRewardableConstructor.cpp +++ b/lib/mapObjectConstructors/CRewardableConstructor.cpp @@ -31,9 +31,9 @@ bool CRewardableConstructor::hasNameTextID() const return !objectInfo.getParameters()["name"].isNull(); } -CGObjectInstance * CRewardableConstructor::create(std::shared_ptr tmpl) const +CGObjectInstance * CRewardableConstructor::create(IGameCallback * cb, std::shared_ptr tmpl) const { - auto * ret = new CRewardableObject(); + auto * ret = new CRewardableObject(cb); preInitObject(ret); ret->appearance = tmpl; ret->blockVisit = blockVisit; diff --git a/lib/mapObjectConstructors/CRewardableConstructor.h b/lib/mapObjectConstructors/CRewardableConstructor.h index a92836f7f..81fd286e6 100644 --- a/lib/mapObjectConstructors/CRewardableConstructor.h +++ b/lib/mapObjectConstructors/CRewardableConstructor.h @@ -25,7 +25,7 @@ class DLL_LINKAGE CRewardableConstructor : public AObjectTypeHandler public: bool hasNameTextID() const override; - CGObjectInstance * create(std::shared_ptr tmpl = nullptr) const override; + CGObjectInstance * create(IGameCallback * cb, std::shared_ptr tmpl = nullptr) const override; void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override; diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp index 4278394f9..707318292 100644 --- a/lib/mapObjectConstructors/CommonConstructors.cpp +++ b/lib/mapObjectConstructors/CommonConstructors.cpp @@ -102,7 +102,7 @@ void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const void CTownInstanceConstructor::randomizeObject(CGTownInstance * object, CRandomGenerator & rng) const { - auto templ = getOverride(CGObjectInstance::cb->getTile(object->pos)->terType->getId(), object); + auto templ = getOverride(object->cb->getTile(object->pos)->terType->getId(), object); if(templ) object->appearance = templ; } @@ -224,7 +224,7 @@ void MarketInstanceConstructor::initTypeData(const JsonNode & input) speech = input["speech"].String(); } -CGMarket * MarketInstanceConstructor::createObject() const +CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const { if(marketModes.size() == 1) { @@ -232,13 +232,13 @@ CGMarket * MarketInstanceConstructor::createObject() const { case EMarketMode::ARTIFACT_RESOURCE: case EMarketMode::RESOURCE_ARTIFACT: - return new CGBlackMarket; + return new CGBlackMarket(cb); case EMarketMode::RESOURCE_SKILL: - return new CGUniversity; + return new CGUniversity(cb); } } - return new CGMarket; + return new CGMarket(cb); } void MarketInstanceConstructor::initializeObject(CGMarket * market) const @@ -256,11 +256,12 @@ void MarketInstanceConstructor::initializeObject(CGMarket * market) const void MarketInstanceConstructor::randomizeObject(CGMarket * object, CRandomGenerator & rng) const { + JsonRandom randomizer(object->cb); JsonRandom::Variables emptyVariables; if(auto * university = dynamic_cast(object)) { - for(auto skill : JsonRandom::loadSecondaries(predefinedOffer, rng, emptyVariables)) + for(auto skill : randomizer.loadSecondaries(predefinedOffer, rng, emptyVariables)) university->skills.push_back(skill.first); } } diff --git a/lib/mapObjectConstructors/CommonConstructors.h b/lib/mapObjectConstructors/CommonConstructors.h index 51aa98753..ac5105b27 100644 --- a/lib/mapObjectConstructors/CommonConstructors.h +++ b/lib/mapObjectConstructors/CommonConstructors.h @@ -121,7 +121,7 @@ protected: std::string speech; public: - CGMarket * createObject() const override; + CGMarket * createObject(IGameCallback * cb) const override; void initializeObject(CGMarket * object) const override; void randomizeObject(CGMarket * object, CRandomGenerator & rng) const override; diff --git a/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp b/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp index 022b2773c..b77bf9577 100644 --- a/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp +++ b/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp @@ -68,9 +68,9 @@ void DwellingInstanceConstructor::initializeObject(CGDwelling * obj) const } } -void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGenerator &rng) const +void DwellingInstanceConstructor::randomizeObject(CGDwelling * dwelling, CRandomGenerator &rng) const { - auto * dwelling = dynamic_cast(object); + JsonRandom randomizer(dwelling->cb); dwelling->creatures.clear(); dwelling->creatures.reserve(availableCreatures.size()); @@ -94,7 +94,7 @@ void DwellingInstanceConstructor::randomizeObject(CGDwelling * object, CRandomGe else if(guards.getType() == JsonNode::JsonType::DATA_VECTOR) //custom guards (eg. Elemental Conflux) { JsonRandom::Variables emptyVariables; - for(auto & stack : JsonRandom::loadCreatures(guards, rng, emptyVariables)) + for(auto & stack : randomizer.loadCreatures(guards, rng, emptyVariables)) { dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->getId(), stack.count)); } diff --git a/lib/mapObjectConstructors/IObjectInfo.h b/lib/mapObjectConstructors/IObjectInfo.h index 29c0ff66f..280402fa8 100644 --- a/lib/mapObjectConstructors/IObjectInfo.h +++ b/lib/mapObjectConstructors/IObjectInfo.h @@ -34,11 +34,6 @@ public: } }; - /// Returns possible composition of guards. Actual guards would be - /// somewhere between these two values - virtual CArmyStructure minGuards() const { return CArmyStructure(); } - virtual CArmyStructure maxGuards() const { return CArmyStructure(); } - virtual bool givesResources() const { return false; } virtual bool givesExperience() const { return false; } diff --git a/lib/mapObjects/CArmedInstance.cpp b/lib/mapObjects/CArmedInstance.cpp index 3f92fe5dd..b936863be 100644 --- a/lib/mapObjects/CArmedInstance.cpp +++ b/lib/mapObjects/CArmedInstance.cpp @@ -40,12 +40,13 @@ void CArmedInstance::randomizeArmy(FactionID type) // Take Angelic Alliance troop-mixing freedom of non-evil units into account. CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(BonusType::NONEVIL_ALIGNMENT_MIX); -CArmedInstance::CArmedInstance() - :CArmedInstance(false) +CArmedInstance::CArmedInstance(IGameCallback *cb) + :CArmedInstance(cb, false) { } -CArmedInstance::CArmedInstance(bool isHypothetic): +CArmedInstance::CArmedInstance(IGameCallback *cb, bool isHypothetic): + CGObjectInstance(cb), CBonusSystemNode(isHypothetic), nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector), battle(nullptr) diff --git a/lib/mapObjects/CArmedInstance.h b/lib/mapObjects/CArmedInstance.h index 815e250dc..0e0560816 100644 --- a/lib/mapObjects/CArmedInstance.h +++ b/lib/mapObjects/CArmedInstance.h @@ -42,8 +42,8 @@ public: virtual CBonusSystemNode & whatShouldBeAttached(); ////////////////////////////////////////////////////////////////////////// - CArmedInstance(); - CArmedInstance(bool isHypothetic); + CArmedInstance(IGameCallback *cb); + CArmedInstance(IGameCallback *cb, bool isHypothetic); PlayerColor getOwner() const override { diff --git a/lib/mapObjects/CBank.cpp b/lib/mapObjects/CBank.cpp index 46661af86..9dc7f48f4 100644 --- a/lib/mapObjects/CBank.cpp +++ b/lib/mapObjects/CBank.cpp @@ -37,8 +37,10 @@ static std::string visitedTxt(const bool visited) return VLC->generaltexth->allTexts[id]; } -//must be instantiated in .cpp file for access to complete types of all member fields -CBank::CBank() = default; +CBank::CBank(IGameCallback *cb) + : CArmedInstance(cb) +{} + //must be instantiated in .cpp file for access to complete types of all member fields CBank::~CBank() = default; diff --git a/lib/mapObjects/CBank.h b/lib/mapObjects/CBank.h index 99bb4fdd7..1ac22869f 100644 --- a/lib/mapObjects/CBank.h +++ b/lib/mapObjects/CBank.h @@ -27,7 +27,7 @@ class DLL_LINKAGE CBank : public CArmedInstance void doVisit(const CGHeroInstance * hero) const; public: - CBank(); + CBank(IGameCallback *cb); ~CBank() override; void setConfig(const BankConfig & bc); diff --git a/lib/mapObjects/CGCreature.h b/lib/mapObjects/CGCreature.h index 4d33ecdf3..7d293686b 100644 --- a/lib/mapObjects/CGCreature.h +++ b/lib/mapObjects/CGCreature.h @@ -18,6 +18,8 @@ VCMI_LIB_NAMESPACE_BEGIN class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map { public: + using CArmedInstance::CArmedInstance; + enum Action { FIGHT = -2, FLEE = -1, JOIN_FOR_FREE = 0 //values > 0 mean gold price }; diff --git a/lib/mapObjects/CGDwelling.cpp b/lib/mapObjects/CGDwelling.cpp index 2276d8a0d..e91b99d42 100644 --- a/lib/mapObjects/CGDwelling.cpp +++ b/lib/mapObjects/CGDwelling.cpp @@ -43,7 +43,10 @@ void CGDwellingRandomizationInfo::serializeJson(JsonSerializeFormat & handler) } } -CGDwelling::CGDwelling() = default; +CGDwelling::CGDwelling(IGameCallback *cb): + CArmedInstance(cb) +{} + CGDwelling::~CGDwelling() = default; FactionID CGDwelling::randomizeFaction(CRandomGenerator & rand) diff --git a/lib/mapObjects/CGDwelling.h b/lib/mapObjects/CGDwelling.h index 09fc96ca4..5f0b6388f 100644 --- a/lib/mapObjects/CGDwelling.h +++ b/lib/mapObjects/CGDwelling.h @@ -38,7 +38,7 @@ public: std::optional randomizationInfo; //random dwelling options; not serialized TCreaturesSet creatures; //creatures[level] -> - CGDwelling(); + CGDwelling(IGameCallback *cb); ~CGDwelling() override; protected: diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 99f4113a8..f6d6bc62c 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -274,7 +274,8 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) return ti->valOfBonuses(BonusType::MOVEMENT, onLand ? BonusCustomSubtype::heroMovementLand : BonusCustomSubtype::heroMovementSea); } -CGHeroInstance::CGHeroInstance(): +CGHeroInstance::CGHeroInstance(IGameCallback * cb) + : CArmedInstance(cb), tacticFormationEnabled(false), inTownGarrison(false), moveDir(4), @@ -789,7 +790,7 @@ void CGHeroInstance::spendMana(ServerCallback * server, const int spellCost) con bool CGHeroInstance::canCastThisSpell(const spells::Spell * spell) const { - const bool isAllowed = IObjectInterface::cb->isAllowed(spell->getId()); + const bool isAllowed = cb->isAllowed(spell->getId()); const bool inSpellBook = vstd::contains(spells, spell->getId()) && hasSpellbook(); const bool specificBonus = hasBonusOfType(BonusType::SPELL, BonusSubtypeID(spell->getId())); @@ -853,7 +854,7 @@ bool CGHeroInstance::canLearnSpell(const spells::Spell * spell, bool allowBanned return false;//creature abilities can not be learned } - if(!allowBanned && !IObjectInterface::cb->isAllowed(spell->getId())) + if(!allowBanned && !cb->isAllowed(spell->getId())) { logGlobal->warn("Hero %s try to learn banned spell %s", nodeName(), spell->getNameTranslated()); return false;//banned spells should not be learned @@ -1760,7 +1761,7 @@ void CGHeroInstance::serializeJsonDefinition(JsonSerializeFormat & handler) bool CGHeroInstance::isMissionCritical() const { - for(const TriggeredEvent & event : IObjectInterface::cb->getMapHeader()->triggeredEvents) + for(const TriggeredEvent & event : cb->getMapHeader()->triggeredEvents) { if (event.effect.type != EventEffect::DEFEAT) continue; diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 923eec081..1b938057a 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -28,6 +28,8 @@ enum class EHeroGender : uint8_t; class DLL_LINKAGE CGHeroPlaceholder : public CGObjectInstance { public: + using CGObjectInstance::CGObjectInstance; + /// if this is placeholder by power, then power rank of desired hero std::optional powerRank; @@ -249,7 +251,7 @@ public: /// If this hero perishes, the scenario is failed bool isMissionCritical() const; - CGHeroInstance(); + CGHeroInstance(IGameCallback *cb); virtual ~CGHeroInstance(); PlayerColor getOwner() const override; diff --git a/lib/mapObjects/CGMarket.cpp b/lib/mapObjects/CGMarket.cpp index 951dd41e9..6ba715f1f 100644 --- a/lib/mapObjects/CGMarket.cpp +++ b/lib/mapObjects/CGMarket.cpp @@ -55,9 +55,9 @@ std::vector CGMarket::availableItemsIds(EMarketMode mode) const return std::vector(); } -CGMarket::CGMarket() -{ -} +CGMarket::CGMarket(IGameCallback *cb): + CGObjectInstance(cb) +{} std::vector CGBlackMarket::availableItemsIds(EMarketMode mode) const { diff --git a/lib/mapObjects/CGMarket.h b/lib/mapObjects/CGMarket.h index abeefd284..a316956d0 100644 --- a/lib/mapObjects/CGMarket.h +++ b/lib/mapObjects/CGMarket.h @@ -25,7 +25,7 @@ public: std::string title; std::string speech; //currently shown only in university - CGMarket(); + CGMarket(IGameCallback *cb); ///IObjectInterface void onHeroVisit(const CGHeroInstance * h) const override; //open trading window void initObj(CRandomGenerator & rand) override;//set skills for trade @@ -49,6 +49,8 @@ public: class DLL_LINKAGE CGBlackMarket : public CGMarket { public: + using CGMarket::CGMarket; + std::vector artifacts; //available artifacts void newTurn(CRandomGenerator & rand) const override; //reset artifacts for black market every month @@ -64,6 +66,8 @@ public: class DLL_LINKAGE CGUniversity : public CGMarket { public: + using CGMarket::CGMarket; + std::vector skills; //available skills std::vector availableItemsIds(EMarketMode mode) const override; diff --git a/lib/mapObjects/CGObjectInstance.cpp b/lib/mapObjects/CGObjectInstance.cpp index b2f7138dd..a3ca5643a 100644 --- a/lib/mapObjects/CGObjectInstance.cpp +++ b/lib/mapObjects/CGObjectInstance.cpp @@ -28,7 +28,8 @@ VCMI_LIB_NAMESPACE_BEGIN //TODO: remove constructor -CGObjectInstance::CGObjectInstance(): +CGObjectInstance::CGObjectInstance(IGameCallback *cb): + IObjectInterface(cb), pos(-1,-1,-1), ID(Obj::NO_OBJ), subID(-1), diff --git a/lib/mapObjects/CGObjectInstance.h b/lib/mapObjects/CGObjectInstance.h index 7292435ba..33ec31e98 100644 --- a/lib/mapObjects/CGObjectInstance.h +++ b/lib/mapObjects/CGObjectInstance.h @@ -44,7 +44,7 @@ public: std::string typeName; std::string subTypeName; - CGObjectInstance(); //TODO: remove constructor + CGObjectInstance(IGameCallback *cb); ~CGObjectInstance() override; MapObjectID getObjGroupIndex() const override; diff --git a/lib/mapObjects/CGPandoraBox.cpp b/lib/mapObjects/CGPandoraBox.cpp index 627ad8637..b79077948 100644 --- a/lib/mapObjects/CGPandoraBox.cpp +++ b/lib/mapObjects/CGPandoraBox.cpp @@ -66,7 +66,7 @@ void CGPandoraBox::grantRewardWithMessage(const CGHeroInstance * h, int index, b return text; }; - auto sendInfoWindow = [h](const MetaString & text, const Rewardable::Reward & reward) + auto sendInfoWindow = [&](const MetaString & text, const Rewardable::Reward & reward) { InfoWindow iw; iw.player = h->tempOwner; diff --git a/lib/mapObjects/CGPandoraBox.h b/lib/mapObjects/CGPandoraBox.h index 4bbd5b2af..77cdf35bc 100644 --- a/lib/mapObjects/CGPandoraBox.h +++ b/lib/mapObjects/CGPandoraBox.h @@ -19,6 +19,8 @@ struct InfoWindow; class DLL_LINKAGE CGPandoraBox : public CRewardableObject { public: + using CRewardableObject::CRewardableObject; + MetaString message; void initObj(CRandomGenerator & rand) override; @@ -41,6 +43,8 @@ protected: class DLL_LINKAGE CGEvent : public CGPandoraBox //event objects { public: + using CGPandoraBox::CGPandoraBox; + bool removeAfterVisit = false; //true if event is removed after occurring std::set availableFor; //players whom this event is available for bool computerActivate = false; //true if computer player can activate this event diff --git a/lib/mapObjects/CGTownBuilding.cpp b/lib/mapObjects/CGTownBuilding.cpp index feca2de77..5bced754c 100644 --- a/lib/mapObjects/CGTownBuilding.cpp +++ b/lib/mapObjects/CGTownBuilding.cpp @@ -19,6 +19,16 @@ VCMI_LIB_NAMESPACE_BEGIN +CGTownBuilding::CGTownBuilding(IGameCallback * cb) + : IObjectInterface(cb) + , town(nullptr) +{} + +CGTownBuilding::CGTownBuilding(CGTownInstance * town) + : IObjectInterface(town->cb) + , town(town) +{} + PlayerColor CGTownBuilding::getOwner() const { return town->getOwner(); @@ -111,12 +121,15 @@ std::string CGTownBuilding::getCustomBonusGreeting(const Bonus & bonus) const return greeting; } +COPWBonus::COPWBonus(IGameCallback *cb) + : CGTownBuilding(cb) +{} COPWBonus::COPWBonus(const BuildingID & bid, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown) + : CGTownBuilding(cgTown) { bID = bid; bType = subId; - town = cgTown; indexOnTV = static_cast(town->bonusingBuildings.size()); } @@ -175,11 +188,15 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const } } +CTownBonus::CTownBonus(IGameCallback *cb) + : CGTownBuilding(cb) +{} + CTownBonus::CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown) + : CGTownBuilding(cgTown) { bID = index; bType = subId; - town = cgTown; indexOnTV = static_cast(town->bonusingBuildings.size()); } @@ -286,11 +303,15 @@ void CTownBonus::applyBonuses(CGHeroInstance * h, const BonusList & bonuses) con town->addHeroToStructureVisitors(h, indexOnTV); } +CTownRewardableBuilding::CTownRewardableBuilding(IGameCallback *cb) + : CGTownBuilding(cb) +{} + CTownRewardableBuilding::CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * cgTown, CRandomGenerator & rand) + : CGTownBuilding(cgTown) { bID = index; bType = subId; - town = cgTown; indexOnTV = static_cast(town->bonusingBuildings.size()); initObj(rand); } diff --git a/lib/mapObjects/CGTownBuilding.h b/lib/mapObjects/CGTownBuilding.h index 47da63af5..d31b07622 100644 --- a/lib/mapObjects/CGTownBuilding.h +++ b/lib/mapObjects/CGTownBuilding.h @@ -22,9 +22,12 @@ class DLL_LINKAGE CGTownBuilding : public IObjectInterface { ///basic class for town structures handled as map objects public: + CGTownBuilding(CGTownInstance * town); + CGTownBuilding(IGameCallback *cb); + si32 indexOnTV = 0; //identifies its index on towns vector - CGTownInstance * town = nullptr; + CGTownInstance * town; STRONG_INLINE BuildingSubID::EBuildingSubID getBuildingSubtype() const @@ -74,7 +77,7 @@ public: void onHeroVisit (const CGHeroInstance * h) const override; COPWBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN); - COPWBonus() = default; + COPWBonus(IGameCallback *cb); template void serialize(Handler &h, const int version) { @@ -93,7 +96,7 @@ public: void onHeroVisit (const CGHeroInstance * h) const override; CTownBonus(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * TOWN); - CTownBonus() = default; + CTownBonus(IGameCallback *cb); template void serialize(Handler &h, const int version) { @@ -131,7 +134,7 @@ public: void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; CTownRewardableBuilding(const BuildingID & index, BuildingSubID::EBuildingSubID subId, CGTownInstance * town, CRandomGenerator & rand); - CTownRewardableBuilding() = default; + CTownRewardableBuilding(IGameCallback *cb); template void serialize(Handler &h, const int version) { diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 70d83674a..0aa6449bb 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -228,7 +228,8 @@ bool CGTownInstance::hasCapitol() const return hasBuilt(BuildingID::CAPITOL); } -CGTownInstance::CGTownInstance(): +CGTownInstance::CGTownInstance(IGameCallback *cb): + CGDwelling(cb), town(nullptr), builded(0), destroyed(0), diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 0bc2976ba..241eb2432 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -200,7 +200,7 @@ public: FactionID getFaction() const override; TerrainId getNativeTerrain() const override; - CGTownInstance(); + CGTownInstance(IGameCallback *cb); virtual ~CGTownInstance(); ///IObjectInterface overrides diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 1aa09ff8e..24a3071bb 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -130,7 +130,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const if(killTarget != ObjectInstanceID::NONE) { - if(CGHeroInstance::cb->getObjByQuestIdentifier(killTarget)) + if(h->cb->getObjByQuestIdentifier(killTarget)) return false; } @@ -167,7 +167,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const cb->giveResources(h->getOwner(), mission.resources); } -void CQuest::addTextReplacements(MetaString & text, std::vector & components) const +void CQuest::addTextReplacements(IGameCallback * cb, MetaString & text, std::vector & components) const { if(mission.heroLevel > 0) text.replaceNumber(mission.heroLevel); @@ -263,10 +263,10 @@ void CQuest::addTextReplacements(MetaString & text, std::vector & com } if(lastDay >= 0) - text.replaceNumber(lastDay - IObjectInterface::cb->getDate(Date::DAY)); + text.replaceNumber(lastDay - cb->getDate(Date::DAY)); } -void CQuest::getVisitText(MetaString &iwText, std::vector &components, bool firstVisit, const CGHeroInstance * h) const +void CQuest::getVisitText(IGameCallback * cb, MetaString &iwText, std::vector &components, bool firstVisit, const CGHeroInstance * h) const { bool failRequirements = (h ? !checkQuest(h) : true); mission.loadComponents(components, h); @@ -279,10 +279,10 @@ void CQuest::getVisitText(MetaString &iwText, std::vector &components if(lastDay >= 0) iwText.appendTextID(TextIdentifier("core", "seerhut", "time", textOption).get()); - addTextReplacements(iwText, components); + addTextReplacements(cb, iwText, components); } -void CQuest::getRolloverText(MetaString &ms, bool onHover) const +void CQuest::getRolloverText(IGameCallback * cb, MetaString &ms, bool onHover) const { if(onHover) ms.appendRawString("\n\n"); @@ -292,15 +292,15 @@ void CQuest::getRolloverText(MetaString &ms, bool onHover) const ms.appendTextID(TextIdentifier("core", "seerhut", "quest", questName, questState, textOption).get()); std::vector components; - addTextReplacements(ms, components); + addTextReplacements(cb, ms, components); } -void CQuest::getCompletionText(MetaString &iwText) const +void CQuest::getCompletionText(IGameCallback * cb, MetaString &iwText) const { iwText.appendRawString(completedText.toString()); std::vector components; - addTextReplacements(iwText, components); + addTextReplacements(cb, iwText, components); } void CQuest::defineQuestName() @@ -411,9 +411,9 @@ bool IQuestObject::checkQuest(const CGHeroInstance* h) const return quest->checkQuest(h); } -void IQuestObject::getVisitText(MetaString &text, std::vector &components, bool FirstVisit, const CGHeroInstance * h) const +void CGSeerHut::getVisitText(MetaString &text, std::vector &components, bool FirstVisit, const CGHeroInstance * h) const { - quest->getVisitText(text, components, FirstVisit, h); + quest->getVisitText(cb, text, components, FirstVisit, h); } void IQuestObject::afterAddToMapCommon(CMap * map) const @@ -479,14 +479,14 @@ void CGSeerHut::initObj(CRandomGenerator & rand) quest->completedText.appendTextID(TextIdentifier("core", "seerhut", "quest", quest-> questName, quest->missionState(2), quest->textOption).get()); } - quest->getCompletionText(configuration.onSelect); + quest->getCompletionText(cb, configuration.onSelect); for(auto & i : configuration.info) - quest->getCompletionText(i.message); + quest->getCompletionText(cb, i.message); } void CGSeerHut::getRolloverText(MetaString &text, bool onHover) const { - quest->getRolloverText(text, onHover);//TODO: simplify? + quest->getRolloverText(cb, text, onHover);//TODO: simplify? if(!onHover) text.replaceRawString(seerName); } diff --git a/lib/mapObjects/CQuest.h b/lib/mapObjects/CQuest.h index cb3046a22..eda83e454 100644 --- a/lib/mapObjects/CQuest.h +++ b/lib/mapObjects/CQuest.h @@ -56,11 +56,11 @@ public: static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army); virtual bool checkQuest(const CGHeroInstance * h) const; //determines whether the quest is complete or not - virtual void getVisitText(MetaString &text, std::vector & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const; - virtual void getCompletionText(MetaString &text) const; - virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry + virtual void getVisitText(IGameCallback * cb, MetaString &text, std::vector & components, bool FirstVisit, const CGHeroInstance * h = nullptr) const; + virtual void getCompletionText(IGameCallback * cb, MetaString &text) const; + virtual void getRolloverText (IGameCallback * cb, MetaString &text, bool onHover) const; //hover or quest log entry virtual void completeQuest(IGameCallback *, const CGHeroInstance * h) const; - virtual void addTextReplacements(MetaString &out, std::vector & components) const; + virtual void addTextReplacements(IGameCallback * cb, MetaString &out, std::vector & components) const; virtual void addKillTargetReplacements(MetaString &out) const; void defineQuestName(); @@ -103,7 +103,7 @@ public: ///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; + virtual void getVisitText (MetaString &text, std::vector &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const = 0; virtual bool checkQuest (const CGHeroInstance * h) const; template void serialize(Handler &h, const int version) @@ -117,6 +117,8 @@ protected: class DLL_LINKAGE CGSeerHut : public CRewardableObject, public IQuestObject { public: + using CRewardableObject::CRewardableObject; + std::string seerName; void initObj(CRandomGenerator & rand) override; @@ -129,6 +131,7 @@ public: void newTurn(CRandomGenerator & rand) const override; void onHeroVisit(const CGHeroInstance * h) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; + void getVisitText (MetaString &text, std::vector &components, bool FirstVisit, const CGHeroInstance * h = nullptr) const override; virtual void init(CRandomGenerator & rand); int checkDirection() const; //calculates the region of map where monster is placed @@ -154,6 +157,8 @@ protected: class DLL_LINKAGE CGQuestGuard : public CGSeerHut { public: + using CGSeerHut::CGSeerHut; + void init(CRandomGenerator & rand) override; void onHeroVisit(const CGHeroInstance * h) const override; @@ -170,6 +175,8 @@ protected: class DLL_LINKAGE CGKeys : public CGObjectInstance //Base class for Keymaster and guards { public: + using CGObjectInstance::CGObjectInstance; + bool wasMyColorVisited(const PlayerColor & player) const; std::string getObjectName() const override; //depending on color @@ -184,6 +191,8 @@ public: class DLL_LINKAGE CGKeymasterTent : public CGKeys { public: + using CGKeys::CGKeys; + bool wasVisited (PlayerColor player) const override; void onHeroVisit(const CGHeroInstance * h) const override; @@ -196,6 +205,8 @@ public: class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject { public: + using CGKeys::CGKeys; + void initObj(CRandomGenerator & rand) override; void onHeroVisit(const CGHeroInstance * h) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; @@ -216,6 +227,8 @@ public: class DLL_LINKAGE CGBorderGate : public CGBorderGuard { public: + using CGBorderGuard::CGBorderGuard; + void onHeroVisit(const CGHeroInstance * h) const override; bool passableFor(PlayerColor color) const override; diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index aa945d043..6d67c9c28 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -385,7 +385,8 @@ void CRewardableObject::initObj(CRandomGenerator & rand) getObjectHandler()->configureObject(this, rand); } -CRewardableObject::CRewardableObject() +CRewardableObject::CRewardableObject(IGameCallback *cb) + :CArmedInstance(cb) {} void CRewardableObject::serializeJsonOptions(JsonSerializeFormat & handler) diff --git a/lib/mapObjects/CRewardableObject.h b/lib/mapObjects/CRewardableObject.h index fa31f963d..bdcff998c 100644 --- a/lib/mapObjects/CRewardableObject.h +++ b/lib/mapObjects/CRewardableObject.h @@ -67,7 +67,7 @@ public: void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override; - CRewardableObject(); + CRewardableObject(IGameCallback *cb); std::string getHoverText(PlayerColor player) const override; std::string getHoverText(const CGHeroInstance * hero) const override; diff --git a/lib/mapObjects/IObjectInterface.cpp b/lib/mapObjects/IObjectInterface.cpp index eebc08478..1c2c15548 100644 --- a/lib/mapObjects/IObjectInterface.cpp +++ b/lib/mapObjects/IObjectInterface.cpp @@ -21,8 +21,6 @@ VCMI_LIB_NAMESPACE_BEGIN -IGameCallback * IObjectInterface::cb = nullptr; - void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInfoWindowMode mode) const { InfoWindow iw; @@ -30,7 +28,7 @@ void IObjectInterface::showInfoDialog(const ui32 txtID, const ui16 soundID, EInf iw.player = getOwner(); iw.type = mode; iw.text.appendLocalString(EMetaText::ADVOB_TXT,txtID); - IObjectInterface::cb->sendAndApply(&iw); + cb->sendAndApply(&iw); } ///IObjectInterface @@ -117,7 +115,7 @@ IBoatGenerator::EGeneratorState IBoatGenerator::shipyardStatus() const if(!tile.valid()) return TILE_BLOCKED; //no available water - const TerrainTile *t = IObjectInterface::cb->getTile(tile); + const TerrainTile *t = getObject()->cb->getTile(tile); if(!t) return TILE_BLOCKED; //no available water diff --git a/lib/mapObjects/IObjectInterface.h b/lib/mapObjects/IObjectInterface.h index 7cf9c8525..baebb223e 100644 --- a/lib/mapObjects/IObjectInterface.h +++ b/lib/mapObjects/IObjectInterface.h @@ -12,6 +12,7 @@ #include "../networkPacks/EInfoWindowMode.h" #include "../networkPacks/ObjProperty.h" #include "../constants/EntityIdentifiers.h" +#include "../GameCallbackHolder.h" VCMI_LIB_NAMESPACE_BEGIN @@ -28,10 +29,10 @@ class int3; class MetaString; class PlayerColor; -class DLL_LINKAGE IObjectInterface +class DLL_LINKAGE IObjectInterface : public GameCallbackHolder { public: - static IGameCallback *cb; + using GameCallbackHolder::GameCallbackHolder; virtual ~IObjectInterface() = default; diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index c5f271e98..4fe166b75 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -584,13 +584,13 @@ void CGSubterraneanGate::initObj(CRandomGenerator & rand) type = BOTH; } -void CGSubterraneanGate::postInit() //matches subterranean gates into pairs +void CGSubterraneanGate::postInit(IGameCallback * cb) //matches subterranean gates into pairs { //split on underground and surface gates std::vector gatesSplit[2]; //surface and underground gates for(auto & obj : cb->gameState()->map->objects) { - if(!obj) // FIXME: Find out why there are nullptr objects right after initialization + if(!obj) continue; auto * hlp = dynamic_cast(cb->gameState()->getObjInstance(obj->id)); @@ -1081,7 +1081,8 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const } } -CGBoat::CGBoat() +CGBoat::CGBoat(IGameCallback * cb) + : CGObjectInstance(cb) { hero = nullptr; direction = 4; diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index 365d13abe..320c4da26 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -24,6 +24,8 @@ using TTeleportExitsList = std::vector>; class DLL_LINKAGE CTeamVisited: public CGObjectInstance { public: + using CGObjectInstance::CGObjectInstance; + std::set players; //players that visited this object bool wasVisited (const CGHeroInstance * h) const override; @@ -41,6 +43,8 @@ public: class DLL_LINKAGE CGSignBottle : public CGObjectInstance //signs and ocean bottles { public: + using CGObjectInstance::CGObjectInstance; + MetaString message; void onHeroVisit(const CGHeroInstance * h) const override; @@ -58,6 +62,8 @@ protected: class DLL_LINKAGE CGGarrison : public CArmedInstance { public: + using CArmedInstance::CArmedInstance; + bool removableUnits; void initObj(CRandomGenerator &rand) override; @@ -78,6 +84,8 @@ protected: class DLL_LINKAGE CGArtifact : public CArmedInstance { public: + using CArmedInstance::CArmedInstance; + CArtifactInstance * storedArtifact = nullptr; MetaString message; @@ -112,6 +120,8 @@ protected: class DLL_LINKAGE CGResource : public CArmedInstance { public: + using CArmedInstance::CArmedInstance; + static constexpr ui32 RANDOM_AMOUNT = 0; ui32 amount = RANDOM_AMOUNT; //0 if random @@ -148,6 +158,8 @@ public: ResourceSet dailyIncome() const; private: + using CArmedInstance::CArmedInstance; + void onHeroVisit(const CGHeroInstance * h) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; @@ -204,6 +216,8 @@ protected: std::vector getAllExits(bool excludeCurrent = false) const; public: + using CGObjectInstance::CGObjectInstance; + TeleportChannelID channel; bool isEntrance() const; @@ -236,6 +250,8 @@ protected: void initObj(CRandomGenerator & rand) override; public: + using CGTeleport::CGTeleport; + template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -248,7 +264,9 @@ class DLL_LINKAGE CGSubterraneanGate : public CGMonolith void initObj(CRandomGenerator & rand) override; public: - static void postInit(); + using CGMonolith::CGMonolith; + + static void postInit(IGameCallback * cb); template void serialize(Handler &h, const int version) { @@ -263,6 +281,8 @@ class DLL_LINKAGE CGWhirlpool : public CGMonolith static bool isProtected( const CGHeroInstance * h ); public: + using CGMonolith::CGMonolith; + template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -272,6 +292,8 @@ public: class DLL_LINKAGE CGSirens : public CGObjectInstance { public: + using CGObjectInstance::CGObjectInstance; + void onHeroVisit(const CGHeroInstance * h) const override; std::string getHoverText(const CGHeroInstance * hero) const override; void initObj(CRandomGenerator & rand) override; @@ -285,6 +307,8 @@ public: class DLL_LINKAGE CGBoat : public CGObjectInstance, public CBonusSystemNode { public: + using CGObjectInstance::CGObjectInstance; + ui8 direction; const CGHeroInstance *hero; //hero on board bool onboardAssaultAllowed; //if true, hero can attack units from transport @@ -296,7 +320,7 @@ public: AnimationPath overlayAnimation; //waves animations std::array flagAnimations; - CGBoat(); + CGBoat(IGameCallback * cb); bool isCoastVisitable() const override; template void serialize(Handler &h, const int version) @@ -327,6 +351,8 @@ protected: BoatId getBoatType() const override; public: + using CGObjectInstance::CGObjectInstance; + template void serialize(Handler & h, const int version) { h & static_cast(*this); @@ -340,6 +366,8 @@ protected: class DLL_LINKAGE CGMagi : public CGObjectInstance { public: + using CGObjectInstance::CGObjectInstance; + void initObj(CRandomGenerator & rand) override; void onHeroVisit(const CGHeroInstance * h) const override; @@ -352,11 +380,15 @@ public: class DLL_LINKAGE CGDenOfthieves : public CGObjectInstance { void onHeroVisit(const CGHeroInstance * h) const override; +public: + using CGObjectInstance::CGObjectInstance; }; class DLL_LINKAGE CGObelisk : public CTeamVisited { public: + using CTeamVisited::CTeamVisited; + static ui8 obeliskCount; //how many obelisks are on map static std::map visited; //map: team_id => how many obelisks has been visited @@ -376,6 +408,8 @@ protected: class DLL_LINKAGE CGLighthouse : public CGObjectInstance { public: + using CGObjectInstance::CGObjectInstance; + void onHeroVisit(const CGHeroInstance * h) const override; void initObj(CRandomGenerator & rand) override; @@ -392,7 +426,7 @@ protected: class DLL_LINKAGE CGTerrainPatch : public CGObjectInstance { public: - CGTerrainPatch() = default; + using CGObjectInstance::CGObjectInstance; virtual bool isTile2Terrain() const override { @@ -411,6 +445,8 @@ protected: void fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack) const override; public: + using CGObjectInstance::CGObjectInstance; + template void serialize(Handler &h, const int version) { h & static_cast(*this); diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 58721b5d0..804514510 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -160,8 +160,9 @@ bool TerrainTile::isWater() const return terType->isWater(); } -CMap::CMap() - : checksum(0) +CMap::CMap(IGameCallback * cb) + : GameCallbackHolder(cb) + , checksum(0) , grailPos(-1, -1, -1) , grailRadius(0) , uidCounter(0) diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index 051d991aa..97a45f7a4 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -11,6 +11,7 @@ #pragma once #include "CMapHeader.h" +#include "../GameCallbackHolder.h" #include "../MetaString.h" #include "../mapObjects/MiscObjects.h" // To serialize static props #include "../mapObjects/CQuest.h" // To serialize static props @@ -73,10 +74,10 @@ struct DLL_LINKAGE DisposedHero }; /// The map contains the map header, the tiles of the terrain, objects, heroes, towns, rumors... -class DLL_LINKAGE CMap : public CMapHeader +class DLL_LINKAGE CMap : public CMapHeader, public GameCallbackHolder { public: - CMap(); + explicit CMap(IGameCallback *cb); ~CMap(); void initTerrain(); diff --git a/lib/mapping/CMapService.cpp b/lib/mapping/CMapService.cpp index 15a21b142..d5ad8b37c 100644 --- a/lib/mapping/CMapService.cpp +++ b/lib/mapping/CMapService.cpp @@ -30,14 +30,14 @@ VCMI_LIB_NAMESPACE_BEGIN -std::unique_ptr CMapService::loadMap(const ResourcePath & name) const +std::unique_ptr CMapService::loadMap(const ResourcePath & name, IGameCallback * cb) const { std::string modName = VLC->modh->findResourceOrigin(name); std::string language = VLC->modh->getModLanguage(modName); std::string encoding = Languages::getLanguageOptions(language).encoding; auto stream = getStreamFromFS(name); - return getMapLoader(stream, name.getName(), modName, encoding)->loadMap(); + return getMapLoader(stream, name.getName(), modName, encoding)->loadMap(cb); } std::unique_ptr CMapService::loadMapHeader(const ResourcePath & name) const @@ -50,10 +50,10 @@ std::unique_ptr CMapService::loadMapHeader(const ResourcePath & name return getMapLoader(stream, name.getName(), modName, encoding)->loadMapHeader(); } -std::unique_ptr CMapService::loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const +std::unique_ptr CMapService::loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const { auto stream = getStreamFromMem(buffer, size); - std::unique_ptr map(getMapLoader(stream, name, modName, encoding)->loadMap()); + std::unique_ptr map(getMapLoader(stream, name, modName, encoding)->loadMap(cb)); std::unique_ptr header(map.get()); //might be original campaign and require patch diff --git a/lib/mapping/CMapService.h b/lib/mapping/CMapService.h index f2b89d423..abad7f8cd 100644 --- a/lib/mapping/CMapService.h +++ b/lib/mapping/CMapService.h @@ -10,7 +10,7 @@ #pragma once -#include "../modding/CModInfo.h" +#include "../modding/ModVerificationInfo.h" VCMI_LIB_NAMESPACE_BEGIN @@ -22,6 +22,7 @@ class CInputStream; class IMapLoader; class IMapPatcher; +class IGameCallback; using ModCompatibilityInfo = std::map; @@ -40,7 +41,7 @@ public: * @param name the name of the map * @return a unique ptr to the loaded map class */ - virtual std::unique_ptr loadMap(const ResourcePath & name) const = 0; + virtual std::unique_ptr loadMap(const ResourcePath & name, IGameCallback * cb) const = 0; /** * Loads the VCMI/H3 map header specified by the name. @@ -57,7 +58,7 @@ public: * @param name indicates name of file that will be used during map header patching * @return a unique ptr to the loaded map class */ - virtual std::unique_ptr loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const = 0; + virtual std::unique_ptr loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const = 0; /** * Loads the VCMI/H3 map header from a buffer. This method is temporarily @@ -82,9 +83,9 @@ public: CMapService() = default; virtual ~CMapService() = default; - std::unique_ptr loadMap(const ResourcePath & name) const override; + std::unique_ptr loadMap(const ResourcePath & name, IGameCallback * cb) const override; std::unique_ptr loadMapHeader(const ResourcePath & name) const override; - std::unique_ptr loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override; + std::unique_ptr loadMap(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const override; std::unique_ptr loadMapHeader(const uint8_t * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override; void saveMap(const std::unique_ptr & map, boost::filesystem::path fullPath) const override; @@ -142,7 +143,7 @@ public: * * @return a unique ptr of the loaded map class */ - virtual std::unique_ptr loadMap() = 0; + virtual std::unique_ptr loadMap(IGameCallback * cb) = 0; /** * Loads the VCMI/H3 map header. diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 0701921ed..30632da20 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -71,10 +71,10 @@ CMapLoaderH3M::CMapLoaderH3M(const std::string & mapName, const std::string & mo //must be instantiated in .cpp file for access to complete types of all member fields CMapLoaderH3M::~CMapLoaderH3M() = default; -std::unique_ptr CMapLoaderH3M::loadMap() +std::unique_ptr CMapLoaderH3M::loadMap(IGameCallback * cb) { // Init map object by parsing the input buffer - map = new CMap(); + map = new CMap(cb); mapHeader = std::unique_ptr(dynamic_cast(map)); init(); @@ -831,7 +831,7 @@ void CMapLoaderH3M::readPredefinedHeroes() if(!custom) continue; - auto * hero = new CGHeroInstance(); + auto * hero = new CGHeroInstance(map->cb); hero->ID = Obj::HERO; hero->subID = heroID; @@ -1005,7 +1005,7 @@ void CMapLoaderH3M::readObjectTemplates() CGObjectInstance * CMapLoaderH3M::readEvent(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven) { - auto * object = new CGEvent(); + auto * object = new CGEvent(map->cb); readBoxContent(object, mapPosition, idToBeGiven); @@ -1025,7 +1025,7 @@ CGObjectInstance * CMapLoaderH3M::readEvent(const int3 & mapPosition, const Obje CGObjectInstance * CMapLoaderH3M::readPandora(const int3 & mapPosition, const ObjectInstanceID & idToBeGiven) { - auto * object = new CGPandoraBox(); + auto * object = new CGPandoraBox(map->cb); readBoxContent(object, mapPosition, idToBeGiven); return object; } @@ -1080,7 +1080,7 @@ void CMapLoaderH3M::readBoxContent(CGPandoraBox * object, const int3 & mapPositi CGObjectInstance * CMapLoaderH3M::readMonster(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID) { - auto * object = new CGCreature(); + auto * object = new CGCreature(map->cb); if(features.levelAB) { @@ -1134,7 +1134,7 @@ CGObjectInstance * CMapLoaderH3M::readMonster(const int3 & mapPosition, const Ob CGObjectInstance * CMapLoaderH3M::readSign(const int3 & mapPosition) { - auto * object = new CGSignBottle(); + auto * object = new CGSignBottle(map->cb); object->message.appendTextID(readLocalizedString(TextIdentifier("sign", mapPosition.x, mapPosition.y, mapPosition.z, "message"))); reader->skipZero(4); return object; @@ -1260,7 +1260,7 @@ CGObjectInstance * CMapLoaderH3M::readScholar(const int3 & position, std::shared CGObjectInstance * CMapLoaderH3M::readGarrison(const int3 & mapPosition) { - auto * object = new CGGarrison(); + auto * object = new CGGarrison(map->cb); setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); readCreatureSet(object, 7); @@ -1277,7 +1277,7 @@ CGObjectInstance * CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::sh { ArtifactID artID = ArtifactID::NONE; //random, set later SpellID spellID = SpellID::NONE; - auto * object = new CGArtifact(); + auto * object = new CGArtifact(map->cb); readMessageAndGuards(object->message, object, mapPosition); @@ -1298,7 +1298,7 @@ CGObjectInstance * CMapLoaderH3M::readArtifact(const int3 & mapPosition, std::sh CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::shared_ptr objectTemplate) { - auto * object = new CGResource(); + auto * object = new CGResource(map->cb); readMessageAndGuards(object->message, object, mapPosition); @@ -1314,7 +1314,7 @@ CGObjectInstance * CMapLoaderH3M::readResource(const int3 & mapPosition, std::sh CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition, std::shared_ptr objectTemplate) { - auto * object = new CGMine(); + auto * object = new CGMine(map->cb); if(objectTemplate->subid < 7) { setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); @@ -1329,14 +1329,14 @@ CGObjectInstance * CMapLoaderH3M::readMine(const int3 & mapPosition, std::shared CGObjectInstance * CMapLoaderH3M::readDwelling(const int3 & position) { - auto * object = new CGDwelling(); + auto * object = new CGDwelling(map->cb); setOwnerAndValidate(position, object, reader->readPlayer32()); return object; } CGObjectInstance * CMapLoaderH3M::readDwellingRandom(const int3 & mapPosition, std::shared_ptr objectTemplate) { - auto * object = new CGDwelling(); + auto * object = new CGDwelling(map->cb); setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); @@ -1395,7 +1395,7 @@ CGObjectInstance * CMapLoaderH3M::readShrine(const int3 & position, std::shared_ CGObjectInstance * CMapLoaderH3M::readHeroPlaceholder(const int3 & mapPosition) { - auto * object = new CGHeroPlaceholder(); + auto * object = new CGHeroPlaceholder(map->cb); setOwnerAndValidate(mapPosition, object, reader->readPlayer()); @@ -1433,23 +1433,23 @@ CGObjectInstance * CMapLoaderH3M::readGrail(const int3 & mapPosition, std::share CGObjectInstance * CMapLoaderH3M::readGeneric(const int3 & mapPosition, std::shared_ptr objectTemplate) { if(VLC->objtypeh->knownSubObjects(objectTemplate->id).count(objectTemplate->subid)) - return VLC->objtypeh->getHandlerFor(objectTemplate->id, objectTemplate->subid)->create(objectTemplate); + return VLC->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(); + return new CGObjectInstance(map->cb); } CGObjectInstance * CMapLoaderH3M::readPyramid(const int3 & mapPosition, std::shared_ptr objectTemplate) { if(objectTemplate->subid == 0) - return new CBank(); + return new CBank(map->cb); - return new CGObjectInstance(); + return new CGObjectInstance(map->cb); } CGObjectInstance * CMapLoaderH3M::readQuestGuard(const int3 & mapPosition) { - auto * guard = new CGQuestGuard(); + auto * guard = new CGQuestGuard(map->cb); readQuest(guard, mapPosition); return guard; } @@ -1463,7 +1463,7 @@ CGObjectInstance * CMapLoaderH3M::readShipyard(const int3 & mapPosition, std::sh CGObjectInstance * CMapLoaderH3M::readLighthouse(const int3 & mapPosition) { - auto * object = new CGLighthouse(); + auto * object = new CGLighthouse(map->cb); setOwnerAndValidate(mapPosition, object, reader->readPlayer32()); return object; } @@ -1733,7 +1733,7 @@ void CMapLoaderH3M::setOwnerAndValidate(const int3 & mapPosition, CGObjectInstan CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const ObjectInstanceID & objectInstanceID) { - auto * object = new CGHeroInstance(); + auto * object = new CGHeroInstance(map->cb); if(features.levelAB) { @@ -1892,7 +1892,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec CGObjectInstance * CMapLoaderH3M::readSeerHut(const int3 & position, const ObjectInstanceID & idToBeGiven) { - auto * hut = new CGSeerHut(); + auto * hut = new CGSeerHut(map->cb); uint32_t questsCount = 1; @@ -2176,7 +2176,7 @@ int CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & position) CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_ptr objectTemplate) { - auto * object = new CGTownInstance(); + auto * object = new CGTownInstance(map->cb); if(features.levelAB) object->identifier = reader->readUInt32(); diff --git a/lib/mapping/MapFormatH3M.h b/lib/mapping/MapFormatH3M.h index d1c1591c6..a0064bdca 100644 --- a/lib/mapping/MapFormatH3M.h +++ b/lib/mapping/MapFormatH3M.h @@ -55,7 +55,7 @@ public: * * @return a unique ptr of the loaded map class */ - std::unique_ptr loadMap() override; + std::unique_ptr loadMap(IGameCallback * cb) override; /** * Loads the VCMI/H3 map header. diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index b342aca72..5a72b0a10 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -677,19 +677,19 @@ void CMapFormatJson::serializeTimedEvents(JsonSerializeFormat & handler) void CMapFormatJson::serializePredefinedHeroes(JsonSerializeFormat & handler) { - //todo:serializePredefinedHeroes + //todo:serializePredefinedHeroes - if(handler.saving) + if(handler.saving) { if(!map->predefinedHeroes.empty()) { auto predefinedHeroes = handler.enterStruct("predefinedHeroes"); - for(auto & hero : map->predefinedHeroes) + for(auto & hero : map->predefinedHeroes) { - auto predefinedHero = handler.enterStruct(hero->getHeroTypeName()); + auto predefinedHero = handler.enterStruct(hero->getHeroTypeName()); - hero->serializeJsonDefinition(handler); + hero->serializeJsonDefinition(handler); } } } @@ -697,13 +697,13 @@ void CMapFormatJson::serializePredefinedHeroes(JsonSerializeFormat & handler) { auto predefinedHeroes = handler.enterStruct("predefinedHeroes"); - const JsonNode & data = handler.getCurrent(); + const JsonNode & data = handler.getCurrent(); - for(const auto & p : data.Struct()) + for(const auto & p : data.Struct()) { auto predefinedHero = handler.enterStruct(p.first); - auto * hero = new CGHeroInstance(); + auto * hero = new CGHeroInstance(map->cb); hero->ID = Obj::HERO; hero->setHeroTypeName(p.first); hero->serializeJsonDefinition(handler); @@ -777,10 +777,10 @@ CMapLoaderJson::CMapLoaderJson(CInputStream * stream) { } -std::unique_ptr CMapLoaderJson::loadMap() +std::unique_ptr CMapLoaderJson::loadMap(IGameCallback * cb) { LOG_TRACE(logGlobal); - auto result = std::make_unique(); + auto result = std::make_unique(cb); map = result.get(); mapHeader = map; readMap(); @@ -1081,7 +1081,7 @@ void CMapLoaderJson::MapObjectLoader::construct() appearance->readJson(configuration["template"], false); // Will be destroyed soon and replaced with shared template - instance = handler->create(std::shared_ptr(appearance)); + instance = handler->create(owner->map->cb, std::shared_ptr(appearance)); instance->id = ObjectInstanceID(static_cast(owner->map->objects.size())); instance->instanceName = jsonKey; diff --git a/lib/mapping/MapFormatJson.h b/lib/mapping/MapFormatJson.h index 6efe186b4..fb8a78e2f 100644 --- a/lib/mapping/MapFormatJson.h +++ b/lib/mapping/MapFormatJson.h @@ -168,7 +168,7 @@ public: * * @return a unique ptr of the loaded map class */ - std::unique_ptr loadMap() override; + std::unique_ptr loadMap(IGameCallback * cb) override; /** * Loads the VCMI/Json map header. diff --git a/lib/mapping/ObstacleProxy.cpp b/lib/mapping/ObstacleProxy.cpp index eeb6b798d..a15b95a9f 100644 --- a/lib/mapping/ObstacleProxy.cpp +++ b/lib/mapping/ObstacleProxy.cpp @@ -79,7 +79,7 @@ int ObstacleProxy::getWeightedObjects(const int3 & tile, CRandomGenerator & rand for(const auto & temp : shuffledObstacles) { auto handler = VLC->objtypeh->getHandlerFor(temp->id, temp->subid); - auto * obj = handler->create(temp); + auto * obj = handler->create(nullptr, temp); allObjects.emplace_back(*obj); rmg::Object * rmgObject = &allObjects.back(); for(const auto & offset : obj->getBlockedOffsets()) diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 41eb78b27..ae54e20d9 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1497,7 +1497,7 @@ void NewObject::applyGs(CGameState *gs) auto handler = VLC->objtypeh->getHandlerFor(ID, subID); - CGObjectInstance * o = handler->create(); + CGObjectInstance * o = handler->create(gs->callback, nullptr); handler->configureObject(o, gs->getRandomGenerator()); assert(o->ID == this->ID); diff --git a/lib/rewardable/Info.cpp b/lib/rewardable/Info.cpp index 6e368e5f9..c9b884fc3 100644 --- a/lib/rewardable/Info.cpp +++ b/lib/rewardable/Info.cpp @@ -123,28 +123,29 @@ Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Conf void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const { auto const & variables = object.variables.values; + JsonRandom randomizer(nullptr); - limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng, variables); - limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng, variables); - limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables); - limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables); + limiter.dayOfWeek = randomizer.loadValue(source["dayOfWeek"], rng, variables); + limiter.daysPassed = randomizer.loadValue(source["daysPassed"], rng, variables); + limiter.heroExperience = randomizer.loadValue(source["heroExperience"], rng, variables); + limiter.heroLevel = randomizer.loadValue(source["heroLevel"], rng, variables); limiter.canLearnSkills = source["canLearnSkills"].Bool(); - limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables); - limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng, variables); + limiter.manaPercentage = randomizer.loadValue(source["manaPercentage"], rng, variables); + limiter.manaPoints = randomizer.loadValue(source["manaPoints"], rng, variables); - limiter.resources = JsonRandom::loadResources(source["resources"], rng, variables); + limiter.resources = randomizer.loadResources(source["resources"], rng, variables); - limiter.primary = JsonRandom::loadPrimaries(source["primary"], rng, variables); - limiter.secondary = JsonRandom::loadSecondaries(source["secondary"], rng, variables); - limiter.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng, variables); - limiter.spells = JsonRandom::loadSpells(source["spells"], rng, variables); - limiter.canLearnSpells = JsonRandom::loadSpells(source["canLearnSpells"], rng, variables); - limiter.creatures = JsonRandom::loadCreatures(source["creatures"], rng, variables); + limiter.primary = randomizer.loadPrimaries(source["primary"], rng, variables); + limiter.secondary = randomizer.loadSecondaries(source["secondary"], rng, variables); + limiter.artifacts = randomizer.loadArtifacts(source["artifacts"], rng, variables); + limiter.spells = randomizer.loadSpells(source["spells"], rng, variables); + limiter.canLearnSpells = randomizer.loadSpells(source["canLearnSpells"], rng, variables); + limiter.creatures = randomizer.loadCreatures(source["creatures"], rng, variables); - limiter.players = JsonRandom::loadColors(source["colors"], rng, variables); - limiter.heroes = JsonRandom::loadHeroes(source["heroes"], rng); - limiter.heroClasses = JsonRandom::loadHeroClasses(source["heroClasses"], rng); + limiter.players = randomizer.loadColors(source["colors"], rng, variables); + limiter.heroes = randomizer.loadHeroes(source["heroes"], rng); + limiter.heroClasses = randomizer.loadHeroClasses(source["heroClasses"], rng); limiter.allOf = configureSublimiters(object, rng, source["allOf"] ); limiter.anyOf = configureSublimiters(object, rng, source["anyOf"] ); @@ -154,31 +155,32 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Reward & reward, const JsonNode & source) const { auto const & variables = object.variables.values; + JsonRandom randomizer(nullptr); - reward.resources = JsonRandom::loadResources(source["resources"], rng, variables); + reward.resources = randomizer.loadResources(source["resources"], rng, variables); - reward.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables); - reward.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables); + reward.heroExperience = randomizer.loadValue(source["heroExperience"], rng, variables); + reward.heroLevel = randomizer.loadValue(source["heroLevel"], rng, variables); - reward.manaDiff = JsonRandom::loadValue(source["manaPoints"], rng, variables); - reward.manaOverflowFactor = JsonRandom::loadValue(source["manaOverflowFactor"], rng, variables); - reward.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables, -1); + reward.manaDiff = randomizer.loadValue(source["manaPoints"], rng, variables); + reward.manaOverflowFactor = randomizer.loadValue(source["manaOverflowFactor"], rng, variables); + reward.manaPercentage = randomizer.loadValue(source["manaPercentage"], rng, variables, -1); - reward.movePoints = JsonRandom::loadValue(source["movePoints"], rng, variables); - reward.movePercentage = JsonRandom::loadValue(source["movePercentage"], rng, variables, -1); + reward.movePoints = randomizer.loadValue(source["movePoints"], rng, variables); + reward.movePercentage = randomizer.loadValue(source["movePercentage"], rng, variables, -1); reward.removeObject = source["removeObject"].Bool(); - reward.bonuses = JsonRandom::loadBonuses(source["bonuses"]); + reward.bonuses = randomizer.loadBonuses(source["bonuses"]); - reward.primary = JsonRandom::loadPrimaries(source["primary"], rng, variables); - reward.secondary = JsonRandom::loadSecondaries(source["secondary"], rng, variables); + reward.primary = randomizer.loadPrimaries(source["primary"], rng, variables); + reward.secondary = randomizer.loadSecondaries(source["secondary"], rng, variables); - reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng, variables); - reward.spells = JsonRandom::loadSpells(source["spells"], rng, variables); - reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng, variables); + reward.artifacts = randomizer.loadArtifacts(source["artifacts"], rng, variables); + reward.spells = randomizer.loadSpells(source["spells"], rng, variables); + reward.creatures = randomizer.loadCreatures(source["creatures"], rng, variables); if(!source["spellCast"].isNull() && source["spellCast"].isStruct()) { - reward.spellCast.first = JsonRandom::loadSpell(source["spellCast"]["spell"], rng, variables); + reward.spellCast.first = randomizer.loadSpell(source["spellCast"]["spell"], rng, variables); reward.spellCast.second = source["spellCast"]["schoolLevel"].Integer(); } @@ -187,13 +189,13 @@ void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRand auto const & entry = source["revealTiles"]; reward.revealTiles = RewardRevealTiles(); - reward.revealTiles->radius = JsonRandom::loadValue(entry["radius"], rng, variables); + reward.revealTiles->radius = randomizer.loadValue(entry["radius"], rng, variables); reward.revealTiles->hide = entry["hide"].Bool(); - reward.revealTiles->scoreSurface = JsonRandom::loadValue(entry["surface"], rng, variables); - reward.revealTiles->scoreSubterra = JsonRandom::loadValue(entry["subterra"], rng, variables); - reward.revealTiles->scoreWater = JsonRandom::loadValue(entry["water"], rng, variables); - reward.revealTiles->scoreRock = JsonRandom::loadValue(entry["rock"], rng, variables); + reward.revealTiles->scoreSurface = randomizer.loadValue(entry["surface"], rng, variables); + reward.revealTiles->scoreSubterra = randomizer.loadValue(entry["subterra"], rng, variables); + reward.revealTiles->scoreWater = randomizer.loadValue(entry["water"], rng, variables); + reward.revealTiles->scoreRock = randomizer.loadValue(entry["rock"], rng, variables); } for ( auto node : source["changeCreatures"].Struct() ) @@ -216,6 +218,8 @@ void Rewardable::Info::configureResetInfo(Rewardable::Configuration & object, CR void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const { + JsonRandom randomizer(nullptr); + for(const auto & category : source.Struct()) { for(const auto & entry : category.second.Struct()) @@ -225,19 +229,19 @@ void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CR int32_t value = -1; if (category.first == "number") - value = JsonRandom::loadValue(input, rng, object.variables.values); + value = randomizer.loadValue(input, rng, object.variables.values); if (category.first == "artifact") - value = JsonRandom::loadArtifact(input, rng, object.variables.values).getNum(); + value = randomizer.loadArtifact(input, rng, object.variables.values).getNum(); if (category.first == "spell") - value = JsonRandom::loadSpell(input, rng, object.variables.values).getNum(); + value = randomizer.loadSpell(input, rng, object.variables.values).getNum(); if (category.first == "primarySkill") - value = JsonRandom::loadPrimary(input, rng, object.variables.values).getNum(); + value = randomizer.loadPrimary(input, rng, object.variables.values).getNum(); if (category.first == "secondarySkill") - value = JsonRandom::loadSecondary(input, rng, object.variables.values).getNum(); + value = randomizer.loadSecondary(input, rng, object.variables.values).getNum(); object.initVariable(category.first, entry.first, value); } diff --git a/lib/rewardable/Limiter.cpp b/lib/rewardable/Limiter.cpp index f4a03edfd..339f45415 100644 --- a/lib/rewardable/Limiter.cpp +++ b/lib/rewardable/Limiter.cpp @@ -69,13 +69,13 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const { if(dayOfWeek != 0) { - if (IObjectInterface::cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek) + if (hero->cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek) return false; } if(daysPassed != 0) { - if (IObjectInterface::cb->getDate(Date::DAY) < daysPassed) + if (hero->cb->getDate(Date::DAY) < daysPassed) return false; } @@ -92,7 +92,7 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const return false; } - if(!IObjectInterface::cb->getPlayerState(hero->tempOwner)->resources.canAfford(resources)) + if(!hero->cb->getPlayerState(hero->tempOwner)->resources.canAfford(resources)) return false; if(heroLevel > static_cast(hero->level)) diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 070e507c2..cd0a6a4ce 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -33,14 +33,14 @@ VCMI_LIB_NAMESPACE_BEGIN -CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) : +CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, IGameCallback * cb, int RandomSeed) : mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0) { loadConfig(); rand.setSeed(this->randomSeed); mapGenOptions.finalize(rand); - map = std::make_unique(mapGenOptions); + map = std::make_unique(mapGenOptions, cb); placer = std::make_shared(*map); } diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index 11e5d999e..e75d9fe3a 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -26,6 +26,7 @@ class RmgMap; class CMap; class Zone; class CZonePlacer; +class IGameCallback; using JsonVector = std::vector; @@ -56,7 +57,7 @@ public: bool singleThread; }; - explicit CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed = std::time(nullptr)); + explicit CMapGenerator(CMapGenOptions& mapGenOptions, IGameCallback * cb, int RandomSeed); ~CMapGenerator(); // required due to std::unique_ptr const Config & getConfig() const; diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index 749e0efdb..1e2d9ebc2 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -38,10 +38,10 @@ VCMI_LIB_NAMESPACE_BEGIN -RmgMap::RmgMap(const CMapGenOptions& mapGenOptions) : +RmgMap::RmgMap(const CMapGenOptions& mapGenOptions, IGameCallback * cb) : mapGenOptions(mapGenOptions), zonesTotal(0) { - mapInstance = std::make_unique(); + mapInstance = std::make_unique(cb); mapProxy = std::make_shared(*this); getEditManager()->getUndoManager().setUndoRedoLimit(0); } diff --git a/lib/rmg/RmgMap.h b/lib/rmg/RmgMap.h index 5acffb133..a1e5a5e10 100644 --- a/lib/rmg/RmgMap.h +++ b/lib/rmg/RmgMap.h @@ -33,7 +33,7 @@ public: std::shared_ptr getMapProxy() const; CMap & getMap(const CMapGenerator *) const; //limited access - RmgMap(const CMapGenOptions& mapGenOptions); + RmgMap(const CMapGenOptions& mapGenOptions, IGameCallback * cb); ~RmgMap() = default; CMapEditManager* getEditManager() const; diff --git a/lib/rmg/modificators/ConnectionsPlacer.cpp b/lib/rmg/modificators/ConnectionsPlacer.cpp index 73e9b5837..d2c1ddada 100644 --- a/lib/rmg/modificators/ConnectionsPlacer.cpp +++ b/lib/rmg/modificators/ConnectionsPlacer.cpp @@ -314,8 +314,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c auto & managerOther = *otherZone->getModificator(); auto factory = VLC->objtypeh->getHandlerFor(Obj::SUBTERRANEAN_GATE, 0); - auto * gate1 = factory->create(); - auto * gate2 = factory->create(); + auto * gate1 = factory->create(map.mapInstance->cb, nullptr); + auto * gate2 = factory->create(map.mapInstance->cb, nullptr); rmg::Object rmgGate1(*gate1); rmg::Object rmgGate2(*gate2); rmgGate1.setTemplate(zone.getTerrainType(), zone.getRand()); @@ -368,8 +368,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c if(!success) { auto factory = VLC->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, generator.getNextMonlithIndex()); - auto * teleport1 = factory->create(); - auto * teleport2 = factory->create(); + auto * teleport1 = factory->create(map.mapInstance->cb, nullptr); + auto * teleport2 = factory->create(map.mapInstance->cb, nullptr); RequiredObjectInfo obj1(teleport1, connection.getGuardStrength(), allowRoad); RequiredObjectInfo obj2(teleport2, connection.getGuardStrength(), allowRoad); diff --git a/lib/rmg/modificators/MinePlacer.cpp b/lib/rmg/modificators/MinePlacer.cpp index 880e0db9a..88ee45629 100644 --- a/lib/rmg/modificators/MinePlacer.cpp +++ b/lib/rmg/modificators/MinePlacer.cpp @@ -56,7 +56,7 @@ bool MinePlacer::placeMines(ObjectManager & manager) { auto mineHandler = VLC->objtypeh->getHandlerFor(Obj::MINE, res); const auto & rmginfo = mineHandler->getRMGInfo(); - auto * mine = dynamic_cast(mineHandler->create()); + auto * mine = dynamic_cast(mineHandler->create(map.mapInstance->cb, nullptr)); mine->producedResource = res; mine->tempOwner = PlayerColor::NEUTRAL; mine->producedQuantity = mine->defaultResProduction(); @@ -87,7 +87,7 @@ bool MinePlacer::placeMines(ObjectManager & manager) { for(int rc = zone.getRand().nextInt(1, extraRes); rc > 0; --rc) { - auto * resource = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create()); + auto * resource = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::RESOURCE, mine->producedResource)->create(map.mapInstance->cb, nullptr)); resource->amount = CGResource::RANDOM_AMOUNT; RequiredObjectInfo roi; diff --git a/lib/rmg/modificators/ObjectDistributor.cpp b/lib/rmg/modificators/ObjectDistributor.cpp index 89910c33f..4f08fc8b9 100644 --- a/lib/rmg/modificators/ObjectDistributor.cpp +++ b/lib/rmg/modificators/ObjectDistributor.cpp @@ -79,9 +79,9 @@ void ObjectDistributor::distributeLimitedObjects() RandomGeneratorUtil::randomShuffle(matchingZones, zone.getRand()); for (auto& zone : matchingZones) { - oi.generateObject = [primaryID, secondaryID]() -> CGObjectInstance * + oi.generateObject = [this, primaryID, secondaryID]() -> CGObjectInstance * { - return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(); + return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(map.mapInstance->cb, nullptr); }; oi.value = rmgInfo.value; diff --git a/lib/rmg/modificators/ObjectManager.cpp b/lib/rmg/modificators/ObjectManager.cpp index 75f18d5fa..6bc51579c 100644 --- a/lib/rmg/modificators/ObjectManager.cpp +++ b/lib/rmg/modificators/ObjectManager.cpp @@ -716,7 +716,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard) auto guardFactory = VLC->objtypeh->getHandlerFor(Obj::MONSTER, creId); - auto * guard = dynamic_cast(guardFactory->create()); + auto * guard = dynamic_cast(guardFactory->create(map.mapInstance->cb, nullptr)); guard->character = CGCreature::HOSTILE; auto * hlp = new CStackInstance(creId, amount); //will be set during initialization diff --git a/lib/rmg/modificators/QuestArtifactPlacer.cpp b/lib/rmg/modificators/QuestArtifactPlacer.cpp index 17a181716..812aa1df0 100644 --- a/lib/rmg/modificators/QuestArtifactPlacer.cpp +++ b/lib/rmg/modificators/QuestArtifactPlacer.cpp @@ -99,7 +99,7 @@ void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand) //Update appearance. Terrain is irrelevant. auto handler = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, artifactToPlace); - auto newObj = handler->create(); + auto newObj = handler->create(map.mapInstance->cb, nullptr); auto templates = handler->getTemplates(); //artifactToReplace->appearance = templates.front(); newObj->appearance = templates.front(); diff --git a/lib/rmg/modificators/RiverPlacer.cpp b/lib/rmg/modificators/RiverPlacer.cpp index d9c7af3e1..c42f24513 100644 --- a/lib/rmg/modificators/RiverPlacer.cpp +++ b/lib/rmg/modificators/RiverPlacer.cpp @@ -395,7 +395,7 @@ void RiverPlacer::connectRiver(const int3 & tile) { if(templ->animationFile == targetTemplateName) { - auto * obj = handler->create(templ); + auto * obj = handler->create(map.mapInstance->cb, templ); rmg::Object deltaObj(*obj, deltaPositions[pos]); deltaObj.finalize(map, zone.getRand()); } diff --git a/lib/rmg/modificators/TownPlacer.cpp b/lib/rmg/modificators/TownPlacer.cpp index baa6b2d6e..ca3542e48 100644 --- a/lib/rmg/modificators/TownPlacer.cpp +++ b/lib/rmg/modificators/TownPlacer.cpp @@ -71,7 +71,7 @@ void TownPlacer::placeTowns(ObjectManager & manager) auto townFactory = VLC->objtypeh->getHandlerFor(Obj::TOWN, zone.getTownType()); - CGTownInstance * town = dynamic_cast(townFactory->create()); + CGTownInstance * town = dynamic_cast(townFactory->create(map.mapInstance->cb, nullptr)); town->tempOwner = player; town->builtBuildings.insert(BuildingID::FORT); town->builtBuildings.insert(BuildingID::DEFAULT); @@ -193,7 +193,7 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player } auto townFactory = VLC->objtypeh->getHandlerFor(Obj::TOWN, subType); - auto * town = dynamic_cast(townFactory->create()); + auto * town = dynamic_cast(townFactory->create(map.mapInstance->cb, nullptr)); town->ID = Obj::TOWN; town->tempOwner = player; diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index 8f92cea55..aeedeb1e8 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -80,9 +80,9 @@ void TreasurePlacer::addAllPossibleObjects() continue; } - oi.generateObject = [primaryID, secondaryID]() -> CGObjectInstance * + oi.generateObject = [this, primaryID, secondaryID]() -> CGObjectInstance * { - return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(); + return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(map.mapInstance->cb, nullptr); }; oi.value = rmgInfo.value; oi.probability = rmgInfo.rarity; @@ -133,7 +133,7 @@ void TreasurePlacer::addAllPossibleObjects() }; auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0); - auto* obj = dynamic_cast(factory->create()); + auto* obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); obj->setHeroType(hid); //will be initialized later obj->exp = generator.getConfig().prisonExperience[i]; @@ -197,9 +197,9 @@ void TreasurePlacer::addAllPossibleObjects() oi.value = static_cast(cre->getAIValue() * cre->getGrowth() * (1 + (nativeZonesCount / map.getTotalZoneCount()) + (nativeZonesCount / 2))); oi.probability = 40; - oi.generateObject = [secondaryID, dwellingType]() -> CGObjectInstance * + oi.generateObject = [this, secondaryID, dwellingType]() -> CGObjectInstance * { - auto * obj = VLC->objtypeh->getHandlerFor(dwellingType, secondaryID)->create(); + auto * obj = VLC->objtypeh->getHandlerFor(dwellingType, secondaryID)->create(map.mapInstance->cb, nullptr); obj->tempOwner = PlayerColor::NEUTRAL; return obj; }; @@ -215,7 +215,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [i, this]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::SPELL_SCROLL, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); std::vector out; for(auto spell : VLC->spellh->objects) //spellh size appears to be greater (?) @@ -239,10 +239,10 @@ void TreasurePlacer::addAllPossibleObjects() //pandora box with gold for(int i = 1; i < 5; i++) { - oi.generateObject = [i]() -> CGObjectInstance * + oi.generateObject = [this, i]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.resources[EGameResID::GOLD] = i * 5000; @@ -261,10 +261,10 @@ void TreasurePlacer::addAllPossibleObjects() //pandora box with experience for(int i = 1; i < 5; i++) { - oi.generateObject = [i]() -> CGObjectInstance * + oi.generateObject = [this, i]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.heroExperience = i * 5000; @@ -323,10 +323,10 @@ void TreasurePlacer::addAllPossibleObjects() if(!creaturesAmount) continue; - oi.generateObject = [creature, creaturesAmount]() -> CGObjectInstance * + oi.generateObject = [this, creature, creaturesAmount]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.creatures.emplace_back(creature, creaturesAmount); @@ -348,7 +348,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [i, this]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); std::vector spells; for(auto spell : VLC->spellh->objects) @@ -381,7 +381,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [i, this]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); std::vector spells; for(auto spell : VLC->spellh->objects) @@ -413,7 +413,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [this]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); std::vector spells; for(auto spell : VLC->spellh->objects) @@ -491,7 +491,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.creatures.emplace_back(creature->getId(), creaturesAmount); @@ -535,7 +535,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.heroExperience = generator.getConfig().questRewardValues[i]; @@ -553,7 +553,7 @@ void TreasurePlacer::addAllPossibleObjects() oi.generateObject = [i, randomAppearance, this, setRandomArtifact]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance); - auto * obj = dynamic_cast(factory->create()); + auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.resources[EGameResID::GOLD] = generator.getConfig().questRewardValues[i]; diff --git a/lib/rmg/modificators/WaterProxy.cpp b/lib/rmg/modificators/WaterProxy.cpp index fae559182..1c0a0ceec 100644 --- a/lib/rmg/modificators/WaterProxy.cpp +++ b/lib/rmg/modificators/WaterProxy.cpp @@ -240,7 +240,7 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout for(auto subObj : subObjects) { //making a temporary object - std::unique_ptr obj(VLC->objtypeh->getHandlerFor(Obj::BOAT, subObj)->create()); + std::unique_ptr obj(VLC->objtypeh->getHandlerFor(Obj::BOAT, subObj)->create(map.mapInstance->cb, nullptr)); if(auto * testBoat = dynamic_cast(obj.get())) { if(testBoat->layer == EPathfindingLayer::SAIL) @@ -251,7 +251,7 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout if(sailingBoatTypes.empty()) return false; - auto * boat = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create()); + auto * boat = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(sailingBoatTypes, zone.getRand()))->create(map.mapInstance->cb, nullptr)); rmg::Object rmgObject(*boat); rmgObject.setTemplate(zone.getTerrainType(), zone.getRand()); @@ -315,7 +315,7 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, bool return false; int subtype = chooseRandomAppearance(zone.getRand(), Obj::SHIPYARD, land.getTerrainType()); - auto * shipyard = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create()); + auto * shipyard = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::SHIPYARD, subtype)->create(map.mapInstance->cb, nullptr)); shipyard->tempOwner = PlayerColor::NEUTRAL; rmg::Object rmgObject(*shipyard); diff --git a/lib/serializer/BinaryDeserializer.h b/lib/serializer/BinaryDeserializer.h index aa2b40f21..c503da472 100644 --- a/lib/serializer/BinaryDeserializer.h +++ b/lib/serializer/BinaryDeserializer.h @@ -69,22 +69,33 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase template struct ClassObjectCreator { - static T *invoke() + static T *invoke(IGameCallback *cb) { - static_assert(!std::is_abstract::value, "Cannot call new upon abstract classes!"); + static_assert(!std::is_base_of_v, "Cannot call new upon map objects!"); + static_assert(!std::is_abstract_v, "Cannot call new upon abstract classes!"); return new T(); } }; template - struct ClassObjectCreator::value>::type> + struct ClassObjectCreator>> { - static T *invoke() + static T *invoke(IGameCallback *cb) { throw std::runtime_error("Something went really wrong during deserialization. Attempted creating an object of an abstract class " + std::string(typeid(T).name())); } }; + template + struct ClassObjectCreator && !std::is_abstract_v>> + { + static T *invoke(IGameCallback *cb) + { + static_assert(!std::is_abstract::value, "Cannot call new upon abstract classes!"); + return new T(cb); + } + }; + STRONG_INLINE ui32 readAndCheckLength() { ui32 length; @@ -121,7 +132,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase auto & s = static_cast(ar); //create new object under pointer - Type * ptr = ClassObjectCreator::invoke(); //does new npT or throws for abstract classes + Type * ptr = ClassObjectCreator::invoke(nullptr); //does new npT or throws for abstract classes s.ptrAllocated(ptr, pid); assert(s.fileVersion != 0); @@ -281,7 +292,7 @@ public: { typedef typename std::remove_pointer::type npT; typedef typename std::remove_const::type ncpT; - data = ClassObjectCreator::invoke(); + data = ClassObjectCreator::invoke(nullptr); ptrAllocated(data, pid); load(*data); } diff --git a/lib/spells/ISpellMechanics.cpp b/lib/spells/ISpellMechanics.cpp index 8c8eff5ab..6d95d6bf1 100644 --- a/lib/spells/ISpellMechanics.cpp +++ b/lib/spells/ISpellMechanics.cpp @@ -139,7 +139,6 @@ public: BattleCast::BattleCast(const CBattleInfoCallback * cb_, const Caster * caster_, const Mode mode_, const CSpell * spell_): spell(spell_), cb(cb_), - gameCb(IObjectInterface::cb), //FIXME: pass player callback (problem is that BattleAI do not have one) caster(caster_), mode(mode_), smart(boost::logic::indeterminate), @@ -150,7 +149,6 @@ BattleCast::BattleCast(const CBattleInfoCallback * cb_, const Caster * caster_, BattleCast::BattleCast(const BattleCast & orig, const Caster * caster_) : spell(orig.spell), cb(orig.cb), - gameCb(orig.gameCb), caster(caster_), mode(Mode::MAGIC_MIRROR), magicSkillLevel(orig.magicSkillLevel), @@ -184,11 +182,6 @@ const CBattleInfoCallback * BattleCast::getBattle() const return cb; } -const IGameInfoCallback * BattleCast::getGame() const -{ - return gameCb; -} - BattleCast::OptionalValue BattleCast::getSpellLevel() const { return magicSkillLevel; @@ -417,8 +410,7 @@ BaseMechanics::BaseMechanics(const IBattleCast * event): mode(event->getMode()), smart(event->isSmart()), massive(event->isMassive()), - cb(event->getBattle()), - gameCb(event->getGame()) + cb(event->getBattle()) { caster = event->getCaster(); @@ -696,11 +688,6 @@ const Service * BaseMechanics::spells() const return VLC->spells(); //todo: redirect } -const IGameInfoCallback * BaseMechanics::game() const -{ - return gameCb; -} - const CBattleInfoCallback * BaseMechanics::battle() const { return cb; diff --git a/lib/spells/ISpellMechanics.h b/lib/spells/ISpellMechanics.h index 2a0f8603d..982b1f744 100644 --- a/lib/spells/ISpellMechanics.h +++ b/lib/spells/ISpellMechanics.h @@ -27,7 +27,6 @@ class CreatureService; class CMap; class CGameInfoCallback; class CBattleInfoCallback; -class IGameInfoCallback; class JsonNode; class CStack; class CGObjectInstance; @@ -81,7 +80,6 @@ public: virtual Mode getMode() const = 0; virtual const Caster * getCaster() const = 0; virtual const CBattleInfoCallback * getBattle() const = 0; - virtual const IGameInfoCallback * getGame() const = 0; virtual OptionalValue getSpellLevel() const = 0; @@ -114,7 +112,6 @@ public: Mode getMode() const override; const Caster * getCaster() const override; const CBattleInfoCallback * getBattle() const override; - const IGameInfoCallback * getGame() const override; OptionalValue getSpellLevel() const override; @@ -162,7 +159,6 @@ private: Mode mode; const CSpell * spell; const CBattleInfoCallback * cb; - const IGameInfoCallback * gameCb; const Caster * caster; }; @@ -252,7 +248,6 @@ public: #endif virtual const Service * spells() const = 0; - virtual const IGameInfoCallback * game() const = 0; virtual const CBattleInfoCallback * battle() const = 0; const Caster * caster; @@ -311,7 +306,6 @@ public: #endif const Service * spells() const override; - const IGameInfoCallback * game() const override; const CBattleInfoCallback * battle() const override; protected: @@ -335,7 +329,6 @@ private: boost::logic::tribool smart; boost::logic::tribool massive; - const IGameInfoCallback * gameCb; const CBattleInfoCallback * cb; }; diff --git a/mapeditor/mainwindow.cpp b/mapeditor/mainwindow.cpp index 15df16223..bc4e609c7 100644 --- a/mapeditor/mainwindow.cpp +++ b/mapeditor/mainwindow.cpp @@ -347,7 +347,7 @@ std::unique_ptr MainWindow::openMapInternal(const QString & filenameSelect if(!modList.empty()) throw ModIncompatibility(modList); - return mapService.loadMap(resId); + return mapService.loadMap(resId, nullptr); } else throw std::runtime_error("Corrupted map"); @@ -546,7 +546,7 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool useCust } //create object to extract name - std::unique_ptr temporaryObj(factory->create(templ)); + std::unique_ptr temporaryObj(factory->create(nullptr, templ)); QString translated = useCustomName ? QString::fromStdString(temporaryObj->getObjectName().c_str()) : subGroupName; itemType->setText(translated); diff --git a/mapeditor/mapview.cpp b/mapeditor/mapview.cpp index 14c95bfbf..5e37b48ff 100644 --- a/mapeditor/mapview.cpp +++ b/mapeditor/mapview.cpp @@ -593,7 +593,7 @@ void MapView::dragEnterEvent(QDragEnterEvent * event) auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId); auto templ = factory->getTemplates()[templateId]; controller->discardObject(sc->level); - controller->createObject(sc->level, factory->create(templ)); + controller->createObject(sc->level, factory->create(nullptr, templ)); } } diff --git a/mapeditor/windownewmap.cpp b/mapeditor/windownewmap.cpp index bfe436e99..cc673b4bd 100644 --- a/mapeditor/windownewmap.cpp +++ b/mapeditor/windownewmap.cpp @@ -231,7 +231,7 @@ void generateRandomMap(CMapGenerator & gen, MainWindow * window) std::unique_ptr generateEmptyMap(CMapGenOptions & options) { - std::unique_ptr map(new CMap); + auto map = std::make_unique(nullptr); map->version = EMapFormat::VCMI; map->width = options.getWidth(); map->height = options.getHeight(); @@ -281,7 +281,7 @@ void WindowNewMap::on_okButton_clicked() if(ui->checkSeed->isChecked() && !ui->lineSeed->text().isEmpty()) seed = ui->lineSeed->text().toInt(); - CMapGenerator generator(mapGenOptions, seed); + CMapGenerator generator(mapGenOptions, nullptr, seed); auto progressBarWnd = new GeneratorProgress(generator, this); progressBarWnd->show(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 7fe7e416e..dc65635b2 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -511,7 +511,6 @@ CGameHandler::CGameHandler(CVCMIServer * lobby) , turnTimerHandler(*this) { QID = 1; - IObjectInterface::cb = this; applier = std::make_shared>(); registerTypesServerPacks(*applier); @@ -541,7 +540,7 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack } CMapService mapService; gs = new CGameState(); - gs->preInit(VLC); + gs->preInit(VLC, this); logGlobal->info("Gamestate created!"); gs->init(&mapService, si, progressTracking); logGlobal->info("Gamestate initialized!"); @@ -1838,7 +1837,7 @@ bool CGameHandler::load(const std::string & filename) lobby->announceMessage(std::string("Failed to load game: ") + e.what()); return false; } - gs->preInit(VLC); + gs->preInit(VLC, this); gs->updateOnLoad(lobby->si.get()); return true; }