Best way to identify if speech has been skipped.

Started by greg, Sat 30/11/2024 17:10:20

Previous topic - Next topic

greg

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:

Code: ags
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:

Code: ags
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?

Crimson Wizard

#1
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.

greg

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!

SMF spam blocked by CleanTalk