RPG-style talk.

You must understand the Game Editor concepts, before post here.

RPG-style talk.

Postby DilloDude » Wed Jun 28, 2006 11:11 pm

I have develloped a system for an rpg-style conversation. It includes things like signs, talking to players, etc. It lets you
  1. easily have multiple text-blocks
  2. easily insert your character's name (where the user can set it)
  3. display an icon when it is an examination or anything else you want (eg. it can display an 'i' symbol if it is just you examining something, as opposed to someone talking.
It does NOT let you have sections where you make a choice, although you could find a way to add this. All the above things are done with symbols in one string, so there is only one input string.
So, you find three symbols you are not using, in my case, I used '`' for separating text-blocks, '|' for your character's name, and '^' for the 'i' symbol. But you can make it anything you like.

This allows you to create a character who introduces himself, says hello, and then gives some advice, but the next time you talk to him, he just gives the advice.
Code: Select all
talk("Hello, |, my name is Fred. How are you?\nDid you know that if you destroy an enemy,\nhe will sometimes drop an item?`Did you know that if you destroy an enemy,\nhe will sometimes drop an item?", SpState);
SpState = 1;

Now for this to work, each actor needs a conversation to say. Here are some tips: For something you examine, like a bookshelf for example, you might want to have two animations: one where it is full of books and one where it is empty.
Rather than create two bookshelf actors, you can create one, and use two text-blocks:
Code: Select all
talk("^   It is a bookshelf, but there is nothing\n on it.`^   It is a bookshelf full of books.", animindex);

Now, depending on the bookshelf's animation, it says a different thing. Now, for fairly common things, like signs, or people, you don't necesarily want five different actors, so here is a hint: use two, one a sign, and the other a text actor.
On the sign's create actor, set a variable, 'talkno' to any number. If you have three people to talk to, and then you want signs, make the sign's talkno 3. So each actor has a variable that can be got from talkno + cloneindex. So if you have five signs,
and three people, they will have variables as follows:Person.0: 0; Person.1: 1; Person.2: 2; Sign.0: 3; Sign.1: 4; Sign 2: 5; Sign 3: 6; Sign 4: 7.
Now create a text actor, and clone it seven times. Place each clone near the actor that will have the same value. So TalkText.4 should be placed near Sign.1. This will make it easier to find which text is which actor. The benefit of cloning text actors is that
you can go to the 'text' window and make it start out with any text you want. So each clone has a different text at startup. In the text's create actor, set the transparency to .99, so you don't see the text. Now on you can use the getclone2 function
to acsess a particular text. So on your event that reads the sign, you can put
Code: Select all
talk(getclone2("TalkText", talkno + cloneindex)->text, 0);
Now what we achieved is making two actors - a sign and a text - instead of creating five individual sign actors. If you want to save the talk state of a person, so someone that says something important to the story,
and you need to remember his SpState variable, put all such actors at the beginning of your talkno list, before things like signs that always say the same thing. Now you need to go through an array and save the SpState of all relevant actors in the array.
Now I'm probably really boring you, and you're just thinking "Enough rambling on about it, tell it to me already!! :evil: "
Well the concept behind it is:
  1. look at the string, and find the correct text-block start position, relative to the inputted integer.
  2. copy the string from the previously found position, up to the next '`' or the end of the string.
  3. check if the first character of this is a '^' and if so set an animation appropriately.
  4. go continue through the string copying the 'PNAM' string if the character is a '|', or otherwise copying the character.
  5. pause the game.
  6. convert the final string to an array of lines.
  7. send an activation event to the text actor that will display the text.
The text actor then moves itself and the box it's in so it is visible, and copies the first four lines of the array to itself.
Then it waits for a key down event when it checks the position of the text relative to the number of lines and either
  1. hides itself and unpauses the game.
  2. moves down two lines.
You'll want some event that triggers the read. I suggest making a key down event with your player that creates an invisible actor that pokes out in front of him. When something collides with it, they can check the animindex and find which direction
It came from (eg. a sign that can only be read from the bottom or a person who turns to face you). You can use this same actor for any other things you want to use.
Now, we need to write the talk function. First we add the string to array function in global code. I have modified this to return the number of lines read.
Code: Select all
int str_to_array(char *str, char array[50][1000])
{
   int i;
   int line = 0;
   char *start = str;
   nlines = 0;
   for(i = 0; i < 50; i ++)
   {
       strcpy(array[i], "");
   }


   while(*str)
   {
      if(*str == '\n')
      {
         //End of line found
         //Copy to array
         *str = 0;
         strcpy(array[line], start);
         *str = '\n';


         //Go to next string
         start = str + 1;
         line++;
      }


      str++;
   }


   //Copy last string
   strcpy(array[line], start);
   return line + 1;
}

add this in a section called 'text functions' or something. In a new section in global code, add
Code: Select all
char speech[50][1000];
call this section'init'. This is where you can put other initializations of variables etc., such as #defines.
This just created a global variable that will be your array of strings for the text box to read. For the next bit to work, you need two actors: TextBoxBacking, which is the box that displays.
Give it two animations: 'TextBacking', which is your standard backing animation and 'i', which contains the 'i' icon. This actor should be parented to 'View Center', if you have one, or 'view'.
Now you need another Actor, TextBox, which is a text actor parented to TextBoxBacking. Put four lines of text in it to check the space it comes to and position it on TextBoxBacking. Position TextBoxBacking so it is just below the view, so it covers the same width,
and is exactly it's height below the bottom of the view.
Now you need a few variables
  • nlines should be global integer.
  • PNAM should be a global string. fill it with the name of your character, or the name the player inputs.
  • speechno, or talkno, is an actor integer as mentioned above.
  • SpState is an actor integer, for use to determine what text to say, or for any other special state; different actors use it differently.
  • spstr is an actor string, for when an actor needs a special string, usually the clonename of another actor.
  • speech is the text array you created above
Now in global code, go back to 'Text Functions', and under str_to_array, put the talk function:
Code: Select all
void talk(char *str1, int wt)
{
    int charst = 0;
    int i, j;
    char strar[4000];
    char talkstr[4000];
    char addchar[2];
    char finstr[4000];
    //find the wt text segment
    strcpy(strar, str1);
    for (i = 0; i < wt; i ++)
    {
        for(j = charst; j < strlen(strar); j ++)
        {
            if (strar[j] == '`')
            {
                charst = j + 1;
            }
        }
    }
    strcpy(talkstr, "");
    //put it into talkstr
    for (i = charst; i < strlen(strar) && strar[i] != '`'; i ++)
    {
        talkstr[i - charst] = strar[i];
    }
    //set text box to default
    ChangeAnimation("TextBoxBacking", "TextBacking", FORWARD);
    strcpy(finstr, "");
    for(i = 0; i < strlen(talkstr); i ++)
    {
        //if ^, change to information anim
        if (i == 0 && talkstr[i] == '^')
        {
            ChangeAnimation("TextBoxBacking", "i", FORWARD);
        }
        //add to finstr
        else if (talkstr[i] != '|')
        {
            addchar[0] = talkstr[i];
            strcat(finstr, addchar);
        }
        //add PNAM into finstr
        else
        {
            strcat(finstr, PNAM);
        }
 
    }
    //pause game: put any script you need to pause the game here
    GlobalSpeed = 0;
    EventDisable("PlayerBase", EVENTALL);
    //convert finstr to an array of lines with returned number of lines
    nlines = str_to_array(finstr, speech);
    //tell textbox to activate with text
    SendActivationEvent("TextBox");
    strcpy(TextBox.spstr, clonename);
}
This is the baulk of what you are doing. Now you need to tell TextBox to activate with this text.
Go to your TextBox actor.
On create actor, disable key down events.
On Activation Event, you need to display the text:
Code: Select all
char  addstr[256];
int i;
SpState = 0;
strcpy(text, "");
for(i = 0; i < 4 && i <= nlines; i ++)
{
    sprintf(addstr, "%s\n", speech[i]);
    strcat(text, addstr);
}
TextBoxBacking.y += (view.height - TextBoxBacking.height / 2) - TextBoxBacking.yscreen;
EventEnable("Event Actor", EVENTKEYDOWN);
You can adjust this for any number of lines you want, just change the '4' above.
Now add a keydown event with the key you want, this does essentially the same thing, but checks to decide whether to end the text, and does a different four lines:
Code: Select all
char addstr[256];
int i;
SpState += 2;
if (SpState > nlines - 2)
{
    TextBoxBacking.y += (view.height + TextBoxBacking.height / 2) - TextBoxBacking.yscreen;
    //unpause game, use any unpause script you want
    GlobalSpeed = 1;
    EventEnable("PlayerBase", EVENTALL);
    EventDisable("Event Actor", EVENTKEYDOWN);
    SendActivationEvent(spstr);
}
else
{
    strcpy(text, "");
    for(i = 0; i < 4 && i < nlines; i ++)
    {
        sprintf(addstr, "%s\n", speech[i + SpState]);
        strcat(text, addstr);
    }
}
again, change values to change the number of lines displayed.
Now, using the tips described above, you can just use the talk function.
Remember, if you want to display the 'i' symbol, put ^ at the beginning of a text-block. Put ` between text blocks. Put | when you want your character's name.
If you need help with this, or if I have forgotten anything, just ask.
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby Game A Gogo » Wed Jun 28, 2006 11:28 pm

ehhh, cool, maybe if you could put it in a little demo so its easyer for some people like me!
Programming games is an art,
    Respect it.
User avatar
Game A Gogo
 
Posts: 3466
Joined: Wed Jun 29, 2005 10:49 pm
Location: French Canada *laughs*
Score: 181 Give a positive score

Postby DilloDude » Wed Jun 28, 2006 11:32 pm

Ok, I'll see if I can get around to that sometime.
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby Game A Gogo » Wed Jun 28, 2006 11:38 pm

k, thx a lot, it will help a lot of peoples
Programming games is an art,
    Respect it.
User avatar
Game A Gogo
 
Posts: 3466
Joined: Wed Jun 29, 2005 10:49 pm
Location: French Canada *laughs*
Score: 181 Give a positive score

Postby DilloDude » Thu Jun 29, 2006 12:10 pm

It's amazing the errors you find when trying to make a demo. The one I just found was in the talk function: near the beginning, in the first for loop, it says
Code: Select all
    for (i = 0; i < wt; i ++)
    {
        for(j = charst; j < strlen(strar); j ++)
        {
            if (strar[j] == '`')
            {
                charst = j + 1;
            }
        }
    }
