Adventure Game Studio

AGS Support => Beginners' Technical Questions => Topic started by: newwaveburritos on Mon 15/08/2022 01:57:29

Title: Help with pointers for a dialogue system [SOLVED]
Post by: newwaveburritos on Mon 15/08/2022 01:57:29
Okay, I've got an idea for an icon based dialogue system which I wish to use in addition to the standard Monkey Island-esque dialogue system of the BASS template.  That is, inside of a regular dialogue when you choose an option that will exit the dialogue and enter this new phase of dialogue which will be the player asking about a character.  You'll scroll through the various icons until you find the character you want and then click it.  It looks like this:

(https://i.imgur.com/xcbfzoj.png)

In this instance we're talking to the Robot about the Mummy.  So, we have here two pieces of information we need to pass on.  Who we're talking to, and who we're talking about.  I was thinking it would be best to have a big switch case so that it's all in the same place and I can see everything and read everything and add the dialogue or instruction easily in one organized place.  But before we get that far let me show you the scrolling GUI where we choose the character icon because I know we're going to have to use that to pass on the character's icon the player chooses.  It's the same button, I'm just going through the views in order to animate it.


function ScrollLeft()
{
  BackgroundGraphic--;
  if (BackgroundGraphic==-1){
    BackgroundGraphic=7;
  }
    switch (BackgroundGraphic)
    {
      case 0:
       
        btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock); //cDracula
       
        break;
     
       
      case 1:
     
        btnCharacterChoice.Animate(43, 0, 5, eRepeat, eNoBlock); //cFrank
        break;
     
      case 2:
     
        btnCharacterChoice.Animate(44, 0, 5, eRepeat, eNoBlock);  //cMummy
        break;
     
      case 3:
     
        btnCharacterChoice.Animate(45, 0, 5, eRepeat, eNoBlock); //cPhantom
        break;
     
      case 4:
     
        btnCharacterChoice.Animate(46, 0, 5, eRepeat, eNoBlock);  //cWolfie
        break;
     
      case 5:
     
        btnCharacterChoice.Animate(78, 0, 5, eRepeat, eNoBlock);  //cYoko
        break;
     
      case 6:
     
        btnCharacterChoice.Animate(79, 0, 5, eRepeat, eNoBlock);  //cRobot
        break;
     
      case 7:
       
        btnCharacterChoice.Animate(41, 0, 5, eRepeat, eNoBlock);  //cAlien
        break;
     
      case 8:
      BackgroundGraphic=0;
      break;
    }
}


