Skip to content

Adding Story Mode Content

Jummit edited this page May 2, 2022 · 6 revisions

Adding Story Mode Content

Story mode is a minigame where the main focus lies on telling a story about little Mario. It features gameplay elements like talking to characters in the world, exploring, collecting items and solving puzzles.

Adding Items

Items can be given by characters or collected from the ground. They can be viewed inside the inventory by pressing [E].

To add a new item, create a new resource of type StoryItem and put it inside the content/items folder.

Inside the resource you can change the name, description and texture of the item.

To add the item to the world you can use the GroundItem scene. Instantiate it inside the level under the Items node, move it to the right place and drag the item resource into the item property.

Adding Characters

Characters, or NPCs, are persons or objects that can be interacted with.

To add a new character type, create a resource of type StoryCharacterData in the content/characters folder.

You can configure the name and texture of the character.

To place this character inside the world, instantiate a Character scene and drag the character into the data property.

Each character can have a dialog you can trigger, and a text that is displayed if you can talk to them. You should also right click the scene and enable Editable Children. Then you can position the label, collision shape and sprite where they make sense. To make sure the YSort works, position the bottom of the sprite at the origin point of the character.

Adding Dialogs

Writing The Dialog

Dialogs are written in JSON files. To get the best editing experience you should use an IDE with JSON schema validation, like VSCode or Vim.

To start, create a new JSON file inside content/dialogs with this template:

{
	"$schema": "schema/dialog.schema.json",
	"text": "I am learning about how to create dialogs!",
	"choices": [
		"That's awesome!",
		{
			"text": "Good luck!",
			"dialog": "Thanks!"
		}
	]
}

The $schema tells your IDE that you are writting JSON with a specific structure. It will give you errors, hints and tooltips.

The text can be a string or a list of strings, and is the message the character says to the player.

Choices can be a list of responses the player can choose.

Using The Dialog

To make the dialog appear in the game you need to assign it to a character or start it inside a script like this:

# Get a reference to the dialog UI.
var dialog_ui = $CanvasLayer/UI/DialogUI
# Start the "shop" dialog. `character` is optional.
dialog_ui.start(preload("shop.json"), character)

Cutscenes

If you want an animation to play during a dialog, add it to the CutScenePlayer animation player. To trigger the cutscene, add an event property with the same name as the animation. The dialog will resume after the animation is done playing.

Advanced Dialogs

Hubs

Hubs are a common pattern inside dialog-based games. They provide a dialog message you can return to after completing branches inside a dialog. This can be achieved using the goto property.

Example:

{
	"$schema": "schema/dialog.schema.json",
	"text": "What do you want to know?",
	"label": "start",
	"choices": [
		{
			"text": "What is two plus two?",
			"dialog": {
				"text": "Uhmm.... That would be.... four?",
				"choices": [
					{
						"text": "One more thing...",
						"dialog": {
							"goto": "start"
						}
					}
				]
			}
		},
		{
			"text": "What is two divided by zero?",
			"dialog": {
				"text": "Uhhmm... I think that's NaN?",
				"choices": [
					{
						"text": "One more thing...",
						"dialog": {
							"goto": "start"
						}
					}
				]
			}
		},
		"Bye!"
	]
}

Events

To get the dialogs to interact with GDScript you can use events. When an event is hit the dialog UI will emit an event_occured signal.

Example:

{
	"$schema": "schema/dialog.schema.json",
	"text": "This looks like a button.",
	"choices": [
		{
			"text": "Press it.",
			"dialog": {
				"text": "Nothing happens.",
				"event": "clicked_button"
			}
		}
	]
}

Giving Items

You can give the players items after a dialog has finished.

The name should be the file name of the item data resource without extension.

Example:

{
	"$schema": "schema/dialog.schema.json",
	"text": "A pie.",
	"choices": [
		{
			"text": "Take it.",
			"dialog": {
				"text": "You take the pie. It looks delicious.",
				"item": "pie"
			}
		}
	]
}

Letting Multiple Characters Speak

Often times it is necessary to have multiple dialogs speak in one conversation. You can do so by chaining dialogs together and setting the character property:

{
	"$schema": "schema/dialog.schema.json",
	"text": "I am the original speaker!",
	"next": [
		{
			"text": ["I AM THE SECOND SPEAKER!"],
			"character": "wizard_dude"
		},
		{
			"text": "i am the third speaker",
			"character": "donk"
		}
	]
}

Conditions

Conditions can be used inside dialogs or conditions to create branching dialogs.

Example of conditional choices:

{
	"$schema": "schema/dialog.schema.json",
	"text": "Have we met before?",
	"choices": [
		{
			"condition": {
				"custom": "have_met",
				"inverted": true
			},
			"text": "I don't think so.",
			"dialog": "Greetings then!"
		{
			"condition": {
				"custom": "have_met"
			},
			"text": "Yes, we have.",
			"dialog": "Nice to see you again!"
		},
		{
			"condition": {
				"item": "pie"
			},
			"text": "Here, have this pie! I'm sadly allergic to it",
			"dialog": "Thank you!"
		}
	],
	"event": "met_guy"
}

Example using true/false:

{
	"$schema": "schema/dialog.schema.json",
	"condition": {
		"custom": "is_rich"
	},
	"true": {
		"text": "You have a lot of coins!"
	},
	"false": {
		"text": "You Are poor!"
	}
}

Custom Condition Methods

When you set the field custom, the method with the same name will be executed on the main story mode script. The condition is only true if the method returned true.

Only Showing The Player Something Once

If it doesn't make sense that the player reaches the same dialog twice you can use the occurence number:

{
	"$schema": "schema/dialog.schema.json",
	"text": "Have we met before?",
	"choices": [
		"Maybe...",
		{
			"text": "No, this is the first time!.",
			"condition": {
				"occurence": 1
			}
		}
	]