Making dialogues used only once

Godot Version

4.2.1

Question

so i have asked this once and a gentelman gave me an answer and it worked, but now I have 2 area2ds and now it doesnt work that way for obviouse reasons. my own idea is that i have to disable the collision shape of the area 2d after exiting it. here is the code:

var here=false
var string


func _input(event):
	if event.is_action_released("interact") and here==true:
		Dialogic.start(string)
	

func _on_test_dialogue_body_entered(body):
	string="res://timeline.dtl"
	if body.name == "player":
		here=true
	else:
		here=false


func _on_test_dialogue_body_exited(body):
	if body.name == "player":
		Dialogic.end_timeline()
		here=false
		


func _on_dia_2_body_entered(body):
	string="res://timeline2.dtl"
	if body.name == "player":
		here=true
	else:
		here=false


func _on_dia_2_body_exited(body):
	if body.name == "player":
		Dialogic.end_timeline()
		here=false
1 Like

Hmmm, could you possibly elaborate a bit on what it is that you are expecting to happen and how you have set up things on your scene view? Having a bit of a hard time guessing here.

the character enters an area2d, by pressing E a dialogue starts, and then if u exit and enter it again, the same dialogue starts again. now there is another area2d that has dialogue happening in it too but that doesnt matter. I want when we exit the area2d (using _on_test_area_2d_body_exited(body) signal) the collision shape disables so when the player presses E again, nothing happens.

also the _on_test_dialogue_body_entered(body) and _on_dia_2_body_entered(body) functions are the signals to the area2ds designated for the dialogues to happen. and also im using the dialogic add on, so the timeline.dtl is the dialogues written.

Add a variable in a script attached to the area2d that tracks if you want the dialogue to show.

Initialize it to true.

Test if it is true before showing the dialogue.

Set it to false once the dialogue has been displayed once.

Would that work for you?

3 Likes

i have done that. a global variable that when the dialogue is done it gets false. BUT if I want to make sure that the dialogue wouldnt start again, than i have to make a variable for every area2d that has a dialogue in it, making the code sloppy and not clean. I know there is a code for disabling the collisoin shapes of area2d in godot 3 but i have no idea how it is in godot 4.

I am certain you can make a unique tracking variable to each area2d, rather than a globally shared one.

I will respond later if no one else has. I am, unfortunately busy right now.

thanks mate take your time.
so you are saying I should make the varieble local so it would look something like this:

func _input(event):
	if event.is_action_released("interact") :
		Dialogic.start(string)
func _on_test_dialogue_body_entered(body):
	var here=false
	string="res://timeline.dtl"
	if body.name == "player":
		here=true
	else:
		here=false

so lets look away from input function. in the body enter signal, if we designat the variable localy, wouldnt it mean if we enter the area2d again it would play the dialogue? im a bit new in coding sorry if i didnt understood you correctly

Here is an example of the kind of thing I mean:

extends Area2D

@export var AreaName: String  = "my default name" # need to use inspector to fill in name

var inputCount: int = 0

func _ready():
	pass 

func _process(_delta):
	pass

func _mouse_enter():
	inputCount = inputCount + 1
	print(AreaName,": Mouse Entered: ", str(inputCount))

With this one script, as is, you can get an effect like you are looking for. You dont need a separate case for each Area2d. You will just have this one script and attach it to multiple Area2d.

This way you will have a single script with a single case to update if anything needs to change.

If you attach this script to each of your Area2D nodes

  1. you will have an “AreaName” field you can type a name into

  2. every time the mouse enters the object, you get a message in the console stating which area was entered (by name) and how many times it has entered.

This is the bones of what you need, but you will have to tailor it for the actions and responses you want.

Instead of exporting a name to fill in the inspector, you could export the string holding the message for the dialogue

And instead of detecting the mouse, you can change it to detecting bodies entering or buttons pressed or whatever.

And instead of using calling print statements, you can call you dialogue function.

and, lastly, instead of counting the number of times the mouse enters you could set a bool…something like this:

extends Area2D

@export var FirstMessage: String  = "my default message"# need to use inspector to fill in dialogue

var beenEntered: bool = false

func _ready():
	pass 

func _process(_delta):
	pass

func _mouse_enter(): #replace with whatever you want to trigger instead of mouse
	if beenEntered == false:
		print(FirstMessage) # replace with however you are handling dialogue
		beenEntered = true

Now you have one script that you can attach to any area2d, it only gets triggered once for each Area2d, and you can customize the message for each one.

You can also drag resources into the exported field in the inspector. So you can keep your dialogue as a resource.

2 Likes

is there a way for a code in the player script instead of a script for the area2ds?

What I would do is have the area2d script send a signal (with any needed info) to the player script. And then have the player script handle it upon receiving the signal.

Does that work for your case?

To clarify, the area2d script would still handle the detection, hold the message, and decide if a message should be displayed.

But instead of displaying the message, it sends it via signal to player script.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.