Implementing character busts during dialogue

Started by SmugMonster, Sat 14/04/2018 00:22:40

Previous topic - Next topic

SmugMonster

I'm looking to implement Visual Novel style character busts during dialogue scenes. Basically, when the player interacts with a character in a room, it should display two images - one for the player's character bust and one for the other character's - overlaid with a dialogue box. Searching around hasn't yielded much in the way of this sort of thing, and I haven't spotted it in various resource/plugin/module pages. Any tips? Could this be accomplished using basic scripting? I haven't uncovered a function for something like this yet...

Crimson Wizard

#1
This reminds me I had an idea to make a visial novel-like template for some time...

Anyway, this should be relatively easy to do: dummy example is to make a large transparent GUI with two buttons. These buttons will be assigned character portraits to.
Then, instead of using Dialog.Start to begin conversation, write a custom function that first displays that GUI on screen and sets up characters, then calls dialog start.

One of the options is to write an extension method
Code: ags

void StartVN(this Dialog*, Character *left, Character *right)
{
    // set the buttons to have first frame of the character's speech view
    // ofcourse you may use different logic, for instance, get character's images from Custom Properties, or other variables
    btnVNLeftPortrait.NormalGraphic = Game.GetViewFrame(left.SpeechView, 0, 0);
    btnVNRightPortrait.NormalGraphic = Game.GetViewFrame(right.SpeechView, 0, 0);
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}


Now you may use this extender method like this:
Code: ags

   dPlayerSpeaksWithNPC1.StartVN(); // instead of .Start()


One thing to remember though, unfortunately AGS does not have a special event for "dialog end", so in all dialog scripts you need to remember call custom function that will clear dialog screen, before stopping a dialog:
Code: ags

void EndVN()
{
   gVisualNovelScreen.Visible = false;
   // add anything else you need to cleanup
}

Code: ags

// In dialog script --
  EndVN(); // make sure to indent with couple of spaces - this way you may call normal script functions from dialog scripts
stop

Actually, that may even be possible to create a macro command for this (to have 1 custom command call both EndVN and stop), but I'd need to test that out first, AGS script language is kind of restricted to what you may do with macros.

This is a simple example, but I believe this may give you an idea how to start.

SmugMonster

This sounds pretty much exactly like what I'm going for. Thanks! I have no idea how to implement those snippets, though - I haven't yet delved much into GUI functionality.

