Home › Dev CE (experimental) › District
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.
District
19 methods (Dev CE test build). this is found with the game's own IDistrict instance resolver (plain).
| Method |
Signature |
Purpose (AI-written, inferred) |
Tested |
Engine function |
Current |
| AddYieldAdjacencyBonusMirror |
District:AddYieldAdjacencyBonusMirror(eYieldToMirror: integer, eYieldToGrant: integer) |
Adds or increments a mirror entry that grants the district an adjacency bonus of one yield equal to another yield. |
plumbing: not run (no live object) |
— |
0x1901f0 |
| CalculateTourismAdjacencyYieldModifier |
District:CalculateTourismAdjacencyYieldModifier(eYield: integer) → number |
Adjacency yield scaled by a stored percent: adjacency yield times stored tourism percent divided by 100; 0 if unset or out of range. |
plumbing: not run (no live object) |
— |
0x1902d0 |
| ChangeExtraRegionalYield |
District:ChangeExtraRegionalYield(eYield: integer, iDelta: integer) |
Adds a delta to the district's extra regional yield for a given yield type. |
plumbing: not run (no live object) |
District::Instance::ChangeExtraRegionalYield |
0x190470 |
| ChangeGreatPersonPointChange |
District:ChangeGreatPersonPointChange(eClass: integer, xChange: number (fixed point, 1/256 steps)) |
Adds a delta to the district's per-turn Great Person point rate for one Great Person class. |
plumbing: not run (no live object) |
District::Instance::ChangeGreatPersonPointChange |
0x1904d0 |
| ChangeRemainingAttackCount |
District:ChangeRemainingAttackCount(iDelta: integer) |
Adds a delta to the district's remaining attacks count, clamping at zero. |
plumbing: not run (no live object) |
District::Instance::ChangeRemainingAttackCount |
0x190520 |
| ChangeTourismAdjacencyYieldModifier |
District:ChangeTourismAdjacencyYieldModifier(eYield: integer, iDelta: integer) |
Adds a delta to the per-yield modifier used for tourism adjacency bonuses on this district. |
plumbing: not run (no live object) |
District::Instance::ChangeTourismAdjacencyYieldModifier |
0x190590 |
| GetAirSlots |
District:GetAirSlots() → number |
Air unit slots: district definition base slots plus district bonus at 0x410. |
plumbing: not run (no live object) |
— |
0x190710 |
| GetAllCalculatedTourismAdjacencyYieldModifier |
District:GetAllCalculatedTourismAdjacencyYieldModifier() → number |
Sums the tourism adjacency yield modifier over all yield types (positive contributions only). |
plumbing: not run (no live object) |
— |
0x1908b0 |
| GetAppealYield |
District:GetAppealYield(eYield: integer) → number |
Sums appeal-based yield bonuses for the given yield whose appeal threshold is met by the district plot's appeal. |
plumbing: not run (no live object) |
— |
0x190a20 |
| GetExtraRegionalYield |
District:GetExtraRegionalYield(eYield: integer) → number |
Returns stored extra regional yield for a yield type; 0 if out of range, default value if beyond array. |
plumbing: not run (no live object) |
— |
0x191710 |
| GetFirstPillagableBuilding |
District:GetFirstPillagableBuilding() → number |
Returns the unpillaged building at the district plot with the highest value (definition field 0x24), or -1 if none or the district is not pillagable. |
plumbing: not run (no live object) |
— |
0x191750 |
| GetMilitaryDomain |
District:GetMilitaryDomain() → number |
Maps the district definition's domain string (DOMAIN_LAND/SEA/AIR) to a domain type; -1 otherwise. |
plumbing: not run (no live object) |
— |
0x191a50 |
| HasGarrisonedUnit |
District:HasGarrisonedUnit() → boolean |
True if the district is active, its definition flag permits it, and the best defender on its plot is a combat unit. |
plumbing: not run (no live object) |
— |
0x191e10 |
| HasMaxDamage |
District:HasMaxDamage() → boolean |
True if district damage (0x318) reaches its definition max damage; if no max is defined, true when damage is non-negative. |
plumbing: not run (no live object) |
— |
0x191ea0 |
| HasWalls |
District:HasWalls() → boolean |
True if the district's outer-defense damage field (0x330) is below the city's outer defense hit points while max damage is positive. |
plumbing: not run (no live object) |
— |
0x191f10 |
| IsBesieged |
District:IsBesieged() → boolean |
Determines whether the district is besieged by enemy units or auto-siege units on adjacent plots at war with its owner; decompilation is truncated so the tail is not visible. |
plumbing: not run (no live object) |
— |
0x1924e0 |
| RemoveYieldAdjacencyBonusMirror |
District:RemoveYieldAdjacencyBonusMirror(eYieldToMirror: integer, eYieldToGrant: integer) |
Decrements the matching adjacency mirror entry and removes it when its count drops below one. |
plumbing: not run (no live object) |
— |
0x192940 |
| SetComplete |
District:SetComplete(bState: boolean, bOriginalCompletion: boolean) |
Sets the district's completed flag; when completed it notifies the owner and game, and pays out any pending add-on district-founding free units or great people. |
plumbing: not run (no live object) |
District::Instance::SetComplete |
0x192c20 |
| SetSiegeStatus |
District:SetSiegeStatus(bIsUnderSiege: boolean) |
Sets whether a district is under siege and sends an event identifying the district via its owner's district list. |
plumbing: not run (no live object) |
District::Instance::SetSiegeStatus |
0x1930e0 |
Details
AddYieldAdjacencyBonusMirror
Arguments: eYieldToMirror — yield whose adjacency bonus is copied; eYieldToGrant — yield that receives the mirrored bonus
Writes
- District mirror list (VariantMap at 0x188): new entry with count 1 or existing count +1
Input checks: No range check on yield types.
Multiplayer: may-desync, changes district adjacency data. Risk: medium (edits a synchronised variable). Confidence of the reading: medium.
CalculateTourismAdjacencyYieldModifier
Arguments: eYield — yield type
Input checks: Range-checks yield.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: high.
ChangeExtraRegionalYield
Arguments: eYield — yield type; iDelta — amount to add
Writes
- per-yield int array in auto variable at this+0x2a8 (or a fallback int at container+0x18)
Input checks: Silent no-op for yield outside 0..NUM_YIELD_TYPES-1.
Preconditions
- game thread
Multiplayer: safe-deterministic. Risk: low (Bounds checked counter change.). Confidence of the reading: medium.
Verified from the code
- Range-checks the yield
- Adds iDelta to element eYield of the array when within container length
- Otherwise adds to a field at container+0x18
Inferred
- Regional yield means yield shared to other cities in the region
Open questions
- Purpose of fallback field
ChangeGreatPersonPointChange
Arguments: eClass — great person class index; xChange — amount to add (raw/256)
Writes
- per-class FixedPoint array in auto-variable at this+0x1e8 (great person point change)
Side effects
- marks the auto-variable as edited (network/replication tracked state)
Input checks: Checks index is non-negative and below array size; otherwise silently ignored.
Preconditions
- valid district
- class index in range
Multiplayer: safe-deterministic. Risk: low (bounds-checked add through tracked edit()). Confidence of the reading: medium.
Verified from the code
- bounds check on class index
- add via FAutoVariable edit
Inferred
- the array is the per-turn rate, not accumulated total (from name)
- size check uses the array at +0x1f8 while edit is on +0x1e8, likely the same data
Open questions
- whether cached player GP rates are refreshed elsewhere
ChangeRemainingAttackCount
Arguments: iDelta — change in remaining attacks
Writes
- remaining attack count at this+0x360 (auto-variable wrapper at +0x350)
Side effects
- none
Input checks: negative result clamped to 0; no upper cap
Preconditions
- valid district instance
Multiplayer: safe-deterministic. Risk: low (clamped counter). Confidence of the reading: high.
Verified from the code
- sets value to current + iDelta then re-assigns 0 if negative
Inferred
- field is the district's attack counter reset each turn
Open questions
- where the maximum is enforced
ChangeTourismAdjacencyYieldModifier
Arguments: eYield — yield type; iDelta — amount to add
Writes
- per-yield int array in auto variable at this+0x2d8 (or fallback int at container+0x18)
Input checks: Silent no-op for yield outside valid range.
Preconditions
- game thread
Multiplayer: safe-deterministic. Risk: low (Bounds checked counter change.). Confidence of the reading: medium.
Verified from the code
- Same structure as ChangeExtraRegionalYield but on the field at this+0x2d8
- Range check on eYield then add to element
Inferred
- Field is a tourism adjacency yield modifier table
Open questions
- Units of the modifier (percent vs flat)
GetAirSlots
Input checks: Bounds-checks definition index (out-of-range path reads a bad address).
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
GetAllCalculatedTourismAdjacencyYieldModifier
Input checks: Range-checks yields.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: high.
GetAppealYield
Arguments: eYield — yield type
Input checks: None.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
GetExtraRegionalYield
Arguments: eYield — yield type
Input checks: Range-checks yield.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: high.
GetFirstPillagableBuilding
Input checks: Checks definition flags.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
GetMilitaryDomain
Input checks: Bounds-checks definition.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: high.
HasGarrisonedUnit
Input checks: Null checks on defender.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
HasMaxDamage
Input checks: Bounds-checks definition.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
HasWalls
Input checks: Bounds-checks definition.
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: medium.
IsBesieged
Input checks: Unknown (truncated).
Multiplayer: read-only, reads city/district state only. Risk: low (pure getter). Confidence of the reading: low.
RemoveYieldAdjacencyBonusMirror
Arguments: eYieldToMirror — mirrored source yield; eYieldToGrant — yield receiving the mirror
Writes
- District mirror list (VariantMap at 0x188)
Input checks: No-op if entry not found.
Multiplayer: may-desync, changes district adjacency data. Risk: medium (edits a synchronised variable). Confidence of the reading: medium.
SetComplete
Arguments: bState — new completion state; bOriginalCompletion — passed through to the city-signal (first-time completion flag) (inferred)
Writes
- district complete flag (auto variable at this+0x3e8)
- player add-on district founding counters (decremented by 1 per paid entry)
- creates units in the city or awards free great person
Side effects
- dispatches a player signal (PlayerTypes, BeliefTypes) on the owner
- dispatches a game signal (City*, bool)
- City::Manager::CreateUnit for non-great-person add-on units, with alternate location search
- Game::GreatPeople::AwardFreePersonByClass for great person class units
- may move units to find a free placement
Input checks: Flag is always written. Everything else only when bState is true, a game exists and the district has a city. District index from this+0xf0 is bounds checked against definitions (null definition otherwise leads to a null deref).
Preconditions
- gameplay state
- district attached to a city
- game thread
Multiplayer: may-desync: creates units and awards great people; deterministic if run on all clients, but dangerous from Lua on one side only. Risk: high (Spawns units/great people and fires signals; invalid district index would read a null definition.). Confidence of the reading: medium.
Verified from the code
- Writes the bool into the auto variable at this+0x3e8 first
- If true and a city exists: dispatches two signals
- Looks up the owner's add-on district founding map keyed by a hash from the district definition and iterates it
- For each entry with nonzero count: great person class unit awards a free person, otherwise creates a unit in the city after trying to find an alternate plot
- Decrements the founding counter by 1 afterwards
Inferred
- Second signal's bool is the 'original completion' flag
- This implements 'free unit on first district built' style abilities
Open questions
- Meaning of local_res10 map key (district hash at definition+0x1c)
- Exact signal names
SetSiegeStatus
Arguments: bIsUnderSiege — new siege flag
Writes
- bool at this+0x440 (auto-variable at this+0x430)
Side effects
- sends Reporting::Event 0xfbada2c8 with district ids and the new flag
Input checks: No-op if unchanged. If the plot has no owner, the district is treated as null and its fields are read through a null pointer (crash risk). Result of Districts::Find is not null-checked.
Preconditions
- district on an owned plot
- gameplay state
Multiplayer: safe-deterministic. Risk: medium (Possible null dereference when plot is unowned or district not found). Confidence of the reading: medium.
Verified from the code
- early-out on equal value
- looks up owner via plot and Districts::Find
- reads from the found pointer without a null check
Inferred
- the event identifies the district by its player-list instance
Open questions
- whether a null pointer is ever reached in practice