diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index bf289681c..99172b213 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -1454,7 +1454,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h) void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building) { - auto name = t->town->buildings.at(building)->getNameTranslated(); + auto name = t->getTown()->buildings.at(building)->getNameTranslated(); logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString()); cb->buildBuilding(t, building); //just do this; } diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 5c2a7f4a8..e2bbbb1fc 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -144,7 +144,7 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, for(auto & slot : sortedSlots) { - alignmentMap[slot.creature->getFaction()] += slot.power; + alignmentMap[slot.creature->getFactionID()] += slot.power; } std::set allowedFactions; @@ -178,7 +178,7 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, for(auto & slot : sortedSlots) { - if(vstd::contains(allowedFactions, slot.creature->getFaction())) + if(vstd::contains(allowedFactions, slot.creature->getFactionID())) { auto slotID = newArmyInstance.getSlotFor(slot.creature->getId()); diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 4496aec3f..55a1ebeaf 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -17,7 +17,7 @@ namespace NKAI void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo) { - auto townInfo = developmentInfo.town->town; + auto townInfo = developmentInfo.town->getTown(); auto creatures = townInfo->creatures; auto buildings = townInfo->getAllBuildings(); @@ -31,7 +31,7 @@ void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo) } } - for(int level = 0; level < developmentInfo.town->town->creatures.size(); level++) + for(int level = 0; level < developmentInfo.town->getTown()->creatures.size(); level++) { logAi->trace("Checking dwelling level %d", level); BuildingInfo nextToBuild = BuildingInfo(); @@ -82,7 +82,7 @@ void BuildAnalyzer::updateOtherBuildings(TownDevelopmentInfo & developmentInfo) { for(auto & buildingID : buildingSet) { - if(!developmentInfo.town->hasBuilt(buildingID) && developmentInfo.town->town->buildings.count(buildingID)) + if(!developmentInfo.town->hasBuilt(buildingID) && developmentInfo.town->getTown()->buildings.count(buildingID)) { developmentInfo.addBuildingToBuild(getBuildingOrPrerequisite(developmentInfo.town, buildingID)); @@ -198,7 +198,7 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( bool excludeDwellingDependencies) const { BuildingID building = toBuild; - auto townInfo = town->town; + auto townInfo = town->getTown(); const CBuilding * buildPtr = townInfo->buildings.at(building); const CCreature * creature = nullptr; @@ -327,7 +327,7 @@ bool BuildAnalyzer::hasAnyBuilding(int32_t alignment, BuildingID bid) const { for(auto tdi : developmentInfos) { - if(tdi.town->getFaction() == alignment && tdi.town->hasBuilt(bid)) + if(tdi.town->getFactionID() == alignment && tdi.town->hasBuilt(bid)) return true; } diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index f64fb4811..b6938ec1f 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -71,7 +71,7 @@ float HeroManager::evaluateSecSkill(SecondarySkill skill, const CGHeroInstance * float HeroManager::evaluateSpeciality(const CGHeroInstance * hero) const { - auto heroSpecial = Selector::source(BonusSource::HERO_SPECIAL, BonusSourceID(hero->type->getId())); + auto heroSpecial = Selector::source(BonusSource::HERO_SPECIAL, BonusSourceID(hero->getHeroTypeID())); auto secondarySkillBonus = Selector::targetSourceType()(BonusSource::SECONDARY_SKILL); auto specialSecondarySkillBonuses = hero->getBonuses(heroSpecial.And(secondarySkillBonus)); auto secondarySkillBonuses = hero->getBonuses(Selector::sourceTypeSel(BonusSource::SECONDARY_SKILL)); diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 2d5839040..8e20c4e54 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -1120,7 +1120,7 @@ public: uint64_t RewardEvaluator::getUpgradeArmyReward(const CGTownInstance * town, const BuildingInfo & bi) const { - if(ai->buildAnalyzer->hasAnyBuilding(town->getFaction(), bi.id)) + if(ai->buildAnalyzer->hasAnyBuilding(town->getFactionID(), bi.id)) return 0; auto creaturesToUpgrade = ai->armyManager->getTotalCreaturesAvailable(bi.baseCreatureID); diff --git a/AI/Nullkiller/Goals/BuildThis.cpp b/AI/Nullkiller/Goals/BuildThis.cpp index 4de43c060..414c8a03d 100644 --- a/AI/Nullkiller/Goals/BuildThis.cpp +++ b/AI/Nullkiller/Goals/BuildThis.cpp @@ -23,7 +23,7 @@ BuildThis::BuildThis(BuildingID Bid, const CGTownInstance * tid) : ElementarGoal(Goals::BUILD_STRUCTURE) { buildingInfo = BuildingInfo( - tid->town->buildings.at(Bid), + tid->getTown()->buildings.at(Bid), nullptr, CreatureID::NONE, tid, @@ -52,7 +52,7 @@ void BuildThis::accept(AIGateway * ai) if(cb->canBuildStructure(town, b) == EBuildingState::ALLOWED) { logAi->debug("Player %d will build %s in town of %s at %s", - ai->playerID, town->town->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString()); + ai->playerID, town->getTown()->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString()); cb->buildBuilding(town, b); return; diff --git a/AI/VCAI/BuildingManager.cpp b/AI/VCAI/BuildingManager.cpp index 202661c33..60d971086 100644 --- a/AI/VCAI/BuildingManager.cpp +++ b/AI/VCAI/BuildingManager.cpp @@ -23,13 +23,13 @@ bool BuildingManager::tryBuildThisStructure(const CGTownInstance * t, BuildingID return false; } - if (!vstd::contains(t->town->buildings, building)) + if (!vstd::contains(t->getTown()->buildings, building)) return false; // no such building in town if (t->hasBuilt(building)) //Already built? Shouldn't happen in general return true; - const CBuilding * buildPtr = t->town->buildings.at(building); + const CBuilding * buildPtr = t->getTown()->buildings.at(building); auto toBuild = buildPtr->requirements.getFulfillmentCandidates([&](const BuildingID & buildID) { @@ -51,7 +51,7 @@ bool BuildingManager::tryBuildThisStructure(const CGTownInstance * t, BuildingID for (const auto & buildID : toBuild) { - const CBuilding * b = t->town->buildings.at(buildID); + const CBuilding * b = t->getTown()->buildings.at(buildID); EBuildingState canBuild = cb->canBuildStructure(t, buildID); if (canBuild == EBuildingState::ALLOWED) @@ -220,7 +220,7 @@ bool BuildingManager::getBuildingOptions(const CGTownInstance * t) //at the end, try to get and build any extra buildings with nonstandard slots (for example HotA 3rd level dwelling) std::vector extraBuildings; - for (auto buildingInfo : t->town->buildings) + for (auto buildingInfo : t->getTown()->buildings) { if (buildingInfo.first > BuildingID::DWELL_UP2_FIRST) extraBuildings.push_back(buildingInfo.first); diff --git a/AI/VCAI/Goals/BuildThis.cpp b/AI/VCAI/Goals/BuildThis.cpp index ee1e3d41a..62e3a1649 100644 --- a/AI/VCAI/Goals/BuildThis.cpp +++ b/AI/VCAI/Goals/BuildThis.cpp @@ -56,7 +56,7 @@ TSubgoal BuildThis::whatToDoToAchieve() case EBuildingState::ALLOWED: case EBuildingState::NO_RESOURCES: { - auto res = town->town->buildings.at(BuildingID(bid))->resources; + auto res = town->getTown()->buildings.at(BuildingID(bid))->resources; return ai->ah->whatToDo(res, iAmElementar()); //realize immediately or gather resources } break; diff --git a/AI/VCAI/Goals/GatherTroops.cpp b/AI/VCAI/Goals/GatherTroops.cpp index 275bef9f5..50b8fdce5 100644 --- a/AI/VCAI/Goals/GatherTroops.cpp +++ b/AI/VCAI/Goals/GatherTroops.cpp @@ -88,13 +88,13 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() } auto creature = VLC->creatures()->getByIndex(objid); - if(t->getFaction() == creature->getFaction()) //TODO: how to force AI to build unupgraded creatures? :O + if(t->getFactionID() == creature->getFactionID()) //TODO: how to force AI to build unupgraded creatures? :O { auto tryFindCreature = [&]() -> std::optional> { - if(vstd::isValidIndex(t->town->creatures, creature->getLevel() - 1)) + if(vstd::isValidIndex(t->getTown()->creatures, creature->getLevel() - 1)) { - auto itr = t->town->creatures.begin(); + auto itr = t->getTown()->creatures.begin(); std::advance(itr, creature->getLevel() - 1); return make_optional(*itr); } @@ -109,7 +109,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() if(upgradeNumber < 0) continue; - BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->town->creatures.size()); + BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->getTown()->creatures.size()); if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->getFullRecruitCost())) //this assumes only creatures with dwellings are assigned to faction { solutions.push_back(sptr(BuyArmy(t, creature->getAIValue() * this->value).setobjid(objid))); diff --git a/AI/VCAI/MapObjectsEvaluator.cpp b/AI/VCAI/MapObjectsEvaluator.cpp index 5536d8fd9..e430c1f08 100644 --- a/AI/VCAI/MapObjectsEvaluator.cpp +++ b/AI/VCAI/MapObjectsEvaluator.cpp @@ -69,7 +69,7 @@ std::optional MapObjectsEvaluator::getObjectValue(const CGObjectInstance * { //special case handling: in-game heroes have hero ID as object subID, but when reading configs available hero object subID's are hero classes auto hero = dynamic_cast(obj); - return getObjectValue(obj->ID, hero->type->heroClass->getIndex()); + return getObjectValue(obj->ID, hero->getHeroClassID()); } else if(obj->ID == Obj::PRISON) { diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index c72a2a655..f9ebb1657 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1994,7 +1994,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h) void VCAI::buildStructure(const CGTownInstance * t, BuildingID building) { - auto name = t->town->buildings.at(building)->getNameTranslated(); + auto name = t->getTown()->buildings.at(building)->getNameTranslated(); logAi->debug("Player %d will build %s in town of %s at %s", ai->playerID, name, t->getNameTranslated(), t->anchorPos().toString()); cb->buildBuilding(t, building); //just do this; } @@ -2081,7 +2081,7 @@ void VCAI::tryRealize(Goals::BuildThis & g) if (cb->canBuildStructure(t, b) == EBuildingState::ALLOWED) { logAi->debug("Player %d will build %s in town of %s at %s", - playerID, t->town->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->anchorPos().toString()); + playerID, t->getTown()->buildings.at(b)->getNameTranslated(), t->getNameTranslated(), t->anchorPos().toString()); cb->buildBuilding(t, b); throw goalFulfilledException(sptr(g)); } diff --git a/CCallback.cpp b/CCallback.cpp index 3eeb6d238..72b6e8b78 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -319,7 +319,7 @@ void CCallback::recruitHero(const CGObjectInstance *townOrTavern, const CGHeroIn assert(townOrTavern); assert(hero); - HireHero pack(hero->getHeroType(), townOrTavern->id, nextHero); + HireHero pack(hero->getHeroTypeID(), townOrTavern->id, nextHero); pack.player = *player; sendRequest(pack); } diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 572924c09..6133cdd64 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1138,7 +1138,7 @@ void CPlayerInterface::showMapObjectSelectDialog(QueryID askID, const Component const CGTownInstance * t = dynamic_cast(cb->getObj(obj)); if(t) { - auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE); + auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->getTown()->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE); image->scaleTo(Point(35, 23)); images.push_back(image); } diff --git a/client/ClientCommandManager.cpp b/client/ClientCommandManager.cpp index a2a7176ef..775c9b806 100644 --- a/client/ClientCommandManager.cpp +++ b/client/ClientCommandManager.cpp @@ -453,7 +453,7 @@ void ClientCommandManager::handleTellCommand(std::istringstream& singleWordBuffe if(what == "hs") { for(const CGHeroInstance* h : LOCPLINT->cb->getHeroesInfo()) - if(h->type->getIndex() == id1) + if(h->getHeroTypeID().getNum() == id1) if(const CArtifactInstance* a = h->getArt(ArtifactPosition(id2))) printCommandMessage(a->nodeName()); } diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index d403120a7..91c8833b2 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -671,7 +671,7 @@ void ApplyClientNetPackVisitor::visitSetHeroesInTown(SetHeroesInTown & pack) void ApplyClientNetPackVisitor::visitHeroRecruited(HeroRecruited & pack) { CGHeroInstance *h = gs.map->heroesOnMap.back(); - if(h->getHeroType() != pack.hid) + if(h->getHeroTypeID() != pack.hid) { logNetwork->error("Something wrong with hero recruited!"); } diff --git a/client/adventureMap/CList.cpp b/client/adventureMap/CList.cpp index 5c46a510a..e730224b4 100644 --- a/client/adventureMap/CList.cpp +++ b/client/adventureMap/CList.cpp @@ -432,7 +432,7 @@ std::shared_ptr CTownList::CTownItem::genSelection() void CTownList::CTownItem::update() { - size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; + size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; picture->setFrame(iconIndex + 2); redraw(); diff --git a/client/battle/BattleInterfaceClasses.cpp b/client/battle/BattleInterfaceClasses.cpp index 919118407..5cf6aa340 100644 --- a/client/battle/BattleInterfaceClasses.cpp +++ b/client/battle/BattleInterfaceClasses.cpp @@ -389,13 +389,13 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her { AnimationPath animationPath; - if(!hero->type->battleImage.empty()) - animationPath = hero->type->battleImage; + if(!hero->getHeroType()->battleImage.empty()) + animationPath = hero->getHeroType()->battleImage; else if(hero->gender == EHeroGender::FEMALE) - animationPath = hero->type->heroClass->imageBattleFemale; + animationPath = hero->getHeroClass()->imageBattleFemale; else - animationPath = hero->type->heroClass->imageBattleMale; + animationPath = hero->getHeroClass()->imageBattleMale; animation = GH.renderHandler().loadAnimation(animationPath, EImageBlitMode::ALPHA); @@ -1027,7 +1027,7 @@ void StackQueue::update() int32_t StackQueue::getSiegeShooterIconID() { - return owner.siegeController->getSiegedTown()->town->faction->getIndex(); + return owner.siegeController->getSiegedTown()->getFactionID().getNum(); } std::optional StackQueue::getHoveredUnitIdIfAny() const diff --git a/client/battle/BattleSiegeController.cpp b/client/battle/BattleSiegeController.cpp index f64bc8ac4..2f3c4df5e 100644 --- a/client/battle/BattleSiegeController.cpp +++ b/client/battle/BattleSiegeController.cpp @@ -58,14 +58,14 @@ ImagePath BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual }; }; - const std::string & prefix = town->town->clientInfo.siegePrefix; + const std::string & prefix = town->getTown()->clientInfo.siegePrefix; std::string addit = std::to_string(getImageIndex()); switch(what) { case EWallVisual::BACKGROUND_WALL: { - auto faction = town->town->faction->getIndex(); + auto faction = town->getFactionID(); if (faction == ETownType::RAMPART || faction == ETownType::NECROPOLIS || faction == ETownType::DUNGEON || faction == ETownType::STRONGHOLD) return ImagePath::builtinTODO(prefix + "TPW1.BMP"); @@ -111,7 +111,7 @@ ImagePath BattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisual void BattleSiegeController::showWallPiece(Canvas & canvas, EWallVisual::EWallVisual what) { - auto & ci = town->town->clientInfo; + auto & ci = town->getTown()->clientInfo; auto const & pos = ci.siegePositions[what]; if ( wallPieceImages[what] && pos.isValid()) @@ -120,7 +120,7 @@ void BattleSiegeController::showWallPiece(Canvas & canvas, EWallVisual::EWallVis ImagePath BattleSiegeController::getBattleBackgroundName() const { - const std::string & prefix = town->town->clientInfo.siegePrefix; + const std::string & prefix = town->getTown()->clientInfo.siegePrefix; return ImagePath::builtinTODO(prefix + "BACK.BMP"); } @@ -130,8 +130,8 @@ bool BattleSiegeController::getWallPieceExistence(EWallVisual::EWallVisual what) switch (what) { - case EWallVisual::MOAT: return fortifications.hasMoat && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT).isValid(); - case EWallVisual::MOAT_BANK: return fortifications.hasMoat && town->town->clientInfo.siegePositions.at(EWallVisual::MOAT_BANK).isValid(); + case EWallVisual::MOAT: return fortifications.hasMoat && town->getTown()->clientInfo.siegePositions.at(EWallVisual::MOAT).isValid(); + case EWallVisual::MOAT_BANK: return fortifications.hasMoat && town->getTown()->clientInfo.siegePositions.at(EWallVisual::MOAT_BANK).isValid(); case EWallVisual::KEEP_BATTLEMENT: return fortifications.citadelHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::KEEP) != EWallState::DESTROYED; case EWallVisual::UPPER_BATTLEMENT: return fortifications.upperTowerHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::UPPER_TOWER) != EWallState::DESTROYED; case EWallVisual::BOTTOM_BATTLEMENT: return fortifications.lowerTowerHealth > 0 && owner.getBattle()->battleGetWallState(EWallPart::BOTTOM_TOWER) != EWallState::DESTROYED; @@ -218,8 +218,8 @@ Point BattleSiegeController::getTurretCreaturePosition( BattleHex position ) con if (posID != 0) { return { - town->town->clientInfo.siegePositions[posID].x, - town->town->clientInfo.siegePositions[posID].y + town->getTown()->clientInfo.siegePositions[posID].x, + town->getTown()->clientInfo.siegePositions[posID].y }; } diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index e7e7c655d..14cc7b14d 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -468,8 +468,8 @@ void CInteractableTownTooltip::init(const CGTownInstance * town) LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE); } }, [town]{ - if(!town->town->faction->getDescriptionTranslated().empty()) - CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated()); + if(!town->getFaction()->getDescriptionTranslated().empty()) + CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated()); }); fastMarket = std::make_shared(Rect(143, 31, 30, 34), []() { @@ -532,8 +532,7 @@ CreatureTooltip::CreatureTooltip(Point pos, const CGCreature * creature) { OBJECT_CONSTRUCTION; - auto creatureID = creature->getCreature(); - int32_t creatureIconIndex = CGI->creatures()->getById(creatureID)->getIconIndex(); + int32_t creatureIconIndex = creature->getCreature()->getIconIndex(); creatureImage = std::make_shared(AnimationPath::builtin("TWCRPORT"), creatureIconIndex); creatureImage->center(Point(parent->pos.x + parent->pos.w / 2, parent->pos.y + creatureImage->pos.h / 2 + 11)); @@ -633,7 +632,7 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A pos.x+=x; pos.y+=y; - auto faction = cre->getFaction(); + auto faction = cre->getFactionID(); assert(CGI->townh->size() > faction); diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 9729bd73c..aea486688 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -82,7 +82,7 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town // special animation frame manipulation for castle shipyard with and without ship // done due to .def used in special way, not to animate building - first image is for shipyard without citadel moat, 2nd image is for including moat - if(Town->town->faction->getId() == FactionID::CASTLE && Str->building && + if(Town->getFactionID() == FactionID::CASTLE && Str->building && (Str->building->bid == BuildingID::SHIPYARD || Str->building->bid == BuildingID::SHIP)) { if(Town->hasBuilt(BuildingID::CITADEL)) @@ -107,7 +107,7 @@ const CBuilding * CBuildingRect::getBuilding() return nullptr; if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes) - return town->town->buildings.at(str->building->getBase()); + return town->getTown()->buildings.at(str->building->getBase()); return str->building; } @@ -156,7 +156,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition) return; BuildingID bid = getBuilding()->bid; - const CBuilding *bld = town->town->buildings.at(bid); + const CBuilding *bld = town->getTown()->buildings.at(bid); if (bid < BuildingID::DWELL_FIRST) { CRClickPopup::createAndPush(CInfoWindow::genText(bld->getNameTranslated(), bld->getDescriptionTranslated()), @@ -235,10 +235,10 @@ std::string CBuildingRect::getSubtitle()//hover text for building int bid = getBuilding()->bid; if (bid<30)//non-dwellings - only building name - return town->town->buildings.at(getBuilding()->bid)->getNameTranslated(); + return town->getTown()->buildings.at(getBuilding()->bid)->getNameTranslated(); else//dwellings - recruit %creature% { - auto & availableCreatures = town->creatures[(bid-30)%town->town->creatures.size()].second; + auto & availableCreatures = town->creatures[(bid-30)%town->getTown()->creatures.size()].second; if(availableCreatures.size()) { int creaID = availableCreatures.back();//taking last of available creatures @@ -566,7 +566,7 @@ CCastleBuildings::CCastleBuildings(const CGTownInstance* Town): { OBJECT_CONSTRUCTION; - background = std::make_shared(town->town->clientInfo.townBackground); + background = std::make_shared(town->getTown()->clientInfo.townBackground); background->needRefresh = true; background->getSurface()->setBlitMode(EImageBlitMode::OPAQUE); pos.w = background->pos.w; @@ -602,7 +602,7 @@ void CCastleBuildings::recreate() } } - for(const CStructure * structure : town->town->clientInfo.structures) + for(const CStructure * structure : town->getTown()->clientInfo.structures) { if(!structure->building) { @@ -617,7 +617,7 @@ void CCastleBuildings::recreate() for(auto & entry : groups) { - const CBuilding * build = town->town->buildings.at(entry.first); + const CBuilding * build = town->getTown()->buildings.at(entry.first); const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b) { @@ -648,7 +648,7 @@ void CCastleBuildings::recreate() void CCastleBuildings::addBuilding(BuildingID building) { //FIXME: implement faster method without complete recreation of town - BuildingID base = town->town->buildings.at(building)->getBase(); + BuildingID base = town->getTown()->buildings.at(building)->getBase(); recreate(); @@ -687,7 +687,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) BuildingID buildingToEnter = building; for(;;) { - const CBuilding *b = town->town->buildings.find(buildingToEnter)->second; + const CBuilding *b = town->getTown()->buildings.find(buildingToEnter)->second; if (buildingTryActivateCustomUI(buildingToEnter, building)) return; @@ -705,7 +705,7 @@ void CCastleBuildings::buildingClicked(BuildingID building) bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, BuildingID buildingTarget) { logGlobal->trace("You've clicked on %d", (int)buildingToTest.toEnum()); - const CBuilding *b = town->town->buildings.at(buildingToTest); + const CBuilding *b = town->getTown()->buildings.at(buildingToTest); if (town->getWarMachineInBuilding(buildingToTest).hasValue()) { @@ -744,7 +744,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu } } - if (town->rewardableBuildings.count(buildingToTest) && town->town->buildings.at(buildingToTest)->manualHeroVisit) + if (town->rewardableBuildings.count(buildingToTest) && town->getTown()->buildings.at(buildingToTest)->manualHeroVisit) { enterRewardable(buildingToTest); return true; @@ -820,10 +820,10 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu return false; case BuildingSubID::PORTAL_OF_SUMMONING: - if (town->creatures[town->town->creatures.size()].second.empty())//No creatures + if (town->creatures[town->getTown()->creatures.size()].second.empty())//No creatures LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]); else - enterDwelling(town->town->creatures.size()); + enterDwelling(town->getTown()->creatures.size()); return true; case BuildingSubID::BANK: @@ -850,7 +850,7 @@ void CCastleBuildings::enterRewardable(BuildingID building) { MetaString message; message.appendTextID("core.genrltxt.273"); // only visiting heroes may visit %s - message.replaceTextID(town->town->buildings.at(building)->getNameTextID()); + message.replaceTextID(town->getTown()->buildings.at(building)->getNameTextID()); LOCPLINT->showInfoDialog(message.toString()); } @@ -868,7 +868,7 @@ void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactI const CGHeroInstance *hero = town->visitingHero; if(!hero) { - LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(building)->second->getNameTranslated())); + LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->getTown()->buildings.find(building)->second->getNameTranslated())); return; } auto art = artifactID.toArtifact(); @@ -897,8 +897,8 @@ void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactI void CCastleBuildings::enterBuilding(BuildingID building) { - std::vector> comps(1, std::make_shared(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), building))); - LOCPLINT->showInfoDialog( town->town->buildings.find(building)->second->getDescriptionTranslated(), comps); + std::vector> comps(1, std::make_shared(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), building))); + LOCPLINT->showInfoDialog( town->getTown()->buildings.find(building)->second->getDescriptionTranslated(), comps); } void CCastleBuildings::enterCastleGate() @@ -915,20 +915,20 @@ void CCastleBuildings::enterCastleGate() { const CGTownInstance *t = Town; if (t->id != this->town->id && t->visitingHero == nullptr && //another town, empty and this is - t->town->faction->getId() == town->town->faction->getId() && //the town of the same faction + t->getFactionID() == town->getFactionID() && //the town of the same faction t->hasBuilt(BuildingSubID::CASTLE_GATE)) //and the town has a castle gate { availableTowns.push_back(t->id.getNum());//add to the list if(settings["general"]["enableUiEnhancements"].Bool()) { - auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->town->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE); + auto image = GH.renderHandler().loadImage(AnimationPath::builtin("ITPA"), t->getTown()->clientInfo.icons[t->hasFort()][false] + 2, 0, EImageBlitMode::OPAQUE); image->scaleTo(Point(35, 23)); images.push_back(image); } } } - auto gateIcon = std::make_shared(town->town->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window + auto gateIcon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window auto wnd = std::make_shared(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1), 0, images); wnd->onPopup = [availableTowns](int index) { CRClickPopup::createAndPush(LOCPLINT->cb->getObjInstance(ObjectInstanceID(availableTowns[index])), GH.getCursorPosition()); }; @@ -940,7 +940,7 @@ void CCastleBuildings::enterDwelling(int level) if (level < 0 || level >= town->creatures.size() || town->creatures[level].second.empty()) { assert(0); - logGlobal->error("Attempt to enter into invalid dwelling of level %d in town %s (%s)", level, town->getNameTranslated(), town->town->faction->getNameTranslated()); + logGlobal->error("Attempt to enter into invalid dwelling of level %d in town %s (%s)", level, town->getNameTranslated(), town->getFaction()->getNameTranslated()); return; } @@ -954,8 +954,8 @@ void CCastleBuildings::enterDwelling(int level) void CCastleBuildings::enterToTheQuickRecruitmentWindow() { const auto beginIt = town->creatures.cbegin(); - const auto afterLastIt = town->creatures.size() > town->town->creatures.size() - ? std::next(beginIt, town->town->creatures.size()) + const auto afterLastIt = town->creatures.size() > town->getTown()->creatures.size() + ? std::next(beginIt, town->getTown()->creatures.size()) : town->creatures.cend(); const auto hasSomeoneToRecruit = std::any_of(beginIt, afterLastIt, [](const auto & creatureInfo) { return creatureInfo.first > 0; }); @@ -967,8 +967,8 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow() void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades) { - std::vector> comps(1, std::make_shared(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), building))); - std::string descr = town->town->buildings.find(building)->second->getDescriptionTranslated(); + std::vector> comps(1, std::make_shared(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), building))); + std::string descr = town->getTown()->buildings.find(building)->second->getDescriptionTranslated(); std::string hasNotProduced; std::string hasProduced; @@ -977,10 +977,10 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID: bool isMysticPondOrItsUpgrade = subID == BuildingSubID::MYSTIC_POND || (upgrades != BuildingID::NONE - && town->town->buildings.find(BuildingID(upgrades))->second->subId == BuildingSubID::MYSTIC_POND); + && town->getTown()->buildings.find(BuildingID(upgrades))->second->subId == BuildingSubID::MYSTIC_POND); if(upgrades != BuildingID::NONE) - descr += "\n\n"+town->town->buildings.find(BuildingID(upgrades))->second->getDescriptionTranslated(); + descr += "\n\n"+town->getTown()->buildings.find(BuildingID(upgrades))->second->getDescriptionTranslated(); if(isMysticPondOrItsUpgrade) //for vanila Rampart like towns { @@ -1056,7 +1056,7 @@ void CCastleBuildings::enterTownHall() void CCastleBuildings::openMagesGuild() { - auto mageGuildBackground = LOCPLINT->castleInt->town->town->clientInfo.guildBackground; + auto mageGuildBackground = LOCPLINT->castleInt->town->getTown()->clientInfo.guildBackground; GH.windows().createAndPushWindow(LOCPLINT->castleInt, mageGuildBackground); } @@ -1247,7 +1247,7 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance * Town, bool townH return;//FIXME: suspicious statement, fix or comment picture = std::make_shared(AnimationPath::builtin("ITMCL.DEF"), town->fortLevel()-1); } - building = town->town->buildings.at(BuildingID(buildID)); + building = town->getTown()->buildings.at(BuildingID(buildID)); pos = picture->pos; } @@ -1322,7 +1322,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst recreateIcons(); if (!from) adventureInt->onAudioPaused(); - CCS->musich->playMusicFromSet("faction", town->town->faction->getJsonKey(), true, false); + CCS->musich->playMusicFromSet("faction", town->getFaction()->getJsonKey(), true, false); } CCastleInterface::~CCastleInterface() @@ -1403,7 +1403,7 @@ void CCastleInterface::removeBuilding(BuildingID bid) void CCastleInterface::recreateIcons() { OBJECT_CONSTRUCTION; - size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; + size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; icon->setFrame(iconIndex); TResources townIncome = town->dailyIncome(); @@ -1425,8 +1425,8 @@ void CCastleInterface::recreateIcons() if(town->hasBuilt(BuildingID::TAVERN)) LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE); }, [this]{ - if(!town->town->faction->getDescriptionTranslated().empty()) - CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated()); + if(!town->getFaction()->getDescriptionTranslated().empty()) + CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated()); }); creainfo.clear(); @@ -1527,7 +1527,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance * -1, -1, -1, 0, 0, 1, 2, -1, 1, 1, -1, -1 }; - icon = std::make_shared(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2); + icon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, building->bid, 0, 2, 2); header = std::make_shared(AnimationPath::builtin("TPTHBAR"), panelIndex[static_cast(state)], 0, 1, 73); if(iconIndex[static_cast(state)] >=0) mark = std::make_shared(AnimationPath::builtin("TPTHCHK"), iconIndex[static_cast(state)], 0, 136, 56); @@ -1569,7 +1569,7 @@ void CHallInterface::CBuildingBox::showPopupWindow(const Point & cursorPosition) } CHallInterface::CHallInterface(const CGTownInstance * Town): - CWindowObject(PLAYER_COLORED | BORDERED, Town->town->clientInfo.hallBackground), + CWindowObject(PLAYER_COLORED | BORDERED, Town->getTown()->clientInfo.hallBackground), town(Town) { OBJECT_CONSTRUCTION; @@ -1581,10 +1581,10 @@ CHallInterface::CHallInterface(const CGTownInstance * Town): auto statusbarBackground = std::make_shared(background->getSurface(), barRect, 5, 556); statusbar = CGStatusBar::create(statusbarBackground); - title = std::make_shared(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->town->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated()); + title = std::make_shared(399, 12, FONT_MEDIUM, ETextAlignment::CENTER, Colors::WHITE, town->getTown()->buildings.at(BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL))->getNameTranslated()); exit = std::make_shared(Point(748, 556), AnimationPath::builtin("TPMAGE1.DEF"), CButton::tooltip(CGI->generaltexth->hcommands[8]), [&](){close();}, EShortcut::GLOBAL_RETURN); - auto & boxList = town->town->clientInfo.hallSlots; + auto & boxList = town->getTown()->clientInfo.hallSlots; boxes.resize(boxList.size()); for(size_t row=0; rowwarn("Invalid building ID found in hallSlots of town '%s'", town->town->faction->getJsonKey() ); + logMod->warn("Invalid building ID found in hallSlots of town '%s'", town->getFaction()->getJsonKey() ); continue; } - const CBuilding * current = town->town->buildings.at(buildingID); + const CBuilding * current = town->getTown()->buildings.at(buildingID); if(town->hasBuilt(buildingID)) { building = current; @@ -1629,7 +1629,7 @@ CBuildWindow::CBuildWindow(const CGTownInstance *Town, const CBuilding * Buildin { OBJECT_CONSTRUCTION; - icon = std::make_shared(town->town->clientInfo.buildingsIcons, building->bid, 0, 125, 50); + icon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, building->bid, 0, 125, 50); auto statusbarBackground = std::make_shared(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26); statusbar = CGStatusBar::create(statusbarBackground); @@ -1711,7 +1711,7 @@ std::string CBuildWindow::getTextForState(EBuildingState state) { auto toStr = [&](const BuildingID build) -> std::string { - return town->town->buildings.at(build)->getNameTranslated(); + return town->getTown()->buildings.at(build)->getNameTranslated(); }; ret = CGI->generaltexth->allTexts[52]; @@ -1721,7 +1721,7 @@ std::string CBuildWindow::getTextForState(EBuildingState state) case EBuildingState::MISSING_BASE: { std::string msg = CGI->generaltexth->translate("vcmi.townHall.missingBase"); - ret = boost::str(boost::format(msg) % town->town->buildings.at(building->upgrade)->getNameTranslated()); + ret = boost::str(boost::format(msg) % town->getTown()->buildings.at(building->upgrade)->getNameTranslated()); break; } } @@ -1780,11 +1780,11 @@ CFortScreen::CFortScreen(const CGTownInstance * town): { OBJECT_CONSTRUCTION; ui32 fortSize = static_cast(town->creatures.size()); - if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty()) + if(fortSize > town->getTown()->creatures.size() && town->creatures.back().second.empty()) fortSize--; fortSize = std::min(fortSize, static_cast(GameConstants::CREATURES_PER_TOWN)); // for 8 creatures + portal of summoning - const CBuilding * fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6)); + const CBuilding * fortBuilding = town->getTown()->buildings.at(BuildingID(town->fortLevel()+6)); title = std::make_shared(400, 12, FONT_BIG, ETextAlignment::CENTER, Colors::WHITE, fortBuilding->getNameTranslated()); std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->getNameTranslated()); @@ -1810,7 +1810,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town): for(ui32 i=0; itown->creatures.size()) + if(fortSize == town->getTown()->creatures.size()) { BuildingID dwelling = BuildingID::getDwellingFromLevel(i, 1); @@ -1839,7 +1839,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town): ImagePath CFortScreen::getBgName(const CGTownInstance * town) { ui32 fortSize = static_cast(town->creatures.size()); - if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty()) + if(fortSize > town->getTown()->creatures.size() && town->creatures.back().second.empty()) fortSize--; fortSize = std::min(fortSize, static_cast(GameConstants::CREATURES_PER_TOWN)); // for 8 creatures + portal of summoning @@ -1877,7 +1877,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance * if(getMyBuilding() != nullptr) { - buildingIcon = std::make_shared(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21); + buildingIcon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21); buildingName = std::make_shared(78, 101, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, getMyBuilding()->getNameTranslated(), 152); if(town->hasBuilt(getMyBuilding()->bid)) @@ -1913,8 +1913,8 @@ const CCreature * CFortScreen::RecruitArea::getMyCreature() { if(!town->creatures.at(level).second.empty()) // built return town->creatures.at(level).second.back().toCreature(); - if(!town->town->creatures.at(level).empty()) // there are creatures on this level - return town->town->creatures.at(level).front().toCreature(); + if(!town->getTown()->creatures.at(level).empty()) // there are creatures on this level + return town->getTown()->creatures.at(level).front().toCreature(); return nullptr; } @@ -1922,17 +1922,17 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding() { BuildingID myID = BuildingID(BuildingID::getDwellingFromLevel(level, 0)); - if (level == town->town->creatures.size()) - return town->town->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING); + if (level == town->getTown()->creatures.size()) + return town->getTown()->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING); - if (!town->town->buildings.count(myID)) + if (!town->getTown()->buildings.count(myID)) return nullptr; - const CBuilding * build = town->town->buildings.at(myID); - while (town->town->buildings.count(myID)) + const CBuilding * build = town->getTown()->buildings.at(myID); + while (town->getTown()->buildings.count(myID)) { if (town->hasBuilt(myID)) - build = town->town->buildings.at(myID); + build = town->getTown()->buildings.at(myID); BuildingID::advanceDwelling(myID); } @@ -1972,7 +1972,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner, const ImagePath & i { OBJECT_CONSTRUCTION; - window = std::make_shared(owner->town->town->clientInfo.guildWindow, 332, 76); + window = std::make_shared(owner->town->getTown()->clientInfo.guildWindow, 332, 76); resdatabar = std::make_shared(); resdatabar->moveBy(pos.topLeft(), true); @@ -2007,7 +2007,7 @@ void CMageGuildScreen::updateSpells(ObjectInstanceID tID) const CGTownInstance * town = LOCPLINT->cb->getTown(townId); - for(size_t i=0; itown->mageLevel; i++) + for(size_t i=0; igetTown()->mageLevel; i++) { size_t spellCount = town->spellsAtLevel((int)i+1,false); //spell at level with -1 hmmm? for(size_t j=0; jsecSkills.size(); ++m) secSkillIcons[leftRight].push_back(std::make_shared(AnimationPath::builtin("SECSK32"), 0, 0, 32 + 36 * m + 454 * leftRight, qeLayout ? 83 : 88)); - specImages[leftRight] = std::make_shared(AnimationPath::builtin("UN32"), hero->type->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45); + specImages[leftRight] = std::make_shared(AnimationPath::builtin("UN32"), hero->getHeroType()->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45); expImages[leftRight] = std::make_shared(AnimationPath::builtin("PSKIL32"), 4, 0, 103 + 490 * leftRight, qeLayout ? 41 : 45); expValues[leftRight] = std::make_shared(119 + 490 * leftRight, qeLayout ? 66 : 71, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE); @@ -151,7 +151,7 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, specialtyAreas[b] = std::make_shared(); specialtyAreas[b]->pos = Rect(Point(pos.x + 69 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32)); specialtyAreas[b]->hoverText = CGI->generaltexth->heroscrn[27]; - specialtyAreas[b]->text = hero->type->getSpecialtyDescriptionTranslated(); + specialtyAreas[b]->text = hero->getHeroType()->getSpecialtyDescriptionTranslated(); experienceAreas[b] = std::make_shared(); experienceAreas[b]->pos = Rect(Point(pos.x + 105 + 490 * b, pos.y + (qeLayout ? 41 : 45)), Point(32, 32)); diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 36dd52d80..809f937f0 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -184,9 +184,9 @@ void CHeroWindow::update() name->setText(curHero->getNameTranslated()); title->setText((boost::format(CGI->generaltexth->allTexts[342]) % curHero->level % curHero->getClassNameTranslated()).str()); - specArea->text = curHero->type->getSpecialtyDescriptionTranslated(); - specImage->setFrame(curHero->type->imageIndex); - specName->setText(curHero->type->getSpecialtyNameTranslated()); + specArea->text = curHero->getHeroType()->getSpecialtyDescriptionTranslated(); + specImage->setFrame(curHero->getHeroType()->imageIndex); + specName->setText(curHero->getHeroType()->getSpecialtyNameTranslated()); tacticsButton = std::make_shared(Point(539, 483), AnimationPath::builtin("hsbtns8.def"), std::make_pair(heroscrn[26], heroscrn[31]), 0, EShortcut::HERO_TOGGLE_TACTICS); tacticsButton->addHoverText(EButtonState::HIGHLIGHTED, CGI->generaltexth->heroscrn[25]); diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index 9363cd2aa..6c99bbca6 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -300,7 +300,7 @@ int InfoBoxHeroData::getSubID() else return 0; case HERO_SPECIAL: - return hero->type->getIndex(); + return hero->getHeroTypeID().getNum(); case HERO_MANA: case HERO_EXPERIENCE: return 0; @@ -800,7 +800,7 @@ CTownItem::CTownItem(const CGTownInstance * Town) garr = std::make_shared(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS); heroes = std::make_shared(town, Point(244,6), Point(475,6), garr, false); - size_t iconIndex = town->town->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; + size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= LOCPLINT->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)]; picture = std::make_shared(AnimationPath::builtin("ITPT"), iconIndex, 0, 5, 6); openTown = std::make_shared(Rect(5, 6, 58, 64), town); @@ -823,8 +823,8 @@ CTownItem::CTownItem(const CGTownInstance * Town) if(town->hasBuilt(BuildingID::TAVERN)) LOCPLINT->showTavernWindow(town, nullptr, QueryID::NONE); }, [&]{ - if(!town->town->faction->getDescriptionTranslated().empty()) - CRClickPopup::createAndPush(town->town->faction->getDescriptionTranslated()); + if(!town->getTown()->faction->getDescriptionTranslated().empty()) + CRClickPopup::createAndPush(town->getFaction()->getDescriptionTranslated()); }); fastMarket = std::make_shared(Rect(153, 6, 65, 64), []() { diff --git a/client/windows/CMarketWindow.cpp b/client/windows/CMarketWindow.cpp index bf7661696..02b167575 100644 --- a/client/windows/CMarketWindow.cpp +++ b/client/windows/CMarketWindow.cpp @@ -192,7 +192,7 @@ std::string CMarketWindow::getMarketTitle(const ObjectInstanceID marketId, const { for(const auto & buildingId : town->getBuildings()) { - if(const auto building = town->town->buildings.at(buildingId); vstd::contains(building->marketModes, mode)) + if(const auto building = town->getTown()->buildings.at(buildingId); vstd::contains(building->marketModes, mode)) return building->getNameTranslated(); } } diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index e014d36a8..46406d4d4 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -522,9 +522,9 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func recruit->block(true); } if(LOCPLINT->castleInt) - videoPlayer = std::make_shared(Point(70, 56), LOCPLINT->castleInt->town->town->clientInfo.tavernVideo, false); + videoPlayer = std::make_shared(Point(70, 56), LOCPLINT->castleInt->town->getTown()->clientInfo.tavernVideo, false); else if(const auto * townObj = dynamic_cast(TavernObj)) - videoPlayer = std::make_shared(Point(70, 56), townObj->town->clientInfo.tavernVideo, false); + videoPlayer = std::make_shared(Point(70, 56), townObj->getTown()->clientInfo.tavernVideo, false); else videoPlayer = std::make_shared(Point(70, 56), VideoPath::builtin("TAVERN.BIK"), false); @@ -548,7 +548,7 @@ void CTavernWindow::addInvite() if(!inviteableHeroes.empty()) { - int imageIndex = heroToInvite ? (*CGI->heroh)[heroToInvite->getHeroType()]->imageIndex : 156; // 156 => special id for random + int imageIndex = heroToInvite ? heroToInvite->getIconIndex() : 156; // 156 => special id for random if(!heroToInvite) heroToInvite = (*RandomGeneratorUtil::nextItem(inviteableHeroes, CRandomGenerator::getDefault())).second; @@ -563,7 +563,7 @@ void CTavernWindow::recruitb() const CGHeroInstance *toBuy = (selected ? h2 : h1)->h; const CGObjectInstance *obj = tavernObj; - LOCPLINT->cb->recruitHero(obj, toBuy, heroToInvite ? heroToInvite->getHeroType() : HeroTypeID::NONE); + LOCPLINT->cb->recruitHero(obj, toBuy, heroToInvite ? heroToInvite->getHeroTypeID() : HeroTypeID::NONE); close(); } @@ -963,7 +963,7 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, BuildingID bu if(auto town = dynamic_cast(_market)) { - auto faction = town->town->faction->getId(); + auto faction = town->getTown()->faction->getId(); titlePic = std::make_shared((*CGI->townh)[faction]->town->clientInfo.buildingsIcons, building); } else if(auto uni = dynamic_cast(_market); uni->appearance) diff --git a/client/windows/QuickRecruitmentWindow.cpp b/client/windows/QuickRecruitmentWindow.cpp index 49f9be79d..cdbb80121 100644 --- a/client/windows/QuickRecruitmentWindow.cpp +++ b/client/windows/QuickRecruitmentWindow.cpp @@ -51,9 +51,9 @@ void QuickRecruitmentWindow::setCreaturePurchaseCards() { int availableAmount = getAvailableCreatures(); Point position = Point((pos.w - 100*availableAmount - 8*(availableAmount-1))/2,64); - for (int i = 0; i < town->town->creatures.size(); i++) + for (int i = 0; i < town->getTown()->creatures.size(); i++) { - if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) + if(!town->getTown()->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) { cards.push_back(std::make_shared(town->creatures[i].second, position, town->creatures[i].first, this)); position.x += 108; @@ -108,7 +108,7 @@ void QuickRecruitmentWindow::purchaseUnits() { int level = 0; int i = 0; - for(auto c : town->town->creatures) + for(auto c : town->getTown()->creatures) { for(auto c2 : c) if(c2 == selected->creatureOnTheCard->getId()) @@ -129,8 +129,8 @@ void QuickRecruitmentWindow::purchaseUnits() int QuickRecruitmentWindow::getAvailableCreatures() { int creaturesAmount = 0; - for (int i=0; i< town->town->creatures.size(); i++) - if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) + for (int i=0; i< town->getTown()->creatures.size(); i++) + if(!town->getTown()->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) creaturesAmount++; return creaturesAmount; } diff --git a/include/vcmi/Entity.h b/include/vcmi/Entity.h index 406a879b5..b00a61525 100644 --- a/include/vcmi/Entity.h +++ b/include/vcmi/Entity.h @@ -26,7 +26,7 @@ class DLL_LINKAGE INativeTerrainProvider { public: virtual TerrainId getNativeTerrain() const = 0; - virtual FactionID getFaction() const = 0; + virtual FactionID getFactionID() const = 0; virtual bool isNativeTerrain(TerrainId terrain) const; }; diff --git a/lib/BasicTypes.cpp b/lib/BasicTypes.cpp index a294a14a2..fecc59c7d 100644 --- a/lib/BasicTypes.cpp +++ b/lib/BasicTypes.cpp @@ -38,7 +38,7 @@ TerrainId AFactionMember::getNativeTerrain() const //this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses //and in the CGHeroInstance::getNativeTerrain() to setup movement bonuses or/and penalties. return getBonusBearer()->hasBonus(selectorNoTerrainPenalty, cachingStringNoTerrainPenalty) - ? TerrainId::ANY_TERRAIN : VLC->factions()->getById(getFaction())->getNativeTerrain(); + ? TerrainId::ANY_TERRAIN : getFactionID().toEntity(VLC)->getNativeTerrain(); } int32_t AFactionMember::magicResistance() const diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index f34608fd2..2eed440ed 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -117,7 +117,7 @@ int32_t CCreature::getHorde() const return hordeGrowth; } -FactionID CCreature::getFaction() const +FactionID CCreature::getFactionID() const { return FactionID(faction); } diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 7b09b8d65..0e6c8011b 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -127,7 +127,7 @@ public: std::string getNamePluralTextID() const override; std::string getNameSingularTextID() const override; - FactionID getFaction() const override; + FactionID getFactionID() const override; int32_t getIndex() const override; int32_t getIconIndex() const override; std::string getJsonKey() const override; diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 69040009d..5de5a3420 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -912,10 +912,10 @@ void CStackInstance::serializeJson(JsonSerializeFormat & handler) } } -FactionID CStackInstance::getFaction() const +FactionID CStackInstance::getFactionID() const { if(type) - return type->getFaction(); + return type->getFactionID(); return FactionID::NEUTRAL; } diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index d20fee553..75b377a11 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -106,7 +106,7 @@ public: //IConstBonusProvider const IBonusBearer* getBonusBearer() const override; //INativeTerrainProvider - FactionID getFaction() const override; + FactionID getFactionID() const override; virtual ui64 getPower() const; CCreature::CreatureQuantityId getQuantityID() const; diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index fa5fe231d..b6017df9d 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -381,7 +381,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero for(const auto & creature : VLC->creh->objects) { - if(creature->getFaction() == factionIndex && static_cast(creature->getAIValue()) > maxAIValue) + if(creature->getFactionID() == factionIndex && static_cast(creature->getAIValue()) > maxAIValue) { maxAIValue = creature->getAIValue(); mostStrong = creature.get(); @@ -575,10 +575,10 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu { ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", EBuildingState::TOWN_NOT_OWNED); - if(!t->town->buildings.count(ID)) + if(!t->getTown()->buildings.count(ID)) return EBuildingState::BUILDING_ERROR; - const CBuilding * building = t->town->buildings.at(ID); + const CBuilding * building = t->getTown()->buildings.at(ID); if(t->hasBuilt(ID)) //already built diff --git a/lib/battle/CUnitState.cpp b/lib/battle/CUnitState.cpp index 131fc2a23..737a9813f 100644 --- a/lib/battle/CUnitState.cpp +++ b/lib/battle/CUnitState.cpp @@ -416,9 +416,9 @@ int32_t CUnitState::creatureIconIndex() const return unitType()->getIconIndex(); } -FactionID CUnitState::getFaction() const +FactionID CUnitState::getFactionID() const { - return unitType()->getFaction(); + return unitType()->getFactionID(); } int32_t CUnitState::getCasterUnitId() const diff --git a/lib/battle/CUnitState.h b/lib/battle/CUnitState.h index b5451ba89..9bb9570a1 100644 --- a/lib/battle/CUnitState.h +++ b/lib/battle/CUnitState.h @@ -253,7 +253,7 @@ public: void localInit(const IUnitEnvironment * env_); void serializeJson(JsonSerializeFormat & handler); - FactionID getFaction() const override; + FactionID getFactionID() const override; void afterAttack(bool ranged, bool counter); diff --git a/lib/bonuses/Limiters.cpp b/lib/bonuses/Limiters.cpp index 4f1786a20..914081139 100644 --- a/lib/bonuses/Limiters.cpp +++ b/lib/bonuses/Limiters.cpp @@ -300,15 +300,15 @@ ILimiter::EDecision FactionLimiter::limit(const BonusLimitationContext &context) if(bearer) { if(faction != FactionID::DEFAULT) - return bearer->getFaction() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; + return bearer->getFactionID() == faction ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; switch(context.b.source) { case BonusSource::CREATURE_ABILITY: - return bearer->getFaction() == context.b.sid.as().toCreature()->getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; + return bearer->getFactionID() == context.b.sid.as().toCreature()->getFactionID() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; case BonusSource::TOWN_STRUCTURE: - return bearer->getFaction() == context.b.sid.as().getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; + return bearer->getFactionID() == context.b.sid.as().getFaction() ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //TODO: other sources of bonuses } diff --git a/lib/campaign/CampaignState.cpp b/lib/campaign/CampaignState.cpp index 132d6e904..89d4eed8c 100644 --- a/lib/campaign/CampaignState.cpp +++ b/lib/campaign/CampaignState.cpp @@ -351,14 +351,14 @@ void CampaignState::setCurrentMapAsConquered(std::vector heroe { JsonNode node = CampaignState::crossoverSerialize(hero); - if (reservedHeroes.count(hero->getHeroType())) + if (reservedHeroes.count(hero->getHeroTypeID())) { - logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroType(), hero->getNameTranslated()); - globalHeroPool[hero->getHeroType()] = node; + logGlobal->info("Hero crossover: %d (%s) exported to global pool", hero->getHeroTypeID(), hero->getNameTranslated()); + globalHeroPool[hero->getHeroTypeID()] = node; } else { - logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroType(), hero->getNameTranslated()); + logGlobal->info("Hero crossover: %d (%s) exported to scenario pool", hero->getHeroTypeID(), hero->getNameTranslated()); scenarioHeroPool[*currentMap].push_back(node); } } diff --git a/lib/entities/faction/CFaction.cpp b/lib/entities/faction/CFaction.cpp index 4ed5d1ad2..3ef88afae 100644 --- a/lib/entities/faction/CFaction.cpp +++ b/lib/entities/faction/CFaction.cpp @@ -92,7 +92,7 @@ FactionID CFaction::getId() const return FactionID(index); } -FactionID CFaction::getFaction() const +FactionID CFaction::getFactionID() const { return FactionID(index); } diff --git a/lib/entities/faction/CFaction.h b/lib/entities/faction/CFaction.h index 294a77529..27d6a2239 100644 --- a/lib/entities/faction/CFaction.h +++ b/lib/entities/faction/CFaction.h @@ -39,7 +39,7 @@ class DLL_LINKAGE CFaction : public Faction FactionID index = FactionID::NEUTRAL; - FactionID getFaction() const override; //This function should not be used + FactionID getFactionID() const override; //This function should not be used public: TerrainId nativeTerrain; diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index d0cd98fae..7bba1770d 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -599,7 +599,7 @@ void CGameState::initHeroes() } hero->initHero(getRandomGenerator()); - map->allHeroes[hero->getHeroType().getNum()] = hero; + map->allHeroes[hero->getHeroTypeID().getNum()] = hero; } // generate boats for all heroes on water @@ -629,20 +629,20 @@ void CGameState::initHeroes() { auto * hero = dynamic_cast(obj.get()); hero->initHero(getRandomGenerator()); - map->allHeroes[hero->getHeroType().getNum()] = hero; + map->allHeroes[hero->getHeroTypeID().getNum()] = hero; } } std::set heroesToCreate = getUnusedAllowedHeroes(); //ids of heroes to be created and put into the pool for(auto ph : map->predefinedHeroes) { - if(!vstd::contains(heroesToCreate, ph->getHeroType())) + if(!vstd::contains(heroesToCreate, ph->getHeroTypeID())) continue; ph->initHero(getRandomGenerator()); heroesPool->addHeroToPool(ph); - heroesToCreate.erase(ph->type->getId()); + heroesToCreate.erase(ph->getHeroTypeID()); - map->allHeroes[ph->getHeroType().getNum()] = ph; + map->allHeroes[ph->getHeroTypeID().getNum()] = ph; } for(const HeroTypeID & htype : heroesToCreate) //all not used allowed heroes go with default state into the pool @@ -756,12 +756,12 @@ void CGameState::initTownNames() for(auto & vti : map->towns) { - assert(vti->town); + assert(vti->getTown()); if(!vti->getNameTextID().empty()) continue; - FactionID faction = vti->getFaction(); + FactionID faction = vti->getFactionID(); if(availableNames.empty()) { @@ -798,8 +798,8 @@ void CGameState::initTowns() for (auto & vti : map->towns) { - assert(vti->town); - assert(vti->town->creatures.size() <= GameConstants::CREATURES_PER_TOWN); + assert(vti->getTown()); + assert(vti->getTown()->creatures.size() <= GameConstants::CREATURES_PER_TOWN); constexpr std::array basicDwellings = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7, BuildingID::DWELL_LVL_8 }; constexpr std::array upgradedDwellings = { BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP, BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP, BuildingID::DWELL_LVL_8_UP }; @@ -828,7 +828,7 @@ void CGameState::initTowns() vti->addBuilding(BuildingID::VILLAGE_HALL); //init hordes - for (int i = 0; i < vti->town->creatures.size(); i++) + for (int i = 0; i < vti->getTown()->creatures.size(); i++) { if(vti->hasBuilt(hordes[i])) //if we have horde for this level { @@ -894,7 +894,7 @@ void CGameState::initTowns() int sel = -1; for(ui32 ps=0;pspossibleSpells.size();ps++) - total += vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction()); + total += vti->possibleSpells[ps].toSpell()->getProbability(vti->getFactionID()); if (total == 0) // remaining spells have 0 probability break; @@ -902,7 +902,7 @@ void CGameState::initTowns() auto r = getRandomGenerator().nextInt(total - 1); for(ui32 ps=0; pspossibleSpells.size();ps++) { - r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->getFaction()); + r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->getFactionID()); if(r<0) { sel = ps; @@ -1655,18 +1655,13 @@ std::set CGameState::getUnusedAllowedHeroes(bool alsoIncludeNotAllow } for(auto hero : map->heroesOnMap) //heroes instances initialization - { - if(hero->type) - ret -= hero->type->getId(); - else - ret -= hero->getHeroType(); - } + ret -= hero->getHeroTypeID(); for(auto obj : map->objects) //prisons { auto * hero = dynamic_cast(obj.get()); if(hero && hero->ID == Obj::PRISON) - ret -= hero->getHeroType(); + ret -= hero->getHeroTypeID(); } return ret; @@ -1690,7 +1685,7 @@ CGHeroInstance * CGameState::getUsedHero(const HeroTypeID & hid) const auto * hero = dynamic_cast(obj.get()); assert(hero); - if (hero->getHeroType() == hid) + if (hero->getHeroTypeID() == hid) return hero; } diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index b4bf3678c..2178da654 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -86,7 +86,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr .And(Selector::subtype()(BonusSubtypeID(g))) .And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)); - hero.hero->getLocalBonus(sel)->val = hero.hero->type->heroClass->primarySkillInitial[g.getNum()]; + hero.hero->getLocalBonus(sel)->val = hero.hero->getHeroClass()->primarySkillInitial[g.getNum()]; } } } @@ -96,7 +96,7 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(const CampaignTravel & tr //trimming sec skills for(auto & hero : campaignHeroReplacements) { - hero.hero->secSkills = hero.hero->type->secSkillsInit; + hero.hero->secSkills = hero.hero->getHeroType()->secSkillsInit; hero.hero->recreateSecondarySkillsBonuses(); } } @@ -240,7 +240,7 @@ void CGameStateCampaign::placeCampaignHeroes() for(auto & replacement : campaignHeroReplacements) if (replacement.heroPlaceholderId.hasValue()) - heroesToRemove.insert(replacement.hero->getHeroType()); + heroesToRemove.insert(replacement.hero->getHeroTypeID()); for(auto & heroID : heroesToRemove) { @@ -369,8 +369,8 @@ void CGameStateCampaign::replaceHeroesPlaceholders() if(heroPlaceholder->tempOwner.isValidPlayer()) heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->setAnchorPos(heroPlaceholder->anchorPos()); - heroToPlace->type = heroToPlace->getHeroType().toHeroType(); - heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->type->heroClass->getIndex())->getTemplates().front(); + heroToPlace->setHeroType(heroToPlace->getHeroTypeID()); + heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->getHeroTypeID())->getTemplates().front(); gameState->map->removeBlockVisTiles(heroPlaceholder, true); gameState->map->objects[heroPlaceholder->id.getNum()] = nullptr; @@ -563,7 +563,7 @@ void CGameStateCampaign::initHeroes() { for (auto & hero : heroes) { - if (hero->getHeroType().getNum() == chosenBonus->info1) + if (hero->getHeroTypeID().getNum() == chosenBonus->info1) { giveCampaignBonusToHero(hero); break; @@ -662,7 +662,7 @@ void CGameStateCampaign::initTowns() if(gameState->scenarioOps->campState->formatVCMI()) newBuilding = BuildingID(chosenBonus->info1); else - newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFaction(), town->getBuildings()); + newBuilding = CBuildingHandler::campToERMU(chosenBonus->info1, town->getFactionID(), town->getBuildings()); // Build granted building & all prerequisites - e.g. Mages Guild Lvl 3 should also give Mages Guild Lvl 1 & 2 while(true) @@ -675,7 +675,7 @@ void CGameStateCampaign::initTowns() town->addBuilding(newBuilding); - auto building = town->town->buildings.at(newBuilding); + auto building = town->getTown()->buildings.at(newBuilding); newBuilding = building->upgrade; } break; diff --git a/lib/gameState/GameStatistics.cpp b/lib/gameState/GameStatistics.cpp index 237da8f54..6e1c95e85 100644 --- a/lib/gameState/GameStatistics.cpp +++ b/lib/gameState/GameStatistics.cpp @@ -381,7 +381,7 @@ float Statistic::getTownBuiltRatio(const PlayerState * ps) for(const auto & t : ps->getTowns()) { built += t->getBuildings().size(); - for(const auto & b : t->town->buildings) + for(const auto & b : t->getTown()->buildings) if(!t->forbiddenBuildings.count(b.first)) total += 1; } diff --git a/lib/gameState/InfoAboutArmy.cpp b/lib/gameState/InfoAboutArmy.cpp index cc3bdc205..cb6ad5e95 100644 --- a/lib/gameState/InfoAboutArmy.cpp +++ b/lib/gameState/InfoAboutArmy.cpp @@ -115,7 +115,7 @@ void InfoAboutHero::initFromHero(const CGHeroInstance *h, InfoAboutHero::EInfoLe initFromArmy(h, detailed); - hclass = h->type->heroClass; + hclass = h->getHeroClass(); name = h->getNameTranslated(); portraitSource = h->getPortraitSource(); diff --git a/lib/gameState/TavernHeroesPool.cpp b/lib/gameState/TavernHeroesPool.cpp index bafaf28b0..44d085c13 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(slot.hero->getHeroType()); + pool.erase(slot.hero->getHeroTypeID()); return pool; } @@ -34,7 +34,7 @@ TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const { for (auto const & slot : currentTavern) { - if (slot.hero->getHeroType() == hero) + if (slot.hero->getHeroTypeID() == hero) return slot.role; } return TavernSlotRole::NONE; @@ -106,7 +106,7 @@ CGHeroInstance * TavernHeroesPool::takeHeroFromPool(HeroTypeID hero) heroesPool.erase(hero); vstd::erase_if(currentTavern, [&](const TavernSlot & entry){ - return entry.hero->type->getId() == hero; + return entry.hero->getHeroTypeID() == hero; }); assert(result); @@ -138,7 +138,7 @@ void TavernHeroesPool::onNewDay() void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero) { - heroesPool[hero->getHeroType()] = hero; + heroesPool[hero->getHeroTypeID()] = hero; } void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set mask) diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp index d90ac8ef2..421d2565f 100644 --- a/lib/mapObjectConstructors/CommonConstructors.cpp +++ b/lib/mapObjectConstructors/CommonConstructors.cpp @@ -96,7 +96,6 @@ bool CTownInstanceConstructor::objectFilter(const CGObjectInstance * object, std void CTownInstanceConstructor::initializeObject(CGTownInstance * obj) const { - obj->town = faction->town; obj->tempOwner = PlayerColor::NEUTRAL; } @@ -144,7 +143,7 @@ bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, std auto heroTest = [&](const HeroTypeID & id) { - return hero->type->getId() == id; + return hero->getHeroTypeID() == id; }; if(filters.count(templ->stringID)) @@ -154,11 +153,6 @@ bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, std return false; } -void CHeroInstanceConstructor::initializeObject(CGHeroInstance * obj) const -{ - obj->type = nullptr; //FIXME: set to valid value. somehow. -} - void CHeroInstanceConstructor::randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const { diff --git a/lib/mapObjectConstructors/CommonConstructors.h b/lib/mapObjectConstructors/CommonConstructors.h index d7ce61f5e..2089acdf7 100644 --- a/lib/mapObjectConstructors/CommonConstructors.h +++ b/lib/mapObjectConstructors/CommonConstructors.h @@ -81,7 +81,6 @@ public: const CHeroClass * heroClass = nullptr; std::map> filters; - void initializeObject(CGHeroInstance * object) const override; void randomizeObject(CGHeroInstance * object, vstd::RNG & rng) const override; void afterLoadFinalization() override; diff --git a/lib/mapObjects/CArmedInstance.cpp b/lib/mapObjects/CArmedInstance.cpp index 5a8b0cae8..23d026cd9 100644 --- a/lib/mapObjects/CArmedInstance.cpp +++ b/lib/mapObjects/CArmedInstance.cpp @@ -78,7 +78,7 @@ void CArmedInstance::updateMoraleBonusFromArmy() const CStackInstance * inst = slot.second; const auto * creature = inst->getCreatureID().toEntity(VLC); - factions.insert(creature->getFaction()); + factions.insert(creature->getFactionID()); // Check for undead flag instead of faction (undead mummies are neutral) if (!hasUndead) { diff --git a/lib/mapObjects/CGCreature.cpp b/lib/mapObjects/CGCreature.cpp index 3ebead8cb..2d595bd5f 100644 --- a/lib/mapObjects/CGCreature.cpp +++ b/lib/mapObjects/CGCreature.cpp @@ -45,7 +45,7 @@ std::string CGCreature::getHoverText(PlayerColor player) const else ms.appendLocalString(EMetaText::ARRAY_TXT, quantityTextIndex); ms.appendRawString(" "); - ms.appendNamePlural(getCreature()); + ms.appendNamePlural(getCreatureID()); return ms.toString(); } @@ -57,7 +57,7 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const MetaString ms; ms.appendNumber(stacks.begin()->second->count); ms.appendRawString(" "); - ms.appendName(getCreature(), stacks.begin()->second->count); + ms.appendName(getCreatureID(), stacks.begin()->second->count); return ms.toString(); } else @@ -69,11 +69,11 @@ std::string CGCreature::getHoverText(const CGHeroInstance * hero) const std::string CGCreature::getMonsterLevelText() const { std::string monsterLevel = VLC->generaltexth->translate("vcmi.adventureMap.monsterLevel"); - bool isRanged = VLC->creatures()->getById(getCreature())->getBonusBearer()->hasBonusOfType(BonusType::SHOOTER); + bool isRanged = getCreature()->getBonusBearer()->hasBonusOfType(BonusType::SHOOTER); std::string attackTypeKey = isRanged ? "vcmi.adventureMap.monsterRangedType" : "vcmi.adventureMap.monsterMeleeType"; std::string attackType = VLC->generaltexth->translate(attackTypeKey); - boost::replace_first(monsterLevel, "%TOWN", (*VLC->townh)[VLC->creatures()->getById(getCreature())->getFaction()]->getNameTranslated()); - boost::replace_first(monsterLevel, "%LEVEL", std::to_string(VLC->creatures()->getById(getCreature())->getLevel())); + boost::replace_first(monsterLevel, "%TOWN", getCreature()->getFactionID().toEntity(VLC)->getNameTranslated()); + boost::replace_first(monsterLevel, "%LEVEL", std::to_string(getCreature()->getLevel())); boost::replace_first(monsterLevel, "%ATTACK_TYPE", attackType); return monsterLevel; } @@ -150,7 +150,7 @@ std::string CGCreature::getPopupText(PlayerColor player) const std::vector CGCreature::getPopupComponents(PlayerColor player) const { return { - Component(ComponentType::CREATURE, getCreature()) + Component(ComponentType::CREATURE, getCreatureID()) }; } @@ -182,7 +182,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.replaceName(getCreature(), getStackCount(SlotID(0))); + ynd.text.replaceName(getCreatureID(), getStackCount(SlotID(0))); cb->showBlockingDialog(this, &ynd); break; } @@ -197,7 +197,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->creatures()->getById(getCreature())->getNamePluralTranslated()); + boost::algorithm::replace_first(tmp,"%s",getCreature()->getNamePluralTranslated()); ynd.text.appendRawString(tmp); cb->showBlockingDialog(this, &ynd); break; @@ -205,11 +205,16 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const } } -CreatureID CGCreature::getCreature() const +CreatureID CGCreature::getCreatureID() const { return CreatureID(getObjTypeIndex().getNum()); } +const CCreature * CGCreature::getCreature() const +{ + return getCreatureID().toCreature(); +} + void CGCreature::pickRandomObject(vstd::RNG & rand) { switch(ID.toEnum()) @@ -279,7 +284,7 @@ void CGCreature::initObj(vstd::RNG & rand) stacks[SlotID(0)]->setType(getCreature()); TQuantity &amount = stacks[SlotID(0)]->count; - const Creature * c = VLC->creatures()->getById(getCreature()); + const Creature * c = getCreature(); if(amount == 0) { amount = rand.nextInt(c->getAdvMapAmountMin(), c->getAdvMapAmountMax()); @@ -353,8 +358,8 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const for(const auto & elem : h->Slots()) { - bool isOurUpgrade = vstd::contains(getCreature().toCreature()->upgrades, elem.second->getCreatureID()); - bool isOurDowngrade = vstd::contains(elem.second->type->upgrades, getCreature()); + bool isOurUpgrade = vstd::contains(getCreature()->upgrades, elem.second->getCreatureID()); + bool isOurDowngrade = vstd::contains(elem.second->type->upgrades, getCreatureID()); if(isOurUpgrade || isOurDowngrade) count += elem.second->count; @@ -380,7 +385,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const if(diplomacy * 2 + sympathy + 1 >= character) { - int32_t recruitCost = VLC->creatures()->getById(getCreature())->getRecruitCost(EGameResID::GOLD); + int32_t recruitCost = getCreature()->getRecruitCost(EGameResID::GOLD); int32_t stackCount = getStackCount(SlotID(0)); return recruitCost * stackCount; //join for gold } @@ -493,7 +498,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.replaceName(getCreature(), getStackCount(SlotID(0))); + ynd.text.replaceName(getCreatureID(), getStackCount(SlotID(0))); cb->showBlockingDialog(this, &ynd); } @@ -513,7 +518,7 @@ void CGCreature::battleFinished(const CGHeroInstance *hero, const BattleResult & { //merge stacks into one TSlots::const_iterator i; - const CCreature * cre = getCreature().toCreature(); + const CCreature * cre = getCreature(); for(i = stacks.begin(); i != stacks.end(); i++) { if(cre->isMyUpgrade(i->second->type)) diff --git a/lib/mapObjects/CGCreature.h b/lib/mapObjects/CGCreature.h index a8c32fb8b..daa554a2e 100644 --- a/lib/mapObjects/CGCreature.h +++ b/lib/mapObjects/CGCreature.h @@ -49,7 +49,8 @@ public: void newTurn(vstd::RNG & rand) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void blockingDialogAnswered(const CGHeroInstance *hero, int32_t answer) const override; - CreatureID getCreature() const; + CreatureID getCreatureID() const; + const CCreature * getCreature() const; //stack formation depends on position, bool containsUpgradedStack() const; diff --git a/lib/mapObjects/CGDwelling.cpp b/lib/mapObjects/CGDwelling.cpp index 51dd897e3..638480ed2 100644 --- a/lib/mapObjects/CGDwelling.cpp +++ b/lib/mapObjects/CGDwelling.cpp @@ -93,7 +93,7 @@ FactionID CGDwelling::randomizeFaction(vstd::RNG & rand) assert(linkedTown->ID == Obj::TOWN); if(linkedTown->ID==Obj::TOWN) - return linkedTown->getFaction(); + return linkedTown->getFactionID(); } if(!randomizationInfo->allowedFactions.empty()) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 080285a96..caaf5081a 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -116,9 +116,9 @@ ui32 CGHeroInstance::getTileMovementCost(const TerrainTile & dest, const Terrain return static_cast(ret); } -FactionID CGHeroInstance::getFaction() const +FactionID CGHeroInstance::getFactionID() const { - return FactionID(type->heroClass->faction); + return getHeroClass()->faction; } const IBonusBearer* CGHeroInstance::getBonusBearer() const @@ -229,10 +229,10 @@ bool CGHeroInstance::canLearnSkill(const SecondarySkill & which) const if (getSecSkillLevel(which) > 0) return false; - if (type->heroClass->secSkillProbability.count(which) == 0) + if (getHeroClass()->secSkillProbability.count(which) == 0) return false; - if (type->heroClass->secSkillProbability.at(which) == 0) + if (getHeroClass()->secSkillProbability.at(which) == 0) return false; return true; @@ -282,7 +282,6 @@ int CGHeroInstance::movementPointsLimitCached(bool onLand, const TurnInfo * ti) CGHeroInstance::CGHeroInstance(IGameCallback * cb) : CArmedInstance(cb), - type(nullptr), tacticFormationEnabled(false), inTownGarrison(false), moveDir(4), @@ -303,14 +302,30 @@ PlayerColor CGHeroInstance::getOwner() const return tempOwner; } -HeroTypeID CGHeroInstance::getHeroType() const +const CHeroClass * CGHeroInstance::getHeroClass() const { + return getHeroType()->heroClass; +} + +HeroClassID CGHeroInstance::getHeroClassID() const +{ + return getHeroType()->heroClass->getId(); +} + +const CHero * CGHeroInstance::getHeroType() const +{ + return getHeroTypeID().toHeroType(); +} + +HeroTypeID CGHeroInstance::getHeroTypeID() const +{ + if (ID == Obj::RANDOM_HERO) + return HeroTypeID::NONE; return HeroTypeID(getObjTypeIndex().getNum()); } void CGHeroInstance::setHeroType(HeroTypeID heroType) { - assert(type == nullptr); subID = heroType; } @@ -323,16 +338,14 @@ void CGHeroInstance::initHero(vstd::RNG & rand, const HeroTypeID & SUBID) void CGHeroInstance::initHero(vstd::RNG & rand) { assert(validTypes(true)); - if(!type) - type = getHeroType().toHeroType(); - + if (ID == Obj::HERO) - appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); + appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, getHeroClass()->getIndex())->getTemplates().front(); if(!vstd::contains(spells, SpellID::PRESET)) { // hero starts with default spells - for(const auto & spellID : type->spells) + for(const auto & spellID : getHeroType()->spells) spells.insert(spellID); } else //remove placeholder @@ -341,7 +354,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand) if(!vstd::contains(spells, SpellID::SPELLBOOK_PRESET)) { // hero starts with default spellbook presence status - if(!getArt(ArtifactPosition::SPELLBOOK) && type->haveSpellBook) + if(!getArt(ArtifactPosition::SPELLBOOK) && getHeroType()->haveSpellBook) { auto artifact = ArtifactUtils::createArtifact(ArtifactID::SPELLBOOK); putArtifact(ArtifactPosition::SPELLBOOK, artifact); @@ -360,14 +373,14 @@ void CGHeroInstance::initHero(vstd::RNG & rand) { for(int g=0; g(g), type->heroClass->primarySkillInitial[g]); + pushPrimSkill(static_cast(g), getHeroClass()->primarySkillInitial[g]); } } if(secSkills.size() == 1 && secSkills[0] == std::pair(SecondarySkill::NONE, -1)) //set secondary skills to default - secSkills = type->secSkillsInit; + secSkills = getHeroType()->secSkillsInit; if (gender == EHeroGender::DEFAULT) - gender = type->gender; + gender = getHeroType()->gender; setFormation(EArmyFormation::LOOSE); if (!stacksCount()) //standard army//initial army @@ -403,9 +416,9 @@ void CGHeroInstance::initHero(vstd::RNG & rand) addNewBonus(bonus); } - if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && type->heroClass->commander.hasValue()) + if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && getHeroClass()->commander.hasValue()) { - commander = new CCommanderInstance(type->heroClass->commander); + commander = new CCommanderInstance(getHeroClass()->commander); commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders commander->giveStackExp (exp); //after our exp is set } @@ -413,7 +426,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand) skillsInfo = SecondarySkillsInfo(); //copy active (probably growing) bonuses from hero prototype to hero object - for(const std::shared_ptr & b : type->specialty) + for(const std::shared_ptr & b : getHeroType()->specialty) addNewBonus(b); //initialize bonuses @@ -433,14 +446,14 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst) auto stacksCountChances = cb->getSettings().getVector(EGameSettings::HEROES_STARTING_STACKS_CHANCES); int stacksCountInitRandomNumber = rand.nextInt(1, 100); - size_t maxStacksCount = std::min(stacksCountChances.size(), type->initialArmy.size()); + size_t maxStacksCount = std::min(stacksCountChances.size(), getHeroType()->initialArmy.size()); for(int stackNo=0; stackNo < maxStacksCount; stackNo++) { if (stacksCountInitRandomNumber > stacksCountChances[stackNo]) continue; - auto & stack = type->initialArmy[stackNo]; + auto & stack = getHeroType()->initialArmy[stackNo]; int count = rand.nextInt(stack.minAmount, stack.maxAmount); @@ -588,11 +601,11 @@ std::string CGHeroInstance::getMovementPointsTextIfOwner(PlayerColor player) con ui8 CGHeroInstance::maxlevelsToMagicSchool() const { - return type->heroClass->isMagicHero() ? 3 : 4; + return getHeroClass()->isMagicHero() ? 3 : 4; } ui8 CGHeroInstance::maxlevelsToWisdom() const { - return type->heroClass->isMagicHero() ? 3 : 6; + return getHeroClass()->isMagicHero() ? 3 : 6; } CGHeroInstance::SecondarySkillsInfo::SecondarySkillsInfo(): @@ -617,11 +630,8 @@ void CGHeroInstance::pickRandomObject(vstd::RNG & rand) { ID = Obj::HERO; subID = cb->gameState()->pickNextHeroType(getOwner()); - type = getHeroType().toHeroType(); - randomizeArmy(type->heroClass->faction); + randomizeArmy(getHeroClass()->faction); } - else - type = getHeroType().toHeroType(); auto oldSubID = subID; @@ -629,7 +639,7 @@ void CGHeroInstance::pickRandomObject(vstd::RNG & rand) // after setType subID used to store unique hero identify id. Check issue 2277 for details // exclude prisons which should use appearance as set in map, via map editor or RMG if (ID != Obj::PRISON) - setType(ID, type->heroClass->getIndex()); + setType(ID, getHeroClass()->getIndex()); this->subID = oldSubID; } @@ -1041,7 +1051,7 @@ si32 CGHeroInstance::getManaNewTurn() const BoatId CGHeroInstance::getBoatType() const { - return BoatId(VLC->townh->getById(type->heroClass->faction)->getBoatType()); + return BoatId(VLC->townh->getById(getHeroClass()->faction)->getBoatType()); } void CGHeroInstance::getOutOffsets(std::vector &offsets) const @@ -1080,7 +1090,7 @@ void CGHeroInstance::pushPrimSkill( PrimarySkill which, int val ) EAlignment CGHeroInstance::getAlignment() const { - return type->heroClass->getAlignment(); + return getHeroClass()->getAlignment(); } void CGHeroInstance::initExp(vstd::RNG & rand) @@ -1104,12 +1114,12 @@ HeroTypeID CGHeroInstance::getPortraitSource() const if (customPortraitSource.isValid()) return customPortraitSource; else - return getHeroType(); + return getHeroTypeID(); } int32_t CGHeroInstance::getIconIndex() const { - return VLC->heroTypes()->getById(getPortraitSource())->getIconIndex(); + return getPortraitSource().toEntity(VLC)->getIconIndex(); } std::string CGHeroInstance::getNameTranslated() const @@ -1126,15 +1136,15 @@ std::string CGHeroInstance::getClassNameTextID() const { if (isCampaignGem()) return "core.genrltxt.735"; - return type->heroClass->getNameTextID(); + return getHeroClass()->getNameTextID(); } std::string CGHeroInstance::getNameTextID() const { if (!nameCustomTextId.empty()) return nameCustomTextId; - if (type) - return type->getNameTextID(); + if (getHeroTypeID().hasValue()) + return getHeroType()->getNameTextID(); // FIXME: called by logging from some specialties (mods?) before type is set on deserialization // assert(0); @@ -1150,8 +1160,8 @@ std::string CGHeroInstance::getBiographyTextID() const { if (!biographyCustomTextId.empty()) return biographyCustomTextId; - if (type) - return type->getBiographyTextID(); + if (getHeroTypeID().hasValue()) + return getHeroType()->getBiographyTextID(); return ""; //for random hero } @@ -1349,11 +1359,11 @@ std::vector CGHeroInstance::getLevelUpProposedSecondarySkills(vs SecondarySkill selection; if (selectWisdom) - selection = type->heroClass->chooseSecSkill(intersect(options, wisdomList), rand); + selection = getHeroClass()->chooseSecSkill(intersect(options, wisdomList), rand); else if (selectSchool) - selection = type->heroClass->chooseSecSkill(intersect(options, schoolList), rand); + selection = getHeroClass()->chooseSecSkill(intersect(options, schoolList), rand); else - selection = type->heroClass->chooseSecSkill(options, rand); + selection = getHeroClass()->chooseSecSkill(options, rand); skills.push_back(selection); options.erase(selection); @@ -1384,7 +1394,7 @@ PrimarySkill CGHeroInstance::nextPrimarySkill(vstd::RNG & rand) const { assert(gainsLevel()); const auto isLowLevelHero = level < GameConstants::HERO_HIGH_LEVEL; - const auto & skillChances = isLowLevelHero ? type->heroClass->primarySkillLowLevel : type->heroClass->primarySkillHighLevel; + const auto & skillChances = isLowLevelHero ? getHeroClass()->primarySkillLowLevel : getHeroClass()->primarySkillHighLevel; if (isCampaignYog()) { @@ -1524,25 +1534,15 @@ bool CGHeroInstance::hasVisions(const CGObjectInstance * target, BonusSubtypeID std::string CGHeroInstance::getHeroTypeName() const { if(ID == Obj::HERO || ID == Obj::PRISON) - { - if(type) - { - return type->getJsonKey(); - } - else - { - return getHeroType().toEntity(VLC)->getJsonKey(); - } - } + return getHeroType()->getJsonKey(); + return ""; } void CGHeroInstance::afterAddToMap(CMap * map) { if(ID != Obj::PRISON) - { map->heroesOnMap.emplace_back(this); - } } void CGHeroInstance::afterRemoveFromMap(CMap* map) { @@ -1729,8 +1729,7 @@ void CGHeroInstance::serializeJsonOptions(JsonSerializeFormat & handler) if(!appearance) { // crossoverDeserialize - type = getHeroType().toHeroType(); - appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); + appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, getHeroClassID())->getTemplates().front(); } } @@ -1817,7 +1816,7 @@ bool CGHeroInstance::isCampaignYog() const if (!boost::starts_with(campaign, "DATA/YOG")) // "Birth of a Barbarian" return false; - if (getHeroType() != HeroTypeID::SOLMYR) // Yog (based on Solmyr) + if (getHeroTypeID() != HeroTypeID::SOLMYR) // Yog (based on Solmyr) return false; return true; @@ -1835,7 +1834,7 @@ bool CGHeroInstance::isCampaignGem() const if (!boost::starts_with(campaign, "DATA/GEM") && !boost::starts_with(campaign, "DATA/FINAL")) // "New Beginning" and "Unholy Alliance" return false; - if (getHeroType() != HeroTypeID::GEM) // Yog (based on Solmyr) + if (getHeroTypeID() != HeroTypeID::GEM) // Yog (based on Solmyr) return false; return true; diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index d07885e70..ebb8261f8 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -72,7 +72,6 @@ public: ////////////////////////////////////////////////////////////////////////// - const CHero * type; TExpType exp; //experience points ui32 level; //current level of hero @@ -171,7 +170,7 @@ public: const IOwnableObject * asOwnable() const final; //INativeTerrainProvider - FactionID getFaction() const override; + FactionID getFactionID() const override; TerrainId getNativeTerrain() const override; int getLowestCreatureSpeed() const; si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day @@ -235,7 +234,11 @@ public: ////////////////////////////////////////////////////////////////////////// - HeroTypeID getHeroType() const; + const CHeroClass * getHeroClass() const; + HeroClassID getHeroClassID() const; + + const CHero * getHeroType() const; + HeroTypeID getHeroTypeID() const; void setHeroType(HeroTypeID type); void initHero(vstd::RNG & rand); @@ -352,7 +355,11 @@ public: h & skillsInfo; h & visitedTown; h & boat; - h & type; + if (h.version < Handler::Version::REMOVE_TOWN_PTR) + { + CHero * type = nullptr; + h & type; + } h & commander; h & visitedObjects; BONUS_TREE_DESERIALIZATION_FIX diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 614cd0477..50d9b8b35 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -45,7 +45,7 @@ int CGTownInstance::getSightRadius() const //returns sight distance for(const auto & bid : builtBuildings) { - auto height = town->buildings.at(bid)->height; + auto height = getTown()->buildings.at(bid)->height; if(ret < height) ret = height; } @@ -115,7 +115,7 @@ int CGTownInstance::mageGuildLevel() const int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present { - return town->hordeLvl.at(HID); + return getTown()->hordeLvl.at(HID); } int CGTownInstance::creatureGrowth(const int & level) const @@ -127,7 +127,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const { GrowthInfo ret; - if (level<0 || level >=town->creatures.size()) + if (level<0 || level >=getTown()->creatures.size()) return ret; if (creatures[level].second.empty()) return ret; //no dwelling @@ -151,11 +151,11 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const else if (hasBuilt(BuildingID::CITADEL)) ret.entries.emplace_back(subID, BuildingID::CITADEL, castleBonus = base / 2); - if(town->hordeLvl.at(0) == level)//horde 1 + if(getTown()->hordeLvl.at(0) == level)//horde 1 if(hasBuilt(BuildingID::HORDE_1)) ret.entries.emplace_back(subID, BuildingID::HORDE_1, creature->getHorde()); - if(town->hordeLvl.at(1) == level)//horde 2 + if(getTown()->hordeLvl.at(1) == level)//horde 2 if(hasBuilt(BuildingID::HORDE_2)) ret.entries.emplace_back(subID, BuildingID::HORDE_2, creature->getHorde()); @@ -209,11 +209,11 @@ int CGTownInstance::getDwellingBonus(const std::vector& creatureIds, TResources CGTownInstance::dailyIncome() const { TResources ret; - for(const auto & p : town->buildings) + for(const auto & p : getTown()->buildings) { BuildingID buildingUpgrade; - for(const auto & p2 : town->buildings) + for(const auto & p2 : getTown()->buildings) { if (p2.second->upgrade == p.first) { @@ -251,10 +251,10 @@ bool CGTownInstance::hasCapitol() const TownFortifications CGTownInstance::fortificationsLevel() const { - auto result = town->fortifications; + auto result = getTown()->fortifications; for (auto const & buildingID : builtBuildings) - result += town->buildings.at(buildingID)->fortifications; + result += getTown()->buildings.at(buildingID)->fortifications; if (result.wallsHealth == 0) return TownFortifications(); @@ -264,7 +264,6 @@ TownFortifications CGTownInstance::fortificationsLevel() const CGTownInstance::CGTownInstance(IGameCallback *cb): CGDwelling(cb), - town(nullptr), built(0), destroyed(0), identifier(0), @@ -379,17 +378,17 @@ void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const std::string CGTownInstance::getObjectName() const { - return getNameTranslated() + ", " + town->faction->getNameTranslated(); + return getNameTranslated() + ", " + getTown()->faction->getNameTranslated(); } bool CGTownInstance::townEnvisagesBuilding(BuildingSubID::EBuildingSubID subId) const { - return town->getBuildingType(subId) != BuildingID::NONE; + return getTown()->getBuildingType(subId) != BuildingID::NONE; } void CGTownInstance::initializeConfigurableBuildings(vstd::RNG & rand) { - for(const auto & kvp : town->buildings) + for(const auto & kvp : getTown()->buildings) { if(!kvp.second->rewardableObjectInfo.getParameters().isNull()) rewardableBuildings[kvp.first] = new TownRewardableBuildingInstance(this, kvp.second->bid, rand); @@ -457,8 +456,7 @@ void CGTownInstance::pickRandomObject(vstd::RNG & rand) assert(ID == Obj::TOWN); // just in case setType(ID, subID); - town = (*VLC->townh)[getFaction()]->town; - randomizeArmy(getFaction()); + randomizeArmy(getFactionID()); updateAppearance(); } @@ -467,19 +465,19 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures blockVisit = true; if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example - creatures.resize(town->creatures.size() + 1); + creatures.resize(getTown()->creatures.size() + 1); else - creatures.resize(town->creatures.size()); + creatures.resize(getTown()->creatures.size()); - for (int level = 0; level < town->creatures.size(); level++) + for (int level = 0; level < getTown()->creatures.size(); level++) { BuildingID buildID = BuildingID(BuildingID::getDwellingFromLevel(level, 0)); int upgradeNum = 0; - for (; town->buildings.count(buildID); upgradeNum++, BuildingID::advanceDwelling(buildID)) + for (; getTown()->buildings.count(buildID); upgradeNum++, BuildingID::advanceDwelling(buildID)) { - if (hasBuilt(buildID) && town->creatures.at(level).size() > upgradeNum) - creatures[level].second.push_back(town->creatures[level][upgradeNum]); + if (hasBuilt(buildID) && getTown()->creatures.at(level).size() > upgradeNum) + creatures[level].second.push_back(getTown()->creatures[level][upgradeNum]); } } initializeConfigurableBuildings(rand); @@ -623,9 +621,9 @@ void CGTownInstance::removeCapitols(const PlayerColor & owner) const if (hasCapitol()) // search if there's an older capitol { PlayerState* state = cb->gameState()->getPlayerState(owner); //get all towns owned by player - for (const auto & town : state->getTowns()) + for (const auto & otherTown : state->getTowns()) { - if (town != this && town->hasCapitol()) + if (otherTown != this && otherTown->hasCapitol()) { RazeStructures rs; rs.tid = id; @@ -648,7 +646,7 @@ void CGTownInstance::clearArmy() const BoatId CGTownInstance::getBoatType() const { - return town->faction->boatType; + return getTown()->faction->boatType; } int CGTownInstance::getMarketEfficiency() const @@ -703,7 +701,7 @@ void CGTownInstance::updateAppearance() std::string CGTownInstance::nodeName() const { - return "Town (" + (town ? town->faction->getNameTranslated() : "unknown") + ") of " + getNameTranslated(); + return "Town (" + getTown()->faction->getNameTranslated() + ") of " + getNameTranslated(); } void CGTownInstance::deserializationFix() @@ -752,7 +750,7 @@ void CGTownInstance::recreateBuildingsBonuses() for(const auto & upgradeID : builtBuildings) { - const auto & upgrade = town->buildings.at(upgradeID); + const auto & upgrade = getTown()->buildings.at(upgradeID); if (upgrade->getBase() == bid && upgrade->upgradeReplacesBonuses) bonusesReplacedByUpgrade = true; } @@ -761,7 +759,7 @@ void CGTownInstance::recreateBuildingsBonuses() if (bonusesReplacedByUpgrade) continue; - auto building = town->buildings.at(bid); + auto building = getTown()->buildings.at(bid); if(building->buildingBonuses.empty()) continue; @@ -828,21 +826,6 @@ bool CGTownInstance::armedGarrison() const return !stacks.empty() || garrisonHero; } -const CTown * CGTownInstance::getTown() const -{ - if(ID == Obj::RANDOM_TOWN) - return VLC->townh->randomTown; - else - { - if(nullptr == town) - { - return (*VLC->townh)[getFaction()]->town; - } - else - return town; - } -} - int CGTownInstance::getTownLevel() const { // count all buildings that are not upgrades @@ -850,7 +833,7 @@ int CGTownInstance::getTownLevel() const for(const auto & bid : builtBuildings) { - if(town->buildings.at(bid)->upgrade == BuildingID::NONE) + if(getTown()->buildings.at(bid)->upgrade == BuildingID::NONE) level++; } return level; @@ -892,7 +875,7 @@ bool CGTownInstance::hasBuilt(BuildingSubID::EBuildingSubID buildingID) const { for(const auto & bid : builtBuildings) { - if(town->buildings.at(bid)->subId == buildingID) + if(getTown()->buildings.at(bid)->subId == buildingID) return true; } return false; @@ -905,7 +888,7 @@ bool CGTownInstance::hasBuilt(const BuildingID & buildingID) const bool CGTownInstance::hasBuilt(const BuildingID & buildingID, FactionID townID) const { - if (townID == town->faction->getId() || townID == FactionID::ANY) + if (townID == getTown()->faction->getId() || townID == FactionID::ANY) return hasBuilt(buildingID); return false; } @@ -923,7 +906,7 @@ std::set CGTownInstance::availableModes() const std::set result; for (const auto & buildingID : builtBuildings) { - const auto * buildingPtr = town->buildings.at(buildingID).get(); + const auto * buildingPtr = getTown()->buildings.at(buildingID).get(); result.insert(buildingPtr->marketModes.begin(), buildingPtr->marketModes.end()); } @@ -950,8 +933,8 @@ std::set CGTownInstance::getBuildings() const TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const { - if (vstd::contains(town->buildings, buildingID)) - return town->buildings.at(buildingID)->resources; + if (vstd::contains(getTown()->buildings, buildingID)) + return getTown()->buildings.at(buildingID)->resources; else { logGlobal->error("Town %s at %s has no possible building %d!", getNameTranslated(), anchorPos().toString(), buildingID.toEnum()); @@ -962,7 +945,7 @@ TResources CGTownInstance::getBuildingCost(const BuildingID & buildingID) const CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID & buildID, bool deep) const { - const CBuilding * building = town->buildings.at(buildID); + const CBuilding * building = getTown()->buildings.at(buildID); //TODO: find better solution to prevent infinite loops std::set processed; @@ -970,13 +953,13 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID & std::function dependTest = [&](const BuildingID & id) -> CBuilding::TRequired::Variant { - if (town->buildings.count(id) == 0) + if (getTown()->buildings.count(id) == 0) { logMod->error("Invalid building ID %d in building dependencies!", id.getNum()); return CBuilding::TRequired::OperatorAll(); } - const CBuilding * build = town->buildings.at(id); + const CBuilding * build = getTown()->buildings.at(id); CBuilding::TRequired::OperatorAll requirements; if (!hasBuilt(id)) @@ -1001,7 +984,7 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID & CBuilding::TRequired::OperatorAll requirements; if (building->upgrade != BuildingID::NONE) { - const CBuilding * upgr = town->buildings.at(building->upgrade); + const CBuilding * upgr = getTown()->buildings.at(building->upgrade); requirements.expressions.push_back(dependTest(upgr->bid)); processed.clear(); @@ -1151,14 +1134,27 @@ void CGTownInstance::serializeJsonOptions(JsonSerializeFormat & handler) } } -FactionID CGTownInstance::getFaction() const +const CFaction * CGTownInstance::getFaction() const { - return FactionID(subID.getNum()); + return getFactionID().toFaction(); +} + +const CTown * CGTownInstance::getTown() const +{ + if(ID == Obj::RANDOM_TOWN) + return VLC->townh->randomTown; + + return getFaction()->town; +} + +FactionID CGTownInstance::getFactionID() const +{ + return FactionID(subID.getNum()); } TerrainId CGTownInstance::getNativeTerrain() const { - return town->faction->getNativeTerrain(); + return getTown()->faction->getNativeTerrain(); } ArtifactID CGTownInstance::getWarMachineInBuilding(BuildingID building) const @@ -1166,21 +1162,21 @@ ArtifactID CGTownInstance::getWarMachineInBuilding(BuildingID building) const if (builtBuildings.count(building) == 0) return ArtifactID::NONE; - if (building == BuildingID::BLACKSMITH && town->warMachineDeprecated.hasValue()) - return town->warMachineDeprecated.toCreature()->warMachine; + if (building == BuildingID::BLACKSMITH && getTown()->warMachineDeprecated.hasValue()) + return getTown()->warMachineDeprecated.toCreature()->warMachine; - return town->buildings.at(building)->warMachine; + return getTown()->buildings.at(building)->warMachine; } bool CGTownInstance::isWarMachineAvailable(ArtifactID warMachine) const { for (auto const & buildingID : builtBuildings) - if (town->buildings.at(buildingID)->warMachine == warMachine) + if (getTown()->buildings.at(buildingID)->warMachine == warMachine) return true; if (builtBuildings.count(BuildingID::BLACKSMITH) && - town->warMachineDeprecated.hasValue() && - town->warMachineDeprecated.toCreature()->warMachine == warMachine) + getTown()->warMachineDeprecated.hasValue() && + getTown()->warMachineDeprecated.toCreature()->warMachine == warMachine) return true; return false; @@ -1200,7 +1196,7 @@ GrowthInfo::Entry::Entry(int subID, const BuildingID & building, int _count): co { MetaString formatter; formatter.appendRawString("%s %+d"); - formatter.replaceRawString((*VLC->townh)[subID]->town->buildings.at(building)->getNameTranslated()); + formatter.replaceRawString(FactionID(subID).toFaction()->town->buildings.at(building)->getNameTranslated()); formatter.replacePositiveNumber(count); description = formatter.toString(); diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index f3b1f90fc..636f2bc5c 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -50,6 +50,7 @@ struct DLL_LINKAGE GrowthInfo class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public IMarket, public INativeTerrainProvider, public ICreatureUpgrader { + friend class CTownInstanceConstructor; std::string nameTextId; // name of town std::map convertOldBuildings(std::vector oldVector); @@ -59,7 +60,6 @@ public: enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3}; CTownAndVisitingHero townAndVis; - const CTown * town; si32 built; //how many buildings has been built this turn si32 destroyed; //how many buildings has been destroyed this turn ConstTransitivePtr garrisonHero, visitingHero; @@ -112,16 +112,21 @@ public: rewardableBuildings = convertOldBuildings(oldVector); } - if (h.saving) + if (h.version < Handler::Version::REMOVE_TOWN_PTR) { - CFaction * faction = town ? town->faction : nullptr; - h & faction; - } - else - { - CFaction * faction = nullptr; - h & faction; - town = faction ? faction->town : nullptr; + CTown * town = nullptr; + + if (h.saving) + { + CFaction * faction = town ? town->faction : nullptr; + h & faction; + } + else + { + CFaction * faction = nullptr; + h & faction; + town = faction ? faction->town : nullptr; + } } h & townAndVis; @@ -213,9 +218,10 @@ public: DamageRange getKeepDamageRange() const; const CTown * getTown() const; + const CFaction * getFaction() const; /// INativeTerrainProvider - FactionID getFaction() const override; + FactionID getFactionID() const override; TerrainId getNativeTerrain() const override; /// Returns ID of war machine that is produced by specified building or NONE if this is not built or if building does not produce war machines diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index b49e169ea..051349282 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -431,7 +431,7 @@ void CGSeerHut::setObjToKill() if(getCreatureToKill(true)) { - quest->stackToKill = getCreatureToKill(false)->getCreature(); + quest->stackToKill = getCreatureToKill(false)->getCreatureID(); assert(quest->stackToKill != CreatureID::NONE); quest->stackDirection = checkDirection(); } diff --git a/lib/mapObjects/TownBuildingInstance.cpp b/lib/mapObjects/TownBuildingInstance.cpp index cb8f2661b..2b485ef6d 100644 --- a/lib/mapObjects/TownBuildingInstance.cpp +++ b/lib/mapObjects/TownBuildingInstance.cpp @@ -73,14 +73,14 @@ TownRewardableBuildingInstance::TownRewardableBuildingInstance(CGTownInstance * void TownRewardableBuildingInstance::initObj(vstd::RNG & rand) { - assert(town && town->town); + assert(town && town->getTown()); configuration = generateConfiguration(rand); } Rewardable::Configuration TownRewardableBuildingInstance::generateConfiguration(vstd::RNG & rand) const { Rewardable::Configuration result; - auto building = town->town->buildings.at(getBuildingType()); + auto building = town->getTown()->buildings.at(getBuildingType()); building->rewardableObjectInfo.configureObject(result, rand, cb); for(auto & rewardInfo : result.info) diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index afd1d610d..57e3a4c24 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -302,7 +302,7 @@ void CMap::calculateGuardingGreaturePositions() CGHeroInstance * CMap::getHero(HeroTypeID heroID) { for(auto & elem : heroesOnMap) - if(elem->getHeroType() == heroID) + if(elem->getHeroTypeID() == heroID) return elem; return nullptr; } diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index bfdb2a289..1fe7da29f 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -896,7 +896,7 @@ void CMapLoaderH3M::readPredefinedHeroes() } map->predefinedHeroes.emplace_back(hero); - logGlobal->debug("Map '%s': Hero predefined in map: %s", mapName, VLC->heroh->getById(hero->getHeroType())->getJsonKey()); + logGlobal->debug("Map '%s': Hero predefined in map: %s", mapName, hero->getHeroType()->getJsonKey()); } } @@ -913,7 +913,7 @@ void CMapLoaderH3M::loadArtifactsOfHero(CGHeroInstance * hero) if(!hero->artifactsWorn.empty() || !hero->artifactsInBackpack.empty()) { - logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroType().getNum(), hero->anchorPos().toString()); + logGlobal->debug("Hero %d at %s has set artifacts twice (in map properties and on adventure map instance). Using the latter set...", hero->getHeroTypeID().getNum(), hero->anchorPos().toString()); hero->artifactsInBackpack.clear(); while(!hero->artifactsWorn.empty()) @@ -1778,7 +1778,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec for(auto & elem : map->disposedHeroes) { - if(elem.heroId == object->getHeroType()) + if(elem.heroId == object->getHeroTypeID()) { object->nameCustomTextId = elem.name; object->customPortraitSource = elem.portrait; @@ -1788,7 +1788,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec bool hasName = reader->readBool(); if(hasName) - object->nameCustomTextId = readLocalizedString(TextIdentifier("heroes", object->getHeroType().getNum(), "name")); + object->nameCustomTextId = readLocalizedString(TextIdentifier("heroes", object->getHeroTypeID().getNum(), "name")); if(features.levelSOD) { @@ -1891,7 +1891,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec auto ps = object->getAllBonuses(Selector::type()(BonusType::PRIMARY_SKILL).And(Selector::sourceType()(BonusSource::HERO_BASE_SKILL)), nullptr); if(ps->size()) { - logGlobal->debug("Hero %s has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", object->getHeroType().getNum() ); + logGlobal->debug("Hero %s has set primary skills twice (in map properties and on adventure map instance). Using the latter set...", object->getHeroTypeID().getNum() ); for(const auto & b : *ps) object->removeBonus(b); } @@ -1904,7 +1904,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(const int3 & mapPosition, const Objec } if (object->subID != MapObjectSubID()) - logGlobal->debug("Map '%s': Hero on map: %s at %s, owned by %s", mapName, VLC->heroh->getById(object->getHeroType())->getJsonKey(), mapPosition.toString(), object->getOwner().toString()); + logGlobal->debug("Map '%s': Hero on map: %s at %s, owned by %s", mapName, object->getHeroType()->getJsonKey(), mapPosition.toString(), object->getOwner().toString()); else logGlobal->debug("Map '%s': Hero on map: (random) at %s, owned by %s", mapName, mapPosition.toString(), object->getOwner().toString()); diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index b1a68b0ec..0777defed 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -436,10 +436,8 @@ void CMapFormatJson::serializePlayerInfo(JsonSerializeFormat & handler) if(hero->ID == Obj::HERO) { std::string temp; - if(hero->type) - temp = hero->type->getJsonKey(); - else - temp = hero->getHeroType().toEntity(VLC)->getJsonKey(); + if(hero->getHeroTypeID().hasValue()) + temp = hero->getHeroType()->getJsonKey(); handler.serializeString("type", temp); } @@ -1154,10 +1152,10 @@ void CMapLoaderJson::readObjects() auto * hero = dynamic_cast(object.get()); - if (debugHeroesOnMap.count(hero->getHeroType())) + if (debugHeroesOnMap.count(hero->getHeroTypeID())) logGlobal->error("Hero is already on the map at %s", hero->visitablePos().toString()); - debugHeroesOnMap.insert(hero->getHeroType()); + debugHeroesOnMap.insert(hero->getHeroTypeID()); } } diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 28c7a7ec9..6ea83ab8f 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1355,7 +1355,7 @@ void NewStructures::applyGs(CGameState *gs) for(const auto & id : bid) { - assert(t->town->buildings.at(id) != nullptr); + assert(t->getTown()->buildings.at(id) != nullptr); t->addBuilding(id); } t->updateAppearance(); @@ -1470,7 +1470,7 @@ void GiveHero::applyGs(CGameState *gs) auto oldVisitablePos = h->visitablePos(); gs->map->removeBlockVisTiles(h,true); - h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->type->heroClass->getIndex())->getTemplates().front(); + h->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, h->getHeroClassID().getNum())->getTemplates().front(); h->setOwner(player); h->setMovementPoints(h->movementPointsLimit(true)); diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index 41b7e7ee5..28f8fa178 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -292,7 +292,7 @@ TeleporterTilesVector CPathfinderHelper::getTeleportExits(const PathNodeInfo & s { auto * town = dynamic_cast(source.nodeObject); assert(town); - if (town && town->getFaction() == FactionID::INFERNO) + if (town && town->getFactionID() == FactionID::INFERNO) { /// TODO: Find way to reuse CPlayerSpecificInfoCallback::getTownsInfo /// This may be handy if we allow to use teleportation to friendly towns diff --git a/lib/rewardable/Limiter.cpp b/lib/rewardable/Limiter.cpp index 563db49e1..384ffea92 100644 --- a/lib/rewardable/Limiter.cpp +++ b/lib/rewardable/Limiter.cpp @@ -173,10 +173,10 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const if(!players.empty() && !vstd::contains(players, hero->getOwner())) return false; - if(!heroes.empty() && !vstd::contains(heroes, hero->type->getId())) + if(!heroes.empty() && !vstd::contains(heroes, hero->getHeroTypeID())) return false; - if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->type->heroClass->getId())) + if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->getHeroClassID())) return false; diff --git a/lib/rmg/modificators/ObjectManager.cpp b/lib/rmg/modificators/ObjectManager.cpp index a15ef0937..c256a85c1 100644 --- a/lib/rmg/modificators/ObjectManager.cpp +++ b/lib/rmg/modificators/ObjectManager.cpp @@ -733,7 +733,7 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard) continue; if(!cre->getAIValue()) //bug #2681 continue; - if(!vstd::contains(zone.getMonsterTypes(), cre->getFaction())) + if(!vstd::contains(zone.getMonsterTypes(), cre->getFactionID())) continue; if((static_cast(cre->getAIValue() * (cre->ammMin + cre->ammMax) / 2) < strength) && (strength < static_cast(cre->getAIValue()) * 100)) //at least one full monster. size between average size of given stack and 100 { diff --git a/lib/rmg/modificators/TownPlacer.cpp b/lib/rmg/modificators/TownPlacer.cpp index 0a3e412c4..1ab68779d 100644 --- a/lib/rmg/modificators/TownPlacer.cpp +++ b/lib/rmg/modificators/TownPlacer.cpp @@ -90,7 +90,7 @@ void TownPlacer::placeTowns(ObjectManager & manager) totalTowns++; //register MAIN town of zone only - map.registerZone(town->getFaction()); + map.registerZone(town->getFactionID()); if(player.isValidPlayer()) //configure info for owning player { @@ -213,7 +213,7 @@ void TownPlacer::addNewTowns(int count, bool hasFort, const PlayerColor & player { //FIXME: discovered bug with small zones - getPos is close to map boarder and we have outOfMap exception //register MAIN town of zone - map.registerZone(town->getFaction()); + map.registerZone(town->getFactionID()); //first town in zone goes in the middle placeMainTown(manager, *town); } diff --git a/lib/rmg/modificators/TreasurePlacer.cpp b/lib/rmg/modificators/TreasurePlacer.cpp index eb1b3c60f..781458d43 100644 --- a/lib/rmg/modificators/TreasurePlacer.cpp +++ b/lib/rmg/modificators/TreasurePlacer.cpp @@ -51,7 +51,7 @@ void TreasurePlacer::process() // Add all native creatures for(auto const & cre : VLC->creh->objects) { - if(!cre->special && cre->getFaction() == zone.getTownType()) + if(!cre->special && cre->getFactionID() == zone.getTownType()) { creatures.push_back(cre.get()); } @@ -192,7 +192,7 @@ void TreasurePlacer::addPrisons() { // Hero can be used again auto* hero = dynamic_cast(obj); - prisonHeroPlacer->restoreDrawnHero(hero->getHeroType()); + prisonHeroPlacer->restoreDrawnHero(hero->getHeroTypeID()); }; oi.setTemplates(Obj::PRISON, 0, zone.getTerrainType()); @@ -236,9 +236,9 @@ void TreasurePlacer::addDwellings() continue; const auto * cre = creatures.front(); - if(cre->getFaction() == zone.getTownType()) + if(cre->getFactionID() == zone.getTownType()) { - auto nativeZonesCount = static_cast(map.getZoneCount(cre->getFaction())); + auto nativeZonesCount = static_cast(map.getZoneCount(cre->getFactionID())); ObjectInfo oi(dwellingType, secondaryID); setBasicProperties(oi, CompoundMapObjectID(dwellingType, secondaryID)); @@ -375,7 +375,7 @@ void TreasurePlacer::addPandoraBoxesWithCreatures() return obj; }; oi.setTemplates(Obj::PANDORAS_BOX, 0, zone.getTerrainType()); - oi.value = static_cast(creature->getAIValue() * creaturesAmount * (1 + static_cast(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount())); + oi.value = static_cast(creature->getAIValue() * creaturesAmount * (1 + static_cast(map.getZoneCount(creature->getFactionID())) / map.getTotalZoneCount())); oi.probability = 3; if(!oi.templates.empty()) addObjectToRandomPool(oi); @@ -555,7 +555,7 @@ void TreasurePlacer::addSeerHuts() oi.destroyObject = destroyObject; oi.probability = 3; oi.setTemplates(Obj::SEER_HUT, randomAppearance, zone.getTerrainType()); - oi.value = static_cast(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast(map.getZoneCount(creature->getFaction())) / map.getTotalZoneCount())) - 4000) / 3); + oi.value = static_cast(((2 * (creature->getAIValue()) * creaturesAmount * (1 + static_cast(map.getZoneCount(creature->getFactionID())) / map.getTotalZoneCount())) - 4000) / 3); if (oi.value > zone.getMaxTreasureValue()) { continue; diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index 23de9965e..f8311a95b 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -26,7 +26,7 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) registerVectoredType(&gs->map->objects, [](const CGObjectInstance &obj){ return obj.id; }); registerVectoredType(&gs->map->allHeroes, - [](const CGHeroInstance &h){ return h.type->getId(); }); + [](const CGHeroInstance &h){ return h.getHeroType()->getId(); }); registerVectoredType(&gs->map->artInstances, [](const CArtifactInstance &artInst){ return artInst.getId(); }); registerVectoredType(&gs->map->quests, diff --git a/lib/serializer/ESerializationVersion.h b/lib/serializer/ESerializationVersion.h index 3f7845cff..d0fe579e4 100644 --- a/lib/serializer/ESerializationVersion.h +++ b/lib/serializer/ESerializationVersion.h @@ -63,6 +63,7 @@ enum class ESerializationVersion : int32_t REGION_LABEL, // 864 - labels for campaign regions SPELL_RESEARCH, // 865 - spell research LOCAL_PLAYER_STATE_DATA, // 866 - player state contains arbitrary client-side data + REMOVE_TOWN_PTR, // 867 - removed pointer to CTown from CGTownInstance - CURRENT = LOCAL_PLAYER_STATE_DATA + CURRENT = REMOVE_TOWN_PTR }; diff --git a/lib/spells/effects/Moat.cpp b/lib/spells/effects/Moat.cpp index 5be7c92fa..889644b88 100644 --- a/lib/spells/effects/Moat.cpp +++ b/lib/spells/effects/Moat.cpp @@ -88,7 +88,7 @@ void Moat::convertBonus(const Mechanics * m, std::vector & converted) con if(m->battle()->battleGetDefendedTown() && m->battle()->battleGetFortifications().hasMoat) { - nb.sid = BonusSourceID(m->battle()->battleGetDefendedTown()->town->buildings.at(BuildingID::CITADEL)->getUniqueTypeID()); + nb.sid = BonusSourceID(m->battle()->battleGetDefendedTown()->getTown()->buildings.at(BuildingID::CITADEL)->getUniqueTypeID()); nb.source = BonusSource::TOWN_STRUCTURE; } else diff --git a/lib/spells/effects/Summon.cpp b/lib/spells/effects/Summon.cpp index 5f9c4d34b..e46cdc6da 100644 --- a/lib/spells/effects/Summon.cpp +++ b/lib/spells/effects/Summon.cpp @@ -79,7 +79,7 @@ bool Summon::applicable(Problem & problem, const Mechanics * m) const text.replaceNamePlural(elemental->creatureId()); - if(caster->type->gender == EHeroGender::FEMALE) + if(caster->gender == EHeroGender::FEMALE) text.replaceLocalString(EMetaText::GENERAL_TXT, 540); else text.replaceLocalString(EMetaText::GENERAL_TXT, 539); diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index 30aa744a3..0fb5859ec 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -138,25 +138,11 @@ void Initializer::initialize(CGHeroInstance * o) o->subID = 0; o->tempOwner = PlayerColor::NEUTRAL; } - - if(o->ID == Obj::HERO) + + if(o->getHeroTypeID().hasValue()) { - for(auto const & t : VLC->heroh->objects) - { - if(t->heroClass->getId() == HeroClassID(o->subID)) - { - o->type = t.get(); - break; - } - } - } - - if(o->type) - { - // o->type = VLC->heroh->objects.at(o->subID); - - o->gender = o->type->gender; - o->randomizeArmy(o->type->heroClass->faction); + o->gender = o->getHeroType()->gender; + o->randomizeArmy(o->getFactionID()); } } @@ -304,7 +290,7 @@ void Inspector::updateProperties(CGHeroInstance * o) auto isPrison = o->ID == Obj::PRISON; addProperty("Owner", o->tempOwner, new OwnerDelegate(controller, isPrison), isPrison); //field is not editable for prison addProperty("Experience", o->exp, false); - addProperty("Hero class", o->type ? o->type->heroClass->getNameTranslated() : "", true); + addProperty("Hero class", o->getHeroClassID().hasValue() ? o->getHeroClass()->getNameTranslated() : "", true); { //Gender auto * delegate = new InspectorDelegate; @@ -319,20 +305,20 @@ void Inspector::updateProperties(CGHeroInstance * o) addProperty("Skills", PropertyEditorPlaceholder(), delegate, false); addProperty("Spells", PropertyEditorPlaceholder(), new HeroSpellDelegate(*o), false); - if(o->type || o->ID == Obj::PRISON) + if(o->getHeroTypeID().hasValue() || o->ID == Obj::PRISON) { //Hero type auto * delegate = new InspectorDelegate; - for(int i = 0; i < VLC->heroh->objects.size(); ++i) + for(const auto & heroPtr : VLC->heroh->objects) { - if(controller.map()->allowedHeroes.count(HeroTypeID(i)) != 0) + if(controller.map()->allowedHeroes.count(heroPtr->getId()) != 0) { - if(o->ID == Obj::PRISON || (o->type && VLC->heroh->objects[i]->heroClass->getIndex() == o->type->heroClass->getIndex())) + if(o->ID == Obj::PRISON || heroPtr->heroClass->getIndex() == o->getHeroClassID()) { - delegate->options.push_back({QObject::tr(VLC->heroh->objects[i]->getNameTranslated().c_str()), QVariant::fromValue(VLC->heroh->objects[i]->getId().getNum())}); + delegate->options.push_back({QObject::tr(heroPtr->getNameTranslated().c_str()), QVariant::fromValue(heroPtr->getIndex())}); } } } - addProperty("Hero type", o->type ? o->type->getNameTranslated() : "", delegate, false); + addProperty("Hero type", o->getHeroTypeID().hasValue() ? o->getHeroType()->getNameTranslated() : "", delegate, false); } } @@ -706,13 +692,10 @@ void Inspector::setProperty(CGHeroInstance * o, const QString & key, const QVari for(auto const & t : VLC->heroh->objects) { if(t->getId() == value.toInt()) - { o->subID = value.toInt(); - o->type = t.get(); - } } - o->gender = o->type->gender; - o->randomizeArmy(o->type->heroClass->faction); + o->gender = o->getHeroType()->gender; + o->randomizeArmy(o->getHeroType()->heroClass->faction); updateProperties(); //updating other properties after change } } diff --git a/mapeditor/inspector/townbuildingswidget.cpp b/mapeditor/inspector/townbuildingswidget.cpp index a90bd654a..4bf95c5c8 100644 --- a/mapeditor/inspector/townbuildingswidget.cpp +++ b/mapeditor/inspector/townbuildingswidget.cpp @@ -331,7 +331,7 @@ void TownBuildingsDelegate::setEditorData(QWidget *editor, const QModelIndex &in { if(auto * ed = qobject_cast(editor)) { - auto * ctown = town.town; + auto * ctown = town.getTown(); if(!ctown) ctown = VLC->townh->randomTown; if(!ctown) diff --git a/mapeditor/inspector/towneventdialog.cpp b/mapeditor/inspector/towneventdialog.cpp index e56af191e..475c42edc 100644 --- a/mapeditor/inspector/towneventdialog.cpp +++ b/mapeditor/inspector/towneventdialog.cpp @@ -100,7 +100,7 @@ void TownEventDialog::initResources() void TownEventDialog::initBuildings() { - auto * ctown = town.town; + auto * ctown = town.getTown(); if (!ctown) ctown = VLC->townh->randomTown; if (!ctown) @@ -156,7 +156,7 @@ QStandardItem * TownEventDialog::addBuilding(const CTown& ctown, BuildingID buil void TownEventDialog::initCreatures() { auto creatures = params.value("creatures").toList(); - auto * ctown = town.town; + auto * ctown = town.getTown(); if (!ctown) ui->creaturesTable->setRowCount(GameConstants::CREATURES_PER_TOWN); else diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index 5fc0c25ec..a30a90aa8 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -138,7 +138,7 @@ void MapController::repairMap(CMap * map) const // FIXME: How about custom scenarios where defeated hero cannot be hired again? - map->allowedHeroes.insert(nih->getHeroType()); + map->allowedHeroes.insert(nih->getHeroTypeID()); auto const & type = VLC->heroh->objects[nih->subID]; assert(type->heroClass); @@ -154,10 +154,6 @@ void MapController::repairMap(CMap * map) const nih->subTypeName = "prison"; nih->subID = 0; } - - if(obj->ID != Obj::RANDOM_HERO) - nih->type = type.get(); - if(nih->ID == Obj::HERO) //not prison nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); //fix spellbook diff --git a/mapeditor/playerparams.cpp b/mapeditor/playerparams.cpp index dc4cfee94..985c01d47 100644 --- a/mapeditor/playerparams.cpp +++ b/mapeditor/playerparams.cpp @@ -77,12 +77,10 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent) { if(auto town = dynamic_cast(controller.map()->objects[i].get())) { - auto * ctown = town->town; + auto * ctown = town->getTown(); if(!ctown) - { ctown = VLC->townh->randomTown; - town->town = ctown; - } + if(ctown && town->getOwner().getNum() == playerColor) { if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos) diff --git a/mapeditor/validator.cpp b/mapeditor/validator.cpp index fdab680b9..b4a98df30 100644 --- a/mapeditor/validator.cpp +++ b/mapeditor/validator.cpp @@ -122,13 +122,13 @@ std::set Validator::validate(const CMap * map) ++amountOfHeroes[ins->getOwner()]; } - if(ins->type) + if(ins->getHeroTypeID().hasValue()) { - if(map->allowedHeroes.count(ins->getHeroType()) == 0) - issues.insert({ tr("Hero %1 is prohibited by map settings").arg(ins->type->getNameTranslated().c_str()), false }); + if(map->allowedHeroes.count(ins->getHeroTypeID()) == 0) + issues.insert({ tr("Hero %1 is prohibited by map settings").arg(ins->getHeroType()->getNameTranslated().c_str()), false }); - if(!allHeroesOnMap.insert(ins->type).second) - issues.insert({ tr("Hero %1 has duplicate on map").arg(ins->type->getNameTranslated().c_str()), false }); + if(!allHeroesOnMap.insert(ins->getHeroType()).second) + issues.insert({ tr("Hero %1 has duplicate on map").arg(ins->getHeroType()->getNameTranslated().c_str()), false }); } else if(ins->ID != Obj::RANDOM_HERO) issues.insert({ tr("Hero %1 has an empty type and must be removed").arg(ins->instanceName.c_str()), true }); diff --git a/scripting/lua/api/Creature.cpp b/scripting/lua/api/Creature.cpp index 64c13c38b..5fca4601b 100644 --- a/scripting/lua/api/Creature.cpp +++ b/scripting/lua/api/Creature.cpp @@ -46,7 +46,7 @@ const std::vector CreatureProxy::REGISTER_CUSTOM = {"getLevel", LuaMethodWrapper::invoke, false}, {"getGrowth", LuaMethodWrapper::invoke, false}, {"getHorde", LuaMethodWrapper::invoke, false}, - {"getFaction", LuaMethodWrapper::invoke, false}, + {"getFactionID", LuaMethodWrapper::invoke, false}, {"getBaseAttack", LuaMethodWrapper::invoke, false}, {"getBaseDefense", LuaMethodWrapper::invoke, false}, diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 42e1961ab..1f9549fa0 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -162,7 +162,7 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero) hlu.player = hero->tempOwner; hlu.heroId = hero->id; hlu.primskill = primarySkill; - hlu.skills = hero->getLevelUpProposedSecondarySkills(heroPool->getHeroSkillsRandomGenerator(hero->getHeroType())); + hlu.skills = hero->getLevelUpProposedSecondarySkills(heroPool->getHeroSkillsRandomGenerator(hero->getHeroTypeID())); if (hlu.skills.size() == 0) { @@ -553,7 +553,7 @@ void CGameHandler::init(StartInfo *si, Load::ProgressAccumulator & progressTrack for (auto & elem : gs->map->allHeroes) { if(elem) - heroPool->getHeroSkillsRandomGenerator(elem->getHeroType()); // init RMG seed + heroPool->getHeroSkillsRandomGenerator(elem->getHeroTypeID()); // init RMG seed } reinitScripting(); @@ -569,12 +569,12 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa return; } - if (forced || town->creatures.at(town->town->creatures.size()).second.empty())//we need to change creature + if (forced || town->creatures.at(town->getTown()->creatures.size()).second.empty())//we need to change creature { SetAvailableCreatures ssi; ssi.tid = town->id; ssi.creatures = town->creatures; - ssi.creatures[town->town->creatures.size()].second.clear();//remove old one + ssi.creatures[town->getTown()->creatures.size()].second.clear();//remove old one std::set availableCreatures; for (const auto & dwelling : p->getOwnedObjects()) @@ -590,13 +590,13 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa if (clear) { - ssi.creatures[town->town->creatures.size()].first = std::max(1, (creatureId.toEntity(VLC)->getGrowth())/2); + ssi.creatures[town->getTown()->creatures.size()].first = std::max(1, (creatureId.toEntity(VLC)->getGrowth())/2); } else { - ssi.creatures[town->town->creatures.size()].first = creatureId.toEntity(VLC)->getGrowth(); + ssi.creatures[town->getTown()->creatures.size()].first = creatureId.toEntity(VLC)->getGrowth(); } - ssi.creatures[town->town->creatures.size()].second.push_back(creatureId); + ssi.creatures[town->getTown()->creatures.size()].second.push_back(creatureId); sendAndApply(ssi); } } @@ -657,7 +657,7 @@ void CGameHandler::onNewTurn() PlayerColor player = t->tempOwner; if(t->hasBuilt(BuildingID::GRAIL) - && t->town->buildings.at(BuildingID::GRAIL)->height == CBuilding::HEIGHT_SKYSHIP) + && t->getTown()->buildings.at(BuildingID::GRAIL)->height == CBuilding::HEIGHT_SKYSHIP) { // Skyship, probably easier to handle same as Veil of darkness // do it every new day before veils @@ -1048,7 +1048,7 @@ bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui if (((h->getOwner() != t->getOwner()) && complain("Cannot teleport hero to another player")) - || (from->town->faction->getId() != t->town->faction->getId() + || (from->getFactionID() != t->getFactionID() && complain("Source town and destination town should belong to the same faction")) || ((!from || !from->hasBuilt(BuildingSubID::CASTLE_GATE)) @@ -1212,7 +1212,7 @@ void CGameHandler::visitCastleObjects(const CGTownInstance * t, std::vectorrewardableBuildings) { - if (!t->town->buildings.at(building.first)->manualHeroVisit && t->hasBuilt(building.first)) + if (!t->getTown()->buildings.at(building.first)->manualHeroVisit && t->hasBuilt(building.first)) buildingsToVisit.push_back(building.first); } @@ -2036,12 +2036,12 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, const CGTownInstance * t = getTown(tid); if(!t) COMPLAIN_RETF("No such town (ID=%s)!", tid); - if(!t->town->buildings.count(requestedID)) - COMPLAIN_RETF("Town of faction %s does not have info about building ID=%s!", t->town->faction->getNameTranslated() % requestedID); + if(!t->getTown()->buildings.count(requestedID)) + COMPLAIN_RETF("Town of faction %s does not have info about building ID=%s!", t->getFaction()->getNameTranslated() % requestedID); if(t->hasBuilt(requestedID)) - COMPLAIN_RETF("Building %s is already built in %s", t->town->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated()); + COMPLAIN_RETF("Building %s is already built in %s", t->getTown()->buildings.at(requestedID)->getNameTranslated() % t->getNameTranslated()); - const CBuilding * requestedBuilding = t->town->buildings.at(requestedID); + const CBuilding * requestedBuilding = t->getTown()->buildings.at(requestedID); //Vector with future list of built building and buildings in auto-mode that are not yet built. std::vector remainingAutoBuildings; @@ -2081,7 +2081,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, int level = BuildingID::getLevelFromDwelling(buildingID); int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID); - if(upgradeNumber >= t->town->creatures.at(level).size()) + if(upgradeNumber >= t->getTown()->creatures.at(level).size()) { complain(boost::str(boost::format("Error encountered when building dwelling (bid=%s):" "no creature found (upgrade number %d, level %d!") @@ -2089,7 +2089,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, return; } - const CCreature * crea = t->town->creatures.at(level).at(upgradeNumber).toCreature(); + const CCreature * crea = t->getTown()->creatures.at(level).at(upgradeNumber).toCreature(); SetAvailableCreatures ssi; ssi.tid = t->id; @@ -2099,7 +2099,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, ssi.creatures[level].second.push_back(crea->getId()); sendAndApply(ssi); } - if(t->town->buildings.at(buildingID)->subId == BuildingSubID::PORTAL_OF_SUMMONING) + if(t->getTown()->buildings.at(buildingID)->subId == BuildingSubID::PORTAL_OF_SUMMONING) { setPortalDwelling(t); } @@ -2110,9 +2110,9 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, { auto isMageGuild = (buildingID <= BuildingID::MAGES_GUILD_5 && buildingID >= BuildingID::MAGES_GUILD_1); auto isLibrary = isMageGuild ? false - : t->town->buildings.at(buildingID)->subId == BuildingSubID::EBuildingSubID::LIBRARY; + : t->getTown()->buildings.at(buildingID)->subId == BuildingSubID::EBuildingSubID::LIBRARY; - if(isMageGuild || isLibrary || (t->getFaction() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL)) + if(isMageGuild || isLibrary || (t->getFactionID() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL)) { if(t->visitingHero) giveSpells(t,t->visitingHero); @@ -2128,7 +2128,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, }; //Init the vectors - for(auto & build : t->town->buildings) + for(auto & build : t->getTown()->buildings) { if(t->hasBuilt(build.first)) { @@ -2212,7 +2212,7 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid) if(!t->hasBuilt(bid)) return false; - auto subID = t->town->buildings.at(bid)->subId; + auto subID = t->getTown()->buildings.at(bid)->subId; if(subID == BuildingSubID::EBuildingSubID::BANK) { @@ -2224,7 +2224,7 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid) return true; } - if (t->rewardableBuildings.count(bid) && t->visitingHero && t->town->buildings.at(bid)->manualHeroVisit) + if (t->rewardableBuildings.count(bid) && t->visitingHero && t->getTown()->buildings.at(bid)->manualHeroVisit) { std::vector buildingsToVisit; std::vector visitors; diff --git a/server/processors/HeroPoolProcessor.cpp b/server/processors/HeroPoolProcessor.cpp index fd26db5f5..44a50884a 100644 --- a/server/processors/HeroPoolProcessor.cpp +++ b/server/processors/HeroPoolProcessor.cpp @@ -47,8 +47,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(heroes[0]->getHeroType()); - auto roleRight = heroesPool->getSlotRole(heroes[1]->getHeroType()); + auto roleLeft = heroesPool->getSlotRole(heroes[0]->getHeroTypeID()); + auto roleRight = heroesPool->getSlotRole(heroes[1]->getHeroTypeID()); if (roleLeft > roleRight) return TavernHeroSlot::RANDOM; @@ -70,7 +70,7 @@ void HeroPoolProcessor::onHeroSurrendered(const PlayerColor & color, const CGHer sah.slotID = selectSlotForRole(color, sah.roleID); sah.player = color; - sah.hid = hero->getHeroType(); + sah.hid = hero->getHeroTypeID(); sah.replenishPoints = false; gameHandler->sendAndApply(sah); } @@ -82,9 +82,9 @@ void HeroPoolProcessor::onHeroEscaped(const PlayerColor & color, const CGHeroIns sah.slotID = selectSlotForRole(color, sah.roleID); sah.player = color; - sah.hid = hero->getHeroType(); + sah.hid = hero->getHeroTypeID(); sah.army.clearSlots(); - sah.army.setCreature(SlotID(0), hero->type->initialArmy.at(0).creature, 1); + sah.army.setCreature(SlotID(0), hero->getHeroType()->initialArmy.at(0).creature, 1); sah.replenishPoints = false; gameHandler->sendAndApply(sah); @@ -112,7 +112,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe if (newHero) { - sah.hid = newHero->getHeroType(); + sah.hid = newHero->getHeroTypeID(); if (giveArmy) { @@ -123,7 +123,7 @@ void HeroPoolProcessor::selectNewHeroForSlot(const PlayerColor & color, TavernHe { sah.roleID = TavernSlotRole::SINGLE_UNIT; sah.army.clearSlots(); - sah.army.setCreature(SlotID(0), newHero->type->initialArmy[0].creature, 1); + sah.army.setCreature(SlotID(0), newHero->getHeroType()->initialArmy[0].creature, 1); } } else @@ -208,7 +208,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy for(const auto & hero : recruitableHeroes) { - if(hero->getHeroType() == heroToRecruit) + if(hero->getHeroTypeID() == heroToRecruit) recruitedHero = hero; } @@ -221,7 +221,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy HeroRecruited hr; hr.tid = mapObject->id; - hr.hid = recruitedHero->getHeroType(); + hr.hid = recruitedHero->getHeroTypeID(); hr.player = player; hr.tile = recruitedHero->convertFromVisitablePos(targetPos ); if(gameHandler->getTile(targetPos)->isWater() && !recruitedHero->boat) @@ -258,14 +258,14 @@ std::vector HeroPoolProcessor::findAvailableClassesFor(const for(const auto & elem : heroesPool->unusedHeroesFromPool()) { - if (vstd::contains(result, elem.second->type->heroClass)) + if (vstd::contains(result, elem.second->getHeroClass())) continue; bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player); - bool heroClassBanned = elem.second->type->heroClass->tavernProbability(factionID) == 0; + bool heroClassBanned = elem.second->getHeroClass()->tavernProbability(factionID) == 0; if(heroAvailable && !heroClassBanned) - result.push_back(elem.second->type->heroClass); + result.push_back(elem.second->getHeroClass()); } return result; @@ -282,7 +282,7 @@ std::vector HeroPoolProcessor::findAvailableHeroesFor(const Pl assert(!vstd::contains(result, elem.second)); bool heroAvailable = heroesPool->isHeroAvailableFor(elem.first, player); - bool heroClassMatches = elem.second->type->heroClass == heroClass; + bool heroClassMatches = elem.second->getHeroClass() == heroClass; if(heroAvailable && heroClassMatches) result.push_back(elem.second); @@ -318,7 +318,7 @@ const CHeroClass * HeroPoolProcessor::pickClassFor(bool isNative, const PlayerCo continue; bool hasSameClass = vstd::contains_if(currentTavern, [&](const CGHeroInstance * hero){ - return hero->type->heroClass == heroClass; + return hero->getHeroClass() == heroClass; }); if (hasSameClass) diff --git a/server/processors/NewTurnProcessor.cpp b/server/processors/NewTurnProcessor.cpp index a1c9c61b8..f87c380f4 100644 --- a/server/processors/NewTurnProcessor.cpp +++ b/server/processors/NewTurnProcessor.cpp @@ -95,10 +95,10 @@ void NewTurnProcessor::handleTownEvents(const CGTownInstance * town) // 1. Building exists in town (don't attempt to build Lvl 5 guild in Fortress // 2. Building was not built yet // othervice, silently ignore / skip it - if (town->town->buildings.count(i) && !town->hasBuilt(i)) + if (town->getTown()->buildings.count(i) && !town->hasBuilt(i)) { gameHandler->buildStructure(town->id, i, true); - iw.components.emplace_back(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), i)); + iw.components.emplace_back(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFactionID(), i)); } } @@ -246,7 +246,7 @@ SetAvailableCreatures NewTurnProcessor::generateTownGrowth(const CGTownInstance sac.tid = t->id; sac.creatures = t->creatures; - for (int k=0; k < t->town->creatures.size(); k++) + for (int k=0; k < t->getTown()->creatures.size(); k++) { if (t->creatures.at(k).second.empty()) continue; @@ -345,7 +345,7 @@ void NewTurnProcessor::updateNeutralTownGarrison(const CGTownInstance * t, int c { const auto * creature = slot.second->type; - if (creature->getFaction() != t->getFaction()) + if (creature->getFactionID() != t->getFactionID()) continue; if (creature->getLevel() != tierToGrow) @@ -518,7 +518,7 @@ std::tuple NewTurnProcessor::pickWeekType(bool newMonth) { newMonster.second = VLC->creh->pickRandomMonster(gameHandler->getRandomGenerator()); } while (VLC->creh->objects[newMonster.second] && - (*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFaction()]->town == nullptr); // find first non neutral creature + (*VLC->townh)[VLC->creatures()->getById(newMonster.second)->getFactionID()]->town == nullptr); // find first non neutral creature return { EWeekType::BONUS_GROWTH, newMonster.second}; } diff --git a/server/processors/PlayerMessageProcessor.cpp b/server/processors/PlayerMessageProcessor.cpp index 83183d478..6ebc78375 100644 --- a/server/processors/PlayerMessageProcessor.cpp +++ b/server/processors/PlayerMessageProcessor.cpp @@ -370,7 +370,7 @@ void PlayerMessageProcessor::cheatBuildTown(PlayerColor player, const CGTownInst if (!town) return; - for (auto & build : town->town->buildings) + for (auto & build : town->getTown()->buildings) { if (!town->hasBuilt(build.first) && !build.second->getNameTranslated().empty() diff --git a/test/entity/CCreatureTest.cpp b/test/entity/CCreatureTest.cpp index 590754e73..3d963df09 100644 --- a/test/entity/CCreatureTest.cpp +++ b/test/entity/CCreatureTest.cpp @@ -100,7 +100,7 @@ TEST_F(CCreatureTest, DISABLED_JsonUpdate) EXPECT_EQ(subject->getFightValue(), 2420); EXPECT_EQ(subject->getLevel(), 6); - EXPECT_EQ(subject->getFaction().getNum(), 55); + EXPECT_EQ(subject->getFactionID().getNum(), 55); EXPECT_TRUE(subject->isDoubleWide()); } diff --git a/test/mock/mock_Creature.h b/test/mock/mock_Creature.h index 6dacd4815..cb51a595a 100644 --- a/test/mock/mock_Creature.h +++ b/test/mock/mock_Creature.h @@ -44,7 +44,7 @@ public: MOCK_CONST_METHOD0(getLevel, int32_t()); MOCK_CONST_METHOD0(getGrowth, int32_t()); MOCK_CONST_METHOD0(getHorde, int32_t()); - MOCK_CONST_METHOD0(getFaction, FactionID()); + MOCK_CONST_METHOD0(getFactionID, FactionID()); MOCK_CONST_METHOD0(getBaseAttack, int32_t()); MOCK_CONST_METHOD0(getBaseDefense, int32_t()); diff --git a/test/mock/mock_battle_Unit.h b/test/mock/mock_battle_Unit.h index 5f2b03bf0..7560bfdc8 100644 --- a/test/mock/mock_battle_Unit.h +++ b/test/mock/mock_battle_Unit.h @@ -82,7 +82,7 @@ public: MOCK_CONST_METHOD1(willMove, bool(int)); MOCK_CONST_METHOD1(waited, bool(int)); - MOCK_CONST_METHOD0(getFaction, FactionID()); + MOCK_CONST_METHOD0(getFactionID, FactionID()); MOCK_CONST_METHOD1(battleQueuePhase, battle::BattlePhases::Type(int));