Home › Dev CE (experimental) › PlayerTechs

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.

PlayerTechs

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

Method Signature Purpose (AI-written, inferred) Tested Engine function Current
CanTriggerBoost PlayerTechs:CanTriggerBoost(eTech: integer) → boolean Checks whether the boost attached to the given tech can currently be triggered for this player; first requires Game::Culture::HasCivic to be true for the id. plumbing ✓
this ✓ (oracle)
— 0x333530
DoResearch PlayerTechs:DoResearch() Per-turn research step: computes science yield, adds it to an accumulated amount and applies it to the current research (first queue entry) or stores it if nothing is being researched. plumbing ✓
this ✓ (oracle)
— 0x3337a0
FindBestTechtoStealFromPlayer PlayerTechs:FindBestTechtoStealFromPlayer(targetPlayer: integer) → number Picks a tech to steal from the target player by scanning tech definitions and building candidate lists; decompilation is truncated so the final selection logic is not visible. plumbing ✓
this ✓ (oracle)
— 0x333a00
GetNumTechsResearched PlayerTechs:GetNumTechsResearched(bIncludeRepeatedTechs: boolean) → number Counts the techs flagged as researched, optionally adding the repeated-tech count. plumbing ✓
this ✓ (oracle)
— 0x333cd0
GrantAllBoostsByEra PlayerTechs:GrantAllBoostsByEra(eStartEra: integer, eEndEra: integer) Triggers the eureka boost for every tech in the eras between eStartEra and eEndEra that has a boost, is not researched and has not yet been boosted. plumbing ✓
this ✓ (oracle)
— 0x3340a0
GrantRandomBoostGoodyHut PlayerTechs:GrantRandomBoostGoodyHut(iNumFreeBoosts: integer, eSource: integer) Grants a number of random tech boosts (from the era of the cheapest not-yet-owned tech) to a player, used by goody huts. plumbing ✓
this ✓ (oracle)
Player::Techs::GrantRandomBoostGoodyHut 0x3342e0
GrantRandomBoostsByEra PlayerTechs:GrantRandomBoostsByEra(iNumFreeBoosts: integer, eStartEra: integer, eEndEra: integer) Collects boostable techs from eras in a range, then randomly triggers a number of their eurekas for the player using the game RNG. plumbing ✓
this ✓ (oracle)
Player::Techs::GrantRandomBoostsByEra 0x3346d0
GrantRandomTechs PlayerTechs:GrantRandomTechs(iNumTechs: integer) Builds the list of researchable techs, then randomly picks iNumTechs of them and sets their research progress to full cost; decompilation is truncated at the end of the loop. plumbing ✓
this ✓ (oracle)
— 0x334a00
SetAllTechsByPreviousEra PlayerTechs:SetAllTechsByPreviousEra(eEraType: integer) Grants every technology whose era is earlier than the given era (index >1), recomputing unit/district costs and signalling each grant. plumbing ✓
this ✓ (oracle)
Player::Techs::SetAllTechsByPreviousEra 0x335a30
SetNumFreeTechBoostOnNewEra PlayerTechs:SetNumFreeTechBoostOnNewEra(numBoosts: integer, applyImmediately: boolean) Adds to the number of free tech boosts granted on entering a new era and optionally grants boosts immediately. plumbing ✓
this ✓ (oracle)
Player::Techs::SetNumFreeTechBoostOnNewEra 0x335b80
SetScienceRateChange PlayerTechs:SetScienceRateChange(xNewValue: number (fixed point, 1/256 steps)) Sets the science rate change value if it differs from the current one and sends an event. plumbing ✓
this ✓ (oracle)
— 0x336590

Details

CanTriggerBoost

Arguments: eTech — Tech type whose boost is tested

Input checks: Returns false when HasCivic fails or no boost matches; index not otherwise checked.

Multiplayer: read-only, only reads player/map state. Risk: low (pure getter). Confidence of the reading: medium.

DoResearch

Writes - Research progress of the current tech (via ChangeResearchProgress) - Stored leftover science value at +0xf8

Side effects - Sends a research notification (hash 0x592df4c8) to the player

Input checks: No validation except an empty queue or -1 head, which stores science instead.

Multiplayer: may-desync, changes research progress. Risk: high (Advances research and sends a notification). Confidence of the reading: medium.

FindBestTechtoStealFromPlayer

Arguments: targetPlayer — Player to steal from

Input checks: Returns -1 for an invalid target player; target is not otherwise checked.

Multiplayer: read-only, only builds temporary candidate lists. Risk: low (Looks like a selector, but the body is cut off). Confidence of the reading: low.

GetNumTechsResearched

Arguments: bIncludeRepeatedTechs — If true adds the repeatable-tech counter (+0x1c8)

Input checks: No validation.

Multiplayer: read-only, only reads player/map state. Risk: low (pure getter). Confidence of the reading: high.

GrantAllBoostsByEra

Arguments: eStartEra — First era (inclusive); eEndEra — Last era (inclusive)

Writes - Boost-triggered state for each qualifying tech (via TriggerBoost)

