[Solved] Interrupt Sierra speech

Started by Radiant, Sat 02/09/2017 09:52:26

Previous topic - Next topic

Radiant

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?

Snarky

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

Radiant

Thanks, but what I'm looking for is to dismiss the portrait and text.

Scorpiorus

I don't think there is an official way to skip the currently displayed text speech programmatically, if that's what you are after.

Kitty Trouble

I had a couple ideas but neither worked. If it's important you might have to go the route of making a custom GUI.

Snarky

#5
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).

Crimson Wizard

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

Scorpiorus

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

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

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

SMF spam blocked by CleanTalk