0 of 0

File information

Last updated

Original upload

Created by

aedenthorn

Uploaded by

aedenthorn

Virus scan

Safe to use

About this mod

A framework for easily creating branching topic-based conversation with specific answers and reactions for individual NPCs.

Requirements
Permissions and credits
Donations
This mod lets you easily create simple or complex branching dialogue by creating topics and specifying NPC answers and reactions to player answers.


For Users

Conversations can be initiated in one of two ways, when an NPC no longer has any normal dialogue waiting to be said:

  • The player can ask a question of the NPC (by default, hold down Left Alt and left click on the NPC)
  • The player can have the NPC ask the player a question (by default, hold down Left Alt and right click on the NPC)


NPCs may ask any question they have something to say about; which question they ask is chosen at random. NPC data is determined by whatever Content Patcher magic one uses - e.g. season-specific specific answers, friendship-level specific questions, etc.

The framework does nothing without content packs that create topics and content packs that give NPCs things to say about those topics. I've created to simple mods that make use of this framework, as examples:



For Modders

Basically, content for this framework is divided into two parts.

  • The part where a topic is created (using a custom content pack)
  • The part where an NPC is given data relating to a created topic (using a Content Patcher content pack)



Topics

Topics are created using Dialogue Trees content packs (suggest using [DT] as a folder prefix).

A Dialogue Trees content pack has two files, manifest.json and content.json.

manifest.json

Here's an example manifest.json:

{
  "Name": "Dialogue Trees RPG Game Content Pack",
  "Author": "aedenthorn",
  "Version": "0.1.0",
  "Description": "",
  "UniqueID": "aedenthorn.DTRPGGamePack",
  "MinimumApiVersion": "3.5.0",
  "ContentPackFor": {
    "UniqueID": "aedenthorn.DialogueTrees",
    "MinimumVersion": "0.1.0"
  },
  "Dependencies": [
   {
      "UniqueID": "aedenthorn.DialogueTrees",
      "IsRequired": true
   },
  ]
}


Pretty self-explanatory, just edit the stuff that makes it yours.


content.json

content.json is a JSON object with four JSON array keys:

{
    "dialogues": [
    ],
    "topicNames": [
    ],
    "standardQuestions": [
    ],
    "playerResponses": [
    ]
}

dialogues is a list of topics. This is where your conversation topics are stored. Topics are not NPC specific; any NPC can ask and answer questions about a topic if they are given the dialogue using content patcher (see Content Patcher section).

Dialogue topics are JSON objects. Here are two different examples, one simple, one a part of complex dialogue:

        {
            "topicID": "climateChange",
            "questionIDs": [
                "whatThink",
                "howFeel",
                "thoughtsOn",
                "whatTake"
            ],
            "responseIDs": [
                "terrified",
                "concerned",
                "dontCare",
                "dontKnow"
            ]
        }


        {
            "topicID": "rpgGameLeftTunnelWizard",
            "isStarter": false,
            "playerCanAsk": false,
            "followupChance": 1,
            "requiredResponses": {
                "rpgGameClass": [
                    "rpgGameWizard"
                ],
                "rpgGameLeftTunnelWizard": [
                    ""
                ]
            },
            "questionIDs": [
                "rpgDeadEndWizard"
            ],
            "responseIDs": [
                "rpgReturnToEntrance"
            ],
            "nextTopics": {
                "any": [
                    "rpgGameEntranceWhichWay"
                ]
            }
        }


  • topicID is the ID used to identify this topic, just make sure it is unique.
  • isStarter means it can be used to start a conversation - otherwise, this topic is only a part of a larger conversation, as a followup to another topic.
  • playerCanAsk is really only for starter topics, it determines whether a player can ask the topic or not.
  • followupChance refers to the chance this topic will be chosen as a followup topic if more than one followup topic is possible (1.0 = 100%, 0.5 = 50%, etc.)
  • requiredResponses means that in order for this topic to be a followup topic, certain responses must have been given to previous topics (in the second example, from a simple RPG game dialogue, one must have chosen the wizard class and not have previously seen this topic)
  • questionIDs is a list of strings that may be used to ask this question useful for dialogue like the first one, where you want flexibility in how the question is asked). These are just unique ID strings - the actual text is specified as standard questions in the standardQuestions key, and specific to NPCs in their CP content. IDs can be generic, because the topic name can be added to the text using {0}, e.g.: "whatThink": "What do you think about {0}?" (more about this in the section on standardQuestions)
  • responseIDs is a list of possible responses. Player responses are added to playerResponses and NPC responses are added to their CP content (see Content Patcher section below)
  • nextTopics is a dictionary of "chosenResponseID": "nextTopicID" pairs. Specifying "any" as chosenResponseID as in the second example means it doesn't matter what your response is, the next topic will always be the same.

