Hooks
static bool BeforeCvCity_read(CvCity* self, FDataStream& kStream);static void AfterCvCity_read(CvCity* self, FDataStream& kStream);static void ReplaceCvCity_read(void (*original)(CvCity*, FDataStream&), CvCity* self, FDataStream& kStream);CivRegisterBefore<CivHooks::CvCity_read>(host, &BeforeCvCity_read);CivRegisterAfter<CivHooks::CvCity_read>(host, &AfterCvCity_read);CivRegisterReplace<CivHooks::CvCity_read>(host, &ReplaceCvCity_read);
Code
15136void CvCity::read(FDataStream& kStream)15137{15138 VALIDATE_OBJECT15139 // Init data before load15140 reset();1514115142 // Version number to maintain backwards compatibility15143 uint uiVersion;15144 kStream >> uiVersion;15145 MOD_SERIALIZE_INIT_READ(kStream);1514615147 kStream >> m_iID;15148 kStream >> m_iX;15149 kStream >> m_iY;15150 kStream >> m_iRallyX;15151 kStream >> m_iRallyY;15152 kStream >> m_iGameTurnFounded;15153 kStream >> m_iGameTurnAcquired;15154 kStream >> m_iPopulation;15155 kStream >> m_iHighestPopulation;15156#if defined(MOD_GLOBAL_CITY_AUTOMATON_WORKERS)15157 MOD_SERIALIZE_READ(89, kStream, m_iAutomatons, 0);15158#endif15159#if defined(MOD_BUILDINGS_CITY_AUTOMATON_WORKERS)15160 MOD_SERIALIZE_READ(90, kStream, m_iCityAutomatonWorkersChange, 0);15161#endif15162 kStream >> m_iNumGreatPeople;15163 kStream >> m_iBaseGreatPeopleRate;15164 kStream >> m_iGreatPeopleRateModifier;15165 kStream >> m_iJONSCultureStored;15166 kStream >> m_iJONSCultureLevel;15167 kStream >> m_iJONSCulturePerTurnFromBuildings;15168 kStream >> m_iJONSCulturePerTurnFromPolicies;15169 kStream >> m_iJONSCulturePerTurnFromSpecialists;15170 kStream >> m_iJONSCulturePerTurnFromReligion;15171 kStream >> m_iFaithPerTurnFromBuildings;15172 kStream >> m_iFaithPerTurnFromPolicies;15173 kStream >> m_iFaithPerTurnFromReligion;1517415175 kStream >> m_iCultureRateModifier;15176 kStream >> m_iNumWorldWonders;15177 kStream >> m_iNumTeamWonders;15178 kStream >> m_iNumNationalWonders;15179 kStream >> m_iWonderProductionModifier;15180 kStream >> m_iCapturePlunderModifier;15181 kStream >> m_iPlotCultureCostModifier;15182 kStream >> m_iPlotBuyCostModifier;15183#if defined(MOD_BUILDINGS_CITY_WORKING)15184 MOD_SERIALIZE_READ(23, kStream, m_iCityWorkingChange, 0);15185#endif15186#if defined(MOD_BUILDINGS_CITY_AUTOMATON_WORKERS)15187 // SEE ABOVE - MOD_SERIALIZE_READ(90, kStream, m_iCityAutomatonWorkersChange, 0);15188#endif15189 kStream >> m_iMaintenance;15190 kStream >> m_iHealRate;15191 kStream >> m_iEspionageModifier;15192#if defined(MOD_RELIGION_CONVERSION_MODIFIERS)15193 MOD_SERIALIZE_READ(23, kStream, m_iConversionModifier, 0);15194#endif15195 kStream >> m_iNoOccupiedUnhappinessCount;15196 kStream >> m_iFood;15197 kStream >> m_iFoodKept;15198 kStream >> m_iMaxFoodKeptPercent;15199 kStream >> m_iOverflowProduction;15200 kStream >> m_iFeatureProduction;15201 kStream >> m_iMilitaryProductionModifier;15202 kStream >> m_iSpaceProductionModifier;15203 kStream >> m_iFreeExperience;15204 kStream >> m_iCurrAirlift; // unused1520515206 if (uiVersion >= 6)15207 {15208 kStream >> m_iMaxAirUnits; 15209 }15210 else15211 {15212 kStream >> m_iMaxAirUnits;1521315214 // Forcibly override this since we didn't track this number before15215 m_iMaxAirUnits = GC.getBASE_CITY_AIR_STACKING();1521615217 // Note that this can get boosted further below once we know which buildings we have15218 }15219 kStream >> m_iAirModifier; // unused15220 kStream >> m_iNukeModifier;1522115222 if (uiVersion >= 2)15223 {15224 kStream >> m_iTradeRouteTargetBonus;15225 kStream >> m_iTradeRouteRecipientBonus;15226 }15227 else15228 {15229 m_iTradeRouteTargetBonus = 0;15230 m_iTradeRouteRecipientBonus = 0;15231 }1523215233 kStream >> m_iCultureUpdateTimer;15234 kStream >> m_iCitySizeBoost;15235 kStream >> m_iSpecialistFreeExperience;15236 kStream >> m_iStrengthValue;15237 kStream >> m_iDamage;15238 kStream >> m_iThreatValue;15239 kStream >> m_iGarrisonedUnit;15240 m_iResourceDemanded = CvInfosSerializationHelper::ReadHashed(kStream);15241 kStream >> m_iWeLoveTheKingDayCounter;15242 kStream >> m_iLastTurnGarrisonAssigned;15243 kStream >> m_iThingsProduced;15244 kStream >> m_iDemandResourceCounter;15245 kStream >> m_iResistanceTurns;15246 kStream >> m_iRazingTurns;15247 kStream >> m_iCountExtraLuxuries;15248 kStream >> m_iCheapestPlotInfluence;15249 kStream >> m_unitBeingBuiltForOperation.m_iOperationID;15250 kStream >> m_unitBeingBuiltForOperation.m_iArmyID;15251 kStream >> m_unitBeingBuiltForOperation.m_iSlotID;1525215253 kStream >> m_bNeverLost;15254 kStream >> m_bDrafted;15255 kStream >> m_bAirliftTargeted; // unused15256 kStream >> m_bProductionAutomated;15257 kStream >> m_bMadeAttack;15258 kStream >> m_bOccupied;15259 kStream >> m_bPuppet;15260 kStream >> m_bEverCapital;15261 kStream >> m_bIndustrialRouteToCapital;15262 kStream >> m_bFeatureSurrounded;1526315264 kStream >> m_eOwner;15265 kStream >> m_ePreviousOwner;15266 kStream >> m_eOriginalOwner;15267 kStream >> m_ePlayersReligion;1526815269 kStream >> m_aiSeaPlotYield;15270 kStream >> m_aiRiverPlotYield;15271 kStream >> m_aiLakePlotYield;15272 kStream >> m_aiSeaResourceYield;15273 kStream >> m_aiBaseYieldRateFromTerrain;15274 kStream >> m_aiBaseYieldRateFromBuildings;15275 kStream >> m_aiBaseYieldRateFromSpecialists;15276 kStream >> m_aiBaseYieldRateFromMisc;15277 kStream >> m_aiBaseYieldRateFromReligion;15278 kStream >> m_aiYieldPerPop;15279 if (uiVersion >= 4)15280 {15281 kStream >> m_aiYieldPerReligion;15282 }15283 else15284 {15285 for (int iI = 0; iI < NUM_YIELD_TYPES; iI++)15286 {15287 m_aiYieldPerReligion[iI] = 0;15288 }15289 }15290 kStream >> m_aiYieldRateModifier;15291 kStream >> m_aiPowerYieldRateModifier;15292 kStream >> m_aiResourceYieldRateModifier;15293 kStream >> m_aiExtraSpecialistYield;15294 kStream >> m_aiProductionToYieldModifier;15295 kStream >> m_aiDomainFreeExperience;15296 kStream >> m_aiDomainProductionModifier;1529715298 kStream >> m_abEverOwned;15299 kStream >> m_abRevealed;1530015301 kStream >> m_strName;15302 kStream >> m_strScriptData;1530315304 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiNoResource.dirtyGet());15305 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiFreeResource.dirtyGet());15306 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiNumResourcesLocal.dirtyGet());1530715308 kStream >> m_paiSpecialistProduction;15309 kStream >> m_paiProjectProduction;1531015311 m_pCityBuildings->Read(kStream);1531215313 if (uiVersion < 6)15314 {15315 CvCivilizationInfo& thisCivInfo = *GC.getCivilizationInfo(getCivilizationType());15316 for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)15317 {15318 BuildingClassTypes eBuildingClass = (BuildingClassTypes)iI;15319 BuildingTypes eBuilding = (BuildingTypes)(thisCivInfo.getCivilizationBuildings(eBuildingClass));15320 if (eBuilding != NO_BUILDING)15321 {15322 CvBuildingEntry *pkEntry = GC.getBuildingInfo(eBuilding);15323 if (pkEntry)15324 {15325 if (pkEntry->GetAirModifier() > 0 && m_pCityBuildings->GetNumBuilding(eBuilding) > 0)15326 {15327#if defined(MOD_BUGFIX_MINOR)15328 m_iMaxAirUnits += pkEntry->GetAirModifier() * m_pCityBuildings->GetNumBuilding(eBuilding);15329#else15330 m_iMaxAirUnits += pkEntry->GetAirModifier();15331#endif15332 }15333 }15334 }15335 }15336 }1533715338 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiUnitProduction.dirtyGet());15339 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiUnitProductionTime.dirtyGet());1534015341 kStream >> m_paiSpecialistCount;15342 kStream >> m_paiMaxSpecialistCount;15343 kStream >> m_paiForceSpecialistCount;15344 kStream >> m_paiFreeSpecialistCount;15345 kStream >> m_paiImprovementFreeSpecialists;15346 kStream >> m_paiUnitCombatFreeExperience;15347 kStream >> m_paiUnitCombatProductionModifier;1534815349 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_paiFreePromotionCount.dirtyGet());1535015351 UINT uLength;15352 kStream >> uLength;15353 for(UINT uIdx = 0; uIdx < uLength; ++uIdx)15354 {15355 OrderData Data;1535615357 kStream >> Data.eOrderType;15358 if (uiVersion >= 5)15359 {15360 // Translate the data15361 switch (Data.eOrderType)15362 {15363 case ORDER_TRAIN:15364 Data.iData1 = CvInfosSerializationHelper::ReadHashed(kStream);15365 kStream >> Data.iData2; // This is a UnitAIType, but no code respects the ordering in GC.getUnitAIInfo15366 break;1536715368 case ORDER_CONSTRUCT:15369 Data.iData1 = CvInfosSerializationHelper::ReadHashed(kStream);15370 kStream >> Data.iData2;15371 break;1537215373 case ORDER_CREATE:15374 Data.iData1 = CvInfosSerializationHelper::ReadHashed(kStream);15375 kStream >> Data.iData2;15376 break;1537715378 case ORDER_PREPARE:15379 Data.iData1 = CvInfosSerializationHelper::ReadHashed(kStream);15380 kStream >> Data.iData2;15381 break;1538215383 case ORDER_MAINTAIN:15384 Data.iData1 = CvInfosSerializationHelper::ReadHashed(kStream);15385 kStream >> Data.iData2;15386 break;1538715388 default:15389 CvAssertMsg(false, "pData->eOrderType failed to match a valid option");15390 kStream >> Data.iData1;15391 kStream >> Data.iData2;15392 break;15393 }15394 }15395 else15396 {15397 kStream >> Data.iData1;15398 kStream >> Data.iData2;15399 }1540015401 kStream >> Data.bSave;15402 kStream >> Data.bRush;1540315404 bool bIsValid = false;15405 switch (Data.eOrderType)15406 {15407 case ORDER_TRAIN:15408 bIsValid = GC.getUnitInfo( (UnitTypes)Data.iData1 ) != NULL;15409 CvAssertMsg(bIsValid, "Unit in build queue is invalid");15410 break;1541115412 case ORDER_CONSTRUCT:15413 bIsValid = GC.getBuildingInfo( (BuildingTypes)Data.iData1 ) != NULL;15414 CvAssertMsg(bIsValid, "Building in build queue is invalid");15415 break;1541615417 case ORDER_CREATE:15418 bIsValid = GC.getProjectInfo( (ProjectTypes)Data.iData1 ) != NULL;15419 CvAssertMsg(bIsValid, "Project in build queue is invalid");15420 break;1542115422 case ORDER_PREPARE:15423 bIsValid = GC.getSpecialistInfo( (SpecialistTypes)Data.iData1 ) != NULL;15424 CvAssertMsg(bIsValid, "Specialize in build queue is invalid");15425 break;1542615427 case ORDER_MAINTAIN:15428 bIsValid = GC.getProcessInfo( (ProcessTypes)Data.iData1 ) != NULL;15429 CvAssertMsg(bIsValid, "Process in build queue is invalid");15430 break;15431 }1543215433 if (bIsValid)15434 m_orderQueue.insertAtEnd(&Data);15435 }1543615437 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_ppaiResourceYieldChange, NUM_YIELD_TYPES, GC.getNumResourceInfos());1543815439 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_ppaiFeatureYieldChange, NUM_YIELD_TYPES, GC.getNumFeatureInfos());1544015441 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_ppaiTerrainYieldChange, NUM_YIELD_TYPES, GC.getNumTerrainInfos());1544215443#if defined(MOD_API_UNIFIED_YIELDS) && defined(MOD_API_PLOT_YIELDS)15444 // MOD_SERIALIZE_READ - v57/v58/v59 broke the save format couldn't be helped, but don't make a habit of it!!!15445 CvInfosSerializationHelper::ReadHashedDataArray(kStream, m_ppaiPlotYieldChange, NUM_YIELD_TYPES, GC.getNumPlotInfos());15446#endif1544715448 kStream >> m_iPopulationRank;15449 kStream >> m_bPopulationRankValid;15450 kStream >> m_aiBaseYieldRank;15451 kStream >> m_abBaseYieldRankValid;15452 kStream >> m_aiYieldRank;15453 kStream >> m_abYieldRankValid;1545415455 kStream >> m_iGameTurnLastExpanded;15456 m_strName = "";1545715458 // City Building Happiness15459 kStream >> m_iBaseHappinessFromBuildings;15460 kStream >> m_iUnmoddedHappinessFromBuildings;1546115462 kStream >> m_bRouteToCapitalConnectedLastTurn;15463 kStream >> m_bRouteToCapitalConnectedThisTurn;15464 kStream >> m_strName;1546515466 kStream >> m_bOwedCultureBuilding;15467#if defined(MOD_BUGFIX_FREE_FOOD_BUILDING)15468 MOD_SERIALIZE_READ(30, kStream, m_bOwedFoodBuilding, false);15469#endif1547015471 m_pCityStrategyAI->Read(kStream);15472 if(m_eOwner != NO_PLAYER)15473 {15474 GET_PLAYER(getOwner()).GetFlavorManager()->AddFlavorRecipient(m_pCityStrategyAI, false /* bPropogateFlavorValues */);15475 }15476 m_pCityCitizens->Read(kStream);15477 kStream >> *m_pCityReligions;15478 m_pEmphases->Read(kStream);1547915480 kStream >> *m_pCityEspionage;1548115482 if (uiVersion >= 3)15483 {15484 kStream >> m_iExtraHitPoints;15485 }15486 else15487 {15488 // Recalculate15489 int iTotalExtraHitPoints = 0;15490 for(int eBuildingType = 0; eBuildingType < GC.getNumBuildingInfos(); eBuildingType++)15491 {15492 const BuildingTypes eBuilding = static_cast<BuildingTypes>(eBuildingType);15493 CvBuildingEntry* pkBuildingInfo = GC.getBuildingInfo(eBuilding);1549415495 if (pkBuildingInfo)15496 {15497 int iCount = m_pCityBuildings->GetNumBuilding(eBuilding);15498 if(iCount > 0)15499 {15500 iTotalExtraHitPoints += (pkBuildingInfo->GetExtraCityHitPoints() * iCount);15501 }15502 }15503 }1550415505 // Change all at once, rather than one by one, else the clamping might adjust the current damage.15506 ChangeExtraHitPoints(iTotalExtraHitPoints);15507 }1550815509 CvCityManager::OnCityCreated(this);15510}