Home › Dev CE (experimental) › GameDiplomacy

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.

GameDiplomacy

16 methods (Dev CE test build). this is found with the game's own IGameDiplomacy instance resolver (virtual).

Method Signature Purpose (AI-written, inferred) Tested Engine function Current
ChangeGrievanceAndTension GameDiplomacy:ChangeGrievanceAndTension(a: integer, b: integer, iNumGrievances: integer) Changes the grievance score between two players by the amount and the tension score by its absolute value. plumbing ✓ — 0x1ce9f0
ChangeTensionScore GameDiplomacy:ChangeTensionScore(a: integer, b: integer, iChangeinTension: integer) Adds a delta to the tension score of an unordered player pair (stored in a triangular array), clamped at 0, and stamps the current game turn when the delta is positive. plumbing ✓ — 0x1ceb50
DoTurn GameDiplomacy:DoTurn() Per-turn processing: for each pair of players with an alliance it adds alliance points per turn to both and, if the alliance level changed, dispatches a signal and sends notifications to both players. Decompilation is truncated, so later behaviour is unseen. plumbing ✓ — 0x1cf680
GetAllianceType GameDiplomacy:GetAllianceType(a: integer, b: integer) → number Returns the alliance type stored for the unordered player pair, or -1 if both players are the same. plumbing ✓ — 0x1d0900
GetGrievanceScore GameDiplomacy:GetGrievanceScore(a: integer, b: integer) → number Returns the grievance score for the pair, signed by who holds the grievance: positive if the stored owner equals a, negative otherwise, 0 if a==b or no owner. plumbing ✓ — 0x1d0cc0
GetJointWarTarget GameDiplomacy:GetJointWarTarget(initiator: integer, partner: integer) → number Returns the joint war target stored for the unordered pair of players. plumbing ✓ — 0x1d0d60
GetLastTurnPlayerWasOfferedDeal GameDiplomacy:GetLastTurnPlayerWasOfferedDeal(ePlayer: integer) → number Loops over all players other than ePlayer calling Diplomacy::GetLastTurnOfferedDeal but discards the results and always returns 0 as decompiled. plumbing ✓ — 0x1d0dc0
GetResearchAgreementTech GameDiplomacy:GetResearchAgreementTech(a: integer, b: integer) → number Returns the tech of the research agreement between the pair, or -1 if same player. plumbing ✓ — 0x1d0e80
GetTensionScore GameDiplomacy:GetTensionScore(a: integer, b: integer) → number Returns the tension score of the unordered pair, 0 if same player. plumbing ✓ — 0x1d0ee0
ResetAllianceDuration GameDiplomacy:ResetAllianceDuration(a: integer, b: integer) If the pair has an alliance, sets its last-change turn field to the current game turn. plumbing ✓ — 0x1d3120
SetAtWar GameDiplomacy:SetAtWar(a: integer, b: integer, war: integer) Sets or clears the war state between two players with a given war type (war type -1 means peace). Logs the event, resets denouncements, expels units from territory, and updates visibility blockers. plumbing ✓ Game::DiplomaticRelations::SetAtWar 0x1d31b0
SetIsAllied GameDiplomacy:SetIsAllied(a: integer, b: integer, allied: integer) Sets or clears the alliance type between two players, stamps the turn, dispatches alliance start or end signals, sets the defensive pact flag, logs a diplomatic event and sends reporting events. Decompilation is truncated after visibility handling. plumbing ✓ — 0x1d3920
SetIsInDefensivePact GameDiplomacy:SetIsInDefensivePact(a: integer, b: integer, pact: boolean) Sets or clears a defensive pact between two players, stamps the current turn, dispatches a pact started/ended signal and logs a diplomatic event. plumbing ✓ Game::DiplomaticRelations::SetIsInDefensivePact 0x1d3c30
SetJointWarTarget GameDiplomacy:SetJointWarTarget(initiator: integer, partner: integer, target: integer) Records a joint war target between two players (initiator and partner) along with the current turn. plumbing ✓ Game::DiplomaticRelations::SetJointWarTarget 0x1d3db0
SetResearchAgreementTech GameDiplomacy:SetResearchAgreementTech(a: integer, b: integer, eTech: integer) Stores the research agreement tech and current turn for the pair, dispatches a start or end signal (end when tech is -1) and logs a diplomatic event. plumbing ✓ — 0x1d4050
SetSharesSuzerain GameDiplomacy:SetSharesSuzerain(a: integer, b: integer, c: boolean) Sets whether two players share the same suzerain (city-state overlord) and logs a diplomatic event for it. plumbing ✓ Game::DiplomaticRelations::SetSharesSuzerain 0x1d41d0