Incidentally, any tips on getting a VN-style dialogue box? So far I've got the lucasarts and sierra styles (let's not mention Whole Screen...) and neither of those do the trick. Just a text box down the bottom, ideally with a nameplate box or something to the top left of it for a character name (though that could just be done within the text itself, it'd be a lot more convenient to have it baked in).

Crimson Wizard

#3
Similarily, you would have to avoid using default Character.Say, and write a custom function for character talking. The text may be printed on a label, placed on same GUI (or separate, whichever you find convenient to work with). Name of the character may be printed on another label.

Code: ags

void SayVN(this Character *c, String text)
{
    lblVNName.Text = c.Name;
    lblVNSpeech.Text = text;
}


Usage:
Code: ags

   player.SayVN("Hello, I am the protagonist character in this game.");


The caveat here is that you will have to use same function in dialog scripts too, you no longer will be able to do "Ego: bla bla", you will have to always do "  cEgo.SayVN("bla bla")" (indented with space).



If you don't want to use regular fonts for the character name, you may try using sprite font plugin (or script a module, but that's another story).
Or, if you really want to have a name as an image (if that's what you mean by "baked in"), then use a button with graphic instead of label.

Experiment with various smaller elements first, anything complex can be built from those elements (and scripting).

SmugMonster

Thanks, man, I really appreciate the help. Final question (for now, inevitably there will be more ahaha):

Where do the first bits of code go? These ones:

Code: ags
void SayVN(this Character *c, string text)
{
    lblVNName.Text = c.Name;
    lblVNSpeech.Text = text;
}
 


And

Code: ags
void StartVN(this Dialog*, Character *left, Character *right)
{
    // set the buttons to have first frame of the character's speech view
    // ofcourse you may use different logic, for instance, get character's images from Custom Properties, or other variables
    btnVNLeftPortrait.NormalGraphic = Game.GetViewFrame(left.SpeechView, 0, 0);
    btnVNRightPortrait.NormalGraphic = Game.GetViewFrame(right.SpeechView, 0, 0);
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}


I'm assuming they need to be plugged in somewhere in one of the scripts, but I'm not sure where. How exactly would I go about actually adding these to my game?

Sorry for being a total noob lol

Crimson Wizard

#5
I recommend reading about functions and script modules in the manual:
http://www.adventuregamestudio.co.uk/manual/ags34.htm#topic41
http://www.adventuregamestudio.co.uk/manual/ags35.htm#topic42
http://www.adventuregamestudio.co.uk/manual/ags37.htm#scriptmodules

You may put the code in any of the script modules. That may be GlobalScript.asc that exists by default, or new script module created specifically for Visual Novel UI logic. What is best will be only seen after your project evolves.

After code is pasted in the script body, you declare these functions in the script's header (e.g. GlobalScript.ash):
Code: ags

import void StartVN(this Dialog*, Character *left, Character *right);
import void SayVN(this Character *c, String text);


After that you will be able to call those functions in globalscript, room scripts and dialog scripts.

SmugMonster

Thank you very much! Yeah, I'm working my way through the manual steadily. Made this thread to see if I could determine whether the functionality we're looking for was actually possible, 'cause AGS has about 80% of what we need that is very obvious. VN busts and dialogue stuff were the main things I didn't readily see, and a way to display full-screen animations (i.e. basically full-screen cutscenes) but I'm figuring I'll manage a way to do that somehow, even if it's making a fullscreen "object" that is invisible until called, with the frames done as a view, or something I dunno, just spitballing. There'll be a way for sure though.

Really appreciate the help!!

Crimson Wizard

Quote from: SmugMonster on Sun 15/04/2018 00:35:52
Thank you very much! Yeah, I'm working my way through the manual steadily. Made this thread to see if I could determine whether the functionality we're looking for was actually possible, 'cause AGS has about 80% of what we need that is very obvious. VN busts and dialogue stuff were the main things I didn't readily see, and a way to display full-screen animations

AGS is a specialized engine, and as such has a number of built-in features, mainly to support classic point-and-click games with walking character. But at the same time you may build almost anything different using "elementary blocks" and scripting. People were making arcade platformers, racing games, puzzle games, I've even seen a realtime strategy demo several years ago.

SmugMonster

Yeah, it seems pretty flexible if you think a bit outside the box. Once I get my head around how the thing works, like how global and room scripts interact and where best to place stuff, I'll be able to manage everything I want to do, I think.

Basically a semi-open VN/adventure in which the player can navigate around the city via a map and clicking locations, and interact with characters at these locations. Their locations will depend on the day of the week and time of day (which I assume I'll be able to set via variables and increment at the end of an event). It occurs to me that I'll have to actually move the characters around... dynamically determining their location based on the variables "weekday" and "time of day"... I suppose I'll need a function that moves each character to their respective spot based on the variables, and when I have an interaction that would change the time of day, I'll need to  run that function (likewise when the player "sleeps").

Pretty sure I'll be able to figure it out... though if you have any ideas/tips/things to avoid when doing something like that, feel free to share lol

SmugMonster

Actually, I do have a question. I'm trying to put together the GUI for the VN busts. Here's what I've done so far:

- Created a GUI called gVisualNovelScreen at full game resolution (720p if that matters)
- Created a button on the left called btnVNLeftPortrait, and on the right called btnVNRightPortrait

- added the following to my GlobalScript.asc:
Code: ags
void SayVN(this Character *c, string text)
{
    lblVNName.Text = c.Name;
    lblVNSpeech.Text = text;
}

void StartVN(this Dialog*, Character *left, Character *right)
{
    // set the buttons to have first frame of the character's speech view
    // ofcourse you may use different logic, for instance, get character's images from Custom Properties, or other variables
    btnVNLeftPortrait.NormalGraphic = Game.GetViewFrame(left.SpeechView, 0, 0);
    btnVNRightPortrait.NormalGraphic = Game.GetViewFrame(right.SpeechView, 0, 0);
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}

void EndVN()
{
   gVisualNovelScreen.Visible = false;
   // add anything else you need to cleanup
}


- Added the following to my GlobalScript.ash:

Code: ags
import void StartVN(this Dialog*, Character *left, Character *right);
import void SayVN(this Character *c, string text);


What I'm unsure about is how to set up the characters as the button images.

Once I get that done, though, then within the dialogue, it should look something like this, right?

Code: ags
dPlayerSpeaksWithNPC1.StartVN();
 player.SayVN("Hello world.");


Assuming I've sort of understood how this works, how would I swap a button's image in mid-dialogue (like a character changing expression/pose/whatever mid-conversation)

Aaaalso, and I realize I may be getting a tad ahead here, but - will the dialogue created by this function persist until the player clicks? If not, how do I get it to do that?

Crimson Wizard

#10
Quote from: SmugMonster on Sun 15/04/2018 02:23:06
Code: ags
import void StartVN(this Dialog*, Character *left, Character *right);
import void SayVN(this Character *c, string text);


What I'm unsure about is how to set up the characters as the button images.

If using the function from above example, you call the function StartVN, passing two character pointers as parameters.
For example:
Code: ags

dPlayerSpeaksWithNPC1.StartVN(player, cNPC1); // where player and cNPC1 are script names for characters



Quote from: SmugMonster on Sun 15/04/2018 02:23:06
Assuming I've sort of understood how this works, how would I swap a button's image in mid-dialogue (like a character changing expression/pose/whatever mid-conversation)

You already have an example of setting a button's image, similarily you may make another function of setting it again with another image without starting a new dialog.

Quote from: SmugMonster on Sun 15/04/2018 02:23:06
Aaaalso, and I realize I may be getting a tad ahead here, but - will the dialogue created by this function persist until the player clicks? If not, how do I get it to do that?

You mean, the text line? Yes, after set the label keeps its text forever. The problem is rather in making it dissapear when player clicks. For that you firstly need to learn how to handle mouse clicks and keyboard events.

Another thing to mention, I found a mistake in my previous example, where I wrote "this Character *c", you need to have "this Character*", and use "this.Name" instead of "c.Name":
Code: ags

void SayVN(this Character *, String text)
{
    lblVNName.Text = this.Name;
    lblVNSpeech.Text = text;
}




But these are formal answers, yet reading your post I realized two things.
First of all, for some reason I assumed you are working with AGS Dialogs, but the script snippet your posted showed that it's not the case.
Secondly, that in visual novels you may have character speaking not only in two-person conversations, but simply as a one-person monologue, or several people conversing with each other. So the "StartVN" function may not be very useful here, or rather, you may need something besides it.

So, I must emphasize this: the code I was posting above are examples, not solution. Maybe it should be scripted slightly differently. Or maybe largely differently...

For example, if you are not using Dialogs, but want to put a sequence of character's lines in a plain script, then you may need to modify SayVN function to make it actually show character itself, without need to call Dialog.StartVN.
You may also make it have an additional argument that tells whether character is displayed on left or right button. Something like this:
Code: ags

import void SayVN(this Character*, string text, bool left = true);

the "left" argument here has a default value "true" which lets you not type it if you want character to be at the left side.
Code: ags

void SayVN(this Character*, String text, bool left)
{
    if (left)
        btnVNLeftPortrait.NormalGraphic = Game.GetViewFrame(this.SpeechView, 0, 0);
    else
        btnVNRightPortrait.NormalGraphic = Game.GetViewFrame(this.SpeechView, 0, 0);
    gVisualNovelScreen.Visible = true;
    lblVNName.Text = this.Name;
    lblVNSpeech.Text = text;
}

Usage examples:
Code: ags

player.SayVN("I am talking at the left side");
player.SayVN("I am talking at the left side again", true);
player.SayVN("I am talking at the right side now", false);


Of course, running this code won't produce good results. There are more problems here:
1) All those commands will execute one after another without waiting for user to click.
2) Character's image will end up on both buttons, left and right one, because these functions do not "know" how to clear the button if same character is displayed on another one.

