Textdata enkeifile.txt
enkeifile.txt (20,824 bytes, part of BIN textdata) is the world zone geometry file. Despite the name (enkei 遠景 = "distant view/scenery"), this is zone/area definition data, not scenery placement.
Format
[edit]Line 1 = zone count (256). Each row: sscanf("%d,%lf,%lf,%lf,%s"):
| # | Type | Meaning |
|---|---|---|
| 1 | int | zoneId (1-based; stored −1 internally)
|
| 2 | double | circle center X |
| 3 | double | circle center Z |
| 4 | double | circle radius |
| 5 | string | zone name (CP949; set once, from the zone's first row) |
The first row of each zoneId creates the World_Zone_Entry (0x460 bytes) with its name; every row adds one circle (x, z, radius) to that zone. A point is "inside" the zone if it lies within any of the zone's circles — so a zone = union of up to 30 circles, plus a name. Blank lines are skipped.
Loading (Ghidra)
[edit]String address 004e4f54. Struct_Setup_GameWorld_struct @ 0049eb23 → Load_Enkeifile_File @ 0049edd0 builds the 256-entry g_pGameWorld->zone_array.
- The point array lives at struct offset 304 (Ghidra mislabels this
inner_event_queue/inner_event_count) — really a ≤30-entry circle list, 24 bytes each (3 doubles). - Containment test:
Object_ContainsPoint @ 0049dfa0— AABB-tests then loops the circles viaObject_IsWithinRadius_w_Bearing. - After zones are built, the loader also allocates
node_array(count fromgWorldData_Get_World_Count).
This zone_array is the target that every effect/interaction table (see the time-windowed world tables and textdata event.txt) resolves ids < 10000 against, and that Character_ScanNearbyObjects tests the player against.