Home › Dev CE (experimental) › PlayerUnits
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.
PlayerUnits
26 methods (Dev CE test build). this is found with the game's own IPlayerUnits instance resolver (plain).
| Method |
Signature |
Purpose (AI-written, inferred) |
Tested |
Engine function |
Current |
| AddEmbarkUnitPass |
PlayerUnits:AddEmbarkUnitPass(eUnit: integer) |
Appends a unit type to the player's embark-pass list (units allowed to embark) stored in the variant vector at +0x2a0. |
plumbing ✓ |
— |
0x34c410 |
| AddRandomBasePromotion |
PlayerUnits:AddRandomBasePromotion(eUnit: integer) → boolean |
Picks a random promotion of the unit's promotion class that the player does not already have as a base promotion for this unit type, adds it via ChangeBasePromotionCount, and assigns it to existing units. |
plumbing ✓ |
— |
0x34c480 |
| AddUnlimitedPromotionChoiceUnitType |
PlayerUnits:AddUnlimitedPromotionChoiceUnitType(eUnit: integer) |
Adds a unit type to the list (+0xe8) of types that receive unlimited promotion choices, unless already present. |
plumbing ✓ |
— |
0x34c670 |
| AssignBasePromotionsToUnits |
PlayerUnits:AssignBasePromotionsToUnits() |
For each unit the player owns, grants every base promotion (matching unit type with positive count) the unit does not yet have. |
plumbing ✓ |
— |
0x34c800 |
| CanEmbark |
PlayerUnits:CanEmbark(eUnit: integer) → boolean |
Returns whether the player can embark the given unit type: false for barbarians, true if a global parameter allows it, if the unit is in the embark-pass list, or if an owned tech/civic grants embarkation for that unit. |
plumbing ✓ |
— |
0x34c950 |
| ChangeAddOnDistrictFounding |
PlayerUnits:ChangeAddOnDistrictFounding(districtHash: integer, unitHash: integer, iDelta: integer) |
Adds a delta to a counter keyed by district hash and unit hash, recording that a unit can found or add on to a district. |
plumbing ✓ |
Player::Units::ChangeAddOnDistrictFounding |
0x34cb20 |
| ChangeBasePromotionCount |
PlayerUnits:ChangeBasePromotionCount(eUnit: integer, ePromotion: integer, iDelta: integer) → boolean |
Adds iDelta to the count for the (unit type, promotion) base promotion entry, removing the entry when the count drops to 0 or below, or appends a new entry when none exists and iDelta is positive. |
plumbing ✓ |
— |
0x34cbd0 |
| ChangeExtraBuildCharges |
PlayerUnits:ChangeExtraBuildCharges(eUnit: integer, iChange: integer) |
Adds a delta to the extra build charges a player grants to a unit type, clamped at zero. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
Player::Units::ChangeExtraBuildCharges |
0x34cd90 |
| ChangeFreePass |
PlayerUnits:ChangeFreePass(eBuildUnit: integer) |
Appends a unit type to the free-pass list (+0x278), then recalculates which unit types the player can ever train. |
plumbing ✓ |
— |
0x949640 |
| ChangeProductionModifier |
PlayerUnits:ChangeProductionModifier(eUnit: integer, iDelta: integer) |
Adds a delta to a per-unit-type production modifier stored for the player. The delta is scaled by a constant and stored as a fixed-point value. |
plumbing ✓ ran ±1, reversible ✓, no visible effect |
Player::Units::ChangeProductionModifier |
0x9497a0 |
| DoEndTurn |
PlayerUnits:DoEndTurn() |
End-of-turn processing for the player's units: for non-barbarian players iterates units and applies fallout damage on plots with fallout turns remaining (scaled by a per-unit reduction), sending reporting events. Decompilation is truncated so the rest is unknown. |
plumbing ✓ |
— |
0x34d690 |
| DoTurnActivate |
PlayerUnits:DoTurnActivate() |
At turn start resets and recomputes per-resource hero-related unit counts (vector +0x5c8) from units' definitions, then iterates required resources for a major player; decompilation is truncated. |
plumbing ✓ |
— |
0x34e9d0 |
| GetCost |
PlayerUnits:GetCost(eUnit: integer) → number |
Returns the per-unit-type cost from the player's cost array (+0x1c0), or 0 when the type index is beyond the array. |
plumbing ✓ |
— |
0x34f550 |
| GetNumUnitsFromCity |
PlayerUnits:GetNumUnitsFromCity(eUnitType: integer, cityID: integer) → number |
Counts the player's units of a given type whose origin city ID matches. |
plumbing ✓ |
— |
0x34f5d0 |
| GetNumUnitsOfType |
PlayerUnits:GetNumUnitsOfType(eUnit: integer) → number |
Counts the player's units of the given type. |
plumbing ✓ |
— |
0x34f6b0 |
| GetResourceCost |
PlayerUnits:GetResourceCost(eUnit: integer, eMilitaryFormation: integer) → number |
Returns the resource cost of a unit type from array +0x1e8, doubled for formation 1 (corps) and tripled for formation 2 (army); 0 if out of range. |
plumbing ✓ |
— |
0x34f6e0 |
| IsProposedPromotion |
PlayerUnits:IsProposedPromotion(iUnitID: integer, ePromotion: integer) → boolean |
Checks whether the (unit ID, promotion) pair is in the list of proposed promotions at +0x3c8. |
plumbing ✓ |
— |
0x34f8e0 |
| RemoveEmbarkUnitPass |
PlayerUnits:RemoveEmbarkUnitPass(eUnit: integer) |
Rebuilds the embark-pass list without the first occurrence of the given unit type and writes it back to +0x2a0. |
plumbing ✓ |
— |
0x34fbf0 |
| RemoveFreePass |
PlayerUnits:RemoveFreePass(eUnit: integer) |
Rebuilds the free-pass list without all occurrences of the unit type, writes it to +0x278 and recalculates can-ever-train. |
plumbing ✓ |
— |
0x34fe20 |
| RemoveUnlimitedPromotionChoiceUnitType |
PlayerUnits:RemoveUnlimitedPromotionChoiceUnitType(eUnit: integer) |
Removes the unit type from the unlimited-promotion-choice list (+0xe8) if present. |
plumbing ✓ |
— |
0x350040 |
| SetBannedProductionYield |
PlayerUnits:SetBannedProductionYield(eNewYield: integer) |
Sets which yield type may not be used to produce units and, when a restriction is active, removes non-formation-class-2 units currently at the head of every city's build queue. |
plumbing ✓ |
Player::Units::SetBannedProductionYield |
0x350cf0 |
| SetCanEverTrain |
PlayerUnits:SetCanEverTrain() |
Rebuilds the player's table of unit types that can ever be trained, taking into account unlocked units, civ/leader/level traits, unit properties, and replacement relationships. |
plumbing ✓ |
Player::Units::SetCanEverTrain |
0x350dc0 |
| SetCorpsArmyUnlockCivic |
PlayerUnits:SetCorpsArmyUnlockCivic(bLand: boolean, bCorps: boolean, eCivic: integer) |
Stores the civic that unlocks corps or army for land or naval units: land+corps +0x418, land+army +0x430, naval+corps +0x448, naval+army +0x460. |
plumbing ✓ |
— |
0x3511f0 |
| SetCorpsArmyUnlockTech |
PlayerUnits:SetCorpsArmyUnlockTech(bLand: boolean, bCorps: boolean, eTech: integer) |
Stores the tech that unlocks corps or army: land+corps +0x478, land+army +0x490, naval+corps +0x4a8, naval+army +0x4c0. |
plumbing ✓ |
— |
0x351260 |
| SetModifiedArmyCorpsStrength |
PlayerUnits:SetModifiedArmyCorpsStrength(bLand: boolean, bCorps: boolean, iAmount: integer) |
Adjusts one of four stored strength modifiers by an amount, chosen by whether the unit is land/sea and corps/army. |
plumbing ✓ |
Player::Units::SetModifiedArmyCorpsStrength |
0x3512d0 |
| SetPromotionSelected |
PlayerUnits:SetPromotionSelected(iUnitID: integer, ePromotion: integer, bClearProposals: boolean) |
Records that a promotion has been selected by incrementing its counter in a promotion list, and optionally rebuilds a pending proposals list excluding entries for the given unit id. |
plumbing ✓ |
Player::Units::SetPromotionSelected |
0x351330 |
Details
AddEmbarkUnitPass
Arguments: eUnit — Unit type to grant the embark pass for
Writes
- Embark unit pass vector at Units+0x2a0 (append)
Input checks: Ignores -1 (NO_UNIT); does not check for duplicates or that the type is valid.
Multiplayer: may-desync, edits synchronised player list. Risk: medium (Allows duplicates and writes player state.). Confidence of the reading: high.
AddRandomBasePromotion
Arguments: eUnit — Unit type to receive a random base promotion
Writes
- Base promotion list (+0x3f8..0x400) via ChangeBasePromotionCount
- Existing units' promotions via AssignBasePromotionsToUnits
Side effects
- Consumes a game random roll labelled 'Random Base Promotion'
Input checks: Returns false for -1 or unit type without a definition; if no candidate remains passes -1 promotion (which fails).
Multiplayer: may-desync, uses game RNG and edits player units. Risk: high (Consumes RNG and promotes units.). Confidence of the reading: medium.
AddUnlimitedPromotionChoiceUnitType
Arguments: eUnit — Unit type to add
Writes
- Unlimited-promotion-choice unit type vector at Units+0xe8
Input checks: Checks for duplicates only; no validity or -1 check.
Multiplayer: may-desync, edits synchronised player list. Risk: medium (Writes player state without range check.). Confidence of the reading: high.
AssignBasePromotionsToUnits
Writes
- Each owned unit's experience/promotion data (+0x960 via SetPromotion)
Input checks: Skips when the player has no units; no other checks.
Multiplayer: may-desync, changes unit promotions. Risk: medium (Changes promotions of many units.). Confidence of the reading: high.
CanEmbark
Arguments: eUnit — Unit type to test
Input checks: Unit type bounds-checked against definitions; no null handling for owner beyond use.
Multiplayer: read-only, pure check of definitions and player state. Risk: low (Pure check.). Confidence of the reading: medium.
ChangeAddOnDistrictFounding
Arguments: districtHash — hash of the district type; unitHash — hash of the unit type; iDelta — amount added to the counter
Writes
- nested hash map (district hash to unit hash to count) in the variant map at this+0x2c8; creates entries on demand
Side effects
- allocates new map entries when keys are missing
Input checks: No validation of the hashes; any value creates an entry. Counts can go negative or stay at zero without removal.
Preconditions
- gameplay Lua state only
- must run on the game thread
Multiplayer: may-desync: direct replicated state write; hash maps must stay identical on all clients. Risk: low (hash-keyed counter with auto-create). Confidence of the reading: medium.
Verified from the code
- outer map lookup/insert by district hash, inner lookup/insert by unit hash with initial 0, then adds iDelta
Inferred
- nonzero count enables the unit to found that district; semantic taken from the name
Open questions
- where the counters are read and how zero or negative values are treated
ChangeBasePromotionCount
Arguments: eUnit — Unit type of the base promotion; ePromotion — Promotion type; iDelta — Amount to add to the count (negative to remove)
Writes
- Base promotion vector at Units+0x3e8 (entries of 12 bytes: unit, promotion, count)
Input checks: Returns false for -1 unit or promotion; no delta range check; no definition validity check.
Multiplayer: may-desync, edits synchronised player list. Risk: medium (Does not itself apply promotions to units.). Confidence of the reading: high.
ChangeExtraBuildCharges
Arguments: eUnit — unit type; iChange — delta to add
Writes
- per-unit extra build charges array at this+0x318
Side effects
- none
Input checks: silently ignores out-of-range or negative unit ids; result clamped to 0
Preconditions
- gameplay thread
Multiplayer: safe-deterministic. Risk: low (bounds checked and clamped). Confidence of the reading: high.
Verified from the code
- bounds check 0 <= unit < count at +0x338
- clamps negative sum to 0
Inferred
- applies to newly created units of that type (not confirmed)
Open questions
- whether existing units are updated
ChangeFreePass
Arguments: eBuildUnit — Unit type to add to the free pass list
Writes
- Free pass unit vector at Units+0x278 (append)
- Can-ever-train data via SetCanEverTrain
Input checks: No -1 or range check; appends even if present.
Multiplayer: may-desync, edits player list and buildability. Risk: medium (Unchecked append.). Confidence of the reading: medium.
ChangeProductionModifier
Arguments: eUnit — unit type index to modify; iDelta — amount to add (scaled by a small constant, then converted to a fixed-point int)
Writes
- per-unit-type int array in a game variable at this+0x200 (production modifier, fixed point)
Side effects
- marks the game variable as edited (FAutoVariable edit)
Input checks: Silently does nothing if the unit type is not below the array size; the unsigned compare also rejects negative ids.
Preconditions
- gameplay state only
- game thread
Multiplayer: may-desync: direct state change, must be applied identically on all clients. Risk: low (bounds-checked simple array add). Confidence of the reading: medium.
Verified from the code
- bounds check against this+0x220
- multiplies delta by a float constant then splits into integer and fractional parts packed as integer part shifted by 8 plus 8-bit fraction
- adds the packed value into the array slot
Inferred
- value is a percentage-like modifier in 8.8 style fixed point
- constant is likely 0.01
Open questions
- exact constant value and the modifier semantics
DoEndTurn
Writes
- Unit damage via Unit manager (fallout damage)
Side effects
- Reporting events
- Unit manager virtual calls
Input checks: Skips when the player has no units; decompilation is truncated so remaining logic is unknown.
Multiplayer: may-desync, damages units at turn end. Risk: high (Turn-processing function; output truncated.). Confidence of the reading: low.
DoTurnActivate
Writes
- Per-resource vector at Units+0x5c8
- Unit Religion-related bool at unit +0x708
Side effects
- Reporting event block 0x1153df52
Input checks: No argument; remaining logic is truncated.
Multiplayer: may-desync, turn-start processing of player state. Risk: high (Truncated; changes turn state.). Confidence of the reading: low.
GetCost
Arguments: eUnit — Unit type index
Input checks: Upper bound only (unsigned compare, so -1 returns 0).
Multiplayer: read-only, array lookup. Risk: low (Pure getter.). Confidence of the reading: high.
GetNumUnitsFromCity
Arguments: eUnitType — Unit type to count; cityID — Origin city ID (compared with unit field +0x8a0)
Input checks: None.
Multiplayer: read-only, counts owned units. Risk: low (Pure getter.). Confidence of the reading: high.
GetNumUnitsOfType
Arguments: eUnit — Unit type to count
Input checks: None.
Multiplayer: read-only, counts owned units. Risk: low (Pure getter.). Confidence of the reading: high.
GetResourceCost
Arguments: eUnit — Unit type; eMilitaryFormation — Formation: 1 corps (x2), 2 army (x3), else standard
Input checks: Bounds check on unit type; formation value not validated.
Multiplayer: read-only, array lookup. Risk: low (Pure getter.). Confidence of the reading: high.
IsProposedPromotion
Arguments: iUnitID — Unit ID; ePromotion — Promotion type
Input checks: None.
Multiplayer: read-only, list search. Risk: low (Pure getter.). Confidence of the reading: medium.
RemoveEmbarkUnitPass
Arguments: eUnit — Unit type to remove one pass for
Writes
- Embark unit pass vector at Units+0x2a0 (rebuilt)
Input checks: Ignores -1; silently does nothing if the type is absent.
Multiplayer: may-desync, edits synchronised player list. Risk: medium (Removes only the first copy.). Confidence of the reading: high.
RemoveFreePass
Arguments: eUnit — Unit type to remove
Writes
- Free pass vector at Units+0x278 (rebuilt)
- Can-ever-train data
Input checks: No -1 check; absent type is a no-op rewrite.
Multiplayer: may-desync, edits player list and buildability. Risk: medium (Rewrites list.). Confidence of the reading: high.
RemoveUnlimitedPromotionChoiceUnitType
Arguments: eUnit — Unit type to remove
Writes
- Unlimited-promotion-choice vector at Units+0xe8
Input checks: No-op if absent; no -1 check.
Multiplayer: may-desync, edits synchronised player list. Risk: medium (Writes player state.). Confidence of the reading: high.
SetBannedProductionYield
Arguments: eNewYield — yield type that is banned for unit production
Writes
- banned yield value in a tracked variable at this+0x568
- city build queues (PopFront) in each city of the player
Side effects
- pops the front item of the build queue of cities whose current production is a unit whose formation class is not 2
Input checks: Unit index is bounds checked against definition list (null definition otherwise, which would then be dereferenced - crash risk). No validation of the yield value.
Preconditions
- gameplay state
- player with a city list
Multiplayer: may-desync: edits city queues, must run identically everywhere. Risk: medium (mutates build queues; possible null deref on bad definition). Confidence of the reading: medium.
Verified from the code
- assigns new yield into this+0x568 via CopyAssignmentDo
- only loops when int at this+0x578 equals 1
- loops over cities of player and pops queue front when current unit formation class != 2
Inferred
- formation class 2 is probably a civilian or special class
- this+0x578 is probably a flag that the ban is active
Open questions
- meaning of the 0x578 field and formation class 2
- helper template name suggests different type but writes a YieldTypes
SetCanEverTrain
Writes
- per-unit can-ever-train array at this+0x118 (reset to -1, then set to unit index when allowed)
Side effects
- resizes and refills the table
Input checks: null definitions handled; per-unit pointers in the definition list assumed non-null
Preconditions
- owning player set at this+0x90
- definitions loaded
Multiplayer: safe-deterministic. Risk: medium (bulk rebuild of cached table). Confidence of the reading: medium.
Verified from the code
- array at +0x118 set to definition count entries of -1
- units in list at +0x288 are marked allowed immediately
- entries with +0x128 value -1 get checked further against level hash cases and properties
- unit removed (set to -1) by flag bits at +0x1b8/+0x1b9 or when definition field +0x2d0 not in civ/leader lists
- also marks replaced units from list at +0x2b0
Inferred
- level hash constants select property hashes for civilization levels (e.g. city-state/free city)
- list at +0x2b0 is unit replacement or upgrade targets
Open questions
- meaning of the hash constants and flag bits
- the function exits through the definition loop end; any additional state set is not seen
SetCorpsArmyUnlockCivic
Arguments: bLand — True for land units, false for naval; bCorps — True for corps slot, false for army slot; eCivic — Civic type that unlocks the formation
Writes
- One of four unlock-civic fields in Player::Units
Input checks: No range checks on civic.
Multiplayer: may-desync, writes player field. Risk: low (Single field write.). Confidence of the reading: high.
SetCorpsArmyUnlockTech
Arguments: bLand — True for land units, false for naval; bCorps — True for corps slot, false for army slot; eTech — Tech type that unlocks the formation
Writes
- One of four unlock-tech fields in Player::Units
Input checks: No range checks on tech.
Multiplayer: may-desync, writes player field. Risk: low (Single field write.). Confidence of the reading: high.
SetModifiedArmyCorpsStrength
Arguments: bLand — true selects land slots, false naval slots (inferred); bCorps — true selects corps, false army (inferred); iAmount — amount added to the current value
Writes
- one of four tracked ints at this+0x4d8, 0x4f0, 0x508, 0x520 (value at +0x10 of each)
Side effects
- tracked variable assignment, may notify variable system
Input checks: No validation; any int accepted.
Preconditions
- gameplay state
Multiplayer: may-desync: direct state change. Risk: low (simple add to fixed slot). Confidence of the reading: medium.
Verified from the code
- four-way selection by two bools
- new value is old value plus iAmount (despite the Set name it adds)
Inferred
- bool meanings (land vs sea, corps vs army) are deduced from the name
Open questions
- which bool order maps to which slot is deduced only from the name
SetPromotionSelected
Arguments: iUnitID — unit id whose pending proposals are dropped; ePromotion — promotion type to mark; bClearProposals — also remove proposals for this unit
Writes
- promotion/count pair list at this+0x388 (count of matching entry incremented)
- proposal vector at this+0x3b8 (cleared and refilled)
Side effects
- allocates a temporary vector copy
Input checks: If promotion not found in the list nothing is incremented (silent). No unit validation.
Preconditions
- gameplay state
Multiplayer: may-desync: direct state change. Risk: low (simple list updates). Confidence of the reading: medium.
Verified from the code
- linear search of 8-byte pairs for promotion
- increments second element of found pair
- if bClearProposals copies vector at +0x3c8, clears +0x3b8 and re-adds entries whose id field differs from iUnitID
Inferred
- list is promotion with selection count
- vector types in the symbol names look mismatched (symbol folding)
Open questions
- real meaning of the vectors at 0x3b8 and 0x3c8