Add a break statement in it so it says
Code: Select all
    for (i = 0; i < wt; i ++)
    {
        for(j = charst; j < strlen(strar); j ++)
        {
            if (strar[j] == '`')
            {
                charst = j + 1;
                break;
            }
        }
    }
The other thing is with pausing: In the demo I'm working on, I'm just wanting to disable key down and up events of the player, but I ran into problems, so in the places where there is a spot for pausing and unpausing, I set Player.SpState. Then In Player's draw actor it checks SpState and either disables or enables keydown and keyup events. This should be more clear when I post the demo.
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby DilloDude » Thu Jun 29, 2006 11:14 pm

Here is the demo;
There are some notes to make:
  • The walking uses a really bad system for changing animations, however as the intention of the demo is for the talking, I did not fix this.
  • The progress of the GoldHunter actors, and whether you have collected the gold, is saved. So if you have collected the gold, and you talk to one of them, they will say something like YOU got MY gold?, and then theyy will say something else. If you exit, and come back, they will say their final statement if you have talked to them after you got the gold before. If you want to erase the saved data, just delete the file.
  • In some cases, you would want to only save the talk dat when the game saves, rather than all the time.
  • You can change PNAM to any name you like, it's in view's create actor. Generally you will have this inputted by the user, but you could also change it if you had multiple characters to play as.
