Four switches that run Lua as the client starts:
-gluescript <code> run at the glue screens
-gluescriptFile <path> the file's contents, run at the glue screens
-gamescript <code> run once in-game
-gamescriptFile <path> the file's contents, run once in-game
None of these exist in 1.12. The strings appear nowhere in the binary, so
there is nothing to parse them and nothing to un-gate -- the feature is
ours end to end.
Registration time is too early for either state. The in-game module
callback runs from FUN_LOAD_SCRIPT_FUNCTIONS, before FrameXML loads, and
the glue callback runs from FUN_LOAD_GLUE_SCRIPT_FUNCTIONS, before
GlueXML does. A script running there could not touch a frame, call a
FrameXML function or see an addon, which is most of what one would be
written for. So each is armed at registration and run from a tick, where
the UI is demonstrably up. Glue uses FrameTick, whose hook is the UI
render root and so fires at the login and character-select screens; it is
re-armed by the glue module callback on every glue boot, so a script that
logs in automatically still works after a logout. Game uses WorldTick,
which is world-only, so its first tick is past FrameXML, past the addon
load pass and past enter-world init; it latches for the life of the
process, since "run once in-game" says once.
FUN_LUA_RUN_STRING resolves the Lua state itself rather than taking one,
so a single call site reaches whichever state is current and the two
paths differ only in when they fire. It installs the FrameScript error
handler as the pcall's errfunc, so a faulty script reports itself the way
any script error does instead of failing silently, and because every
chunk goes through the shared compile chokepoint these scripts get the
same 5.1 syntax support the rest of the client's Lua has.
A *File is read with Win32 rather than the engine's file layer. The
engine resolves relative paths against a loose-file index built once at
boot, so it cannot see a file created afterwards and cannot open an
absolute path at all -- and an absolute path is what goes in a shortcut.
Reading it directly also lets both switches share one execution path, so
inline code and file contents cannot diverge.
The switch parser moves to Config::CommandLine, shared with -config
rather than copied: the quoting and token-boundary rules are exactly
where a second copy would drift unnoticed. Lifting it also fixed a latent
overread, where a switch name at the very end of the command line was
compared past its terminator.
Verified in-game on Turtle: inline and file forms in both states; the
in-game script silent across /reload and a second login while the glue
script re-ran on returning to character select; a syntax error and a
missing file each reported without a crash; and -config still applying
through the shared parser.