This is a complex question and there are a million ways to handle events. We are doing it via messages sent from the script class via a C structure to a message router class which then sends the message to ScriptMsgProc in either the engine or the object manager class based on the numeric range the message ID falls into.
ScriptMsgProc then attempts to find a handler in a vector of handlers. Once it determines a handler does exist, it calls OnScriptMsg to then convert the handler from void (void) to the correct return type and param list for the function. Each type of handler function has a function signature that is stored in an enum. The function prototypes are stored in a union and we use the enum with the union to arrive at the final function prototype. If the message does not have a handler we then call the base class Default() which will attempt to handle the message, but we also flag an error condition stating that a message was sent from the script to an object that did not have a handler for the message. If Default() cannot perform the script command to script handler function resolution then an error message is returned to the script indicating the message was not handled.
To respond to script messages you simply use DECLARE_SCRIPT_MSGMAP() in the class declaration. The class must be derived from CBaseObject in order to work correctly. Then in the implementation file you do this:
The actual internal workings of CBaseObject and ScriptCmn.h are quite complex but that is the jist of it. We did not invent this system but modified the message system that MFC employs.
} else return false;
UINT CThisObject::GoToWaypoint(UINT nWPListID)
//Resolve id to list ptr
if (!pList) return WAYPOINTS_NO_EXIST;