Home › Dev CE (experimental) › CityBuildings
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.
CityBuildings
27 methods (Dev CE test build). this is found with the game's own ICityBuildings instance resolver (plain).
| Method |
Signature |
Purpose (AI-written, inferred) |
Tested |
Engine function |
Current |
| AddGreatWork |
CityBuildings:AddGreatWork(iIndex: integer) |
Places a great work into the first empty compatible slot in the city's buildings, and signals if the building is correctly themed. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::AddGreatWork |
0x109290 |
| AddGreatWorkToSlot |
CityBuildings:AddGreatWorkToSlot(iIndex: integer, eBuilding: integer, iSlot: integer) |
Places a great work into a slot of a building in the city, using the first empty slot if slot is negative, then checks themed-building bonus. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::AddGreatWorkToSlot |
0x1099b0 |
| ChangeWonderYieldChange ✓ |
CityBuildings:ChangeWonderYieldChange(eYield: integer, iChange: integer) |
Adds a flat yield delta that applies to wonders in the city, per yield type, keeping a small list of (yield, value) pairs. |
plumbing ✓ effect ✓ (GetFoodSurplus, GetTurnsUntilGrowth) this ✓ (oracle) |
City::Buildings::ChangeWonderYieldChange |
0x109d30 |
| ChangeYieldChange ✓ |
CityBuildings:ChangeYieldChange(eBuilding: integer, eYield: integer, iChange: integer) |
Adds a flat yield delta for a specific building in a city, creating or removing the entry as needed. |
plumbing ✓ effect ✓ (GetFoodSurplus) this ✓ (oracle) |
City::Buildings::ChangeYieldChange |
0x109dc0 |
| ChangeYieldChangeCityStates ✓ |
CityBuildings:ChangeYieldChangeCityStates(eBuilding: integer, eYield: integer, iChange: integer) |
Same as ChangeYieldChange but for the separate list of per-building flat yield changes tied to city states. |
plumbing ✓ effect ✓ (GetFoodSurplus) this ✓ (oracle) |
City::Buildings::ChangeYieldChangeCityStates |
0x109f10 |
| ChangeYieldChangeFromFeature |
CityBuildings:ChangeYieldChangeFromFeature(eFeature: integer, eYield: integer, iChange: integer) |
Adds or removes a flat yield change entry keyed by feature and yield. Positive deltas append a new entry; negative deltas rebuild the list without the matching entry. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::ChangeYieldChangeFromFeature |
0x10a060 |
| ChangeYieldModifier |
CityBuildings:ChangeYieldModifier(eBuilding: integer, eYield: integer, iChange: integer) |
Adds a delta to a per-building percentage yield modifier entry in a city. Creates the entry if missing and removes it when the sum becomes zero. |
plumbing ✓ ran ±1, reversible ✓, no visible effect this ✓ (oracle) |
City::Buildings::ChangeYieldModifier |
0x10a1d0 |
| CheckForThemedBuilding |
CityBuildings:CheckForThemedBuilding(eBuilding: integer) |
If the building is themed correctly, dispatches a game signal with the city instance and the building type (signal on current game at +0x240; Ghidra shows a Unit-based signature, likely a mismatched type). |
plumbing ✓ this ✓ (oracle) |
— |
0x10a2c0 |
| GetFreeSlot |
CityBuildings:GetFreeSlot(eBuilding: integer) → number |
Finds the first empty great-work slot index in the given building's slot list. |
plumbing ✓ this ✓ (oracle) |
— |
0x10b7a0 |
| GetFreeSlotOfType |
CityBuildings:GetFreeSlotOfType(eBuilding: integer, slotType: integer) → number |
Finds the first empty slot of a specific great-work slot type in the given building. |
plumbing ✓ this ✓ (oracle) |
— |
0x10b800 |
| GetNumBuildings |
CityBuildings:GetNumBuildings() → number |
Counts non-wonder buildings (flag 0x40 clear) that exist in the city, using the location array. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bab0 |
| GetNumBuildingsAtLocation |
CityBuildings:GetNumBuildingsAtLocation(iPlotIndex: integer) → number |
Counts buildings whose recorded plot index equals the given plot index. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bb40 |
| GetNumFreeSlots |
CityBuildings:GetNumFreeSlots(slotType: integer) → number |
Counts empty great-work slots of a given slot type across all buildings. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bbb0 |
| GetNumGreatWorks |
CityBuildings:GetNumGreatWorks(eGreatWorkObjectTypeFilter: integer) → number |
Counts great works held in slots, optionally filtered by great work object type (all if filter is -1). |
plumbing ✓ this ✓ (oracle) |
— |
0x10bc50 |
| GetNumWonders |
CityBuildings:GetNumWonders() → number |
Counts wonders (building flag 0x40 set) that exist in the city. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bd40 |
| GetTourismFromGreatWorks |
CityBuildings:GetTourismFromGreatWorks(bReligious: boolean) → number |
Sums tourism from great works across all buildings with great-work slots via GetBuildingTourismFromGreatWorks. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bdd0 |
| GetTourismFromOneWonder |
CityBuildings:GetTourismFromOneWonder(eBuilding: integer) → number |
Computes tourism of a single wonder: global base parameter plus era difference between player's era and wonder's era, scaled by city wonder tourism modifier; returns the base if the global flag is off. |
plumbing ✓ this ✓ (oracle) |
— |
0x10be50 |
| GetTourismFromWonders |
CityBuildings:GetTourismFromWonders() → number |
Sums tourism over all wonders present in the city that are not flagged in the exclusion array, via GetTourismFromOneWonder. |
plumbing ✓ this ✓ (oracle) |
— |
0x10bf80 |
| GetYieldChange |
CityBuildings:GetYieldChange(eBuilding: integer, eYield: integer) → number |
Returns total flat yield change of a building for a yield: district-derived yield (if a yield-conversion applies), plus a wonder-specific entry, plus a stored per-building yield modifier. |
plumbing ✓ this ✓ (oracle) |
— |
0x10c0e0 |
| GetYieldChangeCityStates |
CityBuildings:GetYieldChangeCityStates(eBuilding: integer, eYield: integer) → number |
Returns the stored city-state yield change for a building and yield, or 0 if none. |
plumbing ✓ this ✓ (oracle) |
— |
0x10c250 |
| GetYieldChangeFromFeature |
CityBuildings:GetYieldChangeFromFeature(eFeature: integer, eYield: integer) → number |
Sums yield change entries matching a feature and yield from the stored list. |
plumbing ✓ this ✓ (oracle) |
— |
0x10c290 |
| GetYieldFromGreatWorks |
CityBuildings:GetYieldFromGreatWorks(eYield: integer) → number |
Sums yield from great works for a yield type across all buildings with slots via GetBuildingYieldFromGreatWorks. |
plumbing ✓ this ✓ (oracle) |
— |
0x10c2d0 |
| GetYieldModifier |
CityBuildings:GetYieldModifier(eBuilding: integer, eYield: integer) → number |
Looks up the stored yield modifier percent for a building (mapped to its generic equivalent) and yield; 0 if none. |
plumbing ✓ this ✓ (oracle) |
— |
0x10c350 |
| IsInCity |
CityBuildings:IsInCity(iIndex: integer) → boolean |
Checks whether the great work with the given list index is held in any building slot of this city. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::IsInCity |
0x10cc60 |
| RemoveAllBuildings |
CityBuildings:RemoveAllBuildings() |
Removes every building from a city: for each building slot it clears the plot link and wonder status, removes great-work slots, and sends removal events. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::RemoveAllBuildings |
0x10cf80 |
| RemoveYieldModifier |
CityBuildings:RemoveYieldModifier(eBuilding: integer, eYield: integer) |
Removes the first (building, yield) modifier entry from the city's building yield-modifier list by swapping in the last element. |
plumbing ✓ this ✓ (oracle) |
— |
0x10d5c0 |
| SetEraCreatedToGameEra |
CityBuildings:SetEraCreatedToGameEra(eBuilding: integer) |
Records the current game era as the era in which a given building was created in this city. |
plumbing ✓ this ✓ (oracle) |
City::Buildings::SetEraCreatedToGameEra |
0x10e880 |
Details
AddGreatWork
Arguments: iIndex — great work list index
Writes
- slot entry in building's great-work slot array
Side effects
- signal dispatch (city, building) when themed correctly
Input checks: If no valid slot, does nothing. Index not bounds-checked in game culture list.
Preconditions
- gameplay state
Multiplayer: may-desync: must be applied everywhere. Risk: medium (unchecked index). Confidence of the reading: medium.
Verified from the code
- first empty slot that accepts object type
- signal only if themed correctly
Open questions
- slot kind 0xffffffff meaning empty
AddGreatWorkToSlot
Arguments: iIndex — great work index; eBuilding — building to hold it; iSlot — slot index, negative = first empty slot
Writes
- great work id stored in the building's slot array
Side effects
- calls CheckForThemedBuilding(building)
Input checks: Silent return if the building is not in the city, slot out of range, or no empty slot.
Preconditions
- building exists in city
- game thread
Multiplayer: safe-deterministic. Risk: low (bounds checked). Confidence of the reading: high.
Verified from the code
- finds building by type
- negative slot picks first slot whose value is -1
- bounds checks slot
- assigns and runs theming check
Inferred
- does not remove the great work from elsewhere
Open questions
- does not check slot type compatibility
ChangeWonderYieldChange
Arguments: eYield — yield type; iChange — delta to add
Writes
- list of (yield, value) 8-byte pairs at this+0xb0 (capacity +0xb8, count +0xc0)
Side effects
- may grow the vector
Input checks: no check on eYield (a -1 yield is appended); entries are never removed when sum is zero
Preconditions
- valid city Buildings
Multiplayer: safe-deterministic. Risk: low (simple list update). Confidence of the reading: medium.
Verified from the code
- linear search for matching yield; adds delta if found, else appends
Inferred
- entry meaning is yield change for each wonder (from the name)
Open questions
- where the list is consumed
ChangeYieldChange
Arguments: eBuilding — building type; eYield — yield type; iChange — delta to add
Writes
- list of (building, yield, value) 12-byte entries at this+0x80 (capacity +0x88, count +0x90)
Side effects
- entry removed (swap with last) when the sum becomes zero
- may grow the vector
Input checks: new entries created only if both ids != -1; otherwise silent no-op
Preconditions
- valid city Buildings
Multiplayer: safe-deterministic. Risk: low (id-guarded list edit). Confidence of the reading: high.
Verified from the code
- FindYieldChange used to locate entry
- append when absent, remove via swap-with-last when value equals -iChange, else add
Inferred
- yields are not recomputed here
Open questions
- who triggers yield recompute
ChangeYieldChangeCityStates
Arguments: eBuilding — building type; eYield — yield type; iChange — delta to add
Writes
- list of (building, yield, value) entries at this+0x98 (capacity +0xa0, count +0xa8)
Side effects
- entry removed (swap with last) when the sum becomes zero
- may grow the vector
Input checks: new entries only if both ids != -1; otherwise silent no-op
Preconditions
- valid city Buildings
Multiplayer: safe-deterministic. Risk: low (id-guarded list edit). Confidence of the reading: medium.
Verified from the code
- identical algorithm to ChangeYieldChange on a separate vector at +0x98
Inferred
- list name suggests city-state based yield (e.g. per suzerain/envoy)
Open questions
- consumer of the list and exact condition
ChangeYieldChangeFromFeature
Arguments: eFeature — feature type; eYield — yield type; iChange — delta (positive adds an entry, negative removes a matching one)
Writes
- list of (feature, yield, value) 12-byte entries at this+0xf8 (capacity +0x100, count +0x108)
Side effects
- allocates and frees a temporary vector on negative deltas
Input checks: for positive deltas, appends only when feature and yield are not -1 (silent no-op otherwise); entries are not merged, duplicates allowed
Preconditions
- valid city Buildings
Multiplayer: safe-deterministic. Risk: medium (negative path appears to only copy to a temp and free it; stored list is not updated in the visible code, possible decompile artifact). Confidence of the reading: low.
Verified from the code
- iChange < 0 branch builds a filtered copy skipping the first entry equal to the negated value, then calls operator_delete and returns
- iChange >= 0 branch appends a new entry without merging
Inferred
- intent is add/remove symmetric entries; negative branch seems not to write the filtered list back (decompile may be incomplete)
Open questions
- whether the filtered list is written back in the real code (decompile shows only delete)
- whether iChange of 0 appends an empty entry
ChangeYieldModifier
Arguments: eBuilding — building type index; eYield — yield type index; iChange — delta to add to the modifier
Writes
- vector of (building, yield, value) 12-byte entries at this+0x68 (capacity at +0x70, count at +0x78)
Side effects
- calls RemoveYieldModifier when an existing entry would become zero
- may grow the vector
Input checks: new entries are only created if building and yield are not -1; if the entry exists it is updated regardless; if not found and ids invalid, silent no-op
Preconditions
- valid city Buildings object
- gameplay thread
Multiplayer: safe-deterministic. Risk: low (simple bookkeeping with id guard). Confidence of the reading: high.
Verified from the code
- linear search over 12-byte entries comparing first two ints
- appends when none found and both ids != -1
- removes via RemoveYieldModifier when existing value == -iChange
- else adds iChange
Inferred
- value is percent yield modifier from the name
- this change is not immediately propagated to city yields (no recompute call seen)
Open questions
- whether the caller triggers a yield recompute
CheckForThemedBuilding
Arguments: eBuilding — building type to check
Side effects
- Dispatches a game-level signal (themed-building event) when theme is correct
Input checks: No range check; relies on IsBuildingThemedCorrectly.
Multiplayer: may-desync: fires signal handlers that may change state. Risk: medium (signal listeners may alter synchronised state). Confidence of the reading: medium.
GetFreeSlot
Arguments: eBuilding — building type
Input checks: None; returns -1 if building not found.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetFreeSlotOfType
Arguments: eBuilding — building type; slotType — great work slot type required
Input checks: None; returns -1 if not found.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetNumBuildings
Input checks: Bounds-checks index against array size.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetNumBuildingsAtLocation
Arguments: iPlotIndex — plot index to match
Input checks: Bounds-checks against array size; negative entries skipped.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetNumFreeSlots
Arguments: slotType — great work slot type
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetNumGreatWorks
Arguments: eGreatWorkObjectTypeFilter — object type filter or -1 for all
Input checks: Checks definition index and null; -1 means no filter.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetNumWonders
Input checks: Bounds-checks against array size.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetTourismFromGreatWorks
Arguments: bReligious — whether to count religious great works (inferred)
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetTourismFromOneWonder
Arguments: eBuilding — wonder building type
Input checks: Range-checks building but does not null-check the definition or era before dereference.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: medium.
GetTourismFromWonders
Input checks: Bounds-checked against array sizes.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetYieldChange
Arguments: eBuilding — building type; eYield — yield type
Input checks: Range-checks building; no null check on the definition before field reads.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: medium.
GetYieldChangeCityStates
Arguments: eBuilding — building type; eYield — yield type
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetYieldChangeFromFeature
Arguments: eFeature — feature type; eYield — yield type
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetYieldFromGreatWorks
Arguments: eYield — yield type
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
GetYieldModifier
Arguments: eBuilding — building type; eYield — yield type
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
IsInCity
Arguments: iIndex — great work list index
Input checks: None.
Multiplayer: read-only: pure getter. Risk: low (pure getter). Confidence of the reading: high.
RemoveAllBuildings
Writes
- building plot-location array at this+0x8 set to -1
- building flag array at this+0x20 cleared to 0
- array at this+0x38 set to -1
- wonder type on the wonder plot via the improvement builder
Side effects
- dispatches a game signal (+0x210) per removed building
- calls RemoveGreatWorkSlots
- if the building is a nuclear reactor type, calls Fallout::Manager::RemoveNuclearReactor
- calls a virtual on Rules::Cities (slot 0xa8) with the building index and plot
- sends Reporting::Event 0xe074eef4 per building with plot coordinates
Input checks: No arguments. Index bounds are checked for the definition arrays; null definition pointers are handled in places but one lookup dereferences without a null check.
Preconditions
- gameplay state
- city must be fully initialised
Multiplayer: may-desync: mass state mutation including map and wonder state. Risk: high (Wipes all buildings, wonders and side data in one call). Confidence of the reading: medium.
Verified from the code
- iterates all slots of the building array
- skips slots whose value is -1
- sets slot value to -1 after processing
- sends one event per removed building
Inferred
- the array at +0x8 maps building type to plot id
- flag 0x10 at definition+0x159 means wonder
- government lookup with bit 8 means nuclear reactor (odd naming)
Open questions
- what the Rules::Cities virtual at 0xa8 does
- exact role of the government-collection lookup
RemoveYieldModifier
Arguments: eBuilding — building type of the entry to remove; eYield — yield type of the entry to remove
Writes
- City::Buildings yield-modifier array (data ptr 0x68, count 0x78): one 12-byte entry removed
Input checks: No range check on types; silently does nothing if no matching entry.
Multiplayer: may-desync, changes city yield modifier data. Risk: medium (alters city yield modifiers without any recalculation call). Confidence of the reading: medium.
SetEraCreatedToGameEra
Arguments: eBuilding — building type index
Writes
- per-building era-created 16-bit entry in the array at this+0x38, indexed by building type
Input checks: None. The building index is used unchecked to index the array, so an invalid or negative index writes out of bounds (crash or memory corruption risk).
Preconditions
- valid building type index
- game running (Eras singleton exists)
- game thread
Multiplayer: safe-deterministic. Risk: medium (Unchecked array index; otherwise a trivial deterministic write.). Confidence of the reading: high.
Verified from the code
- Calls Game::Eras::Edit and copies a 16-bit value from Eras+0xb8
- Stores it at (this+0x38)[eBuilding] as 2 bytes
- No bounds check on the index
Inferred
- Eras+0xb8 is the current game era; the array is the per-building created-era table
Open questions
- Exact meaning/name of the field at Eras+0xb8