GML [SOLVED] Automatic shift-back behavior not working correctly. (ds_list/dialogue system)

Discussion in 'Programming' started by Dr_Nomz, Feb 23, 2019.

  1. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    I was playing around with DS_lists and figured out how to use them for my dialogue system, but now I don't know how to control the behavior of it.

    Basically the way it works is I send the ds_list information to a script which displays the text on screen based on the ds_list's number, so if ds_list_find_value returns a 2, it'll appear 200 pixels from the bottom.

    Problem is when I click on it it's supposed to delete the option and move all the other options down, but it's not doing that.

    Instead it's sending ALL the options up and only removing them when I click on one at the top, and it's not deleting the right ones.

    Here are my project files, relevant scripts and object are clearly marked:

    https://www.mediafire.com/file/7dmozrcvzc7ia3f/dialogue_test_1_3.gmz/file

    Note that option 0 is using different code because it has different behavior, so just ignore that one.
     
    Last edited: Feb 25, 2019
  2. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
  3. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512

    Just made a video showing what it's doing.

    The left text in Dark Green is the list's value, and the right text in Light Green is the position, but it keeps deleting the wrong positions. Why is that?

    Here's the code that handles the values and drawing it using a script:
    Code:
    if !is_undefined(ds_list_find_value(option,1)){
      var number1 = ds_list_find_value(option,1);
      var position1 = ds_list_find_index(option,1);
      show_debug_message(number1);
      scr_Dialogue6(number1,position1,"test",scr_DB5,2);}
    And when that button is clicked on this script is run:
    Code:
    //argument0 = ds_list_find_value(option,#); argument0 of last script
    //argument1 = ds_list index
    //argument2 = Line number, changes NPC's dialogue; argument3 of last script
    if !is_undefined(argument0){
    hide[argument0]=0;
    lines=argument2;
    ds_list_delete(option,argument1);
    for (o=argument1; o<ds_list_size(option); o++){
      ds_list_replace(option,o,o-1)
    }
    }
     
  4. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    People don't like downloading files. That's why the rules state to post code and only upload files when requested.

    First off, still not sure why you are hard-coding your numbers, unless this is just for testing purposes. But it also shows you don't know what you're doing with the list functions.

    if !is_undefined() is fine if you have no way of knowing if an index the list exists when you are looking up a value in the list, but there is never any reason to not know in your case if an index exists. If the value you are looking for is LESS THAN ds_list_size(option), then it's definitely not undefined. And once you get things up and running correctly, that will never be an issue.

    You also don't need to use any function other than ds_list_create() and ds_list_delete(). All the other ds_list* functions are unnecessary in your situation.

    The function ds_list_delete() automatically resizes the list. If you compare the value of ds_list_size() before and after ds_list_delete(), you'll see that the size of the list has gone down.
    I am assuming, without downloading the file, that you have something like an array or whatever of everything that the dialogue can show, so your list is holding the indexes of the array; thus your list probably contains just numbers in it, right? So if you list looks like this originally:
    Code:
    0
    1
    2
    3
    4
    and you try to delete, say, "3" from the list using ds_list_delete(option,3), then the contents of index 4 ("4") will now become the contents of index 3 and index 4 will be deleted. So now your list will be
    Code:
    0
    1
    2
    4
    Your block there with ds_list_replace(), which is utterly unnecessary, is now overwriting your list's values. If you pass "3" as argument1 in this case, then your loop will say
    Code:
    option[|3]=2
    So now your list is
    Code:
    0
    1
    2
    2
    The ds_list_find_value() function is simply listname[|index] with a vertical line nestled between the first bracket and the index. So consider this example line of code:
    Code:
    cat = option[|0];
    That line of code is the same as cat=ds_list_find_value(option,0). That line of code will take the value found at index 0 of the option list and store it in a variable cat.

    So you have ds_list_find_value(option,1) and that's going to tell you the value stored at index 1 (which is 1). Then you have ds_list_find_index(option,1), which is going to tell you the index that has a value of "1".

    So now let's look at your debugging data. At first the numbers match up: index 0 has value 0, index 1 has value 1, index 2 has value 2, and so on. When you click on an option, it deletes it from the list. In this case, you deleted option 1. So now your list is actually:
    Code:
    0
    2
    3
    4
    5
    But then you have your garbage ds_list_replace() loop in there, which rewrites everything from index 1 onward to this:
    Code:
    0
    0    //1-1 = 0
    1    //2-1 = 1
    2    //3-1 = 2
    3    //4-1 = 3
    What your debug information on the right is telling you now is that "0" is at index 0 still (because you never touched it), "1" is at index 2, "2" is at index 3, "3" is at index 4, and that there is no index with a value of "4".

    You can find out what option the player clicked on by comparing the mouse's coordinates to where the options will be. For example, let's say your dialogue options are 480 pixels wide and each one is 128 pixels high and you're just drawing it in the room with no views or anything like that to make this more complicated than it is (LOL):
    Code:
    var size = ds_list_size(option);
    var overOption = (mouse_y - room_height-128*size) div 128;
        if overOption < size && overOption > -1 {
            var choice = option[|overOption];
            ds_list_delete(option,overOption);
            return choice;
        }
    }
    return undefined;
    
    The value returned by that script would be the index in your dialogue array that the player chose.
     
    Dr_Nomz likes this.
  5. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    If nothing else I at least understand that index and value are treated as basically the same, which sucks because if I could just control both the position and value (like with replace...) I don't think I'd have this problem.

    Here's what I'm trying to do, using my code:
    Code:
    ///DRAW
    if !is_undefined(option[|3]){
      scr_Dialogue5(option[|3],"test3",scr_DB5,2); }
    If I delete the option, it'll be undefined eventually and crash the game, so that "!is_undefined" function is mandatory in this case.
    And what this does is it creates a script that displays the option based on it's value. (in this case, a ds_list for automatic shift-back behavior) so 1 will place it above the "goodbye" option, and 5 would place it just under the NPC dialogue.
    The String is what the text is going to be in the option, so I can change it manually at any time.
    The script being passed through is what happens when it's clicked on. (Needs to be a different script sometimes for certain options, you know.)
    And the last value is what the NPC is saying, so if it gets set to 2 it'll change the NPC's lines elsewhere. (This part works fine)

    Code:
    ///scr_Dialogue5(number,dialogue,script,line)
    //argument0 = ds_list_find_value(option,#)
    //argument1 = String, "Hello"
    //argument2 = script, scr_DB5
    //argument3 = Line to set.
    var color=c_black;
    var xx = view_xview[0];
    var yy = view_yview[0];
    
    draw_sprite(spr_Dialogue_Box,0,xx,yy+700-(100*argument0));
    if(point_in_rectangle(mouse_x,mouse_y,xx,yy+700-(100*argument0),xx+500,yy+800-(100*argument0))){
      draw_set_alpha(0.5);
      draw_set_color(c_white);
      draw_rectangle(xx,yy+700-(100*argument0),xx+500,yy+800-(100*argument0),0);
      draw_set_alpha(1);
      if(mouse_check_button_pressed(mb_left)) && click_buffer<0{
        click_buffer=1;
        script_execute(argument2,argument0,argument3)
      }
    }
    draw_set_font(fnt_3);
    draw_set_colour(color);
    draw_text(xx+10,yy+700-(100*argument0),argument1);
    Here is how it all works: the first thing passed through is the value, it displays where the button is and where you can click on it, so no matter what the value is, it should always function correctly.
    The second argument is used at the bottom of the script, just for displaying the text. Again displayed in the correct position based on argument0.
    Third argument is the script, as seen in the script_execute part.
    And the final argument is what line to set, which isn't really important right now.

    Code:
    ///scr_DB5(value,line)
    //argument0 = ds_list_find_value(option,#); argument0 of last script
    //argument1 = Line number, changes NPC's dialogue; argument3 of last script
    if !is_undefined(argument0){
    hide[0]=argument0;
    lines=argument1;
    for (o=argument0; o<ds_list_size(option); o++){
      ds_list_replace(option,o,o-1)
    }
    }
    And this is what happens when it's clicked on. argument0 is the display variable (or the list, in this case) and argument1 is for the lines, but that part isn't important right now. (Since that part works fine.)
    So what THIS should be doing is deleting the value from earlier, then replacing every value above it with 1 minus their current position, which shifts them into the previous position of the clicked on option, and every other one follows suit, so no empty spaces are between any of the options.

    So is what I'm trying to do possible? Because these lists don't seem to work at all.
     
  6. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    How are you determining what text gets displayed for each line? Right now your code, regardless of whether it works as intended or not, seems pretty inflexible. Your demo animation showed multiple dialogue options with different texts. What was the actual code you used for that entire demo clip? I don't want a "sample" of your code, I want the actual full code you used. Because I'm pretty sure lists are the way to go and you are just going about everything all wrong in this situation.
     
    Dr_Nomz likes this.
  7. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    Alright, well that's all the scripts I use up top with full explanations, so here's the object's code:
    Code:
    ///CREATE
    ///List Dialogue System
    hide_self=1;
    lines=0;
    dialogue=0;
    click_buffer=0;
    option = ds_list_create();
    ds_list_add(option,0);
    ds_list_add(option,1);
    ds_list_add(option,2);
    ds_list_add(option,3);
    ds_list_add(option,4);
    ds_list_add(option,5);
    hide[0]=0;
    hide[1]=0;
    hide[2]=0;
    hide[3]=0;
    hide[4]=0;
    hide[5]=0;
    
    ///DRAW
    var color=c_black;
    var xx = view_xview[0];
    var yy = view_yview[0];
    click_buffer-=1;
    
    if hide_self=1{
    
    draw_sprite(spr_Dialogue_Blue,0,xx,yy);
    draw_set_font(fnt_3);
    draw_set_colour(c_navy);
    if lines=0{
    draw_text(xx+12,yy+5,'Hi?');
    }
    if lines=1{
    draw_text(xx+12,yy+5,"Nice to see you.");
    }
    if lines=2{
    draw_text(xx+12,yy+5,"See you later.");
    }
    if lines=3{
    draw_text(xx+12,yy+5,"Yes it is.");
    }
    
    /*if is_undefined(ds_list_find_value(option,0)){
      ds_list_replace(option,0,0);}
    if is_undefined(ds_list_find_value(option,1)){
      ds_list_replace(option,1,1);}
    if ds_list_find_value(option,0)!=0{
      ds_list_replace(option,0,0); }
    if ds_list_find_value(option,1)!=1{
      ds_list_replace(option,1,1); }
    if ds_list_find_value(option,2)!=2{
      ds_list_replace(option,2,2); }*/
    
    //Draws the position of the list on the right,
    //and value of the list positions on the left. For debugging.
    draw_set_color(c_green)
    draw_set_font(fnt_3);
    draw_text(x+400,y+100,ds_list_find_value(option,0))
    draw_text(x+400,y+120,ds_list_find_value(option,1))
    draw_text(x+400,y+140,ds_list_find_value(option,2))
    draw_text(x+400,y+160,ds_list_find_value(option,3))
    draw_text(x+400,y+180,ds_list_find_value(option,4))
    draw_text(x+400,y+200,ds_list_find_value(option,5))
    draw_set_color(c_lime)
    draw_text(x+430,y+100,ds_list_find_index(option,0))
    draw_text(x+430,y+120,ds_list_find_index(option,1))
    draw_text(x+430,y+140,ds_list_find_index(option,2))
    draw_text(x+430,y+160,ds_list_find_index(option,3))
    draw_text(x+430,y+180,ds_list_find_index(option,4))
    draw_text(x+430,y+200,ds_list_find_index(option,5))
    
    switch(dialogue){
    case 0:{
      scr_Dialogue3(0,"Hello!",scr_DB,0,1);
    //1
    if !is_undefined(option[|1]){
      //var number1 = ds_list_find_value(option,1);
      //var position1 = ds_list_find_index(option,1);
      scr_Dialogue5(option[|1],"test1",scr_DB5,2); }
    //2
    if !is_undefined(option[|2]){
      scr_Dialogue5(option[|2],"test2",scr_DB5,2); }
    //3
    if !is_undefined(option[|3]){
      scr_Dialogue5(option[|3],"test3",scr_DB5,2); }
    /*
    
     && ds_list_find_value(option,3)=3
    
    if !is_undefined(ds_list_find_value(option,1)){
      scr_Dialogue3(ds_list_find_value(option,1),"Goobye",scr_DB2,1,1);}
    if !is_undefined(ds_list_find_value(option,2)){
      scr_Dialogue3(ds_list_find_value(option,2),"Wonderful weather we're having.",scr_DB2,2,2);}
    scr_Dialogue3(ds_list_find_value(option,3),"hm",scr_DB2,3,3);
    scr_Dialogue3(ds_list_find_value(option,4),"hello",scr_DB2,4,4);
    scr_Dialogue3(ds_list_find_value(option,5),"test",scr_DB2,5,5);*/
    }
    }
    }//THIS ONE IS THE END THING KEEP IT AT THE END OF THIS CODE BLOCK.
    
    /*
    for(var yy=0; yy<7; yy++){
      //draw_sprite(spr_Color,0,x+10,yy*110);
      scr_Dialogue(yy);
      }
    
    I included my notes as well.
     
  8. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    Okay, let's stop and take a look at this piece of the code, since it shows your mind is not in the right place. Eventually your dialogue system will get even more complex, no doubt, but first you need to get in the right mindset. What you have here is aa clear example of hard-coding the dialogue. This method seems like it should be simple to implement, but it's really one of the most unguainly, difficult ways to do anything. Look at how much code you have so far for just ONE character. Now think about how things are going to be when you add 20 or 30 or 100 more characters with dialogues. Or If you want to add or remove dialogue in any character. So forget everything you have so far. Wipe your mind clean. Start over from scratch, figuratively speaking.

    First off, your list of all available options should be in an array that you define in the Create Event -- or better still, in the instance creation code in the Room Editor so you don't have 500 nearly-identical objects cluttering your project. The same rule of thumb applies to the NPC's speech also. You could also use a text file to hold all the dialogue, but that is slower to execute.
    Code:
    player_options[0] = "Goodbye for now."
    player_options[1] = "Who are you?"
    player_options[2] = "What do you know about Michael Bay?"
    player_options[3] = "So I heard you like big explosions."
    player_options[4] = "Who were you talking to just now?"
    player_options[5] = "I don't believe  you."
    You can create your ds_list in the Create Event, but after you define the player's options array, you can add which options will be available by default to the list by simply putting the index to the array.
    Code:
    ///Create Event
    choices = ds_list_create();
    Code:
    ///Instance Creation Code
    sprite_index = spr_NPC_Cowboy;     //You can have 1 NPC object and individualize it like this so your project stays clean
    
    player_options[0] = "Goodbye for now."
    player_options[1] = "Who are you?"
    player_options[2] = "What do you know about Michael Bay?"
    player_options[3] = "So I heard you like big explosions."
    player_options[4] = "Who were you talking to just now?"
    player_options[5] = "I don't believe  you."
    
    choices[|0] = 0;
    choices[|1] = 2;
    choices[|2] = 3;
    choices[|3] = 1;
    Do you see how this is much more flexible? You defined everything that can be customized in one place that is specific to instances and won't be applied generally to all objects. What will be applied to all objects is how the dialogue is displayed and handled. Furthermore, you can write up your array in ANY order you want (you should leave the goodbye at 0 and I'll get into that in a moment) as the thoughts come to you and then reference each dialogue option in the list in any order you want. When I wrote up the array, "What do you know about Michael Bay?" popped into my head before "So I heard you like big explosions," but when I was adding the options to the list of choices, I decided "So I heard..." would be better situated closer to the top of choices. Also notice how I have 6 options defined in the array, but only 4 dialogue choices in the list. As the dialogue progresses, you might want to change the options available. For example, I could have left option 2 out of the choices completely and then made it so after the player says to the NPC, "So I heard you like big explosions," the NPC could respond with something like, "Oh yeah! They're great!" And then add option 2 to the list of choices, so then the player could ask the NPC what he knows about Michael Bay.

    The order of the choices in the list goes along with how you were drawing things. The goodbye should be at the bottom of the dialogue, right? So since the position in the dialogue is defined as 700-100n, then the option at the bottom should be at index 0 in the list. That means the choice at the top of the list is the one in the highest index. You draw each of the choices by using a FOR loop to loop through the entire list.
    if(point_in_rectangle(mouse_x,mouse_y,xx,yy+700-(100*argument0),xx+500,yy+800-(100*argument0)))
    Code:
    var list_size = ds_list_size(choices);
    if median(mouse_x,xx,xx+500)==mouse_x && median(mouse_y,yy+700-100*list_size, yy+800-100*list_size)==mouse_y
        var hilite = (800 - mouse_y) div 100;
    else
        var hilite = noone;
    draw_set_font(fnt_3);
    draw_set_colour(color);
    for(var i=0; i<list_size; i++) {
        draw_sprite(spr_Dialogue_Box,0,xx,yy+700-(100*i));
        if i == hilite {
              draw_set_alpha(0.5);
              draw_set_color(c_white);
              draw_rectangle(xx,yy+700-(100*i),xx+500,yy+800-(100*i),0);
              draw_set_alpha(1);
              draw_set_colour(color);
        }
        draw_text(xx+10,yy+700-(100*i), player_options[ choices[|i] ]);
    }
    Notice I just loop through the list without any is_undefined checks anywhere. That's because is_undefined is not necessary if you do things the right way in the right order. Even if you delete something from the list, the size of the list will be updated automatically. Your code needed is_undefined because you weren't using the list properly at all. What you were trying to do with your list was just nonsensical and thus errors were cropping up that were getting ignored with an is_undefined check, but not getting resolved. I also changed up the code a bit so the mouse checking can be handled with the draw loop. This isn't necessarily better, it's just how I'd handle it. Since the dialogue box sprite gets draw first and then the rectangle and then the text, it made more sense to me to just draw them all at the same time.

    Deleting the options from the list as they get clicked on is pretty much what you got the hang of already, but with the inclusion of a permanent goodbye option, you want to make sure it doesn't get deleted, or at the very least make sure it gets added back in.
    Code:
    if median(mouse_x,xx,xx+500)==mouse_x && median(mouse_y,yy+700-100*list_size, yy+800-100*list_size)==mouse_y
        var hilite = (800 - mouse_y) div 100;
    else
        var hilite = noone;
    if hilite > 0 {
        ds_list_delete(choices, hilite);
        Do whatever that dialogue option should do
    }
    else
    if hilite == 0
        {close the dialogue box and restore control of the player}
    
    As far as defining what each dialogue option should do, I'm not really fluent on that kind of coding logic, to be honest. Again, I'd try to implement an additional array defined in the Instance Creation Code.
     
    Dr_Nomz likes this.
  9. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    Hey I just tried to use your code but all it did was draw the options. Which it did a good job of, but the hilite and option selection did nothing.

    Note: I put all of what you posted into the draw event, didn't turn any of it into scripts.

    Granted, I didn't bother coding what happens if you click on it, but:
    Code:
    if hilite > 0 {
        ds_list_delete(choices, hilite);
        //Do whatever that dialogue option should do
    }
    else
    if hilite == 0{
      //close the dialogue box and restore control of the player
      }
    that shouldn't affect the hilite should it?

    Also tried to make it do something, but the clicking doesn't even seem to do anything.

    When I did that I added in the vars you left out initially:
    Code:
    var xx = view_xview[0];
    var yy = view_yview[0];
    var color=c_black;
    You did write it with those in mind, right?

    EDIT: Apparently 500 pixels above the bottom of the screen (so yy+300) if you hover over that part of the screen you can make something happen, but not in any other case. I don't know why but maybe it'll help you.
     
    Last edited: Mar 12, 2019
  10. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    Can someone just tell me how the ds_list is behaving already? That's the whole reason this isn't working and if someone just explains to me what it's doing I can probably just fix it myself.
     
  11. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    Wow this post didn't show up as unread for me at all yesterday.

    The last block of code (that deletes options) is for the Step Event, which is why hilite is set again there.

    Also I think it is because i left out yy from the formula for yy. I was simplifying formulas in my head near the end.

    hilite = (yy+800-mouse_y) div 100;

    Make sure you change both locations. If that doesn't fix it, I will have to debug it later tonight, because it worked on my calculator.
     
    Dr_Nomz likes this.
  12. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    It didn't work, and when I moved that other code into the Step event it stopped drawing entirely. When you get it working please send me the GMZ or whatever so I can look over the whole thing. (I'm using GMS 1.4 if that's important)
     
  13. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    omfg I did it single handedly. It only took me over a month at least just to figure out one issue...
    Code:
    ///scr_DB6(placement,line)
    //argument0 = ds_list_find_value(option,#); argument0 of last script (AKA where it is in the list.)
    //argument2 = Line number, changes NPC's dialogue; argument3 of last script
    if !is_undefined(argument1){
    //hide[argument0]=-1;
    lines=argument2;
    ds_list_delete(option,argument0);
    for (o=argument0; o<ds_list_size(option); o++){
      ds_list_replace(option,o,option[|o]-2);
      }
    }
    But I basically just threw code against the wall and used whatever would stick, which yeah I understand SOME things here, but wtf? Why is THIS working?

    Seriously could someone tell me EXACTLY what this code is doing? Because I'm a little lost. (argument0 is just the lists position, sent through the script by hand so as not to make any mistakes.)
     
  14. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    Are you sure that's working right? With the "-2" that should be making a list like
    0
    1
    2
    3
    4
    5
    after deleting index 3 become
    0
    1
    2
    2
    3

    But anyway, the difference between this current line and its previous attempt is previously you replaced the list with the value of o-1; in the current version you're replacing the list with the value in the list -2.
     
    Dr_Nomz likes this.
  15. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    Anyway, as I wrote the code into GM for myself, I realized I messed up a couple things.

    First off, I changed hilite to a global variable. In this situation, I set it to noone in the Create Event of the NPC, but technically it should be set elsewhere at the start of the game. Still, it shouldn't cause any issues if you forget that. I also have a show_dialogue variable in here, but it's just the variable that tells the NPC he's talking to the player.
    Code:
    choices = ds_list_create();
    color = c_black;
    global.hilite = noone;
    //I made hilite a global variable
    
    show_dialogue = 0;     
    //This is just to tell the Draw Event the dialogue is open.
    //You should have other stuff disabling player movement too, but this is just a demo.
    I restricted the Step Event code to only run when show_dialogue is true (makes sense) and the setting of global.hilite is handled only in the Step Event now for speed considerations. As I mentioned earlier, I had messed up the formula for hilite by leaving out yy, so I added that in properly. Also the mouse check was restricted to an area 100 pixels high at first; this was wrong and I revised it so the mouse check is the whole size of the dialogue box. I also put the mouse button check so it only deletes choices or closes the dialogue box when the mouse is clicked on a choice. Yeah, that would have helped earlier. LOL
    Code:
    if show_dialogue {
        var xx = view_xview[0], yy = view_yview[0], list_size = ds_list_size(choices);
        if median(mouse_x,xx,xx+500)==mouse_x && median(mouse_y,yy+700-100*list_size, yy+800)==mouse_y
            global.hilite = (yy+800 - mouse_y) div 100;
        else
            global.hilite = noone;
    
        if mouse_check_button_pressed(mb_left) 
        {
            if global.hilite > 0 {
                ds_list_delete(choices, global.hilite);
            }
            else
            if global.hilite == 0
                {show_dialogue = 0;}
        }
    }
    And now the End Draw Event (I used End Draw so the dialogue box will draw over everything) it's a little more simplified, but not really changed.
    Code:
    if !show_dialogue exit;
    var xx = view_xview[0], yy = view_yview[0];
    var list_size = ds_list_size(choices);
    draw_set_font(fnt_3);
    draw_set_colour(color);
    for(var i=0; i<list_size; i++) {
        draw_sprite(spr_Dialogue_Box,0,xx,yy+700-(100*i));
        if i == global.hilite {
              draw_set_alpha(0.5);
              draw_set_color(c_white);
              draw_rectangle(xx,yy+700-(100*i),xx+500,yy+800-(100*i),0);
              draw_set_alpha(1);
              draw_set_colour(color);
        }
        draw_text(xx+10,yy+700-(100*i), player_options[choices[|i]]);
    
    }
     
    Dr_Nomz likes this.
  16. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    Oh wow that's amazing. That actually works exactly like I need it to, and it seems like the simplest thing yet. I gotta do some more testing, but that might just be it. Thanks!

    EDIT: Hey do you think this could work in switch statement for branching dialogue? And maybe there's a way to add new options over time? ALSO only displaying 7 at a time? If i have all that then this system seems perfect.
     
  17. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,236
    Limiting 7 it to 7 at a time would still be all up to you. You could do a thing like
    while ds_list_size(choices)>7 ds_list_delete(choices,7)
    But then you'd just be deleting everything from the bottom of the list of choices. Ideally what you would do is have some method of determining which choices have been used and which still need to be added.

    You still wouldn't want to use a switch. The idea here is this code would go inside a "parent" NPC and the ONLY thing you edit is the Instance Creation Code. The switch wouldn't work in the instance creation code, so you wouldn't want that.

    Personally, in my opinion, it takes quite a bit more planning. Now, one thing that immediately came to mind a while back when I started this thread was organizing all your dialogue choices in branch order. So if saying "A" leads to being able to say "E" the next time and then being able to say "P" after that, your array of player_options[] would be something like
    A
    E
    P
    B
    C
    And then you'd have a code somewhere that says if the player picked A or E, call ds_list_insert(choices,player_options[choices[|hilite]+1],hilite) or whatever order the arguments go in. But since P would be the end of that dialogue branch, you'd have code that tells it to not add anything to the list (or rather, have no code at all).

    You should just look thruogh Google for ANY advice on branching dialogue trees, even stuff not related to GameMaker at all. There are a lot of considerations and some of the most important considerations depend on how dialogue will actually play out in your game. Fallout's branching dialogues are a lot different than, say, Shining Force's dialogues.
     
    Dr_Nomz likes this.
  18. Dr_Nomz

    Dr_Nomz Member

    Joined:
    Oct 31, 2016
    Posts:
    512
    Yeah I've thought it over, I know exactly what my system can do and I think it'll work well for me, but thank you for all the help, I really appreciate it. :D

    Still your own system is really good too, and you should see what you can do with it, or share it with someone else who's interested, could lead somewhere awesome. =)
     

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