Details

ChangeGrievanceAndTension

Arguments: a — first player; b — second player; iNumGrievances — signed grievance delta; absolute value added to tension

Writes - grievance score for the pair (via ChangeGrievanceScore) - tension score for the pair (via ChangeTensionScore)

Side effects - last-change turn recorded for tension when delta positive

Input checks: No checks itself; delegates.

Multiplayer: may-desync, writes synchronised diplomacy state. Risk: medium (edits diplomacy state without validation). Confidence of the reading: high.

ChangeTensionScore

Arguments: a — first player; b — second player; iChangeinTension — tension delta

Writes - tension VariantMap entry at +0x2c8 (value and last-change turn)

Input checks: Clamps result to >= 0; no check for a==b or invalid players.

Multiplayer: may-desync, writes game diplomacy VariantMap. Risk: medium (unchecked indexing; a==b or invalid player index would hit a wrong slot). Confidence of the reading: high.

DoTurn

Writes - player Diplomacy alliance points (both players)

Side effects - alliance level change signal - localized notifications to both players - callees show game speed adjustment and symmetric deal turn lookup

Input checks: Skips pairs with no alliance (-1); no other checks visible.

Multiplayer: may-desync, advances alliance state each turn. Risk: high (turn processing; calling it again double-counts alliance points). Confidence of the reading: low.

GetAllianceType

Arguments: a — first player; b — second player

Input checks: Only a==b checked; no range check.

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

GetGrievanceScore

Arguments: a — player whose perspective is used; b — other player

Input checks: a==b and owner -1 give 0; no range check.

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

GetJointWarTarget

Arguments: initiator — first player (inferred); partner — second player (inferred)

Input checks: No checks, even for equal players.

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

GetLastTurnPlayerWasOfferedDeal

Arguments: ePlayer — player being queried

Input checks: None.

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

GetResearchAgreementTech

Arguments: a — first player; b — second player

Input checks: Only a==b checked.

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

GetTensionScore

Arguments: a — first player; b — second player

Input checks: Only a==b checked.

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

ResetAllianceDuration

Arguments: a — first player; b — second player

Writes - alliance VariantMap entry turn stamp at +0x200

Input checks: Skips if alliance type is -1; no player range check.

Multiplayer: may-desync, writes alliance state. Risk: medium (synchronised alliance state). Confidence of the reading: high.

SetAtWar

Arguments: a — first player id; b — second player id; war — war type; -1 = peace

Writes - war-state/turn pair for the player pair in a triangular matrix at this+0x188 - aggressor and turn pair for the player pair in matrix at this+0x1b0 (aggressor = a, or -1 on peace) - current game turn stamp copied from game object +0xc0

Side effects - if players differ, pair not yet met and war type != -1: Player::Manager::Meet is called (first meeting) - LogDiplomaticEvent with At War (war type string) or Peace - on war: ResetDenouncement on both players, ExpelFromTerritory(reason 3) both ways, AddOutgoingVisibilityBlocker three times - on peace: ExpelFromTerritory(reason 4) both ways and RemoveOutgoingVisibilityBlocker three times

Input checks: no bounds check on player ids (unchecked triangular index); when a==b the first meet branch is skipped but state write still happens at a degenerate index; war-type not validated

Preconditions - both ids valid active players - gameplay Lua state, game thread

Multiplayer: may-desync: mutates global diplomatic state; must be executed identically on all clients. Risk: high (unchecked player index, changes global diplomacy, visibility and unit placement). Confidence of the reading: medium.

