Tutorial: Adding Items to a Shop

From The Stardew Modding Wiki
Jump to navigation Jump to search

Adding or removing inventory in a Stardew Valley shop is incredibly easy with Category:Shop Tile Framework (STF). This tutorial aims to walk you through adding a new item (vinegar) to Krobus' shop on Wednesdays and Sundays. You can see the end result on NexusMods. The general principles also apply for custom shops. You will just need to change the name of the shop to the NPC doing the selling.

You will notice that certain parts of this mod are very similar to setting up for other mods, such as Adding New Dialogue. However, there are a few key differences to watch out for. In general, however, once you've made one mod you'll find making more to be much easier because you will already understand how editing the code or using a Category:Frameworks works.

If you would like to make a video based on this tutorial, you are welcome to do so but please edit the page to add a link to your video for users who prefer to learn that way. :)

Future infobox info: CopperSun, April 30 2021

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

  1. Install Smapi if you haven't already
  2. Install Category:Shop Tile Framework.
  3. Get Notepad++, Visual Studio, or another text editing program designed for reading code. (You'll be using it for Json files.)

Finding Examples[edit | edit source | hide]

Examples are really the key to understanding any mod or coding project. Fortunately, there are LOTS for you to look at!

  1. Download another shop mod to see how it works.
    1. Krobus Sells Vinegar is the basis for this tutorial.
    2. Immersive Characters - Shane shows how to use STF with an original shop.
  2. To see how the mod is doing what it does, go into its folder in Stardew Valley\Mods and open up any of the files there. Start with shops.json and then take a look at what else they included.
    1. This is where you'll want to use Notepad++ or whatever editor you have. Notepad is fine and will work, but won't show you matching brackets, highlight variable names, etc.
    2. To get a first taste at modding, you can change an item sold in one of these mods, load up Smapi, and see your shop change in action. If you're not comfortable doing that yet, though, read on.
  3. Look at STF's documentation for formatting options and ideas.
    1. If you're brand-new to coding of any kind, think of this as a sort of dictionary. It's the place to look up how to use that "ExcludeFromMarnies" option or see how condition checking works.
    2. Once you know what you're doing, you'll be amazed at all the ideas that will come to you as you read through the list.

Creating a Manifest[edit | edit source | hide]

Now we're actually going to code!

  1. First, create a new folder in Stardew Valley\Mods and name it whatever you want your mod to be called. "Shop Test" is a perfectly fine name for now.
  2. In this folder, create two new files, "shops.json" and "manifest.json"
    1. You can create these files any way that works for you. I usually 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. I'll be using Notepad++.
    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 STF. It has everything you need for your shop mod's manifest.
  "Name": "A store mod",
  "Author": "your name",
  "Version": "1.0.0",
  "Description": "One or two sentences about the mod.",
  "UniqueID": "YourName.YourProjectName",
  "MinimumApiVersion": "3.0.0",
  "UpdateKeys": [],
  "ContentPackFor": {
    "UniqueID": "Cherry.ShopTileFramework"
It's important to include the first { and last }. These brackets/braces (technically "curly braces" if you have a pedantic friend) 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.
    1. Version is what version of your mod you are on. Generally, you will start with 1.0, then if after you release your mod you have an update you might call that 1.1, and so on. The version number in the manifest is how Smapi can tell if your mod has a newer version available or not.
    2. MinimumApiVersion refers to the minimum Smapi version required to run your mod. You need at least Smapi 3.0.0 to run STF.
    3. Leave UpdateKeys empty for now (but make sure to keep the "[ ]"!). You can fill it in later with a key from Nexus or wherever you release your mod.
    4. It's very important to list any frameworks that your mod requires to run in the ContentPackFor section. We're using Shop Tile Framework, so you can see that that is listed with its UniqueID of "Cherry.ShopTileFramework".
  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.)

Adding Your Content[edit | edit source | hide]

Now we're going to tell our mod what we want it to do. Because we're using Shop Tile Framework, we only need to specify what shop(s) we are editing and with what.

Here's the code we're going to use for your first shop mod. We're going to add vinegar to Krobus' shop and specify a price, how much he should stock per day, and when he sells it.
	"VanillaShops": //we are editing a shop that is in the original game
		"ShopName": "KrobusShop", //the shop we are editing is Krobus'
		"ItemStocks": [
			"ItemType": "Object", //we are adding an object for sale, not clothing, furniture, or something else
			"ItemNames": [ "Vinegar", ], //the item Krobus will sell is vinegar
			"IsRecipe": "false", //vinegar is not a recipe
			"StockPrice": 100, //Krobus should sell vinegar for 100
			"Stock": 3, //Krobus should have 3 vinegar in stock each day that he sells them
			"When": [ "d Mon Tue Thu Fri Sat", ], //Krobus will only sell vinegar Sunday and Wednesday. This line can be a little tricky!
		}, ],
		"PriceMultiplierWhen": { "0.75": [ "f Krobus 500" ], },
	}, ],
  1. First, open up the shops.json file you created earlier. Just like manifest.json, it needs to start with "{" and end with "}".
  2. Json files don't care about "white space" (blank spaces) unless they're inside quotation marks. Most people prefer to line up brackets visually so it's easy to see where they go.
  3. Any text following // is a "comment," which means it is not read by the program. You can put whatever comments you want in your code. It's a good idea to remind yourself what each section does!
    1. You can also use /* and */ to make large sections of your code a comment and invisible to Smapi.
  4. "VanillaShops": means that we are editing a shop that is part of the original Stardew Valley ("Vanilla").
    1. We could also use just "Shops" to refer to another mod's shop, or if we were removing items from a vanilla shop's inventory we could use "RemoveItemsFromVanilla". There are other options as well. As always, see the documentation for ideas.
    2. See the quotation marks and the comma? Those are Very Important. They're used to make sure the json file is read correctly by Smapi. Don't leave them out!
  5. Next we have just one bracket, [.
    1. This bracket signifies that we can now list a bunch of different changes. Technically, our list is an array. You may remember arrays from math class. In this case, just remember that you need a [ at the beginning and a ] at the very end to close your array and tell Smapi you're done listing your shop changes.
  6. That bracket is followed by a single {.
    1. This means we're about to specify a specific change to a specific shop, and everything inside this curly brace goes with this specific change we want to make. It will need to be closed and followed by a comma before we can add another change later.
  7. "ShopName": "KrobusShop",
    1. The shop we are going to change is called "KrobusShop". You need to make sure this name is exactly correct, including capitalization, or else Smapi will not know which shop you are referring to.
    2. You can find a list of all the vanilla shop names in the documentation.
    3. Notice that for each of these lines there are two pieces, each in quotation marks. The first part is called a key and the second is a value. The key here is "ShopName" and the value is "KrobusShop". Keys and values are the heart of how json files work.
  8. "ItemStocks": [
    1. Now we're going to list what we want Krobus to stock when. See that bracket? That means we've got another array, aka a list of things. Like all of our brackets, we'll have to make sure we have a matching ] at the end.
  9. {
    1. Each stock item in our ItemStocks array needs to be enclosed in braces. We're only specifying one stock change here, but could theoretically stuff his shop full of every item in the game, so long as we properly used our braces.
  10. "ItemType": "Object",
    1. The item we're going to add is an object. It is not furniture, or clothes, or a ring, or anything else special like that.
    2. Once again, look at the documentation for other options when you start making your own inventory changes.
  11. "ItemNames": [ "Vinegar", ],
    1. Here we're listing the names of the items we want to add in a - you guessed it! - array. We're only adding one item, but you could list as many as you want. Just put a comma after each item name. For example, [ "Vinegar", "Pumpkin", "Ruby", ]
    2. You don't technically need the last comma, but it doesn't hurt anything to include it and it's always a problem if you forget one that you do need, so it's not a bad idea to get in the habit of using commas after each item in an array even if it's the last one.
    3. Alternately, we could have used "ItemIDs": [ 419 ], to add vinegar. This does the same thing as our line but uses item IDs to specify which items we are adding instead of their names. [ 419, 276, 64, ] would add vinegar, pumpkins, and rubies. You can use either ItemNames or ItemIDs based on what is easiest for you.
    4. You can find a list of all items with their names and IDs on the official wiki.
  12. "IsRecipe": "false",
    1. This is not a recipe. :)
    2. Technically this line is optional and STF will assume you didn't mean for your item to be a recipe if you didn't explicitly tell it so, but there's nothing wrong with including it.
  13. "StockPrice": 100,
    1. Vinegar normally costs 200 at Pierre's, but Krobus is selling his at a discount. (Presumably he found a few bottles floating in the sewers and doesn't feel right charging full price.) If we did not include this line, STF would assume we wanted Krobus to also sell vinegar for 200.
  14. "Stock": 3,
    1. Krobus only has 3 bottles of vinegar to sell each day that he sells them.
    2. If we left this blank, STF would assume that Krobus has an infinite amount of vinegar to sell you.
  15. The author trying to figure out how to specify an item should only be available if the player has a Joja membership. The winner was [ "JojaMember" ].
    "When": [ "d Mon Tue Thu Fri Sat", ],
    1. This line specifies the conditions when Krobus will sell us vinegar. This is the trickiest part of using Shop Tile Framework!
    2. If we did not include a "When" key and value, STF would assume that Krobus always has vinegar to sell.
    3. This example uses "d Mon" to mean not on Mondays. Why the conditions work like that instead of just saying which day you do want is a mystery. ¯\_(ツ)_/¯
    4. You can get a list of condition options in the STF documentation. They are based on the same conditions used for events/cut scenes.
    5. If you're trying to do something tricky, it can be easier to test a lot of options at once by trying to add many items, each with a different condition, and then seeing which one(s) appear in the shop you are targeting.
  16. }, ],
    1. We're done with both this shop change and it's the last (and only) change we're making, so we can close both the brace for our stock change and the bracket for our stock changes list.
    2. This bracket is followed by a comma because there may be other keys and values we want to specify for our stock change. We don't have any other keys/values, but as always it's easier to have the comma and not need it than the other way around.
  17. "PriceMultiplierWhen": { "0.75": [ "f Krobus 500" ], },
    1. Krobus will give a discount on vinegar once we have two hearts (500 friendship points) with him.
    2. "0.75" means "multiply the usual sell price by .75 (in other words, make the items 25% off) when the conditions are met
    3. You can set several different multiplier options here as long as you pair each one with a set of conditions.
    4. These conditions work the same was as the ones used with "when"
  18. }, ],
    1. We're done editing Krobus' shop, so we can close this brace too. And we're done with our list of vanilla shop changes, so that bracket can be closed.
  19. }
    1. And last, we have one more closing brace. This one is to tell Smapi that our json file has come to an end. Don't forget it!
  20. Hit save on your file and use https://smapi.io/json to make sure you've got all your brackets, braces, and commas right.
    1. If you copy-pasted this code exactly, the Json checker should find no errors.
  21. Your mod is now ready to run! Load up Smapi, visit Krobus on a Sunday or Wednesday, and see your changes!
  22. That's it! You've made your first mod and seen it in action!

What's next?[edit | edit source | hide]

Now that you have the basics down, you can go wild changing every shop in town. The best advice is to look at other mods and the documentation for ideas, then play around in your mod and see what you can do. Have fun!

PS: Interesting in writing a tutorial for this wiki? We'd love to have you! No qualifications are needed. Just create a new page, call it "Tutorial: Doing a Thing" (name as appropriate), and start sharing your knowledge. :)