Skip to content

NPC ~ Loading NPCs from WDL Files

sglenn-uchi edited this page May 31, 2022 · 4 revisions

Introduction

This document will outline how to load NPCs from WDL files. Modules: load_npc.h, load_npc.c

Mechanism

Before we can load NPCs into the game from WDL files, a few things have to be done by other modules:

  1. The WDL file (essentially, a text file) is converted into a JSON object.
  2. The JSON object is parsed to create individual, nested game objects. (See: load.h, obj.h)
  3. It is from these nested game objects that we retrieve the information from the WDL file to create our NPCs.
  4. We use the obj_get family of functions (in obj.h) to retrieve the game objects we want.

This document will, unfortunately, not go through how exactly NPC loading is implemented. If you would like to understand that, please have a look at the code in load_npc.c.

WDL Format for NPCs

NPCs should be specified in WDL files in the following ways:

NPCs, No Items, No Dialogue

{
    "GAME":
    ...
    "NPCS": {
        "ALICE": {
            "short_desc": "This is Alice",
            "long_desc": "She wants to talk to you.",
            "in": "room_A"
        },
        "BOB": {
            "short_desc": "This is Bob",
            "long_desc": "He wants to talk to you.",
            "in": "room_B"
        }
    }
}

NPCs, with Items and Dialogue

{
    "GAME":    
    ...
    "ITEMS": {
        "APPLE": {
            "short_desc": "An apple",
            "long_desc": "A juicy red fruit",
            "in": "npc",
            "actions": []
        }
    },
    "NPCS": {
        "ALICE": {
            "short_desc": "This is Alice",
            "long_desc": "She wants to talk to you.",
            "in": "room_A",
            "inventory": [
                {
                    "item_id": "APPLE"
                }
            ],
            "dialogue": {
                "nodes": [
                    {
                        "id": "1",
                        "npc_dialogue": "I have an apple. Do you want it?"
                    },
                    {
                        "id": "2a",
                        "npc_dialogue": "Here you go."
                    },
                    {
                        "id": "2b",
                        "npc_dialogue": "That's too bad."
                    }
                ],
                "edges": [
                    {
                        "quip": "Yes",
                        "from_id": "1",
                        "to_id": "2a"
                    },
                    {
                        "quip": "No",
                        "from_id": "1",
                        "to_id": "2b"
                    }
                ]
            }
        }
    }
}

Notice that the "in" field in the item APPLE has "npc" as its value. If you would like to understand how dialogue works, feel free to look at the dialogue Wiki page.

Note: This implementation does not actually make Alice give the player the Apple. To achieve that, we will need advanced dialogue functionalities, discussed below.

NEW: QUESTS

NPCs can also be given Quests and Tasks with unique dialogue. If this feature is omitted, NPCs can still be loaded, but a couple warning messages will occur beforehand. For sample NPCs with lists of quests and tasks, see "pokemon_plus.wdl"

Advanced Dialogue Functionalities

Conditional Dialogue

Currently, only inventory conditions (not attribute) can be loaded into the game. Multiple conditions are possible. Conditions loading is done in the load_condition module.

"dialogue": {
    "nodes": [
        {
            "id": "1",
            "npc_dialogue": "I'll trade this Apple for an Orange."
        },
        {
            "id": "2a",
            "npc_dialogue": "Here you go."
        },
        {
            "id": "2b",
            "npc_dialogue": "That's too bad."
        }
    ],
    "edges": [
        {
            "quip": "I have an Orange right here.",
            "from_id": "1",
            "to_id": "2a",
            "conditions": [
                {
                    "type": "INVENTORY",
                    "item_id": "ORANGE"
                }
            ]
        },
        {
            "quip": "Sorry, I don't have an Orange",
            "from_id": "1",
            "to_id": "2b"
        }
    ]
}

Notice the "conditions" field under the first edge.

Actions

Currently, only two actions are available: (1) GIVE_ITEM, (2) TAKE_ITEM. Important: TAKE_ITEM must be prefaced by a conditional edge leading to it. Otherwise, an error will result if the player doesn't have the item.

"dialogue": {
    "nodes": [
        {
            "id": "1",
            "npc_dialogue": "I'll trade this Apple for an Orange."
        },
        {
            "id": "2a",
            "npc_dialogue": "Here you go.",
            "actions": [
                {
                    "action": "TAKE_ITEM",
                    "action_id": "ORANGE"
                },
                {
                    "action": "GIVE_ITEM",
                    "action_id": "APPLE"
                }
            ]
        },
        {
            "id": "2b",
            "npc_dialogue": "That's too bad."
        }
    ],
    "edges": [
        {
            "quip": "I have an Orange right here.",
            "from_id": "1",
            "to_id": "2a",
            "conditions": [
                {
                    "type": "INVENTORY",
                    "item_id": "ORANGE"
                }
            ]
        },
        {
            "quip": "Sorry, I don't have an Orange",
            "from_id": "1",
            "to_id": "2b"
        }
    ]
}
Clone this wiki locally