That's about all. If you have any problems, just ask.
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby Game A Gogo » Thu Jun 29, 2006 11:38 pm

YAY
Programming games is an art,
    Respect it.
User avatar
Game A Gogo
 
Posts: 3466
Joined: Wed Jun 29, 2005 10:49 pm
Location: French Canada *laughs*
Score: 181 Give a positive score

Postby Game A Gogo » Thu Jun 29, 2006 11:45 pm

just tried the demo, omg its so sweat, i like the game!
Programming games is an art,
    Respect it.
User avatar
Game A Gogo
 
Posts: 3466
Joined: Wed Jun 29, 2005 10:49 pm
Location: French Canada *laughs*
Score: 181 Give a positive score

Postby makslane » Fri Jun 30, 2006 1:52 am

DilloDude wrote:Here is the demo;


Great! Can I put in the demo page?
Last edited by makslane on Fri Jun 30, 2006 5:21 pm, edited 1 time in total.
makslane
Site Admin
 
Posts: 3947
Joined: Sat Apr 05, 2003 6:47 pm
Score: 182 Give a positive score

Postby DilloDude » Fri Jun 30, 2006 1:58 am

Sure!
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby makslane » Fri Jun 30, 2006 5:21 pm

Thanks!
makslane
Site Admin
 
Posts: 3947
Joined: Sat Apr 05, 2003 6:47 pm
Score: 182 Give a positive score