The first problem may be solved using WaitMouseKey function.
To solve the second problem a more sophisticated script must be devised.
Perhaps there are other issues that I did not think about beforehand.


My point is that a custom speech system, while technically possible, should not be approached without a plan.

My recommendation is to first write down the dialog system logic "on paper", and only then try to code it. Of course, before going into this task, it is important to learn at least the basic scripting in AGS.

SmugMonster

Okay, so I'm playing around with this, and have run into a problem. It's throwing an error when I try to compile the script, saying "cannot convert 'ViewFrame' to 'int'" at these lines:

Code: ags
    btnVNLeftPortrait.NormalGraphic = Game.GetViewFrame(left.SpeechView, 0, 0);
    btnVNRightPortrait.NormalGraphic = Game.GetViewFrame(right.SpeechView, 0, 0);


so it's trying to resolve the GetViewFrame to an integer, but I don't see why that wouldn't work. I've tried it with left.NormalView instead as well and it did the same thing. Not sure what's up with it...

Crimson Wizard

Quote from: SmugMonster on Sun 15/04/2018 19:42:53
Okay, so I'm playing around with this, and have run into a problem. It's throwing an error when I try to compile the script, saying "cannot convert 'ViewFrame' to 'int'" at these lines:

Oh, that's my mistake. I forgot to refer to the ViewFrame's "Graphic" property.

