Ok, so I'm finding out how triggers are stored and run in Starcraft, specifically so that I can address this issue in BWAPI.
See the TRIG format to get an idea about the format (may or may not be referenced).
Behaviour Guide
All player's triggers are updated when any these conditions are met:
- Immediately when the game is loaded. This includes saved games. The counters will be reset, not saved.
- After 30 frames have passed (1260ms on fastest).
- When the countdown timer reaches 1 (decrement from a higher value).
- When you press ESC in Single Player and the trigger has debugging enabled, and a wait is currently preventing trigger execution. (Single Player Only)
- When a wait is less or equal to the "milliseconds per frame" mark. (See below for info)
- When Center View has finished? (Single Player only)
- Something involving talking portrait? (Single Player only)
When a wait counts down, it subtracts the "milliseconds per frame" value.
See the divisors in this article for that time (in milliseconds).
The article also contains the exact game frame rate, and includes the values for every game speed setting.
Elapsed Time and countdown timer is updated every 15 frames. Leaderboard info is also updated every 15 frames.
Why 15? Because on NORMAL game speed, a frame occurs every 67 milliseconds, and 67ms*15 = 1005ms, which is roughly 1 second. On fastest this is 630ms.
Almost none of these values are saved when you save a game, and are reset upon loading.
As for countdown timer speeding up trigger execution, it can be shown using the following trigger:
Trigger
Players
Conditions
Actions
Structure
Code
condition conditions[16];
action actions[64];
DWORD executionFlags;
BYTE groupsToExecuteFor[27];
BYTE currentActionIndex;
action actions[64];
DWORD executionFlags;
BYTE groupsToExecuteFor[27];
BYTE currentActionIndex;
The other "internals" mentioned specifically at the end of a condition and action are just padding the data to a 4-byte alignment and is unused. In a C++ project, it would be correct if you set your alignment to 4 bytes and leave it out completely.
Internals
The "internal usage" fields specified in the TRIG format can be used, since Starcraft copy pastas the entire trigger into memory. The only alterations it appears to make are clearing flags 0x08, 0x01, and setting the current action index to 0.
Primary execution flags
- 0x01 : All Conditions are met, executing actions, cleared on the next trigger loop
- 0x02 : Ignore the following actions: Defeat, Draw
- 0x04 : Preserve Trigger
- 0x08 : Ignore execution
- 0x10 : Ignore all of the following actions for this trigger until the next trigger loop: Wait, PauseGame, Transmission, PlayWAV, DisplayTextMessage, CenterView, MinimapPing, TalkingPortrait, and MuteUnitSpeech
- 0x20 : This trigger has paused the game, ignoring subsequent calls to Pause Game (Unpause Game clears this flag only in the same trigger), may automatically call unpause at the end of action execution?
- 0x40 : Wait skipping disabled for this trigger, cleared on next trigger loop
Condition flags
- 0x02 : Ignore execution
Action flags
- 0x01 : Executing Wait, ignore this Wait/Transmission and reset this flag on its next call (Ignore a wait/transmission once)
- 0x02 : Ignore execution
- 0x04 : Always Display
As a practical example, you can basically use "Preserve Trigger" without requiring an action (as if it were 65 actions).
See the attached map for proof: [attach=7780]
Attachments: