Home › Dev CE (experimental) › City
Experimental: needs Dev CE (
fork of the Community Extension, release zip and source). A GameCore that adds these Lua methods by calling engine functions directly. Not part of the upstream Community Extension, single-player testing only. Descriptions on these pages were written by an AI assistant from decompiled code and are marked inferred unless a test result confirms them.
City
123 methods (Dev CE test build). this is found with the game's own ICity instance resolver (virtual).
| Method |
Signature |
Purpose (AI-written, inferred) |
Tested |
Engine function |
Current |
| AddCityAllowedImprovement |
City:AddCityAllowedImprovement(eImprovement: integer) |
Appends an improvement type to the city's allowed-improvement list (variable at this+0x1550), growing the vector as needed. |
plumbing ✓ |
— |
0x12f2b0 |
| AddCityHappinessModifier |
City:AddCityHappinessModifier(eHappiness: integer, eYield: integer, eGreatPersonClass: integer, iYieldChange: integer, iGreatPersonChange: integer) |
Appends a happiness modifier record (happiness type, yield, great person class, yield change, great person change) to the city's modifier list. |
plumbing ✓ |
City::Instance::AddCityHappinessModifier |
0x12f320 |
| AddCityTerrainModifier |
City:AddCityTerrainModifier(eTerrain: integer, eAdjacentImprovement: integer, eYield: integer, iYieldChange: integer) |
Appends a (terrain, adjacent improvement, yield, change) record to the city terrain modifier list (this+0x740) if the change is positive and the improvement is not -1. |
plumbing ✓ |
— |
0x12f3a0 |
| AddCityValidTerrainImprovement |
City:AddCityValidTerrainImprovement(eImprovement: integer, eTerrain: integer) |
Appends an (improvement, terrain) pair to the city valid-terrain-improvement list (this+0x770), making the improvement valid on that terrain in this city. |
plumbing ✓ |
— |
0x12f410 |
| AddYieldPerTerrainClassCitiesImprovement |
City:AddYieldPerTerrainClassCitiesImprovement(eYield: integer, eImprovement: integer, iDelta: integer) |
Appends an (improvement, yield, delta) record to the city list at this+0x7a0 (yield per terrain class cities improvement); skipped if improvement or yield is -1. |
plumbing ✓ |
— |
0x12fd30 |
| AddYieldPerTerrainType |
City:AddYieldPerTerrainType(eTerrain: integer, eYield: integer, xValue: number (fixed point, 1/256 steps)) |
Appends a (terrain, yield, fixed-point value) record to the city list at this+0x830 that drives CalculateYieldPerTerrainType. |
plumbing ✓ |
— |
0x12fda0 |
| ApplyOuterDefenseHealing |
City:ApplyOuterDefenseHealing(iHPHealed: number (fixed point, 1/256 steps)) → boolean |
Heals the outer defense damage of all flagged defensible districts in the city by the given amount; returns whether none still has damage. |
plumbing ✓ |
— |
0x111730 |
| CalculateIdentityPerTurn |
City:CalculateIdentityPerTurn(eIdentityPlayer: integer) → number |
Sums identity per turn the city generates for the given player from many sources (martial law, occupation, starvation, trade routes, governor, happiness, religion, influence tokens, free-city bonuses). Decompilation truncated near the end, so the final handling is unseen. |
plumbing ✓ |
— |
0x114630 |
| CalculateLoyaltyPerTurn |
City:CalculateLoyaltyPerTurn() → number |
Sums identity per turn over all players (added for the owner, subtracted for others) plus the loyalty-from-pressure-ratio term. |
plumbing ✓ |
— |
0x114c80 |
| CalculateYieldFromOwnedBuilding |
City:CalculateYieldFromOwnedBuilding(eBuildingType: integer, eYield: integer) → number |
Computes the yield a given building produces for the city: zero if absent or pillaged, otherwise base building yield (power-aware) plus per-era yield bonuses, then yield modifiers, plus district extra regional yield when applicable. Result returned via a hidden out pointer. |
plumbing ✓ |
— |
0x131670 |
| CalculateYieldPerTerrainType |
City:CalculateYieldPerTerrainType(eYield: integer) → number |
For each stored per-terrain yield record matching the yield, counts city-radius plots worked by this city that have the record's terrain and multiplies by the record's value; sums the results. |
plumbing ✓ |
— |
0x1318d0 |
| CanBuildUnitsOfDomain |
City:CanBuildUnitsOfDomain(domain: integer) → boolean |
True if the city has a district of that military domain, or (for domain 0) the city plot passes a coastal check and domain 1 is valid there; domain 2 is always true. |
plumbing ✓ |
— |
0x131a10 |
| CanPlaceUnit |
City:CanPlaceUnit(eUnit: integer) → boolean |
Checks whether the city can place a newly bought or built unit: unit flags may allow it outright; otherwise looks for a valid placement plot in suitable districts (matching military domain, not pillaged or enemy-occupied) and finally the city center via CanPlaceAtLocation. |
plumbing ✓ |
— |
0x120a80 |
| ChangeAccumulatedIdentity |
City:ChangeAccumulatedIdentity(ePlayer: integer, xIdentityChange: number (fixed point, 1/256 steps)) |
For a Free Cities city, adds identity points for a major player (creating a new presence entry if none exists), with the value clamped at zero when decreasing. |
plumbing ✓ |
City::CulturalIdentity::ChangeAccumulatedIdentity |
0x114fa0 |
| ChangeAllowIncomingRegionalStackingCount |
City:ChangeAllowIncomingRegionalStackingCount(eYield: integer, iDelta: integer) |
Adds a delta to a per-yield counter controlling whether the city allows incoming regional stacking for that yield. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::Instance::ChangeAllowIncomingRegionalStackingCount |
0x131a90 |
| ChangeCountAlwaysLoyalFlags |
City:ChangeCountAlwaysLoyalFlags(iDelta: integer) |
Adds a delta to the counter of always-loyal flags on the city and recalculates the city's conversion trends. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::CulturalIdentity::ChangeCountAlwaysLoyalFlags |
0x1150c0 |
| ChangeExtraIdentityPerTurnPerCitizen |
City:ChangeExtraIdentityPerTurnPerCitizen(xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the city's extra identity gained per turn per citizen. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::CulturalIdentity::ChangeExtraIdentityPerTurnPerCitizen |
0x115100 |
| ChangeFlatYieldBonusForDomestic |
City:ChangeFlatYieldBonusForDomestic(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the per-yield array entry for flat yield bonus for domestic routes. |
plumbing ✓ |
— |
0x14da30 |
| ChangeFlatYieldBonusForInternational ✓ |
City:ChangeFlatYieldBonusForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the city's flat yield bonus for international trade routes for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeFlatYieldBonusForInternational |
0x14da50 |
| ChangeFlatYieldBonusFromOthers |
City:ChangeFlatYieldBonusFromOthers(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the per-yield array entry for flat yield bonus from other routes. |
plumbing ✓ |
— |
0x14da80 |
| ChangeFlatYieldBonusToOthers |
City:ChangeFlatYieldBonusToOthers(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the per-yield array entry for flat yield bonus given to others. |
plumbing ✓ |
— |
0x14daa0 |
| ChangeFlatYieldBonusToOthersForDomestic |
City:ChangeFlatYieldBonusToOthersForDomestic(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the per-yield array entry for flat yield bonus to others for domestic routes. |
plumbing ✓ |
— |
0x14dac0 |
| ChangeFollowerYieldModifier ✓ |
City:ChangeFollowerYieldModifier(eYield: integer, iDelta: integer) |
Adds a delta to the city's follower (religion) yield modifier for one yield type and sends an event. |
plumbing ✓ effect ✓ (GetFoodSurplus) |
City::Instance::ChangeFollowerYieldModifier |
0x131af0 |
| ChangeGreatWorkYieldModifier |
City:ChangeGreatWorkYieldModifier(eObjectType: integer, eYield: integer, iYieldChange: integer, iScalingFactor: integer) |
Adds or removes a great-work yield modifier entry (object type, yield type, flat change, scaling factor) in the city's culture modifier list; a negative change removes the matching entry. |
plumbing ✓ |
City::Culture::ChangeGreatWorkYieldModifier |
0x11b800 |
| ChangeIdentityPerTurnFromModifiers |
City:ChangeIdentityPerTurnFromModifiers(xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the modifier-based identity per turn and sends a reporting event. |
plumbing ✓ |
— |
0x115130 |
| ChangeIdentityPressureFromAges |
City:ChangeIdentityPressureFromAges(xChange: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the identity pressure the city gets from ages. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::CulturalIdentity::ChangeIdentityPressureFromAges |
0x1151b0 |
| ChangeIdentityPressureFromModifiers |
City:ChangeIdentityPressureFromModifiers(xChange: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to the identity pressure the city gets from modifiers. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::CulturalIdentity::ChangeIdentityPressureFromModifiers |
0x1151e0 |
| ChangeNumForeignRoutesPassingThrough |
City:ChangeNumForeignRoutesPassingThrough(iChange: integer) |
Adds a delta to the count of foreign trade routes passing through the city, clamped to at least 0. |
plumbing ✓ |
— |
0x14dae0 |
| ChangeRequiredPower |
City:ChangeRequiredPower(xRequiredPower: number (fixed point, 1/256 steps), eBuilding: integer, eProject: integer) |
Adds a power requirement amount to the city's total required power (floored at 0) and tracks it per building/project in a list. Only acts when building or project is -1 and the amount is non-zero. |
plumbing ✓ |
— |
0x1471e0 |
| ChangeRequiredPowerFromModifiers |
City:ChangeRequiredPowerFromModifiers(xRequiredPower: number (fixed point, 1/256 steps)) |
Adds an amount to the modifier-derived required power (floored at 0) and recalculates the city's power. |
plumbing ✓ |
— |
0x1472b0 |
| ChangeTourism |
City:ChangeTourism(eImprovement: integer, eObjectType: integer, bAffectsWonders: boolean, bAffectsReligiousTourism: boolean, iScalingFactor: integer, iModifierID: integer) |
Adds or removes a tourism modifier entry in the city's culture list (improvement, great work type, wonders/religious flags, scaling factor, modifier id); a negative scaling factor removes matching entries. |
plumbing ✓ |
City::Culture::ChangeTourism |
0x11b960 |
| ChangeYieldChange ✓ |
City:ChangeYieldChange(eYield: integer, iDelta: integer) |
Adds a delta to the city's flat yield bonus for one yield type and sends an event. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Instance::ChangeYieldChange |
0x131c60 |
| ChangeYieldFromForeignRoutesPassingThrough ✓ |
City:ChangeYieldFromForeignRoutesPassingThrough(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the yield the city gets from foreign trade routes passing through it, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldFromForeignRoutesPassingThrough |
0x14db00 |
| ChangeYieldModifier ✓ |
City:ChangeYieldModifier(eYield: integer, iDelta: integer) |
Adds a delta to the city's percentage yield modifier for one yield type and sends an event. |
plumbing ✓ effect ✓ (GetFoodSurplus) |
City::Instance::ChangeYieldModifier |
0x131cf0 |
| ChangeYieldModifierPerGovernorTitle |
City:ChangeYieldModifierPerGovernorTitle(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a fixed-point delta to a city's per-governor-title yield modifier for one yield and sends an event. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::Instance::ChangeYieldModifierPerGovernorTitle |
0x131d80 |
| ChangeYieldPerDestinationLuxuryResourceForInternational ✓ |
City:ChangeYieldPerDestinationLuxuryResourceForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-destination-luxury-resource yield modifier for international routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldPerDestinationLuxuryResourceForInternational |
0x14db30 |
| ChangeYieldPerDestinationStrategicResourceForDomestic ✓ |
City:ChangeYieldPerDestinationStrategicResourceForDomestic(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-destination-strategic-resource yield modifier for domestic routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus) |
City::Trade::ChangeYieldPerDestinationStrategicResourceForDomestic |
0x14db60 |
| ChangeYieldPerDestinationStrategicResourceForInternational ✓ |
City:ChangeYieldPerDestinationStrategicResourceForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-destination-strategic-resource yield modifier for international routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus) |
City::Trade::ChangeYieldPerDestinationStrategicResourceForInternational |
0x14db90 |
| ChangeYieldPerLocalBonusResourceForDomestic ✓ |
City:ChangeYieldPerLocalBonusResourceForDomestic(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-local-bonus-resource yield modifier for domestic routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldPerLocalBonusResourceForDomestic |
0x14dbc0 |
| ChangeYieldPerLocalBonusResourceForInternational ✓ |
City:ChangeYieldPerLocalBonusResourceForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-local-bonus-resource yield modifier for international routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldPerLocalBonusResourceForInternational |
0x14dbf0 |
| ChangeYieldPerLocalLuxuryResourceForInternational ✓ |
City:ChangeYieldPerLocalLuxuryResourceForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-local-luxury-resource yield modifier for international routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldPerLocalLuxuryResourceForInternational |
0x14dc20 |
| ChangeYieldPerLocalStrategicResourceForInternational ✓ |
City:ChangeYieldPerLocalStrategicResourceForInternational(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-local-strategic-resource yield modifier for international routes, for one yield type. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) |
City::Trade::ChangeYieldPerLocalStrategicResourceForInternational |
0x14dc50 |
| ChangeYieldPerMajorTradePartner |
City:ChangeYieldPerMajorTradePartner(eYield: integer, xDelta: number (fixed point, 1/256 steps)) |
Adds a delta to the per-major-trade-partner yield modifier for one yield type. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
City::Trade::ChangeYieldPerMajorTradePartner |
0x14dc80 |
| CheckNotifications |
City:CheckNotifications() |
Checks whether required power exceeds available power; if the city is not fully powered by an active project and 10+ turns passed since the last warning, sends a power-shortage notification to the owner. |
plumbing ✓ |
— |
0x1474f0 |
| CountIncomingRoutes |
City:CountIncomingRoutes() → number |
Counts trade routes whose destination is this city via the trade manager. |
plumbing ✓ |
— |
0x14dcb0 |
| CountOutgoingRoutes |
City:CountOutgoingRoutes() → number |
Counts trade routes originating from this city via the trade manager. |
plumbing ✓ |
— |
0x14dd00 |
| DoBorderExpansion |
City:DoBorderExpansion() |
Per-turn culture border growth: if the capability is present and the city is not blocked, adds the city culture yield (scaled by a percent modifier) to the stored culture; when it reaches the next plot cost it annexes the queued or next buyable plot and bumps the plots-acquired counter. Then re-queues the next buyable plot. |
plumbing ✓ |
— |
0x11bcb0 |
| DoFoundCity |
City:DoFoundCity() |
Called when a city is founded: acquires the starting plots (count from GetNumStartingPlots, min 0) and replays influence tokens the owner already received from each player via OnPlayerGaveInfluenceToken. |
plumbing ✓ |
— |
0x11be40 |
| DoRejectedByPlayer |
City:DoRejectedByPlayer(ePlayer: integer) |
Marks a player as having rejected the city: updates or inserts that player's identity presence entry with zero amount and rejected flag, then recalculates conversion trends. |
plumbing ✓ |
— |
0x115b10 |
| DoTurnActivate |
City:DoTurnActivate() |
Per-turn loyalty and identity update; for free cities computes identity pressure changes per player through lambdas and applies them with ChangeAccumulatedIdentity. Decompilation truncated, so the remaining steps are unseen. |
plumbing ✓ |
— |
0x115be0 |
| GetAccumulatedIdentityPercent |
City:GetAccumulatedIdentityPercent(ePlayer: integer) → number |
Returns the share in percent of accumulated identity held by the given player out of the total of all entries. |
plumbing ✓ |
— |
0x116340 |
| GetBuildingPurchaseCost |
City:GetBuildingPurchaseCost(ePurchaseYield: integer, eBuilding: integer) → number |
Purchase cost of a building in the given yield: production cost converted to purchase cost, game-speed scaled, reduced by city, player and religion purchase-discount bonuses, minimum 1, rounded down to a global step. |
plumbing ✓ |
— |
0x120ed0 |
| GetCityHappinessYieldModifier |
City:GetCityHappinessYieldModifier(eHappiness: integer, eYield: integer) → number |
Sums (percent value * 256) over city happiness-yield entries (list at this+0x720) matching the happiness type and yield type. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x132ad0 |
| GetCityTerrainAdjacentImprovementModifier |
City:GetCityTerrainAdjacentImprovementModifier(eTerrain: integer, eAdjacentImprovement: integer, eYield: integer) → number |
Sums the stored values (times 256) of city terrain-modifier records (list at this+0x750) matching terrain, adjacent improvement and yield. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x132b10 |
| GetCultureCostNextPlot |
City:GetCultureCostNextPlot() → number |
Culture cost of the city's next border plot: (coefficient * plotsAcquired) ^ exponent plus a base value from global parameters, scaled for game speed. |
plumbing ✓ |
— |
0x11c570 |
| GetCultureYield |
City:GetCultureYield() → number |
Returns the owning city's culture yield by forwarding to City::Instance::GetYield. The yield-type argument is not visible in this decompilation (passed in a register). |
plumbing ✓ |
— |
0x11c5d0 |
| GetDistrictPurchaseCost |
City:GetDistrictPurchaseCost(ePurchaseYield: integer, eDistrict: integer) → number |
Purchase cost of a district: player district cost converted to purchase cost, reduced by the city and player purchase-discount bonuses, minimum 1, rounded down to a global step. |
plumbing ✓ |
— |
0x121030 |
| GetFreePower |
City:GetFreePower() → number |
Returns the city's free power, scaled by a percentage bonus (100 + percent) when the percent field is positive. |
plumbing ✓ |
— |
0x147c50 |
| GetGoldFromCitizens |
City:GetGoldFromCitizens() → number |
Returns gold from citizens: the city value at +0x268 times the citizen counter at this+0xa4 in 8-bit fixed point, 0 if the counter is not positive. Result goes through a hidden out pointer. |
plumbing ✓ |
— |
0x121140 |
| GetGreatWorkTourismModifier |
City:GetGreatWorkTourismModifier(eObject: integer) → number |
Starts at 100 and, for every tourism modifier entry whose great-work object type matches, adds (entry value - 100); returns the combined percent. |
plumbing ✓ |
— |
0x11c600 |
| GetGreatWorkYieldChange |
City:GetGreatWorkYieldChange(eObject: integer, eYield: integer) → number |
Scans the city's great-work yield list for the first entry matching object type and yield with a positive flat change, and returns that change; 0 if none. |
plumbing ✓ |
— |
0x11c630 |
| GetGreatWorkYieldModifier |
City:GetGreatWorkYieldModifier(eObject: integer, eYield: integer) → number |
Starts at 100 and multiplies by each matching (object type, yield) entry with a positive percent value / 100; returns the compounded percent. |
plumbing ✓ |
— |
0x11c660 |
| GetHighestOuterDefenseDamage |
City:GetHighestOuterDefenseDamage() → number |
Returns the highest outer defense damage among the city's flagged districts. |
plumbing ✓ |
— |
0x111800 |
| GetIdentityPerTurnFromGovernor |
City:GetIdentityPerTurnFromGovernor() → number |
Returns the identity pressure of the governor assigned to this city, in fixed point; 0 if none. |
plumbing ✓ |
— |
0x116570 |
| GetIdentityPerTurnFromHappiness |
City:GetIdentityPerTurnFromHappiness() → number |
Returns identity per turn change tied to the city's happiness level, 0 for free cities. |
plumbing ✓ |
— |
0x1165e0 |
| GetIdentityPerTurnFromInfluenceTokens |
City:GetIdentityPerTurnFromInfluenceTokens() → number |
For city states, returns the most tokens received times a global parameter; otherwise 0. |
plumbing ✓ |
— |
0x116660 |
| GetIdentityPerTurnFromMartialLaw |
City:GetIdentityPerTurnFromMartialLaw() → number |
If the city is occupied and a defensible district has a garrisoned unit, returns a global parameter plus a player value; otherwise 0. |
plumbing ✓ |
— |
0x1166f0 |
| GetIdentityPerTurnFromOccupation |
City:GetIdentityPerTurnFromOccupation() → number |
Returns the negative of the scaled grievances of the original owner toward this city's owner, clamped between global limits; 0 if the owner is the original or not alive. |
plumbing ✓ |
— |
0x116b40 |
| GetIdentityPerTurnFromOriginalOwnership |
City:GetIdentityPerTurnFromOriginalOwnership() → number |
For free cities returns a global parameter; otherwise 0. |
plumbing ✓ |
— |
0x116c50 |
| GetIdentityPerTurnFromOwnershipBeforeOccupation |
City:GetIdentityPerTurnFromOwnershipBeforeOccupation() → number |
For free cities returns a global parameter; otherwise 0. |
plumbing ✓ |
— |
0x116d30 |
| GetIdentityPerTurnFromReligion |
City:GetIdentityPerTurnFromReligion() → number |
Returns one of two global parameters depending on whether the owner's created religion matches the city's majority religion; 0 if either is none. |
plumbing ✓ |
— |
0x116d90 |
| GetIdentityPerTurnFromStarvation |
City:GetIdentityPerTurnFromStarvation() → number |
Returns a global parameter if the city is starving (turns until starvation not -1), else 0; free cities give 0. |
plumbing ✓ |
— |
0x116e20 |
| GetIdentityPerTurnFromTradeRoutes |
City:GetIdentityPerTurnFromTradeRoutes() → number |
Accumulates identity per turn from outgoing trade routes using the owner's domestic-route origin value, written through an out pointer. |
plumbing ✓ |
— |
0x116ea0 |
| GetIdentityPerTurnPerCitizen |
City:GetIdentityPerTurnPerCitizen() → number |
Computes a per-citizen identity value from civ-wide loyalty per civilian, the capital's value, a global adjustment and the current production project's value, written through an out pointer. |
plumbing ✓ |
— |
0x116f80 |
| GetIdentityPressureFromOwnership |
City:GetIdentityPressureFromOwnership(eToPlayer: integer) → number |
Returns a non-negative global parameter chosen by whether the player is the owner and by a city flag (offset 0x280); 0 for NO_PLAYER. |
plumbing ✓ |
— |
0x1170c0 |
| GetImprovementTourismModifier |
City:GetImprovementTourismModifier(eImprovement: integer) → number |
Starts at 100 and adds (entry value - 100) for each tourism modifier entry that targets the given improvement type. |
plumbing ✓ |
— |
0x11c6b0 |
| GetLastTurnAnyDistrictDamaged |
City:GetLastTurnAnyDistrictDamaged() → number |
Returns the latest turn on which any flagged district was damaged, -100 if none. |
plumbing ✓ |
— |
0x111890 |
| GetLoyaltyLevel |
City:GetLoyaltyLevel() → number |
Maps the city's loyalty value to the loyalty level definition whose range contains it; -1 if none. |
plumbing ✓ |
— |
0x117410 |
| GetNonreligiousTourism |
City:GetNonreligiousTourism() → number |
Sums tourism from great works (non-religious), wonders, improvements, features, districts, a free-power bonus and national park tourism, then applies the owner's tourism modifier percent. |
plumbing ✓ |
— |
0x11c770 |
| GetNumStartingPlots |
City:GetNumStartingPlots() → number |
Number of plots a city starts with: the civilization-level definition's value plus a player offset, plus the game-configured tile count for major players. Returns 0 for a null city or player index -1. |
plumbing ✓ |
— |
0x11c890 |
| GetReligiousTourism |
City:GetReligiousTourism() → number |
Tourism from religion: if the city is its owner's religion holy city, 100 plus religious-tourism modifier entries scaled by a global parameter, plus religious great-work tourism, then the owner's tourism modifier percent. |
plumbing ✓ |
— |
0x11c940 |
| GetReligiousTourismModifier |
City:GetReligiousTourismModifier() → number |
Starts at 100 and adds (entry value - 100) for tourism modifier entries flagged religious (byte at entry+9). |
plumbing ✓ |
— |
0x11ca40 |
| GetTourism |
City:GetTourism() → number |
Total city tourism: GetNonreligiousTourism plus GetReligiousTourism. |
plumbing ✓ |
— |
0x11ca70 |
| GetTourismFromDistricts |
City:GetTourismFromDistricts() → number |
Sums tourism from the city's districts: a per-district value (offset 600) plus tourism adjacency yield modifiers across all yield types. Private method exposed to Lua. |
plumbing ✓ |
— |
0x11caa0 |
| GetTourismFromFeatures |
City:GetTourismFromFeatures() → number |
Counts city-radius plots owned by the same player and worked by this city that have a feature, adding the per-feature tourism value (this+0x20, min 0) for each. Private method exposed to Lua. |
plumbing ✓ |
— |
0x11cb80 |
| GetTourismFromImprovements |
City:GetTourismFromImprovements() → number |
Walks the city-radius plots and, for owned plots with an improvement whose tourism definition passes civic and tech prerequisites, adds tourism from GetTourismFromImprovementOnPlot scaled by the improvement tourism modifier percent. |
plumbing ✓ |
— |
0x11cd40 |
| GetTurnsLeft |
City:GetTurnsLeft() → number |
Estimates turns until the next border plot: computes the plot culture cost (same formula as GetCultureCostNextPlot), the city culture yield and the stored culture, then calls ComputeTurnsLeft. |
plumbing ✓ |
— |
0x11cef0 |
| GetUnitPurchaseCost |
City:GetUnitPurchaseCost(ePurchaseYield: integer, eUnit: integer, eFormation: integer) → number |
Purchase cost of a unit in the given yield and formation: unit production cost converted to purchase cost, reduced by purchase-discount bonuses, adjusted by the owner's unit-cost modifier for non-civilian formation classes, rounded to a global step. |
plumbing ✓ |
— |
0x1216a0 |
| GetWonderTourismModifier |
City:GetWonderTourismModifier() → number |
Starts at 100 and adds (entry value - 100) for tourism modifier entries flagged as wonder (byte at entry+8). |
plumbing ✓ |
— |
0x11cf80 |
| GetYieldFromBuildings |
City:GetYieldFromBuildings(eYield: integer) → number |
Calls CalculateYieldFromBuildings and clamps the result by the optional min and max values it returns, giving the building yield for the yield type. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x133510 |
| GetYieldFromForeignRoutesPassingThrough |
City:GetYieldFromForeignRoutesPassingThrough(eYield: integer) → number |
Returns the per-route yield value for a yield type multiplied by the number of foreign routes passing through the city. |
plumbing ✓ |
— |
0x14de50 |
| GetYieldFromMajorTradePartners |
City:GetYieldFromMajorTradePartners(eYield: integer) → number |
If the per-partner yield for the yield type is positive, multiplies it by the number of outgoing major trade partners of this city; otherwise 0. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x133570 |
| GetYieldFromOutgoingTradeRoutes |
City:GetYieldFromOutgoingTradeRoutes(eYield: integer) → number |
Asks the trade manager to compute the yield this city gets from its outgoing trade routes for the yield type. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x133600 |
| GetYieldFromPopulation |
City:GetYieldFromPopulation(eYield: integer) → number |
Yield from population: per-citizen amounts for science, culture or gold (gold only with a positive counter) from global parameters, plus a per-yield-type per-citizen bonus array times population. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x133660 |
| GetYieldFromTiles |
City:GetYieldFromTiles(eYield: integer) → number |
Sums yield of worked plots in city radius (plot yield times workers), plus yield of improved plots outside territory matching improvement-outside-territory definitions when a city flag is set. Result is returned via a hidden out pointer, so the decompiled parameter list is register-shifted. |
plumbing ✓ |
— |
0x133780 |
| GetYieldPerMajorTradePartner |
City:GetYieldPerMajorTradePartner(eYield: integer) → number |
Returns the per-yield value granted for each major trade partner. |
plumbing ✓ |
— |
0x14e060 |
| GetYieldPerTerrainClassCitiesImprovement |
City:GetYieldPerTerrainClassCitiesImprovement(eYield: integer, eImprovement: integer) → number |
Sums the delta of stored records (list at this+0x7b0) matching the yield and improvement. |
plumbing ✓ |
— |
0x133920 |
| HasActiveTradingPost |
City:HasActiveTradingPost(ePlayer: integer) → boolean |
Returns true if the city has a trading post flag for the player and the city owner is not at war with that player. |
plumbing ✓ |
— |
0x14e0a0 |
| HasBeenRejectedByPlayer |
City:HasBeenRejectedByPlayer(ePlayer: integer) → boolean |
Returns whether the player's identity presence entry has the rejected flag. |
plumbing ✓ |
— |
0x1180e0 |
| HasCityTerrainAdjacentImprovementModifier |
City:HasCityTerrainAdjacentImprovementModifier(eTerrain: integer, eYield: integer) → boolean |
True if any city terrain-modifier record matches the terrain and yield. |
plumbing ✓ |
— |
0x133950 |
| HasDistrict |
City:HasDistrict() → boolean |
Returns true if a district exists at the city's own plot (the city center district). |
plumbing ✓ |
— |
0x1339b0 |
| HasInactiveTradingPost |
City:HasInactiveTradingPost(ePlayer: integer) → boolean |
Returns true if a trading post flag is set for the player but is not active, such as when the owner is at war with that player. |
plumbing ✓ |
— |
0x14e100 |
| IsAllowIncomingRegionalStacking |
City:IsAllowIncomingRegionalStacking(eYield: integer) → boolean |
Checks whether incoming regional yield stacking is allowed for a yield, using a per-yield array with a fallback default value. |
plumbing ✓ |
— |
0x134620 |
| IsAlwaysFullyLoyal |
City:IsAlwaysFullyLoyal() → boolean |
True if a stored always-loyal counter is positive or the location check says so. |
plumbing ✓ |
— |
0x118320 |
| IsCityState |
City:IsCityState() → boolean |
Returns true if the city's owner player has the city-state civilization level. |
plumbing ✓ |
— |
0x134670 |
| IsFullyPoweredByActiveProject |
City:IsFullyPoweredByActiveProject() → boolean |
Returns true if the city's current production project exists and its definition links to a government record with two flags set, meaning the project fully powers the city. |
plumbing ✓ |
— |
0x147e10 |
| IsOccupied |
City:IsOccupied(ignoreNoPenalty: boolean) → boolean |
Returns the city's occupied flag, unless the owner has a no-penalty flag set and the caller does not ask to ignore it. |
plumbing ✓ |
— |
0x1346b0 |
| RecalculatePower |
City:RecalculatePower() |
Recomputes how much power a city needs: zeroes the required total, re-adds power requirements of non-pillaged buildings, the current production project and extra amounts, then signals whether the city is powered and sends an event when power balance sign changes. |
plumbing ✓ |
City::Power::RecalculatePower |
0x147e80 |
| RemoveCityAllowedImprovement |
City:RemoveCityAllowedImprovement(eImprovement: integer) |
Removes the first occurrence of an improvement type from the city's allowed-improvement list by rebuilding the vector without it. |
plumbing ✓ |
— |
0x134790 |
| RemoveCityHappinessModifier |
City:RemoveCityHappinessModifier(eHappiness: integer, eYield: integer, eGreatPersonClass: integer, iYieldChange: integer, iGreatPersonChange: integer) |
Rebuilds the city's happiness modifier list, intended to drop a matching modifier record. |
plumbing ✓ |
City::Instance::RemoveCityHappinessModifier |
0x1349b0 |
| RemoveCityTerrainModifier |
City:RemoveCityTerrainModifier(eTerrain: integer, eAdjacentImprovement: integer, eYield: integer, iYieldChange: integer) |
Removes the first matching entry from the city's terrain-modifier list. Does nothing unless iYieldChange > 0 and eAdjacentImprovement is valid. |
plumbing ✓ |
— |
0x134b10 |
| RemoveCityValidTerrainImprovement |
City:RemoveCityValidTerrainImprovement(eImprovement: integer, eTerrain: integer) |
Removes the first entry matching the improvement or terrain from the city's valid terrain-improvement list. |
plumbing ✓ |
— |
0x134c90 |
| RemoveDynamicAdjacencyBonus |
City:RemoveDynamicAdjacencyBonus(eDistrict: integer, eTerrain: integer, eFeature: integer, bIsRiver: boolean, iAppeal: integer, bAdjacentDistrict: boolean, eYield: integer) |
Removes matching dynamic adjacency bonus entries from the city's list. |
plumbing ✓ |
City::Instance::RemoveDynamicAdjacencyBonus |
0x134d90 |
| RemoveImprovementAdjacencyBonus |
City:RemoveImprovementAdjacencyBonus(eDistrict: integer, eImprovement: integer, eYield: integer) |
Erases all dynamic adjacency bonus entries in the city that match the given district, improvement and yield. |
plumbing ✓ |
— |
0x134e50 |
| RemoveYieldPerTerrainClassCitiesImprovement |
City:RemoveYieldPerTerrainClassCitiesImprovement(eYield: integer, eImprovement: integer, iDelta: integer) |
Removes the first matching entry from the city's yield-per-terrain-class improvement list. |
plumbing ✓ |
— |
0x134ee0 |
| RemoveYieldPerTerrainType |
City:RemoveYieldPerTerrainType(eTerrain: integer, eYield: integer, xValue: number (fixed point, 1/256 steps)) |
Erases all entries matching terrain, yield and value from the city's yield-per-terrain-type list. |
plumbing ✓ |
— |
0x135010 |
| ResetAccumulatedIdentity |
City:ResetAccumulatedIdentity() |
Clears the accumulated identity list by resetting its end pointer to the start. |
plumbing ✓ |
— |
0x118590 |
| ResetCache |
City:ResetCache() |
Resizes and clears the city's per-yield cached values so they will be recomputed. |
plumbing ✓ |
City::Instance::ResetCache |
0x135370 |
| ResetTemporaryPower |
City:ResetTemporaryPower() |
Zeroes the temporary power value and clears the entries in two per-item lists. |
plumbing ✓ |
— |
0x1481a0 |
| SetBuildingFaithPurchaseByDistrict |
City:SetBuildingFaithPurchaseByDistrict(eDistrict: integer, bNewValue: boolean) |
Enables or disables faith purchasing for every building that belongs to a given district type by adjusting a per-building counter. |
plumbing ✓ |
City::Gold::SetBuildingFaithPurchaseByDistrict |
0x121c20 |
| SetComponentID |
City:SetComponentID(eOwner: integer, id: integer) |
Assigns the city's owner and id fields and updates the object's archive ID. |
plumbing ✓ |
— |
0x1357f0 |
| SetOccupied |
City:SetOccupied(bNewValue: boolean) |
Sets the city's occupied flag and sends an event if the stored value actually changed. |
plumbing ✓ |
City::Instance::SetOccupied |
0x135a30 |
| SetSiegeProtection |
City:SetSiegeProtection(bProtected: boolean) |
Sets the city's siege-protection flag, then re-applies the district's current besieged status so the siege state refreshes. |
plumbing ✓ |
City::Combat::SetSiegeProtection |
0x111b10 |
Details
AddCityAllowedImprovement
Arguments: eImprovement — improvement type to allow in this city
Writes
- city allowed-improvement list (this+0x1550)
Input checks: No validation (no -1 check, no duplicate check).
Multiplayer: may-desync, writes synchronised city state. Risk: medium (modifies replicated city data; appends without de-duplication). Confidence of the reading: medium.
AddCityHappinessModifier
Arguments: eHappiness — happiness state the modifier applies to; eYield — yield affected; eGreatPersonClass — great person class affected; iYieldChange — yield change; must be >0 unless iGreatPersonChange >0; iGreatPersonChange — great person point change
Writes
- 20-byte modifier record appended to the vector held in the city's auto variable at this+0x710
Side effects
- may reallocate the vector
Input checks: Silently does nothing unless iYieldChange > 0 or iGreatPersonChange > 0. Enum values are stored unchecked and not deduplicated.
Preconditions
- game thread
- gameplay state
Multiplayer: safe-deterministic. Risk: low (Append to a synchronised auto variable; no validation of enums.). Confidence of the reading: high.
Verified from the code
- Returns without effect when both change values are not positive
- Writes through FAutoVariable<VariantMap>::edit at this+0x710 and appends five 4-byte fields
- Record type is typed as BeliefYield in symbols but the field is City happiness modifiers
Inferred
- Record semantic is 'when city is in this happiness state, add yield/GP'
Open questions
- How RemoveCityHappinessModifier matches records (see that function)
AddCityTerrainModifier
Arguments: eTerrain — terrain type the modifier applies to; eAdjacentImprovement — adjacent improvement required; eYield — yield type changed; iYieldChange — yield amount, must be > 0
Writes
- city terrain modifier list (this+0x740)
Input checks: Silently ignores non-positive change and improvement -1; terrain and yield unchecked.
Multiplayer: may-desync, writes synchronised city state. Risk: medium (modifies replicated city data; appends without de-duplication). Confidence of the reading: medium.
AddCityValidTerrainImprovement
Arguments: eImprovement — improvement type; eTerrain — terrain type where it becomes valid
Writes
- city valid terrain-improvement list (this+0x770)
Input checks: Silently ignores either argument being -1; no duplicate check.
Multiplayer: may-desync, writes synchronised city state. Risk: medium (modifies replicated city data; appends without de-duplication). Confidence of the reading: medium.
AddYieldPerTerrainClassCitiesImprovement
Arguments: eYield — yield type; eImprovement — improvement type; iDelta — yield amount added (inferred)
Writes
- city yield-per-terrain-class list (this+0x7a0)
Input checks: Silently ignores -1 improvement or yield; delta unchecked.
Multiplayer: may-desync, writes synchronised city state. Risk: medium (modifies replicated city data; appends without de-duplication). Confidence of the reading: medium.
AddYieldPerTerrainType
Arguments: eTerrain — terrain type; eYield — yield type; xValue — fixed-point yield per matching plot (passed by pointer)
Writes
- city yield-per-terrain-type list (this+0x830)
Input checks: No validation at all (no -1 or range check).
Multiplayer: may-desync, writes synchronised city state. Risk: medium (modifies replicated city data; appends without de-duplication). Confidence of the reading: medium.
ApplyOuterDefenseHealing
Arguments: iHPHealed — Fixed-point amount of HP to heal
Writes
- Outer defense damage of each flagged district (ChangeDamage by negative amount)
Input checks: Skips null districts and those not flagged at offset 0x3f8; amount not validated.
Multiplayer: may-desync, modifies district damage. Risk: medium (Writes district damage). Confidence of the reading: high.
CalculateIdentityPerTurn
Arguments: eIdentityPlayer — Player whose identity per turn is calculated
Input checks: Returns 0 for NO_PLAYER; rest truncated.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: medium.
CalculateLoyaltyPerTurn
Input checks: No inputs.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
CalculateYieldFromOwnedBuilding
Arguments: eBuildingType — building type to evaluate (inferred); eYield — yield type to compute (inferred)
Input checks: Checks HasBuilding, pillaged state and null definition; argument mapping in the decompilation is register-shifted, so which argument is which is uncertain.
Multiplayer: read-only, computation (flagged writes are local temporaries). Risk: low (pure getter). Confidence of the reading: low.
CalculateYieldPerTerrainType
Arguments: eYield — yield type to compute
Input checks: Skips null plots and plots worked by another city.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
CanBuildUnitsOfDomain
Arguments: domain — domain type (numeric)
Input checks: No range check on domain; domain 2 short-circuits to true.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
CanPlaceUnit
Arguments: eUnit — unit type to place
Input checks: Null city returns false; an out-of-range unit index gives a null definition that is dereferenced unchecked; plot coordinates below -9999 treated as invalid.
Multiplayer: read-only, placement query. Risk: low (pure getter). Confidence of the reading: medium.
ChangeAccumulatedIdentity
Arguments: ePlayer — major player whose identity changes; xIdentityChange — identity delta (raw/256)
Writes
- per-player identity presence list at this+0xc8 (new entry appended or existing amount changed)
Side effects
- may grow the presence vector
Input checks: Does nothing unless the city's owner is Free Cities and ePlayer is major. New entries only created for positive deltas; existing entries below 0 clamp to 0; entries with the flag byte set are not changed.
Preconditions
- city owned by Free Cities
- valid player id
- game thread
Multiplayer: may-desync: direct state edit; run on all clients. Risk: medium (EditPlayer on unchecked player id). Confidence of the reading: medium.
Verified from the code
- gates on owner IsFreeCities and param IsMajor
- entries are 12 bytes (player, amount, flag byte)
- negative result clamped to 0; positive new entry appended
Inferred
- flag byte probably marks a locked/loyal entry
Open questions
- flag byte meaning
- behaviour when entry search runs to end pointer is partially garbled in decompile
ChangeAllowIncomingRegionalStackingCount
Arguments: eYield — yield type; iDelta — amount added to the counter
Writes
- per-yield int at array in auto variable this+0x6b0 (added to), or a fallback int at +0x18 of the container if index beyond its size
Input checks: Silent no-op if eYield is -1 or >= number of yield types. If the index is within the type range but beyond the container length, the delta goes into a fallback field instead.
Preconditions
- game thread
Multiplayer: safe-deterministic. Risk: low (Bounds checked counter change.). Confidence of the reading: medium.
Verified from the code
- Range check against NUM_YIELD_TYPES
- Edits the auto variable at this+0x6b0 and adds iDelta to int[eYield]
- Fallback add to container+0x18 when index >= container length at +0x10
Inferred
- It is a reference-counted flag for regional (per-region) stacking of yields
Open questions
- Purpose of the fallback field at container+0x18
ChangeCountAlwaysLoyalFlags
Arguments: iDelta — change in the number of always-loyal flags
Writes
- always-loyal flag count at this+0x1a0 (value at +0x1b0)
Side effects
- calls RecalculateConversionTrends
Input checks: None; count can go negative.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state. Risk: low (simple counter). Confidence of the reading: medium.
Verified from the code
- new value = old + delta stored via the variable's move assignment
- then RecalculateConversionTrends
Inferred
- flag count above zero means city is always loyal
Open questions
- how the count is consumed
ChangeExtraIdentityPerTurnPerCitizen
Arguments: xDelta — amount to add (raw/256)
Writes
- extra identity per turn per citizen at this+0x1e8 (value at +0x1f8)
Side effects
- none
Input checks: None; unclamped.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state. Risk: low (simple value add). Confidence of the reading: high.
Verified from the code
- reads old value, adds delta from reference, stores via the variable's move assignment
Inferred
- does not recompute trends here
ChangeFlatYieldBonusForDomestic
Arguments: eYield — yield type used as array index; xDelta — fixed-point amount to add
Writes
- flat yield bonus for domestic routes (offset 0x68)
Input checks: ignores out-of-range yield index; no other checks
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeFlatYieldBonusForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x88 (flat bonus, international routes)
Input checks: Bounds checked: index >= array size is silently ignored.
Preconditions
- valid city Trade object
- yield index within yield count
Multiplayer: may-desync: direct state change without events; must run on all clients. Risk: low (bounds-checked simple add; no recalculation of displayed yields triggered). Confidence of the reading: high.
Verified from the code
- unsigned bounds check against vector length
- adds raw delta to element
Inferred
- array is the international flat bonus table by name
Open questions
- whether city yields are refreshed elsewhere
ChangeFlatYieldBonusFromOthers
Arguments: eYield — yield type used as array index; xDelta — fixed-point amount to add
Writes
- flat yield bonus from other routes (offset 0x48)
Input checks: ignores out-of-range yield index; no other checks
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeFlatYieldBonusToOthers
Arguments: eYield — yield type used as array index; xDelta — fixed-point amount to add
Writes
- flat yield bonus given to others (offset 0x28)
Input checks: ignores out-of-range yield index; no other checks
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeFlatYieldBonusToOthersForDomestic
Arguments: eYield — yield type used as array index; xDelta — fixed-point amount to add
Writes
- flat yield bonus to others for domestic routes (offset 0x8)
Input checks: ignores out-of-range yield index; no other checks
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeFollowerYieldModifier
Arguments: eYield — yield type; iDelta — amount to add
Writes
- per-yield array at this+0x4d0 (element += iDelta); out-of-range yield writes to a dummy slot
Side effects
- sends Reporting::Event 0xef1e2348 with city id and yield
Input checks: Out-of-range yield hits a dummy slot rather than crashing.
Preconditions
- gameplay state
Multiplayer: safe-deterministic. Risk: low (Bounds handled additive change). Confidence of the reading: high.
Verified from the code
- bounds checked with dummy slot
- edit() before write
- same event as ChangeYieldChange
Inferred
- 'Follower' semantics come from the function name
Open questions
- unit of the modifier (percent assumed)
ChangeGreatWorkYieldModifier
Arguments: eObjectType — great work object type; eYield — yield type affected; iYieldChange — flat yield change; iScalingFactor — scaling factor
Writes
- modifier vector at this+0x68 (entry of 16 bytes appended or removed)
Side effects
- may reallocate the vector
Input checks: If both values are positive an entry is appended; if either is negative, all entries matching type, yield and the negated values are removed (copying the vector); if both are zero nothing happens. No check on type/yield validity.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state; run on all clients. Risk: low (contained list edit). Confidence of the reading: medium.
Verified from the code
- zero/both-nonpositive-with-a-negative triggers a rebuild of the vector without the entry equal to (type,yield,-change,-scaling)
- positive case appends the 4-field entry
- mixed positive and negative: positive branch tested first only if both >0
Inferred
- note a mixed-sign call (one positive, one negative) is appended, not removed
- removal rebuilds by copy and drops all matches
Open questions
- whether the mixed-sign case is intended
- consumer of the list
ChangeIdentityPerTurnFromModifiers
Arguments: xDelta — Fixed-point amount added to the modifier identity value
Writes
- Identity-per-turn-from-modifiers value (this+0x1b8/0x1c8)
Side effects
- Reporting::Event::Send for the city and player
Input checks: No validation of the delta.
Multiplayer: may-desync, changes synchronised city state. Risk: medium (Alters loyalty modifier). Confidence of the reading: high.
ChangeIdentityPressureFromAges
Arguments: xChange — amount to add (raw/256)
Writes
- identity pressure from ages at this+0xf8 (value at +0x108)
Side effects
- none
Input checks: None; unclamped.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state. Risk: low (simple value add). Confidence of the reading: high.
Verified from the code
- reads old value, adds delta from reference, stores via the variable's move assignment
ChangeIdentityPressureFromModifiers
Arguments: xChange — amount to add (raw/256)
Writes
- identity pressure from modifiers at this+0x140 (value at +0x150)
Side effects
- none
Input checks: None; unclamped.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state. Risk: low (simple value add). Confidence of the reading: high.
Verified from the code
- reads old value, adds delta from reference, stores via the variable's move assignment
ChangeNumForeignRoutesPassingThrough
Arguments: iChange — signed change to the count
Writes
- foreign routes passing through count (0x230)
Input checks: clamps at 0
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeRequiredPower
Arguments: xRequiredPower — fixed-point change in required power; eBuilding — building type the requirement belongs to; eProject — project type the requirement belongs to
Writes
- total required power (0x58)
- per building/project requirement list (0x60..0x70)
Input checks: does nothing unless (eBuilding == -1 or eProject == -1) and amount non-zero; clamps results at 0
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: medium.
ChangeRequiredPowerFromModifiers
Arguments: xRequiredPower — fixed-point change in required power from modifiers
Writes
- required power from modifiers (0x5c)
- fields updated by RecalculatePower
Side effects
- calls RecalculatePower
Input checks: does nothing for zero; clamps at 0
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ChangeTourism
Arguments: eImprovement — improvement type; eObjectType — great work object type; bAffectsWonders — whether it applies to wonders; bAffectsReligiousTourism — whether it applies to religious tourism; iScalingFactor — scaling factor (positive adds, negative removes); iModifierID — modifier id the entry belongs to
Writes
- tourism modifier vector at this+0x30 (20-byte entries appended or removed)
Side effects
- may reallocate the vector
Input checks: Positive factor appends; negative removes all entries with the same improvement, object type, both flags and modifier id (the stored factor is not compared); zero does nothing.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits synchronized state. Risk: low (contained list edit). Confidence of the reading: medium.
Verified from the code
- removal path copies the vector and skips entries matching improvement, type, both flags and modifier id
- append path stores the 20-byte entry
Inferred
- vector element type shown as BeliefYield is probably a mislabel
Open questions
- the consumer of this list
ChangeYieldChange
Arguments: eYield — yield type; iDelta — amount to add
Writes
- per-yield array at this+0x530 (element += iDelta); out-of-range yield writes to a fallback slot
Side effects
- sends Reporting::Event 0xef1e2348 with city id and yield (shared event with the modifier setters)
Input checks: Out-of-range or negative yield does not crash: it writes to a dummy slot at offset 0x18 of the map object.
Preconditions
- gameplay state
Multiplayer: safe-deterministic. Risk: low (Bounds handled, additive change). Confidence of the reading: high.
Verified from the code
- bounds check with dummy slot fallback
- event always sent
- edit() on the variant map
Inferred
- offset +0x530 is a flat yield bonus vs +0x4a0 multiplier
Open questions
- which yield calculation reads this array
ChangeYieldFromForeignRoutesPassingThrough
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x148
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldModifier
Arguments: eYield — yield type; iDelta — amount to add
Writes
- per-yield array at this+0x4a0 (element += iDelta); out-of-range yield writes to a dummy slot
Side effects
- sends Reporting::Event 0xef1e2348 with city id and yield
Input checks: Out-of-range yield hits a dummy slot rather than crashing.
Preconditions
- gameplay state
Multiplayer: safe-deterministic. Risk: low (Bounds handled additive change). Confidence of the reading: high.
Verified from the code
- bounds checked with dummy slot
- edit() before write
- event identical to the other two yield setters
Inferred
- modifier is likely a percentage
Open questions
- whether yields are recalculated automatically afterwards
ChangeYieldModifierPerGovernorTitle
Arguments: eYield — yield; xDelta — amount to add (raw/256)
Writes
- array at this+0x500 element for yield
Side effects
- Reporting::Event 0xef1e2348
Input checks: Out-of-range yield index writes to a fallback slot instead of crashing.
Preconditions
- gameplay state
Multiplayer: may-desync: must be applied everywhere. Risk: low (bounded fallback). Confidence of the reading: high.
Verified from the code
- bounds check with fallback slot
- event includes yield
ChangeYieldPerDestinationLuxuryResourceForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0xe8
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerDestinationStrategicResourceForDomestic
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x108
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerDestinationStrategicResourceForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x128
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerLocalBonusResourceForDomestic
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0xa8
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerLocalBonusResourceForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0xc8
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerLocalLuxuryResourceForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x168
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerLocalStrategicResourceForInternational
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x188
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
ChangeYieldPerMajorTradePartner
Arguments: eYield — yield index; xDelta — amount to add (raw/256)
Writes
- per-yield FixedPoint array at this+0x1a8
Input checks: Bounds checked: out-of-range yield silently ignored.
Preconditions
- valid city Trade object
Multiplayer: may-desync: direct state change; must run on all clients. Risk: low (bounds-checked simple add). Confidence of the reading: high.
Verified from the code
- bounds check then raw add to array element
Inferred
- meaning taken from the function name
CheckNotifications
Writes
- last notification turn (0xa4)
Side effects
- sends a notification with localized text (power required vs available)
- reads current game turn
Input checks: checks game pointer non-null; no input
Multiplayer: may-desync, sends notification and writes last-notified turn. Risk: medium (sends notification and writes city state; uses turn). Confidence of the reading: medium.
CountIncomingRoutes
Input checks: returns 0 if no current game
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
CountOutgoingRoutes
Input checks: returns 0 if no current game
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
DoBorderExpansion
Writes
- stored culture accumulator (this+0x8)
- plots-acquired count (this+0x10)
- queued next-plot index (this+0x1c)
- plot ownership via AnnexPlot
Side effects
- annexes a plot to the city (AnnexPlot)
Input checks: Checks capability hash 0xc7331068, a block flag at this+0x28, null city and null civilization-level definition; does not otherwise validate the queued plot.
Multiplayer: may-desync, changes plot ownership and culture state. Risk: high (writes city culture and plot ownership). Confidence of the reading: medium.
DoFoundCity
Writes
- city plot ownership (via AcquirePlots)
- culture-side influence-token bookkeeping (via OnPlayerGaveInfluenceToken)
Side effects
- acquires plots for the city
Input checks: Clamps a negative starting-plot count to 0; dereferences the owning city without a null check.
Multiplayer: may-desync, acquires plots and changes city state. Risk: high (assigns plot ownership; calling on an established city re-runs founding logic). Confidence of the reading: medium.
DoRejectedByPlayer
Arguments: ePlayer — Player that rejected the city
Writes
- Identity presence list entry for ePlayer (amount zeroed, rejected flag set)
Side effects
- RecalculateConversionTrends
Input checks: No check of the ePlayer value.
Multiplayer: may-desync, changes city identity state. Risk: medium (Writes presence list). Confidence of the reading: high.
DoTurnActivate
Writes
- Accumulated identity per player
- Other city identity fields (truncated)
Side effects
- Notification (per facts)
- Several internal lambdas run
Input checks: Checks free-cities status and player validity; rest truncated.
Multiplayer: may-desync, per-turn city state change. Risk: high (Changes accumulated identity). Confidence of the reading: low.
GetAccumulatedIdentityPercent
Arguments: ePlayer — Player whose share is returned
Input checks: Handles empty or zero total; ePlayer not validated.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetBuildingPurchaseCost
Arguments: ePurchaseYield — yield used to pay (gold branch vs other, e.g. faith); eBuilding — building type to price
Input checks: Null building definition returns 0; no range check on the yield type.
Multiplayer: read-only, cost computation. Risk: low (pure getter). Confidence of the reading: high.
GetCityHappinessYieldModifier
Arguments: eHappiness — happiness type to match (inferred); eYield — yield type to match (inferred)
Input checks: No range checks.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetCityTerrainAdjacentImprovementModifier
Arguments: eTerrain — terrain type to match (inferred); eAdjacentImprovement — adjacent improvement to match (inferred); eYield — yield type to match (inferred)
Input checks: No range checks.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: low.
GetCultureCostNextPlot
Input checks: None; no parameters.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetCultureYield
Input checks: Relies on the owning city pointer being non-null; no checks.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetDistrictPurchaseCost
Arguments: ePurchaseYield — yield used to pay (gold vs other); eDistrict — district type to price
Input checks: Null district definition returns 0; no range check on the yield type.
Multiplayer: read-only, cost computation. Risk: low (pure getter). Confidence of the reading: high.
GetFreePower
Input checks: none
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetGoldFromCitizens
Input checks: Counter must be positive; the city pointer is not null-checked.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetGreatWorkTourismModifier
Arguments: eObject — great work object type to match
Input checks: No range check; unmatched type returns 100.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetGreatWorkYieldChange
Arguments: eObject — great work object type to match; eYield — yield type to match
Input checks: No range check; only positive entries count and only the first match is returned.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetGreatWorkYieldModifier
Arguments: eObject — great work object type to match; eYield — yield type to match
Input checks: No range check; non-positive entries are skipped.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetHighestOuterDefenseDamage
Input checks: Skips null or unflagged districts.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromGovernor
Input checks: Null-checks governor.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromHappiness
Input checks: Free-city check only.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromInfluenceTokens
Input checks: Only for city states and a non-zero parameter.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromMartialLaw
Input checks: Checks occupied state and garrison.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromOccupation
Input checks: Checks the original owner is alive and different.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromOriginalOwnership
Input checks: Free-city check only.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromOwnershipBeforeOccupation
Input checks: Free-city check only.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromReligion
Input checks: Checks both religion values for none.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromStarvation
Input checks: Free-city check only.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetIdentityPerTurnFromTradeRoutes
Input checks: Only iterates routes when the per-route value is non-zero.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: medium.
GetIdentityPerTurnPerCitizen
Input checks: Null-checks capital and project definitions.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: medium.
GetIdentityPressureFromOwnership
Arguments: eToPlayer — Player the pressure applies to
Input checks: Returns 0 for NO_PLAYER; clamps to non-negative.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetImprovementTourismModifier
Arguments: eImprovement — improvement type to match
Input checks: No range check; unmatched type returns 100.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetLastTurnAnyDistrictDamaged
Input checks: Skips null or unflagged districts.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetLoyaltyLevel
Input checks: Iterates definitions, skips null.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
GetNonreligiousTourism
Input checks: Reads the owner via the player manager without checking the player index.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetNumStartingPlots
Input checks: Checks null city and player index -1; a null definition falls back to 0.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetReligiousTourism
Input checks: Handles a missing holy city (base 0); does not null-check the owner.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetReligiousTourismModifier
Input checks: None; no parameters.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetTourism
Input checks: None; no parameters.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetTourismFromDistricts
Input checks: Skips null district lookups.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetTourismFromFeatures
Input checks: Skips null plots and plots owned by another player or worked by another city.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetTourismFromImprovements
Input checks: Checks plot ownership, null improvement, null tourism definition, civic and tech requirements.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetTurnsLeft
Input checks: None; no parameters. The flagged writes are only local temporaries.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetUnitPurchaseCost
Arguments: ePurchaseYield — yield used to pay; eUnit — unit type to price; eFormation — formation (normal, corps, army) used for the production cost
Input checks: Checks unit index range and null definition (returns 0); no range check on yield or formation.
Multiplayer: read-only, cost computation. Risk: low (pure getter). Confidence of the reading: high.
GetWonderTourismModifier
Input checks: None; no parameters.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
GetYieldFromBuildings
Arguments: eYield — yield type
Input checks: None visible; cleans up a temporary breakdown vector.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldFromForeignRoutesPassingThrough
Arguments: eYield — yield type used as array index
Input checks: out-of-range index returns 0
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldFromMajorTradePartners
Arguments: eYield — yield type
Input checks: Returns 0 when the per-partner yield is not positive.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldFromOutgoingTradeRoutes
Arguments: eYield — yield type
Input checks: None; delegates entirely to Trade::Manager.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldFromPopulation
Arguments: eYield — yield type
Input checks: Bounds-checks the yield index against the array, otherwise uses a default slot.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldFromTiles
Arguments: eYield — yield type
Input checks: Skips null plots and plots without workers.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldPerMajorTradePartner
Arguments: eYield — yield type used as array index
Input checks: out-of-range index returns 0
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldPerTerrainClassCitiesImprovement
Arguments: eYield — yield type to match; eImprovement — improvement type to match
Input checks: No range checks.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
HasActiveTradingPost
Arguments: ePlayer — player whose trading post is checked
Input checks: returns false for ePlayer out of range or missing owner
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
HasBeenRejectedByPlayer
Arguments: ePlayer — Player to check
Input checks: Not-found returns false.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
HasCityTerrainAdjacentImprovementModifier
Arguments: eTerrain — terrain to match; eYield — yield to match
Input checks: No range checks.
Multiplayer: read-only, pure computation. Risk: low (pure getter). Confidence of the reading: high.
HasDistrict
Input checks: none needed; no inputs
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
HasInactiveTradingPost
Arguments: ePlayer — player whose trading post is checked
Input checks: returns false for ePlayer out of range; flag lookup after war check is unguarded when owner missing
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: medium.
IsAllowIncomingRegionalStacking
Arguments: eYield — yield type index
Input checks: returns false for -1 or index >= NUM_YIELD_TYPES; indices beyond the array use the default field
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: medium.
IsAlwaysFullyLoyal
Input checks: Delegates to IsAlwaysFullyLoyalAtLocation.
Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.
IsCityState
Input checks: none; assumes owner id is valid
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
IsFullyPoweredByActiveProject
Input checks: returns false when no project is in production or definitions are missing
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: low.
IsOccupied
Arguments: ignoreNoPenalty — if true skip the owner's no-penalty check
Input checks: none; owner lookup unchecked
Multiplayer: read-only, pure getter. Risk: low (pure getter). Confidence of the reading: high.
RecalculatePower
Writes
- required power total at this+0x58 (zeroed then rebuilt)
- this+0x68 reset from this+0x60
- powered flag at this+0xa0 (set to true when newly powered)
Side effects
- city-powered signal dispatch (city, bool)
- Reporting::Event 0xd210fbfb when surplus/deficit sign changes
- calls ChangeRequiredPower per building/project
Input checks: No inputs. Skips signal if there is no current game. Requirement lookups are null-checked.
Preconditions
- gameplay state
- city must have an owner
Multiplayer: safe-deterministic. Risk: low (pure recalculation of derived state). Confidence of the reading: medium.
Verified from the code
- only major players get building/project requirements added
- only buildings that exist and are not pillaged contribute
- signal sent with the city and a bool
- event sent only when sign of (produced minus required) changes between before and after
Inferred
- this+0x30 is power produced, +0x8 is a base amount scaled by a percent modifier
- fixed-point 8 fractional bits used for requirements
Open questions
- exact semantics of fields 0x5c, 0x60, 0x68
- type confusion in Find template names
RemoveCityAllowedImprovement
Arguments: eImprovement — improvement type to remove
Writes
- city allowed-improvements list (offset 0x1550)
Input checks: no range check on eImprovement; if absent the list is rebuilt unchanged
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: medium.
RemoveCityHappinessModifier
Arguments: eHappiness — happiness type to match; eYield — yield to match; eGreatPersonClass — great person class to match; iYieldChange — yield change (checked for <0 as the trigger); iGreatPersonChange — great person change
Writes
- clears and refills the modifier vector in auto variable at this+0x710
Side effects
- allocates a temporary copy of the vector and frees it
Input checks: Does nothing unless iYieldChange < 0 or iGreatPersonChange < 0. Unmatched id combinations leave the list rebuilt as copied.
Preconditions
- game thread
Multiplayer: safe-deterministic. Risk: medium (Matching logic looks odd (any one field equal counts as a match; after the first match later records are not re-added), so it may drop more than expected.). Confidence of the reading: low.
Verified from the code
- Runs only if either amount is negative
- Copies the vector, sets the live vector's end to its begin, then re-adds records
- A record is considered matching if happiness OR yield OR great person class equals the argument; once matched, a flag stops all later records being re-added
- Non-matching records are re-added only when both amounts differ from the arguments
Inferred
- Decompilation may have merged conditions; the intended behaviour is probably removing one exact record
- Caller likely passes negated amounts
Open questions
- Whether the OR/AND logic is a decompiler artefact or a real game quirk
- Why the first matching record and everything after is lost
RemoveCityTerrainModifier
Arguments: eTerrain — terrain type of entry; eAdjacentImprovement — adjacent improvement of entry; eYield — yield type (not used in the match shown) (inferred); iYieldChange — yield amount; must be > 0
Writes
- city terrain-modifier list (offset 0x740)
Input checks: requires iYieldChange > 0 and improvement != -1; the match uses OR over terrain/improvement/amount so a loosely matching entry may be removed
Multiplayer: may-desync, modifies synchronised city state; loose match may remove wrong entry. Risk: medium (modifies synchronised city state; loose match may remove wrong entry). Confidence of the reading: medium.
RemoveCityValidTerrainImprovement
Arguments: eImprovement — improvement type; eTerrain — terrain type
Writes
- city valid terrain-improvement list (offset 0x770)
Input checks: returns early if either type is -1; match uses OR so one equal field removes an entry
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: medium.
RemoveDynamicAdjacencyBonus
Arguments: eDistrict — district type of the bonus; eTerrain — terrain filter; eFeature — feature filter; bIsRiver — river adjacency; iAppeal — appeal value; bAdjacentDistrict — adjacent district flag; eYield — yield type
Writes
- dynamic adjacency bonus vector at this+0x800 (matching elements erased)
Input checks: No validation; non-matches leave list unchanged.
Preconditions
- game thread
Multiplayer: may-desync: synced city state. Risk: low (list filter). Confidence of the reading: medium.
Verified from the code
- remove-if then erase on vector
- match criteria are packed from all 7 parameters
Inferred
- matching compares all fields (lambda not shown)
- no cache refresh is triggered here
Open questions
- exact lambda comparison, whether adjacency yields recalculated elsewhere
RemoveImprovementAdjacencyBonus
Arguments: eDistrict — district type of bonus; eImprovement — improvement type of bonus; eYield — yield type of bonus
Writes
- city dynamic adjacency bonus list (offset 0x800)
Input checks: no validation; non-matching input erases nothing
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
RemoveYieldPerTerrainClassCitiesImprovement
Arguments: eYield — yield type; eImprovement — improvement type; iDelta — amount of the entry
Writes
- city yield-per-terrain-class improvement list (offset 0x7a0)
Input checks: returns early if yield or improvement is -1; match uses OR over the three fields
Multiplayer: may-desync, modifies synchronised city state; loose OR match. Risk: medium (modifies synchronised city state; loose OR match). Confidence of the reading: medium.
RemoveYieldPerTerrainType
Arguments: eTerrain — terrain type; eYield — yield type; xValue — fixed-point yield value to match
Writes
- city yield-per-terrain-type list (offset 0x830)
Input checks: no validation; unmatched input erases nothing
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: high.
ResetAccumulatedIdentity
Writes
- Accumulated identity per-player list emptied
Input checks: None.
Multiplayer: may-desync, clears synchronised city state. Risk: medium (Wipes city identity data). Confidence of the reading: high.
ResetCache
Writes
- per-yield cached value array at this+0x1950 (capacity at +0x1958, count at +0x1960): all entries marked invalid, count set to number of yields
Side effects
- may allocate a bigger block
Input checks: None needed. Protected method.
Preconditions
- definitions loaded
Multiplayer: safe-deterministic. Risk: low (Only invalidates a cache.). Confidence of the reading: medium.
Verified from the code
- Count comes from yield definitions list size
- Grows the vector when capacity is smaller
- Sets the validity byte of every 8-byte entry (value+flag) to 0
- Updates the stored count
Inferred
- Each entry is a CachedValue of fixed-point with a valid flag
Open questions
- The value field is written from an uninitialised local so its content is irrelevant
ResetTemporaryPower
Writes
- temporary power (0x30)
- list at 0x38..0x40
- list at 0x80..0x88 entries
Input checks: none
Multiplayer: may-desync, modifies synchronised city state. Risk: medium (modifies synchronised city state). Confidence of the reading: medium.
SetBuildingFaithPurchaseByDistrict
Arguments: eDistrict — district type whose buildings are affected; bNewValue — true adds one to each counter, false subtracts one
Writes
- per-building int counter array at this+0x50 (+1 or -1 per matching building)
Input checks: No validation. Counters are reference counts, so unbalanced false calls go negative. Building index used unchecked into the array.
Preconditions
- definitions loaded
- counter array sized for all buildings
Multiplayer: safe-deterministic. Risk: low (Simple counter change; the name says Set but it increments/decrements.). Confidence of the reading: high.
Verified from the code
- Iterates all building definitions
- Matches when the building's district entry equals eDistrict
- Adds or subtracts 1 in an int array at this+0x50 indexed by the building type
Inferred
- The array is a faith-purchase enable refcount; nonzero likely means purchasable
Open questions
- How the counter is later interpreted (>0?)
SetComponentID
Arguments: eOwner — owner player id; id — city id number
Writes
- city id field (0xa8)
- city owner field (0xd8)
- FAutoArchive id (offset 0x8)
Side effects
- calls FAutoArchive::SetID
Input checks: no validation
Multiplayer: may-desync, changes city identity used by archive/networking. Risk: high (changes city identity used by archive/networking). Confidence of the reading: medium.
SetOccupied
Arguments: bNewValue — new occupied flag
Writes
- bool at this+0x328 (auto-variable at this+0x318)
Side effects
- sends Reporting::Event 0xde2d2813 with city id when value changed
Input checks: No input checks; the event compares old and new stored value.
Preconditions
- gameplay state
Multiplayer: safe-deterministic. Risk: low (Single flag write). Confidence of the reading: medium.
Verified from the code
- writes through an auto-variable
- event only when flag changed
Inferred
- occupied means city is under foreign/captured occupation
Open questions
- effects of the flag are elsewhere (e.g. yields or loyalty)
SetSiegeProtection
Arguments: bProtected — whether the city is protected from siege
Writes
- siege-protection byte at this+0x18
- district siege status (via SetSiegeStatus)
Side effects
- district SetSiegeStatus may update visuals/combat state
Input checks: None; assumes a valid city pointer at this+0.
Preconditions
- valid city
- game thread
Multiplayer: may-desync: edits gameplay state; apply on all clients. Risk: low (single flag plus status refresh). Confidence of the reading: medium.
Verified from the code
- stores the bool at this+0x18
- reads district IsBesieged then calls SetSiegeStatus on the editable district with the result
Inferred
- IsBesieged now takes the new protection flag into account so the status may flip
Open questions
- whether SetSiegeStatus triggers notifications