Tutorial: Adding a Quest

From The Stardew Modding Wiki
Jump to navigation Jump to search

Future infobox info: Ceruleandeep, May 10 2021

Getting ready[edit | edit source | hide | hide all]

Install Quest Framework

Open up the documentation and bookmark it

Get Notepad++ (Windows), TextMate (Mac), Visual Studio (Windows/Mac/Linux), or another text editing program designed for reading code. (You'll be using it for Json files.)

Setting up your mod[edit | edit source | hide]

  1. Create a new folder in Stardew Valley\Mods and name it whatever you want your mod to be called. "Test Quests" will do for now.
  2. In this folder, create a new file "manifest.json"
    1. You can create JSON files any way that works for you. On Windows you can right-click inside of the folder and choose "New->Text Document" and then rename the file including the extension. You could also create them by choosing "New" inside your text editing program of choice.
  3. Open manifest.json in your editing program.
    1. We're starting with the Manifest because it is short, easy, and every mod needs one to run with Smapi.
  4. The manifest documentation on the official wiki is very clear and simple, so start by looking at that.
  5. We'll be using the sample manifest from QF. It has everything you need for your quest mod's manifest.
{
  "Name": "Your Project Name",
  "Author": "your name",
  "Version": "1.0.0",
  "Description": "One or two sentences about the mod.",
  "UniqueID": "YourName.YourProjectName",
  "MinimumApiVersion": "3.6.0",
  "UpdateKeys": [],
  "ContentPackFor": {
    "UniqueID": "PurrplingCat.QuestFramework", // Quest Framework unique id must be here
    "MinimumVersion": "1.2.0" // optional
  }
}
It's important to include the first { and last }. These braces tell Smapi where your file begins and ends. All json files utilized by SMAPI use them.
  1. Copy that text into your manifest.json file exactly as it appears.
  2. Change the appropriate text to be for your own mod.
    • You don't need to change anything now.
    • But it's fun and easy to change Name, Author, and UniqueID.
    • UniqueID is usually a lowercased, no-spaces version of your nickname and the project name. e.g. ceruleandeep.testquests
  3. Save your file.
  4. Triple-check that you got all the right brackets and commas in the right places by uploading your manifest.json file at https://smapi.io/json
  5. Congrats! You just made your first json. That's programming! (Sort of.)

Always Be Testing[edit | edit source | hide]

You haven't made any quests yet, so believe it or not, now is an ideal time to test your work.

  1. Run Stardew Valley.
  2. Check the SMAPI console log for any errors
  3. Check that your quest mod is being loaded. It might look like:
    • [SMAPI]    Test Quests 1.0.0 by ceruleandeep | for Quest Framework | One or two sentences about the mod.
  4. Note that your quest mod is being ignored, because you haven't written any quests yet:
    • [Quest Framework] Content pack `Test Quests` has no entry file `quests.json`

If your mod isn't being loaded, go back and fix the problem. If it's all good, you know what to do next... make a quests.json!

Adding a bulletin-board quest[edit | edit source | hide]

First we'll make a standard quest that will appear on the bulletin board at Pierre's.

Perch-notice.png Perch-journal.png Emily-reply.png

When you accept the quest and deliver a piece of wood to Emily, you'll receive 60g and some friendship.

Make a quests.json in your mod's folder. Paste this code in:
{
  "Format": "1.0",
  "Quests": [
    {
      "Name": "parrot_perch",
      "Type": "ItemDelivery",
      "Title": "Parrot Perch",
      "Description": "I want to make a perch for my bird friends. Please bring me a piece of wood.",
      "Objective": "Bring wood to Emily",
      "DaysLeft": 5,
      "Reward": 60,
      "RewardType": "Money",
      "Cancelable": true,
      "Trigger": "Emily 388",
      "ReactionText": "This is perfect, @! The birds will love it.",
      "FriendshipGain": {
        "Emily": 100
      }
    }
  ],
  "Offers": [
    {
      "QuestName": "parrot_perch",
      "OfferedBy": "Bulletinboard",
      "When": {
        "DaysOfWeek": "Monday Thursday Friday",
        "Seasons": "spring fall"
      }
    }
  ]
}
Save this json file and run the game again. You should see something like this in the SMAPI log:
[Quest Framework] Loaded 1 content pack:
[Quest Framework]     Test Quests 1.0.0 by ceruleandeep (ceruleandeep.testquests)
Tips for customizing this quest for your own needs:
  • 388 is the item code for Wood. You can look up the codes for other items at https://stardewids.com/
  • In the reaction text, the @ character is used to insert the player's name into the message
  • If you don't want a time limit on your quest, just remove the DaysLeft line

Add a second quest[edit | edit source | hide]

Here we add a second quest. To make it easy, a complete quests.json is included that you can copy and paste to update what you've got.

The second quest is another bulletin board quest, this time to deliver a Stone to Pierre. When you fulfill this quest you won't get any friendship boost (rude, Pierre!) but he will give you a parsnip.

Stone-notice.png Stone-reply.png Stone-reward.png

Notice how the two quests have a comma between their closing and opening braces: }, { When you add your own quests, it's your job to add these commas between quests.
{
  "Format": "1.0",
  "Quests": [
    {
      "Name": "parrot_perch",
      "Type": "ItemDelivery",
      "Title": "Parrot Perch",
      "Description": "I want to make a perch for my bird friends. Please bring me a piece of wood. Emily.",
      "Objective": "Bring wood to Emily",
      "DaysLeft": 5,
      "Reward": 60,
      "RewardType": "Money",
      "Cancelable": true,
      "Trigger": "Emily 388",
      "ReactionText": "This is perfect, @! The birds will love it.",
      "FriendshipGain": {
        "Emily": 100
      }
    },
    {
      "Name": "pet_rock",
      "Type": "ItemDelivery",
      "Title": "Pet Rock",
      "Description": "I need a very low-maintenance pet. I want someone to bring me a Stone to care for. Pierre.",
      "Objective": "Bring stone to Pierre",
      "RewardType": "Object",
      "Reward": "Parsnip",
      "RewardAmount": 1,
      "Cancelable": true,
      "Trigger": "Pierre 390",
      "ReactionText": "Thanks @, this one even looks like me!"
    }
  ],
  "Offers": [
    {
      "QuestName": "parrot_perch",
      "OfferedBy": "Bulletinboard",
      "When": {
        "DaysOfWeek": "Monday Thursday Friday",
        "Seasons": "spring fall"
      }
    },
    {
      "QuestName": "pet_rock",
      "OfferedBy": "Bulletinboard",
      "When": {
        "DaysOfWeek": "Tuesday Thursday",
        "Seasons": "spring fall"
      }
    }
    
  ]
}

Receiving a quest by mail[edit | edit source | hide]

We'll change the Pet Rock quest to be sent to you by mail.

Stone-letter.png

Change its entry in the Offers section to look like this:
{
      "QuestName": "pet_rock",
      "OfferedBy": "Mail",
      "OfferDetails": {
        "Topic": "A request from Pierre",
        "Text": "Dear @,^ I need a very low-maintenance pet. I want someone to bring me a Stone to care for.^Pierre."
      },
      "When": {
        "FriendshipStatus": "Pierre Friendly",
        "QuestNeverAccepted": "yes"
      }
    }
Now test it out. Introduce yourself to Pierre, sleep a night, then check your mailbox. The quest should appear as a new mail.

The When section determines when your quest gets offered. If you don't write anything, your player will get a mail on Spring 1, even though they don't know who Pierre is. As soon as they finish the quest, they will get another letter offering the same quest again. So this template gives you some good defaults: offer the quest after you're introduced, and only offer it to the player one time.

Another good When option is "FriendshipLevel": "Pierre 2", which says to offer the quest once the player has 2 hearts with Pierre. Quest Framework has many other options to control when quests get offered and re-offered.

Note: in the letter text, the ^ symbol lets you start a new line.

Lost item quest[edit | edit source | hide]

Remember the time Lewis lost his lucky shorts? It's happened again! But this time they'll be easy to find because they're right in the middle of the town square. Find them and return them to him to claim your reward.

Shorts-1.png Shorts-2.png Shorts-3.png

Shorts-4.png Shorts-5.png

Here's the Quests block:
    {
      "Name": "lewis_shorts",
      "Type": "LostItem",
      "Title": "Sneaky Shorts",
      "Description": "Lewis's shorts have vanished again. Where could they be?",
      "Objective": "Rescue Lewis's lucky purple shorts",
      "Trigger": "Lewis 789 Town 29 67",
      "RewardType": "Object",
      "Reward": "Trimmed Lucky Purple Shorts",
      "RewardAmount": 1,
      "ReactionText": "Have these... I don't want to see another pair of purple shorts as long as I live!",
      "FriendshipGain": {
        "Lewis": 100
      },
      "Cancelable": true
    }
Here's the Offers: block. It's been keep very short, so the quest is available from the bulletin board every day. Add more When rules if you like.
    {
      "QuestName": "lewis_shorts",
      "OfferedBy": "Bulletinboard",
    }
Don't forget to add commas between your blocks! The JSON validator can help you if you're having trouble.

Next steps[edit | edit source | hide]

Using debug mode to find map coordinates
In the beginning we named our mod folder "Test Quests". Actually it's customary to start all Quest Framework mod folders with [QF]. For example you might rename your mod folder to [QF] Test Quests or maybe even something a bit exciting.

These examples used wood and stones for testing because you can get them easily. You probably want to use rarer items in your quests. CJB Item Spawner mod lets you search for items and move them to your inventory for testing.

You might need to know the co-ordinates of a map square so that you can place a lost item there. Debug Mode mod lets you press the ~ key while playing the game, and see a popup with information about map squares.

Quest Framework is compatible with Json Assets. You can reference JA objects in triggers and use them as rewards.

Made with ❤️ by ceruleandeep 🌊