When Sierra-style speech is playing, a portrait is shown; underneath, room/character animations continue normally. During this time, the function repeatedly_execute_always() also gets called. Is there a way from this function to end the current speech animation that's being displayed?
If you just want to stop the animation (i.e. not actually dismiss the dialog portrait/text), you might be able to use a trick I came up with for the TotalLipSync module (http://www.adventuregamestudio.co.uk/forums/index.php?topic=54722.0). I set the speechview to a view with only one frame, and then I can control the animation by changing that frame's sprite in real-time.
Thanks, but what I'm looking for is to dismiss the portrait and text.
I don't think there is an official way to skip the currently displayed text speech programmatically, if that's what you are after.
I had a couple ideas but neither worked. If it's important you might have to go the route of making a custom GUI.
There's no way in AGS to fake a keypress/mouse click programmatically, is there?
Edit: Maybe I should have checked before posting. There's ProcessClick(), of course. Maybe check if that works to dismiss the speech (if you've set it to skippable by mouse clicks).
Quote from: Snarky on Sun 03/09/2017 07:53:01
Edit: Maybe I should have checked before posting. There's ProcessClick(), of course. Maybe check if that works to dismiss the speech (if you've set it to skippable by mouse clicks).
If you are using 3.4.0 or higher, better try Mouse.Click(), IIRC ProcessClick skips general click checks and sends event straight to the object under cursor.
But then again, it is hard to predict how well this hack will work. If scripting custom speech is acceptable, I'd rather suggest doing that.
Good point guys, I've just tested it out and the trick with faking mouse clicks seems to work!
But yeah, it should be tested carefully to see if there is an unexpected behaviour under certain conditions, as Crimson Wizard says.
The following script should work:
bool gNeedRestoreSkipSpeechStyle = false;
SkipSpeechStyle gSavedSkipSpeechStyle;
function repeatedly_execute_always()
{
if (NEED_TO_SKIP_SPEECH)
{
gSavedSkipSpeechStyle = Speech.SkipStyle; // save current SkipStyle value
Speech.SkipStyle = eSkipMouse; // force it to eSkipMouse, in case it was eSkipTime-ONLY or something
Mouse.Click(eMouseLeft); // request doing a fake mouse click
gNeedRestoreSkipSpeechStyle = true; // set a flag to restore the original SkipStyle value later
}
}
function late_repeatedly_execute_always()
{
if (gNeedRestoreSkipSpeechStyle == true)
{
gNeedRestoreSkipSpeechStyle = false;
Speech.SkipStyle = gSavedSkipSpeechStyle; // restoring original value (<--- CAN CRASH THE GAME AT THE MOMENT)
}
}
But it doesn't, if the Speech.SkipStyle is set to TimerOnly in the General Settings. Then this script crashes...
It appears there is a bug in the AGS engine, where it doesn't correctly return eSkipTime value:
https://github.com/adventuregamestudio/ags/blob/release-3.4.0/Engine/ac/speech.cpp#L47
It returns "-1" (aka kSkipSpeechUndefined) instead of eSkipTime(2).
It should probably be fixed with:
...
if (internal_val & SKIP_AUTOTIMER)
{
internal_val &= ~SKIP_AUTOTIMER;
if (internal_val == (SKIP_KEYPRESS | SKIP_MOUSECLICK))
{
return kSkipSpeechKeyMouseTime;
}
else if (internal_val == SKIP_KEYPRESS)
{
return kSkipSpeechKeyTime;
}
else if (internal_val == SKIP_MOUSECLICK)
{
return kSkipSpeechMouseTime;
}
else if (internal_val == 0x00000000) // <--- FIX (EDIT: better explicitly compare with 0 instead of having vague "else", just in case!)
{
return kSkipSpeechTime;
}
}
...
Radiant, we can consider your post as an indirect bug report actually.
But, if possible, do use this approach with fake mouse click instead of the one I proposed before. :)