[SOLVED] Force speech animation to finish

Started by StillInThe90s, Tue 12/02/2013 04:14:31

Previous topic - Next topic

StillInThe90s

Here is, I would imagine, a proper beginners problem for you.
Using lucas arts style speech, I am simply trying to make a character finish his speech animation even if the text is timed out or clicked away. I guess some kind of 'wait until frame 0 and then return to dialog' would be in order...? But I can't find a way to target and implement this.
It would be even better if I could target a certain frame and do something like: 'if (character.Frame <=X) -return to dialog, else -finish animation'. Ie: if he has started waving his arms around, then let him finish waving. If not, then return and skip waving all together.

Khris

#1
Not possible, unless you do the speech animation yourself, I'm afraid.
You could create an extender function:
Code: ags
void MySay(this Character*, String text) {
  this.LockView(this.SpeechView);
  this.Animate(this.Loop, 3, eRepeat, eNoBlock);
  Overlay* o = this.SayBackground(text);
  delay = (text.Length / Game.TextReadingSpeed + 1) * GetGameSpeed();
  WaitMouseKey(delay);
  if (o != null && o.Valid) o.Remove();
  while (this.Frame != 0) Wait(1);
  this.UnlockView();
}

Not tested, will not work as-is, mostly to give you an idea about how to do it.

Call it like this:   cStan.MySay("Hello there!");

MiteWiseacreLives!

couldn't he just use Character.SayBackground then Character.Animate(0, 0, eOnce, eBlock)?
* have not tested, and I'm new

Khris

You mean couldn't he just animate the character using loop 0 (down) regardless of the direction the character is facing, using a delay of 0 to make the animation really, really fast, and using eOnce, eBlock so the animation has a fixed length while the text might be anything from a few words to a few sentences?
No, I don't think so.

MiteWiseacreLives!

well, I only used loop 0  and animation speed 0  as I assumed he would know what loop and speed he wanted, sorry for my syntax. As for completing the animation regardless of the length of the text, I think that's exactly what StillInThe90s wanted. Unless he needs to run the waiving his arms animation several times, then I suppose he should apply a timer or repeat the Character.Animate a few times??  I am of course assuming again that 90s wants to do this in a specific scenario/instance, if not he would require something more complex.
I'm only on these forums to learn, not to undermine helpful members like Kris who actually know what they're doing.

Khris

"Completing the animation" supposedly means "completing the current iteration of the repeating animation loop", at least that's how I read it.

If this is only for one specific line of text, doing it with a fixed number of calls to .Animate(..., eOnce, eBlock) will do the trick, yes. But as soon as the character is doing more talking, using a generic solution is always the better way to go.
Code should always be written so that a later design change requires the least amount of changes in other parts of the script/game, ideally none.

StillInThe90s

Clarifying time!
Yes, the idea was to implement this in a way that could be used in fairly complex dialogs. I'm sure there are lots of ways to work around a single or a few spoken lines not run from a dialog, so that's not really the issue.
By "finishing the animation" I mean: playing the current loop to it's final frame. (I don't know the correct technical terms) Never mind the "character.Frame <=X" -stuff.

So to sum up, there is really no way to hold the return-to-dialog except building my own dialog from scratch? Not even in repexec_always using character.Speaking or .SpeakingFrame or something? At least repexec_always ignores blocking commands.

Funny thing no one has brought this up before.

Khris

If you use my function, you can simply call it from a dialog script. It emulates AGS's Say and lets the character finish the loop, exactly what you need.
You know that you can use regular script commands in dialogs, right?

StillInThe90s

Sure I know about script commands in dialogs. I use it all the time but I have not managed to force the engine to prioritize animation before 'skip-speech'.
Unfortunately I'm pretty unfamiliar with some parts of your function, so it may take some experimentation. For starters, you wrote that it won't work as is. I can't see why.

Khris

I actually looked for the other thread where I used the speech delay formula and edited the code earlier today.
It should work now, I still didn't test it though.

What it does is start the animation (speed 3) and run a SayBackground.
Then the function waits for a) a mouse click b) a keypress or c) the calculated time to run out.
The background speech overlay, if still there, is removed.
The function now waits for the animation to reach frame 0, then stops it.

StillInThe90s

#10
You are quick, Khris.
I get what the function does, for the most part. My concern was mostly about me not being able to tweak it.
Turns out I may not have to, since you fixed it.  :-D

Embarrassing edit: Not really sure where to put the function and how to define "delay"...
Got it. I think.

StillInThe90s

It works like a charm for the most part. Although, if another character is cued after the affected character, the animation is still interrupted. Can't figure out why but I can work around it by only using the function in strategic places.

Khris

What do you mean by cued?
The functions is blocking from start to finish; nothing should be able to interrupt it.

StillInThe90s

QuoteWhat do you mean by cued?
Typo. I meant to write "queued".

QuoteThe functions is blocking from start to finish; nothing should be able to interrupt it.
That's what I thought. Could default speech lines from a dialog have some sort of blocking priority?

Khris

I know you meant queued, I was asking what you meant by it. :)
Could you post code / dialog scripts that cause the animation to be interrupted?

StillInThe90s

By "queued" i meant the next line spoken by another character, to be displayed before a 'return' or 'stop' in the dialog. Like so:
Code: AGS
cChar1.MySay("something."); //Calling the no-skip function
cEgo.Say("something else.");  //Seems to override the no-skip. Same goes for default speech lines (cego: something else.) 

Line 2 would be the "queued" one.

I reworked my dialog script to iron out this problem, but the original worked like the above. Only with more lines (cChar1-cEgo-cChar1-cEgo...).
The cause of the problem might be some other part of my messy code. So don't pull out your hair, Khris.  :-D

SMF spam blocked by CleanTalk