Code: ags

ViewFrame *vf = Game.GetViewFrame(left.SpeechView, 0, 0);
btnVNLeftPortrait.NormalGraphic = vf.Graphic;
vf = Game.GetViewFrame(right.SpeechView, 0, 0);
btnVNRightPortrait.NormalGraphic = vf.Graphic;


You may check what ViewFrame (and other object) consists of in the manual, if you find "ViewFrame functions and properties" article (and similar ones).

SmugMonster

Thank you! I feel like I'm almost there with this, but now in the dialogue script I'm getting this error when compiling:

Code: ags
Dialog 0(4): Error (line 4): Type mismatch: cannot convert 'string' to 'string'


Here's the dialogue script:

Code: ags
// Dialog script file
@S  // Dialog startup entry point

 cSylvie.SayVN("Hello, player.");
 WaitMouseKey;
 player.SayVN("Hello, Sylvie.");
 WaitMouseKey;
 
 EndVN();
stop


This is confusing me 'cause it looks like it's trying to convert a string to a string...which makes no sense?

Crimson Wizard

#14
Um, error message is weird indeed, probably one of those mistakes in AGS compiler.

But what is wrong is that you are calling WaitMouseKey function without brackets:

Code: ags

WaitMouseKey();


When a function is called, it always must have brackets, even if it has no parameters.
BTW, WaitMouseKey has 1 optional parameter (that may be not necessary in your case, but you may check manual to know how it works).

Also, I may suggest to add WaitMouseKey() to the code inside SayVN function instead, that way you won't have to write it everytime.

void SayVN(this Character *, string text)
{
    lblVNName.Text = this.Name;
    lblVNSpeech.Text = text;
    WaitMouseKey(); // <-----------------
}

SmugMonster

Hmm. WaitMouseKey(); gives me an error "Not enough parameters in call to function", which I'm assuming means it's missing a parameter. The only thing I see under the WaitMouseKey function in the manual is a time measure, though... so if I put 0 as a parameter, I would assume it will just continue immediately. I'd test it out, but I cannot for the life of me get the "convert string to string" error to stop appearing. It appears even if I create an entirely new dialog. Any suggestions for how to fix it?

Snarky

#16
In SayVN(), change "string" to "String" (with uppercase S). Both the import line and the actual function definition need to be updated.

And if WaitMouseKey(0); doesn't do what you need, you can use my BlockMouseKey(); here. It will block indefinitely.

Crimson Wizard

#17
Quote from: Snarky on Sun 15/04/2018 22:10:56
In SayVN(), change "string" to "String" (with uppercase S). Both the import line and the actual function definition need to be updated.

Well! This happens all the time when I switch between AGS and programming in C#........  :(

Of course, in AGS you need to use uppercase "String", not lowercase "string". The lowercase variant is an old version which was a limited-length string (long story).

Sorry for that, I will fix all my code examples.

SmugMonster

Okay - we no longer have errors happening! Yay! Thanks guys.

That said, it's not actually working. I just stuck a character onto the screen, with the idea that when clicked, the dialogue opens between the player and her. Here's the code:

Code: ags
function cSylvie_AnyClick()
{
dDialog1.StartVN(player, cSylvie);
}


