Variables in Custom Speech Functions

Started by Baron, Sat 13/10/2012 00:30:12

Previous topic - Next topic

Baron

Hi.  I've been banging my head against the wall for a while now on this one without any progress, so maybe you guys can help me out.

I've written my own character.Talk extender function to replace character.Say in order to create speech bubbles.  I created a custom text window GUI, hijacked one of the Sierra speech-styles and relay the relevant string through a ghost character (called cGhost) who can be dynamically placed around the talking character's head.  So far so good.  But I can't wrap my head around how to adapt that function to incorporate variables.  I can't, for example, do something like this:

Code: ags
 cVillain.Talk ("I'm going to take all %d of your precious kittens.", kitten_count); 


because character.Talk only has two parameters (I hope I'm using that term correctly): function Talk (this Character*, String charsays).  So of course it doesn't understand the extra integer variable, because all I am giving it is a string.  Later on, after a lot of height, width, text length, character location variables, etc. etc., this line shows the speech in a nicely fitted bubble:

Code: ags
  cGhost.SayAt (this.x +sideoffset -GetViewportX (), charheight +bottomoffset -GetViewportY (), width, charsays); 


...but I can't put in dynamic variables like I could with character.Say.  My question is, how can I add an optional variable to a function, like in character.Says, so that I can build dynamic strings? 

Thanks in advance for any suggestions.

Crimson Wizard

#1
In C++ it is done with "..." in parameter list, which means "any number of parameters of unknown types".
AGS can't do that. Also AGS does not have a way to translate unknown number of parameters to formatted string.

There are perhaps ways make your own string formatting utilities, using monkey_05_06's vector module, for example, to pass random number of values. But the question is: do you really must to pass all that params to your function?

Cannot you just prepare formatted string beforehand, and pass it?
That is instead:
Code: ags
 cVillain.Talk ("I'm going to take all %d of your precious kittens.", kitten_count); 

do
Code: ags

String s = String.Format("I'm going to take all %d of your precious kittens.", kitten_count);
cVillain.Talk (s); 



E: Ahaha, actually AGS CAN do that:
Code: ags

function aa(int x, ...)

Dunno how that will work though. And I don't see a way to GET those params when in the function.

Baron

Ahhhh.....
     I'm reluctant to build the type of function where I have to type in a variable that I would rarely actually use, but I like your work around idea of just formatting another string when I need it and calling that instead of raw text.  It's the kind of quick and dirty fix that appeals to me -thanks!

     On a similar note, though, the thought had crossed my mind that I might want to add voice acting, but I don't think I'll be able to use the same commands.  i.e.

Code: ags
 cVillain.Talk ("&12 You'll never get your kittens back.  Never!"); 


     wouldn't work for the same reasons (I haven't tested it, but it seems &12 functions kind of like %d in that it isn't actually part of the string).  So I'm assuming from what you say, these symbols and their functionality were hard coded into the character.Say function with C++ and there is no way within AGS to adapt similar coding into a custom function?  I can work around a couple of instances where I might need variables, but manually entering hundreds or even thousands of voice files is not something I'd like to undertake.

Khris

You can have optional int parameters by adding a default value to the import line:

Code: ags
import void Talk(this Character*, String charsays, int param = 0);

// inside function:
  charsays = String.Format(charsays, param);   // put optional parameter into string


Not sure how helpful this is since it only works with ints.

As for adding voice speech code handling, afaik there's no way to play an external sound file; the only alternative I can see is setting up an array of structs which contains pointers to imported speech clips and use the character's ID and the speech number extracted from charsays to play the relevant one.
Sounds like a huge hassle though.

Implementing a custom Say function that allows access to all native methods -similar to the custom dialog options rendering- would be a great addition to future versions of AGS.

Crimson Wizard

#4
Quote from: Baron on Sat 13/10/2012 02:42:59
but I like your work around idea of just formatting another string when I need it and calling that instead of raw text.  It's the kind of quick and dirty fix that appeals to me
Dirty fix  ??? why do you think it is a fix? I see it as a common thing to do.
On other hand you could make a function that takes string with formatting characters and a monkey_05_06's Vector I've already mentioned before (which is basically a string which holds description of random variables inside):
http://www.adventuregamestudio.co.uk/forums/index.php?topic=37232.0

Quote from: Baron on Sat 13/10/2012 02:42:59
On a similar note, though, the thought had crossed my mind that I might want to add voice acting, but I don't think I'll be able to use the same commands.  i.e.
Code: ags
 cVillain.Talk ("&12 You'll never get your kittens back.  Never!"); 

wouldn't work for the same reasons (I haven't tested it, but it seems &12 functions kind of like %d in that it isn't actually part of the string).

I think there's huge misunderstanding. &12 IS a part of the string (as well as formatting characters like "%d" ARE part of the string). It is just that they are replaced inside Say command. That means that you can make a String variable and send it via 100 functions to Say command, like:
Code: ags

function SaySomething(String line)
{
   player.Say(line);
}

function OnSomeEvent()
{
   String s = "&12 Bla bla bla";
   SaySomething(s);
}


Similarly you may pass string with "%d" and other special characters, and the string will keep them all the way around.

Their replacement with variables - that what is done in String.Format, and implemented in exactly C++ as you say, although the implementation details aren't very related to this problem. You may make your own formatting function, eitehr with C++ formatting rules or your own rules, and replace special characters yourself.
The only problem here is to make the formatting function take any number of parameters of any types. AGS doesn't provide means for doing this, so if you want you'll have to find a workaround. Monkey's Stack (mentioned above) is one possible workaround.

Baron

Alright, I'm learning a lot here but I'm still in somewhat over my head.  I'm going to go research some of the things you've mentioned and do some experiments in AGS to see what happens.  Thanks a lot of all your advice and ideas!

Snarky

Quote from: Crimson Wizard on Sat 13/10/2012 00:55:02
In C++ it is done with "..." in parameter list, which means "any number of parameters of unknown types".
AGS can't do that. Also AGS does not have a way to translate unknown number of parameters to formatted string.

E: Ahaha, actually AGS CAN do that:
Code: ags

function aa(int x, ...)

Dunno how that will work though. And I don't see a way to GET those params when in the function.

Just reviving this thread to check that there isn't an update to this. It's still not possible to actually access these indeterminate parameters in AGS, right?

(Keywords for thread search: variadic function, params array, varargs, variable arguments)

Crimson Wizard

Quote from: Snarky on Tue 14/11/2017 09:16:19
Just reviving this thread to check that there isn't an update to this. It's still not possible to actually access these indeterminate parameters in AGS, right?

Right.

Snarky

Bumping this thread (celebrating its tenth anniversary!) again as a potential suggestion for AGS 4.0.

This particular use-case is probably not a high priority, since you can always just substitute a String.Format call, but it might be useful to have variadic functions in general.

Crimson Wizard

Quote from: Snarky on Sun 20/11/2022 07:17:01Bumping this thread (celebrating its tenth anniversary!) again as a potential suggestion for AGS 4.0.

I strongly recommend opening the suggestion on github issue tracker, or in development forums. Feature suggestions posted in regular tech forums tend to be missed and forgotten.

The suggestion is related to the script compiler. Fernewelten has been working on an extended compiler for a while now, he might be willing to take a look at this, if he has spare time.

SMF spam blocked by CleanTalk