godotgdscript

GODOT - how to disable player movement when dialog box is active and reenable it when its inactive


Ok, i'm really bad at coding. I'm especially new to GODOT and am trying to make a 2d game. I've been able to set cant_move to false when dialog is playing, the problem I'm having is making cant_move true again. I don't even know where to put done = true on the dialog script (I kinda just put it in a random place and hoped it would work). Here is my dog-shit code. (the solution is probably easy im just really dumb)

npc script

`extends Area2D
var done = true


func _ready(): 
    Global.npc1 = self
func _exit_tree():
    Global.npc1 = null


var can_interact = false
const DIALOG = preload("res://dialoguebox.tscn")

func _physics_process(delta):
    $AnimatedSprite.play()

func diaplay():
    if done == false:
        Global.player.can_move = false
        print("test")

    if done == true:
        print("test2")
        can_interact = false
        Global.player.can_move = true

func _on_Area2D_body_entered(body):
    if body.name == "player":
        $Label.visible = true
        can_interact = true

func _on_Area2D_body_exited(body):
    if body.name == "player":
        $Label.visible = false
        can_interact = false

func _input(event):
    if Input.is_key_pressed(KEY_E) and can_interact == true:
        done = false
        diaplay()
        $Label.visible = false
        var dialog = DIALOG.instance()
        get_parent().add_child(dialog)
        dialog.position = $Position2D.global_position

dialog script

extends Control
var dialog = [
    'sampletext',
    'sampletext2',
]
var done = false
var dialog_index = 0
var finished = false


func _ready():
    load_dialog() 
    Global.DialogBox = self
    
func _exit_tree():
    Global.DialogBox = null

func _physics_process(delta):
    $"Ind".visible = finished
    if Input.is_action_just_pressed("ui_accept"):
        load_dialog()

func load_dialog():
    if dialog_index < dialog.size():
        finished = false
        $RichTextLabel.bbcode_text = dialog[dialog_index]
        $RichTextLabel.percent_visible = 0
        $Tween.interpolate_property(
            $RichTextLabel, "percent_visible",  0, 1, 1,
            Tween.TRANS_LINEAR, Tween.EASE_IN_OUT
        )
        $Tween.start()
    if dialog_index >= 0:
        Global.npc1.done = true
    else:
        queue_free()
        done = true
    dialog_index += 1
    
func _on_Tween_tween_completed(object, key):
    finished = true

Solution

  • If I understand correctly, you are opening the UI with this code:

    var dialog = DIALOG.instance()
    get_parent().add_child(dialog)
    dialog.position = $Position2D.global_position
    

    So add the instruction to make can_move false there (Global.player.can_move = false).

    And apparently it is all done here:

    queue_free()
    

    That is, the UI is removing it self. When the UI removes itself, it exits the scene tree, we are going to take advantage of that. Connect the tree_exited of the UI to a func that sets can_move true again:

        Global.player.can_move = false
        var dialog = DIALOG.instance()
        dialog.position = $Position2D.global_position
        dialog.connect("tree_exited", self, "dialog_exited")
        get_parent().add_child(dialog)
    
    func dialog_exited() -> void:
        Global.player.can_move = true
    

    That should do.

    Alternatively you could create and emit a signal to notify when the player can move again. Refer to the documentation about signals.


    Addendum

    I think I got what else is not working. Look at load_dialog:

    func load_dialog():
        if dialog_index < dialog.size():
            # ... some code ...
        if dialog_index >= 0:
            Global.npc1.done = true
        else:
            queue_free()
            done = true
        dialog_index += 1
    

    The first check (dialog_index < dialog.size()) is if there is more dialog text. If there isn't then it is done. So change it to this:

    func load_dialog():
        if dialog_index < dialog.size():
            # … some code …
        else:
            Global.npc1.done = true
            queue_free()
            done = true
        dialog_index += 1
    

    I hope that makes sense.


    You also mention you got an error in Global.player.can_move = true, I suppose that happened with closing the game, that code ran, and Global.player was no longer valid.

    Regardless of the situation, you can check if the player is valid:

        var player = Global.player
        if is_instance_valid(player):
            player.can_move = true