Tutorial: Adding a New Crop

From Stardew Modding Wiki
Jump to navigation Jump to search

A simple 1.6 guide to adding a new crop to the game using Content Patcher, adapted from 6480's Mouse-Ear Cress example.

Setting Up

The rest of this guide assumes you are aware of how to make a Content Patcher mod, but if not follow these steps first:

  1. Install SMAPI if you haven't already
  2. Install Content Patcher.
  3. Read the author guide for Content Patcher and try making a basic Content pack.

Additionally, it's recommended that you:

  1. Use a text editor with Json support, for example Visual Studio Code and Notepad++.
  2. Unpack the game files so that you can understand the layout of the data, in particular take a look at Data/Objects and Data/Crops. Crops also have a specific number of sprites that are allowed, and the base game crops serve as a good template.
  3. Become comfortable with using debug commands from the SMAPI console, here are some relevant commands:
    1. world_clear current removable: clears every removable thing in your current area, useful for clearing your test save's farm
    2. debug sleep: instantly pass the day
    3. patch reload <YourModUniqueId>: reload your mod without quitting the game

Loading the Textures

First, we will need the sprites. For clarity and simplicity we put the objects on 1 sprite, and the crop on another sprite. Object sprites are 16x16 each, and crop sprites consist of up to 8 16x32 sprites (128x32 total). The first 2 sprites are seed variations, followed by up to 5 sprites for growth phases, and a final sprite reserved for regrowing crops.

To put these assets into the game, we need to do a Load to an asset name, prefixed with {{ModId}} so that you don't conflict with another mod.

{
    "Format": "2.7.0",
    "Changes": [
        {
            "Action": "Load",
            // Multiple textures at once for convenience. If you want, you can list one at a time with one "load" action block for each.
            "Target": "{{ModId}}/objects, {{ModId}}/crops",
            //Target is the custom texture name to use. This needs to be unique between mods, so it is highly recommended to include your *unique mod Id* as part of the path. Texture name can be anything
            //You can also include multiple items or crops on the same spritesheet.
            "FromFile": "assets/{{TargetWithoutPath}}.png"
            //Using {{TargetWithoutPath}} automatically pulls from the .png image with the same name as the texture
            //In this case, "assets/objects.png" and "assets/crops.png". You can use any folder name as long as your image and code match.
        },
    ]
}

From this point on, we will refer to our two textures as {{ModId}}/objects and {{ModId}}/crops

Adding Crop Objects

Then, let's add our objects: the seed, and the produced item. Generally you should use {{ModId}}_YourItem format when assigning item ids so that your item won't override anyone else's.

{
    "Format": "2.7.0",
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Data/Objects",
            "Entries": {
                // SEED ITEM
                "{{ModId}}_PhilSeeds": {
                    "Name": "{{ModId}}_PhilSeeds",
                    "Displayname": "{{i18n:PhilSeeds.name}}",
                    "Description": "{{i18n:PhilSeeds.description}}",
                    "Type": "Seeds",
                    "Category": -74, //crop seeds must be category -74 to plant crops
                    "Price": 40,
                    // Texture must exactly match the name of one of your loaded textures, NOT your .png
                    "Texture": "{{ModId}}/objects",
                    // Tells the game what position on the spritesheet (in this case, objects.png) to look for your item. Indexes start at 0.
                    "SpriteIndex": 0,
                }
                // PRODUCED ITEM
                "{{ModId}}_Phil": {
                    // This is the internal name of the item, not the name shown to players.
                    // It is ecommended to match your Item ID exactly to prevent confusion with cooking/crafting recipes, but it can be anything.
                    "Name": "&lt;nowiki&gt;{{ModId}}_Phil",
                    // DisplayName and Description are set with i18n, so that they can be translated
                    // These i18n keys are automatically linked to the data in the i18n folder for translation purposes. If you dont intend to ever translate your mod, you can just put a normal string here instead, like "The Captured Essence of Early Spring"
                    // i18n keys only need to be unique inside your mod
                    "Displayname": "{{i18n:Phil.name}}",
                    "Description": "{{i18n:Phil.description}}",
                    "Type": "Basic",
                    // The category of Phil is flowers
                    "Category": -80,
                    // Money earned when player sells it
                    "Price": 100,
                    "Edibility": 5,
                    "Texture": "{{ModId}}/objects",
                    "SpriteIndex": 1,
                    // By default crops count for shipping, but this can be set to true if you don't want that
                    "ExcludeFromShippingCollection": false,
                }
            }
        },
    ]
}

Adding the Crop

For our seed to become plantable, we must add the Data/Crops entry matching the seed.

{
    "Format": "2.7.0",
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Data/Crops",
            "Entries": {
                "{{ModId}}_PhilSeeds": { //this must EXACTLY match the item id of your seeds item
                    // The crop grows in all 3 seasons
                    "Seasons": [
                        "spring",
                        "summer",
                        "fall"
                    ],
                    // The crop has 5 phases that each takes 1 day, making it 5 total days to harvest
                    "DaysInPhase": [ // First two seed sprites on the crop image are not counted as a phase, instead they are seed variants
                        1,
                        1,
                        1,
                        1,
                        1
                    ],
                    // For this example, we made a regrowable crop. Non regrowable crops use -1 in this field
					// Regrowing crops show the second to last sprite when they have produce, and the final sprite when they are regrowing
                    "RegrowDays": 5,
                    "HarvestMinStack": 1,
                    "HarvestMaxStack": 2,
                    "HarvestItemId": "{{ModId}}_Phil",
                    "Texture": "{{ModId}}/crops",
                    "SpriteIndex": 0,
                    // Crops do not count for either of these achievements unless the corresponding field is set
                    "CountForMonoculture": false,
                    "CountForPolyculture": false,
                }
            }
        },
    ]
}

Sell the Seed at a Shop

The player needs a way to obtain their seeds, shops is the typical place for this.

{
    "Format": "2.7.0",
    "Changes": [
        { 
            "Action": "EditData",
            "Target": "Data/Shops",
            // Since Carpenter is an existing shop, we need to avoid overwriting the entire entry and only add 1 new item
            "TargetField": [
                "Carpenter",
                "Items"
            ],
            "Entries": {
                // Add the seed item to robin's shop
                "{{ModId}}_PhilSeeds": {
                    "Id": "{{ModId}}_PhilSeeds",
                    "ItemId": "{{ModId}}_PhilSeeds"
                }
            },
            "MoveEntries": [
                {
                    // Move the new seed entry in Robin's shop higher up. Optional
                    "Id": "{{ModId}}_PhilSeeds",
                    "AfterID": "(BC)200"
                }
            ]
        }
    ]
}

At this point, you have created a crop!