I've spent some time refactoring and simplifying the event system, which controls dialogue and scripted events.I had issues with control flow until I discovered custom signals and coroutines. I tried to come up with a system that is easy to add content to and keep organized, but can be expanded as new needs arise.I'm storing all the game's text in a json dictionary. Each event key contains a dictionary that has some combination of the following:[code]{ "repeat": [A dialogue array that displays each line, the repeats the last line until a new event is loaded],"txt" : [A dialogue array that is displayed once (used as part of complex events)],"function": "function" to call,"next": "eventkey" that will be loaded as the next event, but not fired until the player triggers it. Only needed to queue up dialogue arrays with breaks in between. }[/code]Each npc inherits the following. [code]signal player_inputsignal event_finished... vars, connections etc...func _input(event): if event.is_action_pressed("button_action"): if player_in_area == name: if active_event: emit_signal("player_input") print(name, " emitted player_input_signal") elif event_loaded: initiate_event(event_loaded) func initiate_event(event): active_event = true repeat = false if "next" in global.txt[name][event]: event_loaded = global.txt[name][event]["next"] print("next eventkey ", event_loaded, " loaded") if "function" in global.txt[name][event]: var run_event = funcref(self,global.txt[name][event]["function"]) print("calling function") run_event.call_func() else: if "txt" in global.txt[name][event]: if global.txt[name][event]["txt"].size() > 0: dialogue_list = global.txt[name][event]["txt"] print("txt loaded") elif "repeat" in global.txt[name][event]: repeat = true dialogue_list = global.txt[name][event]["repeat"] print("repeating txt loaded") player.freeze=true chat(dialogue_list, repeat)func chat(dialogue_list, repeat=false): get_textbox() while dialogue_list.size()>0: textbox.message(dialogue_list[0]) print(dialogue_list[0]) yield(self,"player_input") if dialogue_list.size()==1 and repeat: break else: dialogue_list.remove(0) print("line removed") get_node("textbox").free() event_ended()func event_ended(): print("event ended") active_event = false player.freeze = false emit_signal("event_finished")[/code]Here's an example of what a complex event would look like:[code]func power(): if active: print("trying to shut lord down after powered") shutdown() else: get_textbox() textbox.message(global.txt.lord.desc) textbox.choice(global.txt.lord.power_menu) yield(get_node("textbox"), "choice_selected") if textbox.player_choice == 0: if "tvland power" in global.triggered_events: print("lord is turned on") active = true initiate_event("turned-on-safe") yield(self, "event_finished") initiate_event("on-friendly") else: textbox.popup("You click the button repeatedly. Nothing happens.") else: textbox.close_overlay() event_ended()[/code]