events.res - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
For the sake of extensibility and legibility, events are not hard-coded into the compiler, but rather are stored in an external file in the main directory, events.res. The file's original format spec appears below.
To promote a more extensible, less hard-coded-strings-flipping-everywhere event system, ENIGMA R4 introduced a file containing event names and info, in order of execution.
Because of the way Game Maker stores events, names need paired up with integer IDs and sometimes Sub-IDs. Because of the way ENIGMA stores event code, IDs and sub-IDs need paired up with function names. This format deals with all of that.
The basic layout of the format is
event_function_name: ID
Mode: MODE DESCRIPTOR
MODE-SPECIFIER: SPECIFIER
Super Check: EXPRESSION
Sub Check: EXPRESSION
In the above, ID is an integer, defined in Game Maker from 0-11 but open to extension. This is how the event will be identified by the IDE, and by ENIGMA initially.
Mode: Sets how the event is represented for iteration in ENIGMA. Behavior is assigned according to MODE DESCRIPTOR.
MODE DESCRIPTOR can be one of the following non-numeric constants:
Mode |
Description |
---|---|
Inline |
The event is added right into the list of events to be iterated. This is mostly for
|
Stacked |
The event appears once in the event list, and instances are expected to register
|
Special |
The event is given entirely different behavior based on the value of the second ID.
|
Spec-none |
This is for specialized events (by second ID) that don't get added to the event list at all. |
None |
This is for whole events that don't get added to the event list at all. |
MODE-SPECIFIER is a named attribute specific to Mode. Depending on the value of mode, certain attributes may be required:
Mode | Parameter |
---|---|
Inline | Nothing needs to be given. |
Stacked | The derived function names need to be given. |
Special | A Case: attribute needs given, coupled with the second ID integer as SPECIFIER. |
Spec-none | Same as special. |
None | Nothing needs to be given. |
This format allows setting additional code attributes for the event, such as checks and default code snippets.
Attribute | Description |
---|---|
Super Check | Specifies an EXPRESSION to be used to determine whether the event as a whole should be iterated (It is iterated if the expression is true). For example, if the event is Keyboard A , the list shouldn't be iterated at all if the 'A' key isn't held. Such conditions are given in the format defined by EXPRESSION. |
Sub Check | Similar to super check, but executed by each instance each event and is therefore simply added to the beginning of each event code. Its conditions are also given in EXPRESSION format. The event is performed if EXPRESSION is true. |
Default | Gives code that is used in place of user code for an event if none is specified. For instance, in GM, the draw event defaults to rendering the sprite of the current instance if no draw code is given. |
Constant | Gives code that is always present at the beginning of the event, whether the user has specified code or not. In GM, the step event always propagates movement variables at the beginning. |
Prefix | Specifies code to be prepended to user code, if any user code was specified. Otherwise, the code given here is ignored. Constant code is prepended in either case. |
Suffix | Specifies code to be appended to user code, if any user code was specified. If the event returns before this code is reached, it will not be executed. This was added as a complement to prefix without a premeditated use case. |
Instead | Code given here is used in place of the traditional event loop. This code is not inserted into any event, but instead into the code that handles event sequences. For example, the draw event specifies screen_redraw() instead of iterating manually (to allow for depth and views to be accounted for). |
This format is more complicated than it may originally sound. Its behavior is based on the first non-white character in the string. If followed by a block, {}, EXPRESSION is copied as-is and is assumed to contain valid return statement(s). In the case of Super Check, the EXPRESSION should always return true or false. In the case of Sub Check, the event is performed if nothing is returned; no return statement is reached.
Otherwise (if EXPRESSION is not given as a {block}), an if statement is generated by simply parenthesizing the EXPRESSION.
In the case of Sub Event, the EXPRESSION is negated as well. This is because the format requests a scenario in which the event should be executed, while the if() will instead exit the event when the expression is true. If the EXPRESSION given to a Sub Check has a negation symbol at the beginning, the symbol is automatically stripped instead of double negated.