topicNames

topicNames is option, useful if you have questions where you want to insert the topic name into the question. E.g.:

    "topicNames": {
        "climateChange": "climate change",
        "politics": "politics",
        "stardewValley": "Stardew Valley",
        "romance": "romance"
    }


standardQuestions

standardQuestions is a dictionary used to preset questions asked by the player or by NPCs without a specific way of asking a certain question. E.g.:

    "standardQuestions": {
        "whatThink": "What do you think about {0}?",
        "areInterested": "Are you interested in {0}?",
        "howFeel": "How do you feel about {0}?",
        "howLike": "How do you like {0}?",
        "thoughtsOn": "What are your thoughts on {0}?",
        "whatTake": "What's your take on {0}?"
    }

{0} is replaced by the topic name from topicNames if it has been set.


playerResponses

playerResponses defines the response text displayed for player answers based on the responseID. E.g.:

    "playerResponses": {
        "peaceful": "It's very peaceful...",
        "exciting": "I find it exciting!",
        "love": "I love {0}!",
        "ok": "It's okay, I guess...",
        "notInterested": "I'm not really interested in {0}!",
        "interested": "I'm very interested in {0}!",
        "terrified": "It terrifies me!",
        "concerned": "I'm very concerned about it.",
        "dontCare": "I don't care about {0} all.",
        "dontKnow": "I don't know much about {0}, sorry."
    }

Again, these can be generic and the topic name replace {0}.



NPC Data

If you are not familiar with Content Patcher, you might need to go learn how it works. I'll leave it up to you to figure out how to actually create a Content Patcher mod, as that's not my business.

This framework looks in the dialogue data for the NPC you click on, i.e. Characters/Dialogue/<NPCNAME>.

So, a CP mod might start like this:

{
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Characters/Dialogue/Sebastian",
            "Entries": {
                "DialogueTrees_question_playRpgGame_1": "Hey, would you like to play a role-playing game?",

The keys are coded based on the type of key. There are four types of key you can implement:

Questions

Questions are the text spoken by the NPC and shown above the list of potential player responses. They can be much more than a question, and you might only want a single response in certain cases, but the key format is (as in the example above):

DialogueTrees_question_<QuestionID>_<QuestionChoice>

The QuestionChoice on the end is to allow for multiple text choices, e.g.:

DialogueTrees_question_playRpgGame_1
DialogueTrees_question_playRpgGame_2
etc.

The framework will choose an option at random if there are more than one.


Responses

Responses are displayed when the player asks an NPC a question. They are formatted as follows:

DialogueTrees_response_<QuestionID>_<ResponseChoice>


Reactions

Reactions are shown by the NPC after the player selects a response, and before the next topic question text (if any).

Reactions are specific to the player response, and so the format is as follows:

DialogueTrees_reaction_<QuestionID>_<ResponseID>_<ReactionChoice>


Friendship

NPC friendship can change based on the player response to a question. Format is as follows:

DialogueTrees_friendship_<QuestionID>_<ResponseID>

The entry value will be the number of friendship points (positive or negative) added. E.g.:

"DialogueTrees_friendship_climateChange_concerned": "10"

This adds 10 friendship points if the player says they are concerned about climate change.


You can check out the mods I've created based on this framework for more detailed examples.


Technical

Requires SMAPI, doesn't use Harmony.

Compatible with Mod Updater for automatic updates.

Code is at https://github.com/aedenthorn/StardewValleyMods.

If you want to complain or ask for help or help me test my mods, you can visit my Discord server.

A list of all my mods for Stardew Valley is available at https://www.nexusmods.com/stardewvalley/articles/895.