Home › Dev CE (experimental) › UnitExperience

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.

UnitExperience

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

Method Signature Purpose (AI-written, inferred) Tested Engine function Current
CanEarnPromotion UnitExperience:CanEarnPromotion(ePromotion: integer, bIgnoreRandomPromotionCheck: boolean) → boolean Checks whether a unit can earn a promotion: promotion exists and not already owned, if the unit type requires proposed promotions it must be proposed, class must be valid for the unit type, and all or any prerequisite is owned. plumbing ✓
this ✓ (oracle)
— 0x3969a0
ChangeGeneralExperienceModifier UnitExperience:ChangeGeneralExperienceModifier(iDelta: integer) Adds a percentage-like delta to the unit's general experience modifier, stored as 24.8 fixed point. plumbing ✓
ran ±1, reversible ✓, no visible effect
this ✓ (oracle)
Unit::Experience::ChangeGeneralExperienceModifier 0x396d70
CheckPromoteNotification UnitExperience:CheckPromoteNotification() If the experience flags at +8 and +9 are set, clears +9 and for human owners adds the unit to a PromoteUnit notification, creating one if needed. plumbing ✓
this ✓ (oracle)
— 0x396dc0
GetExperienceModifier UnitExperience:GetExperienceModifier(bIsUnitAttacking: boolean) → number Returns a fixed-point combat modifier from unit experience: base value at +0x28 plus an optional attacker part from +0x2c plus a player bonus scaled by 0.01. plumbing ✓
this ✓ (oracle)
— 0x396f60
GrantPromotion UnitExperience:GrantPromotion(ePromotion: integer, bIgnoreRandomPromotionCheck: boolean) Grants a promotion to a unit if it is allowed to earn it, marking it as selected in the owner's unit table and applying it. plumbing ✓
this ✓ (oracle)
Unit::Experience::GrantPromotion 0x3970f0
SetLevel UnitExperience:SetLevel(iLevel: integer) Sets a unit's experience level directly and sends an event. plumbing ✓
this ✓ (oracle)
Unit::Experience::SetLevel 0x3974a0
SetLevelAndExperience UnitExperience:SetLevelAndExperience(iLevel: integer, iExperience: integer) Sets the experience level (+0x10), clears experience flags and counter (+8,+0xa,+0xc), then calls ChangeExperience with the given amount. plumbing ✓
this ✓ (oracle)
— 0x397500

Details

CanEarnPromotion

Arguments: ePromotion — Promotion type to test; bIgnoreRandomPromotionCheck — If true skips the proposed-promotion (random choice) check

Input checks: Checks promotion index validity and ownership; unit type pointer used without null check.

Multiplayer: read-only; evaluates unit state. Risk: low (pure check). Confidence of the reading: medium.

ChangeGeneralExperienceModifier

Arguments: iDelta — change in percent

Writes - fixed-point modifier at this+0x28

Side effects - none

Input checks: none needed

Preconditions - valid Experience object

Multiplayer: safe-deterministic. Risk: low (simple arithmetic; uses floorf but deterministic). Confidence of the reading: high.

Verified from the code - multiplies iDelta by a float constant (likely 0.01) - splits into integer and fractional (x256) parts and adds to +0x28 as (int<<8)/frac

Inferred - constant is 1/100 so iDelta is a percent - stored as 8-bit fixed point

Open questions - float constants not read directly (symbol names only)

CheckPromoteNotification

Writes - Experience flag at +9 cleared

Side effects - Creates or updates the promote-unit notification for the owner

Input checks: Only acts for human players; returns if notification creation fails.

Multiplayer: may-desync; notifications and unit flag, human only. Risk: low (notification only). Confidence of the reading: medium.

GetExperienceModifier

Arguments: bIsUnitAttacking — If true, adds the attacking experience component (inferred)

Input checks: None.

Multiplayer: read-only; computes from state. Risk: low (pure getter). Confidence of the reading: low.

GrantPromotion

Arguments: ePromotion — promotion type; bIgnoreRandomPromotionCheck — skip the random-promotion restriction in CanEarnPromotion (inferred)

Writes - owner player's Units promotion-selected state via SetPromotionSelected - unit promotion list via SetPromotion

Side effects - Player::Units::SetPromotionSelected(unit type, promotion, false) - Experience::SetPromotion

Input checks: silently does nothing when CanEarnPromotion returns false; owner index not bounds checked

Preconditions - unit belongs to a valid player - gameplay thread

Multiplayer: safe-deterministic. Risk: low (guarded by CanEarnPromotion). Confidence of the reading: high.

Verified from the code - calls CanEarnPromotion with both args first - on success updates owner's Units via SetPromotionSelected then SetPromotion

Inferred - bool name from Linux debug info implies it bypasses random promotion gating

Open questions - what exactly CanEarnPromotion checks

SetLevel

Arguments: iLevel — new level

Writes - level at this+0x10

Side effects - sends Reporting::Event 0xa038d885 with unit id and new level (always, even if unchanged)

Input checks: No validation of level range or unchanged value.

Preconditions - gameplay state

Multiplayer: safe-deterministic. Risk: medium (Unvalidated level could break promotion logic). Confidence of the reading: high.

Verified from the code - writes level unconditionally - always sends event - does not touch XP or promotions

Inferred - promotion availability may depend on level vs promotions taken

Open questions - whether other code expects level to match XP

SetLevelAndExperience

Arguments: iLevel — New experience level; iExperience — Experience points passed to ChangeExperience

Writes - Experience level at +0x10 - Experience fields at +8,+0xa,+0xc reset - Experience points via ChangeExperience

Side effects - Whatever ChangeExperience triggers (possible promotion notification)

Input checks: None; level not range checked.

Multiplayer: may-desync; writes synchronised unit experience. Risk: medium (unvalidated level and xp). Confidence of the reading: medium.