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?)