GM:S 1.4 Easy Branching Dialogue System

Discussion in 'Tutorials' started by NoobsWeStand, Jun 24, 2016.

  1. ShadowMan

    ShadowMan Member

    Joined:
    Dec 9, 2016
    Posts:
    4
    Greetings! I just started school for video game design and I had an idea for dialogue, but I wasn't sure where to go or who to ask. Maybe you, or someone reading this could assist. I am designing a RPG game that requires character interaction, but I want to avoid that style where the NPC speaks, and then the player is given a list of responses to choose from. Instead, I would like to go back to the more interactive style common in classic games where the player's character encounters a NPC and two dialogue boxes appear; one the player's, the other's NPC. In the NPC dialogue box will say something like "greetings traveler" or another greeting (friendly or otherwise). Now the player gets to type in his or her dialogue box a response--any response he or she feels like. I understand it's a lot of work as there are so many responses, words, topics, a player can type, but this freedom of speech and interaction is critical for the goal of this character-based video game. I am not looking for a pure text adventure, but a visual RPG that uses text-based adventure elements in a conversation style with NPCs. Thank you in advance for any advice or program suggestions that would allow this. :)
     
  2. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    Unfortunately, this system is not setup for that kind of dialog. If you are looking for an easy way to get "freedom of speech" in your video game, then you are out of luck. Many game developers opt out of giving the player too many options that will affect the story later down the line, as it would cause an unimaginable amount of branching
    If you want a simple solution, using the string_count(substr,str) to search for things in the user's input, like "store" or "fight"-- and then using a switch statement to determine what the npc should do
    Another solution, although I haven't seen it done in GM, is by using neural networks. Building one from scratch is very difficult.
     
  3. acidhoover

    acidhoover Member

    Joined:
    Sep 19, 2016
    Posts:
    6
    hy Noobswestand

    i love it really good idea and yoü did it great...büt i have problems i downloadet it and did some dialoüges then i export it and load the txt file in the inclüded files büt then what?? i did make a new room püt the obj_player and obj_npcbob in the room büt nothing happens what do i wrong??plz help me
     
  4. mjmiller1824

    mjmiller1824 Member

    Joined:
    Sep 18, 2016
    Posts:
    33
    One option would be to use something like the "Stupid Backoff" method of text prediction, build a corpus of conversations in games and text messages (corporate customer service chats would be perfect for this if you can find them because they're so structured). Then do a frequency count of n-grams in responses. You would do this in something like R, Java, or python first and use the Stupid Backoff algorithm to come up with a list of reasonable responses and save them as a text file. You would have to limit your characters starting options but this would give your conversation a tone that the player should follow. So the idea is:

    NPC: Hey

    Char: Hello, my name is Kevin.

    program tries to find "Hello my name is Kevin". it can't so it searches for "my name is Kevin" (and I would probably have a list of names so that the game can identify when you're using a name at the end and exclude it from the ngram search) It find's "my name is Kevin"

    the most common response is "Hello Kevin, how are you?"

    So the NPC says "Hello Kevin, how are you"

    but I'm not sure how to make this work in GM outside of an external plugin written in Java or something like that. And all of the heavy lifting with processing the corpus would have to be done ahead of time. Google uses something like 2 trillion phrases in their model. And they have massive amounts of server power to do it. But you could limit it to the top like 300 responses for each NPC which would give you something like 80% coverage simulating an actual conversation.
     
  5. Atra

    Atra Member

    Joined:
    Sep 15, 2016
    Posts:
    9
    SO i have an idea for a game with a branching dialogue system. You could say it is completely dependend on it and i find your solution for the branching paths interesting. But one thing is nagging me and i am not smart enough to figure it out by myself ^^"

    Would it be possible that the Questions in the switch box, are transported outside of the box itself and be its own clickable Box with its own connected paths? With its own gui etc.? I dont know if i made it clear so let me give an example of the idea^^

    Current:
    Do you like me?

    1. Yes
    2. No

    Idea

    Do you like me?
    ______________
    I............................I
    I...........Yes...........I
    I______________I


    ______________
    I............................I
    I...........No............I
    I______________I
     
  6. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,184
    Its a difficult task, but blur unsurmountable.

    First build a I've dictionary to replace words with generics. ( so 'hi, where am I?', would become 'hello, where am player?')

    Next remove any words you don't know/care about. So 'hi, where am player' becomes 'where player'

    Next, match against pattern database. Needs to be pretty big!

    To make this simpler, make sure you try to build a dictionary to natches the most words, to as little generics as possible. This will allow you to build up only the patterns you want.

    This can become very interesting if you allow your system to generate patterns as the player does things. Far more complex however.


    Not a perfect approach, but probably the best you can do within a game.

    [Edit] I think I replied to the wrong thread ^^
     
    Last edited: Jan 3, 2017
  7. Mick

    Mick Member

    Joined:
    Jun 30, 2016
    Posts:
    686
    This branching dialogue system is great, thanks for making it available for others! I changed the editor so the different types of boxes have their unique colours (visible in the gif), makes things clearer. When testing out the editor I might have found a bug, if you check the gif, you can see that the second switch don't give the options "Yes" and "No" like it should I guess?

    [​IMG]

    The colours are implemented like this (just add the code to the start of the event scripts, very simple):

    objNode create:
    Code:
    color_type[0]=$71ae68; // textbox
    color_type[1]=$5353c1; // scriptbox
    color_type[2]=$c18e53; // switchbox
    color_type[3]=$d26db4; // checkbox
    objNode draw:
    Code:
    color = color_type[clamp(type,0,3)]
     
    Last edited: Jan 3, 2017
    NoobsWeStand likes this.
  8. Mick

    Mick Member

    Joined:
    Jun 30, 2016
    Posts:
    686
    Also, @NoobsWeStand, is there a good way to make alternatives in the switches show and hide depending on some value? For example if the player has an item then a switch alternative is shown that otherwise would be hidden.
     
  9. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    Unfortunately, these requests for a more versatile dialog system, where the user can enter anything, is not within the scope of this project.
    Hopefully this video can shed some light on how you might implement such a system:


    This shouldn't be too hard. All you have to do is edit the code around line 66, where it says, "//draw options"
    Here is some example code, so you can compare the two and see the differences:
    Code:
    ///textBox2
    if showText=true{
        var xx,yy,ww,hh;
        xx=global.gui_width-672 yy=global.gui_height-160  ww=382 hh=96
     
        //Draw the box
        draw_set_alpha(0.70)
        draw_set_color(c_black)
        draw_rectangle(xx, yy, xx+ww, yy+hh, false)
        draw_set_alpha(1)
     
        //Draw the Name
        draw_set_valign(fa_top)
        draw_set_halign(fa_center)
        draw_set_font(fnt_chat)
        draw_text_shadow_color(xx+34,yy+10,name, c_aqua)
        xx+=32 ww-=32
    
        //Draw the Main Line
        var p=string_pos("|",line[on0,on1]);//Get rid of the commands
     
        var str="";
        if p=0{
            str=line[on0,on1]
        }else{
            str=string_copy(line[on0,on1],1,p-1)
        }
     
        //typewriter effect
        if dialougeTextOn<string_length(str){
            dialougeTextOn++
            if dialougeTextOn%3==0{
                dialougeTalk=!dialougeTalk
            }
        }else{
            dialougeTalk=0
        }
        str=string_copy(str,1,dialougeTextOn)
        draw_text_shadow_color_ext(xx+(ww/2)-8,yy+28,str,20,ww-44, c_black, c_white)
     
        //Draw options
        if ds_exists(op0[on0,on1],ds_type_list) && ds_list_size(op0[on0,on1])>0{
            var _yy=yy+(string_height_ext(line[on0,on1],25,ww)+60);
            for(i=0;i<ds_list_size(op0[on0,on1]);i++){
                if !scr_GUIhover(xx-32,_yy,xx+ww,_yy+24){
                    draw_set_alpha(0.70)
                    draw_set_color(c_black)
                    draw_rectangle(xx-32, _yy, xx+ww, _yy+20, false)
                    draw_text_shadow_color(xx+(ww/2),_yy,
                    ds_list_find_value(op0[on0,on1],i),merge_color(c_blue,c_aqua,0.5))
                }else{
                    if mouse_check_button(mb_left){
                        draw_set_alpha(0.70)
                        draw_set_color(merge_color(c_dkgray, c_black, 0.75))
                        draw_rectangle(xx-32, _yy, xx+ww, _yy+20, false)
                        draw_text_shadow_color(xx+(ww/2),_yy,
                        ds_list_find_value(op0[on0,on1],i),merge_color(c_blue,c_aqua,0.5))
                    }else{
                        draw_set_alpha(0.70)
                        draw_set_color(merge_color(c_dkgray, c_black, 0.5))
                        draw_rectangle(xx-32, _yy, xx+ww, _yy+20, false)
                        draw_text_shadow_color(xx+(ww/2),_yy,
                        ds_list_find_value(op0[on0,on1],i),merge_color(c_blue,c_aqua,0.5))
                    }
                
                    if mouse_check_button_released(mb_left){
                        scrNPCCDialogOption(i)
                        dialougeTextOn=0
                        break;
                    }
                }
                _yy+=24
            }
        }else{
            //draw the Continue button
            if !scr_GUIhover(xx-32, yy+hh+4, xx+ww, yy+hh+24){
                draw_set_alpha(0.70)
                draw_set_color(c_black)
                draw_rectangle(xx-32, yy+hh+4, xx+ww, yy+hh+24, false)
                draw_text_shadow_color(xx+(ww/2)-16,yy+hh+6,"Click here to continue",merge_color(c_blue,c_aqua,0.5))
            }else{
                if mouse_check_button(mb_left){
                    draw_set_alpha(0.70)
                    draw_set_color(merge_color(c_dkgray, c_black, 0.75))
                    draw_rectangle(xx-32, yy+hh+4, xx+ww, yy+hh+24, false)
                    draw_text_shadow_color(xx+(ww/2)-16,yy+hh+6,"Click here to continue",merge_color(c_blue,c_aqua,0.5))
                }else{
                    draw_set_alpha(0.70)
                    draw_set_color(merge_color(c_dkgray, c_black, 0.5))
                    draw_rectangle(xx-32, yy+hh+4, xx+ww, yy+hh+24, false)
                    draw_text_shadow_color(xx+(ww/2)-16,yy+hh+6,"Click here to continue",merge_color(c_blue,c_aqua,0.5))
                }
                if mouse_check_button_released(mb_left){
                    if dialougeTextOn<string_length(str){
                        dialougeTextOn=string_length(str)
                    }else{
                        scrNPCDialogContinue()
                        dialougeTextOn=0
                    }
                }
            }
        }
    }
    
    draw_set_alpha(1)
    draw_set_color(c_white)
    Here is what it looks like in game:
    [​IMG]



    That is because the checks have to lead to either another switch, or a text box. They cannot only lead to a script that doesn't have anything else connected to it. I will probably make it so you can do that type of behavior later, but for now, you cannot
    Never mind! I just checked and it seems like you can do this, but in your case, you needed your scripts to look like this: "sleep()", instead of "sleep". Although, there might be some weird behaviour if you do not connect the scripts to anything else

    As for the alternative switch statements depending on the player has an item, I would do something like this:
    [​IMG]
    Although right now there is a bug where you cannot have have the convo(questID,QuestON) in an if statement.

    Thanks for the suggestion! I like the colors, and it makes it easier to follow along!

    I will work on the bugs tonight and tomorrow and hopefully fix them all and release a new version soon


    edit: Here is a quick patch. v1.24
    Downloads: exe(3mb) source(716kb) example(185kb)
    Changes:
    -Fixed that bug that would not allow the command "convo(QuestID,QuestON)" to work within an if statement in a script
    -Fixed many graphical bugs
    -Optimizations with larger projects--allows for many more nodes to be present at one time
    -Added in the cool color patch that Mick suggested, and provided code for!
    -Dynamic camera scrolling with zoom level added for arrow keys
    -Update the example to include the save files
     
    Last edited: Jan 11, 2017
    Mick likes this.
  10. TheEnderPrime

    TheEnderPrime Member

    Joined:
    Jan 14, 2017
    Posts:
    1
    Hi! I am trying to add your branching dialogue system into a game I have been working on for a while now. I am hitting some road blocks when it comes to integrating your system. I am wondering if you have a list of your variables and what they do hidden somewhere? For instance, I have a quest variables already but it works differently then yours and I am trying to get them to match up. So if you have any descriptions on your quests variables (checkQuest, checkOn, checkText) these would be immensely helpful to me! Thanks!
     
  11. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    checkQuest, checkOn, and checkText in parNPC are just used for determining which dialog tree to jump to when starting a conversation, based on the quest state. For the most part, you do not have to worry about these variables

    Depending on how yours is set up will determine how hard it is to transfer mine to yours, or vise versa
    As for mine, it is fairly simple and straight forward. All the quest information is stored in an array setup in objControl in the create event as such:
    Code:
    //QuestInfo
    for(i=0;i<100;i++){
        quest[i]=0 //stores the quest info
    }
    
    Each quest state is stored in a position in this array.
    So if I set quest[0]=1, then if an NPC has a "convo" of (0,1), then it will automatically search for the first Node in the conversation

    I am not entirely sure what you needed-- so I hope this helps
     
  12. Buzz Killdrin

    Buzz Killdrin Member

    Joined:
    Jan 27, 2017
    Posts:
    6
    Hi
    I've been planning on using your dialog system for a couple of days now and I'm really excited to replace the dialog code that I have with yours, but the nature of the game I'm working on makes it too convoluted to be able to use your dialog program as-is. I figure I have to adapt it first (as I understand, you're fine with that) but I haven't managed to get a good grasp on the source code for it. The manual is enough to teach me how to play around with the example game you uploaded, but the documentation for the code isn't enough to understand it.

    I wouldn't ask anything like an in depth explanation on how the system works, that's crazy, but if you already posted more info on it somewhere else that would be an awesome read.
     
  13. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    You can do whatever you want with it
    The documentation thing is my fault. I have to comment on everything more - especially with the example
    I am planning on working on it this weekend. I also have BB textbox commands coming up, but it still needs some kinks ironed out
     
    Last edited: Jan 28, 2017
  14. Buzz Killdrin

    Buzz Killdrin Member

    Joined:
    Jan 27, 2017
    Posts:
    6
  15. DonyThePony

    DonyThePony Member

    Joined:
    Jan 29, 2017
    Posts:
    2
    Hey Awesome Thing and it was very easy and clean to install it into my Project.
    I have a Question. Is it possible to colorize some Words or to set some Cool Effects in the Editor? Like Waving etc.

    - DonyThePony
     
  16. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    As stated above, I am working on that right now! The update is coming this week, so keep an eye on this topic
    [​IMG]
    I still have to add waving and shaking text options
     
    mycelia and Mick like this.
  17. mycelia

    mycelia Member

    Joined:
    Jan 31, 2017
    Posts:
    8
    Thanks for the awesome system, and I'm looking forward to the update! Quick question -- I want to have the dialog trigger when the player hits space within a certain distance of the NPC (using distance_to_object), rather than just on collision. I figure it's got something to do with showText and showText2, but I can't for the life of me figure out what to do with them. Any chance you could let me know what I need to change?

    edit: Also, I don't know if anyone's interested, but I prefer a keyboard control system so I added a couple of things to my parNPC script, in the Draw function. It uses X to continue and the number keys to pick dialog options. I'll put it here; I haven't tested it thoroughly but it's working so far. Note that I spell it 'dialogue', so find+replace if you've got the variables and scripts as dialouge.

    Code:
    ///textBox
    event_inherited();
    
    //draw the TextBox
    if showText=true{
        var xx,yy,ww,hh;
        xx=30 yy=global.gui_height-200  ww=350+32 hh=150
        //Fancy outlines
        draw_set_alpha(1)
        draw_set_font(fnt_chat)
        draw_set_alpha(0.8)
        draw_set_color(c_dkgray)
        draw_rectangle(xx,yy,xx+ww,yy+hh,false)
        draw_set_alpha(1)
        draw_set_color(c_black)
        draw_rectangle(xx,yy,xx+ww,yy+hh,true)
      
      
        //Draw the Face
        if dialogueSprite!=-1 && sprite_exists(dialogueSprite){
            draw_sprite(dialogueSprite,dialogueTalk,xx+5,yy+(hh/2)-(sprite_get_height(dialogueSprite)/2))
        }else{
            draw_sprite(sprNPCUnkown,0,xx+5,yy+(hh/2)-(sprite_get_height(dialogueSprite)/2))
        }
      
        //Draw the Name
        draw_set_halign(fa_center)
        draw_set_color(c_black)
        draw_text(xx+5+16+1,yy+(hh/2)+(sprite_get_height(dialogueSprite)/2)+1,name)
        draw_set_color(c_white)
        draw_text(xx+5+16,yy+(hh/2)+(sprite_get_height(dialogueSprite)/2),name)
      
        xx+=32 ww-=32
      
      
        //Draw the Main Line
        var p=string_pos("|",line[on0,on1]);//get rid of the commands
        draw_set_halign(fa_center)
        draw_set_color( c_black );
      
      
        var str="";
        if p=0{
            str=line[on0,on1]
        }else{
            str=string_copy(line[on0,on1],1,p-1)
        }
      
        //typewriter effect
        if dialogueTextOn<string_length(str){
            dialogueTextOn++
            if dialogueTextOn%3==0{
                dialogueTalk=!dialogueTalk
            }
          
        }else{dialogueTalk=0}
        str=string_copy(str,1,dialogueTextOn)
      
        draw_text_ext(xx+(ww/2)+1,yy+16,str,25,ww-xx)
        draw_set_color( c_white );
        draw_text_ext(xx+(ww/2),yy+15,str,25,ww-xx)
      
      
        //draw options
        if ds_exists(op0[on0,on1],ds_type_list) && ds_list_size(op0[on0,on1])>0{
            var _yy=yy+(string_height(line[on0,on1])+30);
          
            for(i=0;i<ds_list_size(op0[on0,on1]);i++){
                currentDialog= string(i+1); //Make the number of dialog options into a string that we can reference in keyboard_check_pressed.
                if !scr_GUIhover(xx+5,_yy,xx+ww-5,_yy+19){
                    draw_text_shadow_color(xx+(ww/2),_yy,
                    ds_list_find_value(op0[on0,on1],i),merge_color(c_blue,c_aqua,0.5))
                    if keyboard_check_pressed(ord(currentDialog)){ //Use the number keys to select an option
    
                        scrNPCCDialogOption(i)
                        dialogueTextOn=0
                        break;
                      
                    }
                }else{
                    if mouse_check_button(mb_left){
                        draw_text_shadow_color(xx+(ww/2),_yy,ds_list_find_value(op0[on0,on1],i),c_white)
                    }else{
                        draw_text_shadow_color(xx+(ww/2),_yy,ds_list_find_value(op0[on0,on1],i),c_ltgray)
                    }
                  
                    if mouse_check_button_released(mb_left){
                        scrNPCCDialogOption(i)
                        dialogueTextOn=0
                        break;
                    }
                }
                _yy+=20
            }
          
        }else{
            //draw the Continue button
            if !scr_GUIhover(xx+5,yy+hh-25,xx+ww-5,yy+hh){
                draw_text_shadow_color(xx+(ww/2),yy+hh-20,"Click here to continue",merge_color(c_blue,c_aqua,0.5))
    
                    if keyboard_check_pressed(ord("X")){ //Keyboard control to advance text
                      
                            if dialogueTextOn<string_length(str){
                            dialogueTextOn=string_length(str)
                                }else{
                            scrNPCDialogContinue()
                            dialogueTextOn=0
                    }
                }
          
            }    else
                {
                    if mouse_check_button(mb_left){
                      draw_text_shadow_color(xx+(ww/2),yy+hh-20,"Click here to continue",c_white)
                    }   else{
                        draw_text_shadow_color(xx+(ww/2),yy+hh-20,"Click here to continue",c_ltgray)
                    }
                    if mouse_check_button_released(mb_left){
                        if dialogueTextOn<string_length(str){
                            dialogueTextOn=string_length(str)
                        }else{
                            scrNPCDialogContinue()
                            dialogueTextOn=0
                    }
                }
            }
        }
      
    }
    
     
    Last edited: Jan 31, 2017
  18. DonyThePony

    DonyThePony Member

    Joined:
    Jan 29, 2017
    Posts:
    2
    Go To your Parent Object of your NPC's
    Then in the Step Event.
    There is an if Statement This one:

    if showText2=true{
    if place_meeting(x,y,Player){

    Change it to:

    if showText2=2{
    if(place_meeting(x,y,Player) && keyboard_check_key_pressed(vk_space))

    This could be the Solution for it.
     
  19. mycelia

    mycelia Member

    Joined:
    Jan 31, 2017
    Posts:
    8
    Thanks, but unfortunately that just makes the text box pop up for a half-second before disappearing. keyboard_check keeps it open for as long as I'm holding it, so I'm thinking that's a clue. I'll keep experimenting.

    edit: Haha! Found it! In the Create event, showText2 is set to true. Changing it to false, along with the fixes as proposed by @DonyThePony, solved it.
     
    Last edited: Jan 31, 2017
  20. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    @mycelia and @DonyThePony
    The reason why there is 2 variables for controlling if the textbox is shown or not, is that if you have a script node containing "showChat", it will cut off the dialog, and stop displaying it. However, the player will most likely still be colliding with the NPC, so it toggles showText2 to false. In order for showText to become true, is if showText2 is true. showText2 can only become true if the player is colliding with the NPC and also presses the space key. This logic can be found in the parNPC in the normal step event.

    As for the distance, instead of colliding with the player, you can simply replace the code in the step event of parNPC with this:
    Code:
    ///DistanceToPlayer
    [IMG]https://www.dropbox.com/s/qrwtpikmna3lzfl/BBText.png?dl=1[/IMG]
    
    var nn=instance_nearest(x,y,objPlayer);
    if showText2=true{
        if point_distance(x,y,nn.x,nn.y)<50{
            showText=true
        }else{
            showText=false
        }
    }else{
        showText=false
        if keyboard_check_released(vk_space)
        && point_distance(x,y,nn.x,nn.y)<50{
            showText2=true
        }
    }

    And there is an update (v1.25)!
    This update mainly focuses on cool new text effects for the text box! These effects work just like they do on the forums. [command=value]Hello World![/command]

    [​IMG]

    Here is the list of commands that can be used (can also be found in the manual):
    [color=c_red]

    Changes the color of the text. You can either use GM’s c_ values, or put your own hex with $ infront of it (eg. $4455ed)

    [font=fnt_name]

    Changes the font. The font must exists in your game as an asset

    [alpha=0.75]

    Changes the alpha value of the text

    [speed=0.1]

    Changes the speed of the typewriter effect

    [waveA=1]

    Changes the wave amplitude

    [waveF=1]

    Changes the wave frequency

    [waveO=25]

    Changes the offset of the wave effect per character

    [shake=1]

    Shake amount in both X+Y

    [shakeX=3]

    Shake amount in only the X direction

    [shakeY=2]

    Shake amount in only the Y direction

    [hsv=1]

    Shifts through the HSV values at the given rate. This will override the [color] tag

    I have also tried to add useful comments in the Example to help people out.

    Downloads:
    Source (720kb)
    EXE (3MB)
    Example (190kb)
     
    Mick likes this.
  21. Mick

    Mick Member

    Joined:
    Jun 30, 2016
    Posts:
    686
    Nice one! Keep up the good work! :)
     
  22. Geoff Jones

    Geoff Jones Member

    Joined:
    Aug 20, 2016
    Posts:
    482
    Will this work in GMS 2.0?
     
  23. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    I have yet to test it with GM2, but I have heard from a couple of friends that it works just fine
     
    Geoff Jones likes this.
  24. KitKatKatu

    KitKatKatu Member

    Joined:
    Feb 5, 2017
    Posts:
    16
    I'm trying to figure something out. What I'm hoping for is:

    Switch: Did you find my glasses?
    1: Yes
    ----------Script: Does the player have glasses in their inventory?
    ----------1: Yes
    --------------------Text: Thank you!
    ----------2: No
    --------------------Text: No, that's not them.
    --------------------Text: They should be somewhere in this room!
    2: No
    Text: They should be somewhere in this room!

    Right now I can get the item to disappear from their inventory, but I don't want them to say "Thank you!" if the item isn't there.
     
    Last edited: Feb 5, 2017
  25. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    Maybe something like this:
    [​IMG]
    Note that you have to "pin" the switch statement, so it starts out there. Otherwise the system will think the text node that says, "No, that's not them." is the first node in the conversation!


    To do this you also have to update to the latest version! I added a label and goto commands for an easier alternative to the confusing "convo" system!
    The above picture should be a great example of how to use them!

    label(str)
    This will set a pointer in the dialog tree, so when you call “goto(str)”, it will automatically find the label, and jump to that Node

    goto(str)
    This will jump to the corresponding label. If the label does not exist, the editor will tell you



    Downloads:
    EXE (3mb)
    Source (720kb)
    Example (190kb)
     
    Last edited: Feb 8, 2017
    KitKatKatu likes this.
  26. Buzz Killdrin

    Buzz Killdrin Member

    Joined:
    Jan 27, 2017
    Posts:
    6
    Possible dumb question
    Is this how your dialog system finds it's next 2d array row positions?

    EBDS.jpg

    As the text suggests, I'm thinking that array row index progression follows the first option in every branch until the branching stops, then moves to the next branch. At that point the row index skips a number, presumably so that the algorithm knows the branch ended (?).

    To clarify, all the numbered nodes in the tree are switch nodes so it's implied that the column index of the 2d array of each node is 0.
     
  27. KitKatKatu

    KitKatKatu Member

    Joined:
    Feb 5, 2017
    Posts:
    16
    Thank you so much!! Yes, I think this will do the trick!
     
  28. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    That is almost exactly how it does it! Although, it uses a much simpler system to find when the branching stops, and when to move to the next branch.

    As you know, everything is stored in a 2D array. text[on0,on1]. When you click the "continue" button, for a non-branching dialog option, then it will simply increment on0 by one. If text[on0+1,on1] does not contain anything, then the NPC will stop talking, and the interface will close.

    If there is a branch in the dialog, then it will reset on0 to 0, and in on1 will then increment by one.
    The example and Dialog editor have no idea where it will go next. All they do is follow some very simple instructions. When there is a branching dialog option, the editor will export which line to jump to, and all they have to do is follow it
    You can actually open up what the dialog editor exports and read how it works
     
  29. Buzz Killdrin

    Buzz Killdrin Member

    Joined:
    Jan 27, 2017
    Posts:
    6
    Sweet
    Also thanks for the text labeling system you showed KitKatKatu, that makes conditional dialog replies much more convenient than what I was about to try.
    One thing I've noticed about it though is that, if you link a branch that's not connected directly to the main tree from the out of the last node in it with the in of a switch node that's supposed to be accessed before said branch, like the "no, that's not them" branch is looped back to the "did you find my glasses" switch node, and you have more than 1 'if' statement nodes that directs to multiple unconnected branches through different labels, the text line that will be displayed is the one in the last unconnected branch that loops back into the switch node --- if the 'loose' branches don't loop back to the switch node, or if only the first one does, then the dialog works correctly.

    I managed to make word salad of the post so hopefully a screen shot will make better sense
    Nodes 0,8 through 0,5 are what I referred to as 'loose' nodes that aren't part of the main dialog tree, like node 0,4 in KitKatKatu's example. In the screenshot all 4 are looped back into a start-of-dialog switch node that isn't visible in the pic. When they are looped like this, only the the bottom branch is displayed, the one with label(outcome5) -- if I 'unloop', say, the 4th branch, then only the branch that comes before it will be displayed, and so on.
    So I'm wondering if I'm doing something wrong or if adding successive if statements like I did with scr_condition2,3,4,5 is outside the scope of the program.
    EBDS2.jpg EBDS2.jpg
     
  30. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    At first look, this might be a bug with exporting. I will take a look at it tomorrow, and see what is up. I think it should work, but I am not entirely sure why it is not working for you
    If you could also give me the file (through PM), that would also help greatly!
     
  31. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    Okay! Update time! v1.26!

    Downloads:
    EXE (3mb)
    Source (725kb)
    Example (200kb)

    [​IMG]

    Added)
    -Syntax Highlighting for scripts and text (can be disabled with options)
    -Highlight which text Node the dialog editor is one when testing
    -New variable system and [var=xxx] tags!
    -Go to Options -> Change Variables to access this new feature
    -Just a simple DS Map, but it can be used for a more dynamic dialog system
    -Example: Hello [var=playerName], my name is Bob!
    -You can also change the variables in the ds_map with simple scripts!
    -Example: playerName="Bob"
    playerMoney+=999
    -You can also check what is inside the ds_map with scripts:
    -Example: if playerMoney<100{playerMoney+=1000}

    Fixed)
    -Fixed the previously stated bug


    Note: to get the value of the variables inside the NPC, just do:
    chatMap[?key], where "key" is your variable name
    To set the variables outside the dialog, you can simply do chatMap[?key]=value


    Also, I have to get better at this, but these are the objects/scripts you need to update in your current project to get all these new features!
    draw_text_bb_ext_black_centered
    draw_text_bb_ext_centered
    load_npcChat
    scr_npcDialogCommands
    parNPC - Create Event ADD: chatMap=ds_map_create()
     
    Last edited: Feb 21, 2017
    Quailfail and Buzz Killdrin like this.
  32. Frioniel

    Frioniel Member

    Joined:
    Feb 24, 2017
    Posts:
    2
    Hi, I'm using your script very well, but I got some problem

    First is, can this system print different languages? such as japanese or chinese or korean

    Second is, can I make dialogue with the object?(using Uses Physics function from GameMaker)
    Well.. this one is the very basic problem using GameMaker not this system... (I used GameMaker only 6days...)
    What I tried is.. meet Player in front of NPC, press button to talk.
    For example, if space key pressed and Player's x position is NPC's x position - 32
    then the textbox needs to appear, but didn't appear

    are there any ways to solve this two problem?
    -----------------------------------------------------------------------

    After this post

    I tried korean (my native language is korean)

    Korean can be printed but some words don't print well, it prints blank

    is it keyboard-string bug or i need to find out what is the problem
     
    Last edited: Feb 25, 2017
  33. shuikun0

    shuikun0 Member

    Joined:
    Feb 25, 2017
    Posts:
    11
    This do support CJK languages. As long as you have add the characters in the font. BTW, the draw_string_ext function in GMS doesn't support CJK for some reason. If you wanna know more about using CJK languages in GMS, I highly recommed you see this https://forum.yoyogames.com/index.php?threads/localizing-for-chinese.1555/.
    Hope that can help you some how. Sorry for my poor English.
     
    NoobsWeStand likes this.
  34. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    You could try to edit your fonts so that it includes a wider range of characters:
    [​IMG]
    It looks like the Korean ascii values are from 40,000 to 50,000, although I am not entirely sure
    You can also try font_add()

    If you can get it to work, PM me or something. I will try to get it to work later this week
     
  35. Frioniel

    Frioniel Member

    Joined:
    Feb 24, 2017
    Posts:
    2
    Thanks for the reply!
    After your reply what I did is
    try with font_add() and add code where fnt_default works
    (I tried both, otf and ttf version of font)
    4.png
    3.png
    and I'm sad to say, it still not prints well
    *Explanation
    7.png
    this reply system indicates Korean as spam something so I replace with image

    Also, has serious frame drop

    minFPS, maxFPS, avgFPS
    0, 73, 7

    I think Korean Ascii is 44032~55203, there are too many words to compile, so it causes frame drop

    After this, I tried the first one that you suggested in reply (add Ascii number to the font)

    Actually, I tried before your reply(add Ascii number to the font)

    what I really did is, I thought too many unnecessary Korean words between 44032~55203 causes missing words
    6.png
    so I just add few words
    and the result is.. sadly

    5.png
    still, have missing words

    Well.... I need to find out more ways to solve out, and this is what I did best to solve the problem currently
     
    Last edited: Feb 27, 2017
  36. Marmaduke

    Marmaduke Member

    Joined:
    Feb 27, 2017
    Posts:
    1
    Hi I've been using your script recently and it's great! However when I tried to have to separate NPC's in the same room with their own dialogue it doesn't seem to work. The NPC that I place down first (and that gets loaded by the game first I assume) has the dialogue working fine but when I go to the second one the dialogue box pops open for a second and then closes. I can see the text is correct but it just wont stay open. I realise this is probably me making a stupid mistake and so would appreciate if you could help me out if you know of any solution. Thanks!
     
  37. hoyakim

    hoyakim Member

    Joined:
    Oct 14, 2016
    Posts:
    9
    hi Frioniel.
    I am glad to meet Korean people.
    I also used this tool and experienced the same problem.

    The problems and solutions are as follows.
    Problem: Korean input can not be handled properly by game maker... This problem is not a problem with this tool.

    Solutions :
    Add Korean font to the source and recompile it. => Not displayed in an item such as an answer is displayed!
    But The character is still missing during Korean input...
    first In a program such as Notepad, write, copy and paste.

    I solved it this way. It is a little inconvenient, but it is a problem of the GMS itself.
     
  38. Quailfail

    Quailfail Member

    Joined:
    Mar 4, 2017
    Posts:
    37
    Firstly, want to say thank you for the lovely dialogue branch engine, I have been experimenting with it but have been running into a few issues.

    When Player collides into the NPC to chat, the first conversation goes well, but after the dialogue is finished and Player collides again to start a new conversation, it does not start up. Neither the dialogue that comes up when a Quest is unfinished or the dialogue when a Quest is finished will show. I've noticed if I skip the 1st dialogue that would "start" the Quest and just finish said Quest the 2nd dialogue (for completion) will pop up. I think there might be something amiss with collision as I can only get one conversation to happen per test run.

    I will admit I am very new to this engine, I'm sorry if I'm asking anything that has an obvious answer.
     
  39. shuikun0

    shuikun0 Member

    Joined:
    Feb 25, 2017
    Posts:
    11
    Chinese works with no problem so Korean should be no problem. What l do is write all character in somewhere of the code and then click the plus button in font, choose add from code. Hope that helps.
     
  40. Team Shinigami

    Team Shinigami Member

    Joined:
    Mar 26, 2017
    Posts:
    3
    Hi, quick question:

    I copied all of the scripts in the Dialogue section into my game, but it gives me an error:
    Code:
    ERROR!!! :: ############################################################################################
    FATAL ERROR in
    action number 1
    of Alarm Event for alarm 0
    for object parNPC:
    
    
    global variable <unknown built-in variable>(-1610512734, -2147483648) not set before reading it.
     at gml_Script_load_npcChat (line 2) - if !file_exists(global.NPCdirectory+"\"+string(argument[0])+".txt"){return 0}
    ############################################################################################
    --------------------------------------------------------------------------------------------
    stack frame is
    gml_Script_load_npcChat (line 2)
    called from - gml_Object_parNPC_ObjAlarm0_1 (line 8) - if load_npcChat(pid) = 1{
    I was wondering how I would be able to fix it? It is stopping me from progressing further into my game, and it would be greatly appreciated if you could take some time to help me.

    --Team Shinigami
     
  41. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    I believe you have to set global.NPCdirectory.
    By default, it should look something like this:
    Code:
    //The directory to store the exported .txt files
    global.NPCdirectory="Dialog/"
    This is just for organizational reasons-- to put all your dialog.txt's into a single folder

    A better place to copy all the scripts from would be the Example project that is provided. Those are more clearly commented, and does not have the extra fluff of the editor stacked on top of it
     
  42. Team Shinigami

    Team Shinigami Member

    Joined:
    Mar 26, 2017
    Posts:
    3
    Thanks!

    I was thinking about making a monologue in this system, is it doable?
     
  43. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    I would think so - You would just use the text Node, and just have that connected to other text Nodes - with no branching
    Unless you want a branching monologue

    You might have to do more explaining on what you want your monologue to do
     
  44. Team Shinigami

    Team Shinigami Member

    Joined:
    Mar 26, 2017
    Posts:
    3
    I was just thinking about doing an introduction, kind of like the ones in Danganronpa
     
  45. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    I see.
    It might just be easier to make an array that stores your text, and then have a variable that ticks up every time you continue in the dialog

    This program is for more complicated stuff; like giving the player choices, and then executing some scripts based off those decisions
    Branching dialog can quickly get out of hand, and manually coding it can get confusing. This is mainly an easy way of visualizing your dialog trees, and testing your dialog trees

    If you are doing something as simple as a monologue, then it would be easier to code it yourself. If you need helping coding something like that, you can PM me, and I can help you there!
     
  46. mycelia

    mycelia Member

    Joined:
    Jan 31, 2017
    Posts:
    8
    Oh sweet, updates! Thanks for all your hard work @NoobsWeStand, this system is amazing.

    One question, the answer for which is probably obvious but I can't seem to figure it out: if I want a conversation to restart from the beginning the next time I approach the same NPC, how do I do that?
     
  47. Quailfail

    Quailfail Member

    Joined:
    Mar 4, 2017
    Posts:
    37
    Ah, I know this one! Your last node after the finishing text needs to be a script node. Write convo(?,?) the "?" replaced with whatever you named your QuestID and QuestON. Like this,

    Untitled.png
     
    NoobsWeStand and mycelia like this.
  48. NoobsWeStand

    NoobsWeStand Member

    Joined:
    Jun 20, 2016
    Posts:
    143
    Or you can simply do something like this, if you do not want to deal with the convo system:
    [​IMG]
    Just make sure you pin the first node, so that the dialog editor knows where to begin
     
    Meowanator and mycelia like this.
  49. mycelia

    mycelia Member

    Joined:
    Jan 31, 2017
    Posts:
    8
    Thanks guys, you rock :)
     
  50. Quailfail

    Quailfail Member

    Joined:
    Mar 4, 2017
    Posts:
    37
    No problem, mycelia!

    I hope it's alright to show everyone what I'm using this lovely text engine in,
    scrsht008.png

    I've been steadily tweaking the text box and come across a few issues. Such as wanting to slow down the typewriting speed. I found this:
    Code:
    textSpeed=1;             //speed at which text typwriter effect goes. Can be changed with [speed=x] tags
    Where do I put the speed tag? As putting in the parNPC code will just make said npc start moving, not the text itself. Changing the number on textSpeed doesn't seem to affect it either.
     
    NoobsWeStand likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice