wormz-a / docs /re-notes /task-hierarchy.md
paavohtl's picture
Claude Opus 4.6 (1M context)
refactor: rename CTaskFireBall β†’ CTaskGirder
35a783f
|
Raw History Blame Contribute Delete
6.63 kB
# Task Hierarchy - Worms Armageddon 3.8.1
## Overview
WA uses a hierarchical task/entity system. All game objects inherit from `CTask`,
which forms a tree via parent/children pointers. Tasks communicate through a
message passing system (see `TaskMessage` enum).
## Class Hierarchy
```
CTask (base) vtable: 0x669F8C ctor: 0x5625A0
β”œβ”€β”€ CGameTask vtable: 0x6641F8 ctor: 0x4FED50
β”‚ β”œβ”€β”€ CTaskWorm ctor: 0x50BFB0
β”‚ β”œβ”€β”€ CTaskOldWorm ctor: 0x51FEB0
β”‚ β”œβ”€β”€ CTaskMissile ctor: 0x507D10
β”‚ β”œβ”€β”€ CTaskArrow ctor: 0x4FE130
β”‚ β”œβ”€β”€ CTaskMine ctor: 0x506660
β”‚ β”œβ”€β”€ CTaskCanister ctor: 0x501A80
β”‚ β”œβ”€β”€ CTaskCrate ctor: 0x502490
β”‚ β”œβ”€β”€ CTaskOilDrum ctor: 0x504AF0
β”‚ β”œβ”€β”€ CTaskCross ctor: 0x5045C0
β”‚ └── CTaskLand ctor: 0x505440
β”œβ”€β”€ CTaskFilter ctor: 0x54F3D0
β”œβ”€β”€ CTaskTeam ctor: 0x555BB0
β”œβ”€β”€ CTaskTurnGame ctor: 0x55B280
β”œβ”€β”€ CTaskAirStrike ctor: 0x5553C0
β”œβ”€β”€ CTaskDirt ctor: 0x54EDC0
β”œβ”€β”€ CTaskFlame ctor: 0x54F0F0
β”œβ”€β”€ CTaskFire ctor: 0x54F4C0
β”œβ”€β”€ CTaskGirder (was CTaskFireBall) ctor: 0x550890
β”œβ”€β”€ CTaskGas ctor: 0x554750
β”œβ”€β”€ CTaskSmoke ctor: 0x5551D0
β”œβ”€β”€ CTaskCloud ctor: 0x5482E0
β”œβ”€β”€ CTaskSeaBubble ctor: 0x554FE0
β”œβ”€β”€ CTaskScoreBubble ctor: 0x554CA0
β”œβ”€β”€ CTaskCPU ctor: 0x5485D0
└── CTaskSpriteAnimation ctor: 0x5466C0
```
Note: Not all tasks are confirmed to inherit from CGameTask. The hierarchy
above needs further verification via Ghidra analysis of each constructor.
## CTask vtable (0x669F8C)
| Index | Offset | Address | Name (from wkJellyWorm) |
|-------|--------|------------|-------------------------|
| 0 | 0x00 | 0x562710 | vtable0 (init?) |
| 1 | 0x04 | 0x562620 | Free |
| 2 | 0x08 | 0x562F30 | HandleMessage |
| 3 | 0x0C | 0x5613D0 | unknown |
| 4 | 0x10 | 0x5613D0 | unknown (=vt3) |
| 5 | 0x14 | 0x562FA0 | unknown |
| 6 | 0x18 | 0x563000 | unknown |
| 7 | 0x1C | 0x563210 | ProcessFrame |
Note: wkJellyWorm says 7 methods but we see 8 entries. The 8th may be
the start of CGameTask's extended vtable region, or the count was off by one.
## CGameTask vtable (0x6641F8)
First 3 entries override CTask:
| Index | Offset | Address | Name |
|-------|--------|------------|-------------------------|
| 0 | 0x00 | 0x4FF1C0 | vtable0 override |
| 1 | 0x04 | 0x4FEF10 | Free override |
| 2 | 0x08 | 0x4FF280 | HandleMessage override |
| 3 | 0x0C | 0x5613D0 | (inherited from CTask) |
| 4 | 0x10 | 0x5613D0 | (inherited from CTask) |
| 5 | 0x14 | 0x562FA0 | (inherited from CTask) |
| 6 | 0x18 | 0x563000 | (inherited from CTask) |
| 7 | 0x1C | 0x4FF720 | CGameTask-specific |
| 8 | 0x20 | 0x4FFED0 | CGameTask-specific |
| 9 | 0x24 | 0x500070 | CGameTask-specific |
| 10 | 0x28 | 0x500080 | CGameTask-specific |
| 11 | 0x2C | 0x5000E0 | CGameTask-specific |
| 12 | 0x30 | 0x500380 | CGameTask-specific |
| 13 | 0x34 | 0x500360 | CGameTask-specific |
| 14 | 0x38 | 0x4FE060 | CGameTask-specific |
| 15 | 0x3C | 0x500CC0 | CGameTask-specific |
| 16 | 0x40 | 0x592A50 | CGameTask-specific |
| 17 | 0x44 | 0x500090 | CGameTask-specific |
| 18 | 0x48 | 0x545780 | CGameTask-specific |
| 19 | 0x4C | 0x4AA060 | CGameTask-specific |
CGameTask also has a secondary vtable at object offset 0xE8, pointing to 0x669CF8.
## CTask memory layout (0x30 bytes)
```
Offset Size Field
0x00 4 vtable pointer
0x04 4 parent (CTask*)
0x08 4 unknown (set to 0x10 in ctor)
0x0C 4 children.max_size (init 0)
0x10 4 children.unk4 (init 0)
0x14 4 children.size
0x18 4 children.data_ptr (allocated 0x60 bytes, zeroed 0x40)
0x1C 4 children.hash_list
0x20 4 class_type (ClassType enum)
0x24 12 unknown padding
```
## CGameTask memory layout (0xEC bytes)
Extends CTask at offset 0x00. Key fields discovered from constructor:
```
Offset Size Field
0x00 0x30 CTask base
0x20 4 class_type (set to 3 = GameCollisionTask in ctor)
0x2C 4 param_3 from ctor
0x30 4 param_3 (weapon id?)
0x38 4 param_4
0x3C 4 unknown
...
0x4C 4 = 0x10000 (Fixed 1.0)
0x50 4 = 0x100000 (Fixed 16.0)
0x54 4 = 0xCCCC (Fixed ~0.8)
0x58 4 = 0x10000 (Fixed 1.0)
0x5C 4 = 0
0x60 4 = 0x10000 (Fixed 1.0)
0x64 4 = 0x20000 (Fixed 2.0)
0x68 4 = 0xF333 (Fixed ~0.95)
...
0x84 4 pos_x (Fixed)
0x88 4 pos_y (Fixed)
0x8C 4 = 0x10000 (Fixed 1.0, scale?)
0x90 4 speed_x (Fixed)
0x94 4 speed_y (Fixed)
...
0xCC 4 = 0x10000 (Fixed 1.0)
0xD8 1 byte flag (init 0)
0xD9 1 byte flag (init 0)
0xE0 4 unknown (init 0)
0xE4 4 unknown (init 0)
0xDC 4 unknown (init 0)
0xE8 4 secondary vtable pointer -> 0x669CF8
```
## Physics defaults from CGameTask constructor
Several fixed-point constants are set in the constructor, likely physics defaults:
- `0x10000` = 1.0 (appears at many offsets β€” scale factors, gravity?)
- `0x100000` = 16.0 (mass? terminal velocity?)
- `0xCCCC` β‰ˆ 0.8 (friction? damping?)
- `0x20000` = 2.0
- `0xF333` β‰ˆ 0.95 (air resistance?)
- `0x3333` β‰ˆ 0.2
- `0x4CCC` β‰ˆ 0.3
- `0xFEB8` β‰ˆ 0.995
- `0x9999` β‰ˆ 0.6
- `0x3AE1` β‰ˆ 0.23
- `0xFC000000` = -67108864 (large negative, possibly a boundary?)