Home › Dev CE (experimental) › PlayerCities

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.

PlayerCities

19 methods (Dev CE test build). this is found with the game's own IPlayerCities instance resolver (plain).

Method Signature Purpose (AI-written, inferred) Tested Engine function Current
AddBuildingReplacementOverride PlayerCities:AddBuildingReplacementOverride(eBuildingToReplace: integer, eBuildingOverride: integer) Registers a building replacement (one building replaced by another) on the player, then swaps existing buildings in every city and moves their great works. The decompilation is truncated near the end. plumbing ✓ — 0x264110
ChangeExtraStartingPopulationOffHomeContinent PlayerCities:ChangeExtraStartingPopulationOffHomeContinent(iChange: integer) Adds a delta to a player's bonus starting population for cities founded off their home continent. plumbing ✓
ran ±1, reversible ✓, no visible effect
Player::Cities::ChangeExtraStartingPopulationOffHomeContinent 0x2644d0
CheckUnhandledCityDecisions PlayerCities:CheckUnhandledCityDecisions() Collects the player's cities that have pending decisions (fields 0x2e0/0x2f8 set). For human players it issues a Destroy command request per city; for AI it resets two request fields to -1. The decompilation is truncated. plumbing ✓ — 0x264500
DoEndTurn PlayerCities:DoEndTurn() If the player has any cities, calls City::Manager::Heal on each city. plumbing ✓ — 0x265330
DoSetTurnComplete PlayerCities:DoSetTurnComplete(eRequestType: integer) For two specific turn request subtypes and a human player, clears unassigned production overflow in all cities. plumbing ✓ — 0x2653d0
DoTurnActivate PlayerCities:DoTurnActivate() Gets the improvements rules object and calls a lambda invoker; the decompilation shows only these two calls, so the real behaviour is unclear. plumbing ✓ — 0x265410
GetAICitiesCaptured PlayerCities:GetAICitiesCaptured(neverHuman: boolean) → number Counts this player's cities originally owned by another AI major player; if neverHuman is true, owners with a nonempty nickname are skipped. plumbing ✓ — 0x265600
GetNumBuildings PlayerCities:GetNumBuildings(eBuilding: integer) → number Counts the player's cities that have the given building. plumbing ✓ — 0x2658c0
GetNumCapturedCityStates PlayerCities:GetNumCapturedCityStates() → number Counts cities whose original owner differs from the current owner and is neither a major player nor barbarian. plumbing ✓ — 0x265920
GetNumOriginalCapitalsCaptured PlayerCities:GetNumOriginalCapitalsCaptured() → number Counts cities whose original owner differs from the current owner, are flagged as original capital (0x298) and whose original owner is a major player. plumbing ✓ — 0x2659a0
HasCityOnContinent PlayerCities:HasCityOnContinent(continent: integer) → boolean Returns true if the continent is in the player's list of continents with cities. plumbing ✓ — 0x265aa0
HasSlotForGreatWork PlayerCities:HasSlotForGreatWork(iIndex: integer) → boolean Returns true if any city of the player can accept the great work index into a slot. plumbing ✓ — 0x265ae0
IsDistrictBuildingBanned PlayerCities:IsDistrictBuildingBanned(eDistrict: integer) → boolean Returns true if the district type is in the player's banned-district list. plumbing ✓ — 0x265d10
RemoveBuildingReplacementOverride PlayerCities:RemoveBuildingReplacementOverride(eBuildingToReplace: integer, eBuildingOverride: integer) Removes one matching pair from the building replacement list, then reverts existing buildings in the player's cities and relocates great works. The decompilation is truncated near the end. plumbing ✓ — 0x265e80
RemoveUnassignedProductionOverflow PlayerCities:RemoveUnassignedProductionOverflow() For each city of the player with no active build item (field 0x12b0 zero or pointer 0x12a0 null), clears the build queue production overflow. plumbing ✓ — 0x266120
SetCanEverConstruct PlayerCities:SetCanEverConstruct() Rebuilds a player's table of buildings that can ever be constructed, based on civ/leader/government traits, obsolete wonders and building conditions, then marks related buildings. plumbing ✓ Player::Cities::SetCanEverConstruct 0x266570
SetCityUrbanDefenses PlayerCities:SetCityUrbanDefenses(iDefenseValue: integer) Sets the player city urban-defense value and fires an event with the owner id and value. plumbing ✓ Player::Cities::SetCityUrbanDefenses 0x266f50
SetDistrictBuildingBanned PlayerCities:SetDistrictBuildingBanned(eDistrict: integer, bBan: boolean) Adds or removes a district type in the list of districts whose buildings are banned for this player. plumbing ✓ Player::Cities::SetDistrictBuildingBanned 0x266f90
SetPopulationAfterConquest PlayerCities:SetPopulationAfterConquest(iPercent: integer) Stores a percentage setting for the population kept in cities after conquest. plumbing ✓ Player::Cities::SetPopulationAfterConquest 0x2670b0

