Hi!
I am working on a simple adventure game engine. I made template nodes for the objects in the rooms. There are objects you can pick up, other trigger a dialogue or change the room. This works really great, and the resulting code is very compact.

There is one variable gamestate containing the position in the game where the player is. If they picked something up, the gamestate changes to the next value. This way, a very linear story can be walked through step by step.

There is another variable event. It is set by the interacting object. Every item in the room, every room change or dialogue box click sends a different event string. The game always know what just happened.

The many return calls have a reason. The game manager always simulates the whole game until the step where the player is at. There is no persistent setting of the objects. Everything is built from scratch in every interaction. It should be very easy to load savegames, I only have to set the gamestate variable and the player is exactly in the position of the story where they left.

The issue is: This code is completely unreadable even if it is clean code. Extremely hard to edit. And this is just a 100% linear story. It will become a mess if there are branching stories. I need a different approach and don't know what to do.

Regards
Thomas

	$room_lager/textvorlage.set_state("active")
	if gamestate == "textvorlage_raumsuche":
		if event == "enterroom_lager":
			gamestate = "textvorlage_aufgabe"
			signals.emit_signal("show_dialogue", "Du hast das Lager gefunden. Siehst du irgendwo die Textvorlage?")
		return

	if gamestate == "textvorlage_aufgabe":
		if event == "dialogue_next_button":
			gamestate = "textvorlage"
			signals.emit_signal("show_dialogue", "Guckst du im Regal.")
		return

	if gamestate == "textvorlage":
		if event == "objectinteraction_textvorlage":
			gamestate = "textvorlage_ablegen"
			signals.emit_signal("show_dialogue", "Der Text muss zum Setzkasten.")
		else:
			return

	$room_lager/textvorlage.set_state("invisible")
	new_inventory_image = $room_lager/textvorlage.get_inventory_texture()
	$room_setzkasten/textvorlage.set_state("empty")
	if gamestate == "textvorlage_ablegen":
		if event == "objectinteraction_textvorlage_ziel":
			signals.emit_signal("show_dialogue", "Super, so hast du den Text immer im Blick.")
			gamestate = "textvorlage_abgelegt"
		else:
			return

    Netaction Make a GameState class and link instances of this class into a queue where each GameState object refers to the next one. That way you can have flexible state system with small amount of state navigation code, and flexibility to insert states without any interventions into the code. It'll also eliminate all the nasty cascading ifs.

    Queue structure is easily expandable into a tree structure in case you wish to add some non-linearity. Instead of single reference to the next state just add multiple references to several possible next states, and condition(s) needed to branch to each.

      This is probably a little off topic but I saw a plugin for godot for adventure game dependencies.

      Looks kind of cool, really.

      9 days later

      xyz
      Thank you for the reply. After reading it very often, it sounds like what I need. But how is this done? I mean, a queue of classes? It can't be an array as an array would be linear. Are the classes linked in the Godot interface somehow?

      • xyz replied to this.

        Netaction A property of a class can hold a reference to an object of that same class. If it's just a linear queue it can be implemented either as a plain array or as a bunch of objects (class instances) referring to each other. In case of thee structure the latter is basically the only option.

        class_name State
        extends Reference
        
        var some_data: String
        var next: State = null
        var previous: State = null
        var s1 = State.new()
        var s2 = State.new()
        s1.next = s2
        s2.previous = s1