From 8346d71c98bbc1d22db62f937726c029b7309fea Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sat, 28 Oct 2023 12:27:10 +0300 Subject: [PATCH] Remove more subID access --- AI/Nullkiller/Analyzers/BuildAnalyzer.cpp | 2 +- AI/Nullkiller/Behaviors/StartupBehavior.cpp | 2 +- AI/Nullkiller/Engine/FuzzyHelper.cpp | 7 ++--- AI/Nullkiller/Engine/PriorityEvaluator.cpp | 31 ++++++++++++++------- AI/VCAI/AIUtility.h | 1 - AI/VCAI/FuzzyEngines.cpp | 2 +- AI/VCAI/FuzzyHelper.cpp | 11 ++------ AI/VCAI/Goals/CollectRes.cpp | 4 +-- AI/VCAI/Goals/GatherTroops.cpp | 2 +- AI/VCAI/Pathfinding/PathfindingManager.cpp | 2 +- AI/VCAI/ResourceManager.cpp | 14 +--------- AI/VCAI/VCAI.cpp | 4 +-- AI/VCAI/VCAI.h | 2 +- CCallback.cpp | 2 +- client/NetPacksClient.cpp | 2 +- client/mapView/MapRendererContext.cpp | 6 +--- client/windows/CCastleInterface.cpp | 6 ++-- client/windows/CTradeWindow.cpp | 4 +-- lib/gameState/CGameState.cpp | 2 +- lib/gameState/CGameStateCampaign.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 6 ++++ lib/mapObjects/CGHeroInstance.h | 1 + lib/mapObjects/MiscObjects.cpp | 10 ++++++- lib/mapObjects/MiscObjects.h | 1 + lib/mapping/MapFormatJson.cpp | 2 +- lib/networkPacks/NetPacksLib.cpp | 3 +- lib/pathfinder/CPathfinder.cpp | 17 ++++++----- lib/rmg/RmgObject.cpp | 6 ++-- lib/rmg/modificators/TreasurePlacer.cpp | 2 +- lib/spells/ViewSpellInt.cpp | 2 +- mapeditor/mapcontroller.cpp | 4 +-- server/CGameHandler.cpp | 6 ++-- server/processors/HeroPoolProcessor.cpp | 14 +++++----- 33 files changed, 92 insertions(+), 90 deletions(-) diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 386e71779..8a6edc8c7 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -318,7 +318,7 @@ bool BuildAnalyzer::hasAnyBuilding(int32_t alignment, BuildingID bid) const { for(auto tdi : developmentInfos) { - if(tdi.town->subID == alignment && tdi.town->hasBuilt(bid)) + if(tdi.town->getFaction() == alignment && tdi.town->hasBuilt(bid)) return true; } diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.cpp b/AI/Nullkiller/Behaviors/StartupBehavior.cpp index 84abb41fe..3a7f59f72 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.cpp +++ b/AI/Nullkiller/Behaviors/StartupBehavior.cpp @@ -71,7 +71,7 @@ bool needToRecruitHero(const CGTownInstance * startupTown) for(auto obj : ai->nullkiller->objectClusterizer->getNearbyObjects()) { - if((obj->ID == Obj::RESOURCE && obj->subID == GameResID(EGameResID::GOLD)) + if((obj->ID == Obj::RESOURCE && dynamic_cast(obj)->resourceID() == EGameResID::GOLD) || obj->ID == Obj::TREASURE_CHEST || obj->ID == Obj::CAMPFIRE || obj->ID == Obj::WATER_WHEEL) diff --git a/AI/Nullkiller/Engine/FuzzyHelper.cpp b/AI/Nullkiller/Engine/FuzzyHelper.cpp index e550c47ba..5252f89c3 100644 --- a/AI/Nullkiller/Engine/FuzzyHelper.cpp +++ b/AI/Nullkiller/Engine/FuzzyHelper.cpp @@ -24,7 +24,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) { //this one is not fuzzy anymore, just calculate weighted average - auto objectInfo = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance); + auto objectInfo = bank->getObjectHandler()->getObjectInfo(bank->appearance); CBankInfo * bankInfo = dynamic_cast(objectInfo.get()); @@ -161,10 +161,7 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj) } case Obj::PYRAMID: { - if(obj->subID == 0) - return estimateBankDanger(dynamic_cast(obj)); - else - return 0; + return estimateBankDanger(dynamic_cast(obj)); } default: return 0; diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 98ce1a86f..be3d87845 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -122,7 +122,7 @@ TResources getCreatureBankResources(const CGObjectInstance * target, const CGHer { //Fixme: unused variable hero - auto objectInfo = VLC->objtypeh->getHandlerFor(target->ID, target->subID)->getObjectInfo(target->appearance); + auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance); CBankInfo * bankInfo = dynamic_cast(objectInfo.get()); auto resources = bankInfo->getPossibleResourcesReward(); TResources result = TResources(); @@ -139,7 +139,7 @@ TResources getCreatureBankResources(const CGObjectInstance * target, const CGHer uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHeroInstance * hero) { - auto objectInfo = VLC->objtypeh->getHandlerFor(target->ID, target->subID)->getObjectInfo(target->appearance); + auto objectInfo = target->getObjectHandler()->getObjectInfo(target->appearance); CBankInfo * bankInfo = dynamic_cast(objectInfo.get()); auto creatures = bankInfo->getPossibleCreaturesReward(); uint64_t result = 0; @@ -467,14 +467,20 @@ float RewardEvaluator::getStrategicalValue(const CGObjectInstance * target) cons switch(target->ID) { case Obj::MINE: - return target->subID == GameResID(EGameResID::GOLD) + { + auto mine = dynamic_cast(target); + return mine->producedResource == EGameResID::GOLD ? 0.5f - : 0.4f * getTotalResourceRequirementStrength(target->subID) + 0.1f * getResourceRequirementStrength(target->subID); + : 0.4f * getTotalResourceRequirementStrength(mine->producedResource) + 0.1f * getResourceRequirementStrength(mine->producedResource); + } case Obj::RESOURCE: - return target->subID == GameResID(EGameResID::GOLD) + { + auto resource = dynamic_cast(target); + return resource->resourceID() == EGameResID::GOLD ? 0 - : 0.2f * getTotalResourceRequirementStrength(target->subID) + 0.4f * getResourceRequirementStrength(target->subID); + : 0.2f * getTotalResourceRequirementStrength(resource->resourceID()) + 0.4f * getResourceRequirementStrength(resource->resourceID()); + } case Obj::CREATURE_BANK: { @@ -626,12 +632,14 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG const int dailyIncomeMultiplier = 5; const float enemyArmyEliminationGoldRewardRatio = 0.2f; const int32_t heroEliminationBonus = GameConstants::HERO_GOLD_COST / 2; - auto isGold = target->subID == GameResID(EGameResID::GOLD); // TODO: other resorces could be sold but need to evaluate market power switch(target->ID) { case Obj::RESOURCE: - return isGold ? 600 : 100; + { + auto * res = dynamic_cast(target); + return res->resourceID() == GameResID::GOLD ? 600 : 100; + } case Obj::TREASURE_CHEST: return 1500; case Obj::WATER_WHEEL: @@ -640,7 +648,10 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG return dailyIncomeMultiplier * estimateTownIncome(ai->cb.get(), target, hero); case Obj::MINE: case Obj::ABANDONED_MINE: - return dailyIncomeMultiplier * (isGold ? 1000 : 75); + { + auto * mine = dynamic_cast(target); + return dailyIncomeMultiplier * (mine->producedResource == GameResID::GOLD ? 1000 : 75); + } case Obj::MYSTICAL_GARDEN: case Obj::WINDMILL: return 100; @@ -1005,7 +1016,7 @@ public: uint64_t RewardEvaluator::getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const { - if(ai->buildAnalyzer->hasAnyBuilding(town->subID, bi.id)) + if(ai->buildAnalyzer->hasAnyBuilding(town->getFaction(), bi.id)) return 0; auto creaturesToUpgrade = ai->armyManager->getTotalCreaturesAvailable(bi.baseCreatureID); diff --git a/AI/VCAI/AIUtility.h b/AI/VCAI/AIUtility.h index 64cf46d28..2b0fe415e 100644 --- a/AI/VCAI/AIUtility.h +++ b/AI/VCAI/AIUtility.h @@ -26,7 +26,6 @@ using crint3 = const int3 &; using crstring = const std::string &; using dwellingContent = std::pair>; -const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1; const int ACTUAL_RESOURCE_COUNT = 7; const int ALLOWED_ROAMING_HEROES = 8; diff --git a/AI/VCAI/FuzzyEngines.cpp b/AI/VCAI/FuzzyEngines.cpp index 91ba40139..f4702f3a7 100644 --- a/AI/VCAI/FuzzyEngines.cpp +++ b/AI/VCAI/FuzzyEngines.cpp @@ -406,7 +406,7 @@ float VisitObjEngine::evaluate(Goals::VisitObj & goal) else { MapObjectsEvaluator::getInstance().addObjectData(obj->ID, obj->subID, 0); - logGlobal->error("AI met object type it doesn't know - ID: " + std::to_string(obj->ID) + ", subID: " + std::to_string(obj->subID) + " - adding to database with value " + std::to_string(objValue)); + logGlobal->error("AI met object type it doesn't know - ID: %d, subID: %d - adding to database with value %d ", obj->ID, obj->subID, objValue); } setSharedFuzzyVariables(goal); diff --git a/AI/VCAI/FuzzyHelper.cpp b/AI/VCAI/FuzzyHelper.cpp index c125e2315..a47cbafa0 100644 --- a/AI/VCAI/FuzzyHelper.cpp +++ b/AI/VCAI/FuzzyHelper.cpp @@ -66,7 +66,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) { //this one is not fuzzy anymore, just calculate weighted average - auto objectInfo = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance); + auto objectInfo = bank->getObjectHandler()->getObjectInfo(bank->appearance); CBankInfo * bankInfo = dynamic_cast(objectInfo.get()); @@ -324,15 +324,8 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj, const VCAI * ai) case Obj::DRAGON_UTOPIA: case Obj::SHIPWRECK: //shipwreck case Obj::DERELICT_SHIP: //derelict ship - // case Obj::PYRAMID: - return estimateBankDanger(dynamic_cast(obj)); case Obj::PYRAMID: - { - if(obj->subID == 0) - return estimateBankDanger(dynamic_cast(obj)); - else - return 0; - } + return estimateBankDanger(dynamic_cast(obj)); default: return 0; } diff --git a/AI/VCAI/Goals/CollectRes.cpp b/AI/VCAI/Goals/CollectRes.cpp index 27e168fa6..d4513dbeb 100644 --- a/AI/VCAI/Goals/CollectRes.cpp +++ b/AI/VCAI/Goals/CollectRes.cpp @@ -43,10 +43,10 @@ TGoalVec CollectRes::getAllPossibleSubgoals() return resID == GameResID(EGameResID::GOLD); break; case Obj::RESOURCE: - return obj->subID == resID; + return dynamic_cast(obj)->resourceID() == GameResID(resID); break; case Obj::MINE: - return (obj->subID == resID && + return (dynamic_cast(obj)->producedResource == GameResID(resID) && (cb->getPlayerRelations(obj->tempOwner, ai->playerID) == PlayerRelations::ENEMIES)); //don't capture our mines break; case Obj::CAMPFIRE: diff --git a/AI/VCAI/Goals/GatherTroops.cpp b/AI/VCAI/Goals/GatherTroops.cpp index 4af9e7434..ed4e1a6c0 100644 --- a/AI/VCAI/Goals/GatherTroops.cpp +++ b/AI/VCAI/Goals/GatherTroops.cpp @@ -88,7 +88,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() } auto creature = VLC->creatures()->getByIndex(objid); - if(t->subID == creature->getFaction()) //TODO: how to force AI to build unupgraded creatures? :O + if(t->getFaction() == creature->getFaction()) //TODO: how to force AI to build unupgraded creatures? :O { auto tryFindCreature = [&]() -> std::optional> { diff --git a/AI/VCAI/Pathfinding/PathfindingManager.cpp b/AI/VCAI/Pathfinding/PathfindingManager.cpp index 3b56951ed..c983150bc 100644 --- a/AI/VCAI/Pathfinding/PathfindingManager.cpp +++ b/AI/VCAI/Pathfinding/PathfindingManager.cpp @@ -190,7 +190,7 @@ Goals::TSubgoal PathfindingManager::clearWayTo(HeroPtr hero, int3 firstTileToGet if(isBlockedBorderGate(firstTileToGet)) { //FIXME: this way we'll not visit gate and activate quest :? - return sptr(Goals::FindObj(Obj::KEYMASTER, cb->getTile(firstTileToGet)->visitableObjects.back()->subID)); + return sptr(Goals::FindObj(Obj::KEYMASTER, cb->getTile(firstTileToGet)->visitableObjects.back()->getObjTypeIndex())); } auto topObj = cb->getTopObj(firstTileToGet); diff --git a/AI/VCAI/ResourceManager.cpp b/AI/VCAI/ResourceManager.cpp index 8a97e430f..b69c4e9bc 100644 --- a/AI/VCAI/ResourceManager.cpp +++ b/AI/VCAI/ResourceManager.cpp @@ -59,19 +59,7 @@ TResources ResourceManager::estimateIncome() const if (obj->ID == Obj::MINE) { auto mine = dynamic_cast(obj); - switch (mine->producedResource.toEnum()) - { - case EGameResID::WOOD: - case EGameResID::ORE: - ret[obj->subID] += WOOD_ORE_MINE_PRODUCTION; - break; - case EGameResID::GOLD: - ret[EGameResID::GOLD] += GOLD_MINE_PRODUCTION; - break; - default: - ret[obj->subID] += RESOURCE_MINE_PRODUCTION; - break; - } + ret += mine->dailyIncome(); } } diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index ca3e5055e..19313633b 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1760,11 +1760,11 @@ void VCAI::addVisitableObj(const CGObjectInstance * obj) CGTeleport::addToChannel(knownTeleportChannels, teleportObj); } -const CGObjectInstance * VCAI::lookForArt(int aid) const +const CGObjectInstance * VCAI::lookForArt(ArtifactID aid) const { for(const CGObjectInstance * obj : ai->visitableObjs) { - if(obj->ID == Obj::ARTIFACT && obj->subID == aid) + if(obj->ID == Obj::ARTIFACT && dynamic_cast(obj)->getArtifact() == aid) return obj; } diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 8231003d9..5f327e5c3 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -251,7 +251,7 @@ public: void retrieveVisitableObjs(); virtual std::vector getFlaggedObjects() const; - const CGObjectInstance * lookForArt(int aid) const; + const CGObjectInstance * lookForArt(ArtifactID aid) const; bool isAccessible(const int3 & pos) const; HeroPtr getHeroWithGrail() const; diff --git a/CCallback.cpp b/CCallback.cpp index 753c443f0..78c8fe884 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -265,7 +265,7 @@ void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroIn assert(townOrTavern); assert(hero); - HireHero pack(HeroTypeID(hero->subID), townOrTavern->id); + HireHero pack(hero->getHeroType(), townOrTavern->id); pack.player = *player; sendRequest(&pack); } diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 5755b34ab..0a7861a3f 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -604,7 +604,7 @@ void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack) void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack) { CGHeroInstance *h = gs.map->heroesOnMap.back(); - if(h->subID != pack.hid) + if(h->getHeroType() != pack.hid) { logNetwork->error("Something wrong with hero recruited!"); } diff --git a/client/mapView/MapRendererContext.cpp b/client/mapView/MapRendererContext.cpp index d3c896029..07b5575eb 100644 --- a/client/mapView/MapRendererContext.cpp +++ b/client/mapView/MapRendererContext.cpp @@ -427,11 +427,7 @@ size_t MapRendererWorldViewContext::overlayImageIndex(const int3 & coordinates) if(!object->visitableAt(coordinates.x, coordinates.y)) continue; - ObjectPosInfo info; - info.pos = coordinates; - info.id = object->ID; - info.subId = object->subID; - info.owner = object->tempOwner; + ObjectPosInfo info(object); size_t iconIndex = selectOverlayImageForObject(info); diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index a0bc94cc8..8751dcf1e 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -920,7 +920,7 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow() void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades) { - std::vector> comps(1, std::make_shared(CComponent::building,town->subID,building)); + std::vector> comps(1, std::make_shared(CComponent::building,town->getFaction(),building)); std::string descr = town->town->buildings.find(building)->second->getDescriptionTranslated(); std::string hasNotProduced; std::string hasProduced; @@ -969,9 +969,9 @@ void CCastleBuildings::enterMagesGuild() { const StartInfo *si = LOCPLINT->cb->getStartInfo(); // it would be nice to find a way to move this hack to config/mapOverrides.json - if(si && si->campState && // We're in campaign, + if(si && si->campState && // We're in campaign, (si->campState->getFilename() == "DATA/YOG.H3C") && // which is "Birth of a Barbarian", - (hero->subID == 45)) // and the hero is Yog (based on Solmyr) + (hero->getHeroType() == 45)) // and the hero is Yog (based on Solmyr) { // "Yog has given up magic in all its forms..." LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[736]); diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index ef65e7912..2d9da6c4c 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -667,10 +667,10 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta title = (*CGI->townh)[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->getNameTranslated(); break; case EMarketMode::RESOURCE_ARTIFACT: - title = (*CGI->townh)[o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated(); + title = (*CGI->townh)[o->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated(); break; case EMarketMode::ARTIFACT_RESOURCE: - title = (*CGI->townh)[o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated(); + title = (*CGI->townh)[o->getFaction()]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->getNameTranslated(); // create image that copies part of background containing slot MISC_1 into position of slot MISC_5 // this is workaround for bug in H3 files where this slot for ragdoll on this screen is missing diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 003f1989c..760a036df 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -580,7 +580,7 @@ void CGameState::placeStartingHero(const PlayerColor & playerColor, const HeroTy CGHeroInstance * hero = dynamic_cast(obj); hero->ID = Obj::HERO; - hero->subID = heroTypeId; + hero->setHeroType(heroTypeId); hero->tempOwner = playerColor; hero->pos = townPos; diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 597bdd7eb..79ee3b3c1 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -256,7 +256,7 @@ void CGameStateCampaign::placeCampaignHeroes() assert(0); // should not happen } - hero->subID = heroTypeId; + hero->setHeroType(heroTypeId); gameState->map->getEditManager()->insertObject(hero); } } diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index ba916b3bb..1143b557b 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -290,6 +290,12 @@ HeroTypeID CGHeroInstance::getHeroType() const return HeroTypeID(getObjTypeIndex().getNum()); } +void CGHeroInstance::setHeroType(HeroTypeID heroType) +{ + assert(type == nullptr); + subID = heroType; +} + void CGHeroInstance::initHero(CRandomGenerator & rand, const HeroTypeID & SUBID) { subID = SUBID.getNum(); diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 0c141d1e0..a07ccff9c 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -232,6 +232,7 @@ public: ////////////////////////////////////////////////////////////////////////// HeroTypeID getHeroType() const; + void setHeroType(HeroTypeID type); void initHero(CRandomGenerator & rand); void initHero(CRandomGenerator & rand, const HeroTypeID & SUBID); diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 78a5079ee..19193d39f 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -129,6 +129,14 @@ bool CGMine::isAbandoned() const return (getObjTypeIndex() >= 7); } +ResourceSet CGMine::dailyIncome() const +{ + ResourceSet result; + result[producedResource] += defaultResProduction(); + + return result; +} + std::string CGMine::getObjectName() const { return VLC->generaltexth->translate("core.minename", getObjTypeIndex()); @@ -466,7 +474,7 @@ TeleportChannelID CGMonolith::findMeChannel(const std::vector & IDs, int Su if(!obj) continue; - const auto * teleportObj = dynamic_cast(cb->getObj(obj->id)); + const auto * teleportObj = dynamic_cast(cb->getObj(obj->id)); if(teleportObj && vstd::contains(IDs, teleportObj->ID) && teleportObj->subID == SubID) return teleportObj->channel; } diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index 3d0e4264f..5afd6f603 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -142,6 +142,7 @@ public: std::set abandonedMineResources; bool isAbandoned() const; + ResourceSet dailyIncome() const; private: void onHeroVisit(const CGHeroInstance * h) const override; diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 06abea28c..c5ddcc26c 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -1263,7 +1263,7 @@ void CMapLoaderJson::readObjects() std::sort(map->heroesOnMap.begin(), map->heroesOnMap.end(), [](const ConstTransitivePtr & a, const ConstTransitivePtr & b) { - return a->subID < b->subID; + return a->getObjTypeIndex() < b->getObjTypeIndex(); }); } diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 3e7dde286..147e99f81 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1487,6 +1487,7 @@ void NewObject::applyGs(CGameState *gs) CGObjectInstance * o = handler->create(); handler->configureObject(o, gs->getRandomGenerator()); + assert(o->ID == this->ID); if (ID == Obj::MONSTER) //probably more options will be needed { @@ -1514,8 +1515,6 @@ void NewObject::applyGs(CGameState *gs) o->appearance = handler->getTemplates().front(); o->id = ObjectInstanceID(static_cast(gs->map->objects.size())); - o->ID = ID; - o->subID = subID; o->pos = targetPos + o->getVisitableOffset(); gs->map->objects.emplace_back(o); diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index ee237bfe5..3887cb774 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -260,15 +260,18 @@ std::vector CPathfinderHelper::getTeleportExits(const PathNodeInfo & sourc teleportationExits.push_back(exit); } } - else if(options.useCastleGate - && (source.nodeObject->ID == Obj::TOWN && source.nodeObject->subID == ETownType::INFERNO - && source.objectRelations != PlayerRelations::ENEMIES)) + else if(options.useCastleGate && source.nodeObject->ID == Obj::TOWN && source.objectRelations != PlayerRelations::ENEMIES) { - /// TODO: Find way to reuse CPlayerSpecificInfoCallback::getTownsInfo - /// This may be handy if we allow to use teleportation to friendly towns - for(const auto & exit : getCastleGates(source)) + auto * town = dynamic_cast(source.nodeObject); + assert(town); + if (town && town->getFaction() == FactionID::INFERNO) { - teleportationExits.push_back(exit); + /// TODO: Find way to reuse CPlayerSpecificInfoCallback::getTownsInfo + /// This may be handy if we allow to use teleportation to friendly towns + for(const auto & exit : getCastleGates(source)) + { + teleportationExits.push_back(exit); + } } } diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index a2f26c03d..a54d54fa3 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -115,7 +115,7 @@ void Object::Instance::setAnyTemplate(CRandomGenerator & rng) { 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)); + throw rmgException(boost::str(boost::format("Did not find any graphics for object (%d,%d)") % dObject.ID % dObject.getObjTypeIndex())); dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng); dAccessibleAreaCache.clear(); @@ -128,7 +128,7 @@ void Object::Instance::setTemplate(TerrainId terrain, CRandomGenerator & rng) if (templates.empty()) { auto terrainName = VLC->terrainTypeHandler->getById(terrain)->getNameTranslated(); - throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % terrainName)); + throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.getObjTypeIndex() % terrainName)); } dObject.appearance = *RandomGeneratorUtil::nextItem(templates, rng); @@ -338,7 +338,7 @@ void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng) 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)); + throw rmgException(boost::str(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.getObjTypeIndex() % getPosition(true).toString() % terrainType)); } else { diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index 20dc751b2..ed3f42bb9 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -111,7 +111,7 @@ void TreasurePlacer::addAllPossibleObjects() auto factory = VLC->objtypeh->getHandlerFor(Obj::PRISON, 0); auto* obj = dynamic_cast(factory->create()); - obj->subID = hid; //will be initialized later + obj->setHeroType(hid); //will be initialized later obj->exp = generator.getConfig().prisonExperience[i]; obj->setOwner(PlayerColor::NEUTRAL); generator.banHero(hid); diff --git a/lib/spells/ViewSpellInt.cpp b/lib/spells/ViewSpellInt.cpp index 2b8e36ec7..1507d761a 100644 --- a/lib/spells/ViewSpellInt.cpp +++ b/lib/spells/ViewSpellInt.cpp @@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN ObjectPosInfo::ObjectPosInfo(const CGObjectInstance * obj): - pos(obj->visitablePos()), id(obj->ID), subId(obj->subID), owner(obj->tempOwner) + pos(obj->visitablePos()), id(obj->ID), subId(obj->getObjTypeIndex()), owner(obj->tempOwner) { } diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index 4912541de..0ba761307 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -217,7 +217,7 @@ void MapController::repairMap(CMap * map) const art->storedArtifact = a; } else - map->allowedArtifact.at(art->subID) = true; + map->allowedArtifact.at(art->getArtifact()) = true; } } } @@ -623,7 +623,7 @@ ModCompatibilityInfo MapController::modAssessmentMap(const CMap & map) if(obj->ID == Obj::HERO) continue; //stub! - auto handler = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID); + auto handler = obj->getObjectHandler(); auto modName = QString::fromStdString(handler->getJsonKey()).split(":").at(0).toStdString(); if(modName != "core") result[modName] = VLC->modh->getModInfo(modName).getVerificationInfo(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 8bda133e7..c702f35ee 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2315,7 +2315,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, auto isLibrary = isMageGuild ? false : t->town->buildings.at(buildingID)->subId == BuildingSubID::EBuildingSubID::LIBRARY; - if(isMageGuild || isLibrary || (t->subID == ETownType::CONFLUX && buildingID == BuildingID::GRAIL)) + if(isMageGuild || isLibrary || (t->getFaction() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL)) { if(t->visitingHero) giveSpells(t,t->visitingHero); @@ -3284,7 +3284,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n) if (!town->hasBuilt(i)) { buildStructure(town->id, i, true); - iw.components.emplace_back(Component::EComponentType::BUILDING, town->subID, i, 0); + iw.components.emplace_back(Component::EComponentType::BUILDING, town->getFaction(), i, 0); } } @@ -3430,7 +3430,7 @@ void CGameHandler::objectVisited(const CGObjectInstance * obj, const CGHeroInsta { using events::ObjectVisitStarted; - logGlobal->debug("%s visits %s (%d:%d)", h->nodeName(), obj->getObjectName(), obj->ID, obj->subID); + logGlobal->debug("%s visits %s (%d)", h->nodeName(), obj->getObjectName(), obj->ID); if (getVisitingHero(obj) != nullptr) { diff --git a/server/processors/HeroPoolProcessor.cpp b/server/processors/HeroPoolProcessor.cpp index f37f09f8a..eeb2ed73d 100644 --- a/server/processors/HeroPoolProcessor.cpp +++ b/server/processors/HeroPoolProcessor.cpp @@ -50,8 +50,8 @@ TavernHeroSlot HeroPoolProcessor::selectSlotForRole(const PlayerColor & player, // try to find "better" slot to overwrite // we want to avoid overwriting retreated heroes when tavern still has slot with random hero // as well as avoid overwriting surrendered heroes if we can overwrite retreated hero - auto roleLeft = heroesPool->getSlotRole(HeroTypeID(heroes[0]->subID)); - auto roleRight = heroesPool->getSlotRole(HeroTypeID(heroes[1]->subID)); + auto roleLeft = heroesPool->getSlotRole(heroes[0]->getHeroType()); + auto roleRight = heroesPool->getSlotRole(heroes[1]->getHeroType()); if (roleLeft > roleRight) return TavernHeroSlot::RANDOM; @@ -73,7 +73,7 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer sah.slotID = selectSlotForRole(color, sah.roleID); sah.player = color; - sah.hid.setNum(hero->subID); + sah.hid = hero->getHeroType(); gameHandler->sendAndApply(&sah); } @@ -84,7 +84,7 @@ void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroIns sah.slotID = selectSlotForRole(color, sah.roleID); sah.player = color; - sah.hid.setNum(hero->subID); + sah.hid = hero->getHeroType(); sah.army.clearSlots(); sah.army.setCreature(SlotID(0), hero->type->initialArmy.at(0).creature, 1); @@ -111,7 +111,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe if (newHero) { - sah.hid.setNum(newHero->subID); + sah.hid = newHero->getHeroType(); if (giveArmy) { @@ -193,7 +193,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy for(const auto & hero : recruitableHeroes) { - if(hero->subID == heroToRecruit) + if(hero->getHeroType() == heroToRecruit) recruitedHero = hero; } @@ -206,7 +206,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy HeroRecruited hr; hr.tid = mapObject->id; - hr.hid.setNum(recruitedHero->subID); + hr.hid = recruitedHero->getHeroType(); hr.player = player; hr.tile = recruitedHero->convertFromVisitablePos(targetPos ); if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->boat)