170 lines
5.6 KiB
Markdown
170 lines
5.6 KiB
Markdown
|
|
# Entity Class Family Split
|
||
|
|
|
||
|
|
## Purpose
|
||
|
|
|
||
|
|
This note breaks the large seg001 `Entity` lane into a conservative class-family model that can later be promoted in Ghidra or emitted as C++ without pretending that every vtable and helper belongs to one monolithic base class.
|
||
|
|
|
||
|
|
Current goal is not full inheritance recovery. Current goal is to identify the safest boundaries between:
|
||
|
|
|
||
|
|
- one shared gameplay-entity core layout
|
||
|
|
- projectile-specific allocation and movement behavior
|
||
|
|
- debris/corpse variants
|
||
|
|
- registry/helper surfaces that look adjacent but should not be merged automatically
|
||
|
|
|
||
|
|
## Core Shared Entity Object
|
||
|
|
|
||
|
|
Strongest current common object is the gameplay entity body documented in [docs/ne-segment1.md](docs/ne-segment1.md).
|
||
|
|
|
||
|
|
Stable shared anchors:
|
||
|
|
|
||
|
|
- `0007:3f2f entity_spawn`
|
||
|
|
- `0007:40d4 entity_remove`
|
||
|
|
- `0007:4552 entity_set_position`
|
||
|
|
- `0007:4591 entity_try_place`
|
||
|
|
- `0007:5092 entity_deactivate`
|
||
|
|
|
||
|
|
Stable shared fields from the current note set include:
|
||
|
|
|
||
|
|
- `+0x00` vtable pointer
|
||
|
|
- `+0x02` slot index
|
||
|
|
- `+0x04` entity type
|
||
|
|
- `+0x19/+0x1a` flags
|
||
|
|
- `+0x3c` sprite handle
|
||
|
|
- `+0x45/+0x47/+0x49` world position
|
||
|
|
- `+0x4f/+0x51/+0x53` base position
|
||
|
|
- `+0x54/+0x56/+0x58` previous position
|
||
|
|
|
||
|
|
This is the safest current candidate for a future `Entity` or `ActorBase` style root.
|
||
|
|
|
||
|
|
## Candidate Split
|
||
|
|
|
||
|
|
### 1. `Entity` base gameplay family
|
||
|
|
|
||
|
|
Best current scope:
|
||
|
|
|
||
|
|
- allocation/spawn and placement
|
||
|
|
- common position, flags, facing, and sprite ownership
|
||
|
|
- generic remove/deactivate behavior
|
||
|
|
- registry-facing slot identity
|
||
|
|
|
||
|
|
Best current vtable anchor:
|
||
|
|
|
||
|
|
- generic/AI entity vtable `0x29aa`
|
||
|
|
|
||
|
|
Current caution:
|
||
|
|
|
||
|
|
- this family likely includes several behaviorally different actors, but the verified note set still supports one shared base before the split gets more specific.
|
||
|
|
|
||
|
|
### 2. `ShotEntity` or projectile-derived family
|
||
|
|
|
||
|
|
Strong anchors:
|
||
|
|
|
||
|
|
- `0007:28ce shot_entity_alloc`
|
||
|
|
- `0007:44a9 shot_entity_free`
|
||
|
|
- `0007:4659 projectile_init_vector`
|
||
|
|
- `0007:4b78 projectile_check_hit`
|
||
|
|
- `0007:4c2e projectile_step_update`
|
||
|
|
- `0007:4d28 projectile_trace_ray`
|
||
|
|
- `0007:51ad projectile_update_tick`
|
||
|
|
- `0007:5a99 projectile_apply_hit`
|
||
|
|
|
||
|
|
Best current distinct evidence:
|
||
|
|
|
||
|
|
- dedicated vtable `0x297e`
|
||
|
|
- extra projectile ownership/target fields through `+0x6a..+0xbd`
|
||
|
|
- separate shot sprite handle at `+0x3f`
|
||
|
|
- dedicated cleanup path in `shot_entity_free`
|
||
|
|
|
||
|
|
Current safest interpretation:
|
||
|
|
|
||
|
|
- projectile objects are not just one mode of the generic entity vtable; they deserve at least one derived-family model with their own ctor/free/update surface.
|
||
|
|
|
||
|
|
### 3. `DebrisEntity` family
|
||
|
|
|
||
|
|
Strong anchors:
|
||
|
|
|
||
|
|
- `0007:7490 debris_spawn`
|
||
|
|
- `0007:75ff entity_die`
|
||
|
|
|
||
|
|
Best current distinct evidence:
|
||
|
|
|
||
|
|
- dedicated debris/fragment vtable `0x2a57`
|
||
|
|
- corpse/debris-adjacent vtable pair `0x2a1a` and `0x2a33`
|
||
|
|
- death-spawn path uses separate velocity/facing behavior rather than only the generic entity update lane
|
||
|
|
|
||
|
|
Current safest interpretation:
|
||
|
|
|
||
|
|
- debris should stay separate from `ShotEntity`; both share movement-style fields but not the same lifecycle intent.
|
||
|
|
|
||
|
|
### 4. `CorpseEntity` or actor-remnant family
|
||
|
|
|
||
|
|
Strong current evidence:
|
||
|
|
|
||
|
|
- vtable pair `0x2a1a` and `0x2a33`
|
||
|
|
- adjacency to `entity_die` and debris-spawn behavior
|
||
|
|
|
||
|
|
Current caution:
|
||
|
|
|
||
|
|
- the notes support a corpse/remnant family, but not yet a crisp split between static remains, actor corpse, and debris fragments.
|
||
|
|
- keep this as a provisional derived branch until a dedicated caller pass closes object lifetime more tightly.
|
||
|
|
|
||
|
|
### 5. Adjacent but probably separate: dialog/menu object lane
|
||
|
|
|
||
|
|
Anchor:
|
||
|
|
|
||
|
|
- `0007:2c92 dialog_spawn`
|
||
|
|
|
||
|
|
Why it should stay separate:
|
||
|
|
|
||
|
|
- vtable `0x28b5`
|
||
|
|
- callback registration at `0x39ca`
|
||
|
|
- behavior is UI/dialog-style rather than ordinary gameplay entity movement or projectile logic
|
||
|
|
|
||
|
|
Current safest interpretation:
|
||
|
|
|
||
|
|
- this object is near the entity notes because it lives in the same broad segment lane, but it should not be promoted under the core gameplay `Entity` family automatically.
|
||
|
|
|
||
|
|
## Registry And Helper Surfaces That Should Not Be Mis-modeled
|
||
|
|
|
||
|
|
### Entity registry vtable `0x2969`
|
||
|
|
|
||
|
|
Current evidence in [docs/ne-segment1.md](docs/ne-segment1.md) shows `0x2969` stored at `0x39ca + slot*4` as a registry vtable rather than as the entity instance's primary vtable.
|
||
|
|
|
||
|
|
That means:
|
||
|
|
|
||
|
|
- do not treat `0x2969` as a normal `Entity` virtual table
|
||
|
|
- keep registry or handle-table behavior separate from per-instance inheritance
|
||
|
|
|
||
|
|
### Pure helpers that should remain free functions for now
|
||
|
|
|
||
|
|
Examples:
|
||
|
|
|
||
|
|
- `snap_entity_to_ground`
|
||
|
|
- `spawn_entity_checked`
|
||
|
|
- `map_find_spawn_point`
|
||
|
|
- `actor_find_in_view`
|
||
|
|
|
||
|
|
These may operate on entities or produce entities, but current evidence still reads better as subsystem helpers than as obvious instance methods.
|
||
|
|
|
||
|
|
## Recommended Promotion Order
|
||
|
|
|
||
|
|
1. model the shared `Entity` base layout first
|
||
|
|
2. split `ShotEntity` next because its ctor/free/update lane is strongest
|
||
|
|
3. split debris/corpse branches only after one more caller-side lifetime pass
|
||
|
|
4. leave dialog/menu object modeling separate from the entity inheritance tree
|
||
|
|
|
||
|
|
## Source-Emission Guidance
|
||
|
|
|
||
|
|
If this family is emitted to provisional C++ later, safest first skeleton is:
|
||
|
|
|
||
|
|
- one `Entity` base struct/class with the stable common layout
|
||
|
|
- one `ShotEntity` derived placeholder
|
||
|
|
- one `DebrisEntity` derived placeholder
|
||
|
|
- one unresolved `CorpseLikeEntity` placeholder if needed
|
||
|
|
- separate `DialogMenuObject` class rather than folding it into the gameplay entity tree
|
||
|
|
|
||
|
|
## Bottom Line
|
||
|
|
|
||
|
|
The current evidence strongly supports a shared gameplay entity core, but it does not support flattening generic actor, projectile, debris, corpse, and dialog/menu behavior into one class.
|
||
|
|
|
||
|
|
The right near-term move is `base first, derived families second, adjacent objects separate`.
|