5.6 KiB
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.
Stable shared anchors:
0007:3f2f entity_spawn0007:40d4 entity_remove0007:4552 entity_set_position0007:4591 entity_try_place0007:5092 entity_deactivate
Stable shared fields from the current note set include:
+0x00vtable pointer+0x02slot index+0x04entity type+0x19/+0x1aflags+0x3csprite handle+0x45/+0x47/+0x49world position+0x4f/+0x51/+0x53base position+0x54/+0x56/+0x58previous 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_alloc0007:44a9 shot_entity_free0007:4659 projectile_init_vector0007:4b78 projectile_check_hit0007:4c2e projectile_step_update0007:4d28 projectile_trace_ray0007:51ad projectile_update_tick0007: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_spawn0007:75ff entity_die
Best current distinct evidence:
- dedicated debris/fragment vtable
0x2a57 - corpse/debris-adjacent vtable pair
0x2a1aand0x2a33 - 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
0x2a1aand0x2a33 - adjacency to
entity_dieand 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
Entityfamily automatically.
Registry And Helper Surfaces That Should Not Be Mis-modeled
Entity registry vtable 0x2969
Current evidence in 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
0x2969as a normalEntityvirtual 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_groundspawn_entity_checkedmap_find_spawn_pointactor_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
- model the shared
Entitybase layout first - split
ShotEntitynext because its ctor/free/update lane is strongest - split debris/corpse branches only after one more caller-side lifetime pass
- 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
Entitybase struct/class with the stable common layout - one
ShotEntityderived placeholder - one
DebrisEntityderived placeholder - one unresolved
CorpseLikeEntityplaceholder if needed - separate
DialogMenuObjectclass 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.