The code for the actual new functions:

Code: ags
void StartVN(this Dialog*, Character *left, Character *right)
{
    // set the buttons to have first frame of the character's speech view
    // ofcourse you may use different logic, for instance, get character's images from Custom Properties, or other variables
    ViewFrame *vf = Game.GetViewFrame(left.NormalView, 0, 0);
    btnVNLeftPortrait.NormalGraphic = vf.Graphic;
    vf = Game.GetViewFrame(right.NormalView, 0, 0);
    btnVNRightPortrait.NormalGraphic = vf.Graphic;
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}

void SayVN(this Character *, String text)
{
    lblVNName.Text = this.Name;
    lblVNSpeech.Text = text;
    WaitMouseKey(0);
}

void EndVN()
{
   gVisualNovelScreen.Visible = false;
   // add anything else you need to cleanup
}


And the header code:

Code: ags
import void StartVN(this Dialog*, Character *left, Character *right);
import void SayVN(this Character *, String text);
import void EndVN();


And, in case it's relevant, the actual dialogue script:

Code: ags
// Dialog script file
@S  // Dialog startup entry point

 cSylvie.SayVN("Hello, player.");
 player.SayVN("Hello, Sylvie.");
 EndVN();
stop


The game runs just fine, Sylvie is hanging out in the middle of the screen where I put her, but clicking her doesn't do anything. Have I missed out on something?

Incidentally this is all being done in a blank project, so perhaps I missed adding in a necessary component or something. Both player and Sylvie have sprites and views defined for them.

Crimson Wizard

Quote from: SmugMonster on Sun 15/04/2018 23:18:37
I just stuck a character onto the screen, with the idea that when clicked, the dialogue opens between the player and her. Here's the code:

Code: ags
function cSylvie_AnyClick()
{
dDialog1.StartVN(player, cSylvie);
}


Hm!
First thing to double check in such situation is whether this function is connected to the actual event on the character's events panel.
Another thing you may do is place a dummy display command into this function to see if it runs at all:
Code: ags
function cSylvie_AnyClick()
{
Display("cSylvie_AnyClick is running!");
dDialog1.StartVN(player, cSylvie);
}

If upon clicking you see the message, but dialog does not start, then it's time to search for mistakes in the code...

BTW, what is assigned to character's speech view? (not normal one)

SmugMonster

#20
The display message didn't work either, which makes me think I messed something up in connecting them. They are connected, though - on the character's events panel, any click has that function associated with it.

I assigned the same view to all the different view types, just in case, because at least so far in this stage, we aren't going to be using animated speech frames (that'll come later).

Edit: I just created an object and stuck it in the room with the same function assigned to it and it didn't work either. So I'm really thinking I just missed something in the configuration somewhere...

Crimson Wizard

#21
Oh, I think I know what this may be.
The default cursor mode in AGS is "Walk to" and Any Click event may not trigger for that.

Since you have a visual novel style of game, you probably may just lock the cursor in "Pointer" mode (generic mode for interacting with GUI), at least for now.

Find "game_start" function in GlobalScript and put this:
Code: ags

mouse.Mode = eModePointer;

Then find "on_mouse_click" and remove the part that switches mode on right click:
Code: ags

  else // right-click, so cycle cursor
  {   
    mouse.SelectNextMode();
  }


Do not forget to assign graphic to the pointer cursor then.

SmugMonster

Okay, that fixed the "not reacting to clicks" problem - which shed light on the next round of problems hahaha... :embarrassed:

One weird thing and one broken thing.

The broken thing: clicking the character gives me an error "AGS had a problem running your game" etc., with the error "GetGameParameter: invalid frame specified" at the following line:

Code: ags
void StartVN(this Dialog*, Character *left, Character *right)
{
    // set the buttons to have first frame of the character's speech view
    // ofcourse you may use different logic, for instance, get character's images from Custom Properties, or other variables
    ViewFrame *vf = Game.GetViewFrame(left.NormalView, 0, 0); //<----------- this line
    btnVNLeftPortrait.NormalGraphic = vf.Graphic;
    vf = Game.GetViewFrame(right.NormalView, 0, 0);
    btnVNRightPortrait.NormalGraphic = vf.Graphic;
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}


