lotr2_player_record — campaign player slot (partial)#
Runtime array: player slots 1..5 (slot 0 unused in most loops), stride 0x160
(352 bytes). Base region anchored at lotr2_game_player_active (0x0055ada4).
- Confidence: likely (offsets from field usage; full layout not recovered)
- Related: display name block @
0x0055a904stride0x2c— see nobles index
Regenerate AI table values:
python3 tools/ghidra/dump_noble_tables.py
See also: nobles index, game MODULE.
Identity fields#
| Offset | Field | Ghidra / VA | Description |
|---|---|---|---|
| +0x00 | active |
lotr2_game_player_active |
Non-zero when slot participates in the campaign |
| +0x01 | eliminated |
lotr2_game_player_eliminated |
Set when lord is defeated; wizard roster dims slot |
| +0x03 | culture_row |
lotr2_game_player_culture_row |
Noble archetype 1–4 (Knight, Baron, Countess, Bishop) |
| +0x04 | text_color_a |
lotr2_game_player_text_color_a |
UI text palette byte from 0x004f7cd6 |
| +0x05 | text_color_b |
lotr2_game_player_text_color_b |
UI text palette byte from 0x004f7cd7 |
| +0x06 | faction_color |
lotr2_game_player_faction_color |
Wizard color index 1–5 (flag / team color) |
| +0x08 | avg_happiness |
lotr2_game_player_avg_happiness |
Mean province happiness (c3bc); Great Noble stat |
culture_row indexes AI parameter tables at (culture_row * 3 - 3) * 0x50 and
L2.ENG group 7 for the default display name.
Assignment: lotr2_game_ai_assign_nation_culture_slots // was FUN_004b2d02 @ 0x004b2d02
Great Noble / diplomacy aggregate stats#
Recomputed each diplomacy pass by lotr2_game_ai_aggregate_player_province_stats
// was FUN_004b342b @ 0x004b342b and ranked by
lotr2_game_ai_compute_player_rankings // was FUN_004b113f @ 0x004b113f.
| Offset | Field | Great Noble label (L2.ENG group 0x23) | Source |
|---|---|---|---|
| +0x25 | county_count |
Most counties | Count of owned provinces |
| +0x48 | castle_count |
Most castles | Provinces with castle under construction (c570, not c573) |
| +0x50 | troop_total |
Most troops | Sum of head_count on active armies |
| +0x08 | avg_happiness |
Happiest people | lotr2_game_player_avg_happiness; mean province c3bc |
| +0x0c | total_province_gold |
Most people * | Sum of province gold stock (c3d4) |
| +0x114 | score |
Most crowns | Running score / treasury ranking field |
| +0x27 | rank_tier |
(late game) | Used when campaign year ≥ 0x4f6 |
* The L2.ENG label Most people is shown for stat index 5; the runtime field at
that index is total_province_gold (+0x0c). Treat label↔field mapping as likely
pending full UI string routing proof.
lotr2_game_ui_great_noble_stat_value // was FUN_0041dc48 @ 0x0041dc48 selects
the field by lotr2_game_great_noble_stat_column // was DAT_00583108 (stat column 0–5, or late-game rank).
Display name block (0x0055a904, stride 0x2c)#
Separate array keyed by player slot; block base is 0x0055a900 (lotr2_game_player_display_id).
| Offset (in 0x2c block) | Field | Symbol (slot 0 anchor) | Role |
|---|---|---|---|
| +0x00 | id_or_rank |
lotr2_game_player_display_id |
DirectPlay id; stores elimination rank on defeat |
| +0x04 | display_name |
— | Up to 31 bytes; AI default from L2.ENG group 7 |
| +0x14 | roster_scratch |
lotr2_game_player_display_roster_scratch |
Zeroed after roster pack/unpack |
| +0x21 | faction_color_copy |
lotr2_net_roster_slot1_id … (wire slots 1–5) |
Per-slot id byte in roster payload |
| +0x25 | nation_slot |
lotr2_game_player_display_nation_slot |
Copy of nation slot; feeds roster lookup rebuild |
| +0x26 | is_custom_name |
lotr2_game_player_display_custom_name |
Non-zero when player entered a custom name |
| +0x27 | defeated |
lotr2_game_player_display_defeated |
Set when player eliminated; cleared on revive |
AI / diplomacy scratch (partial)#
| Offset | Field | Symbol (slot 0 anchor) | Role |
|---|---|---|---|
| +0x18 | attack_pending |
lotr2_game_player_attack_pending |
Set when AI declares war; cleared each sim step |
| +0x1a | alliance_scratch |
lotr2_game_player_alliance_scratch |
Zeroed on alliance form/break (write-only in retail) |
| +0x41 | attack_wait_counter |
lotr2_game_player_attack_wait_counter |
vs attack_patience @ 0x004f3b60 in lotr2_game_ai_army_attack_plan |
| +0x44 | war_target_player |
lotr2_game_player_war_target_player |
Preferred foe for lotr2_map_ai_pick_nearest_attack_province |
| +0x47 | staging_army_slot |
lotr2_game_player_staging_army_slot |
Army slot passed to lotr2_map_ai_pick_best_staging_army |
| +0x49 | castle_build_turns |
lotr2_game_player_castle_build_turns |
Per-turn castle build counter vs table @ 0x004f3bc8 |
| +0x68 | build_rotation_index |
lotr2_game_player_build_rotation_index |
0–9 cycle in lotr2_game_ai_build_rotation_pass |
| +0x6c | ai_buy_sword_budget |
lotr2_game_player_ai_buy_sword_budget |
Troop-buy budget from province sword stock |
| +0x70 | ai_buy_bow_budget |
lotr2_game_player_ai_buy_bow_budget |
vs troop_bow_threshold |
| +0x78 | ai_buy_pike_budget |
lotr2_game_player_ai_buy_pike_budget |
Troop-buy budget from province pike stock |
| +0x7c | alliance_candidate |
lotr2_game_player_alliance_candidate |
AI diplomacy target before alliance |
| +0x7d | alliance_partner |
lotr2_game_player_alliance_partner |
Mutual alliance partner player id |
Diplomacy matrix (per foe, stride 0x10)#
Indexed as base + foe_player_id * 0x10 within each player slot (player_id * 0x160).
| Offset | Field | Symbol (slot 0 anchor) | Role |
|---|---|---|---|
| +0x80 | dipl_attitude |
lotr2_game_player_dipl_attitude |
Signed attitude -30..+30; UI bar; war/trade/tribute deltas |
| +0x81 | dipl_allied |
lotr2_game_player_dipl_allied |
Pairwise allied flag (form_alliance / break_alliance) |
| +0x82 | dipl_ai_alliance_score |
lotr2_game_player_dipl_ai_alliance_score |
AI alliance pressure counter |
| +0x83 | dipl_war_escalation |
lotr2_game_player_dipl_war_escalation |
0→3 escalation before at-war |
| +0x84 | dipl_at_war |
lotr2_game_player_dipl_at_war |
War vs alliance icon in wizard roster |
| +0x85 | dipl_trade_tier |
lotr2_game_player_dipl_trade_tier |
Trade-request tier; bumped on diplomacy queue |
| +0x88 | dipl_tribute_peak |
lotr2_game_player_dipl_tribute_peak |
Max tribute gold offered (dword) |
| +0x8c | dipl_truce |
lotr2_game_player_dipl_truce |
Truce/peace UI sprite when set |
| +0x8d | dipl_contact_level |
lotr2_game_player_dipl_contact_level |
Contact depth; scales diplomacy gold transfer |
AI turn scratch (+0xe1)#
Per-player fields cleared on campaign init; refreshed during AI sim passes.
| Offset | Field | Symbol (slot 0 anchor) | Role |
|---|---|---|---|
| +0xe1 | ai_primary_province |
lotr2_game_player_ai_primary_province |
Best attack province from lotr2_game_ai_pick_primary_secondary_provinces |
| +0xe2 | ai_secondary_province |
lotr2_game_player_ai_secondary_province |
Secondary province from same picker |
| +0xe4 | ai_attack_army_slot |
lotr2_game_player_ai_attack_army_slot |
Army slot scratch in lotr2_game_ai_army_attack_plan |
| +0xe5 | ai_taunt_counter |
lotr2_game_player_ai_taunt_counter |
0–7 counter in lotr2_game_ai_elimination_taunt_pass |
| +0xe6 | ai_taunt_armed |
lotr2_game_player_ai_taunt_armed |
Taunt phase flag after counter rollover |
| +0xe7 | ai_war_target_override |
lotr2_game_player_ai_war_target_override |
Overrides war-target scan in lotr2_map_ai_pick_war_target_player |
| +0xe8 | ai_alliance_attempt_counter |
lotr2_game_player_ai_alliance_attempt_counter |
Alliance candidate attempts vs noble threshold |
| +0xe9 | sole_survivor_flag |
lotr2_game_player_sole_survivor_flag |
Crown message when sole active survivor |
| +0xea | combat_visibility_mask |
lotr2_game_player_combat_visibility_mask |
OR'd into lotr2_combat_figure_visibility_flags during battle reveal/clear |
Economy / upkeep (+0xf0)#
| Offset | Field | Symbol (slot 0 anchor) | Role |
|---|---|---|---|
| +0xf0 | upkeep_tax_total |
lotr2_game_player_upkeep_tax_total |
Parallel accumulator when build-upkeep tax credits treasury |
| +0xf4 | upkeep_tax_mirror |
lotr2_game_player_upkeep_tax_mirror |
Paired with upkeep_tax_total in lotr2_game_compute_build_upkeep |
| +0x100 | treasury_pay_ledger |
lotr2_game_player_treasury_pay_ledger |
Shadow ledger when lotr2_game_apply_resource_delta debits treasury for resource gains |
| +0x104 | treasury_pay_mirror |
lotr2_game_player_treasury_pay_mirror |
Paired pay ledger in resource_delta |
| +0x108 | treasury_recv_ledger |
lotr2_game_player_treasury_recv_ledger |
Shadow ledger when resource_delta credits treasury |
| +0x10c | treasury_recv_mirror |
lotr2_game_player_treasury_recv_mirror |
Paired recv ledger in resource_delta |
| +0x118 | treasury_gold_snapshot |
— (literal 0x55aebc) |
Copy of treasury before diplomacy aggregate sync |
| +0x120 | build_reserve_1_snapshot |
lotr2_game_player_build_reserve_1_snapshot |
Diplomacy affordability snapshot of bow pool |
| +0x128 | build_reserve_3_snapshot |
— (literal 0x55aecc) |
Copy of build-reserve-3 pool for diplomacy |
| +0x130 | build_reserve_0_snapshot |
lotr2_game_player_build_reserve_0_snapshot |
Diplomacy affordability snapshot of sword pool |
| +0xf8 | upkeep_army_strength |
lotr2_game_player_upkeep_army_strength |
Sum from lotr2_game_sum_faction_army_strength; vs treasury in upkeep pass |
| +0x114 | treasury_gold |
lotr2_game_player_treasury_gold |
Faction gold pool; starting value from scenario; province overview UI |
| +0x11c | build_reserve_1 |
lotr2_game_player_build_reserve_1 |
Build-queue slot 1 allocation pool; bow recruitment gate |
| +0x124 | build_reserve_3 |
lotr2_game_player_build_reserve_3 |
Build-queue slot 3 allocation pool |
| +0x12c | build_reserve_0 |
lotr2_game_player_build_reserve_0 |
Build-queue slot 0 allocation pool; sword recruitment gate |
| +0x134 | troop_stock_total |
lotr2_game_player_troop_stock_total |
Sum of six troop-stock dwords |
| +0x138 | province_build_target |
lotr2_game_player_province_build_target |
Six-dword build template copied to faction build table |
| +0x13c | troop_stock |
lotr2_game_player_troop_stock |
Six-dword troop counts; province overview panel; resource kind 0xc (slot 0) |
| +0x140 | troop_yield_res_b |
lotr2_game_player_troop_yield_res_b |
Resource kind 0xb pool; army yield + trade cost |
| +0x144 | troop_yield_res_d |
lotr2_game_player_troop_yield_res_d |
Resource kind 0xd pool |
| +0x148 | troop_yield_res_9 |
lotr2_game_player_troop_yield_res_9 |
Resource kind 9 pool; bishop desperation bonus |
| +0x150 | troop_yield_res_e |
lotr2_game_player_troop_yield_res_e |
Resource kind 0xe pool |
| +0x158 | faction_upkeep_total |
lotr2_game_player_faction_upkeep_total |
Sum of province upkeep; province overview UI |
| +0x14c | crown_total |
lotr2_game_player_crown_total |
Running crown tally; win/desperation checks |
| +0x154 | upkeep_warning_stage |
lotr2_game_player_upkeep_warning_stage |
0→5 when treasury < army upkeep |
| +0x155 | battle_msg_variant |
lotr2_game_player_battle_msg_variant |
Cycles battle-message string variants |
Other economy fields (not yet renamed):
| Offset | Field | Role |
|---|---|---|
| +0x25 | popularity_tier |
Starts at 1 on campaign init; gates score bonuses |
| +0x26 | popularity_tier_copy |
Mirrored at init |
| +0x50 | desperation_counter |
Compared to desperation_threshold before defender spawn |
| +0x114 | score |
Also used for upkeep / diplomacy gold comparisons |
Full per-noble numeric thresholds: nobles index.
Evidence#
| Symbol | Address | Role |
|---|---|---|
lotr2_game_ai_assign_nation_culture_slots |
0x004b2d02 | Assign culture_row, copy L2.ENG name |
lotr2_game_ai_aggregate_player_province_stats |
0x004b342b | Refresh Great Noble counters |
lotr2_game_ai_compute_player_rankings |
0x004b113f | Find leaders per stat column |
lotr2_game_ui_great_noble_stat_value |
0x0041dc48 | Read stat for bar chart |
lotr2_game_ui_great_noble_pick_leader |
0x0041d9e2 | Pick current Greatest Noble |
lotr2_game_ui_enter_great_noble_screen |
0x0041d741 | Draw grtnoble.pl8 screen |
Open questions#
- Full 0x160-byte layout (build templates at
+0xaedc, economy scratch at+0xae85, etc.) - Confirm stat index 5 label vs
total_province_goldfield - GoG build: re-validate table VAs (retail-only dump today)