Creating Dialogue in a Cutscene

Zapzel-24

Member
I have been watching Friendly Cosmonaut video on creating a Dialogue System and building a Cutscene System, I attempted to to combine the two ideas together and it works (sort of). There a couple Technical Hiccups I tried to sort out but it seems out of my grasp.

In the creation code where it runs all of the arrays it should immediately end the action rather it loops through the last dialogue rather than ending it and moving to next cutscene action.
GML:
function cutscene_dialogue(){
    var created = false;  //<--- Check to see if object exists
    
    if created = false{
        instance_create_layer(view_visible[0], view_visible[0], "Instances", obj_cutsceneDialogue); //<--- Create the object
        created  = true;
    }
    with (obj_cutsceneDialogue){
            obj_cutsceneDialogue.cutText  = argument0;
            obj_cutsceneDialogue.cutProfile = argument1;
        }
        if (obj_cutsceneDialogue.complete = true && created = true){ //<--- Checks to see if the Dialogue is complete and ends the cutscene
            instance_destroy();  //<---This prevents the game from crashing for some reason.
            with (obj_cutsceneDialogue){instance_destroy(obj_CutDialogue);}
            cutscene_end_action(); //<---End the action and move on to the next cutscene event.
        }
}
The arguments transfer the strings and sprite of desired profile picture into obj_cutsceneDialogue, with the created object it creates an Dialogue box which both the string and profile appear respectively.

The second issue is that the text overlap one another, strangely it still continues to borrow text from the previous cutscene event even thought it should have finish and not borrow the old text.

Here is the creation code for the trigger that activates the cutscene:
Code:
t_scene_info =[
    [cutscene_dialogue, "That was strange?", spr_profile_none],
    [cutscene_dialogue, "He was here for a second.", spr_profile_none],
];
Here is the cutsceneDialogue that script creates
Create_Event:
Code:
//Initalize Varibles
MyTextbox = noone;
complete = false; //<--- Checks to see if the Dialogue is completed.
playing = false;
Step_Event:
Code:
if playing = false alarm[1] = 1; //<--- Auto plays the Dialogue Box

if MyTextbox = noone{
    if playing = true{
        MyTextbox = instance_create_layer(view_visible[0], view_visible[0], "Instances", obj_CutDialogue);
        MyTextbox.text = cutText;
        MyTextbox.profile = cutProfile;
        MyTextbox.creator = self;
    }else{
        //Reset Varible
        if MyTextbox != noone {
            instance_destroy(MyTextbox);
        }
    }   
}
Alarm 0:
MyTextbox = noone;
complete = true;

Alarm 1:
playing = 1;

Here is the Scripts for obj_cutDialogue the dialogue box created by obj_cutsceneDialogue
Create_Event:
Code:
///scr_textbox_create_script
depth = -1;
//Initalize Varibles
text = "This is a Text";
profile = spr_profile_none;
//Text Positioning
Box_width = sprite_get_width(spr_DialogueBox);
String_height = string_height(text);
charCount = 0;
//Pages
//page = 0;
//Creator
creator = noone;
//Image Index
frame = image_index;
//Animation
FrameSpeed = 0.05;
Step_Event:
Code:
//scr_textbox_step_script

//Interact button
if keyboard_check_pressed(ord("X"))
{
        instance_destroy();
        creator.alarm[0] = 1;
}

//Increase Frame via FrameSpeed
frame += FrameSpeed;

//Profile Animation
if (floor(frame) > sprite_get_number(profile) - 1)
{
    frame = 0;
}
Draw_Event:
Code:
///scr_textbox_draw_script

//Creating Textbox
draw_sprite_ext(spr_DialogueBox, 0, view_visible[0], view_visible[0], 1.98, 1.50, 0,c_white,1);

//Creating Text
draw_set_halign(fa_left);
draw_set_font(txt_font_1);
draw_set_color(c_white);
draw_set_alpha(1);
if (charCount < string_length(text))
{
    charCount += 0.40;
}
TextPart = string_copy(text, 1, charCount)
draw_text_ext(view_visible[0] + 50, view_visible[0] + 50, TextPart, String_height, Box_width);