Details

AddBuildingReplacementOverride

Arguments: eBuildingToReplace — building type that is to be replaced; eBuildingOverride — building type that replaces it

Writes - building replacement override list at 0x168 - cities' buildings (ReplaceBuilding) - can-ever-construct state

Side effects - notifies Rules::Cities OnCityBuildingOverrideAdded and relocates great works in each affected city

Input checks: Ignores -1 for either argument and skips duplicate pairs; does not check the buildings exist.

Multiplayer: may-desync, changes cities' buildings. Risk: high (rewrites buildings in all cities of the player). Confidence of the reading: medium.

ChangeExtraStartingPopulationOffHomeContinent

Arguments: iChange — amount added to the stored bonus

Writes - extra starting population off home continent counter at this+0x1a8 (assigned through an auto-variable wrapper at this+0x198)

Side effects - none visible beyond the tracked variable assignment

Input checks: Zero change returns immediately. No range clamp on result.

Preconditions - valid Cities object for a player

Multiplayer: may-desync: player state mutation; must be applied identically on all clients. Risk: low (simple integer accumulator, no clamping needed). Confidence of the reading: high.

Verified from the code - no-op if param is 0 - new value = old value + change, stored at this+0x1a8

Inferred - counter is applied when new cities are founded off home continent (from the name)

Open questions - where the counter is consumed

CheckUnhandledCityDecisions

Writes - city decision fields reset to -1 for AI cities - city command requests queued for humans

Side effects - queues City::Commands::Destroy request through the command manager for human players

Input checks: Skips cities without a valid index; no other checks.

Multiplayer: may-desync, resets city decisions and queues commands. Risk: high (can issue destroy commands and clear AI decisions). Confidence of the reading: low.

DoEndTurn

Writes - city health through Heal (delegated)

Side effects - each city is healed by City::Manager::Heal

Input checks: Skips when there are no cities; an invalid city index passes null to Heal.

Multiplayer: may-desync, heals cities. Risk: medium (changes city health state). Confidence of the reading: medium.

DoSetTurnComplete

Arguments: eRequestType — turn request subtype; only two hashed values (0x720b6468, 0x4601eac9) trigger the work

Writes - city build queue overflow (via RemoveUnassignedProductionOverflow)

Input checks: Only acts for the two request subtypes and human players.

Multiplayer: may-desync, clears city production overflow. Risk: medium (indirectly clears build queue overflow). Confidence of the reading: medium.

DoTurnActivate

Writes - unknown, delegated to a lambda

Input checks: None visible.

Multiplayer: unknown, behaviour hidden in a lambda. Risk: medium (body only calls a lambda, effect unknown). Confidence of the reading: low.

GetAICitiesCaptured

Arguments: neverHuman — if true, exclude owners whose configuration has a nonempty nickname (inferred)

Input checks: Skips cities with flag at 0x208 set, invalid original owners and the player itself.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: medium.

GetNumBuildings

Arguments: eBuilding — building type to count

Input checks: None; passes the building type to HasBuilding for each city.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

GetNumCapturedCityStates

Input checks: None.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

GetNumOriginalCapitalsCaptured

Input checks: None.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

HasCityOnContinent

Arguments: continent — continent type to look for in the list at 0x128

Input checks: None; linear search.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

HasSlotForGreatWork

Arguments: iIndex — great work list index to place

Input checks: None; each city is queried with no building filter.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

