Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Radiant on Sat 02/09/2017 09:52:26

Title: [Solved] Interrupt Sierra speech
Post by: Radiant on Sat 02/09/2017 09:52:26
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?
Title: Re: Interrupt Sierra speech
Post by: Snarky on Sat 02/09/2017 11:19:14
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.
Title: Re: Interrupt Sierra speech
Post by: Radiant on Sat 02/09/2017 12:22:32
Thanks, but what I'm looking for is to dismiss the portrait and text.
Title: Re: Interrupt Sierra speech
Post by: Scorpiorus on Sat 02/09/2017 22:44:07
I don't think there is an official way to skip the currently displayed text speech programmatically, if that's what you are after.
Title: Re: Interrupt Sierra speech
Post by: Kitty Trouble on Sun 03/09/2017 00:17:41
I had a couple ideas but neither worked. If it's important you might have to go the route of making a custom GUI.
Title: Re: Interrupt Sierra speech
Post by: Snarky on Sun 03/09/2017 07:53:01
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).
Title: Re: Interrupt Sierra speech
Post by: Crimson Wizard on Sun 03/09/2017 10:22:58
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.
Title: Re: Interrupt Sierra speech
Post by: Scorpiorus on Sun 03/09/2017 14:14:48
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:

Code (AGS) Select

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:
Code (cpp) Select

...
    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. :)