[RESOLVED] Possible to allow user interaction during conversation between characters?

Started by paolo, Sat 18/09/2010 14:38:25

Previous topic - Next topic

paolo

The intro to my game features a conversation between two characters (essentially a bunch of "Say" commands). I'd like to make this skippable, which of course is easy enough to do if you use the StartCutscene and EndCutscene commands.

Rather than doing this, I'd like to have "Skip intro" displayed on the screen which will do what it says when clicked on. This can be implemented in various ways (perhaps the simplest of which is to make this an object with a script that runs when it is interacted with) but no matter how I implement it, whether as an object or a GUI, clicking on it has no effect while the characters are talking.

I've tried adding code to on_mouse_click in the global script, which didn't work, and writing an on_mouse_click function in the room script, which didn't work either. The problem is that the game engine does not do anything with mouse clicks while the characters are talking except advance the conversation.

So is there a way of doing this, that is, of making the interact mouse mode operational while characters are talking? I can't use SayBackground because then the characters would talk over each other, and in any case, I'm using portrait-style speech.

I'm using AGS v2.72. Thanks for any help.

Wyz

< snip >

As far as I know there is no command that can stop speech in progress (is there something that can stop speech from a repeatedly_execute_always function?)

You could use SayBackground an build in you own timing. Use repeatedly_execute to see if it's time to say the next line, or when the player skipped: return to the game.

Code: ags

bool Skipping = true;
int timing;

// (...)

function room_RepExec()
{
  
  if (Skipping)
    return;
  
  if (timing == 0)
    cChar1.Say("Some line");
  else if (timing == 80)
    cChar2.Say("Some other line");
  else if (timing > 160)
    Skipping = true;
}


You'd start it by setting Skipping to false, and timing to 0.
Life is like an adventure without the pixel hunts.

paolo

Thanks for your suggestion, Wyz. I'll see if I can do something with that. Note that SayBackground won't work because it doesn't use the character's portrait, but your idea doesn't use SayBackground.

Crimson Wizard

I'd suggest writing different speech system, with drawing speech as a text overlay, for example, and using timer to know when to change it. This will allow player to click around on any objects on screen during character conversation.

paolo

Thanks for the suggestions. I've found a solution. Wyz's idea reminded me of something I had already written for a slightly different purpose and I was able to adapt it to my needs.

Wyz

Glad you got it working, I was still breaking my head over this. I came with a trick you might find useful.

Code: ags

function XSay(this Character *, String message)
{
  this.SayBackground(message);
  
  int time = (message.Length * 40) / Game.TextReadingSpeed;
  if (time < Game.MinimumTextDisplayTimeMs / 25)
    time = Game.MinimumTextDisplayTimeMs / 25;
  
  while (time)
  {
    // Some check that could change time to 0
    
    if (WaitMouseKey(1))
      time = 0;
    else
      time--;
  }
  
  this.SayBackground(" ");
}


This mimics the Character.Say(...) function quite well as far as I could test it.

edit: I'm referring to the timing btw
Life is like an adventure without the pixel hunts.

paolo

Interesting. I haven't come across the WaitMouseKey function before. Does that mean "wait until the user clicks the mouse or presses a key" or something like that?

Wyz

Yes, it waits till one of the following happens: the specified time elapsed, a mouse button was pressed, a key was pressed. The real treat is that it return true if the wait was interrupted by a key or mouse press, otherwise false. Also the function WaitKey() exists which does exactly what you would expect.
I used the function to create a WaitMouseKeyJoy() function for my joystick plugin ;D
Life is like an adventure without the pixel hunts.

monkey0506

A different approach to doing this would just be to reference the Overlay directly, seeing as SayBackground already calculates the timing, and it seems more fluid (to me) to remove the Overlay instead of calling the SayBackground function again. Seeing as it's blocking, you may as well add speech animations too:

Code: ags
function XSay(this Character *, String message) {
  Overlay *speechOverlay = this.SayBackground(message);
  if (this.SpeechView) this.LockView(this.SpeechView);
  this.Animate(this.Loop, this.AnimationSpeed, eRepeat, eNoBlock)
  while ((speechOverlay != null) && (speechOverlay.Valid)) {
    if (WaitMouseKey(1)) speechOverlay.Remove();
  }
  if (this.SpeechView) this.UnlockView();
}

SMF spam blocked by CleanTalk