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