Verified from the code - war type 0xffffffff selects the Peace branch - tri-matrix index uses player count at +0xb8 - edit() called on two FAutoVariable maps - Meet called only when pair not already met and war type != -1 - expel and visibility-blocker calls happen only if both players' flag at +600 is non-zero

Inferred - flag at +600 likely means player is alive/major - maps at +0x188 and +0x1b0 hold war state and aggressor - the +0xd0 per-pair byte is a has-met flag - war-type string is used purely for logging

Open questions - exact meaning of ExpelFromTerritory reason codes 3 and 4 - why visibility blocker is added twice for the same ordered pair

SetIsAllied

Arguments: a — first player; b — second player; allied — alliance type to set, -1 ends the alliance

Writes - alliance VariantMap entry (type and turn) - defensive pact flag via SetIsInDefensivePact - diplomatic event log

Side effects - Alliance start/end message signals - Reporting events sent - visibility updates (seen in truncated tail)

Input checks: No-op if type and turn unchanged; no range check on players.

Multiplayer: may-desync, changes alliances and visibility. Risk: high (alliance change cascades to pacts and visibility). Confidence of the reading: medium.

SetIsInDefensivePact

Arguments: a — first player; b — second player; pact — true to create, false to end

Writes - pair entry in triangular-indexed array at this+0x138: flag byte and turn (from game +0xc0)

Side effects - signal dispatch (Unit, Plot) pact-start (+0xd98) or pact-end (+0xdb0) with the two players' player objects as args - LogDiplomaticEvent 'Defensive Pact' or 'Defensive Pact Ends'

Input checks: No range or equality checks on ids; unchecked pair index and player-array lookups (crash risk).

Preconditions - game thread - two valid distinct player ids

Multiplayer: may-desync: diplomatic state. Risk: medium (unvalidated indices). Confidence of the reading: medium.

Verified from the code - symmetric pair index computed from min/max of ids - logs strings Defensive Pact / Defensive Pact Ends - different signals for set vs clear

Inferred - signal arg types shown in template (Unit, Plot) are probably Ghidra mislabels of player objects

Open questions - real signal parameter types

SetJointWarTarget

Arguments: initiator — player starting the joint war; partner — allied partner; target — player the war is declared on

Writes - pair table entry at this+0x1d8: target player and current turn

Input checks: No bounds check on ids; triangular pair index is unchecked (out-of-bounds risk).

Preconditions - valid player ids - game thread

Multiplayer: safe-deterministic. Risk: medium (Unchecked pair index.). Confidence of the reading: high.

Verified from the code - Pair index is symmetric so initiator/partner order does not matter for storage - Stores target in the first field and the current turn in the second - Does not declare war itself

Inferred - Passing -1 as target probably clears it

Open questions - Whether callers use the stored turn for expiry

SetResearchAgreementTech

Arguments: a — first player; b — second player; eTech — tech under agreement, -1 ends it

Writes - research agreement VariantMap entry (tech, turn) at +0x160

Side effects - Research agreement start/end signal - diplomatic event log entry

Input checks: No range or validity checks.

Multiplayer: may-desync, writes synchronised diplomacy state. Risk: medium (unvalidated indexes). Confidence of the reading: high.

SetSharesSuzerain

Arguments: a — first player; b — second player; c — true if they now share a suzerain

Writes - pair table entry at this+0x228: bool flag and current turn

Side effects - calls LogDiplomaticEvent with text 'Shares Suzerain' or 'No longer shares Suzerain' and an empty second string

Input checks: No bounds checks on player ids (unchecked triangular index). The log is written even if the value did not change.

Preconditions - valid player ids - game thread

Multiplayer: safe-deterministic. Risk: medium (Unchecked pair index.). Confidence of the reading: high.

Verified from the code - Writes bool and turn into pair record - Builds strings and calls LogDiplomaticEvent(this, a, b, text, empty) - Text depends on the bool

Inferred - Used by relationship (diplomatic visibility/modifier) scoring

Open questions - Whether the log appears in UI or only the diplomatic log