function ScrollRight()
{
  BackgroundGraphic++;
  if (BackgroundGraphic==8){
    BackgroundGraphic=0;
  }
    switch (BackgroundGraphic)
    {
      case 0:
       
        btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock);
       
        break;
     
      case 1:
     
        btnCharacterChoice.Animate(43, 0, 5, eRepeat, eNoBlock);
       
        break;
     
      case 2:
     
        btnCharacterChoice.Animate(44, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 3:
     
        btnCharacterChoice.Animate(45, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 4:
     
        btnCharacterChoice.Animate(46, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 5:
     
        btnCharacterChoice.Animate(78, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 6:
     
        btnCharacterChoice.Animate(79, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 7:
       
        btnCharacterChoice.Animate(41, 0, 5, eRepeat, eNoBlock);
        break;
   
    }
}


That's all well and good and works fine, it just doesn't do anything right now. The function to open the GUI is where I start to get lost.  I think it should look something like this:


Character* thisIsWho;
function openCharacterGUI(Character* whoImTalkingTo)
{
  gCharacters.X=player.x-20;
  gCharacters.Y=player.y-90;
  btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock);  //starts the animation since we have to start it before we can open it
  thisIsWho = whoImTalkingTo;
  gCharacters.Visible = true;  //this is the name of the GUI open in the screenshot.
}


What I think this does is pass along the pointer of who I'm talking to and I'll call this inside each character's dialogue.  That is, when I click from dRobot00 I'll call:


openCharacterGUI(cRobot);


Then I have the big switch case.


function talkToChar(Character* talkAbout)
{
 
  switch(talkAbout)
  {
   case cAlien:
      switch(thisIsWho) //this is who I'm talking to
      {
        case cAlien:
        //talking to Frankenstein about the Alien
        break;
        case cDracula:
        player.Say("Tell me about Dracula.");
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        player.Say("Tell me about The Alien!");
        break;
      }
    break;
   
   case cDracula:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Dracula about the Alien
        player.Say("Tell me about Dracula!");
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cFrank:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Frankenstein about the Alien
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cMummy:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Mummy about the Alien
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cPhantom:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Phantom about the Alien
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cWolfie:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Wolfie about the Alien
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cYoko:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to BrunchLadies about the Alien
        break;
        case cDracula:
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
   
    case cRobot:
      switch(thisIsWho)
      {
        case cAlien:
        //talking to Robot about the Alien
        break;
        case cDracula:
        cRobot.Say("Dracula!");
        break;
        case cFrank:
        break;
        case cMummy:
        break;
        case cPhantom:
        break;
        case cWolfie:
        break;
        case cYoko:
        break;
        case cRobot:
        break;
      }
    break;
  }   
}


So, what I think is I should have a similar function to the one that opens the GUI to close it that tells the switch case who the player clicked on.  And actually, I think maybe I don't want a function at all there or maybe one that returns something?  That's where it all falls apart for me but the theory of that switch case being a shelf to put answers on is really appealing to me. 

Well, thanks everybody!

EDIT: I think I have the comments on my switch case backwards.
Title: Re: Help with pointers for a dialogue system
Post by: eri0o on Mon 15/08/2022 03:25:09
I am a bit unsure on what is working and what is not working...

In any case, a little trick I use in AGS is to create inventory items not just for inventory items, but for other things, like conversation topics, and then have dummy characters for the different inventory categories, then it's just changing to who the inventory is wired to, using an extra button for that, and then using an inventory item or asking about something, is all through inventory handling.
Title: Re: Help with pointers for a dialogue system
Post by: newwaveburritos on Mon 15/08/2022 04:56:21
I think the part that isn't working is this:


function openCharacterGUI(Character* thisIsWho)
{
  gCharacters.X=player.x-20;
  gCharacters.Y=player.y-90;
  btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock);  //starts the animation
  thisIsWho = WhoAmITalkingTo;
  gCharacters.Visible = true;
}


When I put openCharacterGUI(cRobot); at the appropriate place in the dialog it doesn't work.  Nothing happens.  When I put WhoAmITalkingTo=cRobot; above the function it does.  WhoAmITalkingTo is a global characater variable as is WhoAmITalkingAbout.
Title: Re: Help with pointers for a dialogue system
Post by: eri0o on Mon 15/08/2022 12:09:11
In openCharacterGUI(Character* thisIsWho) you have reversed how assigning to a variable works, it's right assigns to left of the equal sign, not the reverse - if I understood what you are trying to achieve.
Title: Re: Help with pointers for a dialogue system
Post by: newwaveburritos on Mon 15/08/2022 20:10:19
Oh, yes, I think you're right.  When I swap those two and it works as intended.  I think this whole mess is working now like I envisioned it.  Thanks a million!
Title: Re: Help with pointers for a dialogue system
Post by: newwaveburritos on Mon 22/08/2022 18:51:11
Okay, one thing I failed to account for is that it doesn't make sense to have a whole list of characters available to you at game start since you haven't met anybody yet so it makes sense to populate the thing as you meet the characters.  I think that I'll have to do this with the scrolling system.  The characters get added to a set which is how I am tracking who you have met.  BackgroundGraphic is just an int so you could feasibly change that int based on the number of entries in the set CharactersMet but I feel like there's a better option here that I'm just not thinking of.

Here's the scrolling code:



function ScrollLeft()
{
  BackgroundGraphic--;
  if (BackgroundGraphic==-1){
    BackgroundGraphic=7;
  }
    switch (BackgroundGraphic)
    {
      case 0:
       
        btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock);
       
        break;
     
      case 1:
     
        btnCharacterChoice.Animate(43, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 2:
     
        btnCharacterChoice.Animate(44, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 3:
     
        btnCharacterChoice.Animate(45, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 4:
     
        btnCharacterChoice.Animate(46, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 5:
     
        btnCharacterChoice.Animate(78, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 6:
     
        btnCharacterChoice.Animate(79, 0, 5, eRepeat, eNoBlock);
        break;
     
      case 7:
       
        btnCharacterChoice.Animate(41, 0, 5, eRepeat, eNoBlock);
        break;
     
    }
}


function ScrollRight()
{
  BackgroundGraphic++;
  if (BackgroundGraphic==8){
    BackgroundGraphic=0;
  }
    switch (BackgroundGraphic)
    {
      case 0:
       
        btnCharacterChoice.Animate(42, 0, 5, eRepeat, eNoBlock);
        labelWhoAmITalkingAbout.Text=String.Format("Dracula!");
        WhoAmITalkingAbout=cDracula;
        break;
     
      case 1:
     
        btnCharacterChoice.Animate(43, 0, 5, eRepeat, eNoBlock);
       WhoAmITalkingAbout=cFrank;
        break;
     
      case 2:
     
        btnCharacterChoice.Animate(44, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cMummy;
        break;
     
      case 3:
     
        btnCharacterChoice.Animate(45, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cPhantom;
        break;
     
      case 4:
     
        btnCharacterChoice.Animate(46, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cWolfie;
        break;
     
      case 5:
     
        btnCharacterChoice.Animate(78, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cYoko;
        break;
     
      case 6:
     
        btnCharacterChoice.Animate(79, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cRobot;
        break;
     
      case 7:
       
        btnCharacterChoice.Animate(41, 0, 5, eRepeat, eNoBlock);
        WhoAmITalkingAbout=cAlien;
        break;
   
    }
}

Title: Re: Help with pointers for a dialogue system
Post by: newwaveburritos on Tue 23/08/2022 05:45:32
I've made a little progress.  I think what I'm looking for is something along the lines of:


BackgroundGraphic=CharactersMet.ItemCount;
    BackgroundGraphic++;
    if (BackgroundGraphic==CharactersMet.ItemCount){
      BackgroundGraphic=0;
    }


This will make it so that the background image of the button has the right number of options but I'm having trouble wrapping my head around how to set each of those to the proper character since you could meet them in any order, essentially.  I'm halfway tempted just to make the intro a big monster party so you meet everyone at once!


if (CharactersMet.Contains("Dracula")){
//enable Dracula's button etc. etc.
}
[code]
Title: Re: Help with pointers for a dialogue system
Post by: newwaveburritos on Thu 25/08/2022 20:47:28
Okay, with a LOT of help from timiddolphin this problem can be marked as solved.  For anybody following along now or in the future here is the code that makes the scrolling work.  This is predicated on the other code higher so it may not work for you out of the box but it can certainly be taken as an example.  I think everything that makes it work is in the thread here, though.


int buttonGraph[16];  //this is the number of total characters +1, by the way.

function initButtonGraph()
{
  //runs in game-start,  sets every slot in the array to 0.
  for (int i = 0; i < Game.CharacterCount; i++)
  {
    buttonGraph[i] = 0;
  }
}

function setFirstButtonGraphIndex(int theGraphic)
{
  for (int i = 0; i < 15; i++)
  {
    if(buttonGraph[i] == 0)
    {
      buttonGraph[i] = theGraphic; //sets the first 0 it finds to the graphic you put into this function
      return;
    }
  }
}

int scrollPosition = 0;

int findMaxScrollPosition()
{
  for (int i = 15; i > -1; i--)
  {
    if(buttonGraph[i] != 0)
    {
      return i;
    }
  }
  return 0;
}

function ScrollLeft()
{
  if(scrollPosition == 0)
  {
    scrollPosition = findMaxScrollPosition();
  } else {
    scrollPosition--;
  }
  btnCharacterChoice.Animate(buttonGraph[scrollPosition], 0, 5, eRepeat, eNoBlock);
}

function ScrollRight()
{
  if(scrollPosition == findMaxScrollPosition())
  {
    scrollPosition = 0;
  } else {
    scrollPosition++;
  }
  btnCharacterChoice.Animate(buttonGraph[scrollPosition], 0, 5, eRepeat, eNoBlock);
}



//===========================================


function game_start()
{
  initButtonGraph();
  setFirstButtonGraphIndex(42);  //you'll probably want to call these as you click on a character wherever your clicks are handled.
  setFirstButtonGraphIndex(43);
  setFirstButtonGraphIndex(44);
}