From 03e116978128a0fc95933561999f657fed5d9bc5 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Tue, 24 Oct 2023 17:11:25 +0300 Subject: [PATCH] Reduced number of accesses to CGObjectInstance::subID --- lib/campaign/CampaignState.cpp | 9 +++--- lib/constants/EntityIdentifiers.h | 30 ++++++++++++++++++-- lib/gameState/CGameState.cpp | 6 ++-- lib/gameState/CGameStateCampaign.cpp | 12 ++++---- lib/gameState/TavernHeroesPool.cpp | 6 ++-- lib/mapObjects/CBank.cpp | 2 +- lib/mapObjects/CGCreature.cpp | 29 ++++++++++++-------- lib/mapObjects/CGCreature.h | 1 + lib/mapObjects/CGDwelling.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 13 ++++++--- lib/mapObjects/CGHeroInstance.h | 1 + lib/mapObjects/CGMarket.cpp | 2 +- lib/mapObjects/CGObjectInstance.cpp | 11 ++++++-- lib/mapObjects/CGObjectInstance.h | 12 +++++--- lib/mapObjects/CGTownBuilding.cpp | 4 +-- lib/mapObjects/CGTownBuilding.h | 4 +-- lib/mapObjects/CGTownInstance.cpp | 2 +- lib/mapObjects/CObjectHandler.cpp | 10 ------- lib/mapObjects/CObjectHandler.h | 11 -------- lib/mapObjects/CRewardableObject.cpp | 2 +- lib/mapObjects/IObjectInterface.h | 5 ++-- lib/mapObjects/MiscObjects.cpp | 41 ++++++++++++++++++---------- lib/mapObjects/MiscObjects.h | 3 ++ lib/mapping/CMap.cpp | 4 +-- lib/mapping/CMap.h | 2 +- lib/mapping/MapFormatJson.cpp | 2 +- lib/rmg/RmgObject.cpp | 6 ++-- 27 files changed, 135 insertions(+), 97 deletions(-) diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index 082ddf7ee..eb6144f3e 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -274,17 +274,16 @@ void CampaignState::setCurrentMapAsConquered(std::vector heroe for (auto * hero : heroes) { - HeroTypeID heroType(hero->subID); JsonNode node = CampaignState::crossoverSerialize(hero); - if (reservedHeroes.count(heroType)) + if (reservedHeroes.count(hero->getHeroType())) { - logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->subID, hero->getNameTranslated()); - globalHeroPool[heroType] = node; + logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroType(), hero->getNameTranslated()); + globalHeroPool[hero->getHeroType()] = node; } else { - logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->subID, hero->getNameTranslated()); + logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroType(), hero->getNameTranslated()); scenarioHeroPool[*currentMap].push_back(node); } } diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 6a5e7b5d8..c9b10fd83 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -407,7 +407,7 @@ public: static std::string entityType(); }; -class ObjBase : public IdentifierBase +class MapObjectBaseID : public IdentifierBase { public: enum Type @@ -552,15 +552,38 @@ public: }; }; -class DLL_LINKAGE Obj : public IdentifierWithEnum +class DLL_LINKAGE MapObjectID : public IdentifierWithEnum { public: - using IdentifierWithEnum::IdentifierWithEnum; + using IdentifierWithEnum::IdentifierWithEnum; static std::string encode(int32_t index); static si32 decode(const std::string & identifier); }; +class MapObjectSubID : public Identifier +{ +public: + constexpr MapObjectSubID(const IdentifierBase & value): + Identifier(value.getNum()) + {} + constexpr MapObjectSubID(int32_t value): + Identifier(value) + {} + + MapObjectSubID & operator =(int32_t value) + { + this->num = value; + return *this; + } + + MapObjectSubID & operator =(const IdentifierBase & value) + { + this->num = value.getNum(); + return *this; + } +}; + class DLL_LINKAGE RoadId : public Identifier { public: @@ -966,6 +989,7 @@ public: // Deprecated // TODO: remove +using Obj = MapObjectID; using ETownType = FactionID; using EGameResID = GameResID; using River = RiverId; diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 80a80be05..69a2fbed6 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -77,7 +77,7 @@ public: } }; -static CGObjectInstance * createObject(const Obj & id, int subid, const int3 & pos, const PlayerColor & owner) +static CGObjectInstance * createObject(MapObjectID id, MapObjectSubID subid, const int3 & pos, const PlayerColor & owner) { CGObjectInstance * nobj; switch(id) @@ -810,7 +810,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy } } - CGObjectInstance * hero = createObject(Obj::HERO, heroTypeId.getNum(), townPos, playerColor); + CGObjectInstance * hero = createObject(Obj::HERO, heroTypeId, townPos, playerColor); hero->pos += hero->getVisitableOffset(); map->getEditManager()->insertObject(hero); } @@ -880,8 +880,6 @@ void CGameState::initHeroes() CGBoat * boat = dynamic_cast(handler->create()); handler->configureObject(boat, gs->getRandomGenerator()); - boat->ID = Obj::BOAT; - boat->subID = hero->getBoatType().getNum(); boat->pos = hero->pos; boat->appearance = handler->getTemplates().front(); boat->id = ObjectInstanceID(static_cast(gs->map->objects.size())); diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index c97c159a6..597bdd7eb 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -213,7 +213,7 @@ void CGameStateCampaign::placeCampaignHeroes() std::set heroesToRemove = campaignState->getReservedHeroes(); for(auto & campaignHeroReplacement : campaignHeroReplacements) - heroesToRemove.insert(HeroTypeID(campaignHeroReplacement.hero->subID)); + heroesToRemove.insert(campaignHeroReplacement.hero->getHeroType()); for(auto & heroID : heroesToRemove) { @@ -339,7 +339,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders(const std::vectortempOwner.isValidPlayer()) heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->pos = heroPlaceholder->pos; - heroToPlace->type = VLC->heroh->objects[heroToPlace->subID]; + heroToPlace->type = VLC->heroh->objects[heroToPlace->getHeroType().getNum()]; heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); gameState->map->removeBlockVisTiles(heroPlaceholder, true); @@ -396,7 +396,7 @@ std::vector CGameStateCampaign::generateCampaignHeroesT CGHeroInstance * hero = CampaignState::crossoverDeserialize(node, gameState->map); - logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->subID, hero->getNameTranslated()); + logGlobal->info("Hero crossover: Loading placeholder for %d (%s)", hero->getHeroType(), hero->getNameTranslated()); campaignHeroReplacements.emplace_back(hero, placeholder->id); } @@ -422,7 +422,7 @@ std::vector CGameStateCampaign::generateCampaignHeroesT CGHeroInstance * hero = CampaignState::crossoverDeserialize(*nodeListIter, gameState->map); nodeListIter++; - logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->subID, hero->getNameTranslated()); + logGlobal->info("Hero crossover: Loading placeholder as %d (%s)", hero->getHeroType(), hero->getNameTranslated()); campaignHeroReplacements.emplace_back(hero, placeholder->id); } @@ -468,7 +468,7 @@ void CGameStateCampaign::initHeroes() { for (auto & heroe : heroes) { - if (heroe->subID == chosenBonus->info1) + if (heroe->getHeroType().getNum() == chosenBonus->info1) { giveCampaignBonusToHero(heroe); break; @@ -557,7 +557,7 @@ void CGameStateCampaign::initTowns() if(gameState->scenarioOps->campState->formatVCMI()) newBuilding = BuildingID(chosenBonus->info1); else - newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->subID, town->builtBuildings); + newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->builtBuildings); // Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2 while(true) diff --git a/lib/gameState/TavernHeroesPool.cpp b/lib/gameState/TavernHeroesPool.cpp index 4dabd8ab3..00aec3a73 100644 --- a/lib/gameState/TavernHeroesPool.cpp +++ b/lib/gameState/TavernHeroesPool.cpp @@ -25,7 +25,7 @@ std::map TavernHeroesPool::unusedHeroesFromPool() c { std::map pool = heroesPool; for(const auto & slot : currentTavern) - pool.erase(HeroTypeID(slot.hero->subID)); + pool.erase(slot.hero->getHeroType()); return pool; } @@ -34,7 +34,7 @@ TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const { for (auto const & slot : currentTavern) { - if (HeroTypeID(slot.hero->subID) == hero) + if (slot.hero->getHeroType() == hero) return slot.role; } return TavernSlotRole::NONE; @@ -132,7 +132,7 @@ void TavernHeroesPool::onNewDay() void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero) { - heroesPool[HeroTypeID(hero->subID)] = hero; + heroesPool[hero->getHeroType()] = hero; } void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set mask) diff --git a/lib/mapObjects/CBank.cpp b/lib/mapObjects/CBank.cpp index 53f219939..849d171c6 100644 --- a/lib/mapObjects/CBank.cpp +++ b/lib/mapObjects/CBank.cpp @@ -46,7 +46,7 @@ void CBank::initObj(CRandomGenerator & rand) { daycounter = 0; resetDuration = 0; - VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); + getObjectHandler()->configureObject(this, rand); } bool CBank::isCoastVisitable() const diff --git a/lib/mapObjects/CGCreature.cpp b/lib/mapObjects/CGCreature.cpp index b0c9c8384..dff3ed95d 100644 --- a/lib/mapObjects/CGCreature.cpp +++ b/lib/mapObjects/CGCreature.cpp @@ -28,7 +28,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const if(stacks.empty()) { //should not happen... - logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", pos.toString(), subID, id.getNum()); + logGlobal->error("Invalid stack at tile %s: subID=%d; id=%d", pos.toString(), getCreature(), id.getNum()); return "INVALID_STACK"; } @@ -41,7 +41,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const else ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex); ms.appendRawString(" "); - ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID); + ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature()); hoverName = ms.toString(); return hoverName; } @@ -54,7 +54,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const MetaString ms; ms.appendNumber(stacks.begin()->second->count); ms.appendRawString(" "); - ms.appendLocalString(EMetaText::CRE_PL_NAMES,subID); + ms.appendLocalString(EMetaText::CRE_PL_NAMES, getCreature()); ms.appendRawString("\n\n"); @@ -132,7 +132,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const BlockingDialog ynd(true,false); ynd.player = h->tempOwner; ynd.text.appendLocalString(EMetaText::ADVOB_TXT, 86); - ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID); + ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, getCreature()); cb->showBlockingDialog(&ynd); break; } @@ -146,7 +146,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const std::string tmp = VLC->generaltexth->advobtxt[90]; boost::algorithm::replace_first(tmp, "%d", std::to_string(getStackCount(SlotID(0)))); boost::algorithm::replace_first(tmp, "%d", std::to_string(action)); - boost::algorithm::replace_first(tmp,"%s",VLC->creh->objects[subID]->getNamePluralTranslated()); + boost::algorithm::replace_first(tmp,"%s",VLC->creatures()->getById(getCreature())->getNamePluralTranslated()); ynd.text.appendRawString(tmp); cb->showBlockingDialog(&ynd); break; @@ -155,6 +155,11 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const } +CreatureID CGCreature::getCreature() const +{ + return CreatureID(getObjTypeIndex().getNum()); +} + void CGCreature::initObj(CRandomGenerator & rand) { blockVisit = true; @@ -177,16 +182,16 @@ void CGCreature::initObj(CRandomGenerator & rand) break; } - stacks[SlotID(0)]->setType(CreatureID(subID)); + stacks[SlotID(0)]->setType(getCreature()); TQuantity &amount = stacks[SlotID(0)]->count; - CCreature &c = *VLC->creh->objects[subID]; + const Creature * c = VLC->creatures()->getById(getCreature()); if(amount == 0) { - amount = rand.nextInt(c.ammMin, c.ammMax); + amount = rand.nextInt(c->getAdvMapAmountMin(), c->getAdvMapAmountMax()); if(amount == 0) //armies with 0 creatures are illegal { - logGlobal->warn("Stack %s cannot have 0 creatures. Check properties of %s", nodeName(), c.nodeName()); + logGlobal->warn("Stack cannot have 0 creatures. Check properties of %s", c->getJsonKey()); amount = 1; } } @@ -252,7 +257,7 @@ 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[subID]; + const CCreature * myCreature = VLC->creh->objects[getCreature().getNum()]; myKindCres.insert(myCreature->getId()); //we myKindCres.insert(myCreature->upgrades.begin(), myCreature->upgrades.end()); //our upgrades @@ -290,7 +295,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const return JOIN_FOR_FREE; else if(diplomacy * 2 + sympathy + 1 >= character) - return VLC->creatures()->getByIndex(subID)->getRecruitCost(EGameResID::GOLD) * getStackCount(SlotID(0)); //join for gold + return VLC->creatures()->getById(getCreature())->getRecruitCost(EGameResID::GOLD) * getStackCount(SlotID(0)); //join for gold } //we are still here - creatures have not joined hero, flee or fight @@ -404,7 +409,7 @@ void CGCreature::flee( const CGHeroInstance * h ) const BlockingDialog ynd(true,false); ynd.player = h->tempOwner; ynd.text.appendLocalString(EMetaText::ADVOB_TXT,91); - ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, subID); + ynd.text.replaceLocalString(EMetaText::CRE_PL_NAMES, getCreature()); cb->showBlockingDialog(&ynd); } diff --git a/lib/mapObjects/CGCreature.h b/lib/mapObjects/CGCreature.h index 385b96cb5..438e89c92 100644 --- a/lib/mapObjects/CGCreature.h +++ b/lib/mapObjects/CGCreature.h @@ -44,6 +44,7 @@ public: void newTurn(CRandomGenerator & rand) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; + CreatureID getCreature() const; //stack formation depends on position, bool containsUpgradedStack() const; diff --git a/lib/mapObjects/CGDwelling.cpp b/lib/mapObjects/CGDwelling.cpp index 65da8db66..70fc4d983 100644 --- a/lib/mapObjects/CGDwelling.cpp +++ b/lib/mapObjects/CGDwelling.cpp @@ -95,7 +95,7 @@ void CGDwelling::initObj(CRandomGenerator & rand) case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR4: { - VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); + getObjectHandler()->configureObject(this, rand); if (getOwner() != PlayerColor::NEUTRAL) cb->gameState()->players[getOwner()].dwellings.emplace_back(this); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 1d49f631f..c122af7ab 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -285,6 +285,11 @@ PlayerColor CGHeroInstance::getOwner() const return tempOwner; } +HeroTypeID CGHeroInstance::getHeroType() const +{ + return HeroTypeID(getObjTypeIndex().getNum()); +} + void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID) { subID = SUBID.getNum(); @@ -305,7 +310,7 @@ void CGHeroInstance::initHero(CRandomGenerator & rand) { assert(validTypes(true)); if(!type) - type = VLC->heroh->objects[subID]; + type = VLC->heroh->objects[getHeroType().getNum()]; if (ID == Obj::HERO) appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); @@ -1050,7 +1055,7 @@ HeroTypeID CGHeroInstance::getPortraitSource() const if (customPortraitSource.isValid()) return customPortraitSource; else - return HeroTypeID(subID); + return getHeroType(); } int32_t CGHeroInstance::getIconIndex() const @@ -1502,7 +1507,7 @@ std::string CGHeroInstance::getHeroTypeName() const } else { - return VLC->heroh->objects[subID]->getJsonKey(); + return VLC->heroh->objects[getHeroType()]->getJsonKey(); } } return ""; @@ -1736,7 +1741,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler) if(!appearance) { // crossoverDeserialize - type = VLC->heroh->objects[subID]; + type = VLC->heroh->objects[getHeroType()]; appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); } diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 2035a488b..a742f2d7b 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -231,6 +231,7 @@ public: ////////////////////////////////////////////////////////////////////////// + HeroTypeID getHeroType() const; void setType(si32 ID, si32 subID) override; void initHero(CRandomGenerator & rand); diff --git a/lib/mapObjects/CGMarket.cpp b/lib/mapObjects/CGMarket.cpp index ef20b1024..d6a1e433d 100644 --- a/lib/mapObjects/CGMarket.cpp +++ b/lib/mapObjects/CGMarket.cpp @@ -25,7 +25,7 @@ VCMI_LIB_NAMESPACE_BEGIN void CGMarket::initObj(CRandomGenerator & rand) { - VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); + getObjectHandler()->configureObject(this, rand); } void CGMarket::onHeroVisit(const CGHeroInstance * h) const diff --git a/lib/mapObjects/CGObjectInstance.cpp b/lib/mapObjects/CGObjectInstance.cpp index 7d5cacbe2..1f153a75f 100644 --- a/lib/mapObjects/CGObjectInstance.cpp +++ b/lib/mapObjects/CGObjectInstance.cpp @@ -40,12 +40,12 @@ CGObjectInstance::CGObjectInstance(): //must be instantiated in .cpp file for access to complete types of all member fields CGObjectInstance::~CGObjectInstance() = default; -int32_t CGObjectInstance::getObjGroupIndex() const +MapObjectID CGObjectInstance::getObjGroupIndex() const { - return ID.num; + return ID; } -int32_t CGObjectInstance::getObjTypeIndex() const +MapObjectSubID CGObjectInstance::getObjTypeIndex() const { return subID; } @@ -197,6 +197,11 @@ void CGObjectInstance::setProperty( ui8 what, ui32 val ) } } +TObjectTypeHandler CGObjectInstance::getObjectHandler() const +{ + return VLC->objtypeh->getHandlerFor(ID, subID); +} + void CGObjectInstance::setPropertyDer( ui8 what, ui32 val ) {} diff --git a/lib/mapObjects/CGObjectInstance.h b/lib/mapObjects/CGObjectInstance.h index 1e57c2344..4d1fbc9fd 100644 --- a/lib/mapObjects/CGObjectInstance.h +++ b/lib/mapObjects/CGObjectInstance.h @@ -21,6 +21,8 @@ struct Component; class JsonSerializeFormat; class ObjectTemplate; class CMap; +class AObjectTypeHandler; +using TObjectTypeHandler = std::shared_ptr; class DLL_LINKAGE CGObjectInstance : public IObjectInterface { @@ -28,9 +30,9 @@ public: /// Position of bottom-right corner of object on map int3 pos; /// Type of object, e.g. town, hero, creature. - Obj ID; + MapObjectID ID; /// Subtype of object, depends on type - si32 subID; + MapObjectSubID subID; /// Current owner of an object (when below PLAYER_LIMIT) PlayerColor tempOwner; /// Index of object in map's list of objects @@ -45,8 +47,8 @@ public: CGObjectInstance(); //TODO: remove constructor ~CGObjectInstance() override; - int32_t getObjGroupIndex() const override; - int32_t getObjTypeIndex() const override; + MapObjectID getObjGroupIndex() const override; + MapObjectSubID getObjTypeIndex() const override; /// "center" tile from which the sight distance is calculated int3 getSightCenter() const; @@ -94,6 +96,8 @@ public: std::optional getVisitSound() const; std::optional getRemovalSound() const; + TObjectTypeHandler getObjectHandler() const; + /** VIRTUAL METHODS **/ /// Returns true if player can pass through visitable tiles of this object diff --git a/lib/mapObjects/CGTownBuilding.cpp b/lib/mapObjects/CGTownBuilding.cpp index 4921b085a..b449dc0e0 100644 --- a/lib/mapObjects/CGTownBuilding.cpp +++ b/lib/mapObjects/CGTownBuilding.cpp @@ -24,12 +24,12 @@ PlayerColor CGTownBuilding::getOwner() const return town->getOwner(); } -int32_t CGTownBuilding::getObjGroupIndex() const +MapObjectID CGTownBuilding::getObjGroupIndex() const { return -1; } -int32_t CGTownBuilding::getObjTypeIndex() const +MapObjectSubID CGTownBuilding::getObjTypeIndex() const { return 0; } diff --git a/lib/mapObjects/CGTownBuilding.h b/lib/mapObjects/CGTownBuilding.h index 1fffb3710..77085f67f 100644 --- a/lib/mapObjects/CGTownBuilding.h +++ b/lib/mapObjects/CGTownBuilding.h @@ -45,8 +45,8 @@ public: } PlayerColor getOwner() const override; - int32_t getObjGroupIndex() const override; - int32_t getObjTypeIndex() const override; + MapObjectID getObjGroupIndex() const override; + MapObjectSubID getObjTypeIndex() const override; int3 visitablePos() const override; int3 getPosition() const override; diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 9e7f842b2..a4841a3cd 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -763,7 +763,7 @@ void CGTownInstance::updateAppearance() { auto terrain = cb->gameState()->getTile(visitablePos())->terType->getId(); //FIXME: not the best way to do this - auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(terrain, this); + auto app = getObjectHandler()->getOverride(terrain, this); if (app) appearance = app; } diff --git a/lib/mapObjects/CObjectHandler.cpp b/lib/mapObjects/CObjectHandler.cpp index 34162c4c3..bf9c2158d 100644 --- a/lib/mapObjects/CObjectHandler.cpp +++ b/lib/mapObjects/CObjectHandler.cpp @@ -28,14 +28,4 @@ CObjectHandler::CObjectHandler() logGlobal->trace("\t\tDone loading resource prices!"); } -CGObjectInstanceBySubIdFinder::CGObjectInstanceBySubIdFinder(CGObjectInstance * obj) : obj(obj) -{ - -} - -bool CGObjectInstanceBySubIdFinder::operator()(CGObjectInstance * obj) const -{ - return this->obj->subID == obj->subID; -} - VCMI_LIB_NAMESPACE_END diff --git a/lib/mapObjects/CObjectHandler.h b/lib/mapObjects/CObjectHandler.h index 128d579b4..9cba71ab1 100644 --- a/lib/mapObjects/CObjectHandler.h +++ b/lib/mapObjects/CObjectHandler.h @@ -16,17 +16,6 @@ VCMI_LIB_NAMESPACE_BEGIN class CGObjectInstance; class int3; -/// function object which can be used to find an object with an specific sub ID -class CGObjectInstanceBySubIdFinder -{ -public: - CGObjectInstanceBySubIdFinder(CGObjectInstance * obj); - bool operator()(CGObjectInstance * obj) const; - -private: - CGObjectInstance * obj; -}; - class DLL_LINKAGE CObjectHandler { public: diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 4ec6783e0..1d441b9f3 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -373,7 +373,7 @@ void CRewardableObject::newTurn(CRandomGenerator & rand) const void CRewardableObject::initObj(CRandomGenerator & rand) { - VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand); + getObjectHandler()->configureObject(this, rand); } CRewardableObject::CRewardableObject() diff --git a/lib/mapObjects/IObjectInterface.h b/lib/mapObjects/IObjectInterface.h index 1ed826903..6a6ca40b7 100644 --- a/lib/mapObjects/IObjectInterface.h +++ b/lib/mapObjects/IObjectInterface.h @@ -10,6 +10,7 @@ #pragma once #include "../networkPacks/EInfoWindowMode.h" +#include "../constants/EntityIdentifiers.h" VCMI_LIB_NAMESPACE_BEGIN @@ -33,8 +34,8 @@ public: virtual ~IObjectInterface() = default; - virtual int32_t getObjGroupIndex() const = 0; - virtual int32_t getObjTypeIndex() const = 0; + virtual MapObjectID getObjGroupIndex() const = 0; + virtual MapObjectSubID getObjTypeIndex() const = 0; virtual PlayerColor getOwner() const = 0; virtual int3 visitablePos() const = 0; diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 0bfb191a7..5e688e4d9 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -85,7 +85,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const { BlockingDialog ynd(true,false); ynd.player = h->tempOwner; - ynd.text.appendLocalString(EMetaText::ADVOB_TXT, subID == 7 ? 84 : 187); + ynd.text.appendLocalString(EMetaText::ADVOB_TXT, isAbandoned() ? 84 : 187); cb->showBlockingDialog(&ynd); return; } @@ -119,19 +119,19 @@ void CGMine::initObj(CRandomGenerator & rand) } else { - producedResource = GameResID(subID); + producedResource = GameResID(getObjTypeIndex()); } producedQuantity = defaultResProduction(); } bool CGMine::isAbandoned() const { - return (subID >= 7); + return (getObjTypeIndex() >= 7); } std::string CGMine::getObjectName() const { - return VLC->generaltexth->translate("core.minename", subID); + return VLC->generaltexth->translate("core.minename", getObjTypeIndex()); } std::string CGMine::getHoverText(PlayerColor player) const @@ -206,7 +206,7 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler) if(handler.saving) { JsonNode node(JsonNode::JsonType::DATA_VECTOR); - for(auto const & resID : abandonedMineResources) + for(const auto & resID : abandonedMineResources) { JsonNode one(JsonNode::JsonType::DATA_STRING); one.String() = GameConstants::RESOURCE_NAMES[resID]; @@ -237,9 +237,14 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler) } } +GameResID CGResource::resourceID() const +{ + return getObjTypeIndex().getNum(); +} + std::string CGResource::getHoverText(PlayerColor player) const { - return VLC->generaltexth->restypes[subID]; + return VLC->generaltexth->restypes[resourceID()]; } void CGResource::initObj(CRandomGenerator & rand) @@ -248,7 +253,7 @@ void CGResource::initObj(CRandomGenerator & rand) if(amount == CGResource::RANDOM_AMOUNT) { - switch(static_cast(subID)) + switch(resourceID()) { case EGameResID::GOLD: amount = rand.nextInt(5, 10) * 100; @@ -285,7 +290,7 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const void CGResource::collectRes(const PlayerColor & player) const { - cb->giveResource(player, static_cast(subID), amount); + cb->giveResource(player, resourceID(), amount); InfoWindow sii; sii.player = player; if(!message.empty()) @@ -297,9 +302,9 @@ void CGResource::collectRes(const PlayerColor & player) const { sii.type = EInfoWindowMode::INFO; sii.text.appendLocalString(EMetaText::ADVOB_TXT,113); - sii.text.replaceLocalString(EMetaText::RES_NAMES, subID); + sii.text.replaceLocalString(EMetaText::RES_NAMES, resourceID()); } - sii.components.emplace_back(Component::EComponentType::RESOURCE,subID,amount,0); + sii.components.emplace_back(Component::EComponentType::RESOURCE, resourceID(), amount, 0); sii.soundID = soundBase::pickup01 + CRandomGenerator::getDefault().nextInt(6); cb->showInfoDialog(&sii); cb->removeObject(this, player); @@ -688,6 +693,14 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h) || (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1); } +ArtifactID CGArtifact::getArtifact() const +{ + if(ID == Obj::SPELL_SCROLL) + return ArtifactID::SPELL_SCROLL; + else + return getObjTypeIndex().getNum(); +} + void CGArtifact::initObj(CRandomGenerator & rand) { blockVisit = true; @@ -700,7 +713,7 @@ void CGArtifact::initObj(CRandomGenerator & rand) storedArtifact = a; } if(!storedArtifact->artType) - storedArtifact->setType(VLC->arth->objects[subID]); + storedArtifact->setType(VLC->arth->objects[getArtifact()]); } if(ID == Obj::SPELL_SCROLL) subID = 1; @@ -713,7 +726,7 @@ void CGArtifact::initObj(CRandomGenerator & rand) std::string CGArtifact::getObjectName() const { - return VLC->artifacts()->getByIndex(subID)->getNameTranslated(); + return VLC->artifacts()->getByIndex(getArtifact())->getNameTranslated(); } void CGArtifact::onHeroVisit(const CGHeroInstance * h) const @@ -730,11 +743,11 @@ void CGArtifact::onHeroVisit(const CGHeroInstance * h) const { case Obj::ARTIFACT: { - iw.components.emplace_back(Component::EComponentType::ARTIFACT, subID, 0, 0); + iw.components.emplace_back(Component::EComponentType::ARTIFACT, getArtifact(), 0, 0); if(!message.empty()) iw.text = message; else - iw.text.appendLocalString(EMetaText::ART_EVNTS, subID); + iw.text.appendLocalString(EMetaText::ART_EVNTS, getArtifact()); } break; case Obj::SPELL_SCROLL: diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index 53021a4a9..c40256dc1 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -93,6 +93,8 @@ public: void afterAddToMap(CMap * map) override; BattleField getBattlefield() const override; + ArtifactID getArtifact() const; + template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -118,6 +120,7 @@ public: std::string getHoverText(PlayerColor player) const override; void collectRes(const PlayerColor & player) const; + GameResID resourceID() const; template void serialize(Handler &h, const int version) { diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 806c953c1..46156dac6 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -250,10 +250,10 @@ void CMap::calculateGuardingGreaturePositions() } } -CGHeroInstance * CMap::getHero(int heroID) +CGHeroInstance * CMap::getHero(HeroTypeID heroID) { for(auto & elem : heroesOnMap) - if(elem->subID == heroID) + if(elem->getObjTypeIndex() == heroID.getNum()) return elem; return nullptr; } diff --git a/lib/mapping/CMap.h b/lib/mapping/CMap.h index de9d5e5a2..518b1fb6a 100644 --- a/lib/mapping/CMap.h +++ b/lib/mapping/CMap.h @@ -118,7 +118,7 @@ public: /// Gets object of specified type on requested position const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj type); - CGHeroInstance * getHero(int heroId); + CGHeroInstance * getHero(HeroTypeID heroId); /// Sets the victory/loss condition objectives ?? void checkForObjectives(); diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 0208204a1..06abea28c 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -1229,7 +1229,7 @@ void CMapLoaderJson::MapObjectLoader::configure() else if(art->ID == Obj::ARTIFACT) { //specific artifact - artID = ArtifactID(art->subID); + artID = art->getArtifact(); } art->storedArtifact = ArtifactUtils::createArtifact(owner->map, artID, spellID.getNum()); diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index 9934602a5..a2f26c03d 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -113,7 +113,7 @@ void Object::Instance::setPositionRaw(const int3 & position) void Object::Instance::setAnyTemplate(CRandomGenerator & rng) { - auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(); + auto templates = dObject.getObjectHandler()->getTemplates(); if(templates.empty()) throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.subID)); @@ -124,7 +124,7 @@ void Object::Instance::setAnyTemplate(CRandomGenerator & rng) void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng) { - auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain); + auto templates = dObject.getObjectHandler()->getTemplates(terrain); if (templates.empty()) { auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated(); @@ -335,7 +335,7 @@ void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng) if (!dObject.appearance) { const auto * terrainType = map.getTile(getPosition(true)).terType; - auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->getId()); + auto templates = dObject.getObjectHandler()->getTemplates(terrainType->getId()); if (templates.empty()) { throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType));