From d5c4478816106175e7ab6d6bb5e90723fce6f49d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 31 Dec 2023 23:43:35 +0200 Subject: [PATCH 01/13] Remove most of non-const access to VLC entities --- AI/BattleAI/BattleEvaluator.cpp | 9 +- AI/Nullkiller/AIUtility.cpp | 4 +- AI/Nullkiller/AIUtility.h | 1 - AI/Nullkiller/Analyzers/ArmyManager.cpp | 16 +-- AI/Nullkiller/Goals/BuyArmy.cpp | 4 +- AI/Nullkiller/Pathfinding/Actors.cpp | 4 +- client/CGameInfo.cpp | 3 - client/CGameInfo.h | 29 ++--- client/Client.cpp | 4 +- lib/ArtifactUtils.cpp | 6 +- lib/ArtifactUtils.h | 2 +- lib/CArtHandler.cpp | 6 +- lib/CArtHandler.h | 8 +- lib/CArtifactInstance.cpp | 6 +- lib/CArtifactInstance.h | 6 +- lib/CCreatureHandler.cpp | 13 +- lib/CCreatureHandler.h | 2 +- lib/CCreatureSet.cpp | 7 +- lib/CGameInfoCallback.cpp | 2 +- lib/CHeroHandler.cpp | 19 ++- lib/CHeroHandler.h | 8 +- lib/CTownHandler.cpp | 2 +- lib/IHandlerBase.h | 42 ++++--- lib/JsonRandom.cpp | 3 +- lib/RiverHandler.cpp | 2 +- lib/RoadHandler.cpp | 2 +- lib/VCMI_Lib.cpp | 112 ++++-------------- lib/VCMI_Lib.h | 51 ++++---- lib/constants/EntityIdentifiers.cpp | 10 ++ lib/constants/EntityIdentifiers.h | 5 + lib/gameState/CGameStateCampaign.cpp | 2 +- .../CommonConstructors.cpp | 2 +- .../CommonConstructors.h | 4 +- .../DwellingInstanceConstructor.cpp | 2 +- lib/mapObjects/CGCreature.cpp | 4 +- lib/mapObjects/CGHeroInstance.cpp | 14 +-- lib/mapObjects/CGHeroInstance.h | 2 +- lib/mapObjects/MiscObjects.cpp | 2 +- lib/mapping/CMapOperation.cpp | 2 +- lib/mapping/MapFormatH3M.cpp | 2 +- lib/modding/ContentTypeHandler.cpp | 28 ++--- lib/networkPacks/PacksForClient.h | 2 +- lib/networkPacks/PacksForClientBattle.h | 2 +- lib/rmg/modificators/TreasurePlacer.cpp | 20 ++-- lib/serializer/CSerializer.cpp | 6 - lib/serializer/CSerializer.h | 5 - lib/spells/CSpellHandler.cpp | 4 +- mapeditor/graphics.cpp | 2 +- mapeditor/inspector/inspector.cpp | 2 +- mapeditor/mapcontroller.cpp | 2 +- mapeditor/playerparams.cpp | 2 +- mapeditor/validator.cpp | 2 +- server/CGameHandler.cpp | 22 ++-- server/processors/HeroPoolProcessor.cpp | 6 +- server/processors/PlayerMessageProcessor.cpp | 12 +- 55 files changed, 236 insertions(+), 305 deletions(-) diff --git a/AI/BattleAI/BattleEvaluator.cpp b/AI/BattleAI/BattleEvaluator.cpp index 7e615131d..429e57707 100644 --- a/AI/BattleAI/BattleEvaluator.cpp +++ b/AI/BattleAI/BattleEvaluator.cpp @@ -350,10 +350,11 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack) LOGL("Casting spells sounds like fun. Let's see..."); //Get all spells we can cast std::vector possibleSpells; - vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero, this](const CSpell *s) -> bool - { - return s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero); - }); + + for (auto const & s : VLC->spellh->objects) + if (s->canBeCast(cb->getBattle(battleID).get(), spells::Mode::HERO, hero)) + possibleSpells.push_back(s.get()); + LOGFL("I can cast %d spells.", possibleSpells.size()); vstd::erase_if(possibleSpells, [](const CSpell *s) diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 501d882c8..ace41d24c 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -276,12 +276,10 @@ creInfo infoFromDC(const dwellingContent & dc) ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed if (ci.creID != CreatureID::NONE) { - ci.cre = VLC->creatures()->getById(ci.creID); - ci.level = ci.cre->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore. + ci.level = ci.creID.toCreature()->getLevel(); //this is creature tier, while tryRealize expects dwelling level. Ignore. } else { - ci.cre = nullptr; ci.level = 0; } return ci; diff --git a/AI/Nullkiller/AIUtility.h b/AI/Nullkiller/AIUtility.h index 28a75e12b..ba5157883 100644 --- a/AI/Nullkiller/AIUtility.h +++ b/AI/Nullkiller/AIUtility.h @@ -163,7 +163,6 @@ struct creInfo { int count; CreatureID creID; - const Creature * cre; int level; }; creInfo infoFromDC(const dwellingContent & dc); diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 527471b08..07861de89 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -63,9 +63,9 @@ std::vector ArmyManager::toSlotInfo(std::vector army) const { SlotInfo slot; - slot.creature = VLC->creh->objects[i.cre->getId()]; + slot.creature = i.creID.toCreature(); slot.count = i.count; - slot.power = evaluateStackPower(i.cre, i.count); + slot.power = evaluateStackPower(i.creID.toCreature(), i.count); result.push_back(slot); } @@ -259,7 +259,7 @@ std::shared_ptr ArmyManager::getArmyAvailableToBuyAsCCreatureSet( if(!ci.count || ci.creID == CreatureID::NONE) continue; - vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford + vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford if(!ci.count) continue; @@ -270,7 +270,7 @@ std::shared_ptr ArmyManager::getArmyAvailableToBuyAsCCreatureSet( break; army->setCreature(dst, ci.creID, ci.count); - availableRes -= ci.cre->getFullRecruitCost() * ci.count; + availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count; } return army; @@ -287,7 +287,7 @@ ui64 ArmyManager::howManyReinforcementsCanBuy( for(const creInfo & ci : army) { - aivalue += ci.count * ci.cre->getAIValue(); + aivalue += ci.count * ci.creID.toCreature()->getAIValue(); } return aivalue; @@ -320,7 +320,7 @@ std::vector ArmyManager::getArmyAvailableToBuy( if(i < GameConstants::CREATURES_PER_TOWN && countGrowth) { - ci.count += town ? town->creatureGrowth(i) : ci.cre->getGrowth(); + ci.count += town ? town->creatureGrowth(i) : ci.creID.toCreature()->getGrowth(); } if(!ci.count) continue; @@ -334,13 +334,13 @@ std::vector ArmyManager::getArmyAvailableToBuy( freeHeroSlots--; //new slot will be occupied } - vstd::amin(ci.count, availableRes / ci.cre->getFullRecruitCost()); //max count we can afford + vstd::amin(ci.count, availableRes / ci.creID.toCreature()->getFullRecruitCost()); //max count we can afford if(!ci.count) continue; ci.level = i; //this is important for Dungeon Summoning Portal creaturesInDwellings.push_back(ci); - availableRes -= ci.cre->getFullRecruitCost() * ci.count; + availableRes -= ci.creID.toCreature()->getFullRecruitCost() * ci.count; } return creaturesInDwellings; diff --git a/AI/Nullkiller/Goals/BuyArmy.cpp b/AI/Nullkiller/Goals/BuyArmy.cpp index 55a8ec16e..9e2f52bff 100644 --- a/AI/Nullkiller/Goals/BuyArmy.cpp +++ b/AI/Nullkiller/Goals/BuyArmy.cpp @@ -54,12 +54,12 @@ void BuyArmy::accept(AIGateway * ai) if(objid != CreatureID::NONE && ci.creID.getNum() != objid) continue; - vstd::amin(ci.count, res / ci.cre->getFullRecruitCost()); + vstd::amin(ci.count, res / ci.creID.toCreature()->getFullRecruitCost()); if(ci.count) { cb->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level); - valueBought += ci.count * ci.cre->getAIValue(); + valueBought += ci.count * ci.creID.toCreature()->getAIValue(); } } diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index 0d108dbca..b3f186ce5 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -373,10 +373,10 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade( for(auto & creatureToBuy : buyArmy) { - auto targetSlot = target->getSlotFor(dynamic_cast(creatureToBuy.cre)); + auto targetSlot = target->getSlotFor(dynamic_cast(creatureToBuy.creID.toCreature())); target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count); - target->armyCost += creatureToBuy.cre->getFullRecruitCost() * creatureToBuy.count; + target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count; target->requireBuyArmy = true; } } diff --git a/client/CGameInfo.cpp b/client/CGameInfo.cpp index df2e1372d..f57b093a3 100644 --- a/client/CGameInfo.cpp +++ b/client/CGameInfo.cpp @@ -19,9 +19,6 @@ CServerHandler * CSH; CGameInfo::CGameInfo() { - generaltexth = nullptr; - mh = nullptr; - townh = nullptr; globalServices = nullptr; } diff --git a/client/CGameInfo.h b/client/CGameInfo.h index 332068395..11f1f8111 100644 --- a/client/CGameInfo.h +++ b/client/CGameInfo.h @@ -56,7 +56,7 @@ extern CClientState * CCS; /// CGameInfo class /// for allowing different functions for accessing game informations -class CGameInfo : public Services +class CGameInfo final : public Services { public: const ArtifactService * artifacts() const override; @@ -78,19 +78,20 @@ public: const spells::effects::Registry * spellEffects() const override; spells::effects::Registry * spellEffects() override; - ConstTransitivePtr modh; //public? - ConstTransitivePtr battleFieldHandler; - ConstTransitivePtr heroh; - ConstTransitivePtr creh; - ConstTransitivePtr spellh; - ConstTransitivePtr skillh; - ConstTransitivePtr objh; - ConstTransitivePtr terrainTypeHandler; - ConstTransitivePtr objtypeh; - ConstTransitivePtr obstacleHandler; - CGeneralTextHandler * generaltexth; - CMapHandler * mh; - CTownHandler * townh; + std::shared_ptr modh; + std::shared_ptr battleFieldHandler; + std::shared_ptr heroh; + std::shared_ptr creh; + std::shared_ptr spellh; + std::shared_ptr skillh; + std::shared_ptr objh; + std::shared_ptr terrainTypeHandler; + std::shared_ptr objtypeh; + std::shared_ptr obstacleHandler; + std::shared_ptr generaltexth; + std::shared_ptr townh; + + std::shared_ptr mh; void setFromLib(); diff --git a/client/Client.cpp b/client/Client.cpp index 0a6dd7109..f34c8f6cc 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -370,7 +370,7 @@ void CClient::endGame() logNetwork->info("Ending current game!"); removeGUI(); - vstd::clear_pointer(const_cast(CGI)->mh); + const_cast(CGI)->mh.reset(); vstd::clear_pointer(gs); logNetwork->info("Deleted mapHandler and gameState."); @@ -392,7 +392,7 @@ void CClient::initMapHandler() // During loading CPlayerInterface from serialized state it's depend on MH if(!settings["session"]["headless"].Bool()) { - const_cast(CGI)->mh = new CMapHandler(gs->map); + const_cast(CGI)->mh = std::make_shared(gs->map); logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff()); } diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index bfe46894c..a5005a007 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -187,14 +187,14 @@ DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid) { - auto ret = new CArtifactInstance(VLC->arth->objects[ArtifactID::SPELL_SCROLL]); + auto ret = new CArtifactInstance(ArtifactID(ArtifactID::SPELL_SCROLL).toArtifact()); auto bonus = std::make_shared(BonusDuration::PERMANENT, BonusType::SPELL, BonusSource::ARTIFACT_INSTANCE, -1, BonusSourceID(ArtifactID(ArtifactID::SPELL_SCROLL)), BonusSubtypeID(sid)); ret->addNewBonus(bonus); return ret; } -DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifact * art) +DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const CArtifact * art) { assert(art); @@ -216,7 +216,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const ArtifactID & aid) { - return ArtifactUtils::createNewArtifactInstance((*VLC->arth)[aid]); + return ArtifactUtils::createNewArtifactInstance(aid.toArtifact()); } DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID) diff --git a/lib/ArtifactUtils.h b/lib/ArtifactUtils.h index b4af3b401..74fe67db1 100644 --- a/lib/ArtifactUtils.h +++ b/lib/ArtifactUtils.h @@ -40,7 +40,7 @@ namespace ArtifactUtils DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1); DLL_LINKAGE std::vector assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid); - DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art); + DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, SpellID spellID = SpellID::NONE); DLL_LINKAGE void insertScrrollSpellName(std::string & description, const SpellID & sid); diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 814e2fe5c..f7a020f58 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -49,12 +49,12 @@ bool CCombinedArtifact::isCombined() const return !(constituents.empty()); } -const std::vector & CCombinedArtifact::getConstituents() const +const std::vector & CCombinedArtifact::getConstituents() const { return constituents; } -const std::vector & CCombinedArtifact::getPartOf() const +const std::vector & CCombinedArtifact::getPartOf() const { return partOf; } @@ -597,7 +597,7 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) { // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them - art->constituents.push_back(objects[id]); + art->constituents.push_back(ArtifactID(id).toArtifact()); objects[id]->partOf.push_back(art); }); } diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 065ebefd7..211b1e19e 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -47,12 +47,12 @@ class DLL_LINKAGE CCombinedArtifact protected: CCombinedArtifact() = default; - std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. - std::vector partOf; // Reverse map of constituents - combined arts that include this art + std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. + std::vector partOf; // Reverse map of constituents - combined arts that include this art public: bool isCombined() const; - const std::vector & getConstituents() const; - const std::vector & getPartOf() const; + const std::vector & getConstituents() const; + const std::vector & getPartOf() const; }; class DLL_LINKAGE CScrollArtifact diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 0928b2308..39aa644f7 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -107,7 +107,7 @@ void CArtifactInstance::init() setNodeType(ARTIFACT_INSTANCE); } -CArtifactInstance::CArtifactInstance(CArtifact * art) +CArtifactInstance::CArtifactInstance(const CArtifact * art) { init(); setType(art); @@ -118,10 +118,10 @@ CArtifactInstance::CArtifactInstance() init(); } -void CArtifactInstance::setType(CArtifact * art) +void CArtifactInstance::setType(const CArtifact * art) { artType = art; - attachTo(*art); + attachTo(const_cast(*art)); } std::string CArtifactInstance::nodeName() const diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index fbee8c8fc..76a1c0e3c 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -73,11 +73,11 @@ protected: ArtifactInstanceID id; public: - ConstTransitivePtr artType; + const CArtifact * artType; - CArtifactInstance(CArtifact * art); + CArtifactInstance(const CArtifact * art); CArtifactInstance(); - void setType(CArtifact * art); + void setType(const CArtifact * art); std::string nodeName() const override; std::string getDescription() const; ArtifactID getTypeId() const; diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index adf0c0c67..33f8f95ed 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -407,20 +407,9 @@ void CCreature::serializeJson(JsonSerializeFormat & handler) CCreatureHandler::CCreatureHandler() : expAfterUpgrade(0) { - VLC->creh = this; loadCommanders(); } -const CCreature * CCreatureHandler::getCreature(const std::string & scope, const std::string & identifier) const -{ - std::optional index = VLC->identifiers()->getIdentifier(scope, "creature", identifier); - - if(!index) - throw std::runtime_error("Creature not found "+identifier); - - return objects[*index]; -} - void CCreatureHandler::loadCommanders() { auto configResource = JsonPath::builtin("config/commanders.json"); @@ -797,7 +786,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects) bl.clear(); loadStackExp(b, bl, parser); for(const auto & b : bl) - (*this)[sid]->addNewBonus(b); //add directly to CCreature Node + objects[sid.getNum()]->addNewBonus(b); //add directly to CCreature Node } while (parser.endLine()); diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 09bc9d8f5..ee98ef528 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -222,7 +222,7 @@ public: std::vector< std::vector > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE std::vector , std::pair > > skillRequirements; // first - Bonus, second - which two skills are needed to use it - const CCreature * getCreature(const std::string & scope, const std::string & identifier) const; + //const CCreature * getCreature(const std::string & scope, const std::string & identifier) const; CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index e1aef1d67..8f09c6592 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -739,11 +739,10 @@ void CStackInstance::giveStackExp(TExpType exp) if (!vstd::iswithin(level, 1, 7)) level = 0; - CCreatureHandler * creh = VLC->creh; - ui32 maxExp = creh->expRanks[level].back(); + ui32 maxExp = VLC->creh->expRanks[level].back(); vstd::amin(exp, static_cast(maxExp)); //prevent exp overflow due to different types - vstd::amin(exp, (maxExp * creh->maxExpPerBattle[level])/100); + vstd::amin(exp, (maxExp * VLC->creh->maxExpPerBattle[level])/100); vstd::amin(experience += exp, maxExp); //can't get more exp than this limit } @@ -1055,7 +1054,7 @@ void CStackBasicDescriptor::serializeJson(JsonSerializeFormat & handler) std::string typeName; handler.serializeString("type", typeName); if(!typeName.empty()) - setType(VLC->creh->getCreature(ModScope::scopeMap(), typeName)); + setType(CreatureID(CreatureID::decode(typeName)).toCreature()); } } diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 0404365e3..b86e6ef70 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -382,7 +382,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero if(creature->getFaction() == factionIndex && static_cast(creature->getAIValue()) > maxAIValue) { maxAIValue = creature->getAIValue(); - mostStrong = creature; + mostStrong = creature.get(); } } diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 0488392d3..3d1ce3482 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -155,6 +155,13 @@ bool CHeroClass::isMagicHero() const return affinity == MAGIC; } +int CHeroClass::tavernProbability(FactionID faction) const +{ + if (selectionProbability.count(faction)) + return selectionProbability.at(faction); + return 0; +} + EAlignment CHeroClass::getAlignment() const { return VLC->factions()->getById(faction)->getAlignment(); @@ -292,7 +299,7 @@ CHeroClass * CHeroClassHandler::loadFromJson(const std::string & scope, const Js VLC->identifiers()->requestIdentifier ("creature", node["commander"], [=](si32 commanderID) { - heroClass->commander = VLC->creh->objects[commanderID]; + heroClass->commander = CreatureID(commanderID).toCreature(); }); heroClass->defaultTavernChance = static_cast(node["defaultTavern"].Float()); @@ -369,9 +376,9 @@ std::vector CHeroClassHandler::loadLegacyData() void CHeroClassHandler::afterLoadFinalization() { // for each pair set selection probability if it was not set before in tavern entries - for(CHeroClass * heroClass : objects) + for(auto & heroClass : objects) { - for(CFaction * faction : VLC->townh->objects) + for(auto & faction : VLC->townh->objects) { if (!faction->town) continue; @@ -394,7 +401,7 @@ void CHeroClassHandler::afterLoadFinalization() } } - for(CHeroClass * hc : objects) + for(auto const & hc : objects) { if (!hc->imageMapMale.empty()) { @@ -454,7 +461,7 @@ CHero * CHeroHandler::loadFromJson(const std::string & scope, const JsonNode & n VLC->identifiers()->requestIdentifier("heroClass", node["class"], [=](si32 classID) { - hero->heroClass = classes[HeroClassID(classID)]; + hero->heroClass = HeroClassID(classID).toHeroClass(); }); return hero; @@ -790,7 +797,7 @@ std::set CHeroHandler::getDefaultAllowed() const { std::set result; - for(const CHero * hero : objects) + for(auto & hero : objects) if (hero && !hero->special) result.insert(hero->getId()); diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index 88ce86f5b..1a3219f8c 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -57,7 +57,7 @@ public: std::vector initialArmy; - CHeroClass * heroClass{}; + const CHeroClass * heroClass = nullptr; std::vector > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert) BonusList specialty; std::set spells; @@ -121,7 +121,7 @@ public: // resulting chance = sqrt(town.chance * heroClass.chance) ui32 defaultTavernChance; - CCreature * commander; + const CCreature * commander; std::vector primarySkillInitial; // initial primary skills std::vector primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level @@ -154,6 +154,8 @@ public: void serializeJson(JsonSerializeFormat & handler); EAlignment getAlignment() const; + + int tavernProbability(FactionID faction) const; }; class DLL_LINKAGE CHeroClassHandler : public CHandlerBase @@ -189,8 +191,6 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase> callAfterLoadFinalization; public: - CHeroClassHandler classes; - ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount TExpType reqExp(ui32 level) const; //calculates experience required for given level ui32 maxSupportedLevel() const; diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index c32d24012..331cb881c 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -991,7 +991,7 @@ void CTownHandler::loadTown(CTown * town, const JsonNode & source) VLC->identifiers()->requestIdentifier(node.second.meta, "heroClass",node.first, [=](si32 classID) { - VLC->heroh->classes[HeroClassID(classID)]->selectionProbability[town->faction->getId()] = chance; + VLC->heroclassesh->objects[classID]->selectionProbability[town->faction->getId()] = chance; }); } diff --git a/lib/IHandlerBase.h b/lib/IHandlerBase.h index 8bf602887..fe05606b9 100644 --- a/lib/IHandlerBase.h +++ b/lib/IHandlerBase.h @@ -44,11 +44,21 @@ public: /// allows handler to do post-loading step for validation or integration of loaded data virtual void afterLoadFinalization(){}; - virtual ~IHandlerBase(){} + virtual ~IHandlerBase() = default; }; template class CHandlerBase : public _ServiceBase, public IHandlerBase { + const _Object * getObjectImpl(const int32_t index) const + { + if(index < 0 || index >= objects.size()) + { + logMod->error("%s id %d is invalid", getTypeNames()[0], index); + throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front()); + } + return objects[index].get(); + } + public: virtual ~CHandlerBase() { @@ -56,22 +66,31 @@ public: { o.dellNull(); } + } + _Object * getObjectWriteable(const int32_t index) + { + if(index < 0 || index >= objects.size()) + { + logMod->error("%s id %d is invalid", getTypeNames()[0], index); + throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front()); + } + return objects[index].get(); } const Entity * getBaseByIndex(const int32_t index) const override { - return getByIndex(index); + return getObjectImpl(index); } const _ObjectBase * getById(const _ObjectID & id) const override { - return (*this)[id].get(); + return getObjectImpl(id.getNum()); } const _ObjectBase * getByIndex(const int32_t index) const override { - return (*this)[_ObjectID(index)].get(); + return getObjectImpl(index); } void forEachBase(const std::function & cb) const override @@ -105,21 +124,14 @@ public: registerObject(scope, type_name, name, object->getIndex()); } - ConstTransitivePtr<_Object> operator[] (const _ObjectID id) const + const _Object * operator[] (const _ObjectID id) const { - const int32_t raw_id = id.getNum(); - return operator[](raw_id); + return getObjectImpl(id.getNum()); } - ConstTransitivePtr<_Object> operator[] (int32_t index) const + const _Object * operator[] (int32_t index) const { - if(index < 0 || index >= objects.size()) - { - logMod->error("%s id %d is invalid", getTypeNames()[0], index); - throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front()); - } - - return objects[index]; + return getObjectImpl(index); } void updateEntity(int32_t index, const JsonNode & data) diff --git a/lib/JsonRandom.cpp b/lib/JsonRandom.cpp index ca068c973..1044cf08c 100644 --- a/lib/JsonRandom.cpp +++ b/lib/JsonRandom.cpp @@ -519,7 +519,8 @@ namespace JsonRandom info.minAmount = static_cast(node["min"].Float()); info.maxAmount = static_cast(node["max"].Float()); } - const CCreature * crea = VLC->creh->objects[VLC->identifiers()->getIdentifier("creature", node["type"]).value()]; + CreatureID creatureID(VLC->identifiers()->getIdentifier("creature", node["type"]).value()); + const CCreature * crea = creatureID.toCreature(); info.allowedCreatures.push_back(crea); if (node["upgradeChance"].Float() > 0) { diff --git a/lib/RiverHandler.cpp b/lib/RiverHandler.cpp index 5154505b4..ca0a28756 100644 --- a/lib/RiverHandler.cpp +++ b/lib/RiverHandler.cpp @@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN RiverTypeHandler::RiverTypeHandler() { - objects.push_back(new RiverType); + objects.push_back(new RiverType()); VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), ""); } diff --git a/lib/RoadHandler.cpp b/lib/RoadHandler.cpp index 85380d460..0ae298dfb 100644 --- a/lib/RoadHandler.cpp +++ b/lib/RoadHandler.cpp @@ -18,7 +18,7 @@ VCMI_LIB_NAMESPACE_BEGIN RoadTypeHandler::RoadTypeHandler() { - objects.push_back(new RoadType); + objects.push_back(new RoadType()); VLC->generaltexth->registerString("core", objects[0]->getNameTextID(), ""); } diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 94d3f57fd..45edced97 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -65,27 +65,27 @@ DLL_LINKAGE void loadDLLClasses(bool onlyEssential) const ArtifactService * LibClasses::artifacts() const { - return arth; + return arth.get(); } const CreatureService * LibClasses::creatures() const { - return creh; + return creh.get(); } const FactionService * LibClasses::factions() const { - return townh; + return townh.get(); } const HeroClassService * LibClasses::heroClasses() const { - return &heroh->classes; + return heroclassesh.get(); } const HeroTypeService * LibClasses::heroTypes() const { - return heroh; + return heroh.get(); } #if SCRIPTING_ENABLED @@ -97,22 +97,22 @@ const scripting::Service * LibClasses::scripts() const const spells::Service * LibClasses::spells() const { - return spellh; + return spellh.get(); } const SkillService * LibClasses::skills() const { - return skillh; + return skillh.get(); } const IBonusTypeHandler * LibClasses::getBth() const { - return bth; + return bth.get(); } const CIdentifierStorage * LibClasses::identifiers() const { - return identifiersHandler; + return identifiersHandler.get(); } const spells::effects::Registry * LibClasses::spellEffects() const @@ -127,17 +127,17 @@ spells::effects::Registry * LibClasses::spellEffects() const BattleFieldService * LibClasses::battlefields() const { - return battlefieldsHandler; + return battlefieldsHandler.get(); } const ObstacleService * LibClasses::obstacles() const { - return obstacleHandler; + return obstacleHandler.get(); } const IGameSettings * LibClasses::settings() const { - return settingsHandler; + return settingsHandler.get(); } void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & data) @@ -154,7 +154,7 @@ void LibClasses::updateEntity(Metatype metatype, int32_t index, const JsonNode & townh->updateEntity(index, data); break; case Metatype::HERO_CLASS: - heroh->classes.updateEntity(index, data); + heroclassesh->updateEntity(index, data); break; case Metatype::HERO_TYPE: heroh->updateEntity(index, data); @@ -185,8 +185,8 @@ void LibClasses::loadFilesystem(bool extractArchives) void LibClasses::loadModFilesystem() { CStopWatch loadTime; - modh = new CModHandler(); - identifiersHandler = new CIdentifierStorage(); + modh = std::make_unique(); + identifiersHandler = std::make_unique(); modh->loadMods(); logGlobal->info("\tMod handler: %d ms", loadTime.getDiff()); @@ -199,9 +199,9 @@ static void logHandlerLoaded(const std::string & name, CStopWatch & timer) logGlobal->info("\t\t %s handler: %d ms", name, timer.getDiff()); } -template void createHandler(Handler *&handler, const std::string &name, CStopWatch &timer) +template void createHandler(std::shared_ptr & handler, const std::string &name, CStopWatch &timer) { - handler = new Handler(); + handler = std::make_shared(); logHandlerLoaded(name, timer); } @@ -219,6 +219,7 @@ void LibClasses::init(bool onlyEssential) createHandler(riverTypeHandler, "River", pomtime); createHandler(terrainTypeHandler, "Terrain", pomtime); createHandler(heroh, "Hero", pomtime); + createHandler(heroclassesh, "Hero classes", pomtime); createHandler(arth, "Artifact", pomtime); createHandler(creh, "Creature", pomtime); createHandler(townh, "Town", pomtime); @@ -239,77 +240,6 @@ void LibClasses::init(bool onlyEssential) modh->afterLoad(onlyEssential); } -void LibClasses::clear() -{ - delete heroh; - delete arth; - delete creh; - delete townh; - delete objh; - delete objtypeh; - delete spellh; - delete skillh; - delete modh; - delete bth; - delete tplh; - delete terviewh; -#if SCRIPTING_ENABLED - delete scriptHandler; -#endif - delete battlefieldsHandler; - delete generaltexth; - delete identifiersHandler; - delete obstacleHandler; - delete terrainTypeHandler; - delete riverTypeHandler; - delete roadTypeHandler; - delete settingsHandler; - makeNull(); -} - -void LibClasses::makeNull() -{ - generaltexth = nullptr; - heroh = nullptr; - arth = nullptr; - creh = nullptr; - townh = nullptr; - objh = nullptr; - objtypeh = nullptr; - spellh = nullptr; - skillh = nullptr; - modh = nullptr; - bth = nullptr; - tplh = nullptr; - terviewh = nullptr; -#if SCRIPTING_ENABLED - scriptHandler = nullptr; -#endif - battlefieldsHandler = nullptr; - identifiersHandler = nullptr; - obstacleHandler = nullptr; - terrainTypeHandler = nullptr; - riverTypeHandler = nullptr; - roadTypeHandler = nullptr; - settingsHandler = nullptr; -} - -LibClasses::LibClasses() -{ - //init pointers to handlers - makeNull(); -} - -void LibClasses::callWhenDeserializing() -{ - //FIXME: check if any of these are needed - //generaltexth = new CGeneralTextHandler(); - //generaltexth->load(); - //arth->load(true); - //modh->recreateHandlers(); - //modh->loadConfigFromFile ("defaultMods"); //TODO: remember last saved config -} - #if SCRIPTING_ENABLED void LibClasses::scriptsLoaded() { @@ -317,10 +247,8 @@ void LibClasses::scriptsLoaded() } #endif -LibClasses::~LibClasses() -{ - clear(); -} +LibClasses::LibClasses() = default; +LibClasses::~LibClasses() = default; std::shared_ptr LibClasses::getContent() const { diff --git a/lib/VCMI_Lib.h b/lib/VCMI_Lib.h index 6622d9822..85bfce994 100644 --- a/lib/VCMI_Lib.h +++ b/lib/VCMI_Lib.h @@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CConsoleHandler; class CArtHandler; class CHeroHandler; +class CHeroClassHandler; class CCreatureHandler; class CSpellHandler; class CSkillHandler; @@ -47,20 +48,15 @@ namespace scripting } #endif - /// Loads and constructs several handlers -class DLL_LINKAGE LibClasses : public Services +class DLL_LINKAGE LibClasses final : public Services { - CBonusTypeHandler * bth; + std::shared_ptr bth; - void callWhenDeserializing(); //should be called only by serialize !!! - void makeNull(); //sets all handler pointers to null std::shared_ptr getContent() const; void setContent(std::shared_ptr content); public: - bool IS_AI_ENABLED = false; //unused? - const ArtifactService * artifacts() const override; const CreatureService * creatures() const override; const FactionService * factions() const override; @@ -83,27 +79,27 @@ public: const IBonusTypeHandler * getBth() const; //deprecated const CIdentifierStorage * identifiers() const; - CArtHandler * arth; - CHeroHandler * heroh; - CCreatureHandler * creh; - CSpellHandler * spellh; - CSkillHandler * skillh; - CObjectHandler * objh; - CObjectClassesHandler * objtypeh; - CTownHandler * townh; - CGeneralTextHandler * generaltexth; - CModHandler * modh; + std::shared_ptr arth; + std::shared_ptr heroh; + std::shared_ptr heroclassesh; + std::shared_ptr creh; + std::shared_ptr spellh; + std::shared_ptr skillh; + std::shared_ptr objh; + std::shared_ptr objtypeh; + std::shared_ptr townh; + std::shared_ptr generaltexth; + std::shared_ptr modh; + std::shared_ptr terrainTypeHandler; + std::shared_ptr roadTypeHandler; + std::shared_ptr riverTypeHandler; + std::shared_ptr identifiersHandler; + std::shared_ptr terviewh; + std::shared_ptr tplh; + std::shared_ptr battlefieldsHandler; + std::shared_ptr obstacleHandler; + std::shared_ptr settingsHandler; - TerrainTypeHandler * terrainTypeHandler; - RoadTypeHandler * roadTypeHandler; - RiverTypeHandler * riverTypeHandler; - CIdentifierStorage * identifiersHandler; - - CTerrainViewPatternConfig * terviewh; - CRmgTemplateStorage * tplh; - BattleFieldHandler * battlefieldsHandler; - ObstacleHandler * obstacleHandler; - GameSettings * settingsHandler; #if SCRIPTING_ENABLED scripting::ScriptHandler * scriptHandler; #endif @@ -111,7 +107,6 @@ public: LibClasses(); //c-tor, loads .lods and NULLs handlers ~LibClasses(); void init(bool onlyEssential); //uses standard config file - void clear(); //deletes all handlers and its data // basic initialization. should be called before init(). Can also extract original H3 archives void loadFilesystem(bool extractArchives); diff --git a/lib/constants/EntityIdentifiers.cpp b/lib/constants/EntityIdentifiers.cpp index 597343cc2..73f885303 100644 --- a/lib/constants/EntityIdentifiers.cpp +++ b/lib/constants/EntityIdentifiers.cpp @@ -151,6 +151,16 @@ std::string HeroClassID::entityType() return "heroClass"; } +const CHeroClass * HeroClassID::toHeroClass() const +{ + return dynamic_cast(toEntity(VLC)); +} + +const HeroClass * HeroClassID::toEntity(const Services * services) const +{ + return services->heroClasses()->getByIndex(num); +} + si32 ObjectInstanceID::decode(const std::string & identifier) { return std::stoi(identifier); diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 98d5ddf3c..0c1ff0128 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -21,6 +21,8 @@ class Creature; class CreatureService; class HeroType; class CHero; +class CHeroClass; +class HeroClass; class HeroTypeService; class Faction; class Skill; @@ -81,6 +83,9 @@ public: DLL_LINKAGE static si32 decode(const std::string & identifier); DLL_LINKAGE static std::string encode(const si32 index); static std::string entityType(); + + const CHeroClass * toHeroClass() const; + const HeroClass * toEntity(const Services * services) const; }; class DLL_LINKAGE HeroTypeID : public EntityIdentifier diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 519f4d40a..e93b53b13 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -347,7 +347,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vectortempOwner.isValidPlayer()) heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->pos = heroPlaceholder->pos; - heroToPlace->type = VLC->heroh->objects[heroToPlace->getHeroType().getNum()]; + heroToPlace->type = heroToPlace->getHeroType().toHeroType(); heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); gameState->map->removeBlockVisTiles(heroPlaceholder, true); diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp index f8670ce31..4278394f9 100644 --- a/lib/mapObjectConstructors/CommonConstructors.cpp +++ b/lib/mapObjectConstructors/CommonConstructors.cpp @@ -122,7 +122,7 @@ void CHeroInstanceConstructor::initTypeData(const JsonNode & input) VLC->identifiers()->requestIdentifier( "heroClass", input["heroClass"], - [&](si32 index) { heroClass = VLC->heroh->classes[index]; }); + [&](si32 index) { heroClass = HeroClassID(index).toHeroClass(); }); filtersJson = input["filters"]; } diff --git a/lib/mapObjectConstructors/CommonConstructors.h b/lib/mapObjectConstructors/CommonConstructors.h index 64d181ced..51aa98753 100644 --- a/lib/mapObjectConstructors/CommonConstructors.h +++ b/lib/mapObjectConstructors/CommonConstructors.h @@ -57,7 +57,7 @@ protected: void initTypeData(const JsonNode & input) override; public: - CFaction * faction = nullptr; + const CFaction * faction = nullptr; std::map> filters; void initializeObject(CGTownInstance * object) const override; @@ -76,7 +76,7 @@ protected: void initTypeData(const JsonNode & input) override; public: - CHeroClass * heroClass = nullptr; + const CHeroClass * heroClass = nullptr; std::map> filters; void initializeObject(CGHeroInstance * object) const override; diff --git a/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp b/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp index 6a137b976..022b2773c 100644 --- a/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp +++ b/lib/mapObjectConstructors/DwellingInstanceConstructor.cpp @@ -45,7 +45,7 @@ void DwellingInstanceConstructor::initTypeData(const JsonNode & input) { VLC->identifiers()->requestIdentifier("creature", creaturesOnLevel[currentCreature], [=] (si32 index) { - availableCreatures[currentLevel][currentCreature] = VLC->creh->objects[index]; + availableCreatures[currentLevel][currentCreature] = CreatureID(index).toCreature(); }); } assert(!availableCreatures[currentLevel].empty()); diff --git a/lib/mapObjects/CGCreature.cpp b/lib/mapObjects/CGCreature.cpp index f76915582..f4c68c05b 100644 --- a/lib/mapObjects/CGCreature.cpp +++ b/lib/mapObjects/CGCreature.cpp @@ -313,11 +313,11 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const powerFactor = -3; std::set myKindCres; //what creatures are the same kind as we - const CCreature * myCreature = VLC->creh->objects[getCreature().getNum()]; + const CCreature * myCreature = getCreature().toCreature(); myKindCres.insert(myCreature->getId()); //we myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades - for(ConstTransitivePtr &crea : VLC->creh->objects) + for(auto const & crea : VLC->creh->objects) { if(vstd::contains(crea->upgrades, myCreature->getId())) //it's our base creatures myKindCres.insert(crea->getId()); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 3577b5e33..99f4113a8 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -316,7 +316,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand) { assert(validTypes(true)); if(!type) - type = VLC->heroh->objects[getHeroType().getNum()]; + type = getHeroType().toHeroType(); if (ID == Obj::HERO) appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); @@ -590,11 +590,11 @@ void CGHeroInstance::pickRandomObject(CRandomGenerator & rand) { ID = Obj::HERO; subID = cb->gameState()->pickNextHeroType(getOwner()); - type = VLC->heroh->objects[getHeroType().getNum()]; + type = getHeroType().toHeroType(); randomizeArmy(type->heroClass->faction); } else - type = VLC->heroh->objects[getHeroType().getNum()]; + type = getHeroType().toHeroType(); auto oldSubID = subID; @@ -879,7 +879,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b double necromancySkill = valOfBonuses(BonusType::UNDEAD_RAISE_PERCENTAGE) / 100.0; const ui8 necromancyLevel = valOfBonuses(BonusType::IMPROVED_NECROMANCY); vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all... - const std::map &casualties = battleResult.casualties[!battleResult.winner]; + const std::map &casualties = battleResult.casualties[!battleResult.winner]; // figure out what to raise - pick strongest creature meeting requirements CreatureID creatureTypeRaised = CreatureID::NONE; //now we always have IMPROVED_NECROMANCY, no need for hardcode int requiredCasualtyLevel = 1; @@ -888,7 +888,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b { int maxCasualtyLevel = 1; for(const auto & casualty : casualties) - vstd::amax(maxCasualtyLevel, VLC->creatures()->getByIndex(casualty.first)->getLevel()); + vstd::amax(maxCasualtyLevel, VLC->creatures()->getById(casualty.first)->getLevel()); // pick best bonus available std::shared_ptr topPick; for(const std::shared_ptr & newPick : *improvedNecromancy) @@ -936,7 +936,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b double raisedUnits = 0; for(const auto & casualty : casualties) { - const CCreature * c = VLC->creh->objects[casualty.first]; + const CCreature * c = casualty.first.toCreature(); double raisedFromCasualty = std::min(c->getMaxHealth() / raisedUnitHealth, 1.0) * casualty.second * necromancySkill; if(c->getLevel() < requiredCasualtyLevel) raisedFromCasualty *= 0.5; @@ -1742,7 +1742,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler) if(!appearance) { // crossoverDeserialize - type = VLC->heroh->objects[getHeroType().getNum()]; + type = getHeroType().toHeroType(); appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); } diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 544895312..923eec081 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -69,7 +69,7 @@ public: ////////////////////////////////////////////////////////////////////////// - ConstTransitivePtr type; + const CHero * type; TExpType exp; //experience points ui32 level; //current level of hero diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 36cda23e1..c5f271e98 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -769,7 +769,7 @@ void CGArtifact::initObj(CRandomGenerator & rand) storedArtifact = a; } if(!storedArtifact->artType) - storedArtifact->setType(VLC->arth->objects[getArtifact().getNum()]); + storedArtifact->setType(getArtifact().toArtifact()); } if(ID == Obj::SPELL_SCROLL) subID = 1; diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 59e5e3261..a8e26868b 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -510,7 +510,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const { if(map->isInTheMap(pos)) { - auto * ptrConfig = VLC->terviewh; + const auto & ptrConfig = VLC->terviewh; const auto * terType = map->getTile(pos).terType; auto valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById("n1")).result; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 78e6b2b68..0701921ed 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -760,7 +760,7 @@ void CMapLoaderH3M::readAllowedArtifacts() // ban combo artifacts if(!features.levelSOD) { - for(CArtifact * artifact : VLC->arth->objects) + for(auto const & artifact : VLC->arth->objects) if(artifact->isCombined()) map->allowedArtifact.erase(artifact->getId()); } diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp index 59e1ee718..4323bddc0 100644 --- a/lib/modding/ContentTypeHandler.cpp +++ b/lib/modding/ContentTypeHandler.cpp @@ -189,23 +189,23 @@ void ContentTypeHandler::afterLoadFinalization() void CContentHandler::init() { - handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, "heroClass"))); - handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, "artifact"))); - handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, "creature"))); - handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, "faction"))); - handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh, "object"))); - handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, "hero"))); - handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell"))); - handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh, "skill"))); - handlers.insert(std::make_pair("templates", ContentTypeHandler(VLC->tplh, "template"))); + handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(VLC->heroclassesh.get(), "heroClass"))); + handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth.get(), "artifact"))); + handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh.get(), "creature"))); + handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh.get(), "faction"))); + handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh.get(), "object"))); + handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh.get(), "hero"))); + handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh.get(), "spell"))); + handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh.get(), "skill"))); + handlers.insert(std::make_pair("templates", ContentTypeHandler(VLC->tplh.get(), "template"))); #if SCRIPTING_ENABLED handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler, "script"))); #endif - handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler, "battlefield"))); - handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler, "terrain"))); - handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler, "river"))); - handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler, "road"))); - handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler, "obstacle"))); + handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler.get(), "battlefield"))); + handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler.get(), "terrain"))); + handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler.get(), "river"))); + handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler.get(), "road"))); + handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler.get(), "obstacle"))); //TODO: any other types of moddables? } diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index 3726589f0..971711a67 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -1118,7 +1118,7 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack { ArtifactLocation al; //where assembly will be put - CArtifact * builtArt; + const CArtifact * builtArt; void applyGs(CGameState * gs); diff --git a/lib/networkPacks/PacksForClientBattle.h b/lib/networkPacks/PacksForClientBattle.h index ad0878fe9..7578abcdc 100644 --- a/lib/networkPacks/PacksForClientBattle.h +++ b/lib/networkPacks/PacksForClientBattle.h @@ -128,7 +128,7 @@ struct DLL_LINKAGE BattleResult : public Query BattleID battleID = BattleID::NONE; EBattleResult result = EBattleResult::NORMAL; ui8 winner = 2; //0 - attacker, 1 - defender, [2 - draw (should be possible?)] - std::map casualties[2]; //first => casualties of attackers - map crid => number + std::map casualties[2]; //first => casualties of attackers - map crid => number TExpType exp[2] = {0, 0}; //exp for attacker and defender std::set artifacts; //artifacts taken from loser to winner - currently unused diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index 20c12e2eb..8f92cea55 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -159,12 +159,12 @@ void TreasurePlacer::addAllPossibleObjects() //all following objects are unlimited oi.maxPerZone = std::numeric_limits::max(); - std::vector creatures; //native creatures for this zone + std::vector creatures; //native creatures for this zone for(auto cre : VLC->creh->objects) { if(!cre->special && cre->getFaction() == zone.getTownType()) { - creatures.push_back(cre); + creatures.push_back(cre.get()); } } @@ -283,7 +283,7 @@ void TreasurePlacer::addAllPossibleObjects() //pandora box with creatures const std::vector & tierValues = generator.getConfig().pandoraCreatureValues; - auto creatureToCount = [tierValues](CCreature * creature) -> int + auto creatureToCount = [tierValues](const CCreature * creature) -> int { if(!creature->getAIValue() || tierValues.empty()) //bug #2681 return 0; //this box won't be generated @@ -350,11 +350,11 @@ void TreasurePlacer::addAllPossibleObjects() auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); auto * obj = dynamic_cast(factory->create()); - std::vector spells; + std::vector spells; for(auto spell : VLC->spellh->objects) { if(map.isAllowedSpell(spell->id) && spell->getLevel() == i) - spells.push_back(spell); + spells.push_back(spell.get()); } RandomGeneratorUtil::randomShuffle(spells, zone.getRand()); @@ -383,11 +383,11 @@ void TreasurePlacer::addAllPossibleObjects() auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); auto * obj = dynamic_cast(factory->create()); - std::vector spells; + std::vector spells; for(auto spell : VLC->spellh->objects) { - if(map.isAllowedSpell(spell->id) && spell->school[SpellSchool(i)]) - spells.push_back(spell); + if(map.isAllowedSpell(spell->id) && spell->hasSchool(SpellSchool(i))) + spells.push_back(spell.get()); } RandomGeneratorUtil::randomShuffle(spells, zone.getRand()); @@ -415,11 +415,11 @@ void TreasurePlacer::addAllPossibleObjects() auto factory = VLC->objtypeh->getHandlerFor(Obj::PANDORAS_BOX, 0); auto * obj = dynamic_cast(factory->create()); - std::vector spells; + std::vector spells; for(auto spell : VLC->spellh->objects) { if(map.isAllowedSpell(spell->id)) - spells.push_back(spell); + spells.push_back(spell.get()); } RandomGeneratorUtil::randomShuffle(spells, zone.getRand()); diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index 1ce13bfe3..88ab64a94 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -24,14 +24,8 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) { registerVectoredType(&gs->map->objects, [](const CGObjectInstance &obj){ return obj.id; }); - registerVectoredType(&lib->heroh->objects, - [](const CHero &h){ return h.getId(); }); registerVectoredType(&gs->map->allHeroes, [](const CGHeroInstance &h){ return h.type->getId(); }); - registerVectoredType(&lib->creh->objects, - [](const CCreature &cre){ return cre.getId(); }); - registerVectoredType(&lib->arth->objects, - [](const CArtifact &art){ return art.getId(); }); registerVectoredType(&gs->map->artInstances, [](const CArtifactInstance &artInst){ return artInst.getId(); }); registerVectoredType(&gs->map->quests, diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index 58914184c..ce3b96e42 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -65,11 +65,6 @@ class DLL_LINKAGE CSerializer return t.getNum(); } - template - void registerVectoredType(const std::vector *Vector, const std::function &idRetriever) - { - vectors[&typeid(T)] = VectorizedObjectInfo(Vector, idRetriever); - } template void registerVectoredType(const std::vector > *Vector, const std::function &idRetriever) { diff --git a/lib/spells/CSpellHandler.cpp b/lib/spells/CSpellHandler.cpp index 9d1e4d7fc..b5751ee53 100644 --- a/lib/spells/CSpellHandler.cpp +++ b/lib/spells/CSpellHandler.cpp @@ -969,7 +969,7 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode & void CSpellHandler::afterLoadFinalization() { - for(auto spell : objects) + for(auto & spell : objects) { spell->setupMechanics(); } @@ -997,7 +997,7 @@ std::set CSpellHandler::getDefaultAllowed() const { std::set allowedSpells; - for(const CSpell * s : objects) + for(auto const & s : objects) if (!s->isSpecial() && !s->isCreatureAbility()) allowedSpells.insert(s->getId()); diff --git a/mapeditor/graphics.cpp b/mapeditor/graphics.cpp index 010f65d3d..d80dd6121 100644 --- a/mapeditor/graphics.cpp +++ b/mapeditor/graphics.cpp @@ -125,7 +125,7 @@ void Graphics::load() void Graphics::loadHeroAnimations() { - for(auto & elem : VLC->heroh->classes.objects) + for(auto & elem : VLC->heroclassesh->objects) { for(auto templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->getIndex())->getTemplates()) { diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index 3587dd1b5..d489cc727 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -142,7 +142,7 @@ void Initializer::initialize(CGHeroInstance * o) { if(t->heroClass->getId() == HeroClassID(o->subID)) { - o->type = t; + o->type = t.get(); break; } } diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index 8af35854b..ea94d4739 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -153,7 +153,7 @@ void MapController::repairMap(CMap * map) const } if(obj->ID != Obj::RANDOM_HERO) - nih->type = type; + nih->type = type.get(); if(nih->ID == Obj::HERO) //not prison nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); diff --git a/mapeditor/playerparams.cpp b/mapeditor/playerparams.cpp index 97a869f39..226b3249a 100644 --- a/mapeditor/playerparams.cpp +++ b/mapeditor/playerparams.cpp @@ -48,7 +48,7 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent) //load factions for(auto idx : VLC->townh->getAllowedFactions()) { - CFaction * faction = VLC->townh->objects.at(idx); + const CFaction * faction = VLC->townh->objects.at(idx); auto * item = new QListWidgetItem(QString::fromStdString(faction->getNameTranslated())); item->setData(Qt::UserRole, QVariant::fromValue(idx.getNum())); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); diff --git a/mapeditor/validator.cpp b/mapeditor/validator.cpp index 1d7b8455d..8ec6f51ef 100644 --- a/mapeditor/validator.cpp +++ b/mapeditor/validator.cpp @@ -78,7 +78,7 @@ std::list Validator::validate(const CMap * map) if(!hplayers) issues.emplace_back(tr("No human players allowed to play this map"), true); - std::set allHeroesOnMap; //used to find hero duplicated + std::set allHeroesOnMap; //used to find hero duplicated //checking all objects in the map for(auto o : map->objects) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index cc00e345a..7fe7e416e 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -826,7 +826,7 @@ void CGameHandler::onNewTurn() if (!t->creatures.at(k).second.empty()) // there are creatures at this level { ui32 &availableCount = sac.creatures.at(k).first; - const CCreature *cre = VLC->creh->objects.at(t->creatures.at(k).second.back()); + const CCreature *cre = t->creatures.at(k).second.back().toCreature(); if (n.specialWeek == NewTurn::PLAGUE) availableCount = t->creatures.at(k).first / 2; //halve their number, no growth @@ -2327,7 +2327,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, return; } - CCreature * crea = VLC->creh->objects.at(t->town->creatures.at(level).at(upgradeNumber)); + const CCreature * crea = t->town->creatures.at(level).at(upgradeNumber).toCreature(); SetAvailableCreatures ssi; ssi.tid = t->id; @@ -2461,7 +2461,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst const CGTownInstance * town = dynamic_cast(getObj(objid)); const CArmedInstance * army = dynamic_cast(getObj(dstid)); const CGHeroInstance * hero = dynamic_cast(getObj(dstid)); - const CCreature * c = VLC->creh->objects.at(crid); + const CCreature * c = crid.toCreature(); const bool warMachine = c->warMachine != ArtifactID::NONE; @@ -2568,7 +2568,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI giveResources(player, -totalCost); //upgrade creature - changeStackType(StackLocation(obj, pos), VLC->creh->objects.at(upgID)); + changeStackType(StackLocation(obj, pos), upgID.toCreature()); return true; } @@ -2756,7 +2756,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca auto hero = getHero(dst.artHolder); if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstSlot)) - giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot)); if(src.artHolder != dst.artHolder) @@ -2795,7 +2795,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->getTypeId(), dstSlot)) - giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + giveHeroNewArtifact(dstHero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); } }; @@ -2883,7 +2883,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a const auto dstLoc = ArtifactLocation(hero->id, artifactSlot); if(assemble) { - CArtifact * combinedArt = VLC->arth->objects[assembleTo]; + const CArtifact * combinedArt = assembleTo.toArtifact(); if(!combinedArt->isCombined()) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!"); if(!vstd::contains(ArtifactUtils::assemblyPossibilities(hero, destArtifact->getTypeId()), combinedArt)) @@ -2897,7 +2897,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a } if(ArtifactUtils::checkSpellbookIsNeeded(hero, assembleTo, artifactSlot)) - giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); AssembledArtifact aa; aa.al = dstLoc; @@ -2954,7 +2954,7 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid) return false; giveResource(hero->getOwner(),EGameResID::GOLD,-GameConstants::SPELLBOOK_GOLD_COST); - giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); assert(hero->getArt(ArtifactPosition::SPELLBOOK)); giveSpells(town,hero); return true; @@ -3025,7 +3025,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe COMPLAIN_RET("Cannot find selected artifact on the list"); sendAndApply(&saa); - giveHeroNewArtifact(h, VLC->arth->objects[aid], ArtifactPosition::FIRST_AVAILABLE); + giveHeroNewArtifact(h, aid.toArtifact(), ArtifactPosition::FIRST_AVAILABLE); return true; } @@ -4080,7 +4080,7 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID) RandomGeneratorUtil::randomShuffle(tiles, getRandomGenerator()); logGlobal->trace("Spawning wandering monsters. Found %d free tiles. Creature type: %d", tiles.size(), creatureID.num); - const CCreature *cre = VLC->creh->objects.at(creatureID); + const CCreature *cre = creatureID.toCreature(); for (int i = 0; i < (int)amount; ++i) { tile = tiles.begin(); diff --git a/server/processors/HeroPoolProcessor.cpp b/server/processors/HeroPoolProcessor.cpp index 623340e6c..54612dce2 100644 --- a/server/processors/HeroPoolProcessor.cpp +++ b/server/processors/HeroPoolProcessor.cpp @@ -253,7 +253,7 @@ std::vector HeroPoolProcessor::findAvailableClassesFor(const continue; bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player); - bool heroClassBanned = elem.second->type->heroClass->selectionProbability[factionID] == 0; + bool heroClassBanned = elem.second->type->heroClass->tavernProbability(factionID) == 0; if(heroAvailable && !heroClassBanned) result.push_back(elem.second->type->heroClass); @@ -326,13 +326,13 @@ const CHeroClass * HeroPoolProcessor::pickClassFor(bool isNative, const PlayerCo int totalWeight = 0; for(const auto & heroClass : possibleClasses) - totalWeight += heroClass->selectionProbability.at(factionID); + totalWeight += heroClass->tavernProbability(factionID); int roll = getRandomGenerator(player).nextInt(totalWeight - 1); for(const auto & heroClass : possibleClasses) { - roll -= heroClass->selectionProbability.at(factionID); + roll -= heroClass->tavernProbability(factionID); if(roll < 0) return heroClass; } diff --git a/server/processors/PlayerMessageProcessor.cpp b/server/processors/PlayerMessageProcessor.cpp index 04b4456a3..4cce9c846 100644 --- a/server/processors/PlayerMessageProcessor.cpp +++ b/server/processors/PlayerMessageProcessor.cpp @@ -137,7 +137,7 @@ void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroIns ///Give hero spellbook if (!hero->hasSpellbook()) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); ///Give all spells with bonus (to allow banned spells) GiveBonus giveBonus(GiveBonus::ETarget::OBJECT); @@ -215,11 +215,11 @@ void PlayerMessageProcessor::cheatGiveMachines(PlayerColor player, const CGHeroI return; if (!hero->getArt(ArtifactPosition::MACH1)) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::BALLISTA], ArtifactPosition::MACH1); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::BALLISTA).toArtifact(), ArtifactPosition::MACH1); if (!hero->getArt(ArtifactPosition::MACH2)) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::AMMO_CART], ArtifactPosition::MACH2); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::AMMO_CART).toArtifact(), ArtifactPosition::MACH2); if (!hero->getArt(ArtifactPosition::MACH3)) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(ArtifactID::FIRST_AID_TENT).toArtifact(), ArtifactPosition::MACH3); } void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero, std::vector words) @@ -233,7 +233,7 @@ void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHero { auto artID = VLC->identifiers()->getIdentifier(ModScope::scopeGame(), "artifact", word, false); if(artID && VLC->arth->objects[*artID]) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[*artID], ArtifactPosition::FIRST_AVAILABLE); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(*artID).toArtifact(), ArtifactPosition::FIRST_AVAILABLE); } } else @@ -241,7 +241,7 @@ void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHero for(int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods { if(VLC->arth->objects[g]->canBePutAt(hero)) - gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[g], ArtifactPosition::FIRST_AVAILABLE); + gameHandler->giveHeroNewArtifact(hero, ArtifactID(g).toArtifact(), ArtifactPosition::FIRST_AVAILABLE); } } } From 2c4cad7d9ce1f7becab19902ad535d924532d5b5 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 1 Jan 2024 00:44:09 +0200 Subject: [PATCH 02/13] Slight simplification of bonus system node class --- AI/VCAI/VCAI.cpp | 1 - client/CPlayerInterface.cpp | 1 - lib/CPlayerState.cpp | 2 - lib/CPlayerState.h | 2 - lib/IGameCallback.cpp | 1 - lib/bonuses/Bonus.cpp | 1 - lib/bonuses/CBonusSystemNode.cpp | 74 ++++++++++------------------- lib/bonuses/CBonusSystemNode.h | 11 ++--- lib/bonuses/IBonusBearer.cpp | 2 +- lib/gameState/CGameState.cpp | 8 ---- lib/serializer/BinaryDeserializer.h | 18 +------ 11 files changed, 30 insertions(+), 91 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 3939304f6..8954ff191 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -22,7 +22,6 @@ #include "../../lib/CHeroHandler.h" #include "../../lib/GameSettings.h" #include "../../lib/gameState/CGameState.h" -#include "../../lib/bonuses/CBonusSystemNode.h" #include "../../lib/bonuses/Limiters.h" #include "../../lib/bonuses/Updaters.h" #include "../../lib/bonuses/Propagators.h" diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index c405ff491..fa80b647f 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -82,7 +82,6 @@ #include "../lib/UnlockGuard.h" #include "../lib/VCMIDirs.h" -#include "../lib/bonuses/CBonusSystemNode.h" #include "../lib/bonuses/Limiters.h" #include "../lib/bonuses/Propagators.h" #include "../lib/bonuses/Updaters.h" diff --git a/lib/CPlayerState.cpp b/lib/CPlayerState.cpp index 9cb13671a..2ac3e39db 100644 --- a/lib/CPlayerState.cpp +++ b/lib/CPlayerState.cpp @@ -23,8 +23,6 @@ PlayerState::PlayerState() setNodeType(PLAYER); } -PlayerState::PlayerState(PlayerState && other) noexcept = default; - PlayerState::~PlayerState() = default; std::string PlayerState::nodeName() const diff --git a/lib/CPlayerState.h b/lib/CPlayerState.h index 175d6ff21..87959cdec 100644 --- a/lib/CPlayerState.h +++ b/lib/CPlayerState.h @@ -67,7 +67,6 @@ public: TurnTimerInfo turnTimer; PlayerState(); - PlayerState(PlayerState && other) noexcept; ~PlayerState(); std::string nodeName() const override; @@ -123,7 +122,6 @@ public: std::unique_ptr> fogOfWarMap; //[z][x][y] true - visible, false - hidden TeamState(); - TeamState(TeamState && other) noexcept; template void serialize(Handler &h, const int version) { diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index f40aebcd8..a555c5c1f 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -16,7 +16,6 @@ #include "CBonusTypeHandler.h" #include "BattleFieldHandler.h" #include "ObstacleHandler.h" -#include "bonuses/CBonusSystemNode.h" #include "bonuses/Limiters.h" #include "bonuses/Propagators.h" #include "bonuses/Updaters.h" diff --git a/lib/bonuses/Bonus.cpp b/lib/bonuses/Bonus.cpp index bcf782b78..c0324824c 100644 --- a/lib/bonuses/Bonus.cpp +++ b/lib/bonuses/Bonus.cpp @@ -10,7 +10,6 @@ #include "StdInc.h" #include "Bonus.h" -#include "CBonusSystemNode.h" #include "Limiters.h" #include "Updaters.h" #include "Propagators.h" diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index 8306e3ae1..226648d01 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -20,16 +20,15 @@ VCMI_LIB_NAMESPACE_BEGIN std::atomic CBonusSystemNode::treeChanged(1); constexpr bool CBonusSystemNode::cachingEnabled = true; -#define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); for(CBonusSystemNode *pname : lparents) -#define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); for(CBonusSystemNode *pname : lchildren) - std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) { auto ret = bonuses.getFirst(selector); if(ret) return ret; - FOREACH_PARENT(pname) + TNodes lparents; + getParents(lparents); + for(CBonusSystemNode *pname : lparents) { ret = pname->getBonusLocalFirst(selector); if (ret) @@ -227,39 +226,6 @@ CBonusSystemNode::CBonusSystemNode(ENodeTypes NodeType): { } -CBonusSystemNode::CBonusSystemNode(CBonusSystemNode && other) noexcept: - bonuses(std::move(other.bonuses)), - exportedBonuses(std::move(other.exportedBonuses)), - nodeType(other.nodeType), - cachedLast(0), - isHypotheticNode(other.isHypotheticNode) -{ - std::swap(parents, other.parents); - std::swap(children, other.children); - - //fixing bonus tree without recalculation - - if(!isHypothetic()) - { - for(CBonusSystemNode * n : parents) - { - n->children -= &other; - n->children.push_back(this); - } - } - - for(CBonusSystemNode * n : children) - { - n->parents -= &other; - n->parents.push_back(this); - } - - //cache ignored - - //cachedBonuses - //cachedRequests -} - CBonusSystemNode::~CBonusSystemNode() { detachFromAll(); @@ -405,8 +371,10 @@ void CBonusSystemNode::propagateBonus(const std::shared_ptr & b, const CB logBonus->trace("#$# %s #propagated to# %s", propagated->Description(), nodeName()); } - FOREACH_RED_CHILD(child) - child->propagateBonus(b, source); + TNodes lchildren; + getRedChildren(lchildren); + for(CBonusSystemNode *pname : lchildren) + pname->propagateBonus(b, source); } void CBonusSystemNode::unpropagateBonus(const std::shared_ptr & b) @@ -417,8 +385,10 @@ void CBonusSystemNode::unpropagateBonus(const std::shared_ptr & b) logBonus->trace("#$# %s #is no longer propagated to# %s", b->Description(), nodeName()); } - FOREACH_RED_CHILD(child) - child->unpropagateBonus(b); + TNodes lchildren; + getRedChildren(lchildren); + for(CBonusSystemNode *pname : lchildren) + pname->unpropagateBonus(b); } void CBonusSystemNode::newChildAttached(CBonusSystemNode & child) @@ -467,9 +437,11 @@ void CBonusSystemNode::deserializationFix() } -void CBonusSystemNode::getRedParents(TNodes & out) +void CBonusSystemNode::getRedParents(TCNodes & out) const { - FOREACH_PARENT(pname) + TCNodes lparents; + getParents(lparents); + for(const CBonusSystemNode *pname : lparents) { if(pname->actsAsBonusSourceOnly()) { @@ -488,7 +460,9 @@ void CBonusSystemNode::getRedParents(TNodes & out) void CBonusSystemNode::getRedChildren(TNodes &out) { - FOREACH_PARENT(pname) + TNodes lparents; + getParents(lparents); + for(CBonusSystemNode *pname : lparents) { if(!pname->actsAsBonusSourceOnly()) { @@ -512,7 +486,7 @@ void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) if(b->propagator) descendant.propagateBonus(b, *this); } - TNodes redParents; + TCNodes redParents; getRedAncestors(redParents); //get all red parents recursively for(auto * parent : redParents) @@ -531,7 +505,7 @@ void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) if(b->propagator) descendant.unpropagateBonus(b); - TNodes redParents; + TCNodes redParents; getRedAncestors(redParents); //get all red parents recursively for(auto * parent : redParents) @@ -542,14 +516,14 @@ void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) } } -void CBonusSystemNode::getRedAncestors(TNodes &out) +void CBonusSystemNode::getRedAncestors(TCNodes &out) const { getRedParents(out); - TNodes redParents; + TCNodes redParents; getRedParents(redParents); - for(CBonusSystemNode * parent : redParents) + for(const CBonusSystemNode * parent : redParents) parent->getRedAncestors(out); } @@ -646,4 +620,4 @@ int64_t CBonusSystemNode::getTreeVersion() const return treeChanged; } -VCMI_LIB_NAMESPACE_END \ No newline at end of file +VCMI_LIB_NAMESPACE_END diff --git a/lib/bonuses/CBonusSystemNode.h b/lib/bonuses/CBonusSystemNode.h index b5d4f8f71..7dd5f782a 100644 --- a/lib/bonuses/CBonusSystemNode.h +++ b/lib/bonuses/CBonusSystemNode.h @@ -33,7 +33,7 @@ private: BonusList bonuses; //wielded bonuses (local or up-propagated here) BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away) - TNodesVector parents; //parents -> we inherit bonuses from them, we may attach our bonuses to them + TNodesVector parents; // we inherit bonuses from them, we may attach our bonuses to them TNodesVector children; ENodeTypes nodeType; @@ -54,8 +54,8 @@ private: TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const; std::shared_ptr getUpdatedBonus(const std::shared_ptr & b, const TUpdaterPtr & updater) const; - void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from) - void getRedAncestors(TNodes &out); + void getRedParents(TCNodes &out) const; //retrieves list of red parent nodes (nodes bonuses propagate from) + void getRedAncestors(TCNodes &out) const; void getRedChildren(TNodes &out); void getAllParents(TCNodes & out) const; @@ -80,7 +80,6 @@ protected: public: explicit CBonusSystemNode(bool isHypotetic = false); explicit CBonusSystemNode(ENodeTypes NodeType); - CBonusSystemNode(CBonusSystemNode && other) noexcept; virtual ~CBonusSystemNode(); void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here @@ -128,14 +127,12 @@ public: template void serialize(Handler &h, const int version) { -// h & bonuses; h & nodeType; h & exportedBonuses; BONUS_TREE_DESERIALIZATION_FIX - //h & parents & children; } friend class CBonusProxy; }; -VCMI_LIB_NAMESPACE_END \ No newline at end of file +VCMI_LIB_NAMESPACE_END diff --git a/lib/bonuses/IBonusBearer.cpp b/lib/bonuses/IBonusBearer.cpp index 63ab0b631..a0bfc7087 100644 --- a/lib/bonuses/IBonusBearer.cpp +++ b/lib/bonuses/IBonusBearer.cpp @@ -10,7 +10,7 @@ #include "StdInc.h" -#include "CBonusSystemNode.h" +#include "IBonusBearer.h" #include "BonusList.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 089d4aced..5529df727 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -1928,14 +1928,6 @@ TeamState::TeamState() fogOfWarMap = std::make_unique>(); } -TeamState::TeamState(TeamState && other) noexcept: - CBonusSystemNode(std::move(other)), - id(other.id) -{ - std::swap(players, other.players); - std::swap(fogOfWarMap, other.fogOfWarMap); -} - CRandomGenerator & CGameState::getRandomGenerator() { return rand; diff --git a/lib/serializer/BinaryDeserializer.h b/lib/serializer/BinaryDeserializer.h index 8b2696957..aa2b40f21 100644 --- a/lib/serializer/BinaryDeserializer.h +++ b/lib/serializer/BinaryDeserializer.h @@ -416,26 +416,10 @@ public: ui32 length = readAndCheckLength(); data.clear(); T1 key; - T2 value; for(ui32 i=0;i(std::move(key), std::move(value))); - } - } - template - void load(std::multimap &data) - { - ui32 length = readAndCheckLength(); - data.clear(); - T1 key; - T2 value; - for(ui32 i = 0; i < length; i++) - { - load(key); - load(value); - data.insert(std::pair(std::move(key), std::move(value))); + load(data[key]); } } void load(std::string &data) From c37ce05d06bcbb270f8eee5bb467876244c5f361 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 1 Jan 2024 12:49:17 +0200 Subject: [PATCH 03/13] Attempt to make constant bonus system nodes (CCreature / CArtifact) fully constant --- lib/CArtifactInstance.cpp | 2 +- lib/CCreatureSet.cpp | 4 +- lib/CStack.cpp | 2 +- lib/bonuses/CBonusSystemNode.cpp | 111 ++++++++++++++++++++----------- lib/bonuses/CBonusSystemNode.h | 11 +-- 5 files changed, 83 insertions(+), 47 deletions(-) diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 39aa644f7..a3efb5dfd 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -121,7 +121,7 @@ CArtifactInstance::CArtifactInstance() void CArtifactInstance::setType(const CArtifact * art) { artType = art; - attachTo(const_cast(*art)); + attachToSource(*art); } std::string CArtifactInstance::nodeName() const diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 8f09c6592..30479aef2 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -758,7 +758,7 @@ void CStackInstance::setType(const CCreature *c) { if(type) { - detachFrom(const_cast(*type)); + detachFromSource(*type); if (type->isMyUpgrade(c) && VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) experience = static_cast(experience * VLC->creh->expAfterUpgrade / 100.0); } @@ -766,7 +766,7 @@ void CStackInstance::setType(const CCreature *c) CStackBasicDescriptor::setType(c); if(type) - attachTo(const_cast(*type)); + attachToSource(*type); } std::string CStackInstance::bonusToString(const std::shared_ptr& bonus, bool description) const { diff --git a/lib/CStack.cpp b/lib/CStack.cpp index 128b1e2bb..a84f8cd0f 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -72,7 +72,7 @@ void CStack::localInit(BattleInfo * battleInfo) CArmedInstance * army = battle->battleGetArmyObject(side); assert(army); attachTo(*army); - attachTo(const_cast(*type)); + attachToSource(*type); } nativeTerrain = getNativeTerrain(); //save nativeTerrain in the variable on the battle start to avoid dead lock CUnitState::localInit(this); //it causes execution of the CStack::isOnNativeTerrain where nativeTerrain will be considered diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index 226648d01..82f792849 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -25,10 +25,18 @@ std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & se auto ret = bonuses.getFirst(selector); if(ret) return ret; + return nullptr; +} - TNodes lparents; +std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) const +{ + auto ret = bonuses.getFirst(selector); + if(ret) + return ret; + + TCNodes lparents; getParents(lparents); - for(CBonusSystemNode *pname : lparents) + for(const CBonusSystemNode *pname : lparents) { ret = pname->getBonusLocalFirst(selector); if (ret) @@ -38,28 +46,15 @@ std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & se return nullptr; } -std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) const -{ - return (const_cast(this))->getBonusLocalFirst(selector); -} - void CBonusSystemNode::getParents(TCNodes & out) const /*retrieves list of parent nodes (nodes to inherit bonuses from) */ { - for(const auto * elem : parents) + for(const auto * elem : parentsToInherit) out.insert(elem); } -void CBonusSystemNode::getParents(TNodes &out) -{ - for (auto * elem : parents) - { - out.insert(elem); - } -} - void CBonusSystemNode::getAllParents(TCNodes & out) const //retrieves list of parent nodes (nodes to inherit bonuses from) { - for(auto * parent : parents) + for(auto * parent : parentsToInherit) { out.insert(parent); parent->getAllParents(out); @@ -239,14 +234,14 @@ CBonusSystemNode::~CBonusSystemNode() void CBonusSystemNode::attachTo(CBonusSystemNode & parent) { - assert(!vstd::contains(parents, &parent)); - parents.push_back(&parent); + assert(!vstd::contains(parentsToPropagate, &parent)); + parentsToPropagate.push_back(&parent); + + attachToSource(parent); if(!isHypothetic()) { - if(parent.actsAsBonusSourceOnly()) - parent.newRedDescendant(*this); - else + if(!parent.actsAsBonusSourceOnly()) newRedDescendant(parent); parent.newChildAttached(*this); @@ -255,21 +250,35 @@ void CBonusSystemNode::attachTo(CBonusSystemNode & parent) CBonusSystemNode::treeHasChanged(); } -void CBonusSystemNode::detachFrom(CBonusSystemNode & parent) +void CBonusSystemNode::attachToSource(const CBonusSystemNode & parent) { - assert(vstd::contains(parents, &parent)); + assert(!vstd::contains(parentsToInherit, &parent)); + parentsToInherit.push_back(&parent); if(!isHypothetic()) { if(parent.actsAsBonusSourceOnly()) - parent.removedRedDescendant(*this); - else + parent.newRedDescendant(*this); + } + + CBonusSystemNode::treeHasChanged(); +} + +void CBonusSystemNode::detachFrom(CBonusSystemNode & parent) +{ + assert(vstd::contains(parentsToPropagate, &parent)); + + if(!isHypothetic()) + { + if(!parent.actsAsBonusSourceOnly()) removedRedDescendant(parent); } - if (vstd::contains(parents, &parent)) + detachFromSource(parent); + + if (vstd::contains(parentsToPropagate, &parent)) { - parents -= &parent; + parentsToPropagate -= &parent; } else { @@ -284,6 +293,30 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode & parent) CBonusSystemNode::treeHasChanged(); } + +void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent) +{ + assert(vstd::contains(parentsToInherit, &parent)); + + if(!isHypothetic()) + { + if(parent.actsAsBonusSourceOnly()) + parent.removedRedDescendant(*this); + } + + if (vstd::contains(parentsToPropagate, &parent)) + { + parentsToInherit -= &parent; + } + else + { + logBonus->error("Error on Detach. Node %s (nodeType=%d) has not parent %s (nodeType=%d)" + , nodeShortInfo(), nodeType, parent.nodeShortInfo(), parent.nodeType); + } + + CBonusSystemNode::treeHasChanged(); +} + void CBonusSystemNode::removeBonusesRecursive(const CSelector & s) { removeBonuses(s); @@ -410,13 +443,16 @@ void CBonusSystemNode::childDetached(CBonusSystemNode & child) void CBonusSystemNode::detachFromAll() { - while(!parents.empty()) - detachFrom(*parents.front()); + while(!parentsToPropagate.empty()) + detachFrom(*parentsToPropagate.front()); + + while(!parentsToInherit.empty()) + detachFromSource(*parentsToInherit.front()); } bool CBonusSystemNode::isIndependentNode() const { - return parents.empty() && children.empty(); + return parentsToInherit.empty() && parentsToPropagate.empty() && children.empty(); } std::string CBonusSystemNode::nodeName() const @@ -434,7 +470,6 @@ std::string CBonusSystemNode::nodeShortInfo() const void CBonusSystemNode::deserializationFix() { exportBonuses(); - } void CBonusSystemNode::getRedParents(TCNodes & out) const @@ -460,9 +495,7 @@ void CBonusSystemNode::getRedParents(TCNodes & out) const void CBonusSystemNode::getRedChildren(TNodes &out) { - TNodes lparents; - getParents(lparents); - for(CBonusSystemNode *pname : lparents) + for(CBonusSystemNode *pname : parentsToPropagate) { if(!pname->actsAsBonusSourceOnly()) { @@ -479,7 +512,7 @@ void CBonusSystemNode::getRedChildren(TNodes &out) } } -void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) +void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) const { for(const auto & b : exportedBonuses) { @@ -489,7 +522,7 @@ void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) TCNodes redParents; getRedAncestors(redParents); //get all red parents recursively - for(auto * parent : redParents) + for(const auto * parent : redParents) { for(const auto & b : parent->exportedBonuses) { @@ -499,7 +532,7 @@ void CBonusSystemNode::newRedDescendant(CBonusSystemNode & descendant) } } -void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) +void CBonusSystemNode::removedRedDescendant(CBonusSystemNode & descendant) const { for(const auto & b : exportedBonuses) if(b->propagator) @@ -550,7 +583,7 @@ CBonusSystemNode::ENodeTypes CBonusSystemNode::getNodeType() const const TNodesVector& CBonusSystemNode::getParentNodes() const { - return parents; + return parentsToPropagate; } void CBonusSystemNode::setNodeType(CBonusSystemNode::ENodeTypes type) diff --git a/lib/bonuses/CBonusSystemNode.h b/lib/bonuses/CBonusSystemNode.h index 7dd5f782a..afc4dec5d 100644 --- a/lib/bonuses/CBonusSystemNode.h +++ b/lib/bonuses/CBonusSystemNode.h @@ -19,6 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN using TNodes = std::set; using TCNodes = std::set; using TNodesVector = std::vector; +using TCNodesVector = std::vector; class DLL_LINKAGE CBonusSystemNode : public virtual IBonusBearer, public boost::noncopyable { @@ -33,7 +34,8 @@ private: BonusList bonuses; //wielded bonuses (local or up-propagated here) BonusList exportedBonuses; //bonuses coming from this node (wielded or propagated away) - TNodesVector parents; // we inherit bonuses from them, we may attach our bonuses to them + TCNodesVector parentsToInherit; // we inherit bonuses from them + TNodesVector parentsToPropagate; // we may attach our bonuses to them TNodesVector children; ENodeTypes nodeType; @@ -66,8 +68,8 @@ private: void unpropagateBonus(const std::shared_ptr & b); bool actsAsBonusSourceOnly() const; - void newRedDescendant(CBonusSystemNode & descendant); //propagation needed - void removedRedDescendant(CBonusSystemNode & descendant); //de-propagation needed + void newRedDescendant(CBonusSystemNode & descendant) const; //propagation needed + void removedRedDescendant(CBonusSystemNode & descendant) const; //de-propagation needed std::string nodeShortInfo() const; @@ -89,11 +91,12 @@ public: std::shared_ptr getBonusLocalFirst(const CSelector & selector) const; //non-const interface - void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from) std::shared_ptr getBonusLocalFirst(const CSelector & selector); void attachTo(CBonusSystemNode & parent); + void attachToSource(const CBonusSystemNode & parent); void detachFrom(CBonusSystemNode & parent); + void detachFromSource(const CBonusSystemNode & parent); void detachFromAll(); virtual void addNewBonus(const std::shared_ptr& b); void accumulateBonus(const std::shared_ptr& b); //add value of bonus with same type/subtype or create new From a15366f5a525ba198a76f77cf0b0bb6d0707d5a3 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 1 Jan 2024 16:37:48 +0200 Subject: [PATCH 04/13] 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; } From e67e4430bac50722869389c24e0591ebc7b43218 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 9 Jan 2024 16:43:36 +0200 Subject: [PATCH 05/13] Removed most of non-const static fields in lib. Reduced header includes. --- CCallback.cpp | 1 + client/NetPacksClient.cpp | 1 + client/mapView/MapRendererContext.cpp | 1 + lib/CArtHandler.cpp | 4 ++-- lib/CCreatureHandler.h | 2 -- lib/CGameInfoCallback.cpp | 10 ++++++---- lib/CTownHandler.cpp | 10 +++++----- lib/CTownHandler.h | 6 +++--- lib/IGameCallback.cpp | 3 +++ lib/IHandlerBase.h | 10 ---------- lib/JsonNode.cpp | 5 ++--- lib/battle/CBattleInfoEssentials.cpp | 5 ++--- lib/bonuses/BonusSelector.cpp | 24 ++++++++++++------------ lib/bonuses/BonusSelector.h | 12 ++++++------ lib/campaign/CampaignState.cpp | 1 + lib/gameState/CGameState.cpp | 22 ++++++++++++---------- lib/gameState/CGameStateCampaign.cpp | 1 + lib/mapObjects/CGDwelling.cpp | 1 + lib/mapObjects/CGHeroInstance.cpp | 1 + lib/mapObjects/CGTownInstance.cpp | 14 ++------------ lib/mapObjects/CGTownInstance.h | 4 ---- lib/mapObjects/MiscObjects.cpp | 19 +++++-------------- lib/mapObjects/MiscObjects.h | 4 ---- lib/mapping/CDrawRoadsOperation.cpp | 1 + lib/mapping/CMap.cpp | 8 ++++++-- lib/mapping/CMap.h | 22 ++++++++++++++-------- lib/mapping/CMapOperation.cpp | 9 +++++---- lib/mapping/MapFormatJson.cpp | 1 + lib/mapping/ObstacleProxy.cpp | 1 + lib/networkPacks/NetPacksLib.cpp | 5 ++++- lib/pathfinder/CPathfinder.cpp | 2 ++ lib/pathfinder/NodeStorage.cpp | 1 + lib/rmg/CMapGenerator.cpp | 1 + lib/rmg/CZonePlacer.cpp | 5 +++-- lib/rmg/RmgMap.h | 1 + lib/rmg/RmgObject.cpp | 1 + lib/rmg/modificators/MinePlacer.cpp | 1 + lib/rmg/modificators/ObstaclePlacer.cpp | 1 + lib/rmg/modificators/RoadPlacer.cpp | 1 + lib/rmg/modificators/TerrainPainter.cpp | 1 + lib/rmg/modificators/TownPlacer.cpp | 1 + lib/rmg/modificators/TreasurePlacer.cpp | 10 ++++++---- lib/rmg/modificators/WaterProxy.cpp | 1 + lib/serializer/CSerializer.cpp | 7 +++++++ lib/serializer/CSerializer.h | 5 +++++ lib/spells/AdventureSpellMechanics.cpp | 2 ++ mapeditor/maphandler.cpp | 1 + mapeditor/mapsettings/translations.cpp | 1 + server/CGameHandler.cpp | 4 +++- 49 files changed, 139 insertions(+), 116 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index 85cf0471b..5930c4fe7 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -16,6 +16,7 @@ #include "client/Client.h" #include "lib/mapping/CMap.h" #include "lib/mapObjects/CGHeroInstance.h" +#include "lib/mapObjects/CGTownInstance.h" #include "lib/CBuildingHandler.h" #include "lib/CGeneralTextHandler.h" #include "lib/CHeroHandler.h" diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index a6d0bff9a..1b7ab14c1 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -39,6 +39,7 @@ #include "../lib/StartInfo.h" #include "../lib/CConfigHandler.h" #include "../lib/mapObjects/CGMarket.h" +#include "../lib/mapObjects/CGTownInstance.h" #include "../lib/gameState/CGameState.h" #include "../lib/CStack.h" #include "../lib/battle/BattleInfo.h" diff --git a/client/mapView/MapRendererContext.cpp b/client/mapView/MapRendererContext.cpp index 07b5575eb..88348af09 100644 --- a/client/mapView/MapRendererContext.cpp +++ b/client/mapView/MapRendererContext.cpp @@ -21,6 +21,7 @@ #include "../../lib/Point.h" #include "../../lib/mapObjects/CGHeroInstance.h" +#include "../../lib/mapObjects/MiscObjects.h" #include "../../lib/spells/CSpellHandler.h" #include "../../lib/mapping/CMap.h" #include "../../lib/pathfinder/CGPathNode.h" diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index f7a020f58..b3ed48b6a 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -328,7 +328,7 @@ std::vector CArtHandler::loadLegacyData() const std::vector artSlots = { ART_POS_LIST }; #undef ART_POS - static std::map classes = + static const std::map classes = {{'S',"SPECIAL"}, {'T',"TREASURE"},{'N',"MINOR"},{'J',"MAJOR"},{'R',"RELIC"},}; CLegacyConfigParser parser(TextPath::builtin("DATA/ARTRAITS.TXT")); @@ -353,7 +353,7 @@ std::vector CArtHandler::loadLegacyData() artData["slot"].Vector().back().String() = artSlot; } } - artData["class"].String() = classes[parser.readString()[0]]; + artData["class"].String() = classes.at(parser.readString()[0]); artData["text"]["description"].String() = parser.readString(); parser.endLine(); diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index ee98ef528..bb89960ff 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -222,8 +222,6 @@ public: std::vector< std::vector > skillLevels; //how much of a bonus will be given to commander with every level. SPELL_POWER also gives CASTS and RESISTANCE std::vector , std::pair > > skillRequirements; // first - Bonus, second - which two skills are needed to use it - //const CCreature * getCreature(const std::string & scope, const std::string & identifier) const; - CreatureID pickRandomMonster(CRandomGenerator & rand, int tier = -1) const; //tier <1 - CREATURES_PER_TOWN> or -1 for any CCreatureHandler(); diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index b86e6ef70..2f40a5ab7 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -16,6 +16,8 @@ #include "gameState/TavernHeroesPool.h" #include "gameState/QuestInfo.h" #include "mapObjects/CGHeroInstance.h" +#include "mapObjects/CGTownInstance.h" +#include "mapObjects/MiscObjects.h" #include "networkPacks/ArtifactLocation.h" #include "CGeneralTextHandler.h" #include "StartInfo.h" // for StartInfo @@ -791,7 +793,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio ) { - if (!getPlayerID() || CGObelisk::obeliskCount == 0) + if (!getPlayerID() || gs->map->obeliskCount == 0) { *outKnownRatio = 0.0; } @@ -799,10 +801,10 @@ int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio ) { TeamID t = gs->getPlayerTeam(*getPlayerID())->id; double visited = 0.0; - if(CGObelisk::visited.count(t)) - visited = static_cast(CGObelisk::visited[t]); + if(gs->map->obelisksVisited.count(t)) + visited = static_cast(gs->map->obelisksVisited[t]); - *outKnownRatio = visited / CGObelisk::obeliskCount; + *outKnownRatio = visited / gs->map->obeliskCount; } return gs->map->grailPos; } diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 331cb881c..cac5982bc 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -336,9 +336,9 @@ JsonNode readBuilding(CLegacyConfigParser & parser) return ret; } -TPropagatorPtr & CTownHandler::emptyPropagator() +const TPropagatorPtr & CTownHandler::emptyPropagator() { - static TPropagatorPtr emptyProp(nullptr); + static const TPropagatorPtr emptyProp(nullptr); return emptyProp; } @@ -534,7 +534,7 @@ R CTownHandler::getMappedValue(const JsonNode & node, const R defval, const std: void CTownHandler::addBonusesForVanilaBuilding(CBuilding * building) const { std::shared_ptr b; - static TPropagatorPtr playerPropagator = std::make_shared(CBonusSystemNode::ENodeTypes::PLAYER); + static const TPropagatorPtr playerPropagator = std::make_shared(CBonusSystemNode::ENodeTypes::PLAYER); if(building->bid == BuildingID::TAVERN) { @@ -578,7 +578,7 @@ std::shared_ptr CTownHandler::createBonus(CBuilding * build, BonusType ty return createBonus(build, type, val, subtype, emptyPropagator()); } -std::shared_ptr CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, TPropagatorPtr & prop) const +std::shared_ptr CTownHandler::createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const { std::ostringstream descr; descr << build->getNameTranslated(); @@ -589,7 +589,7 @@ std::shared_ptr CTownHandler::createBonusImpl(const BuildingID & building const FactionID & faction, BonusType type, int val, - TPropagatorPtr & prop, + const TPropagatorPtr & prop, const std::string & description, BonusSubtypeID subtype) const { diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 5a8421b35..97bfa325f 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -290,7 +290,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase requirementsToLoad; std::vector overriddenBidsToLoad; //list of buildings, which bonuses should be overridden. - static TPropagatorPtr & emptyPropagator(); + static const TPropagatorPtr & emptyPropagator(); void initializeRequirements(); void initializeOverridden(); @@ -303,12 +303,12 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase createBonus(CBuilding * build, BonusType type, int val) const; std::shared_ptr createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype) const; - std::shared_ptr createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, TPropagatorPtr & prop) const; + std::shared_ptr createBonus(CBuilding * build, BonusType type, int val, BonusSubtypeID subtype, const TPropagatorPtr & prop) const; std::shared_ptr createBonusImpl(const BuildingID & building, const FactionID & faction, BonusType type, int val, - TPropagatorPtr & prop, + const TPropagatorPtr & prop, const std::string & description, BonusSubtypeID subtype) const; diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index a555c5c1f..61d940cf3 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -25,7 +25,10 @@ #include "rmg/CMapGenOptions.h" #include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/CObjectClassesHandler.h" +#include "mapObjects/CGTownInstance.h" #include "mapObjects/CObjectHandler.h" +#include "mapObjects/CQuest.h" +#include "mapObjects/MiscObjects.h" #include "mapObjects/ObjectTemplate.h" #include "campaign/CampaignState.h" #include "StartInfo.h" diff --git a/lib/IHandlerBase.h b/lib/IHandlerBase.h index fe05606b9..1666acee1 100644 --- a/lib/IHandlerBase.h +++ b/lib/IHandlerBase.h @@ -68,16 +68,6 @@ public: } } - _Object * getObjectWriteable(const int32_t index) - { - if(index < 0 || index >= objects.size()) - { - logMod->error("%s id %d is invalid", getTypeNames()[0], index); - throw std::runtime_error("Attempt to access invalid index " + std::to_string(index) + " of type " + getTypeNames().front()); - } - return objects[index].get(); - } - const Entity * getBaseByIndex(const int32_t index) const override { return getObjectImpl(index); diff --git a/lib/JsonNode.cpp b/lib/JsonNode.cpp index 1402ecd13..23ac2da6b 100644 --- a/lib/JsonNode.cpp +++ b/lib/JsonNode.cpp @@ -690,7 +690,6 @@ std::shared_ptr JsonUtils::parseBonus(const JsonVector & ability_vec) template const T parseByMap(const std::map & map, const JsonNode * val, const std::string & err) { - static T defaultValue = T(); if (!val->isNull()) { const std::string & type = val->String(); @@ -698,7 +697,7 @@ const T parseByMap(const std::map & map, const JsonNode * val, c if (it == map.end()) { logMod->error("Error: invalid %s%s.", err, type); - return defaultValue; + return {}; } else { @@ -706,7 +705,7 @@ const T parseByMap(const std::map & map, const JsonNode * val, c } } else - return defaultValue; + return {}; } template diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index b7761a6f8..f3ee409c0 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -401,10 +401,9 @@ PlayerColor CBattleInfoEssentials::battleGetOwner(const battle::Unit * unit) con PlayerColor initialOwner = getBattle()->getSidePlayer(unit->unitSide()); - static CSelector selector = Selector::type()(BonusType::HYPNOTIZED); - static std::string cachingString = "type_103s-1"; + static const CSelector selector = Selector::type()(BonusType::HYPNOTIZED); - if(unit->hasBonus(selector, cachingString)) + if(unit->hasBonus(selector)) return otherPlayer(initialOwner); else return initialOwner; diff --git a/lib/bonuses/BonusSelector.cpp b/lib/bonuses/BonusSelector.cpp index 1c75f1f4e..b0c30602e 100644 --- a/lib/bonuses/BonusSelector.cpp +++ b/lib/bonuses/BonusSelector.cpp @@ -15,39 +15,39 @@ VCMI_LIB_NAMESPACE_BEGIN namespace Selector { - DLL_LINKAGE CSelectFieldEqual & type() + DLL_LINKAGE const CSelectFieldEqual & type() { - static CSelectFieldEqual stype(&Bonus::type); + static const CSelectFieldEqual stype(&Bonus::type); return stype; } - DLL_LINKAGE CSelectFieldEqual & subtype() + DLL_LINKAGE const CSelectFieldEqual & subtype() { - static CSelectFieldEqual ssubtype(&Bonus::subtype); + static const CSelectFieldEqual ssubtype(&Bonus::subtype); return ssubtype; } - DLL_LINKAGE CSelectFieldEqual & info() + DLL_LINKAGE const CSelectFieldEqual & info() { - static CSelectFieldEqual sinfo(&Bonus::additionalInfo); + static const CSelectFieldEqual sinfo(&Bonus::additionalInfo); return sinfo; } - DLL_LINKAGE CSelectFieldEqual & sourceType() + DLL_LINKAGE const CSelectFieldEqual & sourceType() { - static CSelectFieldEqual ssourceType(&Bonus::source); + static const CSelectFieldEqual ssourceType(&Bonus::source); return ssourceType; } - DLL_LINKAGE CSelectFieldEqual & targetSourceType() + DLL_LINKAGE const CSelectFieldEqual & targetSourceType() { - static CSelectFieldEqual ssourceType(&Bonus::targetSourceType); + static const CSelectFieldEqual ssourceType(&Bonus::targetSourceType); return ssourceType; } - DLL_LINKAGE CSelectFieldEqual & effectRange() + DLL_LINKAGE const CSelectFieldEqual & effectRange() { - static CSelectFieldEqual seffectRange(&Bonus::effectRange); + static const CSelectFieldEqual seffectRange(&Bonus::effectRange); return seffectRange; } diff --git a/lib/bonuses/BonusSelector.h b/lib/bonuses/BonusSelector.h index 14fe31c92..f8434b4c7 100644 --- a/lib/bonuses/BonusSelector.h +++ b/lib/bonuses/BonusSelector.h @@ -125,12 +125,12 @@ public: namespace Selector { - extern DLL_LINKAGE CSelectFieldEqual & type(); - extern DLL_LINKAGE CSelectFieldEqual & subtype(); - extern DLL_LINKAGE CSelectFieldEqual & info(); - extern DLL_LINKAGE CSelectFieldEqual & sourceType(); - extern DLL_LINKAGE CSelectFieldEqual & targetSourceType(); - extern DLL_LINKAGE CSelectFieldEqual & effectRange(); + extern DLL_LINKAGE const CSelectFieldEqual & type(); + extern DLL_LINKAGE const CSelectFieldEqual & subtype(); + extern DLL_LINKAGE const CSelectFieldEqual & info(); + extern DLL_LINKAGE const CSelectFieldEqual & sourceType(); + extern DLL_LINKAGE const CSelectFieldEqual & targetSourceType(); + extern DLL_LINKAGE const CSelectFieldEqual & effectRange(); extern DLL_LINKAGE CWillLastTurns turns; extern DLL_LINKAGE CWillLastDays days; diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index 65468b42e..cb09e516d 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -11,6 +11,7 @@ #include "CampaignState.h" #include "../JsonNode.h" +#include "../Point.h" #include "../filesystem/ResourcePath.h" #include "../VCMI_Lib.h" #include "../CGeneralTextHandler.h" diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 8ebd2885d..0a52f96fc 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -36,6 +36,8 @@ #include "../mapObjectConstructors/DwellingInstanceConstructor.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGTownInstance.h" +#include "../mapObjects/CQuest.h" +#include "../mapObjects/MiscObjects.h" #include "../mapping/CMap.h" #include "../mapping/CMapEditManager.h" #include "../mapping/CMapService.h" @@ -226,7 +228,7 @@ void CGameState::init(const IMapService * mapService, StartInfo * si, Load::Prog for(auto & elem : teams) { - CGObelisk::visited[elem.first] = 0; + map->obelisksVisited[elem.first] = 0; } logGlobal->debug("\tChecking objectives"); @@ -766,11 +768,11 @@ void CGameState::initTowns() if (campaign) campaign->initTowns(); - CGTownInstance::universitySkills.clear(); - CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC)); - CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC)); - CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC)); - CGTownInstance::universitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC)); + map->townUniversitySkills.clear(); + map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::FIRE_MAGIC)); + map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::AIR_MAGIC)); + map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::WATER_MAGIC)); + map->townUniversitySkills.push_back(SecondarySkill(SecondarySkill::EARTH_MAGIC)); for (auto & elem : map->towns) { @@ -1202,7 +1204,7 @@ int3 CGameState::guardingCreaturePosition (int3 pos) const void CGameState::updateRumor() { - static std::vector rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND}; + static const std::vector rumorTypes = {RumorState::TYPE_MAP, RumorState::TYPE_SPECIAL, RumorState::TYPE_RAND, RumorState::TYPE_RAND}; std::vector sRumorTypes = { RumorState::RUMOR_OBELISKS, RumorState::RUMOR_ARTIFACTS, RumorState::RUMOR_ARMY, RumorState::RUMOR_INCOME}; if(map->grailPos.valid()) // Grail should always be on map, but I had related crash I didn't manage to reproduce @@ -1716,10 +1718,10 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level) } if(level >= 3) //obelisks found { - auto getObeliskVisited = [](const TeamID & t) + auto getObeliskVisited = [&](const TeamID & t) { - if(CGObelisk::visited.count(t)) - return CGObelisk::visited[t]; + if(map->obelisksVisited.count(t)) + return map->obelisksVisited[t]; else return ui8(0); }; diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index f7614751d..ae6a5680f 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -16,6 +16,7 @@ #include "../campaign/CampaignState.h" #include "../mapping/CMapEditManager.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CGTownInstance.h" #include "../networkPacks/ArtifactLocation.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" diff --git a/lib/mapObjects/CGDwelling.cpp b/lib/mapObjects/CGDwelling.cpp index e91b99d42..dafcc8819 100644 --- a/lib/mapObjects/CGDwelling.cpp +++ b/lib/mapObjects/CGDwelling.cpp @@ -16,6 +16,7 @@ #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjectConstructors/DwellingInstanceConstructor.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CGTownInstance.h" #include "../networkPacks/StackLocation.h" #include "../networkPacks/PacksForClient.h" #include "../networkPacks/PacksForClientBattle.h" diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index f6d6bc62c..6c4c07821 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -33,6 +33,7 @@ #include "../serializer/JsonSerializeFormat.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" +#include "../mapObjects/MiscObjects.h" #include "../modding/ModScope.h" #include "../networkPacks/PacksForClient.h" #include "../networkPacks/PacksForClientBattle.h" diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 0aa6449bb..ecb233ff5 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -33,10 +33,6 @@ VCMI_LIB_NAMESPACE_BEGIN -std::vector CGTownInstance::merchantArtifacts; -std::vector CGTownInstance::universitySkills; - - int CGTownInstance::getSightRadius() const //returns sight distance { auto ret = CBuilding::HEIGHT_NO_TOWER; @@ -772,7 +768,7 @@ std::vector CGTownInstance::availableItemsIds(EMarketMode mode) co if(mode == EMarketMode::RESOURCE_ARTIFACT) { std::vector ret; - for(const CArtifact *a : merchantArtifacts) + for(const CArtifact *a : cb->gameState()->map->townMerchantArtifacts) if(a) ret.push_back(a->getId()); else @@ -781,7 +777,7 @@ std::vector CGTownInstance::availableItemsIds(EMarketMode mode) co } else if ( mode == EMarketMode::RESOURCE_SKILL ) { - return universitySkills; + return cb->gameState()->map->townUniversitySkills; } else return IMarket::availableItemsIds(mode); @@ -1115,12 +1111,6 @@ void CGTownInstance::afterRemoveFromMap(CMap * map) vstd::erase_if_present(map->towns, this); } -void CGTownInstance::reset() -{ - CGTownInstance::merchantArtifacts.clear(); - CGTownInstance::universitySkills.clear(); -} - void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler) { CGObjectInstance::serializeJsonOwner(handler); diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 241eb2432..d29edeac5 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -67,9 +67,6 @@ public: std::pair bonusValue;//var to store town bonuses (rampart = resources from mystic pond); ////////////////////////////////////////////////////////////////////////// - static std::vector merchantArtifacts; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought) - static std::vector universitySkills;//skills for university of magic - template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -216,7 +213,6 @@ public: void afterAddToMap(CMap * map) override; void afterRemoveFromMap(CMap * map) override; - static void reset(); inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const { diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 4fe166b75..a0fac366b 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -34,9 +34,6 @@ VCMI_LIB_NAMESPACE_BEGIN -ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map -std::map CGObelisk::visited; //map: team_id => how many obelisks has been visited - ///helpers static std::string visitedTxt(const bool visited) { @@ -1243,13 +1240,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const void CGObelisk::initObj(CRandomGenerator & rand) { - obeliskCount++; -} - -void CGObelisk::reset() -{ - obeliskCount = 0; - visited.clear(); + cb->gameState()->map->obeliskCount++; } std::string CGObelisk::getHoverText(PlayerColor player) const @@ -1263,12 +1254,12 @@ void CGObelisk::setPropertyDer(ObjProperty what, ObjPropertyID identifier) { case ObjProperty::OBELISK_VISITED: { - auto progress = ++visited[identifier.as()]; - logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast(progress) , static_cast(obeliskCount)); + auto progress = ++cb->gameState()->map->obelisksVisited[identifier.as()]; + logGlobal->debug("Player %d: obelisk progress %d / %d", identifier.getNum(), static_cast(progress) , static_cast(cb->gameState()->map->obeliskCount)); - if(progress > obeliskCount) + if(progress > cb->gameState()->map->obeliskCount) { - logGlobal->error("Visited %d of %d", static_cast(progress), obeliskCount); + logGlobal->error("Visited %d of %d", static_cast(progress), cb->gameState()->map->obeliskCount); throw std::runtime_error("Player visited more obelisks than present on map!"); } diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index 320c4da26..1a319a704 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -389,13 +389,9 @@ 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 - void onHeroVisit(const CGHeroInstance * h) const override; void initObj(CRandomGenerator & rand) override; std::string getHoverText(PlayerColor player) const override; - static void reset(); template void serialize(Handler &h, const int version) { diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 98efe7563..9ea49db26 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -12,6 +12,7 @@ #include "CDrawRoadsOperation.h" #include "CMap.h" +#include "../CRandomGenerator.h" #include "../RoadHandler.h" #include "../RiverHandler.h" diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 804514510..01a0478f7 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -19,6 +19,8 @@ #include "../RoadHandler.h" #include "../TerrainHandler.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CGTownInstance.h" +#include "../mapObjects/CQuest.h" #include "../mapObjects/ObjectTemplate.h" #include "../CGeneralTextHandler.h" #include "../spells/CSpellHandler.h" @@ -676,8 +678,10 @@ CMapEditManager * CMap::getEditManager() void CMap::resetStaticData() { - CGObelisk::reset(); - CGTownInstance::reset(); + obeliskCount = 0; + obelisksVisited.clear(); + townMerchantArtifacts.clear(); + townUniversitySkills.clear(); } VCMI_LIB_NAMESPACE_END diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index 97a45f7a4..ca879f037 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -10,13 +10,13 @@ #pragma once +#include "CMapDefines.h" #include "CMapHeader.h" + +#include "../ConstTransitivePtr.h" #include "../GameCallbackHolder.h" #include "../MetaString.h" -#include "../mapObjects/MiscObjects.h" // To serialize static props -#include "../mapObjects/CQuest.h" // To serialize static props -#include "../mapObjects/CGTownInstance.h" // To serialize static props -#include "CMapDefines.h" +#include "../networkPacks/TradeItem.h" VCMI_LIB_NAMESPACE_BEGIN @@ -159,6 +159,12 @@ public: bool waterMap; + ui8 obeliskCount = 0; //how many obelisks are on map + std::map obelisksVisited; //map: team_id => how many obelisks has been visited + + std::vector townMerchantArtifacts; + std::vector townUniversitySkills; + private: /// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground boost::multi_array terrain; @@ -193,10 +199,10 @@ public: h & artInstances; // static members - h & CGObelisk::obeliskCount; - h & CGObelisk::visited; - h & CGTownInstance::merchantArtifacts; - h & CGTownInstance::universitySkills; + h & obeliskCount; + h & obelisksVisited; + h & townMerchantArtifacts; + h & townUniversitySkills; h & instanceNames; } diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index a8e26868b..072fbf2ce 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -12,7 +12,9 @@ #include "CMapOperation.h" #include "../VCMI_Lib.h" +#include "../CRandomGenerator.h" #include "../TerrainHandler.h" +#include "../mapObjects/CGObjectInstance.h" #include "CMap.h" #include "MapEditUtils.h" @@ -510,9 +512,8 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const { if(map->isInTheMap(pos)) { - const auto & ptrConfig = VLC->terviewh; const auto * terType = map->getTile(pos).terType; - auto valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById("n1")).result; + auto valid = validateTerrainView(pos, VLC->terviewh->getTerrainTypePatternById("n1")).result; // Special validity check for rock & water if(valid && (terType->isWater() || !terType->isPassable())) @@ -520,7 +521,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const static const std::string patternIds[] = { "s1", "s2" }; for(const auto & patternId : patternIds) { - valid = !validateTerrainView(pos, ptrConfig->getTerrainTypePatternById(patternId)).result; + valid = !validateTerrainView(pos, VLC->terviewh->getTerrainTypePatternById(patternId)).result; if(!valid) break; } } @@ -530,7 +531,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const static const std::string patternIds[] = { "n2", "n3" }; for(const auto & patternId : patternIds) { - valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById(patternId)).result; + valid = validateTerrainView(pos, VLC->terviewh->getTerrainTypePatternById(patternId)).result; if(valid) break; } } diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 5a72b0a10..9e05f940a 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -28,6 +28,7 @@ #include "../mapObjects/ObjectTemplate.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGTownInstance.h" +#include "../mapObjects/MiscObjects.h" #include "../modding/ModScope.h" #include "../modding/ModUtility.h" #include "../spells/CSpellHandler.h" diff --git a/lib/mapping/ObstacleProxy.cpp b/lib/mapping/ObstacleProxy.cpp index a15b95a9f..ed6caa4c0 100644 --- a/lib/mapping/ObstacleProxy.cpp +++ b/lib/mapping/ObstacleProxy.cpp @@ -13,6 +13,7 @@ #include "../mapping/CMap.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" +#include "../mapObjects/CGObjectInstance.h" #include "../mapObjects/ObjectTemplate.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index ae54e20d9..b998c416a 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -34,6 +34,9 @@ #include "TerrainHandler.h" #include "mapObjects/CGCreature.h" #include "mapObjects/CGMarket.h" +#include "mapObjects/CGTownInstance.h" +#include "mapObjects/CQuest.h" +#include "mapObjects/MiscObjects.h" #include "mapObjectConstructors/AObjectTypeHandler.h" #include "mapObjectConstructors/CObjectClassesHandler.h" #include "campaign/CampaignState.h" @@ -1990,7 +1993,7 @@ void SetAvailableArtifacts::applyGs(CGameState * gs) const } else { - CGTownInstance::merchantArtifacts = arts; + gs->map->townMerchantArtifacts = arts; } } diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index 28d510ee9..40fa2f650 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -19,6 +19,8 @@ #include "../CPlayerState.h" #include "../TerrainHandler.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CGTownInstance.h" +#include "../mapObjects/MiscObjects.h" #include "../mapping/CMap.h" #include "spells/CSpellHandler.h" diff --git a/lib/pathfinder/NodeStorage.cpp b/lib/pathfinder/NodeStorage.cpp index 07d283d19..c24c10f1a 100644 --- a/lib/pathfinder/NodeStorage.cpp +++ b/lib/pathfinder/NodeStorage.cpp @@ -16,6 +16,7 @@ #include "../CPlayerState.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/MiscObjects.h" #include "../mapping/CMap.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index cd0a6a4ce..807090d78 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -17,6 +17,7 @@ #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapping/CMapEditManager.h" +#include "../CArtHandler.h" #include "../CTownHandler.h" #include "../CHeroHandler.h" #include "../constants/StringConstants.h" diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index 81e92ecbf..44e372dbe 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -9,9 +9,10 @@ */ #include "StdInc.h" -#include -#include "../CRandomGenerator.h" #include "CZonePlacer.h" + +#include "../CRandomGenerator.h" +#include "../CTownHandler.h" #include "../TerrainHandler.h" #include "../mapping/CMap.h" #include "../mapping/CMapEditManager.h" diff --git a/lib/rmg/RmgMap.h b/lib/rmg/RmgMap.h index a1e5a5e10..26079a9c1 100644 --- a/lib/rmg/RmgMap.h +++ b/lib/rmg/RmgMap.h @@ -17,6 +17,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CMap; class CMapEditManager; +class CRandomGenerator; class TileInfo; class CMapGenOptions; class Zone; diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index fcc593801..8fc118abd 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -17,6 +17,7 @@ #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjects/ObjectTemplate.h" +#include "../mapObjects/CGObjectInstance.h" #include "Functions.h" #include "../TerrainHandler.h" diff --git a/lib/rmg/modificators/MinePlacer.cpp b/lib/rmg/modificators/MinePlacer.cpp index 88ee45629..b0dc77a9e 100644 --- a/lib/rmg/modificators/MinePlacer.cpp +++ b/lib/rmg/modificators/MinePlacer.cpp @@ -12,6 +12,7 @@ #include "../RmgMap.h" #include "../../mapObjectConstructors/AObjectTypeHandler.h" #include "../../mapObjectConstructors/CObjectClassesHandler.h" +#include "../../mapObjects/MiscObjects.h" #include "../../mapping/CMapEditManager.h" #include "../RmgPath.h" #include "../RmgObject.h" diff --git a/lib/rmg/modificators/ObstaclePlacer.cpp b/lib/rmg/modificators/ObstaclePlacer.cpp index 8c7e41f87..49be0fa59 100644 --- a/lib/rmg/modificators/ObstaclePlacer.cpp +++ b/lib/rmg/modificators/ObstaclePlacer.cpp @@ -24,6 +24,7 @@ #include "../../mapping/CMapEditManager.h" #include "../../mapping/CMap.h" #include "../../mapping/ObstacleProxy.h" +#include "../../mapObjects/CGObjectInstance.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/rmg/modificators/RoadPlacer.cpp b/lib/rmg/modificators/RoadPlacer.cpp index fcd2fe053..4c2b2fd41 100644 --- a/lib/rmg/modificators/RoadPlacer.cpp +++ b/lib/rmg/modificators/RoadPlacer.cpp @@ -17,6 +17,7 @@ #include "../CMapGenerator.h" #include "../threadpool/MapProxy.h" #include "../../mapping/CMapEditManager.h" +#include "../../mapObjects/CGObjectInstance.h" #include "../../modding/IdentifierStorage.h" #include "../../modding/ModScope.h" #include "../../TerrainHandler.h" diff --git a/lib/rmg/modificators/TerrainPainter.cpp b/lib/rmg/modificators/TerrainPainter.cpp index 2a795244c..5651ff8c0 100644 --- a/lib/rmg/modificators/TerrainPainter.cpp +++ b/lib/rmg/modificators/TerrainPainter.cpp @@ -20,6 +20,7 @@ #include "../RmgMap.h" #include "../../VCMI_Lib.h" #include "../../TerrainHandler.h" +#include "../../CTownHandler.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/rmg/modificators/TownPlacer.cpp b/lib/rmg/modificators/TownPlacer.cpp index ca3542e48..743ddfdf8 100644 --- a/lib/rmg/modificators/TownPlacer.cpp +++ b/lib/rmg/modificators/TownPlacer.cpp @@ -14,6 +14,7 @@ #include "../RmgMap.h" #include "../../mapObjectConstructors/AObjectTypeHandler.h" #include "../../mapObjectConstructors/CObjectClassesHandler.h" +#include "../../mapObjects/CGTownInstance.h" #include "../../mapping/CMap.h" #include "../../mapping/CMapEditManager.h" #include "../../spells/CSpellHandler.h" //for choosing random spells diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index aeedeb1e8..95f2dd151 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -26,6 +26,8 @@ #include "../../mapObjectConstructors/DwellingInstanceConstructor.h" #include "../../mapObjects/CGHeroInstance.h" #include "../../mapObjects/CGPandoraBox.h" +#include "../../mapObjects/CQuest.h" +#include "../../mapObjects/MiscObjects.h" #include "../../CCreatureHandler.h" #include "../../spells/CSpellHandler.h" //for choosing random spells #include "../../mapping/CMap.h" @@ -110,7 +112,7 @@ void TreasurePlacer::addAllPossibleObjects() //prisons //levels 1, 5, 10, 20, 30 - static int prisonsLevels = std::min(generator.getConfig().prisonExperience.size(), generator.getConfig().prisonValues.size()); + static const int prisonsLevels = std::min(generator.getConfig().prisonExperience.size(), generator.getConfig().prisonValues.size()); size_t prisonsLeft = getMaxPrisons(); for (int i = prisonsLevels - 1; i >= 0; i--) @@ -178,7 +180,7 @@ void TreasurePlacer::addAllPossibleObjects() if(dwellingType == Obj::CREATURE_GENERATOR1) { //don't spawn original "neutral" dwellings that got replaced by Conflux dwellings in AB - static MapObjectSubID elementalConfluxROE[] = {7, 13, 16, 47}; + static const MapObjectSubID elementalConfluxROE[] = {7, 13, 16, 47}; for(auto const & i : elementalConfluxROE) vstd::erase_if_present(subObjects, i); } @@ -516,7 +518,7 @@ void TreasurePlacer::addAllPossibleObjects() } } - static int seerLevels = std::min(generator.getConfig().questValues.size(), generator.getConfig().questRewardValues.size()); + static const int seerLevels = std::min(generator.getConfig().questValues.size(), generator.getConfig().questRewardValues.size()); for(int i = 0; i < seerLevels; i++) //seems that code for exp and gold reward is similiar { int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType()); @@ -819,7 +821,7 @@ void TreasurePlacer::createTreasures(ObjectManager& manager) int mapMonsterStrength = map.getMapGenOptions().getMonsterStrength(); int monsterStrength = (zone.monsterStrength == EMonsterStrength::ZONE_NONE ? 0 : zone.monsterStrength + mapMonsterStrength - 1); //array index from 0 to 4; pick any correct value for ZONE_NONE, minGuardedValue won't be used in this case anyway - static int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 }; + static const int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 }; minGuardedValue = minGuardedValues[monsterStrength]; auto valueComparator = [](const CTreasureInfo& lhs, const CTreasureInfo& rhs) -> bool diff --git a/lib/rmg/modificators/WaterProxy.cpp b/lib/rmg/modificators/WaterProxy.cpp index 1c0a0ceec..551b00860 100644 --- a/lib/rmg/modificators/WaterProxy.cpp +++ b/lib/rmg/modificators/WaterProxy.cpp @@ -15,6 +15,7 @@ #include "../../TerrainHandler.h" #include "../../mapObjectConstructors/AObjectTypeHandler.h" #include "../../mapObjectConstructors/CObjectClassesHandler.h" +#include "../../mapObjects/MiscObjects.h" #include "../../mapping/CMap.h" #include "../../mapping/CMapEditManager.h" #include "../RmgPath.h" diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index 88ab64a94..72d54ecd3 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -14,6 +14,7 @@ #include "../mapping/CMap.h" #include "../CHeroHandler.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CQuest.h" VCMI_LIB_NAMESPACE_BEGIN @@ -24,8 +25,14 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) { registerVectoredType(&gs->map->objects, [](const CGObjectInstance &obj){ return obj.id; }); + registerVectoredType(&lib->heroh->objects, + [](const CHero &h){ return h.getId(); }); registerVectoredType(&gs->map->allHeroes, [](const CGHeroInstance &h){ return h.type->getId(); }); + registerVectoredType(&lib->creh->objects, + [](const CCreature &cre){ return cre.getId(); }); + registerVectoredType(&lib->arth->objects, + [](const CArtifact &art){ return art.getId(); }); registerVectoredType(&gs->map->artInstances, [](const CArtifactInstance &artInst){ return artInst.getId(); }); registerVectoredType(&gs->map->quests, diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index ce3b96e42..58914184c 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -65,6 +65,11 @@ class DLL_LINKAGE CSerializer return t.getNum(); } + template + void registerVectoredType(const std::vector *Vector, const std::function &idRetriever) + { + vectors[&typeid(T)] = VectorizedObjectInfo(Vector, idRetriever); + } template void registerVectoredType(const std::vector > *Vector, const std::function &idRetriever) { diff --git a/lib/spells/AdventureSpellMechanics.cpp b/lib/spells/AdventureSpellMechanics.cpp index 6e8b02233..5689e290a 100644 --- a/lib/spells/AdventureSpellMechanics.cpp +++ b/lib/spells/AdventureSpellMechanics.cpp @@ -18,6 +18,8 @@ #include "../CPlayerState.h" #include "../CRandomGenerator.h" #include "../mapObjects/CGHeroInstance.h" +#include "../mapObjects/CGTownInstance.h" +#include "../mapObjects/MiscObjects.h" #include "../mapping/CMap.h" #include "../networkPacks/PacksForClient.h" diff --git a/mapeditor/maphandler.cpp b/mapeditor/maphandler.cpp index 1db39af2f..3c11ed278 100644 --- a/mapeditor/maphandler.cpp +++ b/mapeditor/maphandler.cpp @@ -18,6 +18,7 @@ #include "../lib/mapping/CMap.h" #include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/ObjectTemplate.h" +#include "../lib/mapObjects/MiscObjects.h" #include "../lib/CHeroHandler.h" #include "../lib/CTownHandler.h" #include "../lib/GameConstants.h" diff --git a/mapeditor/mapsettings/translations.cpp b/mapeditor/mapsettings/translations.cpp index dc20d4db0..ae5476a89 100644 --- a/mapeditor/mapsettings/translations.cpp +++ b/mapeditor/mapsettings/translations.cpp @@ -13,6 +13,7 @@ #include "ui_translations.h" #include "../../lib/Languages.h" #include "../../lib/CGeneralTextHandler.h" +#include "../../lib/mapObjects/CGObjectInstance.h" #include "../../lib/VCMI_Lib.h" void Translations::cleanupRemovedItems(CMap & map) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index dc65635b2..060ffcd80 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -49,6 +49,8 @@ #include "../lib/mapping/CMap.h" #include "../lib/mapping/CMapService.h" #include "../lib/mapObjects/CGMarket.h" +#include "../lib/mapObjects/CGTownInstance.h" +#include "../lib/mapObjects/MiscObjects.h" #include "../lib/modding/ModIncompatibility.h" #include "../lib/networkPacks/StackLocation.h" #include "../lib/pathfinder/CPathfinder.h" @@ -2999,7 +3001,7 @@ bool CGameHandler::buyArtifact(const IMarket *m, const CGHeroInstance *h, GameRe if(dynamic_cast(m)) { saa.id = ObjectInstanceID::NONE; - saa.arts = CGTownInstance::merchantArtifacts; + saa.arts = gs->map->townMerchantArtifacts; } else if(const CGBlackMarket *bm = dynamic_cast(m)) //black market { From 60ffb81b33f861307da33f5cf886f028810658e7 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 9 Jan 2024 19:08:22 +0200 Subject: [PATCH 06/13] Replaced remaining placeholder code with callbacks --- AI/Nullkiller/Engine/PriorityEvaluator.cpp | 2 +- .../CBankInstanceConstructor.cpp | 10 ++--- .../CBankInstanceConstructor.h | 4 +- .../CRewardableConstructor.cpp | 2 +- lib/mapObjects/CGTownBuilding.cpp | 2 +- lib/mapping/CMapService.cpp | 5 +-- lib/mapping/ObstacleProxy.cpp | 8 ++-- lib/mapping/ObstacleProxy.h | 5 ++- lib/rewardable/Info.cpp | 39 ++++++++++--------- lib/rewardable/Info.h | 13 ++++--- lib/rmg/modificators/ObjectDistributor.cpp | 4 +- lib/rmg/modificators/ObstaclePlacer.cpp | 2 +- lib/serializer/BinaryDeserializer.h | 9 +++-- lib/serializer/Connection.cpp | 2 + 14 files changed, 55 insertions(+), 52 deletions(-) diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index be3d87845..1a081de8c 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -141,7 +141,7 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero { auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance); CBankInfo * bankInfo = dynamic_cast(objectInfo.get()); - auto creatures = bankInfo->getPossibleCreaturesReward(); + auto creatures = bankInfo->getPossibleCreaturesReward(target->cb); uint64_t result = 0; const auto& slots = hero->Slots(); diff --git a/lib/mapObjectConstructors/CBankInstanceConstructor.cpp b/lib/mapObjectConstructors/CBankInstanceConstructor.cpp index e2a4c3b03..405986c85 100644 --- a/lib/mapObjectConstructors/CBankInstanceConstructor.cpp +++ b/lib/mapObjectConstructors/CBankInstanceConstructor.cpp @@ -34,10 +34,10 @@ void CBankInstanceConstructor::initTypeData(const JsonNode & input) coastVisitable = input["coastVisitable"].Bool(); } -BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const +BankConfig CBankInstanceConstructor::generateConfig(IGameCallback * cb, const JsonNode & level, CRandomGenerator & rng) const { BankConfig bc; - JsonRandom randomizer(nullptr); + JsonRandom randomizer(cb); JsonRandom::Variables emptyVariables; bc.chance = static_cast(level["chance"].Float()); @@ -71,7 +71,7 @@ void CBankInstanceConstructor::randomizeObject(CBank * bank, CRandomGenerator & cumulativeChance += static_cast(node["chance"].Float()); if(selectedChance < cumulativeChance) { - bank->setConfig(generateConfig(node, rng)); + bank->setConfig(generateConfig(bank->cb, node, rng)); break; } } @@ -125,10 +125,10 @@ std::vector> CBankInfo::getPossibleResourcesReward() return result; } -std::vector> CBankInfo::getPossibleCreaturesReward() const +std::vector> CBankInfo::getPossibleCreaturesReward(IGameCallback * cb) const { JsonRandom::Variables emptyVariables; - JsonRandom randomizer(nullptr); + JsonRandom randomizer(cb); std::vector> aproximateReward; for(const JsonNode & configEntry : config) diff --git a/lib/mapObjectConstructors/CBankInstanceConstructor.h b/lib/mapObjectConstructors/CBankInstanceConstructor.h index a8883b2d7..a0b73ba77 100644 --- a/lib/mapObjectConstructors/CBankInstanceConstructor.h +++ b/lib/mapObjectConstructors/CBankInstanceConstructor.h @@ -57,7 +57,7 @@ public: TPossibleGuards getPossibleGuards(IGameCallback * cb) const; std::vector> getPossibleResourcesReward() const; - std::vector> getPossibleCreaturesReward() const; + std::vector> getPossibleCreaturesReward(IGameCallback * cb) const; bool givesResources() const override; bool givesArtifacts() const override; @@ -67,7 +67,7 @@ public: class CBankInstanceConstructor : public CDefaultObjectTypeHandler { - BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const; + BankConfig generateConfig(IGameCallback * cb, const JsonNode & conf, CRandomGenerator & rng) const; JsonVector levels; diff --git a/lib/mapObjectConstructors/CRewardableConstructor.cpp b/lib/mapObjectConstructors/CRewardableConstructor.cpp index 551db2330..83242529b 100644 --- a/lib/mapObjectConstructors/CRewardableConstructor.cpp +++ b/lib/mapObjectConstructors/CRewardableConstructor.cpp @@ -44,7 +44,7 @@ void CRewardableConstructor::configureObject(CGObjectInstance * object, CRandomG { if(auto * rewardableObject = dynamic_cast(object)) { - objectInfo.configureObject(rewardableObject->configuration, rng); + objectInfo.configureObject(rewardableObject->configuration, rng, object->cb); for(auto & rewardInfo : rewardableObject->configuration.info) { for (auto & bonus : rewardInfo.reward.bonuses) diff --git a/lib/mapObjects/CGTownBuilding.cpp b/lib/mapObjects/CGTownBuilding.cpp index 5bced754c..94c855448 100644 --- a/lib/mapObjects/CGTownBuilding.cpp +++ b/lib/mapObjects/CGTownBuilding.cpp @@ -322,7 +322,7 @@ void CTownRewardableBuilding::initObj(CRandomGenerator & rand) auto building = town->town->buildings.at(bID); - building->rewardableObjectInfo.configureObject(configuration, rand); + building->rewardableObjectInfo.configureObject(configuration, rand, cb); for(auto & rewardInfo : configuration.info) { for (auto & bonus : rewardInfo.reward.bonuses) diff --git a/lib/mapping/CMapService.cpp b/lib/mapping/CMapService.cpp index d5ad8b37c..7a7ecbcb3 100644 --- a/lib/mapping/CMapService.cpp +++ b/lib/mapping/CMapService.cpp @@ -176,10 +176,7 @@ static JsonNode loadPatches(const std::string & path) std::unique_ptr CMapService::getMapPatcher(std::string scenarioName) { - static JsonNode node; - - if (node.isNull()) - node = loadPatches("config/mapOverrides.json"); + static const JsonNode node = loadPatches("config/mapOverrides.json"); boost::to_lower(scenarioName); logGlobal->debug("Request to patch map %s", scenarioName); diff --git a/lib/mapping/ObstacleProxy.cpp b/lib/mapping/ObstacleProxy.cpp index ed6caa4c0..920afc4e3 100644 --- a/lib/mapping/ObstacleProxy.cpp +++ b/lib/mapping/ObstacleProxy.cpp @@ -66,7 +66,7 @@ bool ObstacleProxy::isProhibited(const rmg::Area& objArea) const return false; }; -int ObstacleProxy::getWeightedObjects(const int3 & tile, CRandomGenerator & rand, std::list & allObjects, std::vector> & weightedObjects) +int ObstacleProxy::getWeightedObjects(const int3 & tile, CRandomGenerator & rand, IGameCallback * cb, std::list & allObjects, std::vector> & weightedObjects) { int maxWeight = std::numeric_limits::min(); for(auto & possibleObstacle : possibleObstacles) @@ -147,7 +147,7 @@ int ObstacleProxy::getWeightedObjects(const int3 & tile, CRandomGenerator & rand return maxWeight; } -std::set ObstacleProxy::createObstacles(CRandomGenerator & rand) +std::set ObstacleProxy::createObstacles(CRandomGenerator & rand, IGameCallback * cb) { //reverse order, since obstacles begin in bottom-right corner, while the map coordinates begin in top-left auto blockedTiles = blockedArea.getTilesVector(); @@ -160,7 +160,7 @@ std::set ObstacleProxy::createObstacles(CRandomGenerator & ra std::list allObjects; std::vector> weightedObjects; - int maxWeight = getWeightedObjects(tile, rand, allObjects, weightedObjects); + int maxWeight = getWeightedObjects(tile, rand, cb, allObjects, weightedObjects); if(weightedObjects.empty()) { @@ -222,7 +222,7 @@ bool EditorObstaclePlacer::isInTheMap(const int3& tile) std::set EditorObstaclePlacer::placeObstacles(CRandomGenerator & rand) { - auto obstacles = createObstacles(rand); + auto obstacles = createObstacles(rand, map->cb); finalInsertion(map->getEditManager(), obstacles); return obstacles; } diff --git a/lib/mapping/ObstacleProxy.h b/lib/mapping/ObstacleProxy.h index 70f1f46df..3f6e92f09 100644 --- a/lib/mapping/ObstacleProxy.h +++ b/lib/mapping/ObstacleProxy.h @@ -19,6 +19,7 @@ class CMapEditManager; class CGObjectInstance; class ObjectTemplate; class CRandomGenerator; +class IGameCallback; class DLL_LINKAGE ObstacleProxy { @@ -41,7 +42,7 @@ public: virtual void placeObject(rmg::Object & object, std::set & instances); - virtual std::set createObstacles(CRandomGenerator & rand); + virtual std::set createObstacles(CRandomGenerator & rand, IGameCallback * cb); virtual bool isInTheMap(const int3& tile) = 0; @@ -50,7 +51,7 @@ public: virtual void postProcess(const rmg::Object& object) {}; protected: - int getWeightedObjects(const int3& tile, CRandomGenerator& rand, std::list& allObjects, std::vector>& weightedObjects); + int getWeightedObjects(const int3& tile, CRandomGenerator& rand, IGameCallback * cb, std::list& allObjects, std::vector>& weightedObjects); rmg::Area blockedArea; diff --git a/lib/rewardable/Info.cpp b/lib/rewardable/Info.cpp index c9b884fc3..f81870fef 100644 --- a/lib/rewardable/Info.cpp +++ b/lib/rewardable/Info.cpp @@ -105,14 +105,14 @@ void Rewardable::Info::init(const JsonNode & objectConfig, const std::string & o loadString(parameters["onEmptyMessage"], TextIdentifier(objectName, "onEmpty")); } -Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const +Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, const JsonNode & source) const { Rewardable::LimitersList result; for (const auto & input : source.Vector()) { auto newLimiter = std::make_shared(); - configureLimiter(object, rng, *newLimiter, input); + configureLimiter(object, rng, cb, *newLimiter, input); result.push_back(newLimiter); } @@ -120,10 +120,10 @@ Rewardable::LimitersList Rewardable::Info::configureSublimiters(Rewardable::Conf return result; } -void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const +void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const { auto const & variables = object.variables.values; - JsonRandom randomizer(nullptr); + JsonRandom randomizer(cb); limiter.dayOfWeek = randomizer.loadValue(source["dayOfWeek"], rng, variables); limiter.daysPassed = randomizer.loadValue(source["daysPassed"], rng, variables); @@ -147,15 +147,15 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan 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"] ); - limiter.noneOf = configureSublimiters(object, rng, source["noneOf"] ); + limiter.allOf = configureSublimiters(object, rng, cb, source["allOf"] ); + limiter.anyOf = configureSublimiters(object, rng, cb, source["anyOf"] ); + limiter.noneOf = configureSublimiters(object, rng, cb, source["noneOf"] ); } -void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Reward & reward, const JsonNode & source) const +void Rewardable::Info::configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, Rewardable::Reward & reward, const JsonNode & source) const { auto const & variables = object.variables.values; - JsonRandom randomizer(nullptr); + JsonRandom randomizer(cb); reward.resources = randomizer.loadResources(source["resources"], rng, variables); @@ -216,9 +216,9 @@ void Rewardable::Info::configureResetInfo(Rewardable::Configuration & object, CR resetParameters.rewards = source["rewards"].Bool(); } -void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const +void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, const JsonNode & source) const { - JsonRandom randomizer(nullptr); + JsonRandom randomizer(cb); for(const auto & category : source.Struct()) { @@ -277,6 +277,7 @@ void Rewardable::Info::replaceTextPlaceholders(MetaString & target, const Variab void Rewardable::Info::configureRewards( Rewardable::Configuration & object, CRandomGenerator & rng, + IGameCallback * cb, const JsonNode & source, Rewardable::EEventType event, const std::string & modeName) const @@ -319,8 +320,8 @@ void Rewardable::Info::configureRewards( } Rewardable::VisitInfo info; - configureLimiter(object, rng, info.limiter, reward["limiter"]); - configureReward(object, rng, info.reward, reward); + configureLimiter(object, rng, cb, info.limiter, reward["limiter"]); + configureReward(object, rng, cb, info.reward, reward); info.visitType = event; info.message = loadMessage(reward["message"], TextIdentifier(objectTextID, modeName, i)); @@ -333,15 +334,15 @@ void Rewardable::Info::configureRewards( } } -void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRandomGenerator & rng) const +void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb) const { object.info.clear(); - configureVariables(object, rng, parameters["variables"]); + configureVariables(object, rng, cb, parameters["variables"]); - configureRewards(object, rng, parameters["rewards"], Rewardable::EEventType::EVENT_FIRST_VISIT, "rewards"); - configureRewards(object, rng, parameters["onVisited"], Rewardable::EEventType::EVENT_ALREADY_VISITED, "onVisited"); - configureRewards(object, rng, parameters["onEmpty"], Rewardable::EEventType::EVENT_NOT_AVAILABLE, "onEmpty"); + configureRewards(object, rng, cb, parameters["rewards"], Rewardable::EEventType::EVENT_FIRST_VISIT, "rewards"); + configureRewards(object, rng, cb, parameters["onVisited"], Rewardable::EEventType::EVENT_ALREADY_VISITED, "onVisited"); + configureRewards(object, rng, cb, parameters["onEmpty"], Rewardable::EEventType::EVENT_NOT_AVAILABLE, "onEmpty"); object.onSelect = loadMessage(parameters["onSelectMessage"], TextIdentifier(objectTextID, "onSelect")); object.description = loadMessage(parameters["description"], TextIdentifier(objectTextID, "description")); @@ -405,7 +406,7 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand } if (object.visitMode == Rewardable::VISIT_LIMITER) - configureLimiter(object, rng, object.visitLimiter, parameters["visitLimiter"]); + configureLimiter(object, rng, cb, object.visitLimiter, parameters["visitLimiter"]); } diff --git a/lib/rewardable/Info.h b/lib/rewardable/Info.h index 5ad96ca40..7df4c17e9 100644 --- a/lib/rewardable/Info.h +++ b/lib/rewardable/Info.h @@ -17,6 +17,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CRandomGenerator; class MetaString; +class IGameCallback; namespace Rewardable { @@ -38,13 +39,13 @@ class DLL_LINKAGE Info : public IObjectInfo void replaceTextPlaceholders(MetaString & target, const Variables & variables) const; void replaceTextPlaceholders(MetaString & target, const Variables & variables, const VisitInfo & info) const; - void configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const; - void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source, Rewardable::EEventType mode, const std::string & textPrefix) const; + void configureVariables(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, const JsonNode & source) const; + void configureRewards(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, const JsonNode & source, Rewardable::EEventType mode, const std::string & textPrefix) const; - void configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Limiter & limiter, const JsonNode & source) const; - Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, const JsonNode & source) const; + void configureLimiter(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, Rewardable::Limiter & limiter, const JsonNode & source) const; + Rewardable::LimitersList configureSublimiters(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, const JsonNode & source) const; - void configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::Reward & info, const JsonNode & source) const; + void configureReward(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb, Rewardable::Reward & info, const JsonNode & source) const; void configureResetInfo(Rewardable::Configuration & object, CRandomGenerator & rng, Rewardable::ResetInfo & info, const JsonNode & source) const; public: const JsonNode & getParameters() const; @@ -64,7 +65,7 @@ public: bool givesBonuses() const override; - void configureObject(Rewardable::Configuration & object, CRandomGenerator & rng) const; + void configureObject(Rewardable::Configuration & object, CRandomGenerator & rng, IGameCallback * cb) const; void init(const JsonNode & objectConfig, const std::string & objectTextID); diff --git a/lib/rmg/modificators/ObjectDistributor.cpp b/lib/rmg/modificators/ObjectDistributor.cpp index 4f08fc8b9..76a0ac0a6 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 = [this, primaryID, secondaryID]() -> CGObjectInstance * + oi.generateObject = [cb=map.mapInstance->cb, primaryID, secondaryID]() -> CGObjectInstance * { - return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(map.mapInstance->cb, nullptr); + return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(cb, nullptr); }; oi.value = rmgInfo.value; diff --git a/lib/rmg/modificators/ObstaclePlacer.cpp b/lib/rmg/modificators/ObstaclePlacer.cpp index 49be0fa59..ecab26e77 100644 --- a/lib/rmg/modificators/ObstaclePlacer.cpp +++ b/lib/rmg/modificators/ObstaclePlacer.cpp @@ -87,7 +87,7 @@ void ObstaclePlacer::process() prohibitedArea.unite(zone.areaPossible()); } - auto objs = createObstacles(zone.getRand()); + auto objs = createObstacles(zone.getRand(), map.mapInstance->cb); mapProxy->insertObjects(objs); } diff --git a/lib/serializer/BinaryDeserializer.h b/lib/serializer/BinaryDeserializer.h index c503da472..85c32c21b 100644 --- a/lib/serializer/BinaryDeserializer.h +++ b/lib/serializer/BinaryDeserializer.h @@ -114,7 +114,7 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase class IPointerLoader { public: - virtual void * loadPtr(CLoaderBase &ar, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER + virtual void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const =0; //data is pointer to the ACTUAL POINTER virtual ~IPointerLoader() = default; template static IPointerLoader *getApplier(const Type * t = nullptr) @@ -127,12 +127,12 @@ class DLL_LINKAGE BinaryDeserializer : public CLoaderBase class CPointerLoader : public IPointerLoader { public: - void * loadPtr(CLoaderBase &ar, ui32 pid) const override //data is pointer to the ACTUAL POINTER + void * loadPtr(CLoaderBase &ar, IGameCallback * cb, ui32 pid) const override //data is pointer to the ACTUAL POINTER { auto & s = static_cast(ar); //create new object under pointer - Type * ptr = ClassObjectCreator::invoke(nullptr); //does new npT or throws for abstract classes + Type * ptr = ClassObjectCreator::invoke(cb); //does new npT or throws for abstract classes s.ptrAllocated(ptr, pid); assert(s.fileVersion != 0); @@ -152,6 +152,7 @@ public: std::map loadedPointers; std::map> loadedSharedPointers; + IGameCallback * cb; bool smartPointerSerialization; bool saving; @@ -305,7 +306,7 @@ public: data = nullptr; return; } - data = static_cast(app->loadPtr(*this, pid)); + data = static_cast(app->loadPtr(*this, cb, pid)); } } diff --git a/lib/serializer/Connection.cpp b/lib/serializer/Connection.cpp index ed0625296..cda305ff7 100644 --- a/lib/serializer/Connection.cpp +++ b/lib/serializer/Connection.cpp @@ -11,6 +11,7 @@ #include "Connection.h" #include "../networkPacks/NetPacksBase.h" +#include "../gameState/CGameState.h" #include @@ -342,6 +343,7 @@ void CConnection::enterGameplayConnectionMode(CGameState * gs) enableStackSendingByID(); disableSmartPointerSerialization(); addStdVecItems(gs); + iser.cb = gs->callback; } void CConnection::disableSmartVectorMemberSerialization() From ea1f05d15ae0da04d369f6157f2679ba9f006ea1 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 10 Jan 2024 19:43:34 +0200 Subject: [PATCH 07/13] Stabilization --- AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp | 2 +- client/CServerHandler.cpp | 10 ++++++++-- client/CServerHandler.h | 7 ++++++- client/Client.cpp | 3 ++- lib/GameCallbackHolder.h | 4 +++- lib/bonuses/CBonusSystemNode.cpp | 6 +++--- lib/bonuses/CBonusSystemNode.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 1 + lib/serializer/BinaryDeserializer.h | 4 ++-- mapeditor/graphics.h | 2 +- 10 files changed, 28 insertions(+), 13 deletions(-) diff --git a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp index cf61d56e4..162d02187 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(nullptr); + auto townHero = new CGHeroInstance(town->cb); CRandomGenerator rng; auto visitablePos = town->visitablePos(); diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index a26d4aac7..6326e7786 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -142,6 +142,8 @@ CServerHandler::CServerHandler() registerTypesLobbyPacks(*applier); } +CServerHandler::~CServerHandler() = default; + void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector * names) { hostClientId = -1; @@ -260,6 +262,9 @@ void CServerHandler::justConnectToServer(const std::string & addr, const ui16 po addr.size() ? addr : getHostAddress(), port ? port : getHostPort(), NAME, uuid); + + nextClient = std::make_unique(); + c->iser.cb = nextClient.get(); } catch(std::runtime_error & error) { @@ -636,7 +641,8 @@ void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameSta { if(CMM) CMM->disable(); - client = new CClient(); + + std::swap(client, nextClient);; highScoreCalc = nullptr; @@ -687,7 +693,7 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart) } client->endGame(); - vstd::clear_pointer(client); + client.reset(); if(!restart) { diff --git a/client/CServerHandler.h b/client/CServerHandler.h index e4a5d02ca..4db794ede 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -95,6 +95,10 @@ class CServerHandler : public IServerAPI, public LobbyInfo std::shared_ptr highScoreCalc; + /// temporary helper member that exists while game in lobby mode + /// required to correctly deserialize gamestate using client-side game callback + std::unique_ptr nextClient; + void threadHandleConnection(); void threadRunServer(); void onServerFinished(); @@ -116,13 +120,14 @@ public: std::shared_ptr threadRunLocalServer; std::shared_ptr c; - CClient * client; + std::unique_ptr client; CondSh campaignServerRestartLock; static const std::string localhostAddress; CServerHandler(); + ~CServerHandler(); std::string getHostAddress() const; ui16 getHostPort() const; diff --git a/client/Client.cpp b/client/Client.cpp index e78f96c03..f1edcf38d 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -173,7 +173,8 @@ void CClient::newGame(CGameState * initializedGameState) { CSH->th->update(); CMapService mapService; - gs = initializedGameState ? initializedGameState : new CGameState(); + assert(initializedGameState); + gs = initializedGameState; gs->preInit(VLC, this); logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); if(!initializedGameState) diff --git a/lib/GameCallbackHolder.h b/lib/GameCallbackHolder.h index 1fb5312f2..8888d3105 100644 --- a/lib/GameCallbackHolder.h +++ b/lib/GameCallbackHolder.h @@ -18,7 +18,9 @@ class DLL_LINKAGE GameCallbackHolder public: IGameCallback * const cb; - GameCallbackHolder(IGameCallback *cb): + explicit GameCallbackHolder(IGameCallback *cb): cb(cb) {} }; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index 82f792849..e8760f9c0 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -304,7 +304,7 @@ void CBonusSystemNode::detachFromSource(const CBonusSystemNode & parent) parent.removedRedDescendant(*this); } - if (vstd::contains(parentsToPropagate, &parent)) + if (vstd::contains(parentsToInherit, &parent)) { parentsToInherit -= &parent; } @@ -581,9 +581,9 @@ CBonusSystemNode::ENodeTypes CBonusSystemNode::getNodeType() const return nodeType; } -const TNodesVector& CBonusSystemNode::getParentNodes() const +const TCNodesVector& CBonusSystemNode::getParentNodes() const { - return parentsToPropagate; + return parentsToInherit; } void CBonusSystemNode::setNodeType(CBonusSystemNode::ENodeTypes type) diff --git a/lib/bonuses/CBonusSystemNode.h b/lib/bonuses/CBonusSystemNode.h index afc4dec5d..f8a529d65 100644 --- a/lib/bonuses/CBonusSystemNode.h +++ b/lib/bonuses/CBonusSystemNode.h @@ -117,7 +117,7 @@ public: const BonusList & getExportedBonusList() const; CBonusSystemNode::ENodeTypes getNodeType() const; void setNodeType(CBonusSystemNode::ENodeTypes type); - const TNodesVector & getParentNodes() const; + const TCNodesVector & getParentNodes() const; static void treeHasChanged(); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 6c4c07821..11b945659 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -277,6 +277,7 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) CGHeroInstance::CGHeroInstance(IGameCallback * cb) : CArmedInstance(cb), + type(nullptr), tacticFormationEnabled(false), inTownGarrison(false), moveDir(4), diff --git a/lib/serializer/BinaryDeserializer.h b/lib/serializer/BinaryDeserializer.h index 85c32c21b..911a04b05 100644 --- a/lib/serializer/BinaryDeserializer.h +++ b/lib/serializer/BinaryDeserializer.h @@ -152,7 +152,7 @@ public: std::map loadedPointers; std::map> loadedSharedPointers; - IGameCallback * cb; + IGameCallback * cb = nullptr; bool smartPointerSerialization; bool saving; @@ -293,7 +293,7 @@ public: { typedef typename std::remove_pointer::type npT; typedef typename std::remove_const::type ncpT; - data = ClassObjectCreator::invoke(nullptr); + data = ClassObjectCreator::invoke(cb); ptrAllocated(data, pid); load(*data); } diff --git a/mapeditor/graphics.h b/mapeditor/graphics.h index 009cf4399..1e568ff0e 100644 --- a/mapeditor/graphics.h +++ b/mapeditor/graphics.h @@ -22,10 +22,10 @@ class CGObjectInstance; class EntityService; class JsonNode; class ObjectTemplate; +class CHeroClass; VCMI_LIB_NAMESPACE_END -class CHeroClass; struct InfoAboutHero; struct InfoAboutTown; class Animation; From 9af7c63a262b20461f80a2e6225046f7e3cbde9d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 10 Jan 2024 21:30:12 +0200 Subject: [PATCH 08/13] Fix build --- client/CServerHandler.cpp | 2 +- lib/CHeroHandler.cpp | 15 ++++++++------- lib/VCMI_Lib.cpp | 2 +- lib/VCMI_Lib.h | 2 +- lib/battle/BattleInfo.cpp | 2 +- .../DwellingInstanceConstructor.h | 1 + .../HillFortInstanceConstructor.h | 1 + .../ShipyardInstanceConstructor.h | 1 + lib/modding/ContentTypeHandler.cpp | 2 +- test/game/CGameStateTest.cpp | 5 +---- test/map/CMapEditManagerTest.cpp | 6 +++--- test/map/CMapFormatTest.cpp | 6 +++--- test/map/MapComparer.cpp | 1 + test/mock/mock_MapService.cpp | 6 +++--- test/mock/mock_MapService.h | 4 ++-- test/mock/mock_spells_Mechanics.h | 1 + test/scripting/ScriptFixture.cpp | 2 +- test/spells/effects/CatapultTest.cpp | 8 ++++---- 18 files changed, 35 insertions(+), 32 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 6326e7786..302bd9f7e 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -642,7 +642,7 @@ void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameSta if(CMM) CMM->disable(); - std::swap(client, nextClient);; + std::swap(client, nextClient); highScoreCalc = nullptr; diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 3d1ce3482..0fc7b587d 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -157,8 +157,9 @@ bool CHeroClass::isMagicHero() const int CHeroClass::tavernProbability(FactionID faction) const { - if (selectionProbability.count(faction)) - return selectionProbability.at(faction); + auto it = selectionProbability.find(faction); + if (it != selectionProbability.end()) + return it->second; return 0; } @@ -401,9 +402,9 @@ void CHeroClassHandler::afterLoadFinalization() } } - for(auto const & hc : objects) + for(const auto & hc : objects) { - if (!hc->imageMapMale.empty()) + if(!hc->imageMapMale.empty()) { JsonNode templ; templ["animation"].String() = hc->imageMapMale; @@ -539,7 +540,7 @@ static std::vector> createCreatureSpecialty(CreatureID ba { std::set oldTargets = targets; - for (auto const & upgradeSourceID : oldTargets) + for(const auto & upgradeSourceID : oldTargets) { const CCreature * upgradeSource = upgradeSourceID.toCreature(); targets.insert(upgradeSource->upgrades.begin(), upgradeSource->upgrades.end()); @@ -551,7 +552,7 @@ static std::vector> createCreatureSpecialty(CreatureID ba for(CreatureID cid : targets) { - auto const & specCreature = *cid.toCreature(); + const auto & specCreature = *cid.toCreature(); int stepSize = specCreature.getLevel() ? specCreature.getLevel() : 5; { @@ -611,7 +612,7 @@ void CHeroHandler::beforeValidate(JsonNode & object) void CHeroHandler::afterLoadFinalization() { - for (auto const & functor : callAfterLoadFinalization) + for(const auto & functor : callAfterLoadFinalization) functor(); callAfterLoadFinalization.clear(); diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 45edced97..f1b0a3cfd 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -91,7 +91,7 @@ const HeroTypeService * LibClasses::heroTypes() const #if SCRIPTING_ENABLED const scripting::Service * LibClasses::scripts() const { - return scriptHandler; + return scriptHandler.get(); } #endif diff --git a/lib/VCMI_Lib.h b/lib/VCMI_Lib.h index 85bfce994..10cdaecba 100644 --- a/lib/VCMI_Lib.h +++ b/lib/VCMI_Lib.h @@ -101,7 +101,7 @@ public: std::shared_ptr settingsHandler; #if SCRIPTING_ENABLED - scripting::ScriptHandler * scriptHandler; + std::shared_ptr scriptHandler; #endif LibClasses(); //c-tor, loads .lods and NULLs handlers diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index d25b81d28..cebbaeeeb 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -1009,7 +1009,7 @@ scripting::Pool * BattleInfo::getContextPool() const { //this is real battle, use global scripting context pool //TODO: make this line not ugly - return IObjectInterface::cb->getGlobalContextPool(); + return battleGetFightingHero(0)->cb->getGlobalContextPool(); } #endif diff --git a/lib/mapObjectConstructors/DwellingInstanceConstructor.h b/lib/mapObjectConstructors/DwellingInstanceConstructor.h index ee06219be..78d32f60a 100644 --- a/lib/mapObjectConstructors/DwellingInstanceConstructor.h +++ b/lib/mapObjectConstructors/DwellingInstanceConstructor.h @@ -10,6 +10,7 @@ #pragma once #include "CDefaultObjectTypeHandler.h" +#include "../mapObjects/CGDwelling.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/mapObjectConstructors/HillFortInstanceConstructor.h b/lib/mapObjectConstructors/HillFortInstanceConstructor.h index ace75dd1d..e43ab93c5 100644 --- a/lib/mapObjectConstructors/HillFortInstanceConstructor.h +++ b/lib/mapObjectConstructors/HillFortInstanceConstructor.h @@ -10,6 +10,7 @@ #pragma once #include "CDefaultObjectTypeHandler.h" +#include "../mapObjects/MiscObjects.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/mapObjectConstructors/ShipyardInstanceConstructor.h b/lib/mapObjectConstructors/ShipyardInstanceConstructor.h index 845bf77b0..334031cd1 100644 --- a/lib/mapObjectConstructors/ShipyardInstanceConstructor.h +++ b/lib/mapObjectConstructors/ShipyardInstanceConstructor.h @@ -10,6 +10,7 @@ #pragma once #include "CDefaultObjectTypeHandler.h" +#include "../mapObjects/MiscObjects.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp index 4323bddc0..c255ebc07 100644 --- a/lib/modding/ContentTypeHandler.cpp +++ b/lib/modding/ContentTypeHandler.cpp @@ -199,7 +199,7 @@ void CContentHandler::init() handlers.insert(std::make_pair("skills", ContentTypeHandler(VLC->skillh.get(), "skill"))); handlers.insert(std::make_pair("templates", ContentTypeHandler(VLC->tplh.get(), "template"))); #if SCRIPTING_ENABLED - handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler, "script"))); + handlers.insert(std::make_pair("scripts", ContentTypeHandler(VLC->scriptHandler.get(), "script"))); #endif handlers.insert(std::make_pair("battlefields", ContentTypeHandler(VLC->battlefieldsHandler.get(), "battlefield"))); handlers.insert(std::make_pair("terrains", ContentTypeHandler(VLC->terrainTypeHandler.get(), "terrain"))); diff --git a/test/game/CGameStateTest.cpp b/test/game/CGameStateTest.cpp index 1edf8c5cb..921f76108 100644 --- a/test/game/CGameStateTest.cpp +++ b/test/game/CGameStateTest.cpp @@ -46,17 +46,14 @@ public: void SetUp() override { - IObjectInterface::cb = gameCallback.get(); - gameState = std::make_shared(); gameCallback->setGameState(gameState.get()); - gameState->preInit(&services); + gameState->preInit(&services, gameCallback.get()); } void TearDown() override { gameState.reset(); - IObjectInterface::cb = nullptr; } bool describeChanges() const override diff --git a/test/map/CMapEditManagerTest.cpp b/test/map/CMapEditManagerTest.cpp index b8ae125ca..f25a0434b 100644 --- a/test/map/CMapEditManagerTest.cpp +++ b/test/map/CMapEditManagerTest.cpp @@ -25,7 +25,7 @@ TEST(MapManager, DrawTerrain_Type) { try { - auto map = std::make_unique(); + auto map = std::make_unique(nullptr); map->width = 52; map->height = 52; map->initTerrain(); @@ -114,8 +114,8 @@ TEST(MapManager, DrawTerrain_View) const ResourcePath testMap("test/TerrainViewTest", EResType::MAP); // Load maps and json config CMapService mapService; - const auto originalMap = mapService.loadMap(testMap); - auto map = mapService.loadMap(testMap); + const auto originalMap = mapService.loadMap(testMap, nullptr); + auto map = mapService.loadMap(testMap, nullptr); // Validate edit manager auto editManager = map->getEditManager(); diff --git a/test/map/CMapFormatTest.cpp b/test/map/CMapFormatTest.cpp index 2e0dd623a..cf20dfed1 100644 --- a/test/map/CMapFormatTest.cpp +++ b/test/map/CMapFormatTest.cpp @@ -62,7 +62,7 @@ TEST(MapFormat, DISABLED_Random) opt.setPlayerTypeForStandardPlayer(PlayerColor(2), EPlayerType::AI); opt.setPlayerTypeForStandardPlayer(PlayerColor(3), EPlayerType::AI); - CMapGenerator gen(opt, TEST_RANDOM_SEED); + CMapGenerator gen(opt, nullptr, TEST_RANDOM_SEED); std::unique_ptr initialMap = gen.generate(); initialMap->name.appendRawString("Test"); @@ -80,7 +80,7 @@ TEST(MapFormat, DISABLED_Random) serializeBuffer.seek(0); { CMapLoaderJson loader(&serializeBuffer); - std::unique_ptr serialized = loader.loadMap(); + std::unique_ptr serialized = loader.loadMap(nullptr); MapComparer c; c(serialized, initialMap); @@ -130,7 +130,7 @@ static std::unique_ptr loadOriginal(const JsonNode & header, const JsonNod CMapLoaderJson initialLoader(&initialBuffer); - return initialLoader.loadMap(); + return initialLoader.loadMap(nullptr); } static void loadActual(CMemoryBuffer * serializeBuffer, const std::unique_ptr & originalMap, JsonNode & header, JsonNode & objects, JsonNode & surface, JsonNode & underground) diff --git a/test/map/MapComparer.cpp b/test/map/MapComparer.cpp index 62ffcabfb..28ace85c2 100644 --- a/test/map/MapComparer.cpp +++ b/test/map/MapComparer.cpp @@ -12,6 +12,7 @@ #include "MapComparer.h" #include "../lib/mapping/CMap.h" +#include "../lib/mapObjects/CGObjectInstance.h" #include "../lib/mapObjects/ObjectTemplate.h" #define VCMI_CHECK_FIELD_EQUAL_P(field) EXPECT_EQ(actual->field, expected->field) diff --git a/test/mock/mock_MapService.cpp b/test/mock/mock_MapService.cpp index d9883c9d6..6b44d634a 100644 --- a/test/mock/mock_MapService.cpp +++ b/test/mock/mock_MapService.cpp @@ -45,7 +45,7 @@ std::unique_ptr MapServiceMock::loadMap() const initialBuffer.seek(0); CMapLoaderJson initialLoader(&initialBuffer); - std::unique_ptr res = initialLoader.loadMap(); + std::unique_ptr res = initialLoader.loadMap(nullptr); if(mapListener) mapListener->mapLoaded(res.get()); @@ -53,7 +53,7 @@ std::unique_ptr MapServiceMock::loadMap() const return res; } -std::unique_ptr MapServiceMock::loadMap(const ResourcePath & name) const +std::unique_ptr MapServiceMock::loadMap(const ResourcePath & name, IGameCallback * cb) const { return loadMap(); } @@ -65,7 +65,7 @@ std::unique_ptr MapServiceMock::loadMapHeader(const ResourcePath & n return initialLoader.loadMapHeader(); } -std::unique_ptr MapServiceMock::loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const +std::unique_ptr MapServiceMock::loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const { return loadMap(); } diff --git a/test/mock/mock_MapService.h b/test/mock/mock_MapService.h index cf2da28a9..3f1413683 100644 --- a/test/mock/mock_MapService.h +++ b/test/mock/mock_MapService.h @@ -29,9 +29,9 @@ class MapServiceMock : public IMapService public: MapServiceMock(const std::string & path, MapListener * mapListener_); - 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 ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding) const override; + std::unique_ptr loadMap(const ui8 * buffer, int size, const std::string & name, const std::string & modName, const std::string & encoding, IGameCallback * cb) const override; std::unique_ptr loadMapHeader(const ui8 * 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; diff --git a/test/mock/mock_spells_Mechanics.h b/test/mock/mock_spells_Mechanics.h index 985e093f3..288c06fa4 100644 --- a/test/mock/mock_spells_Mechanics.h +++ b/test/mock/mock_spells_Mechanics.h @@ -11,6 +11,7 @@ #pragma once #include "../../lib/spells/ISpellMechanics.h" +#include "../../lib/CGameInfoCallback.h" namespace spells { diff --git a/test/scripting/ScriptFixture.cpp b/test/scripting/ScriptFixture.cpp index e350c6c61..aabcea131 100644 --- a/test/scripting/ScriptFixture.cpp +++ b/test/scripting/ScriptFixture.cpp @@ -41,7 +41,7 @@ void ScriptFixture::loadScript(const JsonNode & scriptConfig) void ScriptFixture::loadScript(ModulePtr module, const std::string & scriptSource) { - subject = std::make_shared(VLC->scriptHandler); + subject = std::make_shared(VLC->scriptHandler.get()); subject->host = module; subject->sourceText = scriptSource; diff --git a/test/spells/effects/CatapultTest.cpp b/test/spells/effects/CatapultTest.cpp index f88b582ad..690d9cb5c 100644 --- a/test/spells/effects/CatapultTest.cpp +++ b/test/spells/effects/CatapultTest.cpp @@ -50,7 +50,7 @@ TEST_F(CatapultTest, NotApplicableWithoutTown) TEST_F(CatapultTest, NotApplicableInVillage) { - auto fakeTown = std::make_shared(); + auto fakeTown = std::make_shared(nullptr); EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get())); EXPECT_CALL(mechanicsMock, adaptProblem(_, _)).WillOnce(Return(false)); @@ -62,7 +62,7 @@ TEST_F(CatapultTest, NotApplicableInVillage) TEST_F(CatapultTest, NotApplicableForDefenderIfSmart) { - auto fakeTown = std::make_shared(); + auto fakeTown = std::make_shared(nullptr); fakeTown->builtBuildings.insert(BuildingID::FORT); mechanicsMock.casterSide = BattleSide::DEFENDER; @@ -76,7 +76,7 @@ TEST_F(CatapultTest, NotApplicableForDefenderIfSmart) TEST_F(CatapultTest, DISABLED_ApplicableInTown) { - auto fakeTown = std::make_shared(); + auto fakeTown = std::make_shared(nullptr); fakeTown->builtBuildings.insert(BuildingID::FORT); EXPECT_CALL(*battleFake, getDefendedTown()).WillRepeatedly(Return(fakeTown.get())); @@ -106,7 +106,7 @@ protected: void SetUp() override { EffectFixture::setUp(); - fakeTown = std::make_shared(); + fakeTown = std::make_shared(nullptr); fakeTown->builtBuildings.insert(BuildingID::FORT); } private: From 496c13b34a0f2f7a9bb2859a4925f160a31beb66 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 16 Jan 2024 17:45:43 +0200 Subject: [PATCH 09/13] Stabilization --- client/CServerHandler.cpp | 2 ++ lib/CArtifactInstance.h | 2 +- lib/mapObjects/MiscObjects.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 302bd9f7e..4b3ef7adf 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -710,6 +710,8 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart) if(c) { + nextClient = std::make_unique(); + c->iser.cb = nextClient.get(); c->enterLobbyConnectionMode(); c->disableStackSendingByID(); } diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index 76a1c0e3c..4a252e931 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -73,7 +73,7 @@ protected: ArtifactInstanceID id; public: - const CArtifact * artType; + const CArtifact * artType = nullptr; CArtifactInstance(const CArtifact * art); CArtifactInstance(); diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index a0fac366b..778e5eb52 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -772,7 +772,7 @@ void CGArtifact::initObj(CRandomGenerator & rand) subID = 1; assert(storedArtifact->artType); - assert(storedArtifact->getParentNodes().size()); + assert(!storedArtifact->getParentNodes().empty()); //assert(storedArtifact->artType->id == subID); //this does not stop desync } From 6e629a6a5fd433290f9d9479344e359b0081f489 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 16 Jan 2024 18:14:40 +0200 Subject: [PATCH 10/13] split getBonusLocalFirst into two distinct method: - const method getFirstBonus that returns single matching bonusToString - non-const method getLocalBonus that returns bonus from current node --- client/battle/BattleInterfaceClasses.cpp | 2 +- client/battle/BattleWindow.cpp | 2 +- client/windows/CCreatureWindow.cpp | 2 +- lib/CArtifactInstance.cpp | 2 +- lib/bonuses/CBonusSystemNode.cpp | 6 +++--- lib/bonuses/CBonusSystemNode.h | 8 +++++--- lib/gameState/CGameStateCampaign.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 2 +- lib/mapObjects/MiscObjects.cpp | 2 +- lib/networkPacks/NetPacksLib.cpp | 2 +- lib/spells/ISpellMechanics.cpp | 2 +- lib/spells/effects/Timed.cpp | 6 +++--- server/CGameHandler.cpp | 2 +- server/battles/BattleActionProcessor.cpp | 6 +++--- server/battles/BattleFlowProcessor.cpp | 2 +- 15 files changed, 25 insertions(+), 23 deletions(-) diff --git a/client/battle/BattleInterfaceClasses.cpp b/client/battle/BattleInterfaceClasses.cpp index 5bf689fda..6d09150d0 100644 --- a/client/battle/BattleInterfaceClasses.cpp +++ b/client/battle/BattleInterfaceClasses.cpp @@ -530,7 +530,7 @@ void StackInfoBasicPanel::initializeData(const CStack * stack) if (hasGraphics) { //FIXME: support permanent duration - int duration = stack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; + int duration = stack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; icons.push_back(std::make_shared(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); if(settings["general"]["enableUiEnhancements"].Bool()) diff --git a/client/battle/BattleWindow.cpp b/client/battle/BattleWindow.cpp index 991f79251..85d2618d8 100644 --- a/client/battle/BattleWindow.cpp +++ b/client/battle/BattleWindow.cpp @@ -601,7 +601,7 @@ void BattleWindow::bSpellf() { //TODO: move to spell mechanics, add more information to spell cast problem //Handle Orb of Inhibition-like effects -> we want to display dialog with info, why casting is impossible - auto blockingBonus = owner.currentHero()->getBonusLocalFirst(Selector::type()(BonusType::BLOCK_ALL_MAGIC)); + auto blockingBonus = owner.currentHero()->getFirstBonus(Selector::type()(BonusType::BLOCK_ALL_MAGIC)); if (!blockingBonus) return; diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index d59c25da3..449c005bd 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -225,7 +225,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." boost::replace_first(spellText, "%s", spell->getNameTranslated()); //FIXME: support permanent duration - int duration = battleStack->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; + int duration = battleStack->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(effect)))->turnsRemain; boost::replace_first(spellText, "%d", std::to_string(duration)); spellIcons.push_back(std::make_shared(AnimationPath::builtin("SpellInt"), effect + 1, 0, firstPos.x + offset.x * printed, firstPos.y + offset.y * printed)); diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index a3efb5dfd..0451e2d2f 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -62,7 +62,7 @@ void CCombinedArtifactInstance::addPlacementMap(CArtifactSet::ArtPlacementMap & SpellID CScrollArtifactInstance::getScrollSpellID() const { auto artInst = static_cast(this); - const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); + const auto bonus = artInst->getFirstBonus(Selector::type()(BonusType::SPELL)); if(!bonus) return SpellID::NONE; return bonus->subtype.as(); diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index e8760f9c0..f8f45cbbd 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -20,7 +20,7 @@ VCMI_LIB_NAMESPACE_BEGIN std::atomic CBonusSystemNode::treeChanged(1); constexpr bool CBonusSystemNode::cachingEnabled = true; -std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) +std::shared_ptr CBonusSystemNode::getLocalBonus(const CSelector & selector) { auto ret = bonuses.getFirst(selector); if(ret) @@ -28,7 +28,7 @@ std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & se return nullptr; } -std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) const +std::shared_ptr CBonusSystemNode::getFirstBonus(const CSelector & selector) const { auto ret = bonuses.getFirst(selector); if(ret) @@ -38,7 +38,7 @@ std::shared_ptr CBonusSystemNode::getBonusLocalFirst(const CSelecto getParents(lparents); for(const CBonusSystemNode *pname : lparents) { - ret = pname->getBonusLocalFirst(selector); + ret = pname->getFirstBonus(selector); if (ret) return ret; } diff --git a/lib/bonuses/CBonusSystemNode.h b/lib/bonuses/CBonusSystemNode.h index f8a529d65..dd00b66ce 100644 --- a/lib/bonuses/CBonusSystemNode.h +++ b/lib/bonuses/CBonusSystemNode.h @@ -88,10 +88,12 @@ public: TBonusListPtr limitBonuses(const BonusList &allBonuses) const; //same as above, returns out by val for convienence TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override; void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from), - std::shared_ptr getBonusLocalFirst(const CSelector & selector) const; - //non-const interface - std::shared_ptr getBonusLocalFirst(const CSelector & selector); + /// Returns first bonus matching selector + std::shared_ptr getFirstBonus(const CSelector & selector) const; + + /// Provides write access to first bonus from this node that matches selector + std::shared_ptr getLocalBonus(const CSelector & selector); void attachTo(CBonusSystemNode & parent); void attachToSource(const CBonusSystemNode & parent); diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index ae6a5680f..8887c8212 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -91,7 +91,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(std::vectorgetBonusLocalFirst(sel)->val = cgh->type->heroClass->primarySkillInitial[g.getNum()]; + cgh->getLocalBonus(sel)->val = cgh->type->heroClass->primarySkillInitial[g.getNum()]; } } } diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 11b945659..dd4e8c974 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1412,7 +1412,7 @@ void CGHeroInstance::setPrimarySkill(PrimarySkill primarySkill, si64 value, ui8 { if(primarySkill < PrimarySkill::EXPERIENCE) { - auto skill = getBonusLocalFirst(Selector::type()(BonusType::PRIMARY_SKILL) + auto skill = getLocalBonus(Selector::type()(BonusType::PRIMARY_SKILL) .And(Selector::subtype()(BonusSubtypeID(primarySkill))) .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL))); assert(skill); diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 778e5eb52..f83fbe362 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -929,7 +929,7 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler) if(handler.saving && ID == Obj::SPELL_SCROLL) { - const std::shared_ptr b = storedArtifact->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); + const auto & b = storedArtifact->getFirstBonus(Selector::type()(BonusType::SPELL)); SpellID spellId(b->subtype.as()); handler.serializeId("spell", spellId, SpellID::NONE); diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index b998c416a..bbe706877 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -2147,7 +2147,7 @@ void BattleTriggerEffect::applyGs(CGameState * gs) const } case BonusType::POISON: { - auto b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, SpellID(SpellID::POISON)) + auto b = st->getLocalBonus(Selector::source(BonusSource::SPELL_EFFECT, SpellID(SpellID::POISON)) .And(Selector::type()(BonusType::STACK_HEALTH))); if (b) b->val = val; diff --git a/lib/spells/ISpellMechanics.cpp b/lib/spells/ISpellMechanics.cpp index 6d95d6bf1..6e260347f 100644 --- a/lib/spells/ISpellMechanics.cpp +++ b/lib/spells/ISpellMechanics.cpp @@ -475,7 +475,7 @@ bool BaseMechanics::adaptProblem(ESpellCastProblem source, Problem & target) con return adaptGenericProblem(target); //Recanter's Cloak or similar effect. Try to retrieve bonus - const auto b = hero->getBonusLocalFirst(Selector::type()(BonusType::BLOCK_MAGIC_ABOVE)); + const auto b = hero->getFirstBonus(Selector::type()(BonusType::BLOCK_MAGIC_ABOVE)); //TODO what about other values and non-artifact sources? if(b && b->val == 2 && b->source == BonusSource::ARTIFACT) { diff --git a/lib/spells/effects/Timed.cpp b/lib/spells/effects/Timed.cpp index 3bedc80ac..956fcf884 100644 --- a/lib/spells/effects/Timed.cpp +++ b/lib/spells/effects/Timed.cpp @@ -112,9 +112,9 @@ void Timed::apply(ServerCallback * server, const Mechanics * m, const EffectTarg const auto *casterHero = dynamic_cast(m->caster); if(casterHero) { - peculiarBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_PECULIAR_ENCHANT, BonusSubtypeID(m->getSpellId()))); - addedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_ADD_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId()))); - fixedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(BonusType::SPECIAL_FIXED_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId()))); + peculiarBonus = casterHero->getFirstBonus(Selector::typeSubtype(BonusType::SPECIAL_PECULIAR_ENCHANT, BonusSubtypeID(m->getSpellId()))); + addedValueBonus = casterHero->getFirstBonus(Selector::typeSubtype(BonusType::SPECIAL_ADD_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId()))); + fixedValueBonus = casterHero->getFirstBonus(Selector::typeSubtype(BonusType::SPECIAL_FIXED_VALUE_ENCHANT, BonusSubtypeID(m->getSpellId()))); } //TODO: does hero specialty should affects his stack casting spells? diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 060ffcd80..dce051289 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -886,7 +886,7 @@ void CGameHandler::onNewTurn() { if (getPlayerStatus(player.first) == EPlayerStatus::INGAME && getPlayerRelations(player.first, t->tempOwner) == PlayerRelations::ENEMIES) - changeFogOfWar(t->visitablePos(), t->getBonusLocalFirst(Selector::type()(BonusType::DARKNESS))->val, player.first, ETileVisibility::HIDDEN); + changeFogOfWar(t->visitablePos(), t->getFirstBonus(Selector::type()(BonusType::DARKNESS))->val, player.first, ETileVisibility::HIDDEN); } } } diff --git a/server/battles/BattleActionProcessor.cpp b/server/battles/BattleActionProcessor.cpp index af8e88994..520fcdd02 100644 --- a/server/battles/BattleActionProcessor.cpp +++ b/server/battles/BattleActionProcessor.cpp @@ -404,7 +404,7 @@ bool BattleActionProcessor::doCatapultAction(const CBattleInfoCallback & battle, if (!canStackAct(battle, stack)) return false; - std::shared_ptr catapultAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::CATAPULT)); + std::shared_ptr catapultAbility = stack->getFirstBonus(Selector::type()(BonusType::CATAPULT)); if(!catapultAbility || catapultAbility->subtype == BonusSubtypeID()) { gameHandler->complain("We do not know how to shoot :P"); @@ -492,7 +492,7 @@ bool BattleActionProcessor::doHealAction(const CBattleInfoCallback & battle, con } const battle::Unit * destStack = nullptr; - std::shared_ptr healerAbility = stack->getBonusLocalFirst(Selector::type()(BonusType::HEALER)); + std::shared_ptr healerAbility = stack->getFirstBonus(Selector::type()(BonusType::HEALER)); if(target.at(0).unitValue) destStack = target.at(0).unitValue; @@ -975,7 +975,7 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const drainedLife += applyBattleEffects(battle, bat, attackerState, fireShield, stack, distance, true); } - std::shared_ptr bonus = attacker->getBonusLocalFirst(Selector::type()(BonusType::SPELL_LIKE_ATTACK)); + std::shared_ptr bonus = attacker->getFirstBonus(Selector::type()(BonusType::SPELL_LIKE_ATTACK)); if(bonus && ranged) //TODO: make it work in melee? { //this is need for displaying hit animation diff --git a/server/battles/BattleFlowProcessor.cpp b/server/battles/BattleFlowProcessor.cpp index 975f281df..a27be3606 100644 --- a/server/battles/BattleFlowProcessor.cpp +++ b/server/battles/BattleFlowProcessor.cpp @@ -664,7 +664,7 @@ void BattleFlowProcessor::stackTurnTrigger(const CBattleInfoCallback & battle, c if (st->hasBonusOfType(BonusType::POISON)) { - std::shared_ptr b = st->getBonusLocalFirst(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::POISON))).And(Selector::type()(BonusType::STACK_HEALTH))); + std::shared_ptr b = st->getFirstBonus(Selector::source(BonusSource::SPELL_EFFECT, BonusSourceID(SpellID(SpellID::POISON))).And(Selector::type()(BonusType::STACK_HEALTH))); if (b) //TODO: what if not?... { bte.val = std::max (b->val - 10, -(st->valOfBonuses(BonusType::POISON))); From ffd604c1148fcef29fd5b1d700ced2e5d80e2be6 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 16 Jan 2024 19:06:41 +0200 Subject: [PATCH 11/13] Removed unnecessary access to IHandler::objects --- lib/StartInfo.cpp | 2 +- lib/battle/BattleInfo.cpp | 4 ++-- lib/gameState/CGameState.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 2 +- lib/mapObjects/IMarket.cpp | 4 ++-- lib/mapObjects/ObjectTemplate.cpp | 2 +- lib/mapping/CMap.cpp | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/StartInfo.cpp b/lib/StartInfo.cpp index cf1a70112..194f7d561 100644 --- a/lib/StartInfo.cpp +++ b/lib/StartInfo.cpp @@ -32,7 +32,7 @@ FactionID PlayerSettings::getCastleValidated() const { if (!castle.isValid()) return FactionID(0); - if (castle.getNum() < VLC->townh->size() && VLC->townh->objects[castle.getNum()]->town != nullptr) + if (castle.getNum() < VLC->townh->size() && castle.toEntity(VLC)->hasTown()) return castle; return FactionID(0); diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index cebbaeeeb..7a9dcbe82 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -240,7 +240,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const { try { - RangeGenerator obidgen(0, VLC->obstacleHandler->objects.size() - 1, ourRand); + RangeGenerator obidgen(0, VLC->obstacleHandler->size() - 1, ourRand); auto obstPtr = std::make_shared(); obstPtr->obstacleType = CObstacleInstance::ABSOLUTE_OBSTACLE; obstPtr->ID = obidgen.getSuchNumber(appropriateAbsoluteObstacle); @@ -262,7 +262,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const { while(tilesToBlock > 0) { - RangeGenerator obidgen(0, VLC->obstacleHandler->objects.size() - 1, ourRand); + RangeGenerator obidgen(0, VLC->obstacleHandler->size() - 1, ourRand); auto tileAccessibility = curB->getAccesibility(); const int obid = obidgen.getSuchNumber(appropriateUsualObstacle); const ObstacleInfo &obi = *Obstacle(obid).getInfo(); diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 0a52f96fc..1d1a10aa9 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -99,7 +99,7 @@ HeroTypeID CGameState::pickUnusedHeroTypeRandomly(const PlayerColor & owner) const PlayerSettings &ps = scenarioOps->getIthPlayersSettings(owner); for(const HeroTypeID & hid : getUnusedAllowedHeroes()) { - if(VLC->heroh->objects[hid.getNum()]->heroClass->faction == ps.castle) + if(hid.toHeroType()->heroClass->faction == ps.castle) factionHeroes.push_back(hid); else otherHeroes.push_back(hid); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index dd4e8c974..6af40312e 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -1261,7 +1261,7 @@ EDiggingStatus CGHeroInstance::diggingStatus() const { if(static_cast(movement) < movementPointsLimit(true)) return EDiggingStatus::LACK_OF_MOVEMENT; - if(!VLC->arth->objects[ArtifactID::GRAIL]->canBePutAt(this)) + if(ArtifactID(ArtifactID::GRAIL).toArtifact()->canBePutAt(this)) return EDiggingStatus::BACKPACK_IS_FULL; return cb->getTileDigStatus(visitablePos()); } diff --git a/lib/mapObjects/IMarket.cpp b/lib/mapObjects/IMarket.cpp index 907d90378..02b6d4631 100644 --- a/lib/mapObjects/IMarket.cpp +++ b/lib/mapObjects/IMarket.cpp @@ -96,14 +96,14 @@ bool IMarket::getOffer(int id1, int id2, int &val1, int &val2, EMarketMode mode) case EMarketMode::CREATURE_EXP: { val1 = 1; - val2 = (VLC->creh->objects[id1]->getAIValue() / 40) * 5; + val2 = (CreatureID(id1).toEntity(VLC)->getAIValue() / 40) * 5; } break; case EMarketMode::ARTIFACT_EXP: { val1 = 1; - int givenClass = VLC->arth->objects[id1]->getArtClassSerial(); + int givenClass = ArtifactID(id1).toArtifact()->getArtClassSerial(); if(givenClass < 0 || givenClass > 3) { val2 = 0; diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 3f284bbb4..817ca57c7 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -350,7 +350,7 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const if(withTerrain) { //assumed that ROCK and WATER terrains are not included - if(allowedTerrains.size() < (VLC->terrainTypeHandler->objects.size() - 2)) + if(allowedTerrains.size() < (VLC->terrainTypeHandler->size() - 2)) { JsonVector & data = node["allowedTerrains"].Vector(); diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 01a0478f7..6e6d95b39 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -169,7 +169,7 @@ CMap::CMap(IGameCallback * cb) , grailRadius(0) , uidCounter(0) { - allHeroes.resize(VLC->heroh->objects.size()); + allHeroes.resize(VLC->heroh->size()); allowedAbilities = VLC->skillh->getDefaultAllowed(); allowedArtifact = VLC->arth->getDefaultAllowed(); allowedSpells = VLC->spellh->getDefaultAllowed(); From e50f586d8b5b391618f0b6b6a6e37396735c7cf2 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 16 Jan 2024 20:47:09 +0200 Subject: [PATCH 12/13] Stabilization --- lib/modding/CModInfo.cpp | 2 +- lib/rmg/modificators/TreasurePlacer.cpp | 4 ++-- server/CGameHandler.cpp | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/modding/CModInfo.cpp b/lib/modding/CModInfo.cpp index 26fb1e8f1..dab87979a 100644 --- a/lib/modding/CModInfo.cpp +++ b/lib/modding/CModInfo.cpp @@ -127,7 +127,7 @@ void CModInfo::loadLocalData(const JsonNode & data) if (config["modType"].String() == "Translation") { - if (baseLanguage != VLC->generaltexth->getPreferredLanguage()) + if (baseLanguage != CGeneralTextHandler::getPreferredLanguage()) { if (identifier.find_last_of('.') == std::string::npos) logGlobal->warn("Translation mod %s was not loaded: language mismatch!", verificationInfo.name); diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index 95f2dd151..ea5898117 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -490,10 +490,10 @@ void TreasurePlacer::addAllPossibleObjects() int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType()); // FIXME: Remove duplicated code for gold, exp and creaure reward - oi.generateObject = [creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> CGObjectInstance * + oi.generateObject = [cb=map.mapInstance->cb, creature, creaturesAmount, randomAppearance, setRandomArtifact]() -> CGObjectInstance * { auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance); - auto * obj = dynamic_cast(factory->create(map.mapInstance->cb, nullptr)); + auto * obj = dynamic_cast(factory->create(cb, nullptr)); Rewardable::VisitInfo reward; reward.reward.creatures.emplace_back(creature->getId(), creaturesAmount); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index dce051289..b8f6cfaf6 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1800,6 +1800,7 @@ bool CGameHandler::load(const std::string & filename) { { CLoadFile lf(*CResourceHandler::get()->getResourceName(ResourcePath(stem.to_string(), EResType::SAVEGAME)), MINIMAL_SERIALIZATION_VERSION); + lf.serializer.cb = this; loadCommonState(lf); logGlobal->info("Loading server state"); lf >> *this; From d04241b10a99575c76a8975ae076f75350f0ed02 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 19 Jan 2024 23:02:00 +0200 Subject: [PATCH 13/13] Code cleanup --- AI/Nullkiller/Engine/PriorityEvaluator.cpp | 2 +- AI/Nullkiller/Pathfinding/Actors.cpp | 2 +- client/CGameInfo.cpp | 2 +- client/CGameInfo.h | 2 +- client/CMT.cpp | 2 +- client/Client.cpp | 4 ++-- lib/CHeroHandler.cpp | 4 ++-- lib/JsonRandom.cpp | 10 +++++----- lib/JsonRandom.h | 2 +- lib/bonuses/CBonusSystemNode.cpp | 2 +- lib/gameState/CGameState.cpp | 8 ++++---- server/processors/HeroPoolProcessor.cpp | 4 ++-- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 1a081de8c..77411dac6 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -236,7 +236,7 @@ int getDwellingArmyCost(const CGObjectInstance * target) return cost; } -uint64_t evaluateArtifactArmyValue(CArtifactInstance * art) +static uint64_t evaluateArtifactArmyValue(const CArtifactInstance * art) { if(art->artType->getId() == ArtifactID::SPELL_SCROLL) return 1500; diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index b3f186ce5..900d65506 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -373,7 +373,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade( for(auto & creatureToBuy : buyArmy) { - auto targetSlot = target->getSlotFor(dynamic_cast(creatureToBuy.creID.toCreature())); + auto targetSlot = target->getSlotFor(creatureToBuy.creID.toCreature()); target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count); target->armyCost += creatureToBuy.creID.toCreature()->getFullRecruitCost() * creatureToBuy.count; diff --git a/client/CGameInfo.cpp b/client/CGameInfo.cpp index f57b093a3..bcc0cfc8e 100644 --- a/client/CGameInfo.cpp +++ b/client/CGameInfo.cpp @@ -12,7 +12,7 @@ #include "../lib/VCMI_Lib.h" -const CGameInfo * CGI; +CGameInfo * CGI; CClientState * CCS = nullptr; CServerHandler * CSH; diff --git a/client/CGameInfo.h b/client/CGameInfo.h index 11f1f8111..c07bb3c7d 100644 --- a/client/CGameInfo.h +++ b/client/CGameInfo.h @@ -99,4 +99,4 @@ public: private: const Services * globalServices; }; -extern const CGameInfo* CGI; +extern CGameInfo* CGI; diff --git a/client/CMT.cpp b/client/CMT.cpp index 4e47b70f6..e3b6780f9 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -72,7 +72,7 @@ void init() CStopWatch tmh; loadDLLClasses(); - const_cast(CGI)->setFromLib(); + CGI->setFromLib(); logGlobal->info("Initializing VCMI_Lib: %d ms", tmh.getDiff()); diff --git a/client/Client.cpp b/client/Client.cpp index f1edcf38d..10c2b64e9 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -367,7 +367,7 @@ void CClient::endGame() logNetwork->info("Ending current game!"); removeGUI(); - const_cast(CGI)->mh.reset(); + CGI->mh.reset(); vstd::clear_pointer(gs); logNetwork->info("Deleted mapHandler and gameState."); @@ -389,7 +389,7 @@ void CClient::initMapHandler() // During loading CPlayerInterface from serialized state it's depend on MH if(!settings["session"]["headless"].Bool()) { - const_cast(CGI)->mh = std::make_shared(gs->map); + CGI->mh = std::make_shared(gs->map); logNetwork->trace("Creating mapHandler: %d ms", CSH->th->getDiff()); } diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 0fc7b587d..d90ce3fa0 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -155,9 +155,9 @@ bool CHeroClass::isMagicHero() const return affinity == MAGIC; } -int CHeroClass::tavernProbability(FactionID faction) const +int CHeroClass::tavernProbability(FactionID targetFaction) const { - auto it = selectionProbability.find(faction); + auto it = selectionProbability.find(targetFaction); if (it != selectionProbability.end()) return it->second; return 0; diff --git a/lib/JsonRandom.cpp b/lib/JsonRandom.cpp index 7a35d7bb7..39a639fef 100644 --- a/lib/JsonRandom.cpp +++ b/lib/JsonRandom.cpp @@ -31,7 +31,7 @@ VCMI_LIB_NAMESPACE_BEGIN - si32 JsonRandom::loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue) + si32 JsonRandom::loadVariable(const std::string & variableGroup, const std::string & value, const Variables & variables, si32 defaultValue) { if (value.empty() || value[0] != '@') { @@ -54,7 +54,7 @@ VCMI_LIB_NAMESPACE_BEGIN if(value.isNull()) return defaultValue; if(value.isNumber()) - return static_cast(value.Float()); + return value.Integer(); if (value.isString()) return loadVariable("number", value.String(), variables, defaultValue); @@ -68,9 +68,9 @@ VCMI_LIB_NAMESPACE_BEGIN if(value.isStruct()) { if (!value["amount"].isNull()) - return static_cast(loadValue(value["amount"], rng, variables, defaultValue)); - si32 min = static_cast(loadValue(value["min"], rng, variables, 0)); - si32 max = static_cast(loadValue(value["max"], rng, variables, 0)); + return loadValue(value["amount"], rng, variables, defaultValue); + si32 min = loadValue(value["min"], rng, variables, 0); + si32 max = loadValue(value["max"], rng, variables, 0); return rng.getIntRange(min, max)(); } return defaultValue; diff --git a/lib/JsonRandom.h b/lib/JsonRandom.h index 613350941..79ab292ce 100644 --- a/lib/JsonRandom.h +++ b/lib/JsonRandom.h @@ -41,7 +41,7 @@ private: template IdentifierType decodeKey(const JsonNode & value, const Variables & variables); - si32 loadVariable(std::string variableGroup, const std::string & value, const Variables & variables, si32 defaultValue); + si32 loadVariable(const std::string & variableGroup, const std::string & value, const Variables & variables, si32 defaultValue); public: using GameCallbackHolder::GameCallbackHolder; diff --git a/lib/bonuses/CBonusSystemNode.cpp b/lib/bonuses/CBonusSystemNode.cpp index f8f45cbbd..3cedf4408 100644 --- a/lib/bonuses/CBonusSystemNode.cpp +++ b/lib/bonuses/CBonusSystemNode.cpp @@ -486,7 +486,7 @@ void CBonusSystemNode::getRedParents(TCNodes & out) const if(!actsAsBonusSourceOnly()) { - for(CBonusSystemNode *child : children) + for(const CBonusSystemNode *child : children) { out.insert(child); } diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 1d1a10aa9..6987dd802 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -171,10 +171,10 @@ CGameState::~CGameState() initialOpts.dellNull(); } -void CGameState::preInit(Services * services, IGameCallback * callback) +void CGameState::preInit(Services * newServices, IGameCallback * newCallback) { - this->services = services; - this->callback = callback; + services = newServices; + callback = newCallback; } void CGameState::init(const IMapService * mapService, StartInfo * si, Load::ProgressAccumulator & progressTracking, bool allowSavingRandomMap) @@ -631,7 +631,7 @@ void CGameState::initHeroes() if (tile.terType->isWater()) { auto handler = VLC->objtypeh->getHandlerFor(Obj::BOAT, hero->getBoatType().getNum()); - CGBoat * boat = dynamic_cast(handler->create(callback, nullptr)); + auto boat = dynamic_cast(handler->create(callback, nullptr)); handler->configureObject(boat, gs->getRandomGenerator()); boat->pos = hero->pos; diff --git a/server/processors/HeroPoolProcessor.cpp b/server/processors/HeroPoolProcessor.cpp index 54612dce2..cef39cf07 100644 --- a/server/processors/HeroPoolProcessor.cpp +++ b/server/processors/HeroPoolProcessor.cpp @@ -247,7 +247,7 @@ std::vector HeroPoolProcessor::findAvailableClassesFor(const const auto & heroesPool = gameHandler->gameState()->heroesPool; FactionID factionID = gameHandler->getPlayerSettings(player)->castle; - for(auto & elem : heroesPool->unusedHeroesFromPool()) + for(const auto & elem : heroesPool->unusedHeroesFromPool()) { if (vstd::contains(result, elem.second->type->heroClass)) continue; @@ -268,7 +268,7 @@ std::vector HeroPoolProcessor::findAvailableHeroesFor(const Pl const auto & heroesPool = gameHandler->gameState()->heroesPool; - for(auto & elem : heroesPool->unusedHeroesFromPool()) + for(const auto & elem : heroesPool->unusedHeroesFromPool()) { assert(!vstd::contains(result, elem.second));