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// wasDAT_00583140@ 0x00583140 (retail); GoGDAT_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#
- Allocate —
lotr2_combat_alloc_group_slot(player_id, player_control_flag)finds first empty slot, clears it, writes +0x00 and +0x01. - Spawn link — each spawned figure stores the group index;
member_countincrements. - Sync —
lotr2_combat_sync_group_slot_countersrebuilds counts, busy flags, and target-lock state each battle frame before figure tick. - Clear —
lotr2_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_flagsource at spawn (player_record +0x01/ eliminated flag — may be repurposed per context)