Is there a reliable way to identify if the player has just skipped a line of speech?
My method in 3.6.1 is as follows:
1. Wrap Character.Say() to track when a character is speaking and if speech was skipped:
function MySay(this Character*, String message) {
SetGlobalInt(IS_SPEAKING, this.ID);
this.Say(message);
if (GetGlobalInt(IS_SKIPPING_SPEECH)) {
Display("speech was skipped");
SetGlobalInt(IS_SKIPPING_SPEECH, 0);
}
SetGlobalInt(IS_SPEAKING, -1);
}
In 3.6.2, you can use Speech.SpeakingCharacter instead of SetGlobalInt(IS_SPEAKING, ...).
2. In repeatedly_execute_always(), check if a character is speaking and the skip key is pressed:
function repeatedly_execute_always() {
if (GetGlobalInt(IS_SPEAKING) >= 0 && IsKeyPressed(Speech.SkipKey)) {
SetGlobalInt(IS_SKIPPING_SPEECH, 1);
}
}
This approach sometimes but not always captures whether speech has been skipped. I assume this is because there's a race condition between completing the rest of the MySay() function (which clears IS_SPEAKING) and running repeatedly_execute_always() (which checks IS_SPEAKING).
Is there a better, more reliable way of tracking if speech has been skipped?
Since AGS 3.6.0 there's a special property for this called Game.BlockingWaitSkipped:
Quote- Added Game.BlockingWaitSkipped which tells the result of the last blocking wait skipping,
also including result of the blocking speech skipping.
https://adventuregamestudio.github.io/ags-manual/Game.html#gameblockingwaitskipped
Unfortunately the manual does not mention the meaning of return values.
IIRC they are matching the new return values of Wait():
https://adventuregamestudio.github.io/ags-manual/Globalfunctions_Wait.html#global-functions-wait
Quote0 - ended by timeout or SkipWait();
!= 0 - an integer value which combines InputType, KeyMod, and a key or button code corresponding to that input type; that describes what input device and which button on that device were used to skip this "wait".
On a side note, there are no race conditions in AGS script, because whole game logic is performed on a single thread. Only one script may be run at a time. "repeatedly_execute_always" is run only when there's "waiting" in another script (either call to Wait, or a blocking action). But it's never called in the middle of executing that script itself.
QuoteSince AGS 3.6.0 there's a special property for this called Game.BlockingWaitSkipped:
Thanks, CW! Game.BlockingWaitSkipped is exactly what I'd been looking for. (I'd been searching under Speech.* in the manual, but Game.* makes sense as this applies to all blocking waits across the game, not just Speech-related waits.)
QuoteOn a side note, there are no race conditions in AGS script, because whole game logic is performed on a single thread. Only one script may be run at a time. "repeatedly_execute_always" is run only when there's "waiting" in another script (either call to Wait, or a blocking action). But it's never called in the middle of executing that script itself.
Understood. Thanks for this glimpse into AGS internals!