Skip to content

lotr2_battle_group — combat group slot (partial)#

Summary#

Each battle group is a fixed slot (stride 0x34, up to 80 slots indexed 1..0x50) that ties one or more battle figures to a shared goal, order type, and group-AI state machine. Groups are allocated at army spawn (lotr2_combat_spawn_figure_batch) and rebuilt when the player regroups (lotr2_combat_assign_group_orders).

  • Confidence: likely (offsets from field usage; full 0x34-byte layout not fully zeroed/analyzed)
  • Stride: 0x34 (52 bytes)
  • Base region: lotr2_combat_group_table // was DAT_00583140 @ 0x00583140 (retail); GoG DAT_00566520
  • Max index: 0x50 (80 groups; index 0 unused)

Normative AI rules: ../spec/combat/npc-battle-ai.md. Module: combat MODULE.

Key offset table#

Offset Field Ghidra / VA Description
+0x00 player_id +0x00583140 Owner player slot byte (same namespace as figure player_id)
+0x01 player_control_flag +0x00583141 Non-zero → skip group-AI dispatch in lotr2_combat_tick_all_groups
+0x02 member_count +0x00583142 Live figures assigned to this group
+0x03 defender_spawn_row +0x00583143 Siege defender spawn row index (from spawn param_4)
+0x04 first_figure +0x00583144 First figure slot index in group (int16)
+0x06 last_figure +0x00583146 Last figure slot index in group (int16)
+0x08 order_type lotr2_combat_group_order_type @ +0x00583148 Indexes group tick handler table (see spec)
+0x0A target_group +0x0058314a Locked enemy group index for focus / stalk (int16)
+0x0C target_lock_timer +0x0058314c Countdown from 0x32 when a kill target is acquired
+0x0D busy_flag +0x0058314d Set while any member is in melee-engage figure state 4
+0x0E retreat_timer +0x0058314e Decrements each sync pass; gates rout behavior
+0x0F stalk_timer +0x0058314f Ranged stalk / assault pacing timer
+0x10 stalk_cleared +0x00583150 Cleared by approach_enemy; used by stalk branch
+0x11 siege_engaged +0x00583151 Set when a member enters figure state 9
+0x12 kill_counter +0x00583152 Incremented on target acquisition; decrements each sync
+0x13 formation_blocked +0x00583153 Set by move_group_to_tile; cleared on replan
+0x14 replan_timer +0x00583154 Counts down each frame; at 0 triggers group_replan_orders (initial 600)
+0x16 phase_counter +0x0058315a AI phase index; drives behavior branches within tick handlers
+0x18 decision_timer +0x0058315c Increments each frame; decisions fire when > 199 (or > 99 for defend_wall)
+0x1A routing_flag +0x0058316a Set by mark_side_infantry_routing; blocks replan
+0x1B siege_lane_flag +0x0058316b Gates periodic siege-lane reposition
+0x1C move_mode +0x0058316c Passed to move_group_to_tile as param_4
+0x1D lane_timer +0x0058316d Decrements each sync; clears stalk timer
+0x1E centroid_x +0x0058315e Group center tile X (int16)
+0x20 centroid_y +0x00583160 Group center tile Y (int16)
+0x22 goal_x +0x00583162 Current movement goal X (int16)
+0x24 goal_y +0x00583164 Current movement goal Y (int16)

Figure back-link: figure group_index at figure +0x186 (DAT_005496b8 field).

Lifecycle#

  1. Allocatelotr2_combat_alloc_group_slot(player_id, player_control_flag) finds first empty slot, clears it, writes +0x00 and +0x01.
  2. Spawn link — each spawned figure stores the group index; member_count increments.
  3. Synclotr2_combat_sync_group_slot_counters rebuilds counts, busy flags, and target-lock state each battle frame before figure tick.
  4. Clearlotr2_combat_clear_group_slot / lotr2_combat_clear_all_group_slots.

Evidence#

Claim Source
Stride 0x34 param_1 * 0x34 on all group field accesses
order_type at +0x08 lotr2_combat_group_order_type rename @ 0x00583148
AI skip when +0x01 set lotr2_combat_tick_all_groups @ 0x0049a0b5
replan_timer initial 600 lotr2_combat_tick_all_groups resets to 600 on expiry
decision_timer threshold 200 All lotr2_combat_group_tick_order_* compare > 199
Centroid recompute lotr2_combat_update_group_centroid @ 0x00499e61

Open questions#

  • Purpose of bytes +0x26..+0x33 (if any — slot is 0x34 bytes total)
  • Exact semantics of player_control_flag source at spawn (player_record +0x01 / eliminated flag — may be repurposed per context)