Postby Zehper48 » Mon Jul 10, 2006 12:47 am

I found the gold! It was awsome
I like score
User avatar
Zehper48
 
Posts: 241
Joined: Sun Jun 11, 2006 1:34 am
Location: Advanced Noob
Score: 4 Give a positive score

Postby DilloDude » Sun Jul 16, 2006 12:26 pm

Heres another clever thing to do: rather than using a text actor, you could try finding a line from a text file. Search the forums - I think you should find out how to find the n-th line. There are some advantages and disadvantages to this:
  • The user can find and edit the text. :?
  • It is harder to find the correct text: you can't see the text the actor says sitting there, and you can't easily find which actor says the text. :(
  • You could have different text files, so you could have it easy to do things such as shange language (just read from a different text file) :)
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby DilloDude » Mon Jul 17, 2006 3:20 am

The other problem with changing language is that texts such as things you examine that will normally each say the same thing will need to be recorded in the text file. So you will need to be able to reference them somehow. It might be best to add comments in the text before the text so it only puts the text after an end comment symbol (eg. >: ). Make it check the first occurence of it only. So in your ext file, you might have:

First introduction>:Once upon a time there was a world\nwhere chocolate grew on trees. But on a dark and\nrainy day, an evil man came and took over the land and\ntook all the chocolate for himself. The land was in panic, but a\nhero arose to challenge the evil man...
Sign 1>:North to Cityton.
Sign 2>:^ Someone has torn the sign, and you can't read it.

etc.
Image
User avatar
DilloDude
 
Posts: 866
Joined: Tue Jan 24, 2006 9:51 am
Location: Nyerellion
Score: 58 Give a positive score

Postby Joshua Worth » Mon Jul 17, 2006 6:08 am

I like it! Did you do most of it by your self? Are you good at C?
Stay sweet
User avatar
Joshua Worth
 
Posts: 515
Joined: Tue Jul 19, 2005 12:00 am
Location: Stralia
Score: 5 Give a positive score

Next

Return to Advanced Topics

Who is online

Users browsing this forum: No registered users and 1 guest