IsDistrictBuildingBanned

Arguments: eDistrict — district type to look for in the ban list at 0x228

Input checks: None; linear search.

Multiplayer: read-only, pure query. Risk: low (pure getter). Confidence of the reading: high.

RemoveBuildingReplacementOverride

Arguments: eBuildingToReplace — building type that had been replaced; eBuildingOverride — building type that replaced it

Writes - building replacement override list at 0x168 (rebuilt without the pair) - cities' buildings (ReplaceBuilding) - can-ever-construct state

Side effects - relocates great works in each affected city via Rules::Cities

Input checks: No -1 or existence check; rebuilds the list even if the pair is absent.

Multiplayer: may-desync, changes cities' buildings. Risk: high (rewrites buildings in all cities of the player). Confidence of the reading: medium.

RemoveUnassignedProductionOverflow

Writes - city build queue overflow cleared

Input checks: Invalid city indices pass a null city; no other checks.

Multiplayer: may-desync, clears city overflow production. Risk: medium (loses leftover production). Confidence of the reading: medium.

SetCanEverConstruct

Writes - per-building can-ever-construct int array at this+0x140 (cleared to -1, then set to the building's own index when allowed) - local fixed_vector scratch of unlocked building ids

Side effects - resizes and refills the can-ever-construct vector - calls Initializer::ObsoleteWonders per building

Input checks: null definition pointers skipped; recomputation only in the branch where civ or leader definition exists

Preconditions - owning player set (this+0x90) - definitions loaded

Multiplayer: safe-deterministic. Risk: medium (bulk rebuild of a cached table; output C is truncated so details unconfirmed). Confidence of the reading: low.

Verified from the code - array at +0x140 is reset to size of building definition count filled with -1 - civilization and leader types read from player configuration of owner - checks BuildingCondition entries and ObsoleteWonders - entries set to the building index mean allowed

Inferred - conditions with flag bit 1 and matching type block the building - unique building replacement handling occurs in the truncated tail

Open questions - input C is truncated mid-function so the tail (unique-building replacement and final writes) was not read - semantics of fixed_vector scratch use

SetCityUrbanDefenses

Arguments: iDefenseValue — new urban defense value

Writes - int at this+0xec (urban defenses)

Side effects - sends reporting event 0x93556d2d with player id and new value

Input checks: No validation; value stored as-is.

Preconditions - gameplay Lua state - valid Cities object

Multiplayer: may-desync: direct state write. Risk: medium (Unvalidated state write.). Confidence of the reading: medium.

Verified from the code - Stores param at this+0xec - Sends event 0x93556d2d with owner id and value

Inferred - It is a replacement, not additive - Field is player-wide (stored on Cities, not on a city)

Open questions - How the value is consumed in combat

SetDistrictBuildingBanned

Arguments: eDistrict — district whose buildings are banned/unbanned; bBan — true to add the ban, false to remove it

Writes - banned-district-buildings list at this+0x218

Side effects - none visible; unlike SetCityProductionBanned it does not touch build queues

Input checks: Type -1 returns silently. Duplicates not checked. Unban of absent entry silent.

Preconditions - valid player Cities object

Multiplayer: may-desync: player state mutation; must run identically on all clients. Risk: low (list edit only, no queue changes). Confidence of the reading: high.

Verified from the code - appends on ban, erase-by-shift on unban - no queue manipulation in this function

Inferred - checked by building eligibility logic

Open questions - whether existing queued buildings are purged elsewhere

SetPopulationAfterConquest

Arguments: iPercent — percentage value stored

Writes - population-after-conquest percent at this+0x1b0 (via auto-variable assignment)

Side effects - none visible

Input checks: A value of 0 is ignored (returns without writing), so it cannot be set to 0 through this function. No clamping.

Preconditions - valid player Cities object

Multiplayer: may-desync: player state mutation; must run identically on all clients. Risk: low (single integer assignment). Confidence of the reading: medium.

Verified from the code - param 0 is a no-op - otherwise assigns the value (not additive) at this+0x1b0

Inferred - value is a percentage as named in the Linux parameter - consumer is city capture logic

Open questions - default value and where it is consumed - whether the 0 guard is deliberate