//Creating Portrait
draw_sprite_ext(profile, frame,view_visible[0] + 32,view_visible[0] + 68,1,1,0,c_white,1);
It should be noted that page variable is omitted out of the script due to it causing frequent crashing.
 

Zapzel-24

Member
Update: I am on to something, I'll continue to use this post as a reference point in case something goes wrong and need to go back to the drawing board.
 

Zapzel-24

Member
Update: Ok, so I managed to streamlined the code and managed to fix the text problem and the looping problem. However, the cutscene is unable to advance to the next scene and just stops at the textbox, even though the code instructs it to move on to the next scene once the textbox is created. I'm kind of stumped here.

Cutscene Code for the Dialogue:
GML:
function cutscene_dialogue(){
    if (!instance_exists(obj_Textbox)){
        DB = instance_create_layer(view_visible[0], view_visible[0], "Instances", obj_Textbox);
        DB.MyText = argument0;
        DB.MyProfile = argument1;
        
    }
    else{
        cutscene_end_action();
    }
}
The Dialogue Box itself has been redesigned, it no longer has a page array. The cutscene array itself will erase the previous Dialogue Box and replace it with another Dialogue Box with a different text and profile images.

Dialogue Box- Create Event:
GML:
depth = -1;
//Initalize Varibles
MyText = "This is a Test";
MyProfile = spr_profile_none;
//Text Positioning
Box_width = sprite_get_width(spr_DialogueBox);
String_height = string_height(MyText);
charCount = 0;
//Image Index
frame = image_index;
//Animation
FrameSpeed = 0.05;
Dialogue Box - Step Event:
GML:
//Increase Frame via FrameSpeed
frame += FrameSpeed

//Profile Animation
if (floor(frame) > sprite_get_number(MyProfile) -1)
{
    frame = 0
}
Dialogue Box - Create Event:
GML:
//Creating TextBox
draw_sprite_ext(spr_DialogueBox, 0, view_visible[0], view_visible[0],1.98, 1.50, 0, c_white, 1);

//Creating Text
draw_set_halign(fa_left);
draw_set_font(txt_font_1);
draw_set_color(c_white);
draw_set_alpha(1);
if (charCount < string_length(MyText))
{
    charCount += 0.40;
}

TextPart = string_copy(MyText, 1, charCount)
draw_text_ext(view_visible[0], view_visible[0], TextPart, String_height, Box_width);

//Creating Portrait
draw_sprite_ext(MyProfile, frame, view_visible[0] + 32, view_visible[0] + 68, 1, 1, 0, c_white, 1);
 

Zapzel-24

Member
the cutscene dialogue is called by the cutscene object, when the player steps into the trigger box. I have checked my previous posts and I did not put any information regarding the cutscene object so here is an explanation.

The Cutscene object is created when the player steps into a trigger object. The Cutscene object proceeds to run the array scenes that are implemented in the Trigger objects creation code.
The Triggers creation codes contain arrays witch carry scripts for the Cutscene object uses to execute, once completed the Cutscene object will proceed to destroy itself.

Here is the Cutscene Object
Creation Code:
GML:
//Initalize Varibles
scene_info = -1;
scene = 0;

timer = 0;