Side effects - TriggerBoost may raise events/notifications for each tech

Input checks: Era indices are bounds checked; if either era is invalid nothing is boosted.

Multiplayer: may-desync, triggers boosts changing research. Risk: medium (Mass-triggers boosts, but only for unresearched techs). Confidence of the reading: medium.

GrantRandomBoostGoodyHut

Arguments: iNumFreeBoosts — how many boosts to grant; eSource — source of the boost, passed to TriggerBoost

Writes - triggers tech boosts through Techs::TriggerBoost - consumes random numbers

Side effects - calls Techs::TriggerBoost per selected tech - advances game RNG (label: Choosing random tech boost to grant based on era) - heap-allocates candidate list on overflow

Input checks: Does nothing if count <= 0 or no candidates; tech ids of -1 or out of range skip the already-boosted checks.

Preconditions - valid player - game thread

Multiplayer: safe-deterministic. Risk: low (normal gameplay path using game RNG). Confidence of the reading: medium.

Verified from the code - structure mirrors the Culture version: find lowest-era unowned tech, collect its era's available boosts, pick randomly without repeats - uses GetRandNum with the label 'Choosing random tech boost to grant based on era' - calls TriggerBoost for chosen techs not already boosted

Inferred - decompiler mislabels Government/Culture types; actual types are technologies

Open questions - exact era selection due to decompiler type confusion

GrantRandomBoostsByEra

Arguments: iNumFreeBoosts — number of boosts to grant; eStartEra — first era of range; eEndEra — last era of range

Writes - tech boost state via TriggerBoost(tech, 3)

Side effects - TriggerBoost per chosen tech with source 3 - consumes game RNG draws (named 'Choosing random tech boost...')

Input checks: Silent no-op if either era is not found; stops when no candidates remain.

Preconditions - game thread - valid eras

Multiplayer: safe-deterministic: uses the synced game RNG with a log string. Risk: medium (triggers boosts, RNG consumption). Confidence of the reading: medium.

Verified from the code - filters by era range, HasBoost, HasCivic, not HasTech, not already triggered - picks via Game::Instance::GetRandNum and removes chosen from list - calls TriggerBoost with 3

Inferred - HasCivic on the tech id is likely a mislabeled check - candidate weights are all 1

Open questions - meaning of TriggerBoost source value 3 - oddity of HasCivic check on a tech id

GrantRandomTechs

Arguments: iNumTechs — How many random techs to grant

Writes - Research progress of the chosen techs (SetResearchProgress)

Side effects - Consumes game random numbers - Likely completes techs and triggers their unlock events

Input checks: Stops when the candidate list is empty; iNumTechs <= 0 does nothing.

Multiplayer: may-desync, uses game RNG and changes techs. Risk: high (Gives free techs and uses synchronized RNG). Confidence of the reading: low.

SetAllTechsByPreviousEra

Arguments: eEraType — era; techs from earlier eras are granted

Writes - tech-researched byte array at this+0x128

Side effects - Units::RecomputeAllCosts and Districts::RecomputeAllCosts for each tech granted - signal (Unit*,uint) at game signal +0x12f0 with player and tech id

Input checks: Era pointer used unchecked if index out of range (null deref risk); does nothing when era index <=1.

Preconditions - game thread - valid era

Multiplayer: may-desync: bulk grant. Risk: medium (bulk tech grant, expensive recompute per tech). Confidence of the reading: medium.

Verified from the code - only techs with era value below target - recomputes unit and district costs for each - dispatches per-tech signal

Inferred - does not grant eurekas or tech side effects beyond the signal

Open questions - whether already known techs are re-signalled (no check seen)

SetNumFreeTechBoostOnNewEra

Arguments: numBoosts — amount added to the stored count (despite the Set name it is additive); applyImmediately — also grant random boosts now for the current era

Writes - int auto-variable at this+0x1a0 (stored count at this+0x1b0 plus numBoosts)

Side effects - when applyImmediately, current era valid and numBoosts > 0: calls GrantRandomBoostsByEra, which grants random tech boosts (uses random numbers)

Input checks: Immediate grant is skipped if the era is -1 or numBoosts is not positive. The stored count is updated regardless.

Preconditions - gameplay Lua state only - owner player must be set

Multiplayer: may-desync: random boost selection must use the synchronized game RNG. Risk: medium (additive despite Set name, plus random grant side effect). Confidence of the reading: medium.

Verified from the code - stored value = old + numBoosts - calls GrantRandomBoostsByEra only if applyImmediately, era != -1 and numBoosts > 0

Inferred - GrantRandomBoostsByEra takes the era twice, probably a from/to range - negative numBoosts reduces stored count

Open questions - whether the era-change handler consumes the stored count

SetScienceRateChange

Arguments: xNewValue — New science rate change as a fixed point value

Writes - Science rate change at +0x110/+0x120

Side effects - Sends an event (hash 0xdca96e74) for the owning player

Input checks: No validation; skips when the value is unchanged.

Multiplayer: may-desync, writes player state. Risk: medium (Only modifies a rate and sends an event). Confidence of the reading: high.