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