And the weird thing... in both the character and the object, the following line works...but prints the text backwards:

Code: ags
Display("Sylvie click is working!");


I don't think that's meant to be backwards, is it? It's printing as "!gnikrow si kcilc eivlyS"

Crimson Wizard

#23
Quote from: SmugMonster on Mon 16/04/2018 01:25:22
The broken thing: clicking the character gives me an error "AGS had a problem running your game" etc., with the error "GetGameParameter: invalid frame specified" at the following line:

Code: ags

    ViewFrame *vf = Game.GetViewFrame(left.NormalView, 0, 0); //<----------- this line
}


In my example that was "SpeechView", in your code it is "NormalView". These are not same thing. Double check that you have assigned what you are actually using here in character properties. The view you are referencing must have at least 1 loop and 1 frame.


Quote from: SmugMonster on Mon 16/04/2018 01:25:22
And the weird thing... in both the character and the object, the following line works...but prints the text backwards:

Only reason I can think of is "Write text left-to-right" option in the General Settings ("Text output" category). This is for Hebrew and Arabic languages.

SmugMonster

Huh, yep, that was set to "True" for some reason. Hah.

Right, so, I've fixed it up now, changed around some views and whatnot so that the normal view is an empty frame (I don't want the main character to actually appear outside of dialogue scenes) but the speech view is the portrait image, aaaaand I changed the code back to speech view.

Now, when I click, it prints the Display text but doesn't do anything else. No errors now, though! It just doesn't actually seem to be running StartVN().

Crimson Wizard

The interesting thing is that there is another mistake that I missed, WaitMouseKey cannot be called with 0 for some reason (design mistake in AGS imho), so you need to wait for particular time like WaitMouseKey(100); or use the module Snarky linked above.

But this also means that your game never gets to call WaitMouseKey, or maybe even SayVN, otherwise you would seen the error message.

Not sure what to check here. For instance, are you certain that you are starting correct dialog?
What "Visibility" option your GUIs have?

SmugMonster

#26
Yeah, I only have the one dialogue, which is called dDialog1, and here's the code I'm using to start it:

Code: ags
function cSylvie_AnyClick()
{
  Display("Sylvie click is working!");
dDialog1.StartVN(player, cSylvie);
}


The GUI has "Normal, initially off".

Here's a weird thing, though. I just went in and added a display line to the dialogue:

Code: ags
// Dialog script file
@S  // Dialog startup entry point
 Display("Dialogue is working");
 cSylvie.SayVN("Hello, player.");
 player.SayVN("Hello, Sylvie.");
 EndVN();
stop


And that sort of worked. Clicking the character created a the "clicking this character is working" display, and clicking again then actually created the GUI as expected, with the right portraits! It also had the display string "Dialogue is working".

So I removed both Display lines, and then it didn't work again. So I put the one back in the dialog, and it worked again, this time (because the "clicking this character is working" display was still gone) it worked to show the GUI properly on one click.

Soooo it's initializing the dialog properly, but not actually displaying the GUI unless the Display message is in the dialog script.

Also, the actual strings for the name and text "hello player" etc. is not displaying on the labels. The portraits are working, though, so progress!!

EDIT: How do I get the actual GUI window to be invisible/transparent? Like I just want the buttons and labels to show up, but not the big grey box they're on top of. Setting it to 100% transparency makes the buttons/labels also transparent.

Snarky

You're running into a lot of basic problems that could have been avoided if you'd gone through the tutorial and read the manual before jumping straight into this task.

As for transparent GUI background, you just have to set the background color to 0 in the editor.

Crimson Wizard

#28
Quote from: SmugMonster on Mon 16/04/2018 03:22:39
Soooo it's initializing the dialog properly, but not actually displaying the GUI unless the Display message is in the dialog script.

Hm, still don't have any idea what may be going on. Yesterday I quickly made a test game to see if the code works, and it worked immediately.

Quote from: SmugMonster on Mon 16/04/2018 03:22:39
Also, the actual strings for the name and text "hello player" etc. is not displaying on the labels.

Are the labels on same GUI as the portraits? If not, is their GUI set visible?

Snarky

