Like the S3Engine I'm using LUA, however there were some evil hacks that I had to do in order to get it to work like I wanted to; this time around however I managed to fix a few.
Co-Routines is the main reason I like LUA, though it's speed and simplicity is nice too. When a new game state is created a new LUA state is made, when when a script is to be run (that is, a function in a given script file) a new co-routine (virtual thread) is created, the code is loaded into this new state, and the function is called.
The Environment Table:
One of the more annoying aspects of LUA is that pretty much everything by default is global. Which means whenever you load code up, it becomes part of the Environment Table, and hangs around indefinably. Normally this would not be a bad thing, however in the case of "Call Function F in Script cool.script", we normally like some feedback on if the function exists, because if it doesn't sometimes 'default' actions should be performed.
However, if you have scriptA and scriptB, scriptA defines a function func(), if you first call func() on scriptA everything is fine, but if you ask for func() on scriptB (which does not define func()), func() will still be left in the environment from the previous loading of scriptA; in short, not good.
To make things worse, at some point we need to serialize the data in this globals table, all the global variables and whatnot. Walking the table to do this is easy enough, except for the fact that by default the environment table has a TON of 'other stuff' just hanging around in it as global variables and functions, things which don't belong in our saved states.
Now LUA has ways (which aren't very clear or easy to do), to replace the environment table with one of our own making. So after a lot of fuding around I managed to replace the environment table with a new empty one, now at least the 'other stuff' was gone, BUT there was still a big issue, the previous table we were no longer using still had lots of important 'stuff' in it, so there is a way to define a 'meta-table' for a table, this meta-table allows you to define certain functionality for operations performed on a table. To make a long story shorter, in our new table we defined a meta-table that would direct a request for a key to the original table, this is done by setting the original table as the value of the meta-table's __index property. Now everything works properly and we have a generally clean environment that we can save freely.
Unfortunetly this does nothing to stop the scriptA and scriptB scenario, my current solution is to 'scrub' the environment table before every call to clean out any previous functions, not elegant but it works. Chances are i'm abusing LUA somehow, but it seems the only way to get my per-script events working the way I want. I've also got some more ideas to make it all work elegantly but at the moment working is better than elegant, so it'll do.