x_dest = -1;
y_dest = -1;
the Cutscene Object Step Event has only a single script:
GML:
script_execute_alt(current_scene[0], current_scene_array);
Within script_execute_alt:
GML:
function script_execute_alt(){
    //@description Script execute ALT
    
    var s = argument0;
    var a = argument1;
    var len = array_length(argument1);
    
    switch(len){
        case 0: script_execute(s); break;
        case 1: script_execute(s, a[0]); break;
        case 2: script_execute(s, a[0], a[1]); break;
        case 3: script_execute(s, a[0], a[1], a[2]); break;
        case 4: script_execute(s, a[0], a[1], a[2], a[3]); break;
        case 5: script_execute(s, a[0], a[1], a[2], a[3], a[4]); break;
        case 6: script_execute(s, a[0], a[1], a[2], a[3], a[4], a[5]); break;
        case 7: script_execute(s, a[0], a[1], a[2], a[3], a[4], a[5], a[6]); break;
        case 8: script_execute(s, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break;
        case 9: script_execute(s, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); break;
        case 10: script_execute(s, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); break;
    }
}
obj_Cutscene User_Event0:
GML:
current_scene = scene_info[scene];

var len = array_length(current_scene) -1;

current_scene_array = -1;
current_scene_array = array_create(len, 0);
array_copy(current_scene_array, 0, current_scene, 1, len);
Here is the Trigger Object that the player makes in contact with.
Trigger Create Event:
GML:
t_scene_info = -1;
Trigger Step Event:
GML:
if (!instance_exists(obj_cutscene)){
    if (place_meeting(x, y, obj_player)){
        cutscene_create(t_scene_info);
    }
}
This is the Trigger's Creation Code the Cutscene object reads through:
GML:
t_scene_info = [
    [cutscene_move_character, obj_player, 750, 240, false, 1],
    [cutscene_instance_destroy_neareast, 100, 100, obj_player],
    [cutscene_create_instance, 100, 100, "Instances", obj_explosion],

    [cutscene_wait, 4],
    
    [cutscene_move_character, obj_NPC, 0, 200, true, 1],
    [cutscene_create_instance, 846, 207, "Instances", obj_bubble],
    [cutscene_dialogue, "That was strange", spr_profile_none], //<--- THIS IS WERE IT STOPS
    [cutscene_clear_dialogue],
    
    [cutscene_create_instance, 430, 240, "Instances" , obj_explosion],
    [cutscene_create_instance, 430, 240, "Instances", obj_player],
    [cutscene_move_character, obj_player, 0, 16, true, 1],
];
It might be wise to have Some of the Cutscene scripts that is responsible for starting and end the cutscene array
Cutscene Create creates the cutscene object when activated:
GML:
function cutscene_create_instance(){
    ///@description Create an Instance
    ///@arg x
    ///@arg y
    ///@arg layer_id
    ///@arg object
    
    var inst = instance_create_layer(argument0, argument1, argument2, argument3);
    cutscene_end_action();
    
    return inst;
}
Cutscene End Action is responsible for advancing to the next scene once it completes the array it destroys itself.
GML:
function cutscene_end_action(){
    scene ++;
    //End Cutscene Scripts
    if (scene > array_length(scene_info)-1){
        instance_destroy();
        exit;
        }
    
    event_perform(ev_other, ev_user0);
}
Cutscene Dialogue creates a Textbox within the cutscene:
GML:
function cutscene_dialogue(){
    if (!instance_exists(obj_Textbox)){ //<--Checks to see if Textbox object exists
        DB = instance_create_layer(view_visible[0], view_visible[0], "Instances", obj_Textbox);
        DB.MyText = argument0; //<--Write your Text here.
        DB.MyProfile = argument1; //<-- Place your sprite to use as a profile.
        
    }
    else{
        cutscene_end_action(); //<--Once the Textbox object exists it should move but it never does.
    }
}
 

Nidoking

Member
I think your problem is that whatever is supposed to call your cutscene_dialogue function is not calling it once the textbox is created. It's hard to tell because there's a lot of logic there and not all the pieces are here. Have you tried running this in the debugger to see whether it's calling the functions you think it should?
 
S

SkinnyFries

Guest
Hi! I also followed FriendlyCosmonaut videos to try doing the exact same thing you were doing although my dialogue code is a bit different. I'm having the same problem though where once the first text object gets created it never moved onto the next scene. Can I ask how you got it to work?
 
Hi! I've also been following the FriendlyCosmonaut tutorials and use the dialogue system from her Farming RPG tutorials. Here's a simple snippet that worked for me:

Located on the onDestroy event of my dialogue object (called "Textbox").
if (instance_exists(objCutscene)) { CutsceneEndAction(); exit; }

// Code to stop player movement



This works because this code is being called once the dialogue has finished. It blocks the cutscene until the the object has been destroyed. Hope this helps!
 
Top