I'm betting you haven't changed the WaitMouseKey() call, and the problem is that it never blocks, so it just falls straight through the entire dialog in one go before you can see it. The Dialog() calls provide the blocking, but because they're placed before text is set on the Labels, you don't see it.

SmugMonster

#30
I actually did change the WaitMouseKey call, to a fairly large number precisely to avoid that happening.

The labels are on the same GUI as the portraits, yup. They're appearing, with the text "new label" on them. The actual speech string isn't being written. Sorry, could have been a bit clearer with that explanation.

EDIT: Hmm. Crimson, would it be possible for you to share the scripts you used where it worked immediately, so I can compare to mine and see if I might have messed something up somewhere in there?

I just got it a bit closer to working - I put the Display command below the speech lines instead of above it and they printed on the labels as expected. So I just need to figure out why the UI isn't appearing when there's no Display command in there... and, after having fixed the actual UI box to be transparent, I gotta figure out why my portraits have a fuzzy grey box over them, but I figure I've just messed up something in importing them or in setting up the button.

Crimson Wizard

#31
Quote from: SmugMonster on Mon 16/04/2018 16:28:54
EDIT: Hmm. Crimson, would it be possible for you to share the scripts you used where it worked immediately, so I can compare to mine and see if I might have messed something up somewhere in there?


I simply copied the code from those posts above into a new game.

Spoiler


In GlobalScript
Code: ags

void StartVN(this Dialog*, Character *left, Character *right)
{
    ViewFrame *vf = Game.GetViewFrame(left.SpeechView, 0, 0);
    btnVNLeftPortrait.NormalGraphic = vf.Graphic;
    vf = Game.GetViewFrame(right.SpeechView, 0, 0);
    btnVNRightPortrait.NormalGraphic = vf.Graphic;
    gVisualNovelScreen.Visible = true;
    // add anything else you need to setup
    this.Start();
}

void SayVN(this Character *, String text)
{
    lblVNName.Text = this.Name;
    lblVNSpeech.Text = text;
    WaitMouseKey(100);
}
 
void EndVN()
{
   gVisualNovelScreen.Visible = false;
   // add anything else you need to cleanup
}



Room script:
Code: ags

function dummy_AnyClick()
{
	dDialog1.StartVN(player, cSylvie);
}



Dialog script:
Code: ags

// Dialog script file
@S  // Dialog startup entry point
 
 cSylvie.SayVN("Hello, player.");
 player.SayVN("Hello, Sylvie.");
 EndVN();
stop


[close]

Created two characters, one GUI with 2 buttons and 2 labels.


Idk what may be else. Make sure that the background color and color of the label texts are different?...

Snarky

#32
Quote from: SmugMonster on Mon 16/04/2018 16:28:54
EDIT: Hmm. Crimson, would it be possible for you to share the scripts you used where it worked immediately, so I can compare to mine and see if I might have messed something up somewhere in there?

It'd probably be more efficient if you shared yours.

QuoteI just got it a bit closer to working - I put the Display command below the speech lines instead of above it and they printed on the labels as expected. So I just need to figure out why the UI isn't appearing when there's no Display command in there...

I'm telling you, it's because it's not blocking. Maybe the number you put in is too big (the max is... uh, I think something like 15000. Edit: It's 32767 â€" some 13.6 minutes at 40 fps). You could also try changing the WaitMouseKey() call to a simple Wait() â€" try something like Wait(200) (IOW 5 seconds).

The BlockMouseKey() code I linked to above was created precisely for this purpose: the timeout can be as long as you want (within the size of an int), or you can make it wait indefinitely.

Quoteand, after having fixed the actual UI box to be transparent, I gotta figure out why my portraits have a fuzzy grey box over them, but I figure I've just messed up something in importing them or in setting up the button.

The "fuzzy grey box" is the "GUI disabled" gray-out. You can get rid of it by going into General Settings, under Visual, and changing "When player interface is disabled, GUIs should" to "display normally".

SmugMonster

THAT was it - the number in the WaitMouseKey call was too large! Changing that fixed it all.

Thank you, Snarky - it's working as I hoped. Got some prettifying to do with the UI (need to add a background image for the labels, basically just a text box graphic) but I can just tuck another button behind the labels and that should do the trick.

You guys rock!

Snarky


SMF spam blocked by CleanTalk