Editing
Textdata event.txt
From Raynegard Wiki
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
'''<code>event.txt</code>''' (268,065 bytes, part of [[BIN textdata]]) is the largest textdata file: a time-scheduled world-event / object-scripting table. Each row schedules a scripted action (object state change, sound, lighting, scene transition) on a specific world object / map-area node / zone at a specific in-game calendar time. '''Important:''' in this build the client's time-driven dispatch of these rows is permanently gated off (see [[#Dispatch gating|Dispatch gating]] below) β the rows are meant to be '''server-driven'''. The server should walk this schedule and emit <code>0xC062</code> effect packets at the scheduled ticks. == Loader / parser (Ghidra) == {| class="wikitable" ! Function !! Addr !! Role |- | <code>Struct_Setup_Effect_Manager</code> || <code>00498546</code> || opens <code>event.txt</code>, parses every row, builds the trees |- | <code>Archive_OpenTextFileByName</code> || <code>004bc800</code> || opens the file from <code>g_NewArchive2</code> |- | <code>TextAsset_ReadNextLine</code> || β || row iterator |- | <code>TickKey_InitFromCoords</code> β <code>TickKey_ComputeAndDecompose</code> || <code>004b50c0</code> / <code>004b5250</code> || converts cols 2β6 (calendar) β absolute tick key |- | <code>EffectDef_AppendKeyframe</code> || β || stores the row payload as a keyframe on the effect def |} Parse loop (paraphrased): <pre> while (TextAsset_ReadNextLine(&buf, line)) { if (line[0] == '#') continue; // '#' = comment line if (sscanf(line, "%d,%d,...,%d", &c1..&c16) != 16) // exactly 16 ints continue; // malformed -> skip if (c12 < 10000) c12 -= 1; // sprite id -> 0-based for <10000 key = TickKey(c2,c3,c4,c5,c6); // week,day,hour,min,sec -> tick tree = (c1 == 0) ? ground_effect_tree : air_effect_tree; ... insert effect def at key into tree, append keyframe(c7..c16) ... } </pre> Format string <code>"%d,%d,β¦,%d"</code> (16 fields) @ <code>004e4dd4</code>. Lines beginning with <code>#</code> are comments; any line that doesn't scan to exactly 16 ints is skipped. == Column layout (16 comma-separated ints) == {| class="wikitable" ! # !! Name !! Meaning |- | 1 || layer / kind || <code>0</code> β ground tree, <code>β 0</code> β air tree. In practice always β₯ 1 (no row is 0), so every row goes to the air tree β the gated-off path. |- | 2 || week || in-game week (1-based). <code>99</code> = recurring/any week β selects a separate keyframe layout. |- | 3 || day || in-game day (1-based). |- | 4 || hour || 0β23. |- | 5 || minute || 0β59. |- | 6 || second || 0β59. |- | 7 || aux param A || effect payload; only used when week β 99 (one-shot events). |- | 8 || aux param B || effect payload. |- | 9 || keyframe_count || <code>Effect_Def.keyframe_count</code> (struct off 40). |- | 10 || keyframe_start || <code>Effect_Def.keyframe_start</code> (struct off 44). |- | 11 || keyframe_end || <code>Effect_Def.keyframe_end</code> (struct off 48). |- | 12 || target id || object/node/zone the action runs on: <code>< 10000</code> β world object; <code>>= 10001</code> β map-area node = <code>world.wlist</code> record <code>id β 10001</code>; <code>11190</code> β zone. If <code>< 10000</code> it's decremented to a 0-based index. (struct off 56) |- | 13 || mode / action || which <code>Event_Dispatch</code> action runs (state change / sound / lighting+transition). Values 0, 1, 3 get special count handling (col 14). (struct off 60) |- | 14 || count / repeat || if <code>modeβ{1,3}</code> and <code>β 99</code> β <code>β1</code>; if <code>mode==0</code> and <code>==0</code> β <code>β1</code>. <code>99</code> kept as "infinite/any". (struct off 64) |- | 15 || aux param C || action payload (e.g. sound id / state value). (struct off 68) |- | 16 || aux param D || action payload. (struct off 52) |} Cols 9/10/11/13/14 map to named <code>Effect_Def</code> fields and col 12 is the dispatch target id. Cols 7/8/15/16 land in currently-unnamed <code>Effect_Def</code> offsets (32/36/52/68) and carry the per-action payload β treat these column-to-payload bindings as provisional. == The calendar / tick key (cols 2β6) == <code>TickKey_ComputeAndDecompose @ 004b5250</code> converts <code>(week, day, hour, minute, second)</code> into an absolute tick. Calendar is 7-day weeks, 24-hour days; week/day are 1-indexed, hour/minute/second are 0-indexed: <pre> day_index = (week - 1) * 7 + day // stored at Effect_Def off 8 (tick_raw) tick = (day_index - 1) * 86400 + hour * 3600 + minute * 60 + second // stored at Effect_Def off 4 (tick_value) </pre> A negative <code>tick</code> marks the entry invalid. <code>week == 99</code> is the wildcard for recurring effects. Full derived tick constants: 1 week base, 1 day base, 7 days/week, 24 hours/day, 60 min/hour, 60 sec/min (all read from <code>rg.exe</code> <code>.data</code>). == Example rows == <pre> 1,1,1,22,0,0,0,0,0,0,0,11308,1,44,0,1 1,1,1,22,0,0,0,0,0,0,0,11425,1,99,0,1 </pre> Row 1: week 1 / day 1 / '''22:00:00''', target id '''11308''', mode 1, count 44. Row 2: same time, target 11425, count '''99''' (kept = recurring/infinite). == What a fired row does (<code>Event_Dispatch @ 00497ae0</code>) == When a row's tick arrives it is not rendered as a free particle. <code>Event_Dispatch</code> looks up a target by id and runs a scripted action on it: * id <code>< 10000</code> β <code>GameWorld_GetObject</code> (a <code>World_Zone_Entry</code>); id <code>>= 10001</code> β <code>GameWorld_GetWorldNode(id - 10001)</code> (a <code>World_Node</code>); sentinel <code>11190</code> β <code>GameWorld_GetZone(...)</code>. * action type (col 13) switches between: change the target's state slots, load a sound (<code>SoundManager_Load_Single_SSF</code> / <code>TryLoad_SoundEffect</code>), or set lighting + trigger a scene transition (<code>Lighting_SetInstant</code> β <code>GameState_Transition(0xf)</code>). * it only acts if the player is in the target's area, gated by <code>target->Vtable[5](player_x, player_y, player_z, active_area)</code>. '''The <code>>= 10001</code> target is a map-area NODE, not a character NPC.''' <code>GameWorld_GetWorldNode</code> returns <code>g_pGameWorld->node_array[id - 10001]</code> β a <code>World_Node</code> carrying that area's interaction_type, sound_index, and per-node BGM/SE/effect arrays. The index maps 1:1 to <code>world.wlist</code> record order (1,471 area records, id range 10001β11471). Verified: node 0 (id 10001) = <code>field</code> (overworld), node 1307 (id 11308) = <code>1ta16</code>, node 1124 (id 11425) = <code>ir_b2p06</code>. So <code>event.txt</code> wires scheduled night-time ambiance (sounds/effects/BGM) to specific map areas, never to characters. The <code>/effect 1 0</code> console command (0xC062, channel 1) reaches this same machinery directly (<code>EffectManager_ScheduleKeyframesForObject</code>). == Dispatch gating β why the client never self-fires these == The per-frame dispatcher <code>EffectManager_TickAndDispatchEffects @ 00498da0</code> is called from <code>GameStateMachine_Update @ 004a4180</code> and processes two trees: * <code>ground_effect_tree</code> (col1 == 0) β dispatched unconditionally, but empty: of 6,590 rows, none have col1 == 0. * <code>air_effect_tree</code> (col1 != 0) β holds every row, dispatched only inside <code>if (g_NetworkGlobal->field4_0x8 == 0)</code>. <code>field4_0x8</code> is written exactly once β in <code>Struct_Setup_Net0x98_0x1C @ 004b7010</code>, and its only caller passes a literal <code>1</code>. No state, command, or packet ever clears it. So the air path is permanently off, and the client's time-driven <code>event.txt</code> dispatch never runs in normal play. Two further gates apply even if that flag were 0: the dispatcher only runs on a minute boundary (<code>if (nSecond == 0)</code>), and <code>Event_Dispatch</code> only acts when <code>g_EffectSystem_Initialized == 0</code> (armed on world-entry). == Server relevance == Because client self-dispatch is fused off, <code>event.txt</code> is effectively the '''server's schedule'''. To reproduce original behavior the server should: # Drive an in-game clock (week/day/hour/min/sec β tick) using the calendar constants above. # At each row's tick, send the matching <code>0xC062</code> effect packet to clients in the target's area (col 12 resolves to a map area via <code>world.wlist</code>, <code>id β 10001</code>, so the broadcast can be filtered to players actually in that area). The clock bases must match the client's (set via <code>0xC05C</code> "/timeconfig" + <code>0xC05D</code> "/time") so server schedule and client clock stay in sync. == Open items == * Trace the keyframeβtask copy to pin the exact column β <code>Event_Dispatch param_1[0..3]</code> mapping, and name <code>Effect_Def</code> offsets 32/36/52/68. * Map <code>mode</code> (col 13) values to the concrete <code>Event_Dispatch</code> action types (0β4). * Cross-check target ids (col 12, <code>11xxx</code>) against <code>world.wlist</code> area codes to label which area each event scripts. == See also == * [[BIN textdata]] * [[textdata bgmtable.txt]], [[textdata tenkoutable.txt]], [[textdata tensoutable.txt]] β the related time-windowed per-area tables
Summary:
Please note that all contributions to Raynegard Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Raynegard Wiki:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Navigation menu
Page actions
Page
Discussion
Read
Edit
History
Page actions
Page
Discussion
More
Tools
Personal tools
Not logged in
Talk
Contributions
Create account
Log in
Navigation
Main page
Reddit Community
Discord Server
Recent changes
Random page
Help about MediaWiki
Special pages
Search
Tools
What links here
Related changes
Page information