Help writing a character extender function.

Started by newwaveburritos, Fri 13/05/2022 19:44:21

Previous topic - Next topic

newwaveburritos

I know what I would like to do and I'm reasonably certain it can be done but I don't myself have the chops to do it myself so I would appreciate any help.

What I want: a character function that displays a thought bubble GUI when that character is thinking of a particular different character.  I have the thought bubbles themselves laid out in different views and I think animating them with a GUI button since I will want to be able to call it from anywhere.

Code: ags

player.ThinkAbout(Dracula, 10);  //displays the Dracula thought bubble above any character for ten seconds


would be something like:

Code: ags

guiDraculaThoughtBubble.SetPosition(player.x+20, player.y-30);
guiDraculaThoughtBubble.Visible=true;
Button.Animate(VDRACULATHOUGHTBUBBLE, 0, 5, eRepeat)



But this doesn't solve the problem of how long to display it and is really just a pile of pseudo-code I'm using to illustrate a point.  And also it would have to be non-blocking.  Anyway, any thought on this, as always, are very much appreciated.  Thanks a million!!

Khris

I don't think you need more than one GUI for this. Anyway, to display a GUI non-blocking, you need to set its Visibility to Normal, turn it visible, start a timer, then hide the GUI again when the timer expires.
Not sure where exactly you got stuck here? Have you tried to write the extender function yet? From the title I thought this was specifically about the syntax of an extender function.

Snarky

Yeah, the only things I would add are to consider:

-Can two (or more) characters ever have a thought bubble at the same time?
-Will the thinking character ever move while the bubble is displayed, or will the camera/viewport move while it's displaying?

Either of those will make it more complex, otherwise it's just a matter of checking a timer/counter in repeatedly_execute()

newwaveburritos

#3
The part that I'm stuck on is how to assign the variable argument if that makes sense.  That is, a single GUI will work but assigning the proper view to the GUI button based on which character it is called for is unclear to me.  I could assign the view integer to each character's custom properties but I'm unclear how to pass that to the function. 

I am trying to make something like this but that actually works:

Code: ags


#DEFINE VDRACULATHOUGHTBUBBLE 42 //view 42, dreaming about Dracula

function ThinkAbout(this Character*, int ThoughtBubbleTarget)
{
  this.SayBubble("I sure think Dracula is dreamy!");
  gThoughtBubble.Visible=true;
  btnThoughtBubble.Animate(ThoughtBubbleTarget, 0, 5, eRepeat, eNoBlock);
}


So I can call this or change the target for whoever may be in your thoughts and dreams:

Code: ags

player.ThinkAbout(DRACULATHOUGHTBUBBLE);


That bit of imaginary code skips the timer part, obviously, but that's not the part I'm struggling with.

Snarky

#4
Aha, so your actual problem is how to link a View to a Character, so that you can go from a handle on the Character to the associated View.

Well, the easiest way is to use one of the built-in properties. AGS Characters come with various default views you can set (Normal, Talk, Idle, Think…), and if you're not using one of these you can repurpose it for this purpose. Just set the view property to the view where you have the thought-bubble animation. Then, going off your first post, you'd do something like:

Code: ags
int thinkTimer;

void ThinkAbout(this Character*, Character* targetCharacter, int thinkTime)
{
  guiThoughtBubble.SetPosition(this.x+20, this.y-30);
  guiThoughtBubble.Visible=true;
  btnThoughBubble.Animate(targetCharacter.ThinkView, 0, 5, eRepeat);
  thinkTimer = thinkTime*GetGameSpeed();
}


Which you could then call as:

Code: ags
  player.ThinkAbout(cDracula, 10); // Thinks about Dracula for 10 seconds


If you don't have a spare view property to repurpose, you can use a custom property instead. Instead of targetCharacter.ThinkView you would then use something like targetCharacter.GetProperty("ThoughtBubbleView").

(Note that in the example I've removed the references to Dracula in the GUI name, since you definitely don't want it tied to the particular Character being displayed.)

newwaveburritos

Oh, this is very clever!  I was not using the think view so repurposing it for this is really nice.  I also had the positioning way off but this works beautifully.  Thanks so much for your help!

Code: ags

int thinkTimer;
 
void ThinkAbout(this Character*, Character* targetCharacter, int thinkTime)
{
  gThoughtBubble.SetPosition(this.x-7, this.y-83);
  gThoughtBubble.Visible=true;
  btnThoughtBubble.Animate(targetCharacter.ThinkView, 0, 5, eRepeat);
  thinkTimer = thinkTime*GetGameSpeed();
  SetTimer(THOUGHTBUBBLETIMER, thinkTimer);
}

Snarky

Glad you figured it out. Note that if you're using an actual Timer, you don't need the thinkTimer variable; I had it there as an alternative to an AGS Timer, to be counted down in repeatedly_execute().

SMF spam blocked by CleanTalk