Changes

m
Pet behaviour Name key renamed to Id
Line 2: Line 2:     
{{Modder compatibility header}}
 
{{Modder compatibility header}}
{{upcoming|1.6.0}}
     −
This page explains how to update your mods for compatibility with the next major game version (tentatively {{version|1.6.0|Stardew Valley 1.6.0}}), and documents some of the changes and new functionality. See also [[Modding:Migrate to SMAPI 4.0|''Migrate to SMAPI 4.0'']].
+
This page explains how to update your mods for compatibility with {{version|1.6|Stardew Valley 1.6}}, and documents some of the changes and new functionality. See also [[Modding:Migrate to SMAPI 4.0|''Migrate to SMAPI 4.0'']].
 
  −
'''This describes an unreleased alpha version of the game. Things ''will'' change before it's released!'''
      
{{TOC|limit=3}}
 
{{TOC|limit=3}}
Line 18: Line 15:     
===How to update your mod===
 
===How to update your mod===
# Update your mod code and assets for the changes listed below (particularly [[#Breaking changes for C# mods|''Breaking changes for C# mods'']] and [[#Breaking changes for content packs|''Breaking changes for content packs'']]).
+
The rest of this page may seem overwhelming, but fortunately most of it probably doesn't apply to your specific mods. Here's a suggested 'quick start' guide to update a mod for Stardew Valley 1.6.
# If SMAPI still says your mod is incompatible, check the <samp>TRACE</samp> messages in the log file for the reason why.<br />If the logs say "''marked 'assume broken' in SMAPI's internal compatibility list''", you can increase the <samp>Version</samp> in your content pack's <samp>manifest.json</samp> file to bypass it.
+
 
# Test the mod in-game and make any other changes needed.
+
; For C# mods&#58;
 +
:# Update the [https://www.nuget.org/packages/Pathoschild.Stardew.ModBuildConfig mod build config NuGet package] to the latest version.
 +
:# In each <samp>.csproj</samp> project file, change <code>&lt;TargetFramework&gt;net5.0&lt;/TargetFramework&gt;</code> to <code>&lt;TargetFramework&gt;net6.0&lt;/TargetFramework&gt;</code>.<br /><small>(Tip: if the second line looks like <code>&lt;Project ToolsVersion=...</code> instead of <code>&lt;Project Sdk="Microsoft.NET.Sdk"&gt;</code>, you'll need to [[Modding:Migrate to Stardew Valley 1.5.5|migrate it to Stardew Valley 1.5.5]] first.)</small>
 +
:# Rebuild the solution.
 +
:# Fix any build errors. You can search this page for relevant info as needed.
 +
:# Review all build warnings (particularly obsolete-code warnings), which may indicate code that broke in 1.6.
 +
:# Increment your mod version in <samp>manifest.json</samp>.<br /><small>(Some mods may be added to SMAPI's compatibility blacklist due to runtime errors. Incrementing the mod version will fix that if so.)</small>
 +
:# Test to make sure the mod works.
 +
:# Skim through [[#Breaking changes for C# mods|''breaking changes for C# mods'']] and the table of contents, and check any section that might be relevant to the mod.
 +
 
 +
; For [[Modding:Content Patcher|Content Patcher]] packs&#58;
 +
:# Follow the [https://smapi.io/cp-migrate Content Patcher migration guide] until your content pack has <code>"Format": "2.0.0"</code>.<br /><small>'''Do not skip this step!''' Content Patcher will assume your content pack is pre-1.6 if you don't, which can cause confusing errors if you already updated it.</small>
 +
:# Review [[#Breaking changes for content packs|''breaking changes for content packs'']] and update the content pack as needed.
 +
 
 +
; For content packs which use another framework&#58;
 +
: See the documentation for the framework mod. Often you won't need to update the content pack if the framework mod itself was updated.
    
==What's new architecturally?==
 
==What's new architecturally?==
Line 32: Line 44:  
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record record structs];
 
* [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record record structs];
 
* and support for ARM64 on macOS.
 
* and support for ARM64 on macOS.
 +
 +
===Trigger actions===
 +
{{/doc status|[[Modding:Trigger actions]]|done=true}}
 +
 +
Trigger actions are a new feature which lets content packs perform an action when something happens, with support for a wide range of actions (like sending mail, changing friendship, starting a quest, etc).
 +
 +
For example, it lets you have logic like "''When the player arrives in the Farm location, if Leo has moved to the valley, then send a letter and start a conversation topic''":
 +
<syntaxhighlight lang="js">
 +
{
 +
    "Trigger": "LocationChanged",
 +
    "Location": "Farm",
 +
    "Condition": "PLAYER_HAS_FLAG Host leoMoved",
 +
    "Actions": [
 +
        "AddMail Current Abigail_LeoMoved Today",
 +
        "AddConversationTopic LeoMoved 5"
 +
    ]
 +
}
 +
</syntaxhighlight>
    
===Hash set fields===
 
===Hash set fields===
Line 88: Line 118:     
In Stardew Valley 1.6, you can now rewrite that code like <code>DataLoader.PassiveFestivals(Game1.content)</code>. That's simpler, you can't use the wrong asset name or type, and it's more future-proof in case the game changes them.
 
In Stardew Valley 1.6, you can now rewrite that code like <code>DataLoader.PassiveFestivals(Game1.content)</code>. That's simpler, you can't use the wrong asset name or type, and it's more future-proof in case the game changes them.
 +
 +
===Unique string IDs===
 +
{{/doc status|[[Modding:Common data field types#Unique string ID]]|done=true}}
 +
 +
Stardew Valley now uses ''unique string IDs'' throughout the code to identify data (like events, locations, items, NPCs, etc). For example, <code>Town</code> is the unique ID for the [[Pelican Town]] location; no other location can use that ID. The IDs are used for a wide range of purposes, from internal game logic to [[Modding:Content Patcher|content pack edits]].
 +
 +
For mods, it's '''strongly recommended''' to...
 +
* Use namespaced IDs prefixed with your [[Modding:Modder Guide/APIs/Manifest#Basic fields|mod's unique ID]] for all new content. For example, if your mod ID is <code>Example.PufferchickMod</code> and you're adding a pufferchick plushy, your item ID would look like <code>Example.PufferchickMod_PufferchickPlushy</code>. In a [[Modding:Content Patcher|Content Patcher pack]], you can use <code><nowiki>{{ModId}}_PufferchickPlushy</nowiki></code> to insert your mod ID automatically. This eliminates ID conflicts between mods, and makes it easy (for both troubleshooters and mod code) to identify which mod added a particular content. See [[Modding:Common data field types#Unique string ID|the new format docs]] for the recommended format.
 +
* Only use alphanumeric (a–z, A–Z, 0–9), underscore (<code>_</code>), and dot (<code>.</code>) characters in string IDs. This is important because they're often used in places where some characters have special meaning (like file names or [[#Game state queries|game state queries]]).
 +
 +
You can optionally migrate pre-1.6 content to use unique string IDs too, without breaking existing players' saves. This is recommended to reduce mod conflicts and simplify troubleshooting going forward. Here's how to migrate for each data type:
 +
{{collapse|migration steps for pre-1.6 content|content=&#32;
 +
{{{!}} class="wikitable"
 +
{{!}}-
 +
! content type
 +
! how to change IDs
 +
{{!}}-
 +
{{!}} [[Modding:Event data|event IDs]]<br />[[Modding:Items|item IDs]]<br />[[Modding:Mail data|mail IDs]]<br />[[Modding:Recipe data|recipe IDs]]<br />[[#Custom jukebox tracks|song IDs for jukebox]]
 +
{{!}} [[Modding:Content Patcher|Content Patcher]] adds a custom [[Modding:Trigger actions|trigger action]] which can migrate IDs everywhere in the save data.
 +
 +
For example, this migrates two crafting recipe IDs:
 +
<syntaxhighlight lang="js">
 +
{
 +
    "Action": "EditData",
 +
    "Target": "Data/TriggerActions",
 +
    "Entries": {
 +
        "{{ModId}}_MigrateToUniqueIds": {
 +
            "Id": "{{ModId}}_MigrateToUniqueIds",
 +
            "Trigger": "DayStarted",
 +
            "Actions": [
 +
                // Note: use double-quotes around an argument if it contains spaces. This example has single-quotes for
 +
                // the action itself, so we don't need to escape the double-quotes inside it.
 +
                'Pathoschild.ContentPatcher_MigrateIds CraftingRecipes "Puffer Plush" {{ModId}}_PufferPlush "Puffer Sofa" {{ModId}}_PufferSofa'
 +
            ],
 +
            "HostOnly": true
 +
        }
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 +
See the [https://github.com/Pathoschild/StardewMods/blob/develop/ContentPatcher/docs/author-guide/trigger-actions.md Content Patcher docs] for more info about using the trigger action, including restrictions and valid ID types.
 +
{{!}}-
 +
{{!}} [[Modding:Location data|location IDs]]
 +
{{!}} Add the old name to the location's <samp>FormerLocationNames</samp> field in <samp>Data/Locations</samp>.
 +
{{!}}-
 +
{{!}} [[Modding:NPC data|NPC internal names]]
 +
{{!}} Add the old name to the NPC's <samp>FormerCharacterNames</samp> field in <samp>Data/Characters</samp>.
 +
{{!}}-
 +
{{!}} [[Modding:Quest data|quest]] and [[Modding:Special orders|special order]] IDs
 +
{{!}} Currently there's no safe way to migrate quest and special order IDs, since removing and readding them will reset any progress the player has made on them.
 +
{{!}}}
 +
}}
    
==What's new for items==
 
==What's new for items==
 
===Custom items===
 
===Custom items===
 +
{{/doc status|[[Modding:Items]]|done=false}}
 +
 
====Overview====
 
====Overview====
 
Stardew Valley 1.6 makes three major changes to how items work in the game:
 
Stardew Valley 1.6 makes three major changes to how items work in the game:
Line 108: Line 192:  
| <samp>ItemId</samp>
 
| <samp>ItemId</samp>
 
| <samp>string</samp>
 
| <samp>string</samp>
| A [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this item which should be globally unique (but may not be for existing vanilla items for backwards compatibility). For example, <samp>128</samp> (vanilla item) or <samp>Example.ModId_Watermelon</samp> (custom item).
+
| A [[Modding:Common data field types#Unique string ID|unique string ID]] for this item which should be globally unique (but may not be for existing vanilla items for backwards compatibility). For example, <samp>128</samp> (vanilla item) or <samp>Example.ModId_Watermelon</samp> (custom item).
 
|-
 
|-
 
| <samp>QualifiedItemId</samp>
 
| <samp>QualifiedItemId</samp>
Line 143: Line 227:  
| &#32;
 
| &#32;
 
* Ingredients: both supported.
 
* Ingredients: both supported.
* Output: set field 2 to the unqualified item ID, and field 3 to one of <samp>true</samp> (bigcraftable) or <samp>false</samp> (object) or an item type identifier like <samp>BC</samp>.
+
* Output: set field 2 to the unqualified item ID, and field 3 to one of <samp>true</samp> (bigcraftable) or <samp>false</samp> (object).
 
|-
 
|-
 
| [[#Custom fruit trees|<samp>Data/fruitTrees</samp>]]
 
| [[#Custom fruit trees|<samp>Data/fruitTrees</samp>]]
Line 246: Line 330:  
             "Target": "Data/Objects",
 
             "Target": "Data/Objects",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Pufferchick": {
+
                 "{{ModId}}_Pufferchick": {
                     "Name": "Pufferchick",
+
                     "Name": "{{ModId}}_Pufferchick", // best practice to match the ID, since it's sometimes used as an alternate ID (e.g. in Data/CraftingRecipes)
 
                     "Displayname": "Pufferchick",
 
                     "Displayname": "Pufferchick",
 
                     "Description": "An example object.",
 
                     "Description": "An example object.",
Line 254: Line 338:  
                     "Price": 1200,
 
                     "Price": 1200,
   −
                     "Texture": "Mods/Example.ModId/Objects",
+
                     "Texture": "Mods/{{ModId}}/Objects",
 
                     "SpriteIndex": 0
 
                     "SpriteIndex": 0
 +
                }
 
             }
 
             }
 
         },
 
         },
Line 267: Line 352:  
                     "Operation": "Append",
 
                     "Operation": "Append",
 
                     "Target": ["Entries", "Universal_Love"],
 
                     "Target": ["Entries", "Universal_Love"],
                     "Value": "Example.ModId_Pufferchick",
+
                     "Value": "{{ModId}}_Pufferchick",
 
                     "Delimiter": " " // if there are already values, add a space between them and the new one
 
                     "Delimiter": " " // if there are already values, add a space between them and the new one
 
                 }
 
                 }
Line 278: Line 363:  
             "Target": "Data/Crops",
 
             "Target": "Data/Crops",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Pufferchick": {
+
                 "{{ModId}}_Pufferchick": {
 
                     "Seasons": [ "spring", "summer", "fall" ],
 
                     "Seasons": [ "spring", "summer", "fall" ],
 
                     "DaysInPhase": [ 1, 1, 1, 1, 1 ],
 
                     "DaysInPhase": [ 1, 1, 1, 1, 1 ],
                     "HarvestItemId": "Example.ModId_Pufferchick",
+
                     "HarvestItemId": "{{ModId}}_Pufferchick",
   −
                     "Texture": "Mods/Example.ModId/Crops",
+
                     "Texture": "Mods/{{ModId}}/Crops",
 
                     "SpriteIndex": 0
 
                     "SpriteIndex": 0
 +
                }
 
             }
 
             }
 
         },
 
         },
Line 291: Line 377:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Mods/Example.ModId/Crops, Mods/Example.ModId/Objects",
+
             "Target": "Mods/{{ModId}}/Crops, Mods/{{ModId}}/Objects",
 
             "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/Crops.png, assets/Objects.png
 
             "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/Crops.png, assets/Objects.png
         },
+
         }
 
     ]
 
     ]
 
}</nowiki>|lang=javascript}}
 
}</nowiki>|lang=javascript}}
Line 479: Line 565:  
</dl>
 
</dl>
   −
===Custom big craftables===
+
===Custom big craftables:===
 +
{{/doc status|[[Modding:Items#Big craftables]]|done=false}}
 +
 
 
You can now create/edit [[Modding:Items#Big craftables|big craftables]] by editing the new <samp>Data/BigCraftables</samp> asset, which replaces the previous slash-delimited <samp>Data/BigCraftablesInformation</samp>.
 
You can now create/edit [[Modding:Items#Big craftables|big craftables]] by editing the new <samp>Data/BigCraftables</samp> asset, which replaces the previous slash-delimited <samp>Data/BigCraftablesInformation</samp>.
   Line 529: Line 617:  
|-
 
|-
 
| <samp>Texture</samp>
 
| <samp>Texture</samp>
| The asset name for the texture containing the item's sprite. Defaults to <samp>TileSheets/Craftables</samp>.
+
| ''(Optional)'' The asset name for the texture containing the item's sprite. Defaults to <samp>TileSheets/Craftables</samp>.
 
|-
 
|-
 
| <samp>SpriteIndex</samp>
 
| <samp>SpriteIndex</samp>
| The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite.
+
| ''(Optional)'' The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite.
 
|}
 
|}
   Line 624: Line 712:  
| <samp>TintColors</samp>
 
| <samp>TintColors</samp>
 
| ''(Optional)'' The colors with which to tint the sprite when drawn (e.g. for colored flowers). A random color from the list will be chosen for each crop. See [[#Color fields|color format]]. Default none.
 
| ''(Optional)'' The colors with which to tint the sprite when drawn (e.g. for colored flowers). A random color from the list will be chosen for each crop. See [[#Color fields|color format]]. Default none.
 +
|-
 +
!colspan="2"| Achievements
 +
|-
 +
| <samp>CountForMonoculture</samp>
 +
| ''(Optional)'' Whether the player can ship 300 of this crop's harvest item to unlock the monoculture [[achievements|achievement]]. Default false.
 +
|-
 +
| <samp>CountForPolyculture</samp>
 +
| ''(Optional)'' Whether the player must ship 15 of this crop's harvest item (along with any other required crops) to unlock the polyculture [[achievements|achievement]]. Default false.
 
|-
 
|-
 
!colspan="2"| Advanced
 
!colspan="2"| Advanced
Line 638: Line 734:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
 
|-
 
|-
 
| <samp>Result</samp>
 
| <samp>Result</samp>
Line 682: Line 778:     
===Custom fences===
 
===Custom fences===
 +
{{/doc status|a new doc page|done=false}}
 +
 
You can now add or customize [[Crafting#Fences|fences]] by editing the <samp>Data/Fences</samp> asset.
 
You can now add or customize [[Crafting#Fences|fences]] by editing the <samp>Data/Fences</samp> asset.
   Line 729: Line 827:     
===Custom floors (craftable) & paths===
 
===Custom floors (craftable) & paths===
 +
{{/doc status|a new doc page|done=false}}
 +
 
You can now add or customize [[Crafting#Decor|craftable floors & paths]] by editing the <samp>Data/FloorsAndPaths</samp> asset.
 
You can now add or customize [[Crafting#Decor|craftable floors & paths]] by editing the <samp>Data/FloorsAndPaths</samp> asset.
   Line 738: Line 838:  
|-
 
|-
 
| <samp>ID</samp>
 
| <samp>ID</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this floor/path.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this floor/path.
 
|-
 
|-
 
| <samp>ItemId</samp>
 
| <samp>ItemId</samp>
Line 813: Line 913:     
===Custom machines===
 
===Custom machines===
You can now add/edit machine logic by editing the <samp>Data/Machines</samp> asset.
+
{{/doc status|[[Modding:Machines]]|done=true}}
 +
 
 +
You can now add/edit machine logic by editing the <samp>Data/Machines</samp> asset. This supports the full range of vanilla functionality, including calling custom code define in C# mods.
 +
 
 +
For C# mods, 1.6 also adds a new <samp>MachineDataUtility</samp> class and various <samp>Object</samp> to simplify working with machines in code. These are used by the game code itself to implement the base machine logic.
 +
 
 +
===Custom melee weapons===
 +
{{/doc status|[[Modding:Items#Weapons]]|done=false}}
 +
 
 +
[[Modding:Items#Weapons|Melee weapons]] are still stored in <samp>Data/Weapons</samp>, but that asset has been overhauled in Stardew Valley 1.6. The slash-delimited entries are now models to simplify edits and enable new features (like the new <samp>Projectiles</samp> feature).
    
This consists of a string → model lookup, where...
 
This consists of a string → model lookup, where...
* The key is the [[#Custom items|'''qualified''' item ID]] for the item which acts as a machine (like <samp>(BC)127</samp> for [[The Cave|mushroom boxes]]).
+
* The key is the unqualified [[#Custom items|item ID]] for the weapon.
* The value is a model with the fields listed below.
+
* The value is model with the fields listed below.
   −
====Item processing rules====
+
====Basic weapon info====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 825: Line 934:  
! effect
 
! effect
 
|-
 
|-
| <samp>OutputRules</samp>
+
| <samp>Name</samp>
| The output produced by this machine. If multiple output rules can be produced, the first available one is selected. This consists of a list of models with these fields:
+
| The internal weapon name.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>DisplayName</samp><br /><samp>Description</samp>
! effect
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the translated display name & description.
 
|-
 
|-
| <samp>Id</samp>
+
| <samp>Type</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this rule within the current machine (it doesn't need to be unique between machines).
+
| The weapon type. One of <samp>0</samp> (stabbing sword), <samp>1</samp> (dagger), <samp>2</samp> (club or hammer), or <samp>3</samp> (slashing sword).
|-
+
|}
| <samp>Triggers</samp>
  −
| When to apply this output rule. This can list any number of triggers; the output will apply if any of them match.
     −
This consists of a list of models with these fields:
+
====Appearance====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 844: Line 950:  
! effect
 
! effect
 
|-
 
|-
| <samp>Id</samp>
+
| <samp>Texture</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this trigger within the current rule.
+
| The asset name for the spritesheet containing the weapon's sprite.
 
|-
 
|-
| <samp>Trigger</samp>
+
| <samp>SpriteIndex</samp>
| ''(Optional)'' When this output rule applies. Defaults to <samp>ItemPlacedInMachine</samp>. The possible values are...
+
| The index within the <samp>Texture</samp> for the weapon sprite, where 0 is the top-left sprite.
* <samp>ItemPlacedInMachine</samp>: apply this rule when an item is placed into the machine. This is the most common machine behavior.
+
|}
* <samp>OutputCollected</samp>: apply this rule when the machine's previous output is collected. An output-collected rule won't require or consume the input items, and the input item will be the previous output. For example, this is used to reload the [[crystalarium]].
  −
* <samp>MachinePutDown</samp>: apply this rule when the machine is put down. For example, this is used to start the [[Worm Bin|worm bin]].
  −
* <samp>DayUpdate</samp>: apply this rule when a new day starts, if it isn't already processing output. For example, this is used for the [[Soda Machine|soda machine]].
     −
You can specify multiple values, like <code>"Trigger": "DayUpdate, MachinePutDown, OutputCollected"</code>.
+
====Stats====
|-
  −
| <samp>RequiredItemId</samp>
  −
| ''(Optional)'' The qualified or unqualified item ID for the item to match, if the trigger is <samp>ItemPlacedInMachine</samp> or <samp>OutputCollected</samp>. Defaults to allowing any item ID.
  −
|-
  −
| <samp>RequiredTags</samp>
  −
| ''(Optional)'' The [[Modding:Context tags|context tags]] to match against input items, if the trigger is <samp>ItemPlacedInMachine</samp> or <samp>OutputCollected</samp>. An item must have all of the listed tags to select this rule. You can negate a tag with <samp>!</samp> (like <code>"RequiredTags": [ "bone_item", "!fossil_item" ]</code> for bone items that aren't fossils).
  −
|-
  −
| <samp>RequiredCount</samp>
  −
| ''(Optional)'' The required stack size for the input item, if the trigger is <samp>ItemPlacedInMachine</samp> or <samp>OutputCollected</samp>. Default 1.
  −
|-
  −
| <samp>Condition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this trigger should be checked. Item-only tokens are valid for this check if the trigger is <samp>ItemPlacedInMachine</samp> or <samp>OutputCollected</samp>. Defaults to always true.
  −
|}
  −
|-
  −
| <samp>OutputItem</samp>
  −
| The items produced by this machine. If multiple output entries match, one will be selected randomly unless you specify <samp>UseFirstValidOutput</samp>. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 876: Line 963:  
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <samp>MinDamage</samp><br /><samp>MaxDamage</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported by machine output.
+
| The minimum and maximum based damage caused when hitting a monster with this weapon.
 
  −
Notes:
  −
<ul>
  −
<li>If <samp>ItemId</samp> or <samp>RandomItemId</samp> is set to an [[#Item queries|item query]] which returns multiple items, one item will be selected at random.</li>
  −
<li>The <samp>ItemId</samp> and <samp>RandomItemId</samp> can optionally contain special tokens, which will be replaced before the item ID is parsed. For example, you can use <code>FLAVORED_ITEM Wine DROP_IN_ID</code> to create a wine for whatever item was placed in the machine.
  −
{| class="wikitable"
   
|-
 
|-
! token
+
| <samp>Knockback</samp>
! replaced with
+
| ''(Optional)'' How far the target is pushed when hit, as a multiplier relative to a base weapon like the [[Rusty Sword]] (e.g. <samp>1.5</samp> for 150% of Rusty Sword's weight). Default 1.
 
|-
 
|-
| <samp>DROP_IN_ID</samp>
+
| <samp>Speed</samp>
| The qualified item ID for the item placed in the machine.
+
| ''(Optional)'' How fast the player can swing the weapon. Each point of speed is worth 40ms of swing time relative to 0. This stacks with the [[speed|player's weapon speed]]. Default 0.
 
|-
 
|-
| <samp>DROP_IN_PRESERVE</samp>
+
| <samp>Precision</samp>
| If the item placed into the machine is a flavored item like Apple Juice or Tuna Roe, the ''unqualified'' item ID for the flavor item (e.g. the apple in Apple Wine). Otherwise <samp>0</samp>.
+
| ''(Optional)'' Reduces the chance that a strike will miss. Default 0.
 
|-
 
|-
| <samp>NEARBY_FLOWER_ID</samp>
+
| <samp>Defense</samp>
| The item ID for a flower within 5 tiles of the machine, or <samp>-1</samp> if no flower is found. For example, [[Bee House|bee houses]] produce <code>FLAVORED_ITEM Honey NEARBY_FLOWER_ID</code>.
+
| ''(Optional)'' Reduces damage received by the player. Default 0.
|}
  −
</li>
  −
<li>The <samp>ObjectInternalName</samp> can optionally contain <samp>{0}</samp>, which will be replaced with the input item's internal name. This is used to prevent flavored items from stacking (''e.g.'' apple [[wine]] and blueberry wine).</li>
  −
<li>The <samp>Condition</samp> field will check the ''input'' (not output) item for item-related conditions.</li>
  −
</ul>
   
|-
 
|-
| <samp>PreserveType</samp>
+
| <samp>AreaOfEffect</samp>
| ''(Optional)'' The produced item's preserved item type, if applicable. This sets the equivalent flag on the output item. The valid values are <samp>Jelly</samp>, <samp>Juice</samp>, <samp>Pickle</samp>, <samp>Roe</samp> or <samp>AgedRoe</samp>, and <samp>Wine</samp>. Defaults to none.
+
| ''(Optional)'' Slightly increases the area of effect. Default 0.
 
|-
 
|-
| <samp>PreserveId</samp>
+
| <samp>CritChance</samp>
| ''(Optional)'' The produced item's preserved unqualified item ID, if applicable. For example, [[Wine|blueberry wine]] has its preserved item ID set to the [[blueberry]] ID. This can be set to <samp>DROP_IN</samp> to use the input item's ID. Default none.
+
| ''(Optional)'' The chance of a critical hit, as a decimal value between 0 (never) and 1 (always). Default 0.02.
 
|-
 
|-
| <samp>CopyColor</samp>
+
| <samp>CritMultiplier</samp>
| ''(Optional)'' Whether to inherit the color of the input item if it was a <samp>ColoredObject</samp>. This mainly affects [[roe]]. Default false.
+
| ''(Optional)'' A multiplier applied to the base damage for a critical hit. This can be a decimal value. Default 3.
 +
|}
 +
 
 +
====Game logic====
 +
{| class="wikitable"
 
|-
 
|-
| <samp>CopyPrice</samp>
+
! field
| ''(Optional)'' Whether to inherit the quality of the input item (before <samp>PriceModifiers</samp> are applied). This is ignored if the input or output aren't both object (<samp>(O)</samp>)-type.
+
! effect
 
|-
 
|-
| <samp>CopyQuality</samp>
+
| <samp>CanBeLostOnDeath</samp>
| ''(Optional)'' Whether to inherit the quality of the input item (before <samp>QualityModifiers</samp> are applied).
+
| Whether the player can [[Adventurer's Guild#Item Recovery Service|lose this tool when they die]]. Default true.
 
|-
 
|-
| <samp>PriceModifiers</samp><br /><samp>PriceModifiers</samp>
+
| <samp>MineBaseLevel</samp><br /><samp>MineMinLevel</samp>
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] applied to the output item's price. Default none.
+
| ''(Optional)'' The base and minimum mine level, which affect [[#Mine container drops|mine container drops]]. Both default to -1, which disables automatic mine drops.
|-
  −
| <samp>IncrementMachineParentSheetIndex</samp>
  −
| ''(Optional)'' Whether to increment the machine's spritesheet index by one while it's processing this output. This stacks with the <samp>ShowNextIndexWhenLoaded</samp> field (''i.e.'' setting both to true will increment the index by two). Default false.
  −
|-
  −
| <samp>OutputMethod</samp>
  −
| ''(Optional, specialized)'' A C# method which decides which item to produce. If set, the <samp>ItemId</samp> field is optional and ignored.
  −
 
  −
This must be specified in the form <samp>{{t|full type name}}.{{t|method name}}</samp> (like <samp>StardewValley.Object.OutputSolarPanel</samp>). The method must be static and match the game's <samp>MachineOutputDelegate</samp> method signature:
  −
<syntaxhighlight lang="c#">
  −
/// <summary>Get the output item to produce.</summary>
  −
/// <param name="machine">The machine instance for which to produce output.</param>
  −
/// <param name="inputItem">The item being dropped into the machine, if applicable.</param>
  −
/// <param name="probe">Whether the machine is only checking whether the input is valid. If so, the input/machine shouldn't be changed and no animations/sounds should play.</param>
  −
/// <param name="outputData">The item output data from <c>Data/Machines</c> for which output is being created, if applicable.</param>
  −
/// <param name="overrideMinutesUntilReady">The in-game minutes until the item will be ready to collect, if set. This overrides the equivalent fields in the machine data if set.</param>
  −
/// <returns>Returns the item to produce, or <c>null</c> if none should be produced.</returns>
  −
public static Item GetOutput(Object machine, Item inputItem, bool probe, MachineItemOutput outputData, out int? overrideMinutesUntilReady);
  −
</syntaxhighlight>
  −
 
  −
If this method returns null, the machine won't output anything.
  −
|-
  −
| <samp>CustomData</samp>
  −
| Machine-specific data provided to the machine logic, if applicable.
  −
 
  −
For example, the cask uses this to set the aging rate for each item:
  −
<syntaxhighlight lang="js">
  −
"OutputItem": {
  −
    "OutputMethod": "StardewValley.Objects.Cask.OutputCask",
  −
    "CustomData": {
  −
        "AgingMultiplier": 4
  −
    }
  −
}
  −
</syntaxhighlight>
   
|}
 
|}
|-
  −
| <samp>UseFirstValidOutput</samp>
  −
| ''(Optional)'' If multiple <samp>OutputItem</samp> entries match, whether to use the first match instead of choosing one randomly. Default false.
  −
|-
  −
| <samp>MinutesUntilReady</samp><br /><samp>DaysUntilReady</samp>
  −
| ''(Optional)'' The number of in-game minutes or days until the output is ready to collect. If both days and minutes are specified, days are used. If none are specified, the item will be ready instantly.
  −
|-
  −
| <samp>InvalidCountMessage</samp>
  −
| ''(Optional)'' If set, overrides the machine's main <samp>InvalidCountMessage</samp> field.
  −
|-
  −
| <samp>RecalculateOnCollect</samp>
  −
| ''(Optional)'' Whether to regenerate the output right before the player collects it, similar to [[Bee House|bee houses]]. If the new item is null, the original output is returned instead.
  −
|}
  −
|-
  −
| <samp>AdditionalConsumedItems</samp>
  −
| ''(Optional)'' A list of extra items required before <samp>OutputRules</samp> will be checked. If specified, every listed item must be present in the player, [[hopper]], or chest inventory (depending how the machine is being loaded).
     −
This consists of a list of models with these fields:
+
====Advanced====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 976: Line 1,007:  
! effect
 
! effect
 
|-
 
|-
| <samp>ItemId</samp>
+
| <samp>Projectiles</samp>
| The [[#Custom items|qualified or unqualified item ID]] for the required item.
+
| ''(Optional)'' The projectiles fired when the weapon is used, which continue along their path until they hit a monster and cause damage. A separate projectile is fired for each entry in this list.
|-
  −
| <samp>RequiredCount</samp>
  −
| ''(Optional)'' The required stack size for the item matching <samp>ItemId</samp>. Default 1.
  −
|-
  −
| <samp>InvalidCountMessage</samp>
  −
| ''(Optional)'' If set, overrides the machine's main <samp>InvalidCountMessage</samp> field.
  −
|}
  −
|-
  −
| <samp>AllowFairyDust</samp>
  −
| ''(Optional)'' Whether the player can add [[Fairy Dust|fairy dust]] to speed up the machine. Default true.
  −
|-
  −
| <samp>ReadyTimeModifiers</samp>
  −
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] applied to the produced item's processing time. The modifier conditions can use item-only tokens, which will check the ''input'' (not output) item.
  −
|-
  −
| <samp>ReadyTimeModifierMode</samp>
  −
| ''(Optional)'' A [[#Quantity modifiers|quantity modifier mode]] which indicates what to do if multiple modifiers apply at the same time. Default <samp>Stack</samp>.
  −
|}
     −
====Behavior tweaks====
+
This consists of a list of models with these fields (one projectile will fire for each entry in the list):
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,002: Line 1,016:  
! effect
 
! effect
 
|-
 
|-
| <samp>PreventTimePass</samp>
+
| <samp>Id</samp>
| ''(Optional)'' A list of cases when the machine should be paused, so the timer on any item being produced doesn't decrement. Possible values:
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for the projectile within the current weapon's data.
{| class="wikitable"
   
|-
 
|-
! value
+
| <samp>Damage</samp>
! effect
+
| ''(Optional)'' The amount of damage caused when the projectile hits a monster. Default 10.
 
|-
 
|-
| <samp>Outside</samp><br /><samp>Inside</samp>
+
| <samp>Explodes</samp>
| Pause when placed in an outside or inside location. For example, [[Bee House|bee houses]] don't work inside.
+
| ''(Optional)'' Whether the projectile explodes when it collides with something. Default false.
 
|-
 
|-
| <samp>Spring</samp><br /><samp>Summer</samp><br /><samp>Fall</samp><br /><samp>Winter</samp>
+
| <samp>Bounces</samp>
| Pause in the given season. For example, [[Bee House|bee houses]] don't work in winter.
+
| ''(Optional)'' The number of times the projectile can bounce off walls before being destroyed. Default 0.
 
|-
 
|-
 +
| <samp>MaxDistance</samp>
 +
| ''(Optional)'' The maximum tile distance the projectile can travel. Default 4.
 
|-
 
|-
| <samp>Sun</samp><br /><samp>Rain</samp>
+
| <samp>Velocity</samp>
| Pause on days with the given weather.
+
| ''(Optional)'' The speed at which the projectile moves. Default 10.
 
|-
 
|-
| <samp>Always</samp>
+
| <samp>RotationVelocity</samp>
| Always pause the machine. This is used in specialized cases where the timer is handled by [[#Advanced logic|advanced machine logic]].
+
| ''(Optional)'' The rotation velocity. Default 32.
|}
   
|-
 
|-
| <samp>AllowLoadWhenFull</samp>
+
| <samp>TailLength</samp>
| ''(Optional)'' Whether the player can drop a new item into the machine before it's done processing the last one (like the [[crystalarium]]). The previous item will be lost. Default false.
+
| ''(Optional)'' The length of the tail which trails behind the main projectile. Default 1.
 
|-
 
|-
| <samp>ClearContentsOvernightCondition</samp>
+
| <samp>FireSound</samp><br /><samp>BounceSound</samp><br /><samp>CollisionSound</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the machine should be emptied overnight, so any current output will be lost. Defaults to always false.
+
| ''(Optional)'' The sound played when the projectile is fired, bounces off a wall, or collides with something. All three default to none.
|}
  −
 
  −
====Audio & visuals====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>MinAngleOffset</samp><br /><samp>MaxAngleOffset</samp>
! effect
+
| ''(Optional)'' A random offset applied to the direction of the project each time it's fired. Both fields default to 0, in which case it's always shot at the 90° angle matching the player's facing direction.
 
|-
 
|-
| <samp>LoadEffects</samp><br /><samp>WorkingEffects</samp>
+
| <samp>SpriteIndex</samp>
| ''(Optional)'' The cosmetic effects shown when an item is loaded into the machine (for <samp>LoadEffects</samp>), or while it's processing the item (for <samp>WorkingEffects</samp>, based on the <samp>WorkingEffectChance</samp> probability). Both default to none. These consist of a list of models with these fields:
+
| ''(Optional)'' The sprite index in the <samp>TileSheets/Projectiles</samp> asset to draw for this projectile. Defaults to 11 (a glowing-yellow-ball sprite).
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>Item</samp>
! effect
+
| ''(Optional)'' The item to shoot. If set, this overrides <samp>SpriteIndex</samp>.
|-
+
 
| <samp>RequiredItemId</samp>
+
This consists of a list of models with these fields:
| ''(Optional)'' If set, only apply this effect if the main input item has this qualified or unqualified item ID.
  −
|-
  −
| <samp>RequiredTags</samp>
  −
| ''(Optional)'' If set, only apply this effect if the main input item has ''all'' of these [[Modding:Context tags|context tags]]. You can negate a tag with <samp>!</samp> (like <code>"RequiredTags": [ "bone_item", "!fossil_item" ]</code> for bone items that aren't fossils).
  −
|-
  −
| <samp>Sound</samp>
  −
| ''(Optional)'' An [[#Custom audio|audio cue ID]] to play. Defaults to no sound.
  −
|-
  −
| <samp>DelayedSounds</samp>
  −
| ''(Optional)'' The audio to play after a short delay. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,059: Line 1,058:  
! effect
 
! effect
 
|-
 
|-
| <samp>Sound</samp>
+
| ''common fields''
| The [[#Custom audio|audio cue ID]] to play.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for ammo items.
 +
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 +
|}
 +
|}
 +
 
 +
Note that these are magic projectiles fired when the weapon is used, they're not aimed directly like [[slingshot]] projectiles.
 
|-
 
|-
| <samp>Delay</samp>
+
| <samp>CustomFields</samp>
| The number of milliseconds until the sound should play.
+
| The [[#Custom data fields|custom fields]] for this entry.
 
|}
 
|}
|-
+
 
| <samp>ShakeDuration</samp>
+
===Custom movie concessions===
| ''(Optional)'' A duration in milliseconds during which the machine sprite should shake. Default none.
+
{{/doc status|[[Modding:Movie theater data]]|done=false}}
|-
+
: ''See also: [[#Custom movies|custom movies]].''
| <samp>Frames</samp>
+
 
| ''(Optional)'' The animation to apply to the machine sprite, specified as a list of offsets relative to the base sprite index. Default none.
+
You could already [[Modding:Movie theater data#Concession data|add/edit concessions]] sold in the [[Movie Theater|movie theater]], but conflicts were likely since each concession had an incrementing numeric ID which matched its position in the vanilla tilesheet.
|-
+
 
| <samp>Interval</samp>
+
Stardew Valley 1.6 addresses that with two changes:
| ''(Optional)'' The number of milliseconds for which each frame in <samp>Frames</samp> is kept on-screen. Default 100.
+
<ul>
|-
+
<li>The <samp>Id</samp> field is now a [[Modding:Common data field types#Unique string ID|unique string ID]].</li>
| <samp>TemporarySprites</samp>
+
<li>You can now use a different texture with two new required fields:
| ''(Optional)'' The temporary animated sprites to show. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,083: Line 1,087:  
|-
 
|-
 
| <samp>Texture</samp>
 
| <samp>Texture</samp>
| The asset name for the texture (under the game's <samp>Content</samp> folder) for the animated sprite.
+
| The asset name for the texture containing the concession's sprite.
 
|-
 
|-
| <samp>SourceRect</samp>
+
| <samp>SpriteIndex</samp>
| The pixel area for the first animated frame within the <samp>Texture</samp>, specified as an object with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields.
+
| The index within the <samp>Texture</samp> for the concession sprite, where 0 is the top-left sprite.
|-
  −
| <samp>PositionOffset</samp>
  −
| ''(Optional)'' A pixel offset applied to the sprite, relative to the top-left corner of the machine's collision box, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. Defaults to (0, 0).
  −
|-
  −
| <samp>Color</samp>
  −
| ''(Optional)'' A tint color to apply to the sprite. See [[#Color fields|color format]]. Default <samp>White</samp> (no tint).
  −
|-
  −
| <samp>AlphaFade</samp><br /><samp>Loops</samp><br /><samp>Rotation</samp><br /><samp>RotationChange</samp><br /><samp>ScaleChange</samp><br /><samp>SortOffset</samp>
  −
| ''(Optional)'' See equivalent fields in the [[#Event changes|<samp>temporaryAnimatedSprite</samp> event command]]. Default 0.
  −
|-
  −
| <samp>Frames</samp><br /><samp>Scale</samp>
  −
| ''(Optional)'' See equivalent fields in the [[#Event changes|<samp>temporaryAnimatedSprite</samp> event command]]. Default 1.
  −
|-
  −
| <samp>Interval</samp>
  −
| ''(Optional)'' See equivalent fields in the [[#Event changes|<samp>temporaryAnimatedSprite</samp> event command]]. Default 100.
  −
|-
  −
| <samp>Flicker</samp><br /><samp>Flip</samp>
  −
| ''(Optional)'' See equivalent fields in the [[#Event changes|<samp>temporaryAnimatedSprite</samp> event command]]. Default false.
   
|}
 
|}
|}
+
</li>
|-
+
</ul>
| <samp>WorkingEffectChance</samp>
  −
| ''(Optional)'' The percentage chance to apply <samp>WorkingEffects</samp> each time the day starts or the in-game clock changes, as a value between 0 (never) and 1 (always). Default 0.33.
  −
|-
  −
| <samp>LightWhileWorking</samp>
  −
| ''(Optional)'' The light emitted by the machine while it's processing an item. Default none.
     −
This consists of a list of models with these fields:  
+
For example, this content pack adds a new 'Pufferchick Pop' concession with a custom image:
{| class="wikitable"
+
{{#tag:syntaxhighlight|<nowiki>
|-
+
{
! field
+
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
! effect
+
    "Changes": [
|-
+
        {
| <samp>Radius</samp>
+
            "Action": "EditData",
| ''(Optional)'' The size of the area covered by the light effect, as a multiplier of the default radius (like <samp>1.5</samp> for an area 50% wider than the default). Default 1.
+
            "Target": "Data/Concessions",
|-
+
            "Entries": {
| <samp>Color</samp>
+
                "{{ModId}}_PufferchickPop": {
| ''(Optional)'' A tint color to apply to the light. See [[#Color fields|color format]]. Default <samp>White</samp> (no tint).
+
                    "Id": "{{ModId}}_PufferchickPop",  // must specify ID again when creating a new entry
|}
+
                    "Name": "{{ModId}}_PufferchickPop", // best practice to match the ID, since it's sometimes used as an alternate ID
|-
+
                    "DisplayName": "Pufferchick Pop",
| <samp>WobbleWhileWorking</samp>
+
                    "Description": "A cute cake pop shaped like a pufferchick.",
| ''(Optional)'' Whether the machine sprite should bulge in & out while it's processing an item. Default false.
+
                    "Price": 25,
|-
+
                    "Texture": "{{InternalAssetKey: assets/pufferchick-pop.png}}" // an image in your content pack
| <samp>ShowNextIndexWhileWorking</samp><br /><samp>ShowNextIndexWhenReady</samp>
+
                    "SpriteIndex": 0
| ''(Optional)'' Whether to show the next sprite in the machine's spritesheet while it's processing an item (<samp>ShowNextIndexWhileWorking</samp>) or ready (<samp>ShowNextIndexWhenReady</samp>). Default false.
+
                }
|}
+
            }
 +
        }
 +
    ]
 +
}</nowiki>|lang=javascript}}
   −
====Player interaction messages====
+
===Custom museum donations & rewards===
These only apply when the player interacts with a chest directly, instead of using a [[hopper]] or mod like {{nexus mod|1063|Automate}}.
+
{{/doc status|a new doc page|done=false}}
   −
{| class="wikitable"
+
You can now add/edit the items which the [[museum]] gives back in rewards through the new <samp>Data/MuseumRewards</samp> data asset.
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>InvalidItemMessage</samp>
  −
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the message shown in a toaster notification if the player tries to input an item that isn't accepted by the machine.
  −
|-
  −
| <samp>InvalidItemMessageCondition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether <samp>InvalidItemMessage</samp> should be shown. This can use item-related queries like <samp>ITEM_TYPE</samp>. Defaults to always true.
  −
|-
  −
| <samp>InvalidCountMessage</samp>
  −
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the message shown in a toaster notification if the input inventory doesn't contain this item, unless overridden by <samp>InvalidCountMessage</samp> under <samp>OutputRules</samp>.
     −
This can use extra custom tokens:
+
====Format====
* <samp>[ItemCount]</samp>: the number of remaining items needed. For example, if you're holding three and need five, <samp>[ItemCount]</samp> will be replaced with <samp>2</samp>.
+
The data asset consists of a string → model lookup, where...
|}
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the reward group.
 +
* The value is a model with the fields listed below.
   −
====Advanced logic====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,161: Line 1,133:  
! effect
 
! effect
 
|-
 
|-
| <samp>InteractMethod</samp>
+
| <samp>TargetContextTags</samp>
| ''(Optional)'' A C# method invoked when the player interacts with the machine when it doesn't have output ready to harvest.
+
| The items that must be donated to complete this reward group. The player must fulfill every entry in the list to unlock the reward. This consists of a list of models with these fields:
 
  −
This must be specified in the form <samp>{{t|full type name}}.{{t|method name}}</samp> (like <samp>StardewValley.Object.SomeInteractMethod</samp>). The method must be static and match the game's <samp>MachineInteractDelegate</samp> method signature:
  −
<syntaxhighlight lang="c#">
  −
/// <summary>The method signature for a custom <see cref="MachineData.InteractMethod"/> method.</summary>
  −
/// <param name="machine">The machine instance for which to produce output.</param>
  −
/// <param name="location">The location containing the machine.</param>
  −
/// <param name="player">The player using the machine.</param>
  −
/// <returns>Returns whether the interaction was handled.</returns>
  −
public static bool InteractWithMachine(Object machine, GameLocation location, Farmer player);
  −
</syntaxhighlight>
  −
|-
  −
| <samp>HasInput</samp><br /><samp>HasOutput</samp>
  −
| ''(Optional)'' Whether to force adding the <samp>machine_input</samp> or <samp>machine_output</samp> [[#New context tags|context tags]] respectively. This isn't needed for most machines, since they'll be set based on the <samp>OutputRules</samp> field. Default false.
  −
|-
  −
| <samp>IsIncubator</samp>
  −
| ''(Optional)'' Whether this machine acts as an incubator when placed in a building, so players can incubate eggs in it. Default false.
  −
 
  −
This is used by the [[incubator]] and [[Ostrich Incubator|ostrich incubator]]. The game logic assumes there's only one such machine in each building, so this generally shouldn't be used by custom machines that can be built in a vanilla [[barn]] or [[coop]].
  −
|-
  −
| <samp>StatsToIncrementWhenLoaded</samp><br /><samp>StatsToIncrementWhenHarvested</samp>
  −
| ''(Optional)'' The game stat counters to increment when an item is placed in the machine (<samp>StatsToIncrementWhenLoaded</samp>) or when the processed output is collected (<samp>StatsToIncrementWhenHarvested</samp>). Default none. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,189: Line 1,140:  
! effect
 
! effect
 
|-
 
|-
| <samp>StatName</samp>
+
| <samp>Tag</samp>
| The name of the stat counter field in <samp>Game1.stats</samp>. Stat names are case-insensitive.
+
| The [[Modding:Context tags|context tag]] for the items to require.
 
|-
 
|-
| <samp>RequiredItemId</samp>
+
| <samp>Count</samp>
| ''(Optional)'' If set, only increment the stat if the main input item has this qualified or unqualified item ID.
+
| The minimum number of items matching the context tags that must be donated.
|-
  −
| <samp>RequiredTags</samp>
  −
| ''(Optional)'' If set, only increment the stat if the main input item has ''all'' of these [[Modding:Context tags|context tags]]. You can negate a tag with <samp>!</samp> (like <code>"RequiredTags": [ "bone_item", "!fossil_item" ]</code> for bone items that aren't fossils).
   
|}
 
|}
   −
This can be used to increment both built-in stats (like <samp>GeodesCracked</samp> for the [[Geode Crusher|geode crusher]]) and custom stats. Using a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] is strongly recommended for custom stats to avoid conflicts.
+
For example, an entry with the tag <samp>forage_item</samp> and count 2 will require donating any two forage items.
 +
 
 +
Special case: an entry with the exact values <code>Tag: "", Count: -1</code> passes if the museum is complete (i.e. the player has donated the max number of items).
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>FlagOnCompletion</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| ''(Optional if <samp>RewardItemIsSpecial</samp> is true)'' Whether to add the <samp>ID</samp> value to the player's received mail. This is used to track whether the player has collected the reward, and should almost always be true. If this is omitted and <samp>RewardItemIsSpecial</samp> is false, the player will be able collect the reward infinite times. Default false.
|}
     −
====Interacting with machines in C#====
+
After the reward is collected, you can check this value using the <samp><nowiki>HasFlag</nowiki></samp> condition in [[Modding:Content Patcher|Content Patcher]].
Stardew Valley 1.6 adds two <samp>Object</samp> fields for reference:
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>RewardActions</samp>
! effect
+
| Run one or more [[Modding:Trigger actions|trigger action strings]]. For example, this adds {{price|500}} to the current player:
 +
<syntaxhighlight lang="js">
 +
"RewardActions": [
 +
    "AddMoney 500"
 +
]
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>lastOutputRuleId</samp>
+
| <samp>RewardItemId</samp>
| If this is a machine, the output rule ID for the rule being processed by the machine (if any).
+
| ''(Optional)'' The [[#Custom items|qualified item ID]] for the item given to the player when they donate all required items for this group. There's no reward item if omitted.
 
|-
 
|-
| <samp>lastInputItem</samp>
+
| <samp>RewardItemCount</samp>
| If this is a machine, the item that was dropped into the machine to start the current output (if any).
+
| ''(Optional)'' The stack size for the <samp>RewardItemId</samp> (if the item supports stacking). Default 1.
|}
  −
 
  −
And a few methods for processing items:
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>RewardItemIsSpecial</samp>
! effect
+
| ''(Optional)'' Whether to mark the <samp>RewardItemId</samp> as a special permanent item, which can't be destroyed/dropped and can only be collected once. Default false.
 
|-
 
|-
| <samp>IsMachineWorking()</samp>
+
| <samp>RewardItemIsRecipe</samp>
| Get whether the machine is currently processing an item.
+
| ''(Optional)'' Whether to give the player a cooking/crafting recipe which produces the <samp>RewardItemId</samp>, instead of the item itself. Ignored if the item type can't be cooked/crafted (i.e. non-object-type items). Default false.
 
|-
 
|-
| <samp>ShouldTimePassForMachine(location)</samp>
+
| <samp>CustomFields</samp>
| Get whether the machine should be updated in the given location. For example, this will return false for [[Solar Panel|solar panels]] placed indoors, or outdoors on a cloudy day.
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
  −
| <samp>GetMachineData()</samp>
  −
| Get the underlying machine data from <samp>Data/Machines</samp>.
  −
|-
  −
| <samp>PlaceInMachine(…)</samp>
  −
| Try to place an item in the machine using the rules from <samp>Data/Machines</samp>. This returns a boolean which indicates whether the machine was successfully started.
  −
|-
  −
| <samp>OutputMachine(…)</samp>
  −
| Try to set the machine output given the input item and an optional output rule to apply. Most code should call <samp>PlaceInMachine</samp> instead.
   
|}
 
|}
   −
A lot of the generic machine logic is also handled by a new <samp>MachineDataUtility</samp> class, which lets C# mods interact with machine data more directly. For example, you can check which output a machine would produce without actually updating the machine.
+
For example, this content pack adds two rewards (one mail and one item):
 +
{{#tag:syntaxhighlight|<nowiki>
 +
{
 +
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 +
    "Changes": [
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/MuseumRewards",
 +
            "Entries": {
 +
                // send a letter when a specific item is donated
 +
                "{{ModId}}_ShinyArtifact": {
 +
                    "TargetContextTags": [
 +
                        {
 +
                            "Tag": "id_{{ModId}}_ShinyArtifact", // unique context tag identifying the item by ID
 +
                            "Count": 1
 +
                        },
 +
                    ],
 +
                    "FlagOnCompletion": true,
 +
                    "RewardActions": [ "AddMail Current {{ModId}}_ShinyArtifact" ]
 +
                },
 +
 
 +
                // give item when 18 minerals are donated
 +
                "{{ModId}}_18MineralItems": {
 +
                    "TargetContextTags": [
 +
                        {
 +
                            "Tag": "item_type_minerals",
 +
                            "Count": 18
 +
                        },
 +
                    ],
 +
                    "RewardItemId": "(BC){{ModId}}_SuperMachine",
 +
                    "RewardItemCount": 1,
 +
                    "FlagOnCompletion": true
 +
                }
 +
            }
 +
        }
 +
    ]
 +
}</nowiki>|lang=javascript}}
   −
===Custom melee weapons===
+
See also [[Modding:Mail data|mail data]], [[#Custom items|custom items]], and [[#custom machines|custom machines]] to add the custom mail and items.
[[Modding:Items#Weapons|Melee weapons]] are still stored in <samp>Data/Weapons</samp>, but that asset has been overhauled in Stardew Valley 1.6. The slash-delimited entries are now models to simplify edits and enable new features (like the new <samp>Projectiles</samp> feature).
     −
This consists of a string → model lookup, where...
+
====Achievements====
* The key is the unqualified [[#Custom items|item ID]] for the weapon.
+
The ''A Complete Collection'' [[Achievements|achievement]] is automatically adjusted to require any custom donations added too. This is based on the number of donated items though, so removing custom donations later may incorrectly mark the museum complete (since you may have donated enough items to meet the total required).
* The value is model with the fields listed below.
     −
====Basic weapon info====
+
===Custom fruit trees===
{| class="wikitable"
+
{{/doc status|[[Modding:Fruit trees]]|done=false}}
 +
 
 +
====Data format====
 +
You can now add custom [[Fruit Trees|fruit trees]] by editing the revamped <samp>Data/fruitTrees</samp> asset. This consists of a string → model lookup, where...
 +
* The key is the [[#Custom items|unqualified item ID]] for the sapling item in <samp>Data/Objects</samp>.
 +
* The value is a model with the fields listed below.
 +
 
 +
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>Name</samp>
+
| <samp>DisplayName</samp>
| The internal weapon name.
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the tree's display name. This should return a display name without 'tree' (like <samp>Cherry</samp> for a cherry tree). This is used in UI messages like "''Your &lt;display name&gt; tree wasn't able to grow last night''".
 
|-
 
|-
| <samp>DisplayName</samp><br /><samp>Description</samp>
+
| <samp>Seasons</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the translated display name & description.
+
| The seasons in which the fruit tree bears fruit. This consists of an array of season names (any combination of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>).
 +
 
 +
'''Note:''' the previous '<samp>island</samp>' season value is no longer valid. Using <samp>summer</samp> is equivalent to how it worked before (since we now have [[#Custom location contexts|per-location seasons]]).
 
|-
 
|-
| <samp>Type</samp>
+
| <samp>Fruit</samp>
| The weapon type. One of <samp>0</samp> (stabbing sword), <samp>1</samp> (dagger), <samp>2</samp> (club or hammer), or <samp>3</samp> (slashing sword).
+
| The fruit items to add to the tree each day while the tree is in-season. The first matching fruit (if any) is selected each day.
|}
     −
====Appearance====
+
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
 
! effect
 
! effect
 +
|-
 +
| ''common fields''
 +
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for fruit items.
 +
 +
Notes:
 +
* If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 +
* Season conditions are ignored in non-seasonal locations like the [[greenhouse]] and [[Ginger Island]].
 +
|-
 +
| <samp>Season</samp>
 +
| ''(Optional)'' If set, the group only applies if the tree's location is in this season. This is ignored in non-seasonal locations like the [[greenhouse]] and [[Ginger Island]].
 +
|-
 +
| <samp>Chance</samp>
 +
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
 +
|}
 
|-
 
|-
 
| <samp>Texture</samp>
 
| <samp>Texture</samp>
| The asset name for the spritesheet containing the weapon's sprite.
+
| The asset name for the texture under the game's <samp>Content</samp> folder. Use <samp>\</samp> (or <samp>\\</samp> in JSON) to separate name segments if needed. For example, vanilla fruit trees use <samp>TileSheets\fruitTrees</samp>.
 +
|-
 +
| <samp>TextureSpriteRow</samp>
 +
| The tree's row index in the <samp>Texture</samp> spritesheet (e.g. 0 for the first tree, 1 for the second tree, etc).
 
|-
 
|-
| <samp>SpriteIndex</samp>
+
| <samp>PlantableLocationRules</samp>
| The index within the <samp>Texture</samp> for the weapon sprite, where 0 is the top-left sprite.
+
| ''(Optional)'' The rules to decide which locations you can plant the sapling in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
|}
+
 
 +
This consists of a list of models with these fields:
   −
====Stats====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,285: Line 1,283:  
! effect
 
! effect
 
|-
 
|-
| <samp>MinDamage</samp><br /><samp>MaxDamage</samp>
+
| <samp>Id</samp>
| The minimum and maximum based damage caused when hitting a monster with this weapon.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
 
|-
 
|-
| <samp>Knockback</samp>
+
| <samp>Result</samp>
| ''(Optional)'' How far the target is pushed when hit, as a multiplier relative to a base weapon like the [[Rusty Sword]] (e.g. <samp>1.5</samp> for 150% of Rusty Sword's weight). Default 1.
+
| Indicates whether the sapling can be planted in a location if this entry is selected. The possible values are:
|-
+
* <samp>Default</samp>: the sapling can be planted if the location normally allows it. This can be used to stop processing further rules, and/or set a custom <samp>DeniedMessage</samp>.
| <samp>Speed</samp>
+
* <samp>Allow</samp>: the sapling can be planted here, regardless of whether the location normally allows it.
| ''(Optional)'' How fast the player can swing the weapon. Each point of speed is worth 40ms of swing time relative to 0. This stacks with the [[speed|player's weapon speed]]. Default 0.
+
* <samp>Deny</samp>: the sapling can't be planted here, regardless of whether the location normally allows it.
 
|-
 
|-
| <samp>Precision</samp>
+
| <samp>Condition</samp>
| ''(Optional)'' Reduces the chance that a strike will miss. Default 0.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry applies. Default true.
 
|-
 
|-
| <samp>Defense</samp>
+
| <samp>PlantedIn</samp>
| ''(Optional)'' Reduces damage received by the player. Default 0.
+
| ''(Optional)'' The planting context to apply this rule for. The possible values are <samp>Ground</samp> (planted directly in the ground), <samp>GardenPot</samp> (planted in a [[Garden Pot|garden pot]]), or <samp>Any</samp>. Default <samp>Any</samp>.
 +
 
 +
Note that saplings can't be planted in garden pots.
 
|-
 
|-
| <samp>AreaOfEffect</samp>
+
| <samp>DeniedMessage</samp>
| ''(Optional)'' Slightly increases the area of effect. Default 0.
+
| ''(Optional)'' If this rule prevents planting the sapling, the tokenizable string to show to the player (or <samp>null</samp> to default to the normal behavior for the context). This also applies when the <samp>Result</samp> is <samp>Default</samp>, if that causes the planting to be denied.
|-
  −
| <samp>CritChance</samp>
  −
| ''(Optional)'' The chance of a critical hit, as a decimal value between 0 (never) and 1 (always). Default 0.02.
  −
|-
  −
| <samp>CritMultiplier</samp>
  −
| ''(Optional)'' A multiplier applied to the base damage for a critical hit. This can be a decimal value. Default 3.
   
|}
 
|}
  −
====Game logic====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>CustomFields</samp>
! effect
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
  −
| <samp>CanBeLostOnDeath</samp>
  −
| Whether the player can [[Adventurer's Guild#Item Recovery Service|lose this tool when they die]]. Default true.
  −
|-
  −
| <samp>MineBaseLevel</samp><br /><samp>MineMinLevel</samp>
  −
| ''(Optional)'' The base and minimum mine level, which affect [[#Mine container drops|mine container drops]]. Both default to -1, which disables automatic mine drops.
   
|}
 
|}
   −
====Advanced====
+
For example, this content pack adds a custom fruit tree, including [[#Custom items|custom items]] for the sapling and fruit:
{| class="wikitable"
  −
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>Projectiles</samp>
  −
| ''(Optional)'' The projectiles fired when the weapon is used, which continue along their path until they hit a monster and cause damage. A separate projectile is fired for each entry in this list.
     −
This consists of a list of models with these fields (one projectile will fire for each entry in the list):
+
{{#tag:syntaxhighlight|<nowiki>
{| class="wikitable"
+
{
|-
+
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
! field
+
    "Changes": [
! effect
+
        // add fruit + sapling items
|-
+
        // note: sapling must have an edibility under 0 (usually -300) to be plantable
| <samp>Id</samp>
+
        {
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the projectile within the current weapon's data.
+
            "Action": "EditData",
|-
+
            "Target": "Data/Objects",
| <samp>Damage</samp>
+
            "Entries": {
| ''(Optional)'' The amount of damage caused when the projectile hits a monster. Default 10.
+
                "{{ModId}}_Pufferfruit": {
|-
+
                    "Name": "{{ModId}}_Pufferfruit", // best practice to match the ID, since it's sometimes used as an alternate ID
| <samp>Explodes</samp>
+
                    "DisplayName": "Pufferfruit",
| ''(Optional)'' Whether the projectile explodes when it collides with something. Default false.
+
                    "Description": "An example fruit item.",
|-
+
                    "Type": "Basic",
| <samp>Bounces</samp>
+
                    "Category": -6,
| ''(Optional)'' The number of times the projectile can bounce off walls before being destroyed. Default 0.
+
                    "Price": 1200,
|-
  −
| <samp>MaxDistance</samp>
  −
| ''(Optional)'' The maximum tile distance the projectile can travel. Default 4.
  −
|-
  −
| <samp>Velocity</samp>
  −
| ''(Optional)'' The speed at which the projectile moves. Default 10.
  −
|-
  −
| <samp>RotationVelocity</samp>
  −
| ''(Optional)'' The rotation velocity. Default 32.
  −
|-
  −
| <samp>TailLength</samp>
  −
| ''(Optional)'' The length of the tail which trails behind the main projectile. Default 1.
  −
|-
  −
| <samp>FireSound</samp><br /><samp>BounceSound</samp><br /><samp>CollisionSound</samp>
  −
| ''(Optional)'' The sound played when the projectile is fired, bounces off a wall, or collides with something. All three default to none.
  −
|-
  −
| <samp>MinAngleOffset</samp><br /><samp>MaxAngleOffset</samp>
  −
| ''(Optional)'' A random offset applied to the direction of the project each time it's fired. Both fields default to 0, in which case it's always shot at the 90° angle matching the player's facing direction.
  −
|-
  −
| <samp>SpriteIndex</samp>
  −
| ''(Optional)'' The sprite index in the <samp>TileSheets/Projectiles</samp> asset to draw for this projectile. Defaults to 11 (a glowing-yellow-ball sprite).
  −
|-
  −
| <samp>Item</samp>
  −
| ''(Optional)'' The item to shoot. If set, this overrides <samp>SpriteIndex</samp>.
     −
This consists of a list of models with these fields:
+
                    "Texture": "Mods/{{ModId}}/Objects",
{| class="wikitable"
+
                    "SpriteIndex": 0
|-
+
                },
! field
+
                "{{ModId}}_Puffersapling": {
! effect
+
                    "Name": "{{ModId}}_Puffersapling",
|-
+
                    "DisplayName": "Puffersapling",
| ''common fields''
+
                    "Description": "An example tree sapling.",
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for ammo items.
+
                    "Type": "Basic",
 +
                    "Category": -74,
 +
                    "Price": 1200,
   −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
                    "Texture": "Mods/{{ModId}}/Objects",
|}
+
                    "SpriteIndex": 1
|}
+
                }
 +
            }
 +
        },
   −
Note that these are magic projectiles fired when the weapon is used, they're not aimed directly like [[slingshot]] projectiles.
+
        // add fruit tree
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
  −
|}
  −
 
  −
===Custom movie concessions===
  −
: ''See also: [[#Custom movies|custom movies]].''
  −
 
  −
You could already [[Modding:Movie theater data#Concession data|add/edit concessions]] sold in the [[Movie Theater|movie theater]], but conflicts were likely since each concession had an incrementing numeric ID which matched its position in the vanilla tilesheet.
  −
 
  −
Stardew Valley 1.6 addresses that with two changes:
  −
<ul>
  −
<li>The <samp>Id</samp> field is now a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]].</li>
  −
<li>You can now use a different texture with two new required fields:
  −
{| class="wikitable"
  −
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>Texture</samp>
  −
| The asset name for the texture containing the concession's sprite.
  −
|-
  −
| <samp>SpriteIndex</samp>
  −
| The index within the <samp>Texture</samp> for the concession sprite, where 0 is the top-left sprite.
  −
|}
  −
</li>
  −
</ul>
  −
 
  −
For example, this content pack adds a new 'Pufferchick Pop' concession with a custom image:
  −
{{#tag:syntaxhighlight|<nowiki>
  −
{
  −
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
  −
    "Changes": [
   
         {
 
         {
 
             "Action": "EditData",
 
             "Action": "EditData",
             "Target": "Data/Concessions",
+
             "Target": "Data/FruitTrees",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_PufferchickPop": {
+
                 "{{ModId}}_Puffersapling": {
                     "Id": "Example.ModId_PufferchickPop", // must specify ID again when creating a new entry
+
                     "DisplayName": "Pufferfruit",
                     "Name": "PufferchickPop",
+
                     "Seasons": [ "spring" ],
                     "DisplayName": "Pufferchick Pop",
+
                     "Fruit": [
                    "Description": "A cute cake pop shaped like a pufferchick.",
+
                        {
                     "Price": 25,
+
                            "Id": "E{{ModId}}_Pufferfruit",
                     "Texture": "{{InternalAssetKey: assets/pufferchick-pop.png}}" // an image in your content pack
+
                            "ItemId": "{{ModId}}_Pufferfruit"
                     "SpriteIndex": 0
+
                        }
 +
                     ],
 +
                     "Texture": "Mods/{{ModId}}/FruitTrees",
 +
                     "TextureSpriteRow": 0
 
                 }
 
                 }
 
             }
 
             }
         }
+
         },
    ]
  −
}</nowiki>|lang=javascript}}
     −
===Custom museum donations & rewards===
+
        // add images
You can now add/edit the items which the [[museum]] accepts in donation and gives back in rewards through the new <samp>Data/MuseumRewards</samp> data asset.
+
        {
 +
            "Action": "Load",
 +
            "Target": "Mods/{{ModId}}/FruitTrees, Mods/{{ModId}}/Objects",
 +
            "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/FruitTrees.png, assets/Objects.png
 +
        },
 +
    ]
 +
}</nowiki>|lang=javascript}}
 +
 
 +
The fruit trees can then be added to the game by giving the player a sapling item in the usual ways (e.g. from [[#Custom shops|a shop]]).
 +
 
 +
====Fruit items====
 +
For C# mods, the <samp>fruitsOnTree</samp> field (number of fruit on the tree) has been replaced by <samp>fruit</samp> (list of fruit items).
 +
 
 +
====Spawning fruit trees====
 +
Custom trees can be added to the game in two ways:
 +
* Spawn them on [[Modding:Maps|map tiles]] when the location is created, using the new <samp>SpawnTree: fruit {{t|tree ID}} {{o|growth stage on location created}} {{o|growth stage on day-update regrowth}}</samp> tile property. This must be added on the <samp>Paths</samp> layer, which must also have tile index 34 from the <samp>paths</samp> tilesheet.
 +
* Or give the player a seed item in the usual ways (e.g. from [[#Custom shops|a shop]], [[Modding:Mail data|mail letter]], etc).
 +
 
 +
===Custom objects===
 +
{{/doc status|[[Modding:Items#Objects]]|done=false}}
 +
 
 +
You can now create/edit objects (the main item type) by editing the new <samp>Data/Objects</samp> asset, which replaces the previous slash-delimited <samp>Data/objectInformation</samp>.
 +
 
 +
Besides the format change, this adds...
 +
* support for custom textures;
 +
* revamped geode drops with support for conditions, probabilities, and item queries;
 +
* expanded food/drink buffs (e.g. set a custom buff ID, add a custom buff icon, etc);
 +
* context tags (moved from the former <samp>Data/ObjectContextTags</samp> asset);
 +
* [[#Custom data fields|custom fields]] to let framework mods support additional features.
   −
====Format====
+
This consists of a string → model lookup, where...
The data asset consists of a string → model lookup, where...
+
* The key is the unqualified [[#Custom items|item ID]].
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the reward group.
   
* The value is a model with the fields listed below.
 
* The value is a model with the fields listed below.
    +
====Basic info====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
! effect
+
! purpose
 +
|-
 +
| <samp>Name</samp>
 +
| The internal item name.
 
|-
 
|-
| <samp>TargetContextTags</samp>
+
| <samp>DisplayName</samp><br /><samp>Description</samp>
| The items that must be donated to complete this reward group. The player must fulfill every entry in the list to unlock the reward. This consists of a list of models with these fields:
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>Type</samp>
! effect
+
| The item's general type, like <samp>Arch</samp> (artifact) or <samp>Minerals</samp>. See details at [[Modding:Items#Objects]].
 
|-
 
|-
| <samp>Tag</samp>
+
| <samp>Category</samp>
| The [[Modding:Context tags|context tag]] for the items to require.
+
| The [[Modding:Items#Categories|item category]].
 
|-
 
|-
| <samp>Count</samp>
+
| <samp>Price</samp>
| The minimum number of items matching the context tags that must be donated.
+
| ''(Optional)'' The price when sold by the player. This is not the price when bought from a shop. Default 0.
 
|}
 
|}
   −
For example, an entry with the tag <samp>forage_item</samp> and count 2 will require donating any two forage items.
+
====Appearance====
 
+
{| class="wikitable"
Special case: an entry with the exact values <code>Tag: "", Count: -1</code> passes if the museum is complete (i.e. the player has donated the max number of items).
   
|-
 
|-
| <samp>FlagOnCompletion</samp>
+
! field
| ''(Optional if <samp>RewardItemIsSpecial</samp> is true)'' Whether to add the <samp>ID</samp> value to the player's received mail. This is used to track whether the player has collected the reward, and should almost always be true. If this is omitted and <samp>RewardItemIsSpecial</samp> is false, the player will be able collect the reward infinite times. Default false.
+
! purpose
 
  −
After the reward is collected, you can check this value using the <samp><nowiki>HasFlag</nowiki></samp> condition in [[Modding:Content Patcher|Content Patcher]].
   
|-
 
|-
| <samp>RewardEventSeenFlag</samp>
+
| <samp>Texture</samp>
| ''(Optional)'' The ID to add to the player's event-seen list when the reward is collected. (You must still specify <samp>FlagOnCompletion</samp> or <samp>RewardItemIsSpecial</samp> either way.)
+
| The asset name for the texture containing the item's sprite. Defaults to <samp>Maps/springobjects</samp>.
 
  −
After the reward is collected, you can check this value using the <samp><nowiki>HasSeenEvent</nowiki></samp> condition in [[Modding:Content Patcher|Content Patcher]].
   
|-
 
|-
| <samp>RewardItemId</samp>
+
| <samp>SpriteIndex</samp>
| ''(Optional)'' The [[#Custom items|qualified item ID]] for the item given to the player when they donate all required items for this group. There's no reward item if omitted.
+
| The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite.
|-
  −
| <samp>RewardItemCount</samp>
  −
| ''(Optional)'' The stack size for the <samp>RewardItemId</samp> (if the item supports stacking). Default 1.
  −
|-
  −
| <samp>RewardItemIsSpecial</samp>
  −
| ''(Optional)'' Whether to mark the <samp>RewardItemId</samp> as a special permanent item, which can't be destroyed/dropped and can only be collected once. Default false.
  −
|-
  −
| <samp>RewardItemIsRecipe</samp>
  −
| ''(Optional)'' Whether to give the player a cooking/crafting recipe which produces the <samp>RewardItemId</samp>, instead of the item itself. Ignored if the item type can't be cooked/crafted (i.e. non-object-type items). Default false.
  −
|-
  −
| <samp>RewardMail</samp>
  −
| ''(Optional)'' A [[Modding:Mail data|mail ID]] to add to the player's mailbox tomorrow.
  −
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
   
|}
 
|}
   −
 
+
====Edibility====
For example, this content pack adds two rewards, one in form of a mail, the other a machine :
  −
 
  −
{{#tag:syntaxhighlight|<nowiki>
  −
{
  −
    "Format": "1.28.0",
  −
"Changes": [
  −
{
  −
"Action": "EditData",
  −
"Target": "Data/MuseumRewards",
  −
"Entries": {
  −
//Send a mail when a specific item is donated
  −
"Example.ModId_ShinyArtifact": {
  −
"TargetContextTags": [
  −
{
  −
"Tag": "id_example.modid_shinyartifact",//The unique context tag identifying the item
  −
"Count": 1
  −
},
  −
],
  −
"FlagOnCompletion": true,
  −
"RewardMail": "Example.ModId_ShinyArtifact"
  −
},
  −
//Gives a machine as reward when 18 minerals are donated.
  −
"Example.ModId_18MineralItems": {
  −
"TargetContextTags": [
  −
{
  −
"Tag": "item_type_minerals",
  −
"Count": 18
  −
},
  −
],
  −
"RewardItemId": "(BC)Example.ModId_SuperMachine",
  −
"RewardItemCount": 1,
  −
"FlagOnCompletion": true,
  −
  −
},
  −
},
  −
}
  −
]
  −
}</nowiki>|lang=javascript}}
  −
 
  −
The mail entry would then be added to [[Modding:Mail_data|mail data]] using the same key. See [[#Custom_items|Custom Items]] and [[#Custom_machines|Custom Machines]] to add the items themselves.
  −
 
  −
====Achievements====
  −
The ''A Complete Collection'' [[Achievements|achievement]] is automatically adjusted to require any custom donations added too. This is based on the number of donated items though, so removing custom donations later may incorrectly mark the museum complete (since you may have donated enough items to meet the total required).
  −
 
  −
===Custom fruit trees===
  −
====Data format====
  −
You can now add custom [[Fruit Trees|fruit trees]] by editing the revamped <samp>Data/fruitTrees</samp> asset. This consists of a string → model lookup, where...
  −
* The key is the [[#Custom items|unqualified item ID]] for the sapling item in <samp>Data/Objects</samp>.
  −
* The value is a model with the fields listed below.
  −
 
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
! effect
+
! purpose
 
|-
 
|-
| <samp>DisplayName</samp>
+
| <samp>Edibility</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the tree's display name. This should return a display name without 'tree' (like <samp>Cherry</samp> for a cherry tree). This is used in UI messages like "''Your &lt;display name&gt; tree wasn't able to grow last night''".
+
| ''(Optional)'' A numeric value that determines how much energy (edibility × 2.5) and health (edibility × 1.125) is restored when this item is eaten. An item with an edibility of -300 can't be eaten, values from -299 to -1 reduce health and energy, and zero can be eaten but doesn't change health/energy. Default -300.
 
|-
 
|-
| <samp>Seasons</samp>
+
| <samp>IsDrink</samp>
| The seasons in which the fruit tree bears fruit. This consists of an array of season names (any combination of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>).
+
| ''(Optional)'' Whether to drink the item instead of eating it. Default false.
 
  −
'''Note:''' the previous '<samp>island</samp>' season value is no longer valid. Using <samp>summer</samp> is equivalent to how it worked before (since we now have [[#Custom location contexts|per-location seasons]]).
   
|-
 
|-
| <samp>Fruit</samp>
+
| <samp>Buffs</samp>
| The fruit items to add to the tree each day while the tree is in-season. The first matching fruit (if any) is selected each day.
+
| ''(Optional)'' The buffs to apply to the player when this item is eaten, if any. Default none.
    
This consists of a list of models with these fields:
 
This consists of a list of models with these fields:
Line 1,570: Line 1,454:  
|-
 
|-
 
! field
 
! field
! effect
+
! purpose
 +
|-
 +
| <samp>Id</samp>
 +
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
 +
|-
 +
| <samp>Duration</samp>
 +
| ''(Optional if <samp>BuffId</samp> is set)'' The buff duration measured in in-game minutes. This can be set to <samp>-2</samp> for a buff that should last for the rest of the day.
 
|-
 
|-
| ''common fields''
+
| <samp>BuffId</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for fruit items.
+
| ''(Optional)'' The unique ID of a buff from [[#Custom buffs|<samp>Data/Buffs</samp>]] to apply, or <samp>null</samp> to ignore <samp>Data/Buffs</samp> and set the ID to <samp>food</samp> or <samp>drink</samp> depending on the item's <samp>IsDrink</samp> field.
   −
Notes:
+
If a buff from <samp>Data/Buffs</samp> is applied and you also specify other fields, here's how the buff data is combined:
* If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
{| class="wikitable"
* Season conditions are ignored in non-seasonal locations like the [[greenhouse]] and [[Ginger Island]].
+
|-
 +
! field
 +
! result
 +
|-
 +
| <samp>Duration</samp><br /><samp>IconTexture</samp><br /><samp>SpriteIndex</samp><br /><samp>GlowColor</samp>
 +
| If specified, the value in <samp>Data/Objects</samp> is used instead of the one in <samp>Data/Buffs</samp>. If omitted, defaults to the value from <samp>Data/Buffs</samp>.
 
|-
 
|-
| <samp>Season</samp>
+
| <samp>CustomAttributes</samp>
| ''(Optional)'' If set, the group only applies if the tree's location is in this season. This is ignored in non-seasonal locations like the [[greenhouse]] and [[Ginger Island]].
+
| The values from both entries are combined (e.g. +1 speed in <samp>Data/Objects</samp> and +1 speed in <samp>Data/Buffs</samp> results in +2 speed).
 
|-
 
|-
| <samp>Chance</samp>
+
| <samp>IsDebuff</samp>
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| The value in <samp>Data/Objects</samp> is used.
 
|}
 
|}
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>IsDebuff</samp>
| The asset name for the texture under the game's <samp>Content</samp> folder. Use <samp>\</samp> (or <samp>\\</samp> in JSON) to separate name segments if needed. For example, vanilla fruit trees use <samp>TileSheets\fruitTrees</samp>.
+
| ''(Optional)'' Whether this buff counts as a debuff, so its duration should be halved when wearing a Sturdy Ring. Default false.
 +
|-
 +
| <samp>IconTexture</samp>
 +
| ''(Optional)'' The asset name for the icon texture to load. This must contain one or more 16x16 icons in a grid of any size. If omitted, the game will draw a default icon based on the <samp>BuffId</samp> and <samp>CustomAttributes</samp> fields.
 +
|-
 +
| <samp>SpriteIndex</samp>
 +
| ''(Optional)'' The buff's icon index within the <samp>IconTexture</samp>, where 0 is the top-left icon. Default 0.
 
|-
 
|-
| <samp>TextureSpriteRow</samp>
+
| <samp>GlowColor</samp>
| The tree's row index in the <samp>Texture</samp> spritesheet (e.g. 0 for the first tree, 1 for the second tree, etc).
+
| ''(Optional)'' The glow color to apply to the player. See [[#Color fields|color format]]. Default none.
 
|-
 
|-
| <samp>PlantableLocationRules</samp>
+
| <samp>CustomAttributes</samp>
| ''(Optional)'' The rules to decide which locations you can plant the sapling in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
+
| The custom buff attributes to apply, if any.
 
  −
This consists of a list of models with these fields:
      +
This consists of a model with any combination of these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
! effect
+
! purpose
 
|-
 
|-
| <samp>Id</samp>
+
| <samp>FarmingLevel</samp><br /><samp>FishingLevel</samp><br /><samp>ForagingLevel</samp><br /><samp>LuckLevel</samp><br /><samp>MiningLevel</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the list.
+
| ''(Optional)'' An amount applied to the matching [[Skills|skill level]] while the buff is active. This can be negative for a debuff. Default 0.
 
|-
 
|-
| <samp>Result</samp>
+
| <samp>Attack</samp><br /><samp>Defense</samp><br /><samp>MagneticRadius</samp><br /><samp>MaxStamina</samp><br /><samp>Speed</samp>
| Indicates whether the sapling can be planted in a location if this entry is selected. The possible values are:
+
| ''(Optional)'' An amount applied to the player's [[attack]], [[defense]], [[Magnetism|magnetic radius]], maximum [[Energy|stamina]], or [[speed]] while the buff is active. This can be negative for a debuff. Default 0.
* <samp>Default</samp>: the sapling can be planted if the location normally allows it. This can be used to stop processing further rules, and/or set a custom <samp>DeniedMessage</samp>.
+
|}
* <samp>Allow</samp>: the sapling can be planted here, regardless of whether the location normally allows it.
  −
* <samp>Deny</samp>: the sapling can't be planted here, regardless of whether the location normally allows it.
   
|-
 
|-
| <samp>Condition</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry applies. Default true.
+
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.  
 +
|}
 +
|}
 +
 
 +
====Geodes & artifact spots====
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! purpose
 
|-
 
|-
| <samp>PlantedIn</samp>
+
| <samp>GeodeDrops</samp><br /><samp><samp>GeodeDropsDefaultItems</samp>
| ''(Optional)'' The planting context to apply this rule for. The possible values are <samp>Ground</samp> (planted directly in the ground), <samp>GardenPot</samp> (planted in a [[Garden Pot|garden pot]]), or <samp>Any</samp>. Default <samp>Any</samp>.
+
| ''(Optional)'' The items that can be dropped when breaking open this item as a [[Minerals#Geodes|geode]]. Specifying either or both fields automatically enables geode behavior for this item.
   −
Note that saplings can't be planted in garden pots.
+
You can specify one or both fields:
 +
<ul>
 +
<li><samp>GeodeDrops</samp> can be set to the specific items to drop. Default none. This consists of a list of models with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! purpose
 
|-
 
|-
| <samp>DeniedMessage</samp>
  −
| ''(Optional)'' If this rule prevents planting the sapling, the tokenizable string to show to the player (or <samp>null</samp> to default to the normal behavior for the context). This also applies when the <samp>Result</samp> is <samp>Default</samp>, if that causes the planting to be denied.
  −
|}
   
|-
 
|-
| <samp>CustomFields</samp>
+
| ''common fields''
| The [[#Custom data fields|custom fields]] for this entry.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported by geode drops.
|}
     −
For example, this content pack adds a custom fruit tree, including [[#Custom items|custom items]] for the sapling and fruit:
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 +
|-
 +
| <samp>Chance</samp>
 +
| ''(Optional)'' The probability that the item will be dropped if the other fields match, as a decimal value between 0 (never) and 1 (always). Default 1.
 +
|-
 +
| <samp>SetFlagOnPickup</samp>
 +
| ''(Optional)'' The mail flag to set for the current player when this drop is picked up.
 +
|-
 +
| <samp>Precedence</samp>
 +
| ''(Optional)'' The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Geode drops with the same precedence are checked in the order listed. Default 0.
   −
{{#tag:syntaxhighlight|<nowiki>
+
For consistency, vanilla drops mostly use these values:
{
+
* <samp>-1000</samp>: special overrides like the [[Golden Helmet]];
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
+
* <samp>0</samp>: normal items.
    "Changes": [
+
|}</li>
        // add fruit + sapling items
+
<li><samp>GeodeDropsDefaultItems</samp> chooses a predefined list of possible geode drops like [[clay]], [[coal]], [[Copper Ore|copper]], [[Iridium Ore|iridium]], etc. Default false.</li>
        // note: sapling must have an edibility under 0 (usually -300) to be plantable
+
</ul>
        {
  −
            "Action": "EditData",
  −
            "Target": "Data/Objects",
  −
            "Entries": {
  −
                "Example.ModId_Pufferfruit": {
  −
                    "Name": "Pufferfruit",
  −
                    "DisplayName": "Pufferfruit",
  −
                    "Description": "An example fruit item.",
  −
                    "Type": "Basic",
  −
                    "Category": -6,
  −
                    "Price": 1200,
     −
                    "Texture": "Mods/Example.ModId/Objects",
+
If both fields are specified, each geode will choose between them with an equal 50% chance. If <samp>GeodeDrops</samp> is specified but no entries match, the geode will use the <samp>GeodeDropsDefaultItems</samp> regardless of whether it's true.
                    "SpriteIndex": 0
+
|-
                },
+
| <samp>ArtifactSpotChances</samp>
                "Example.ModId_Puffersapling": {
+
| ''(Optional)'' If this is an artifact (i.e. the <samp>Type</samp> field is <samp>Arch</samp>), the chance that it can be found by digging [[Artifact Spot|artifact spots]] in each location.
                    "Name": "Puffersapling",
  −
                    "DisplayName": "Puffersapling",
  −
                    "Description": "An example tree sapling.",
  −
                    "Type": "Basic",
  −
                    "Category": -74,
  −
                    "Price": 1200,
     −
                    "Texture": "Mods/Example.ModId/Objects",
+
This consists of a string → model lookup, where:
                    "SpriteIndex": 1
+
* the key is the internal location name;
                }
+
* the value is the probability the item will spawn if checked, as a decimal value between 0 (never) and 1 (always).
            }
+
|}
        },
     −
        // add fruit tree
+
====Context tags & exclusions====
        {
+
{| class="wikitable"
            "Action": "EditData",
+
|-
            "Target": "Data/FruitTrees",
+
! field
            "Entries": {
+
! purpose
                "Example.ModId_Puffersapling": {
+
|-
                    "DisplayName": "Pufferfruit",
+
| <samp>ContextTags</samp>
                    "Seasons": [ "spring" ],
+
| ''(Optional)'' The custom [[Modding:Items#Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other object data). This is formatted as a list; for example:
                    "Fruit": [
+
<syntaxhighlight lang="json">
                        {
+
"ContextTags": [ "color_yellow", "fish_ocean", "fish_upright", "season_summer" ]
                            "Id": "Example.ModId_Pufferfruit",
+
</syntaxhighlight>
                            "ItemId": "Example.ModId_Pufferfruit"
+
|-
                        }
+
| <samp>ExcludeFromRandomSale</samp>
                    ],
+
| ''(Optional)'' Whether to exclude this item from shops when selecting random items to sell. Default false.
                    "Texture": "Mods/Example.ModId/FruitTrees",
+
|-
                    "TextureSpriteRow": 0
+
| <samp>ExcludeFromFishingCollection</samp><br /><samp>ExcludeFromShippingCollection</samp>
                }
+
| ''(Optional)'' Whether to exclude this item from the fishing/shipping collection and their respective effect on the [[perfection|perfection score]]. Default false, in which case the normal requirements apply (e.g. artifacts are always excluded from the shipping collection).
            }
+
|}
        },
     −
        // add images
+
====Advanced====
        {
+
{| class="wikitable"
            "Action": "Load",
+
|-
            "Target": "Mods/Example.ModId/FruitTrees, Mods/Example.ModId/Objects",
+
! field
            "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/FruitTrees.png, assets/Objects.png
+
! purpose
        },
+
|-
    ]
+
| <samp>CustomFields</samp>
}</nowiki>|lang=javascript}}
+
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.
 +
|}
   −
The fruit trees can then be added to the game by giving the player a sapling item in the usual ways (e.g. from [[#Custom shops|a shop]]).
+
===Custom pants===
 +
{{/doc status|[[Modding:Items]]|done=false}}
   −
====Fruit items====
+
You can now create/edit [[Tailoring#Pants|pants]] by editing the new <samp>Data/Pants</samp> asset, which replaces <samp>Data/clothingInformation</samp>. This consists of a string → model lookup, where...
For C# mods, the <samp>fruitsOnTree</samp> field (number of fruit on the tree) has been replaced by <samp>fruit</samp> (list of fruit items).
  −
 
  −
====Spawning fruit trees====
  −
Custom trees can be added to the game in two ways:
  −
* Spawn them on [[Modding:Maps|map tiles]] when the location is created, using the new <samp>SpawnTree: fruit {{t|tree ID}} {{o|growth stage on location created}} {{o|growth stage on day-update regrowth}}</samp> tile property. This must be added on the <samp>Paths</samp> layer, which must also have tile index 34 from the <samp>paths</samp> tilesheet.
  −
* Or give the player a seed item in the usual ways (e.g. from [[#Custom shops|a shop]], [[Modding:Mail data|mail letter]], etc).
  −
 
  −
===Custom objects===
  −
You can now create/edit objects (the main item type) by editing the new <samp>Data/Objects</samp> asset, which replaces the previous slash-delimited <samp>Data/objectInformation</samp>.
  −
 
  −
Besides the format change, this adds...
  −
* support for custom textures;
  −
* revamped geode drops with support for conditions, probabilities, and item queries;
  −
* expanded food/drink buffs (e.g. set a custom buff ID, add a custom buff icon, etc);
  −
* context tags (moved from the former <samp>Data/ObjectContextTags</samp> asset);
  −
* [[#Custom data fields|custom fields]] to let framework mods support additional features.
  −
 
  −
This consists of a string → model lookup, where...
   
* The key is the unqualified [[#Custom items|item ID]].
 
* The key is the unqualified [[#Custom items|item ID]].
 
* The value is a model with the fields listed below.
 
* The value is a model with the fields listed below.
   −
====Basic info====
+
====Basic pants data====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,724: Line 1,606:  
|-
 
|-
 
| <samp>Name</samp>
 
| <samp>Name</samp>
| The internal item name.
+
| ''(Optional)'' The internal name for the item. Default <samp>Pants</samp>.
 
|-
 
|-
 
| <samp>DisplayName</samp><br /><samp>Description</samp>
 
| <samp>DisplayName</samp><br /><samp>Description</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description.
+
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description. Defaults to the generic pants text (''Pants'' and ''A wearable pair of pants'').
|-
  −
| <samp>Type</samp>
  −
| The item's general type, like <c>Arch</c> (artifact) or <c>Minerals</c>. See details at [[Modding:Items#Objects]].
  −
|-
  −
| <samp>Category</samp>
  −
| The [[Modding:Items#Categories|item category]].
   
|-
 
|-
 
| <samp>Price</samp>
 
| <samp>Price</samp>
| ''(Optional)'' The price when sold by the player. This is not the price when bought from a shop. Default 0.
+
| ''(Optional)'' The default price when the item is sold to the player in a shop. Default 50.
 
|}
 
|}
   Line 1,746: Line 1,622:  
|-
 
|-
 
| <samp>Texture</samp>
 
| <samp>Texture</samp>
| The asset name for the texture containing the item's sprite. Defaults to <samp>Maps/springobjects</samp>.
+
| The asset name for the texture containing the pants' sprite. Defaults to <samp>Characters/Farmer/pants</samp>.
 
|-
 
|-
 
| <samp>SpriteIndex</samp>
 
| <samp>SpriteIndex</samp>
| The sprite's index within the <samp>Texture</samp>, where 0 is the top-left sprite.
+
| The pants' sprite index within the <samp>Texture</samp>, where 0 is the top-left set.
 +
|-
 +
| <samp>DefaultColor</samp>
 +
| ''(Optional)'' The dye color to apply to the sprite when the player hasn't [[dyeing|dyed]] it yet, if any. See [[#Color fields|color format]]. Default <samp>255 235 203</samp> (which matches the color of the cloth item).
 +
|-
 +
| <samp>CanBeDyed</samp>
 +
| ''(Optional)'' Whether the player can [[dyeing|dye]] these pants. Default false.
 +
|-
 +
| <samp>IsPrismatic</samp>
 +
| ''(Optional)'' Whether the pants continuously shift colors. This overrides <samp>DefaultColor</samp> and <samp>CanBeDyed</samp> if set. Default false.
 
|}
 
|}
   −
====Edibility====
+
====Other====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,758: Line 1,643:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>Edibility</samp>
+
| <samp>CanChooseDuringCharacterCustomization</samp>
| ''(Optional)'' A numeric value that determines how much energy (edibility × 2.5) and health (edibility × 1.125) is restored when this item is eaten. An item with an edibility of -300 can't be eaten, values from -299 to -1 reduce health and energy, and zero can be eaten but doesn't change health/energy. Default -300.
+
| ''(Optional)'' Whether these pants can be selected on the character customization screen (e.g. when creating a character). Default false.
 
|-
 
|-
| <samp>IsDrink</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' Whether to drink the item instead of eating it. Default false.
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
+
|}
| <samp>Buff</samp>
+
 
| ''(Optional)'' The buff to apply to the player when this item is eaten, if any. Default none.
+
===Custom shirts===
 +
{{/doc status|[[Modding:Items]]|done=false}}
 +
 
 +
You can now create/edit [[Tailoring#Shirts|shirts]] by editing the new <samp>Data/Shirts</samp> asset, which replaces <samp>Data/clothingInformation</samp>. This consists of a string → model lookup, where...
 +
* The key is the unqualified [[#Custom items|item ID]].
 +
* The value is a model with the fields listed below.
   −
This consists of a model with these fields:
+
====Basic shirt data====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,773: Line 1,663:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>Duration</samp>
+
| <samp>Name</samp>
| The buff duration measured in in-game minutes.
+
| ''(Optional)'' The internal name for the item. Default <samp>Shirt</samp>.
 +
|-
 +
| <samp>DisplayName</samp><br /><samp>Description</samp>
 +
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description. Defaults to the generic shirt text (''Shirt'' and ''A wearable shirt'').
 
|-
 
|-
| <samp>BuffId</samp>
+
| <samp>Price</samp>
| ''(Optional)'' The buff ID to apply. Defaults to <samp>food</samp> or <samp>drink</samp> depending on the item's <samp>IsDrink</samp> field.
+
| ''(Optional)'' The default price when the item is sold to the player in a shop. Default 50.
 +
|}
 +
 
 +
====Appearance====
 +
{| class="wikitable"
 
|-
 
|-
| <samp>IsDebuff</samp>
+
! field
| ''(Optional)'' Whether this buff counts as a debuff, so its duration should be halved when wearing a Sturdy Ring. Default false.
+
! purpose
 
|-
 
|-
| <samp>IconTexture</samp>
+
| <samp>Texture</samp>
| ''(Optional)'' The asset name for the icon texture to load. This must contain one or more 16x16 icons in a grid of any size. If omitted, the game will draw a default icon based on the <samp>BuffId</samp> and <samp>CustomAttributes</samp> fields.
+
| The asset name for the texture containing the shirt's sprite. Defaults to <samp>Characters/Farmer/shirts</samp>.
 
|-
 
|-
 
| <samp>SpriteIndex</samp>
 
| <samp>SpriteIndex</samp>
| ''(Optional)'' The buff's icon index within the <samp>IconTexture</samp>, where 0 is the top-left icon. Default 0.
+
| The shirt's sprite index within the <samp>Texture</samp>, where 0 is the top-left set.
 +
|-
 +
| <samp>DefaultColor</samp>
 +
| ''(Optional)'' The dye color to apply to the sprite when the player hasn't [[dyeing|dyed]] it yet, if any. See [[#Color fields|color format]]. Default none.
 +
|-
 +
| <samp>CanBeDyed</samp>
 +
| ''(Optional)'' Whether the player can [[dyeing|dye]] this shirt. Default false.
 
|-
 
|-
| <samp>GlowColor</samp>
+
| <samp>IsPrismatic</samp>
| ''(Optional)'' The glow color to apply to the player. See [[#Color fields|color format]]. Default none.
+
| ''(Optional)'' Whether the shirt continuously shifts colors. This overrides <samp>DefaultColor</samp> and <samp>CanBeDyed</samp> if set. Default false.
 
|-
 
|-
| <samp>CustomAttributes</samp>
+
| <samp>HasSleeves</samp>
| The custom buff attributes to apply, if any.
+
| ''(Optional)'' Whether to draw shirt sleeves. Default true.
 +
|}
   −
This consists of a model with any combination of these fields:
+
====Other====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,800: Line 1,704:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>FarmingLevel</samp><br /><samp>FishingLevel</samp><br /><samp>ForagingLevel</samp><br /><samp>LuckLevel</samp><br /><samp>MiningLevel</samp>
+
| <samp>CanChooseDuringCharacterCustomization</samp>
| ''(Optional)'' An amount applied to the matching [[Skills|skill level]] while the buff is active. This can be negative for a debuff. Default 0.
+
| ''(Optional)'' Whether this shirt can be selected on the character customization screen (e.g. when creating a character). Default false.
|-
  −
| <samp>Attack</samp><br /><samp>Defense</samp><br /><samp>MagneticRadius</samp><br /><samp>MaxStamina</samp><br /><samp>Speed</samp>
  −
| ''(Optional)'' An amount applied to the player's [[attack]], [[defense]], [[Magnetism|magnetic radius]], maximum [[Energy|stamina]], or [[speed]] while the buff is active. This can be negative for a debuff. Default 0.
  −
|}
   
|-
 
|-
 
| <samp>CustomFields</samp>
 
| <samp>CustomFields</samp>
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.  
+
| The [[#Custom data fields|custom fields]] for this entry.
|}
   
|}
 
|}
   −
====Geodes & artifact spots====
+
===Custom tools===
 +
{{/doc status|[[Modding:Items]]|done=false}}
 +
 
 +
You can now create/edit [[tools]] by editing the new <samp>Data/Tools</samp> asset. This consists of a string → model lookup, where...
 +
* The key is the unqualified [[#Custom items|item ID]].
 +
* The value is a model with the fields listed below.
 +
 
 +
====Basic tool data====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,818: Line 1,724:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>GeodeDrops</samp><br /><samp><samp>GeodeDropsDefaultItems</samp>
+
| <samp>ClassName</samp>
| ''(Optional)'' The items that can be dropped when breaking open this item as a [[Minerals#Geodes|geode]]. Specifying either or both fields automatically enables geode behavior for this item.
+
| The name of the C# class to construct within the <code>StardewValley.Tools</code> namespace. The class must be a subclass of <samp>StardewValley.Tool</samp>, and have a constructor with no arguments. For example, given a value of <samp>Axe</samp>, the game will create <code>StardewValley.Tools.Axe</code> instances.
 +
 
 +
The main values are:
 +
* main tools (<samp>Axe</samp>, <samp>FishingRod</samp>, <samp>Hoe</samp>, <samp>MeleeWeapon</samp>, <samp>MilkPail</samp>, <samp>Pan</samp>, <samp>Pickaxe</samp>, <samp>Shears</samp>, <samp>Wand</samp>, and <samp>WateringCan</samp>);
 +
* a special <samp>GenericTool</samp> type which applies the <samp>Data/Tools</samp> data and only has generic logic, so C# mods can patch in their own logic;
 +
* and two tools cut from the game which may not work correctly (<samp>Lantern</samp> and <samp>Raft</samp>).
 +
|-
 +
| <samp>Name</samp>
 +
| The internal name to set for the tool item.
 +
|-
 +
| <samp>DisplayName</samp><br /><samp>Description</samp>
 +
| A [[Modding:Tokenizable strings|tokenizable string]] for the tool's in-game display name and description.
 +
|-
 +
| <samp>AttachmentSlots</samp>
 +
| ''(Optional)'' The number of attachment slots to enable on the tool. Note that only <samp>FishingRod</samp> tools have the code to render and use attachment slots. Default <samp>-1</samp>, which keeps the default value set by the tool class.
 +
|-
 +
| <samp>SalePrice</samp>
 +
| ''(Optional)'' The default price when the item is sold to the player in a shop. Defaults to <samp>-1</samp>, in which case you should set the price manually in shops.
 +
|-
 +
| <samp>CustomFields</samp>
 +
| The [[#Custom data fields|custom fields]] for this entry.
 +
|}
 +
 
 +
====Appearance====
 +
Note that drawing the tool correctly in the world (ie, while the player is trying to use it) probably still needs custom code.
   −
You can specify one or both fields:
  −
<ul>
  −
<li><samp>GeodeDrops</samp> can be set to the specific items to drop. Default none. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,829: Line 1,756:  
! purpose
 
! purpose
 
|-
 
|-
 +
| <samp>Texture</samp>
 +
| The asset name for the texture containing the tool's sprite.
 +
|-
 +
| <samp>SpriteIndex</samp>
 +
| The tool's sprite index within the <samp>Texture</samp>, where 0 is the top row.
 
|-
 
|-
| ''common fields''
+
| <samp>MenuSpriteIndex</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported by geode drops.
+
| ''(Optional)'' The sprite index within the <samp>Texture</samp> for the item icon. Defaults to <samp>SpriteIndex</samp>.
 +
|}
   −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
====Upgrades====
 +
{| class="wikitable"
 
|-
 
|-
| <samp>Chance</samp>
+
! field
| ''(Optional)'' The probability that the item will be dropped if the other fields match, as a decimal value between 0 (never) and 1 (always). Default 1.
+
! purpose
 
|-
 
|-
| <samp>SetFlagOnPickup</samp>
+
| <samp>UpgradeLevel</samp>
| ''(Optional)'' The mail flag to set for the current player when this drop is picked up.
+
| ''(Optional)'' The tool upgrade level. Default <samp>-1</samp>, which keeps the default value set by the tool class.
 
|-
 
|-
| <samp>Precedence</samp>
+
| <samp>ApplyUpgradeLevelToDisplayName</samp>
| ''(Optional)'' The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Geode drops with the same precedence are checked in the order listed. Default 0.
+
| ''(Optional)'' Whether to adjust the <samp>DisplayName</samp> for the usual upgrade levels. For example, the display name for a level one Axe changes to 'Copper Axe'. Default false.
   −
For consistency, vanilla drops mostly use these values:
+
The display name format in English is:
* <samp>-1000</samp>: special overrides like the [[Golden Helmet]];
+
{| class="wikitable"
* <samp>0</samp>: normal items.
+
|-
|}</li>
+
! upgrade level
<li><samp>GeodeDropsDefaultItems</samp> chooses a predefined list of possible geode drops like [[clay]], [[coal]], [[Copper Ore|copper]], [[Iridium Ore|iridium]], etc. Default false.</li>
+
! display name format
</ul>
+
|-
 
+
| 1
If both fields are specified, each geode will choose between them with an equal 50% chance. If <samp>GeodeDrops</samp> is specified but no entries match, the geode will use the <samp>GeodeDropsDefaultItems</samp> regardless of whether it's true.
+
| Copper {{t|display name}}
 
|-
 
|-
| <samp>ArtifactSpotChances</samp>
+
| 2
| ''(Optional)'' If this is an artifact (i.e. the <samp>Type</samp> field is <samp>Arch</samp>), the chance that it can be found by digging [[Artifact Spot|artifact spots]] in each location.
+
| Steel {{t|display name}}
 
  −
This consists of a string → model lookup, where:
  −
* the key is the internal location name;
  −
* the value is the probability the item will spawn if checked, as a decimal value between 0 (never) and 1 (always).
  −
|}
  −
 
  −
====Context tags====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| 3
! purpose
+
| Gold {{t|display name}}
 
|-
 
|-
| <samp>ContextTags</samp>
+
| 4
| ''(Optional)'' The custom [[Modding:Items#Context tags|context tags]] to add for this item (in addition to the tags added automatically based on the other object data). This is formatted as a list; for example:
+
| Iridium {{t|display name}}
<syntaxhighlight lang="json">
  −
"ContextTags": [ "color_yellow", "fish_ocean", "fish_upright", "season_summer" ]
  −
</syntaxhighlight>
   
|}
 
|}
 +
|-
 +
| <samp>ConventionalUpgradeFrom</samp>
 +
| ''(Optional)'' If set, prepends an upgrade for the given tool ID to the <samp>UpgradeFrom</samp> field. This applies these rules (based on the <samp>UpgradeLevel</samp> field, not the upgrade level of the specified tool ID):
   −
====Advanced====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! upgrade level
! purpose
+
! price
 +
! items needed
 +
|-
 +
| 1
 +
| {{price|2000}}
 +
| {{name|Copper Bar|5}}
 +
|-
 +
| 2
 +
| {{price|5000}}
 +
| {{name|Iron Bar|5}}
 +
|-
 +
| 3
 +
| {{price|10000}}
 +
| {{name|Gold Bar|5}}
 
|-
 
|-
| <samp>CustomFields</samp>
+
| 4
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.
+
| {{price|25000}}
 +
| {{name|Iridium Bar|5}}
 
|}
 
|}
   −
===Custom pants===
+
For example, Iridium Axe specifies this value:
You can now create/edit [[Tailoring#Pants|pants]] by editing the new <samp>Data/Pants</samp> asset, which replaces <samp>Data/clothingInformation</samp>. This consists of a string → model lookup, where...
+
<syntaxhighlight lang="js">
* The key is the unqualified [[#Custom items|item ID]].
+
"ConventionalUpgradeFrom": "(T)GoldAxe"
* The value is a model with the fields listed below.
+
</syntaxhighlight>
 +
|-
 +
| <samp>UpgradeFrom</samp>
 +
| ''(Optional)'' The requirements to buy this tool from Clint's [[Blacksmith#Upgrade Tools|blacksmith tool upgrade shop]]. If you specify multiple entries, the first one which matches will be applied.
   −
====Basic pants data====
+
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
 
! purpose
 
! purpose
|-
  −
| <samp>Name</samp>
  −
| ''(Optional)'' The internal name for the item. Default <samp>Pants</samp>.
  −
|-
  −
| <samp>DisplayName</samp><br /><samp>Description</samp>
  −
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description. Defaults to the generic pants text (''Pants'' and ''A wearable pair of pants'').
   
|-
 
|-
 
| <samp>Price</samp>
 
| <samp>Price</samp>
| ''(Optional)'' The default price when the item is sold to the player in a shop. Default 50.
+
| ''(Optional)'' The gold price to buy the upgrade. Defaults to 0.
|}
  −
 
  −
====Appearance====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>RequireToolId</samp>
! purpose
+
| ''(Optional)'' If set, the [[#Custom items|qualified or unqualified item ID]] for the tool that must be in the player's inventory for the upgrade to appear. The tool will be destroyed when the upgrade is purchased.
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>TradeItemId</samp>
| The asset name for the texture containing the pants' sprite. Defaults to <samp>Characters/Farmer/pants</samp>.
+
| ''(Optional)'' If set, the [[#Custom items|qualified or unqualified item ID]] for an extra item that must be traded to upgrade the tool. (For example, many vanilla tools need metal bars.)
 
|-
 
|-
| <samp>SpriteIndex</samp>
+
| <samp>TradeItemAmount</samp>
| The pants' sprite index within the <samp>Texture</samp>, where 0 is the top-left set.
+
| ''(Optional)'' The number of <samp>TradeItemId</samp> required. Defaults to 1.
 
|-
 
|-
| <samp>DefaultColor</samp>
+
| <samp>Condition</samp>
| ''(Optional)'' The dye color to apply to the sprite when the player hasn't [[dyeing|dyed]] it yet, if any. See [[#Color fields|color format]]. Default <samp>255 235 203</samp> (which matches the color of the cloth item).
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this upgrade is available. Defaults to always true.
|-
+
|}
| <samp>CanBeDyed</samp>
+
 
| ''(Optional)'' Whether the player can [[dyeing|dye]] these pants. Default false.
+
For example, these are equivalent to the Steel Axe's upgrade settings:
|-
+
<syntaxhighlight lang="js">
| <samp>IsPrismatic</samp>
+
"UpgradeFrom": [
| ''(Optional)'' Whether the pants continuously shift colors. This overrides <samp>DefaultColor</samp> and <samp>CanBeDyed</samp> if set. Default false.
+
    {
 +
        "RequireToolId": "(T)CopperAxe",
 +
        "Price": 5000,
 +
        "TradeItemId": "(O)335", // Iron Bar
 +
        "TradeItemAmount": 5
 +
    }
 +
]
 +
</syntaxhighlight>
 +
 
 +
If you want the tool to always be available, you can just omit the conditions. For example:
 +
<syntaxhighlight lang="js">
 +
"UpgradeFrom": [
 +
    {
 +
        "Price": 5000
 +
    }
 +
]
 +
</syntaxhighlight>
 +
 
 +
Note that Clint needs a few days to smith the new tool. If you want to sell the tool directly, [[#Custom shops|add it to a regular shop]] instead.
 
|}
 
|}
   −
====Other====
+
====Game logic====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,933: Line 1,883:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>CanChooseDuringCharacterCustomization</samp>
+
| <samp>CanBeLostOnDeath</samp>
| ''(Optional)'' Whether these pants can be selected on the character customization screen (e.g. when creating a character). Default false.
+
| Whether the player can [[Adventurer's Guild#Item Recovery Service|lose this tool when they die]]. Default false.
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
   
|}
 
|}
   −
===Custom shirts===
+
====Extensibility====
You can now create/edit [[Tailoring#Shirts|shirts]] by editing the new <samp>Data/Shirts</samp> asset, which replaces <samp>Data/clothingInformation</samp>. This consists of a string → model lookup, where...
  −
* The key is the unqualified [[#Custom items|item ID]].
  −
* The value is a model with the fields listed below.
  −
 
  −
====Basic shirt data====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,951: Line 1,893:  
! purpose
 
! purpose
 
|-
 
|-
| <samp>Name</samp>
+
| <samp>ModData</samp>
| ''(Optional)'' The internal name for the item. Default <samp>Shirt</samp>.
+
| ''(Optional)'' The mod data values to set when the tool is created, accessible in C# code via the <samp>tool.modData</samp> dictionary. For example:
 +
<syntaxhighlight lang="js">
 +
"ModData": {
 +
    "PowerLevel": 9000
 +
}
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>DisplayName</samp><br /><samp>Description</samp>
+
| <samp>SetProperties</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the item's in-game display name and description. Defaults to the generic shirt text (''Shirt'' and ''A wearable shirt'').
+
| ''(Optional)'' Set the value of arbitrary properties on the tool class. For example, this would disable the tool animation and require no stamina:
|-
+
<syntaxhighlight lang="js">
| <samp>Price</samp>
+
"SetProperties": {
| ''(Optional)'' The default price when the item is sold to the player in a shop. Default 50.
+
    "InstantUse": true,
 +
    "IsEfficient": true
 +
}
 +
</syntaxhighlight>
 
|}
 
|}
   −
====Appearance====
+
===Custom wild trees===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
====Data format====
 +
You can now create/edit [[Trees|wild trees]] by editing the <samp>Data/WildTrees</samp> asset.
 +
 
 +
This consists of a string → model lookup, where...
 +
* The asset key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the tree type. The vanilla tree IDs are <samp>1</samp> (oak), <samp>2</samp> (maple), <samp>3</samp> (pine), <samp>6</samp> (palm), <samp>7</samp> (mushroom), and <samp>8</samp> (mahogany).
 +
* The asset value is a model with thee fields listed below.
 +
 
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
! purpose
+
! effect
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>Textures</samp>
| The asset name for the texture containing the shirt's sprite. Defaults to <samp>Characters/Farmer/shirts</samp>.
+
| The texture to use as the tree's spritesheet in-game. If multiple textures are listed, the first matching one is used.
 +
 
 +
This consists of a list of models with these fields:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>SpriteIndex</samp>
+
! field
| The shirt's sprite index within the <samp>Texture</samp>, where 0 is the top-left set.
+
! effect
 
|-
 
|-
| <samp>DefaultColor</samp>
+
| <samp>Texture</samp>
| ''(Optional)'' The dye color to apply to the sprite when the player hasn't [[dyeing|dyed]] it yet, if any. See [[#Color fields|color format]]. Default none.
+
| The asset name for the tree's spritesheet.
 
|-
 
|-
| <samp>CanBeDyed</samp>
+
| <samp>Season</samp>
| ''(Optional)'' Whether the player can [[dyeing|dye]] this shirt. Default false.
+
| ''(Optional)'' If set, the specific season when this texture should apply. For more complex conditions, see <samp>Condition</samp>.
 
|-
 
|-
| <samp>IsPrismatic</samp>
+
| <samp>Condition</samp>
| ''(Optional)'' Whether the shirt continuously shifts colors. This overrides <samp>DefaultColor</samp> and <samp>CanBeDyed</samp> if set. Default false.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this texture should be applied for a tree. Defaults to always enabled.
|-
+
 
| <samp>HasSleeves</samp>
+
This is checked when the tree is created, a new day starts, or its texture is reloaded by a mod. More frequent conditions (like time of day) won't work as expected unless a mod manually triggers a tree update.
| ''(Optional)'' Whether to draw shirt sleeves. Default true.
   
|}
 
|}
  −
====Other====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>SeedItemId</samp>
! purpose
+
| ''(Optional)'' The [[#Custom items|qualified item ID]] for the seed item. If omitted, the tree can't be planted and <samp>SeedOnShakeChance</samp> will be ignored.
 
|-
 
|-
| <samp>CanChooseDuringCharacterCustomization</samp>
+
| <samp>SeedPlantable</samp>
| ''(Optional)'' Whether this shirt can be selected on the character customization screen (e.g. when creating a character). Default false.
+
| ''(Optional)'' Whether the seed can be planted by the player. If this is false, it can only be spawned automatically via map properties. Default true.
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>GrowthChance</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| ''(Optional)'' The probability each day that the tree will grow to the next stage without [[Tree Fertilizer|tree fertilizer]], as a value from 0 (will never grow) to 1 (will grow every day). Defaults to 0.2 (20% chance).
|}
  −
 
  −
===Custom tools===
  −
You can now create/edit [[tools]] by editing the new <samp>Data/Tools</samp> asset. This consists of a string → model lookup, where...
  −
* The key is the unqualified [[#Custom items|item ID]].
  −
* The value is a model with the fields listed below.
  −
 
  −
====Basic tool data====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>FertilizedGrowthChance</samp>
! purpose
+
| ''(Optional)'' Equivalent to <samp>GrowthChance</samp>, but with [[Tree Fertilizer|tree fertilizer]]. Defaults to 1 (100% chance).
 
|-
 
|-
| <samp>ClassName</samp>
+
| <samp>SeedSpreadChance</samp>
| The name of the C# class to construct within the <code>StardewValley.Tools</code> namespace. The class must be a subclass of <samp>StardewValley.Tool</samp>, and have a constructor with no arguments. For example, given a value of <samp>Axe</samp>, the game will create <code>StardewValley.Tools.Axe</code> instances.
+
| ''(Optional)'' The probability each day that the tree will plant a seed on a nearby tile, as a value from 0 (never) to 1 (always). This only applied in locations where trees plant seeds (e.g. farms in vanilla). Default 0.15 (15% chance).
 
  −
The main values are:
  −
* main tools (<samp>Axe</samp>, <samp>FishingRod</samp>, <samp>Hoe</samp>, <samp>MeleeWeapon</samp>, <samp>MilkPail</samp>, <samp>Pan</samp>, <samp>Pickaxe</samp>, <samp>Shears</samp>, <samp>Wand</samp>, and <samp>WateringCan</samp>);
  −
* a special <samp>GenericTool</samp> type which applies the <samp>Data/Tools</samp> data and only has generic logic, so C# mods can patch in their own logic;
  −
* and two tools cut from the game which may not work correctly (<samp>Lantern</samp> and <samp>Raft</samp>).
   
|-
 
|-
| <samp>Name</samp>
+
| <samp>SeedOnShakeChance</samp>
| The internal name to set for the tool item.
+
| ''(Optional)'' The probability each day that the tree will produce a seed that will drop when the tree is shaken, as a value from 0 (never) to 1 (always). Default 0.05 (5% chance).
 
|-
 
|-
| <samp>DisplayName</samp><br /><samp>Description</samp>
+
| <samp>SeedOnChopChance</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the tool's in-game display name and description.
+
| ''(Optional)'' The probability that a seed will drop when the player chops down the tree, as a value from 0 (never) to 1 (always). Default 0.75 (75% chance).
 
|-
 
|-
| <samp>AttachmentSlots</samp>
+
| <samp>DropWoodOnChop</samp>
| ''(Optional)'' The number of attachment slots to enable on the tool. Note that only <samp>FishingRod</samp> tools have the code to render and use attachment slots. Default <samp>-1</samp>, which keeps the default value set by the tool class.
+
| ''(Optional)'' Whether to drop [[wood]] when the player chops down the tree. Default true.
 
|-
 
|-
| <samp>SalePrice</samp>
+
| <samp>DropHardwoodOnLumberChop</samp>
| ''(Optional)'' The default price when the item is sold to the player in a shop. Defaults to <samp>-1</samp>, in which case you should set the price manually in shops.
+
| ''(Optional)'' Whether to drop [[hardwood]] when the player chops down the tree, if they have the [[Skills#Foraging|Lumberjack profession]]. Default true.
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>IsLeafy</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| ''(Optional)'' Whether shaking or chopping the tree causes cosmetic leaves to drop from tree and produces a leaf rustle sound. When a leaf drops, the game will use one of the four leaf sprites in the tree's spritesheet in the slot left of the stump sprite. Default true.
|}
  −
 
  −
====Appearance====
  −
Note that drawing the tool correctly in the world (ie, while the player is trying to use it) probably still needs custom code.
  −
 
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>IsLeafyInWinter</samp>
! purpose
+
| ''(Optional)'' Whether <samp>IsLeafy</samp> also applies in winter. Default false.
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>GrowsInWinter</samp>
| The asset name for the texture containing the tool's sprite.
+
| ''(Optional)'' Whether the tree can grow in winter (subject to <samp>GrowthChance</samp> or <samp>FertilizedGrowthChance</samp>). Default false.
 
|-
 
|-
| <samp>SpriteIndex</samp>
+
| <samp>IsStumpDuringWinter</samp>
| The tool's sprite index within the <samp>Texture</samp>, where 0 is the top row.
+
| ''(Optional)'' Whether the tree is reduced to a stump in winter and regrows in spring, like the vanilla [[Trees#Mushroom Tree|mushroom tree]]. Default false.
 
|-
 
|-
| <samp>MenuSpriteIndex</samp>
+
| <samp>AllowWoodpeckers</samp>
| ''(Optional)'' The sprite index within the <samp>Texture</samp> for the item icon. Defaults to <samp>SpriteIndex</samp>.
+
| ''(Optional)'' Whether woodpeckers can spawn on the tree. Default true.
|}
  −
 
  −
====Upgrades====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>UseAlternateSpriteWhenNotShaken</samp><br /><samp>UseAlternateSpriteWhenSeedReady</samp>
! purpose
+
| ''(Optional)'' Whether to render a different tree sprite when the player hasn't shaken it on that day (<samp>UseAlternateSpriteWhenNotShaken</samp>) or it has a seed ready (<samp>UseAlternateSpriteWhenSeedReady</samp>). If either field is true, the tree spritesheet must be double-width with the alternate textures on the right. If both are true, the same alternate sprites are used for both. Default false.
 
|-
 
|-
| <samp>UpgradeLevel</samp>
+
| <samp>DebrisColor</samp>
| ''(Optional)'' The tool upgrade level. Default <samp>-1</samp>, which keeps the default value set by the tool class.
+
| ''(Optional)'' The color of the cosmetic wood chips when chopping the tree. This can be...
 +
* a [[#Color fields|standard color format]];
 +
* or one of <samp>12</samp> (brown/woody), <samp>100001</samp> (white), <samp>100001</samp> (light green),  <samp>100002</samp> (light blue), <samp>100003</samp> (red), <samp>100004</samp> (yellow), <samp>100005</samp> (black), <samp>100006</samp> (gray), or <samp>100007</samp> (charcoal / dim gray).
 +
 
 +
Defaults to <samp>12</samp> (brown/woody).
 
|-
 
|-
| <samp>ApplyUpgradeLevelToDisplayName</samp>
+
| <samp>SeedDropItems</samp>
| ''(Optional)'' Whether to adjust the <samp>DisplayName</samp> for the usual upgrade levels. For example, the display name for a level one Axe changes to 'Copper Axe'. Default false.
+
| ''(Optional)'' When a seed is dropped subject to <samp>SeedOnShakeChance</samp>, the item to drop instead of the item specified by <samp>SeedItemId</samp>. If this is empty or none match, the <samp>SeedItemId</samp> will be dropped instead.
   −
The display name format in English is:
+
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! upgrade level
+
! field
! display name format
+
! effect
 
|-
 
|-
| 1
+
| ''common fields''
| Copper {{t|display name}}
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for chop drops.
 +
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
| 2
+
| <samp>Season</samp>
| Steel {{t|display name}}
+
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
 
|-
 
|-
| 3
+
| <samp>Chance</samp>
| Gold {{t|display name}}
+
| ''(Optional)'' The probability that the item will drop, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
 
|-
 
|-
| 4
+
| <samp>ContinueOnDrop</samp>
| Iridium {{t|display name}}
+
| ''(Optional)'' If this item is dropped, whether to continue as if it hadn't been dropped for the remaining drop candidates. Default false.
 
|}
 
|}
 
|-
 
|-
| <samp>ConventionalUpgradeFrom</samp>
+
| <samp>ChopItems</samp>
| ''(Optional)'' If set, prepends an upgrade for the given tool ID to the <samp>UpgradeFrom</samp> field. This applies these rules (based on the <samp>UpgradeLevel</samp> field, not the upgrade level of the specified tool ID):
+
| ''(Optional)'' The additional items to drop when the tree is chopped down. All matching items are dropped.
    +
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! upgrade level
+
! field
! price
+
! effect
! items needed
+
|-
 +
| ''common fields''
 +
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for chop drops.
 +
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
| 1
+
| <samp>Season</samp>
| {{price|2000}}
+
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
| {{name|Copper Bar|5}}
   
|-
 
|-
| 2
+
| <samp>Chance</samp>
| {{price|5000}}
+
| ''(Optional)'' The probability that the item will drop, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
| {{name|Iron Bar|5}}
   
|-
 
|-
| 3
+
| <samp>MinSize</samp><br /><samp>MaxSize</samp>
| {{price|10000}}
+
| ''(Optional)'' The minimum and/or maximum growth stage for the tree at which this item is produced. The possible values are <samp>Seed</samp>, <samp>Sprout</samp>, <samp>Sapling</samp>, <samp>Bush</samp>, and <samp>Tree</samp>. Both default to no limit.
| {{name|Gold Bar|5}}
   
|-
 
|-
| 4
+
| <samp>ForStump</samp>
| {{price|25000}}
+
| ''(Optional)'' Whether the item is only produced if the tree is a stump (<samp>true</samp>), not a stump (<samp>false</samp>), or both (<samp>null</samp>). Defaults to <samp>false</samp> (non-stumps only).
| {{name|Iridium Bar|5}}
   
|}
 
|}
  −
For example, Iridium Axe specifies this value:
  −
<syntaxhighlight lang="js">
  −
"ConventionalUpgradeFrom": "(T)GoldAxe"
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>UpgradeFrom</samp>
+
| <samp>ShakeItems</samp>
| ''(Optional)'' The requirements to buy this tool from Clint's [[Blacksmith#Upgrade Tools|blacksmith tool upgrade shop]]. If you specify multiple entries, the first one which matches will be applied.
+
| The items produced by shaking the tree when it's fully grown. This only applies the first time the tree is shaken each day. All matching items are dropped.
    
This consists of a list of models with these fields:
 
This consists of a list of models with these fields:
Line 2,121: Line 2,057:  
|-
 
|-
 
! field
 
! field
! purpose
+
! effect
 
|-
 
|-
| <samp>Price</samp>
+
| ''common fields''
| ''(Optional)'' The gold price to buy the upgrade. Defaults to 0.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for shake items.
 +
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
| <samp>RequireToolId</samp>
+
| <samp>Season</samp>
| ''(Optional)'' If set, the [[#Custom items|qualified or unqualified item ID]] for the tool that must be in the player's inventory for the upgrade to appear. The tool will be destroyed when the upgrade is purchased.
+
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
 
|-
 
|-
| <samp>TradeItemId</samp>
+
| <samp>Chance</samp>
| ''(Optional)'' If set, the [[#Custom items|qualified or unqualified item ID]] for an extra item that must be traded to upgrade the tool. (For example, many vanilla tools need metal bars.)
+
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
 +
|}
 
|-
 
|-
| <samp>TradeItemAmount</samp>
+
| <samp>TapItems</samp>
| ''(Optional)'' The number of <samp>TradeItemId</samp> required. Defaults to 1.
+
| The items produced by [[Tapper|tapping]] the tree. If multiple items can be produced, the first available one is selected.
 +
 
 +
This consists of a list of models with these fields:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>Condition</samp>
+
! field
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this upgrade is available. Defaults to always true.
+
! effect
|}
+
|-
 +
| ''common fields''
 +
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for tapper items.
   −
For example, these are equivalent to the Steel Axe's upgrade settings:
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
<syntaxhighlight lang="js">
+
|-
"UpgradeFrom": [
+
| <samp>Season</samp>
    {
+
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
        "RequireToolId": "(T)CopperAxe",
+
|-
        "Price": 5000,
+
| <samp>Chance</samp>
        "TradeItemId": "(O)335", // Iron Bar
+
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
        "TradeItemAmount": 5
+
|-
    }
+
| <samp>DaysUntilReady</samp>
]
+
| The number of days before the tapper is ready to empty.
</syntaxhighlight>
+
|-
 +
| <samp>PreviousItemId</samp>
 +
| ''(Optional)'' If set, the item only applies if the previous item produced by the tapper matches one of the given [[#Custom items|qualified item IDs]]. If an entry is null or an empty string, it matches when there's no previous item.
   −
If you want the tool to always be available, you can just omit the conditions. For example:
+
For example: <code>"PreviousItemId": [ null ]</code> only applies when a tapper is first added to the tree, and <code>"PreviousItemsId": [ "(O)420" ]</code> applies if the player just collected a [[Red Mushroom|red mushroom]] (object #420) from it.
<syntaxhighlight lang="js">
  −
"UpgradeFrom": [
  −
    {
  −
        "Price": 5000
  −
    }
  −
]
  −
</syntaxhighlight>
  −
 
  −
Note that Clint needs a few days to smith the new tool. If you want to sell the tool directly, [[#Custom shops|add it to a regular shop]] instead.
  −
|}
  −
 
  −
====Game logic====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>DaysUntilReadyModifiers</samp>
! purpose
+
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] applied to the <samp>DaysUntilReady</samp> value. Default none.
 
|-
 
|-
| <samp>CanBeLostOnDeath</samp>
+
| <samp>DaysUntilReadyModifiersMode</samp>
| Whether the player can [[Adventurer's Guild#Item Recovery Service|lose this tool when they die]]. Default false.
+
| ''(Optional)'' [[#Quantity modifiers|Quantity modifier modes]] which indicate what to do if multiple modifiers in the <samp>DaysUntilReadyModifiersMode</samp> field apply at the same time. Default <samp>Stack</samp>.
 
|}
 
|}
 +
|-
 +
| <samp>PlantableLocationRules</samp>
 +
| ''(Optional)'' The rules to decide which locations you can plant the seed in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
 +
 +
This consists of a list of models with these fields:
   −
====Extensibility====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
! purpose
+
! effect
 
|-
 
|-
| <samp>ModData</samp>
+
| <samp>Id</samp>
| ''(Optional)'' The mod data values to set when the tool is created, accessible in C# code via the <samp>tool.modData</samp> dictionary. For example:
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
<syntaxhighlight lang="js">
  −
"ModData": {
  −
    "PowerLevel": 9000
  −
}
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>SetProperties</samp>
+
| <samp>Result</samp>
| ''(Optional)'' Set the value of arbitrary properties on the tool class. For example, this would disable the tool animation and require no stamina:
+
| Indicates whether the seed can be planted in a location if this entry is selected. The possible values are:
<syntaxhighlight lang="js">
+
* <samp>Default</samp>: the seed can be planted if the location normally allows it. This can be used to stop processing further rules, and/or set a custom <samp>DeniedMessage</samp>.
"SetProperties": {
+
* <samp>Allow</samp>: the seed can be planted here, regardless of whether the location normally allows it.
    "InstantUse": true,
+
* <samp>Deny</samp>: the seed can't be planted here, regardless of whether the location normally allows it.
    "IsEfficient": true
  −
}
  −
</syntaxhighlight>
  −
|}
  −
 
  −
===Custom wild trees===
  −
====Data format====
  −
You can now create/edit [[Trees|wild trees]] by editing the <samp>Data/WildTrees</samp> asset.
  −
 
  −
This consists of a string → model lookup, where...
  −
* The asset key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the tree type. The vanilla tree IDs are <samp>1</samp> (oak), <samp>2</samp> (maple), <samp>3</samp> (pine), <samp>6</samp> (palm), <samp>7</samp> (mushroom), and <samp>8</samp> (mahogany).
  −
* The asset value is a model with thee fields listed below.
  −
 
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>Condition</samp>
! effect
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry applies. Default true.
 
|-
 
|-
| <samp>Textures</samp>
+
| <samp>PlantedIn</samp>
| The texture to use as the tree's spritesheet in-game. If multiple textures are listed, the first matching one is used.
+
| ''(Optional)'' The planting context to apply this rule for. The possible values are <samp>Ground</samp> (planted directly in the ground), <samp>GardenPot</samp> (planted in a [[Garden Pot|garden pot]]), or <samp>Any</samp>. Default <samp>Any</samp>.
   −
This consists of a list of models with these fields:
+
Note that trees can't be planted in garden pots.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>DeniedMessage</samp>
! effect
+
| ''(Optional)'' If this rule prevents planting the seed, the tokenizable string to show to the player (or <samp>null</samp> to default to the normal behavior for the context). This also applies when the <samp>Result</samp> is <samp>Default</samp>, if that causes the planting to be denied.
|-
  −
| <samp>Texture</samp>
  −
| The asset name for the tree's spritesheet.
  −
|-
  −
| <samp>Season</samp>
  −
| ''(Optional)'' If set, the specific season when this texture should apply. For more complex conditions, see <samp>Condition</samp>.
  −
|-
  −
| <samp>Condition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this texture should be applied for a tree. Defaults to always enabled.
  −
 
  −
This is checked when the tree is created, a new day starts, or its texture is reloaded by a mod. More frequent conditions (like time of day) won't work as expected unless a mod manually triggers a tree update.
   
|}
 
|}
 
|-
 
|-
| <samp>SeedItemId</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' The [[#Custom items|qualified item ID]] for the seed item. If omitted, the tree can't be planted and <samp>SeedChance</samp> will be ignored.
+
| The [[#Custom data fields|custom fields]] for this entry.
 +
|}
 +
 
 +
====Spawning wild trees====
 +
Custom trees can be added to the game in two ways:
 +
* Spawn them on [[Modding:Maps|map tiles]] when the location is created, using the new <samp>SpawnTree: wild {{t|tree ID}} {{o|growth stage on location created}} {{o|growth stage on day-update regrowth}}</samp> tile property. This must be added on the <samp>Paths</samp> layer, which must also have tile index 34 from the <samp>paths</samp> tilesheet.
 +
* Or give the player a seed item in the usual ways (e.g. from [[#Custom shops|a shop]], [[Modding:Mail data|mail letter]], etc).
 +
 
 +
===Default recipes===
 +
{{/doc status|[[Modding:Recipe data]]|done=false}}
 +
 
 +
You can now have [[Modding:Recipe data|crafting and cooking recipes]] that are learned automatically by setting the condition field to <samp>default</samp>. Any missing default recipes will be learned on day start.
 +
 
 +
For example, here's the chest entry from <samp>Data/CraftingRecipes</samp>:
 +
<syntaxhighlight lang="js">
 +
"Chest": "388 50/Home/130/true/default/"
 +
</syntaxhighlight>
 +
 
 +
===Global inventories===
 +
C# mods can now set a <samp>chest.GlobalInventoryId</samp> field to make it share a global inventory with every other chest having the same ID. This replaces the equivalent hardcoded logic for [[Junimo Chest|Junimo chests]], which now just default to a <samp>"JunimoChests"</samp> global inventory ID. For example, this can be used to have multiple Junimo chest networks or make other containers share inventory.
 +
 
 +
C# mods can also use this to store items for other mod purposes, by using <samp>Game1.player.team.globalInventories</samp> or <samp>Game1.player.team.GetOrCreateGlobalInventory(id)</samp> directly.
 +
 
 +
===Hats on aquarium fish===
 +
{{/doc status|[[Modding:Fish data]]|done=false}}
 +
 
 +
Custom [[Modding:Fish data|fish in aquariums]] can now wear [[hats]], just like vanilla [[Sea Urchin|sea urchins]]. This can be enabled by specifying a new field in <samp>Data/AquariumFish</samp>:
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <samp>SeedPlantable</samp>
+
! index
| ''(Optional)'' Whether the seed can be planted by the player. If this is false, it can only be spawned automatically via map properties. Default true.
+
! field
 +
! purpose
 
|-
 
|-
| <samp>GrowthChance</samp>
+
| 7
| ''(Optional)'' The probability each day that the tree will grow to the next stage without [[Tree Fertilizer|tree fertilizer]], as a value from 0 (will never grow) to 1 (will grow every day). Defaults to 0.2 (20% chance).
+
| hat position
 +
| The pixel position of the hat on the sprite, specified as an object with <samp>X</samp> and <samp>Y</samp> values.
 +
|}
 +
 
 +
===Context tag changes===
 +
{{/doc status|[[Modding:Items#Context tags]]|done=false}}
 +
 
 +
====New context tags====
 +
1.6 adds several new [[Modding:Items#Context tags|item context tags]]:
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <samp>FertilizedGrowthChance</samp>
+
! context tag
| ''(Optional)'' Equivalent to <samp>GrowthChance</samp>, but with [[Tree Fertilizer|tree fertilizer]]. Defaults to 1 (100% chance).
+
! effect
 
|-
 
|-
| <samp>SeedChance</samp>
+
| <samp>campfire_item</samp>
| ''(Optional)'' The probability each day that the tree will produce a seed that will drop when the tree is shaken, as a value from 0 (never) to 1 (always). Default 0.05 (5% chance).
+
| Marks the item as a [[campfire]]. If the item also has the <samp>torch_item</samp> context tag, when it's placed in the world and turned on...
 +
* campfire flames are drawn over it;
 +
* if the item is [[Modding:Items#Big craftables|big craftable]], light is emitted from its center instead of the top.
 
|-
 
|-
| <samp>SeedOnChopChance</samp>
+
| <samp>fish_pond_ignore</samp>
| ''(Optional)'' The probability that a seed will drop when the player chops down the tree, as a value from 0 (never) to 1 (always). Default 0.75 (75% chance).
+
| Prevents players from adding this fish to [[Fish Pond|fish ponds]], even if it would otherwise match an entry in <samp>Data/FishPondData</samp>.
 
|-
 
|-
| <samp>DropWoodOnChop</samp>
+
| <samp>geode_crusher_ignored</samp>
| ''(Optional)'' Whether to drop [[wood]] when the player chops down the tree. Default true.
+
| Prevents breaking this item open in a [[Geode Crusher|geode crusher]], even if the item has geode fields in [[#Custom objects|<samp>Data/Objects</samp>]].
 
|-
 
|-
| <samp>DropHardwoodOnLumberChop</samp>
+
| <samp>item_type_{{t|type}}</samp>
| ''(Optional)'' Whether to drop [[hardwood]] when the player chops down the tree, if they have the [[Skills#Foraging|Lumberjack profession]]. Default true.
+
| For an [[Modding:Items#Objects|object-type item]], the type value from the 'type and category' field. (Non-object items always have the exact tag <samp>item_type_</samp> with nothing after the last underscore.) This is automatic and shouldn't be set manually. The tag is checked in a few places (''e.g.'' the [[museum]] to check if an item is an artifact or mineral), but most of the game won't be affected.
 
|-
 
|-
| <samp>IsLeafy</samp>
+
| <samp>museum_donatable</samp><br /><samp>not_museum_donatable</samp>
| ''(Optional)'' Whether shaking or chopping the tree causes cosmetic leaves to drop from tree and produces a leaf rustle sound. When a leaf drops, the game will use one of the four leaf sprites in the tree's spritesheet in the slot left of the stump sprite. Default true.
+
| Set whether the item can be donated to the [[museum]], overriding the vanilla logic.
 
|-
 
|-
| <samp>IsLeafyInWinter</samp>
+
| <samp>not_giftable</samp>
| ''(Optional)'' Whether <samp>IsLeafy</samp> also applies in winter. Default false.
+
| Prevents players from gifting this item to NPCs, who'll ignore the item entirely (e.g. as if you were holding a tool).
 +
 
 +
This only affects gift-giving, it doesn't affect non-gift logic like quest goals or special order objectives. If the NPC also has a <samp>reject_*</samp> dialogue for the item, the dialogue takes priority.
 
|-
 
|-
| <samp>GrowsInWinter</samp>
+
| <samp>not_placeable</samp><br /><samp>placeable</samp>
| ''(Optional)'' Whether the tree can grow in winter (subject to <samp>GrowthChance</samp> or <samp>FertilizedGrowthChance</samp>). Default false.
+
| Sets whether the item can be placed on the ground.
 
|-
 
|-
| <samp>IsStumpDuringWinter</samp>
+
| <samp>prevent_loss_on_death</samp>
| ''(Optional)'' Whether the tree is reduced to a stump in winter and regrows in spring, like the vanilla [[Trees#Mushroom Tree|mushroom tree]]. Default false.
+
| Indicates the item can't be [[Adventurer's Guild#Item Recovery Service|lost when the player dies]].
 
|-
 
|-
| <samp>AllowWoodpeckers</samp>
+
| <samp>sign_item</samp>
| ''(Optional)'' Whether woodpeckers can spawn on the tree. Default true.
+
| Marks the item as a [[Crafting#Signs|sign]], which lets player display items on it or place it on a [[Fish Pond|fish pond]] to show the fish count.
 
|-
 
|-
| <samp>UseAlternateSpriteWhenNotShaken</samp><br /><samp>UseAlternateSpriteWhenSeedReady</samp>
+
| <samp>torch_item</samp>
| ''(Optional)'' Whether to render a different tree sprite when the player hasn't shaken it on that day (<samp>UseAlternateSpriteWhenNotShaken</samp>) or it has a seed ready (<samp>UseAlternateSpriteWhenSeedReady</samp>). If either field is true, the tree spritesheet must be double-width with the alternate textures on the right. If both are true, the same alternate sprites are used for both. Default false.
+
| Marks the item as a [[torch]], which lets the player turn it on/off to emit light.
|-
  −
| <samp>DebrisColor</samp>
  −
| ''(Optional)'' The color of the cosmetic wood chips when chopping the tree. This can be...
  −
* a [[#Color fields|standard color format]];
  −
* or one of <samp>12</samp> (brown/woody), <samp>100001</samp> (white), <samp>100001</samp> (light green),  <samp>100002</samp> (light blue), <samp>100003</samp> (red), <samp>100004</samp> (yellow), <samp>100005</samp> (black), <samp>100006</samp> (gray), or <samp>100007</samp> (charcoal / dim gray).
     −
Defaults to <samp>12</samp> (brown/woody).
+
See also <samp>campfire_item</samp>.
|-
+
|}
| <samp>SeedDropItems</samp>
  −
| ''(Optional)'' When a seed is dropped subject to <samp>SeedChance</samp>, the item to drop instead of the item specified by <samp>SeedItemId</samp>. If this is empty or none match, the <samp>SeedItemId</samp> will be dropped instead.
     −
This consists of a list of models with these fields:
+
Context tags which affect [[#Custom machines|machine processing]]:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! context tag
 
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <samp>crystalarium_banned</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for chop drops.
+
| When applied to a gem or mineral item, prevents players from placing it in a [[crystalarium]].
 
  −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
   
|-
 
|-
| <samp>Season</samp>
+
| <samp>keg_juice</samp><br /><samp>keg_wine</samp>
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
+
| Allows processing the item in a [[keg]] to produce a juice or wine variant.
 
|-
 
|-
| <samp>Chance</samp>
+
| <samp>preserves_jelly</samp><br /><samp>preserves_pickle</samp>
| ''(Optional)'' The probability that the item will drop, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| Allows processing the item in a [[Preserves Jar|preserves jar]] to produce a jelly or pickled variant.
 +
|-
 +
| <samp>seedmaker_banned</samp>
 +
| When applied to a seed item, prevents players from placing it in a [[Seed Maker|seed maker]].
 +
|-
 +
| <samp>tapper_item</samp>
 +
| Marks the item as a [[tapper]] or [[Heavy Tapper|heavy tapper]].
 
|-
 
|-
| <samp>ContinueOnDrop</samp>
+
| <samp>tapper_multiplier_{{t|multiplier}}</samp>
| ''(Optional)'' If this item is dropped, whether to continue as if it hadn't been dropped for the remaining drop candidates. Default false.
+
| The multiplier applied to the tapper production speed. For example, <samp>2</samp> will make items take half their base time (''i.e.'' each item will finish in <sup>base time</sup>/<sub>speed multiplier</sub>). Defaults to 1 if omitted.
 
|}
 
|}
|-
  −
| <samp>ChopItems</samp>
  −
| ''(Optional)'' The additional items to drop when the tree is chopped down. All matching items are dropped.
     −
This consists of a list of models with these fields:
+
And informational tags which have no effect on the game logic:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! context tag
 
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <samp>fish_legendary</samp><br /><samp>fish_legendary_family</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for chop drops.
+
| Marks the fish as a [[Fish#Legendary Fish|legendary fish]] or [[Quests#Extended Family|legendary fish family]]. These are purely informational; the legendary fish behavior is determined by data fields like <samp>CatchLimit</samp> or <samp>IsBossFish</samp> in [[#Custom locations|<samp>Data/Locations</samp>]].
 
+
|-
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
| <samp>geode</samp>
 +
| ''(Added automatically)'' Marks the item as a [[Minerals#Geodes|geode]] item, which can be broken open at [[Blacksmith|Clint's blacksmith shop]] or using a [[Geode Crusher|geode crusher]]. This is added automatically if the geode fields are present in [[#Custom objects|<samp>Data/Objects</samp>]].
 
|-
 
|-
| <samp>Season</samp>
+
| <samp>id_{{t|item id}}</samp>
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
+
| ''(Added automatically)'' The [[#Custom items|qualified item ID]], like <samp>id_(o)128</samp>. This can be used to match or exclude an item by ID using context tags. Any spaces in the ID are replaced with underscores, and single quotes are removed.
 
|-
 
|-
| <samp>Chance</samp>
+
| <samp>is_machine</samp>
| ''(Optional)'' The probability that the item will drop, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| ''(Added automatically)'' Indicates the item has [[#Custom machines|machine logic]]. This is added automatically based on <samp>Data/Machines</samp>.
 
|-
 
|-
| <samp>MinSize</samp><br /><samp>MaxSize</samp>
+
| <samp>machine_input</samp>
| ''(Optional)'' The minimum and/or maximum growth stage for the tree at which this item is produced. The possible values are <samp>Seed</samp>, <samp>Sprout</samp>, <samp>Sapling</samp>, <samp>Bush</samp>, and <samp>Tree</samp>. Both default to no limit.
+
| ''(Added automatically)'' Whether the item is a machine which accepts items from the player. This is added automatically based on the machine's fields in <samp>Data/Machines</samp>:
 +
* if <samp>HasInput</samp> is true;
 +
* ''or'' if any output rules have an <samp>ItemPlacedInMachine</samp> trigger.
 
|-
 
|-
| <samp>ForStump</samp>
+
| <samp>machine_output</samp>
| ''(Optional)'' Whether the item is only produced if the tree is a stump (<samp>true</samp>), not a stump (<samp>false</samp>), or both (<samp>null</samp>). Defaults to <samp>false</samp> (non-stumps only).
+
| ''(Added automatically)'' Whether the item is a machine which produces items for the player to collect. This is added automatically based on the machine's fields in <samp>Data/Machines</samp>:
 +
* if <samp>HasOutput</samp> is true;
 +
* ''or'' if it has any output rules.
 
|}
 
|}
|-
  −
| <samp>ShakeItems</samp>
  −
| The items produced by shaking the tree when it's fully grown. This only applies the first time the tree is shaken each day. All matching items are dropped.
     −
This consists of a list of models with these fields:
+
====ItemContextTagManager class====
 +
For C# mods, 1.6 adds a new <samp>ItemContextTagManager</samp> class which simplifies working with [[Modding:Items#Context tags|item context tags]] and reduces repeated code.
 +
 
 +
This provides a few utility methods:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! method
 
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <code>GetBaseContextTags(id)</code>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for shake items.
+
| Get the base context tags for an item based on its raw data in <samp>Data/Objects</samp> or <samp>Data/BigCraftables</samp>. This doesn't include dynamic tags added that are based on instance info (like quality), which you can get using <code>item.GetContextTags()</code>.
 
+
|-
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
| <code>DoesTagQueryMatch(query, tags)</code>
 +
| Get whether a context tag query matches the given tags. For example, <code>ItemContextTagManager.DoesTagQueryMatch("bone_item, !fossil_item", item.GetContextTags())</code> returns true if the item is a bone item but not a fossil (like the [[Bone Flute]]).
 +
|-
 +
| <code>DoAllTagsMatch(requiredTags, actualTags)</code><br /><code>DoAnyTagsMatch(requiredTags, actualTags)</code>
 +
| Get whether every (<samp>DoAllTagsMatch</samp>) or at least one (<samp>DoAnyTagsMatch</samp) required tag matches the actual item tags. This supports negated required tags like <samp>"!fossil_item"</samp> too.
 
|-
 
|-
| <samp>Season</samp>
+
| <code>DoesTagMatch(requiredTag, actualTags)</code>
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
+
| Get whether a single tag matches the actual item tags. This supports negated required tags like <samp>"!fossil_item"</samp> too.
 
|-
 
|-
| <samp>Chance</samp>
+
| <code>SanitizeContextTag(tag)</code>
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| ''(Specialized)'' Replace characters that may appear in item names so they're valid in context tags. For example, <code>SanitizeContextTag("Sam's Boombox")</code> returns <samp>sams_boombox</samp>.
 
|}
 
|}
|-
  −
| <samp>TapItems</samp>
  −
| The items produced by [[Tapper|tapping]] the tree. If multiple items can be produced, the first available one is selected.
     −
This consists of a list of models with these fields:
+
====Other context tag changes====
 +
* Context tags are now case-insensitive.
 +
 
 +
===Inventory class===
 +
For C# mods, 1.6 adds a new <samp>Inventory</samp> class to manage a list of items. This is used for the <samp>Farmer.items</samp> and <samp>Chest.items</samp> fields. It implements <samp>IList&lt;Item&gt;</samp>, so most existing code should still work fine.
 +
 
 +
This has three main benefits:
 +
<ul>
 +
<li>It has methods to simplify many common operations. For example:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! method
 
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <code>HasAny()</code>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for tapper items.
+
| Get whether the inventory contains any items (ignoring empty slots).
 
  −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
   
|-
 
|-
| <samp>Season</samp>
+
| <code>CountItemStacks()</code>
| ''(Optional)'' If set, the item only applies if the tree's location is in this season.
+
| Get the number of item stacks in the inventory (ignoring empty slots).
 
|-
 
|-
| <samp>Chance</samp>
+
| <code>ContainsId(id)</code>
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| Get whether the inventory contains any item with the given qualified or unqualified item ID.
 
|-
 
|-
| <samp>DaysUntilReady</samp>
+
| <code>ContainsId(id, minCount)</code>
| The number of days before the tapper is ready to empty.
+
| Get whether the inventory contains items with the given qualified or unqualified item ID, and their combined stack size is at least <samp>minCount</samp>.
 
|-
 
|-
| <samp>PreviousItemId</samp>
+
| <code>CountId(id)</code>
| ''(Optional)'' If set, the item only applies if the previous item produced by the tapper matches one of the given [[#Custom items|qualified item IDs]]. If an entry is null or an empty string, it matches when there's no previous item.
+
| Get the combined stack size of all items with the given qualified or unqualified item ID.
 
  −
For example: <code>"PreviousItemId": [ null ]</code> only applies when a tapper is first added to the tree, and <code>"PreviousItemsId": [ "(O)420" ]</code> applies if the player just collected a [[Red Mushroom|red mushroom]] (object #420) from it.
   
|-
 
|-
| <samp>DaysUntilReadyModifiers</samp>
+
| <code>GetById(id)</code>
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] applied to the <samp>DaysUntilReady</samp> value. Default none.
+
| Get a list of items in the inventory with the given qualified or unqualified item ID.
 
|-
 
|-
| <samp>DaysUntilReadyModifiersMode</samp>
+
| <code>ReduceId(id, count)</code>
| ''(Optional)'' [[#Quantity modifiers|quantity modifier modes]] which indicate what to do if multiple modifiers in the <samp>DaysUntilReadyModifiersMode</samp> field apply at the same time. Default <samp>Stack</samp>.
+
| Remove the given number of items matching the given qualified or unqualified item ID. This reduces the stack size for matching items until a total of <samp>count</samp> have been removed, and clears any slots which reach a stack size of zero.
|}
+
|}</li>
|-
+
<li>Many common operations have been unified, so previously player-only methods can now be used with chests too.</li>
| <samp>PlantableLocationRules</samp>
+
<li>It has an internal index by item ID, so operations like <code>items.ContainsId("(O)128")</code> are much more efficient since they no longer iterate the list.</li>
| ''(Optional)'' The rules to decide which locations you can plant the seed in, if applicable. The first matching rule is used. This can override location checks (e.g. crops being limited to the farm), but not built-in requirements like crops needing dirt.
+
</ul>
   −
This consists of a list of models with these fields:
+
This replaces some previous methods:
    
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! game class
! effect
+
! old code
 +
! migration
 +
|-
 +
|rowspan="6"| <samp>Farmer</samp>
 +
| <code>getItemCount(id)</code><br /><code>GetTallyOfObject(id)</code><br /><code>GetTallyOfObject(id, isBigCraftable)</code><br /><code>hasItemInInventory(id, count)</code><br /><code>hasItemInList(list, id, count)</code>
 +
| &#32;
 +
* To check an item ID, use <code>items.CountId(id)</code> or <code>Items.ContainsId(id, count)</code>.
 +
* To check Golden Walnuts or Qi Gems, use the <samp>Game1.netWorldState.Value.GoldenWalnuts</samp> and <samp>Farmer.QiGems</samp> fields.
 +
* To check category matches or <samp>-777</samp> (seasonal wild seeds), the <samp>getItemCount</samp> and <samp>getItemCountInList</samp> still exist.
 +
|-
 +
| <code>hasItemInInventoryNamed(name)</code><br /><code>hasItemWithNameThatContains(name)</code>
 +
| In most cases, you should match items by ID instead (see the previous row).
 +
 
 +
If you really need to match items by name, you can replace it like this:
 +
<syntaxhighlight lang="c#">
 +
// exact name
 +
bool hasMatch = Game1.player.Items.Any(item => item?.Name == name);
 +
 
 +
// name contains
 +
bool hasMatch = Game1.player.Items.Any(item => item?.Name?.Contains(name) is true);
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>Id</samp>
+
| <code>areAllItemsNull()</code>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the list.
+
| Use <code>!items.HasAny()</code>.
 
|-
 
|-
| <samp>Result</samp>
+
| <code>numberOfItemsInInventory()</code>
| Indicates whether the seed can be planted in a location if this entry is selected. The possible values are:
+
| Use <code>items.CountItemStacks()</code> to count all items, or <code>Items.Count(p => p is Object)</code> to match this method's actual behavior.
* <samp>Default</samp>: the seed can be planted if the location normally allows it. This can be used to stop processing further rules, and/or set a custom <samp>DeniedMessage</samp>.
  −
* <samp>Allow</samp>: the seed can be planted here, regardless of whether the location normally allows it.
  −
* <samp>Deny</samp>: the seed can't be planted here, regardless of whether the location normally allows it.
   
|-
 
|-
| <samp>Condition</samp>
+
| <code>consumeObject(id, count)</code>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry applies. Default true.
+
| Use <code>items.ReduceId(id, count)</code>.
 
|-
 
|-
| <samp>PlantedIn</samp>
+
| <code>removeItemsFromInventory(id, count)</code>
| ''(Optional)'' The planting context to apply this rule for. The possible values are <samp>Ground</samp> (planted directly in the ground), <samp>GardenPot</samp> (planted in a [[Garden Pot|garden pot]]), or <samp>Any</samp>. Default <samp>Any</samp>.
+
| &#32;
 
+
* To remove an item by ID, use <code>items.ReduceId(id, count)</code>.
Note that trees can't be planted in garden pots.
+
* To deduct Golden Walnuts or Qi Gems, change the <samp>Game1.netWorldState.Value.GoldenWalnuts</samp> and <samp>Farmer.QiGems</samp> fields.
 
|-
 
|-
| <samp>DeniedMessage</samp>
+
|rowspan="2"| <samp>Object</samp>
| ''(Optional)'' If this rule prevents planting the seed, the tokenizable string to show to the player (or <samp>null</samp> to default to the normal behavior for the context). This also applies when the <samp>Result</samp> is <samp>Default</samp>, if that causes the planting to be denied.
+
| <code>ConsumeInventoryItem(player, id, count)</code>
|}
+
| This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be <code>(Object.autoLoadChest ?? player.items).ReduceId(id, count)</code>. See also notes for <samp>Farmer.removeItemsFromInventory</samp>.
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <code>GetTallyOfObject(player, id)</code>
| The [[#Custom data fields|custom fields]] for this entry.
+
| This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be <code>(Object.autoLoadChest ?? player.items).CountId(id)</code>. See also notes for <samp>Farmer.getTallyOfObject</samp>.
 
|}
 
|}
   −
====Spawning wild trees====
+
It implements a new <samp>IInventory</samp> interface, which lets mods pass their own implementations to code which works on inventories.
Custom trees can be added to the game in two ways:
  −
* Spawn them on [[Modding:Maps|map tiles]] when the location is created, using the new <samp>SpawnTree: wild {{t|tree ID}} {{o|growth stage on location created}} {{o|growth stage on day-update regrowth}}</samp> tile property. This must be added on the <samp>Paths</samp> layer, which must also have tile index 34 from the <samp>paths</samp> tilesheet.
  −
* Or give the player a seed item in the usual ways (e.g. from [[#Custom shops|a shop]], [[Modding:Mail data|mail letter]], etc).
     −
===Default recipes===
+
===Furniture changes===
You can now have [[Modding:Recipe data|crafting and cooking recipes]] that are learned automatically by setting the condition field to <samp>default</samp>. Any missing default recipes will be learned on day start.
+
{{/doc status|[[Modding:Items#Furniture]]|done=false}}
   −
For example, here's the chest entry from <samp>Data/CraftingRecipes</samp>:
+
<ul>
<syntaxhighlight lang="js">
+
<li>[[Modding:Items#Furniture|<samp>Data/furniture</samp>]] no longer has language variants. Translations were moved into <samp>Strings/Furniture</samp>.</li>
"Chest": "388 50/Home/130/true/default/"
+
<li>
</syntaxhighlight>
+
There are a few changes in [[Modding:Items#Furniture|<samp>Data/furniture</samp>]]:
 
+
<ul>
===Global inventories===
+
<li>Field index 6 is now placement restrictions and field index 7 is now display name. The display name field is no longer omitted in English.</li>
C# mods can now set a <samp>chest.GlobalInventoryId</samp> field to make it share a global inventory with every other chest having the same ID. This replaces the equivalent hardcoded logic for [[Junimo Chest|Junimo chests]], which now just default to a <samp>"JunimoChests"</samp> global inventory ID. For example, this can be used to have multiple Junimo chest networks or make other containers share inventory.
+
<li>Field index 7 (display name) now allows [[Modding:Tokenizable strings|tokenizable strings]].</li>
 
+
<li>Added new fields:
C# mods can also use this to store items for other mod purposes, by using <samp>Game1.player.team.globalInventories</samp> or <samp>Game1.player.team.GetOrCreateGlobalInventory(id)</samp> directly.
  −
 
  −
===Hats on aquarium fish===
  −
Custom [[Modding:Fish data|fish in aquariums]] can now wear [[hats]], just like vanilla [[Sea Urchin|sea urchins]]. This can be enabled by specifying a new field in <samp>Data/AquariumFish</samp>:
      
{| class="wikitable"
 
{| class="wikitable"
Line 2,447: Line 2,410:  
! index
 
! index
 
! field
 
! field
! purpose
  −
|-
  −
| 7
  −
| hat position
  −
| The pixel position of the hat on the sprite, specified as an object with <samp>X</samp> and <samp>Y</samp> values.
  −
|}
  −
  −
===Context tag changes===
  −
====New context tags====
  −
1.6 adds several new [[Modding:Items#Context tags|item context tags]]:
  −
  −
{| class="wikitable"
  −
|-
  −
! context tag
   
! effect
 
! effect
 
|-
 
|-
| <samp>campfire_item</samp>
+
| 8
| Marks the item as a [[campfire]]. If the item also has the <samp>torch_item</samp> context tag, when it's placed in the world and turned on...
+
| sprite index
* campfire flames are drawn over it;
+
| The sprite index within the spritesheet texture to draw.
* if the item is [[Modding:Items#Big craftables|big craftable]], light is emitted from its center instead of the top.
   
|-
 
|-
| <samp>fish_pond_ignore</samp>
+
| 9
| Prevents players from adding this fish to [[Fish Pond|fish ponds]], even if it would otherwise match an entry in <samp>Data/FishPondData</samp>.
+
| texture
 +
| ''(Optional)'' The asset name of the texture to draw. Defaults to <samp>TileSheets/furniture</samp>.
 
|-
 
|-
| <samp>geode_crusher_ignored</samp>
+
| 10
| Prevents breaking this item open in a [[Geode Crusher|geode crusher]], even if the item has geode fields in [[#Custom objects|<samp>Data/Objects</samp>]].
+
| off limits for random sale
 +
| ''(Optional)'' Whether to prevent this furniture from appearing in randomly generated shop stocks and the furniture catalogue. Default false.
 
|-
 
|-
| <samp>item_type_{{t|type}}</samp>
+
| 11
| For an [[Modding:Items#Objects|object-type item]], the type value from the 'type and category' field. (Non-object items always have the exact tag <samp>item_type_</samp> with nothing after the last underscore.) This is automatic and shouldn't be set manually. The tag is checked in a few places (''e.g.'' the [[museum]] to check if an item is an artifact or mineral), but most of the game won't be affected.
+
| context tags
|-
+
| ''(Optional)'' A space-delimited list of [[Modding:Items#Context tags|context tags]] which apply to this furniture. Default none.
| <samp>museum_donatable</samp><br /><samp>not_museum_donatable</samp>
+
|}</li>
| Set whether the item can be donated to the [[museum]], overriding the vanilla logic.
+
</ul>
|-
+
</li>
| <samp>not_giftable</samp>
+
</ul>
| Prevents players from gifting this item to NPCs, who'll ignore the item entirely (e.g. as if you were holding a tool).
     −
This only affects gift-giving, it doesn't affect non-gift logic like quest goals or special order objectives. If the NPC also has a <samp>reject_*</samp> dialogue for the item, the dialogue takes priority.
+
===Other item changes for C# mods===
|-
+
* Placed object changes:
| <samp>not_placeable</samp><br /><samp>placeable</samp>
+
** Every placed object now has a <samp>Location</samp> property set to the location which contains it. This removes location parameters from many object methods.
| Sets whether the item can be placed on the ground.
+
** Setting an object's tile position through <samp>obj.TileLocation</samp> now recalculcates its collision box automatically. (Setting it through the <samp>tileLocation</samp> net field directly won't though.)
|-
+
** The <samp>obj.IsScarecrow()</samp> and <samp>GetScarecrowRadius()</samp> methods now work for non-bigcraftable objects too.
| <samp>prevent_loss_on_death</samp>
+
* Clothing changes:
| Indicates the item can't be [[Adventurer's Guild#Item Recovery Service|lost when the player dies]].
+
** <samp>Clothes.clothesType</samp> is now an enum field.
|-
+
** Clothing is no longer gender-specific. This renames <samp>indexInTileSheetMale</samp> to <samp>indexInTileSheet</samp>, obsoletes <samp>indexInTileSheetFemale</samp>, and converts gender-variant clothing into regular items.
| <samp>sign_item</samp>
+
** Removed unused <samp>ClothesType.ACCESSORY</samp> value.
| Marks the item as a [[Crafting#Signs|sign]], which lets player display items on it or place it on a [[Fish Pond|fish pond]] to show the fish count.
+
** <samp>Farmer.pants</samp> and <samp>Farmer.shirt</samp> now store the item ID instead of the sprite index.
|-
+
** In <samp>Data/TailoringRecipes</samp>, added a <samp>CraftingIdFeminine</samp> field which overrides <samp>CraftingId</samp> for female characters.
| <samp>torch_item</samp>
+
* Crop changes:
| Marks the item as a [[torch]], which lets the player turn it on/off to emit light.
+
** Added <samp>Game1.cropData</samp> to read crop info without constantly reloading the <samp>Data/Crops</samp> asset.
 +
** Removed most crop fields which only mirror the data (like <samp>harvestMethod</samp> or <samp>seasonsToGrowIn</samp>). Mods can get the info through <samp>crop.GetData()</samp> instead.
 +
** Partly de-hardcoded fertilizer logic. Almost all fertilizer logic is now centralized into a new patchable set of <samp>HoeDirt</samp> methods (see list below). The only fertilizer logic that's still embedded elsewhere is the interaction errors in <samp>Utility.tryToPlaceItem</samp>.
 +
** HoeDirt.fertilizer.Value is now set to <samp>null</samp> when there is no fertilizer. Both qualified and unqualified IDs should be expected.
 +
** Removed <samp>crop.InferSeedIndex()</samp>. This was used to support old crops, which are now fixed by a save migration instead.
 +
* Tool changes:
 +
** Fixed various logic not handling custom tool upgrade levels.
 +
<ul>
 +
<li>Other item logic:<ul>
 +
<li>Simplified the constructors for many item types, particularly <samp>Object</samp>.</li>
 +
<li>[[Honey]] items now have their <samp>preserve</samp> field set to a new <samp>Honey</samp> type (instead of null).</li>
 +
<li>The <samp>Object.performObjectDropInAction</samp> method now applies the <samp>probe</samp> argument much more consistently. This only affects method calls with <samp>probe: true</samp>.</li>
 +
<li>The <samp>Item.salePrice()</samp> method now has option to get the price without [[Multiplayer#Profit margins|profit margins]].</li>
 +
<li>Added new fields & methods:
   −
See also <samp>campfire_item</samp>.
  −
|}
  −
  −
Context tags which affect [[#Custom machines|machine processing]]:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! context tag
+
! type
 +
! field/method
 
! effect
 
! effect
 
|-
 
|-
| <samp>crystalarium_banned</samp>
+
| <samp>Chest</samp>
| When applied to a gem or mineral item, prevents players from placing it in a [[crystalarium]].
+
| <samp>GetItemsForPlayer()</samp>
 +
| Shortcut for <samp>chest.GetItemsForPlayer(Game1.player.UniqueMultiplayerID)</samp>.
 
|-
 
|-
| <samp>keg_juice</samp><br /><samp>keg_wine</samp>
+
| rowspan="2"| <samp>Crop</samp>
| Allows processing the item in a [[keg]] to produce a juice or wine variant.
+
| <samp>GetHarvestMethod()</samp>
 +
| Get the method used to harvest the crop (one of <samp>HarvestMethod.Grab</samp> or <samp>HarvestMethod.Scythe</samp>).
 +
|-
 +
| <samp>IsInSeason(location)</samp>
 +
| Whether the crop can grow in the location's current season (or true if crops ignore seasons in the location, like the [[greenhouse]]).
 
|-
 
|-
| <samp>preserves_jelly</samp><br /><samp>preserves_pickle</samp>
+
| rowspan="8"| <samp>HoeDirt</samp>
| Allows processing the item in a [[Preserves Jar|preserves jar]] to produce a jelly or pickled variant.
+
| <samp>HasFertilizer()</samp>
 +
| Get whether the dirt has any fertilizer applied.
 
|-
 
|-
| <samp>seedmaker_banned</samp>
+
| <samp>CanApplyFertilizer(itemId)</samp>
| When applied to a seed item, prevents players from placing it in a [[Seed Maker|seed maker]].
+
| Get whether a player can apply the given fertilizer to this dirt.
 
|-
 
|-
| <samp>tapper_item</samp>
+
| <samp>CheckApplyFertilizerRules(itemId)</samp>
| Marks the item as a [[tapper]] or [[Heavy Tapper|heavy tapper]].
+
| Get whether a player can apply the given fertilizer to this dirt, and the reason they can't if applicable.
 
|-
 
|-
| <samp>tapper_multiplier_{{t|multiplier}}</samp>
+
| <samp>GetFertilizerSpeedBoost()</samp>
| The multiplier applied to the tapper production speed. For example, <samp>2</samp> will make items take half their base time (''i.e.'' each item will finish in <sup>base time</sup>/<sub>speed multiplier</sub>). Defaults to 1 if omitted.
+
| Get the crop growth speed boost from fertilizers applied to this dirt.
|}
  −
 
  −
And informational tags which have no effect on the game logic:
  −
{| class="wikitable"
   
|-
 
|-
! context tag
+
| <samp>GetFertilizerWaterRetentionChance()</samp>
! effect
+
| Get the water retention chance from fertilizers applied to this dirt, as a value between 0 (no change) and 1 (100% chance of staying watered).
 
|-
 
|-
| <samp>fish_legendary</samp><br /><samp>fish_legendary_family</samp>
+
| <samp>GetFertilizerQualityBoostLevel()</samp>
| Marks the fish as a [[Fish#Legendary Fish|legendary fish]] or [[Quests#Extended Family|legendary fish family]]. These are purely informational; the legendary fish behavior is determined by data fields like <samp>CatchLimit</samp> or <samp>IsBossFish</samp> in [[#Custom locations|<samp>Data/Locations</samp>]].
+
| Get the quality boost level from fertilizers applied to this dirt, which influences the chance of producing a higher-quality crop.
 
|-
 
|-
| <samp>geode</samp>
+
| <samp>GetFertilizerSourceRect()</samp>
| ''(Added automatically)'' Marks the item as a [[Minerals#Geodes|geode]] item, which can be broken open at [[Blacksmith|Clint's blacksmith shop]] or using a [[Geode Crusher|geode crusher]]. This is added automatically if the geode fields are present in [[#Custom objects|<samp>Data/Objects</samp>]].
+
| Get the pixel area within the dirt spritesheet to draw for any fertilizer applied to this dirt.
 +
 
 +
(This method existed before, but no longer requires the fertilizer ID argument.)
 
|-
 
|-
| <samp>id_{{t|item id}}</samp>
+
| <samp>isWatered()</samp>
| ''(Added automatically)'' The [[#Custom items|qualified item ID]], like <samp>id_(o)128</samp>. This can be used to match or exclude an item by ID using context tags. Any spaces in the ID are replaced with underscores, and single quotes are removed.
+
| Get whether the dirt is currently watered.
 
|-
 
|-
| <samp>is_machine</samp>
+
|rowspan="5"| <samp>Item</samp>
| ''(Added automatically)'' Indicates the item has [[#Custom machines|machine logic]]. This is added automatically based on <samp>Data/Machines</samp>.
+
| <samp>IsRecipe</samp><br /><samp>Quality</samp><br /><samp>Stack</samp></samp><br /><samp>sellToStorePrice()</samp>
 +
| Equivalent to the previous <samp>Object</samp> fields/methods, to simplify common code and avoid needing to special-case <samp>Object</samp> items.
 
|-
 
|-
| <samp>machine_input</samp>
+
| <samp>appliesProfitMargins()</samp>
| ''(Added automatically)'' Whether the item is a machine which accepts items from the player. This is added automatically based on the machine's fields in <samp>Data/Machines</samp>:
+
| Get whether this item should apply [[Multiplayer#Profit margins|profit margins]] to shop prices.
* if <samp>HasInput</samp> is true;
  −
* ''or'' if any output rules have an <samp>ItemPlacedInMachine</samp> trigger.
   
|-
 
|-
| <samp>machine_output</samp>
+
| <samp>CanBeLostOnDeath()</samp>
| ''(Added automatically)'' Whether the item is a machine which produces items for the player to collect. This is added automatically based on the machine's fields in <samp>Data/Machines</samp>:
+
| Get whether this item can be lost when the player dies, so it can be recovered from the [[Adventurer's Guild#Item Recovery Service|item recovery service]].
* if <samp>HasOutput</samp> is true;
+
|-
* ''or'' if it has any output rules.
+
| <samp>HasTypeId(id)</samp><br /><samp>HasTypeObject()</samp><br /><samp>HasTypeBigCraftable()</samp>
|}
+
| Get whether the item has the given [[#Custom items|type definition ID]]. These are null-safe and double as a null check:
 +
<syntaxhighlight lang="c#">
 +
if (item.HasTypeId(ItemRegistry.type_object))
 +
{
 +
    // item is non-null and has type (O)
 +
}
 +
</syntaxhighlight>
 +
<samp>HasTypeObject()</samp> and <samp>HasTypeBigCraftable()</samp> are shortcuts for passing <samp>ItemRegistry.type_object</samp> and <samp>ItemRegistry.type_bigCraftable</samp> respectively.
 +
|-
 +
| <samp>TryGetTempData</samp><br /><samp>SetTempData</samp>
 +
| Get or set temporary item info that's not synchronized in multiplayer or written to the save file.
 +
 
 +
For example, the game uses this to pass spawn options to the fishing minigame:
 +
<syntaxhighlight lang="c#">
 +
if (spawn.IsBossFish)
 +
    fish.SetTempData(nameof(spawn.IsBossFish), true);
   −
====ItemContextTagManager class====
+
...
For C# mods, 1.6 adds a new <samp>ItemContextTagManager</samp> class which simplifies working with [[Modding:Items#Context tags|item context tags]] and reduces repeated code.
     −
This provides a few utility methods:
+
fish.TryGetTempData(nameof(SpawnFishData.IsBossFish), out bool bossFish);
{| class="wikitable"
+
</syntaxhighlight>
 
|-
 
|-
! method
+
| <samp>FishingRod</samp>
! effect
+
| <samp>CanUseBait()</samp><br /><samp>CanUseTackle()</samp><br /><samp>GetBait()</samp><br /><samp>GetTackle()</samp><br /><samp>HasMagicBait()</samp><br /><samp>HasCuriosityLure()</samp>
 +
| Simplifies working with the fishing rod's [[bait]] and [[tackle]].
 
|-
 
|-
| <code>GetBaseContextTags(id)</code>
+
|rowspan="2"| <samp>Furniture</samp>
| Get the base context tags for an item based on its raw data in <samp>Data/Objects</samp> or <samp>Data/BigCraftables</samp>. This doesn't include dynamic tags added that are based on instance info (like quality), which you can get using <code>item.GetContextTags()</code>.
+
| <samp>SetPlacement</samp><br /><samp>SetHeldObject</samp>
 +
| Set the furniture's position and rotation (<samp>SetPlacement</samp>) or held object (<samp>SetHeldObject</samp>). The latter will initialize the held object's tile position to match the furniture instance.
 +
 
 +
These are used by the game to initialize furniture in one go. For example:
 +
<syntaxhighlight lang="c#">
 +
// oak table holding decorative bowl
 +
Furniture table = ItemRegistry
 +
    .Create<Furniture>("(F)1120")
 +
    .SetPlacement(5, 4, 0)
 +
    .SetHeldObject(ItemRegistry.Create<Furniture>("(F)1364"));
 +
</syntaxhighlight>
 
|-
 
|-
| <code>DoesTagQueryMatch(query, tags)</code>
+
| <samp>IsTable()</samp>
| Get whether a context tag query matches the given tags. For example, <code>ItemContextTagManager.DoesTagQueryMatch("bone_item, !fossil_item", item.GetContextTags())</code> returns true if the item is a bone item but not a fossil (like the [[Bone Flute]]).
+
| Get whether this furniture is a table.
 
|-
 
|-
| <code>DoAllTagsMatch(requiredTags, actualTags)</code><br /><code>DoAnyTagsMatch(requiredTags, actualTags)</code>
+
|rowspan="2"| <samp>FruitTree</samp>
| Get whether every (<samp>DoAllTagsMatch</samp>) or at least one (<samp>DoAnyTagsMatch</samp) required tag matches the actual item tags. This supports negated required tags like <samp>"!fossil_item"</samp> too.
+
| <samp>GetQuality()</samp>
 +
| Get the quality of fruit currently being produced by the fruit tree.
 
|-
 
|-
| <code>DoesTagMatch(requiredTag, actualTags)</code>
+
| <samp>TryAddFruit()</samp>
| Get whether a single tag matches the actual item tags. This supports negated required tags like <samp>"!fossil_item"</samp> too.
+
| Add a fruit item to the tree based on [[#Custom fruit trees|its data]].
 
|-
 
|-
| <code>SanitizeContextTag(tag)</code>
+
| <samp>IndoorPot</samp>
| ''(Specialized)'' Replace characters that may appear in item names so they're valid in context tags. For example, <code>SanitizeContextTag("Sam's Boombox")</code> returns <samp>sams_boombox</samp>.
+
| <samp>Water()</samp>
|}
+
| Simplifies watering dirt in the [[Garden Pot|garden pot]].
 
  −
====Other context tag changes====
  −
* Context tags are now case-insensitive.
  −
 
  −
===Inventory class===
  −
For C# mods, 1.6 adds a new <samp>Inventory</samp> class to manage a list of items. This is used for the <samp>Farmer.items</samp> and <samp>Chest.items</samp> fields. It implements <samp>IList&lt;Item&gt;</samp>, so most existing code should still work fine.
  −
 
  −
This has three main benefits:
  −
<ul>
  −
<li>It has methods to simplify many common operations. For example:
  −
{| class="wikitable"
   
|-
 
|-
! method
+
| <samp>Object</samp>
! effect
+
| <samp>GetBoundingBox()</samp><br /><samp>GetBoundingBoxAt(x, y)</samp>
 +
| Get the pixel collision area for the item placed in the world. These replace the former <samp>getBoundingBox(position)</samp> method.
 
|-
 
|-
| <code>HasAny()</code>
+
| <samp>Tool</samp>
| Get whether the inventory contains any items (ignoring empty slots).
+
| <samp>isScythe()</samp>
 +
| Equivalent to the previous <samp>MeleeWeapon</samp> method, to simplify common code and avoid needing to special-case <samp>MeleeWeapon</samp> items.
 
|-
 
|-
| <code>CountItemStacks()</code>
+
|rowspan="3"| <samp>Tree</samp>
| Get the number of item stacks in the inventory (ignoring empty slots).
+
| <samp>CheckForNewTexture()</samp>
 +
| Reset the tree's texture if it would change based on [[#Custom wild trees|its data]].
 
|-
 
|-
| <code>ContainsId(id)</code>
+
| <samp>GetMaxSizeHere</samp>
| Get whether the inventory contains any item with the given qualified or unqualified item ID.
+
| Get the maximum size the tree can grow in its current position (e.g. accounting for nearby trees blocking growth).
 
|-
 
|-
| <code>ContainsId(id, minCount)</code>
+
| <samp>IsGrowthBlockedByNearbyTree</samp>
| Get whether the inventory contains items with the given qualified or unqualified item ID, and their combined stack size is at least <samp>minCount</samp>.
+
| Get whether growth is blocked because it's too close to another fully-grown tree.
|-
+
|}
| <code>CountId(id)</code>
+
</li>
| Get the combined stack size of all items with the given qualified or unqualified item ID.
+
<li>Modularized <samp>Object.CheckForAction</samp> to simplify mod patches.</li>
|-
+
<li>Reworked <samp>Item.getOne()</samp> implementation to avoid common pitfalls. (This only affects mods with custom item classes, or which patch <samp>Item.getOne</samp> or <samp>Item._GetOneFrom</samp>.)</li>
| <code>GetById(id)</code>
+
<li>Fixed fruit trees forgetting the growth stage set in their constructor when they're updated overnight.</li>
| Get a list of items in the inventory with the given qualified or unqualified item ID.
  −
|-
  −
| <code>ReduceId(id, count)</code>
  −
| Remove the given number of items matching the given qualified or unqualified item ID. This reduces the stack size for matching items until a total of <samp>count</samp> have been removed, and clears any slots which reach a stack size of zero.
  −
|}</li>
  −
<li>Many common operations have been unified, so previously player-only methods can now be used with chests too.</li>
  −
<li>It has an internal index by item ID, so operations like <code>items.ContainsId("(O)128")</code> are much more efficient since they no longer iterate the list.</li>
   
</ul>
 
</ul>
   −
This replaces some previous methods:
+
===Other item changes===
 +
* Added per-object display names (''e.g.'' for custom flavored items). See the <samp>ObjectDisplayName</samp> [[Modding:Item queries#Item spawn fields|item spawn field]], or <samp>object.displayNameFormat</samp> in C#.
 +
* [[Ginger Island#Gem Birds|Item pedestals]] are now normal item, so you can spawn them using a mod like CJB Item Spawner to display items.
 +
* Added optional <samp>Condition</samp> [[Modding:Game state queries|game state query]] field to <samp>Data/SpecialOrders</samp>.
 +
* Item data changes:
 +
** The display name field now exists in English too for <samp>Data/Boots</samp>, <samp>Data/Bundles</samp>, <samp>Data/CookingRecipes</samp>, <samp>Data/CraftingRecipes</samp>, <samp>Data/Furniture</samp>, <samp>Data/Hats</samp>, and <samp>Data/Weapons</samp>.
 +
** The randomly spawned [[The Farm#Stone|stones]], [[The Farm#Wood|twigs]], and [[weeds]] have been formalized into ''litter''. They all now have object type <samp>Litter</samp>, [[Modding:Items#Categories|category]] -999 (<samp>StardewValley.Object.litterCategory</samp>), a relevant display name/description (like ''Gold Stone'' & ''Break apart to obtain gold ore'' instead of ''Stone'' & ''...''), a price of 0 (not sellable), and edibility of -300 (inedible). This also adds all mine ore nodes to <samp>Data/Objects</samp>, so the game no longer creates invalid items to show their sprite. (Doing so in 1.6 will now show an Error Item sprite instead.)
 +
** [[Honey]] items now have the <samp>honey_item</samp> context tag.
 +
** Shirts no longer have a dynamic numeric ID range; every valid shirt is now listed in [[#Custom shirts|<samp>Data/Shirts</samp>]].
 +
** You can now apply a custom buff ID when the item is eaten, via <samp>Data/Objects</samp>'s <samp>Buff</samp> field.
 +
** The type field in <samp>Data/Objects</samp> is no longer checked using substring matching (e.g. the game now uses <code>data.Type == "Fish"</code> instead of <code>typeAndCategory.Contains("Fish")</code>), which may impact mods which depended on that undocumented behavior.
 +
* Crop changes:
 +
** Paddy crops now recheck for nearby water each day, so they'll update if you add/remove a building with water or change the map layout.
 +
** In <samp>Data/Crops</samp>, each harvest option is now self-contained. For example, you can set <samp>HarvestMinStack</samp> without <samp>ExtraHarvestChance</samp>.
 +
* Fish changes:
 +
** <samp>Data/Fish</samp> is no longer translated, so there's only one <samp>Data/Fish.xnb</samp> field. Fish display names are now taken from <samp>Data/Objects</samp>.
 +
** Added a new field (index 13) in <samp>Data/Fish</samp>, which sets whether the fish can be selected for the first-catch tutorial.
 +
* Recipe changes in <samp>Data/CookingRecipes</samp> and <samp>Data/CraftingRecipes</samp>:
 +
** These assets no longer have language variants.
 +
** The display name now supports [[Modding:Tokenizable strings|tokenizable strings]].
 +
** The display name can now be left blank to get it from the first item in the output list.
 +
* Other item logic:
 +
** Missing recipes that should already be unlocked are now added to the player automatically on save load.
 +
** <samp>Data/Bundles</samp> is now loaded later, so content packs can edit it reliably.</samp>
 +
** Chests with <samp>fridge: true</samp> are now treated as mini-fridges for the cooking menu.
 +
** Gift boxes can now contain multiple items.
 +
** Fixed furniture drawn over sitting players if it has no front texture.
 +
** Fixed tool being upgraded by Clint not affected by recursive item search logic.
 +
** Fixed <samp>tool.getOne()</samp> not copying the tool name.
 +
** Fixed cooking menu constantly creating hovered item if the item/recipe names don't match.
 +
 
 +
==What's new for locations & weather==
 +
===Custom locations===
 +
{{/doc status|[[Modding:Location data]]|done=true}}
 +
 
 +
You can now add/edit locations by editing the revamped <samp>Data/Locations</samp> asset. This makes nearly everything in the location configurable — display name, default warp arrival tile, how the location is created, artifact spots / fish / forage / weeds, music, etc.
 +
 
 +
See [[Modding:Location data]] for docs on the new data format.
 +
 
 +
===Custom location contexts===
 +
{{/doc status|[[Modding:Location data]] or a new doc page|done=false}}
    +
====Vanilla contexts====
 +
* The game previously had two hardcoded location context enums: <samp>Default</samp> (for the valley) and <samp>Island</samp> (for [[Ginger Island]]). These have been replaced with data models which define the location context settings, loaded from the <samp>Data/LocationContexts</samp> asset.
 +
* [[The Desert|The desert]] is now part of a new <samp>Desert</samp> context (instead of <samp>Default</samp>). Some of the previously hardcoded desert logic (like always sunny weather) is now just part of the context data in <samp>Data/LocationContexts</samp>.
 +
 +
====Format====
 +
Custom contexts can be created by editing the new <samp>Data/LocationContexts</samp> asset, and setting the context name in the location's <samp>LocationContext</samp> [[Modding:Maps|map property]].
 +
 +
The data asset consists of a string → model lookup, where the key matches the <samp>Name</samp> field and the value is a model with these fields:
 +
 +
<dl style="margin-left: 2em;">
 +
<dt>Required fields:</dt>
 +
<dd>
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! game class
+
! field
! old code
+
! effect
! migration
   
|-
 
|-
|rowspan="6"| <samp>Farmer</samp>
+
| <samp>Name</samp>
| <code>getItemCount(id)</code><br /><code>GetTallyOfObject(id)</code><br /><code>GetTallyOfObject(id, isBigCraftable)</code>
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for the location context.
| Use <code>items.CountId(id)</code>.
+
|}
|-
+
</dd>
| <code>hasItemInInventory(id, count)</code><br /><code>hasItemInInventoryNamed(name)</code><br /><code>hasItemWithNameThatContains(name)</code>
+
 
| Use <code>Items.ContainsId(id, count)</code>.
+
<dt>Player actions:</dt>
|-
+
<dd>
| <code>hasItemInList(list, id, count)</code>
+
{| class="wikitable"
| Use <code>list.ContainsId(id, count)</code>.
+
|-
|-
+
! field
| <code>areAllItemsNull()</code>
+
! effect
| Use <code>!items.HasAny()</code>.
   
|-
 
|-
| <code>numberOfItemsInInventory()</code>
+
| <samp>AllowRainTotem</samp>
| Use <code>items.CountItemStacks()</code> to count all items, or <code>Items.Count(p => p is Object)</code> to match this method's actual behavior.
+
| ''(Optional)'' Whether a [[Rain Totem|rain totem]] can be used to force rain in this context tomorrow. If false, using a rain totem here will show a "''this item can't be used here''" message instead.
 
|-
 
|-
| <code>consumeObject(id, count)</code><br /><code>removeItemsFromInventory(id, count)</code>
+
| <samp>RainTotemAffectsContext</samp>
| Use <code>items.ReduceId(id, count)</code>.
+
| ''(Optional)'' If set, using a rain totem here will change the weather in the given context ID. For example, rain totems in the desert change weather in the valley.
 
|-
 
|-
|rowspan="2"| <samp>Object</samp>
+
| <samp>MaxPassOutCost</samp>
| <code>ConsumeInventoryItem(player, id, count)</code>
+
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context, the maximum amount of [[gold]] lost. If omitted or set to <samp>-1</samp>, uses the same value as the <samp>Default</samp> context ({{price|1000}} by default).
| This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be <code>(obj.autoLoadChest?.items ?? player.items).ReduceId(id, count)</code>.
   
|-
 
|-
| <code>GetTallyOfObject(player, id)</code>
+
| <samp>PassOutMail</samp>
| This was somewhat specialized and shouldn't be called by mod code, but the equivalent would be <code>(obj.autoLoadChest?.items ?? player.items).CountId(id)</code>.
+
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context, the possible [[Modding:Mail data|letter IDs]] to add to their mailbox (if they haven't received it before). If multiple letters are valid, one will be chosen randomly (unless one specifies <samp>SkipRandomSelection</samp>).
|}
  −
 
  −
It implements a new <samp>IInventory</samp> interface, which lets mods pass their own implementations to code which works on inventories.
  −
 
  −
===Field changes in furniture data===
  −
There are a few changes in [[Modding:Items#Furniture|<samp>Data/furniture</samp>]]:
  −
<ul>
  −
<li>Field index 6 is now placement restrictions and field index 7 is now display name. The display name field is no longer omitted in English.</li>
  −
<li>Added new fields:
      +
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! index
   
! field
 
! field
 
! effect
 
! effect
 
|-
 
|-
| 8
+
| <samp>Id</samp>
| sprite index
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry in the list.
| The sprite index within the spritesheet texture to draw.
   
|-
 
|-
| 9
+
| <samp>Mail</samp>
| texture
+
| The [[Modding:Mail data|letter ID]] to add.
| ''(Optional)'' The asset name of the texture to draw. Defaults to <samp>TileSheets/furniture</samp>.
+
 
 +
The game will look for an existing letter ID in <samp>Data/mail</samp> in this order (where {{t|billed}} is <samp>Billed</samp> if they lost [[gold]] or <samp>NotBilled</samp> otherwise, and {{t|gender}} is <samp>Female</samp> or <samp>Male</samp>):
 +
* <samp>{{t|letter id}}_{{t|billed}}_{{t|gender}}</samp>
 +
* <samp>{{t|letter id}}_{{t|billed}}</samp>
 +
* <samp>{{t|letter id}}</samp>
 +
 
 +
If no match is found in <samp>Data/mail</samp>, the game will send <samp>passedOut2</samp> instead.
 +
 
 +
If the mail ID starts with <samp>passedOut</samp>, <samp>{0}</samp> in the letter text will be replaced with the gold amount lost, and it won't appear in the [[collections]] page.
 
|-
 
|-
| 10
+
| <samp>MaxPassOutCost</samp>
| off limits for random sale
+
| ''(Optional)'' The maximum amount of [[gold]] lost. This is applied after the context's <samp>MaxPassOutCost</samp> (i.e. the context's value is used to calculate the random amount, then this field caps the result). Defaults to unlimited.
| ''(Optional)'' Whether to prevent this furniture from appearing in randomly generated shop stocks and the furniture catalogue. Default false.
   
|-
 
|-
| 11
+
| <samp>Condition</samp>
| context tags
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always true.
| ''(Optional)'' A space-delimited list of [[Modding:Items#Context tags|context tags]] which apply to this furniture. Default none.
+
|-
|}</li>
+
| <samp>SkipRandomSelection</samp>
</ul>
+
| ''(Optional)'' If true, send this mail if the <samp>Condition</samp> matches instead of choosing a random valid mail. Default false.
 +
|}
 +
|-
 +
| <samp>PassOutLocations</samp>
 +
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context ''and'' they started the day in a different location context, the locations where they'll wake up. (If the player started the day in the same context, they'll wake up in the last bed they slept in instead.)
   −
===Other item changes for C# mods===
+
If the selected location doesn't contain a bed and doesn't have the [[#New map properties|<samp>AllowWakeUpWithoutBed</samp> map property]], the player will wake up in the farmhouse instead.
* Placed object changes:
  −
** Every placed object now has a <samp>Location</samp> property set to the location which contains it. This removes location parameters from many object methods.
  −
** Setting an object's tile position through <samp>obj.TileLocation</samp> now recalculcates its collision box automatically. (Setting it through the <samp>tileLocation</samp> net field directly won't though.)
  −
** The <samp>obj.IsScarecrow()</samp> and <samp>GetScarecrowRadius()</samp> methods now work for non-bigcraftable objects too.
  −
* Clothing changes:
  −
** <samp>Clothes.clothesType</samp> is now an enum field.
  −
** Clothing is no longer gender-specific. This renames <samp>indexInTileSheetMale</samp> to <samp>indexInTileSheet</samp>, obsoletes <samp>indexInTileSheetFemale</samp>, and converts gender-variant clothing into regular items.
  −
** Removed unused <samp>ClothesType.ACCESSORY</samp> value.
  −
** <samp>Farmer.pants</samp> and <samp>Farmer.shirt</samp> now store the item ID instead of the sprite index.
  −
** In <samp>Data/TailoringRecipes</samp>, added a <samp>CraftingIdFeminine</samp> field which overrides <samp>CraftingId</samp> for female characters.
  −
* Crop changes:
  −
** Added <samp>Game1.cropData</samp> to read crop info without constantly reloading the <samp>Data/Crops</samp> asset.
  −
** Removed most crop fields which only mirror the data (like <samp>harvestMethod</samp> or <samp>seasonsToGrowIn</samp>). Mods can get the info through <samp>crop.GetData()</samp> instead.
  −
** Partly de-hardcoded fertilizer logic. Almost all fertilizer logic is now centralized into a new patchable set of <samp>HoeDirt</samp> methods (see list below). The only fertilizer logic that's still embedded elsewhere is the interaction errors in <samp>Utility.tryToPlaceItem</samp>.
  −
** HoeDirt.fertilizer.Value is now set to <samp>null</samp> when there is no fertilizer. Both qualified and unqualified IDs should be expected.
  −
** Removed <samp>crop.InferSeedIndex()</samp>. This was used to support old crops, which are now fixed by a save migration instead.
  −
* Tool changes:
  −
** Fixed various logic not handling custom tool upgrade levels.
  −
<ul>
  −
<li>Other item logic:<ul>
  −
<li>Simplified the constructors for many item types, particularly <samp>Object</samp>.</li>
  −
<li>[[Honey]] items now have their <samp>preserve</samp> field set to a new <samp>Honey</samp> type (instead of null).</li>
  −
<li>The <samp>Object.performObjectDropInAction</samp> method now applies the <samp>probe</samp> argument much more consistently. This only affects method calls with <samp>probe: true</samp>.</li>
  −
<li>The <samp>Item.salePrice()</samp> method now has option to get the price without [[Multiplayer#Profit margins|profit margins]].</li>
  −
<li>Added new fields & methods:
      +
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! type
+
! field
! field/method
   
! effect
 
! effect
 
|-
 
|-
| rowspan="2"| <samp>Crop</samp>
+
| <samp>Id</samp>
| <samp>GetHarvestMethod()</samp>
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry in the list.
| Get the method used to harvest the crop (one of <samp>HarvestMethod.Grab</samp> or <samp>HarvestMethod.Scythe</samp>).
   
|-
 
|-
| <samp>IsInSeason(location)</samp>
+
| <samp>Location</samp>
| Whether the crop can grow in the location's current season (or true if crops ignore seasons in the location, like the [[greenhouse]]).
+
| The internal location name.
 
|-
 
|-
| rowspan="7"| <samp>HoeDirt</samp>
+
| <samp>Position</samp>
| <samp>HasFertilizer()</samp>
+
| The ''default'' tile position within the location, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. If the location has any bed furniture, they'll be placed in the first bed found instead.
| Get whether the dirt has any fertilizer applied.
   
|-
 
|-
| <samp>CanApplyFertilizer(itemId)</samp>
+
| <samp>Condition</samp>
| Get whether a player can apply the given fertilizer to this dirt.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always applied.
 +
|}
 +
 
 +
If no locations are specified or none match, the player will wake up in their bed at home.
 +
|-
 +
| <samp>ReviveLocations</samp>
 +
| ''(Optional)'' If the player just got knocked out in combat, the location names where they'll wake up.
 +
 
 +
This consists of a list of models with these fields:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>CheckApplyFertilizerRules(itemId)</samp>
+
! field
| Get whether a player can apply the given fertilizer to this dirt, and the reason they can't if applicable.
+
! effect
 
|-
 
|-
| <samp>GetFertilizerSpeedBoost()</samp>
+
| <samp>Id</samp>
| Get the crop growth speed boost from fertilizers applied to this dirt.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry in the list.
 
|-
 
|-
| <samp>GetFertilizerWaterRetentionChance()</samp>
+
| <samp>Location</samp>
| Get the water retention chance from fertilizers applied to this dirt, as a value between 0 (no change) and 1 (100% chance of staying watered).
+
| The internal location name.
 
|-
 
|-
| <samp>GetFertilizerQualityBoostLevel()</samp>
+
| <samp>Position</samp>
| Get the quality boost level from fertilizers applied to this dirt, which influences the chance of producing a higher-quality crop.
+
| The tile position within the location, specified as an object with <samp>X</samp> and <samp>Y</samp> fields.
 
|-
 
|-
| <samp>GetFertilizerSourceRect()</samp>
+
| <samp>Condition</samp>
| Get the pixel area within the dirt spritesheet to draw for any fertilizer applied to this dirt.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always applied.
 +
|}
 +
 
 +
If the selected location has a standard [[Modding:Event data|event]] with the exact key <samp>PlayerKilled</samp> (with no <samp>/</samp> or preconditions in the key), that event will play when the player wakes up and the game will apply the lost items or [[gold]] logic. The game won't track this event, so it'll repeat each time the player is revived. If there's no such event, the player will wake up without an event, and no items or gold will be lost.
 +
 
 +
If no locations are specified or none match, the player will wake up at [[Harvey's Clinic|Harvey's clinic]].
 +
|}
 +
</dd>
   −
(This method existed before, but no longer requires the fertilizer ID argument.)
+
<dt>Season:</dt>
 +
<dd>
 +
{| class="wikitable"
 
|-
 
|-
|rowspan="5"| <samp>Item</samp>
+
! field
| <samp>IsRecipe</samp><br /><samp>Quality</samp><br /><samp>Stack</samp></samp><br /><samp>sellToStorePrice(…)</samp>
+
! effect
| Equivalent to the previous <samp>Object</samp> fields/methods, to simplify common code and avoid needing to special-case <samp>Object</samp> items.
   
|-
 
|-
| <samp>appliesProfitMargins()</samp>
+
| <samp>SeasonOverride</samp>
| Get whether this item should apply [[Multiplayer#Profit margins|profit margins]] to shop prices.
+
| ''(Optional)'' The season which is always active for locations within this context (one of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>). For example, setting <samp>summer</samp> will make it always [[summer]] there regardless of the calendar season. If not set, the calendar season applies.
 +
|}
 +
</dd>
 +
 
 +
<dt>Weather:</dt>
 +
<dd>
 +
{| class="wikitable"
 
|-
 
|-
| <samp>CanBeLostOnDeath()</samp>
+
! field
| Get whether this item can be lost when the player dies, so it can be recovered from the [[Adventurer's Guild#Item Recovery Service|item recovery service]].
+
! effect
|-
  −
| <samp>HasTypeId(id)</samp><br /><samp>HasTypeObject()</samp><br /><samp>HasTypeBigCraftable()</samp>
  −
| Get whether the item has the given [[#Custom items|type definition ID]]. These are null-safe and double as a null check:
  −
<syntaxhighlight lang="c#">
  −
if (item.HasTypeId(ItemRegistry.type_object))
  −
{
  −
    // item is non-null and has type (O)
  −
}
  −
</syntaxhighlight>
  −
<samp>HasTypeObject()</samp> and <samp>HasTypeBigCraftable()</samp> are shortcuts for passing <samp>ItemRegistry.type_object</samp> and <samp>ItemRegistry.type_bigCraftable</samp> respectively.
   
|-
 
|-
| <samp>TryGetTempData</samp><br /><samp>SetTempData</samp>
+
| <samp>WeatherConditions</samp>
| Get or set temporary item info that's not synchronized in multiplayer or written to the save file.
+
| ''(Optional)'' The weather logic to apply for locations in this context (ignored if <samp>CopyWeatherFromLocation</samp> is set). Defaults to always sunny. If multiple are specified, the first matching weather is applied.
   −
For example, the game uses this to pass spawn options to the fishing minigame:
+
This consists of a list of models with these fields:
<syntaxhighlight lang="c#">
+
{| class="wikitable"
if (spawn.IsBossFish)
  −
    fish.SetTempData(nameof(spawn.IsBossFish), true);
  −
 
  −
...
  −
 
  −
fish.TryGetTempData(nameof(SpawnFishData.IsBossFish), out bool bossFish);
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>FishingRod</samp>
+
! field
| <samp>CanUseBait()</samp><br /><samp>CanUseTackle()</samp><br /><samp>GetBait()</samp><br /><samp>GetTackle()</samp><br /><samp>HasMagicBait()</samp><br /><samp>HasCuriosityLure()</samp>
+
! effect
| Simplifies working with the fishing rod's [[bait]] and [[tackle]].
   
|-
 
|-
| <samp>Furniture</samp>
+
| <samp>Id</samp>
| <samp>SetPlacement</samp><br /><samp>SetHeldObject</samp>
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry in the list.
| Set the furniture's position and rotation (<samp>SetPlacement</samp>) or held object (<samp>SetHeldObject</samp>). The latter will initialize the held object's tile position to match the furniture instance.
  −
 
  −
These are used by the game to initialize furniture in one go. For example:
  −
<syntaxhighlight lang="c#">
  −
// oak table holding decorative bowl
  −
Furniture table = ItemRegistry
  −
    .Create<Furniture>("(F)1120")
  −
    .SetPlacement(5, 4, 0)
  −
    .SetHeldObject(ItemRegistry.Create<Furniture>("(F)1364"));
  −
</syntaxhighlight>
   
|-
 
|-
|rowspan="2"| <samp>FruitTree</samp>
+
| <samp>Weather</samp>
| <samp>GetQuality()</samp>
+
| The [[#Custom weather|weather ID]] to set.
| Get the quality of fruit currently being produced by the fruit tree.
   
|-
 
|-
| <samp>TryAddFruit()</samp>
+
| <samp>Condition</samp>
| Add a fruit item to the tree based on [[#Custom fruit trees|its data]].
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether to apply the weather. Defaults to always applied.
 +
|}
 
|-
 
|-
| <samp>IndoorPot</samp>
+
| <samp>CopyWeatherFromLocation</samp>
| <samp>Water()</samp>
+
| ''(Optional)'' The <samp>Name</samp> (i.e. unique ID) of the location context from which to inherit weather.
| Simplifies watering dirt in the [[Garden Pot|garden pot]].
+
|}
 +
 
 +
If a [[#Custom passive festivals|passive festival]] is active in any location within this context, the weather is sunny for the entire context regardless of these fields.
 +
 
 +
</dd>
 +
 
 +
<dt>Music:</dt>
 +
<dd>
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>DefaultMusic</samp>
 +
| ''(Optional)'' The [[#Custom audio|cue ID]] for the music to play when the player is in the location, unless overridden by a <samp>Music</samp> map property. Despite the name, this has a higher priority than the seasonal music fields below. Ignored if omitted.
 +
|-
 +
| <samp>DefaultMusicCondition</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which returns whether the <samp>DefaultMusic</samp> field should be applied (if more specific music isn't playing). Defaults to always true.
 +
|-
 +
| <samp>DefaultMusicDelayOneScreen</samp>
 +
| ''(Optional)'' When the player warps and the music changes, whether to silence the music and play the ambience (if any) until the next warp (similar to the default valley locations). Default false.
 +
|-
 +
| <samp>Music</samp>
 +
| ''(Optional)'' A list of [[#Custom audio|cue IDs]] to play before noon in this location unless it's raining, there's a <samp>Music</samp> map property, or the context has a <samp>DefaultMusic</samp> value. If multiple values are specified, the game will play one per day in sequence.
 +
 
 +
This consists of a list of models with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 
|-
 
|-
| <samp>Object</samp>
+
| <samp>Id</samp>
| <samp>GetBoundingBox()</samp><br /><samp>GetBoundingBoxAt(x, y)</samp>
+
| ''(Optional)'' A [[Modding:Common data field types#Unique string ID|unique string ID]] which identifies this entry within the list. Defaults to the <samp>Track</samp> value.
| Get the pixel collision area for the item placed in the world. These replace the former <samp>getBoundingBox(position)</samp> method.
   
|-
 
|-
| <samp>Tool</samp>
+
| <samp>Track</samp>
| <samp>isScythe()</samp>
+
| The [[Modding:Migrate to Stardew Valley 1.6#Custom audio|audio track ID]] to play.
| Equivalent to the previous <samp>MeleeWeapon</samp> method, to simplify common code and avoid needing to special-case <samp>MeleeWeapon</samp> items.
   
|-
 
|-
|rowspan="3"| <samp>Tree</samp>
+
| <samp>Condition</samp>
| <samp>CheckForNewTexture()</samp>
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry applies. Default true.
| Reset the tree's texture if it would change based on [[#Custom wild trees|its data]].
+
|}
 
|-
 
|-
| <samp>GetMaxSizeHere</samp>
+
| <samp>DayAmbience</samp><br /><samp>NightAmbience</samp>
| Get the maximum size the tree can grow in its current position (e.g. accounting for nearby trees blocking growth).
+
| ''(Optional)'' The [[#Custom audio|cue ID]] for the background ambience to play when there's no music active, depending on the [[Day Cycle|time of day]]. Both default to none.
 
|-
 
|-
| <samp>IsGrowthBlockedByNearbyTree</samp>
+
| <samp>PlayRandomAmbientSounds</samp>
| Get whether growth is blocked because it's too close to another fully-grown tree.
+
| ''(Optional)'' Whether to play random outdoor ambience sounds depending on factors like the season and time of day (e.g. birds, crickets, and mysterious groan sounds in the rain). This is unrelated to the <samp>DayAmbience</samp> and <samp>NightAmbience</samp> fields. Default true.
 
|}
 
|}
</li>
+
</dd>
<li>Modularized <samp>Object.CheckForAction</samp> to simplify mod patches.</li>
  −
<li>Reworked <samp>Item.getOne()</samp> implementation to avoid common pitfalls. (This only affects mods with custom item classes, or which patch <samp>Item.getOne</samp> or <samp>Item._GetOneFrom</samp>.)</li>
  −
<li>Fixed fruit trees forgetting the growth stage set in their constructor when they're updated overnight.</li>
  −
</ul>
     −
===Other item changes===
+
<dt>Advanced:</dt>
* Added per-object display names (''e.g.'' for custom flavored items). See the <samp>ObjectDisplayName</samp> [[#Item spawn fields|item spawn field]], or <samp>object.displayNameFormat</samp> in C#.
+
<dd>
* [[Ginger Island#Gem Birds|Item pedestals]] are now normal item, so you can spawn them using a mod like CJB Item Spawner to display items.
+
{| class="wikitable"
* Added optional <samp>Condition</samp> [[Modding:Game state queries|game state query]] field to <samp>Data/SpecialOrders</samp>.
+
|-
* Item data changes:
+
! field
** The display name field now exists in English too for <samp>Data/Boots</samp>, <samp>Data/Bundles</samp>, <samp>Data/CookingRecipes</samp>, <samp>Data/CraftingRecipes</samp>, <samp>Data/Furniture</samp>, <samp>Data/Hats</samp>, and <samp>Data/Weapons</samp>.
+
! effect
** The randomly spawned [[The Farm#Stone|stones]], [[The Farm#Wood|twigs]], and [[weeds]] have been formalized into ''litter''. They all now have object type <samp>Litter</samp>, [[Modding:Items#Categories|category]] -999 (<samp>Game1.litterCategory</samp>), a relevant display name/description (like ''Gold Stone'' & ''Break apart to obtain gold ore'' instead of ''Stone'' & ''...''), a price of 0 (not sellable), and edibility of -300 (inedible). This also adds all mine ore nodes to <samp>Data/Objects</samp>, so the game no longer creates invalid items to show their sprite. (Doing so in 1.6 will now show an Error Item sprite instead.)
+
|-
** [[Honey]] items now have the <samp>honey_item</samp> context tag.
+
| <samp>CustomFields</samp>
** Shirts no longer have a dynamic numeric ID range; every valid shirt is now listed in [[#Custom shirts|<samp>Data/Shirts</samp>]].
+
| The [[#Custom data fields|custom fields]] for this entry.
** You can now apply a custom buff ID when the item is eaten, via <samp>Data/Objects</samp>'s <samp>Buff</samp> field.
+
|}
** The type field in <samp>Data/Objects</samp> is no longer checked using substring matching (e.g. the game now uses <code>data.Type == "Fish"</code> instead of <code>typeAndCategory.Contains("Fish")</code>), which may impact mods which depended on that undocumented behavior.
+
</dd>
* Crop changes:
+
</dl>
** Paddy crops now recheck for nearby water each day, so they'll update if you add/remove a building with water or change the map layout.
  −
** In <samp>Data/Crops</samp>, each harvest option is now self-contained. For example, you can set <samp>HarvestMinStack</samp> without <samp>ExtraHarvestChance</samp>.
  −
* Fish changes:
  −
** <samp>Data/Fish</samp> is no longer translated, so there's only one <samp>Data/Fish.xnb</samp> field. Fish display names are now taken from <samp>Data/Objects</samp>.
  −
** Added a new field (index 13) in <samp>Data/Fish</samp>, which sets whether the fish can be selected for the first-catch tutorial.
  −
* Recipe changes in <samp>Data/CookingRecipes</samp> and <samp>Data/CraftingRecipes</samp>:
  −
** These assets no longer have language variants.
  −
** The display name now supports [[Modding:Tokenizable strings|tokenizable strings]].
  −
** The display name can now be left blank to get it from the first item in the output list.
  −
* Other item logic:
  −
** Missing recipes that should already be unlocked are now added to the player automatically on save load.
  −
** <samp>Data/Bundles</samp> is now loaded later, so content packs can edit it reliably.</samp>
  −
** Gift boxes can now contain multiple items.
  −
** Fixed furniture drawn over sitting players if it has no front texture.
  −
** Fixed tool being upgraded by Clint not affected by recursive item search logic.
  −
** Fixed <samp>tool.getOne()</samp> not copying the tool name.
  −
** Fixed cooking menu constantly creating hovered item if the item/recipe names don't match.
     −
==What's new for locations & weather==
+
===Custom garbage cans===
===Custom locations===
+
{{/doc status|a new doc page|done=false}}
You can now add/edit locations by editing the revamped <samp>Data/Locations</samp> asset. This makes nearly everything in the location configurable — display name, default warp arrival tile, how the location is created, artifact spots / fish / forage / weeds, music, etc.
  −
 
  −
See [[Modding:Location data]] for docs on the new data format.
  −
 
  −
===Custom location contexts===
  −
====Vanilla contexts====
  −
* The game previously had two hardcoded location context enums: <samp>Default</samp> (for the valley) and <samp>Island</samp> (for [[Ginger Island]]). These have been replaced with data models which define the location context settings, loaded from the <samp>Data/LocationContexts</samp> asset.
  −
* [[The Desert|The desert]] is now part of a new <samp>Desert</samp> context (instead of <samp>Default</samp>). Some of the previously hardcoded desert logic (like always sunny weather) is now just part of the context data in <samp>Data/LocationContexts</samp>.
      
====Format====
 
====Format====
Custom contexts can be created by editing the new <samp>Data/LocationContexts</samp> asset, and setting the context name in the location's <samp>LocationContext</samp> [[Modding:Maps|map property]].
+
You can now add or edit [[Garbage Can|garbage cans]] on any map by editing the new <samp>Data/GarbageCans</samp> asset (see examples below).
   −
The data asset consists of a string → model lookup, where the key matches the <samp>Name</samp> field and the value is a model with these fields:
+
The asset consists of a data model with these fields:
   −
<dl style="margin-left: 2em;">
  −
<dt>Required fields:</dt>
  −
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 2,888: Line 2,874:  
! effect
 
! effect
 
|-
 
|-
| <samp>Name</samp>
+
| <samp>DefaultBaseChance</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the location context.
+
| The probability that an item will be found when searching garbage cans, as a value between 0 (never) and 1 (always). If the probability check fails, only items that set <samp>IgnoreBaseChance</samp> can spawn. This can be overridden by the per-garbage-can <samp>BaseChance</samp> field. Default 0.2.
|}
+
|-
</dd>
+
| <samp>BeforeAll</samp><br /><samp>AfterAll</samp>
 +
| The items to prepend (<samp>BeforeAll</samp>) or append (<samp>AfterAll</samp>) to the <samp>GarbageCans</samp> → <samp>Items</samp> field for all garbage cans. These work exactly like the items in that field (e.g. subject to the garbage can's base chance).
 +
|-
 +
| <samp>GarbageCans</samp>
 +
| The data for individual garbage cans. This consists of a string → model lookup with these fields:
   −
<dt>Player actions:</dt>
  −
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 2,900: Line 2,888:  
! effect
 
! effect
 
|-
 
|-
| <samp>PlantableLocations</samp>
+
| ''entry key''
| ''(Optional)'' The internal names of the locations where crops can be planted and grown, unless overridden by planting rules in their data.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this garbage can.
 
|-
 
|-
| <samp>AllowRainTotem</samp>
+
| <samp>BaseChance</samp>
| ''(Optional)'' Whether a [[Rain Totem|rain totem]] can be used to force rain in this context tomorrow. If false, using a rain totem here will show a "''this item can't be used here''" message instead.
+
| ''(Optional)'' If set, overrides the root <samp>DefaultBaseChance</samp> field for this garbage can. Defaults to <samp>DefaultBaseChance</samp>.
 
|-
 
|-
| <samp>RainTotemAffectsContext</samp>
+
| <samp>Items</samp>
| ''(Optional)'' If set, using a rain totem here will change the weather in the given context ID. For example, rain totems in the desert change weather in the valley.
+
| ''(Optional)'' The items to try spawning when the player searches the garbage can. The first matching item in <samp>BeforeAll</samp> + <samp>Items</samp> + <samp>AfterAll</samp> will be spawned, and any further items will be ignored. Defaults to none.
|-
  −
| <samp>MaxPassOutCost</samp>
  −
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context, the maximum amount of [[gold]] lost. If omitted or set to <samp>-1</samp>, uses the same value as the <samp>Default</samp> context ({{price|1000}} by default).
  −
|-
  −
| <samp>PassOutMail</samp>
  −
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context, the possible [[Modding:Mail data|letter IDs]] to add to their mailbox (if they haven't received it before). If multiple letters are valid, one will be chosen randomly (unless one specifies <samp>SkipRandomSelection</samp>).
      
This consists of a list of models with these fields:
 
This consists of a list of models with these fields:
Line 2,921: Line 2,903:  
! effect
 
! effect
 
|-
 
|-
| <samp>Mail</samp>
+
| ''common fields''
| The [[Modding:Mail data|letter ID]] to add.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported by garbage cans.
   −
The game will look for an existing letter ID in <samp>Data/mail</samp> in this order (where {{t|billed}} is <samp>Billed</samp> if they lost [[gold]] or <samp>NotBilled</samp> otherwise, and {{t|gender}} is <samp>Female</samp> or <samp>Male</samp>):
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
* <samp>{{t|letter id}}_{{t|billed}}_{{t|gender}}</samp>
+
|-
* <samp>{{t|letter id}}_{{t|billed}}</samp>
+
| <samp>IgnoreBaseChance</samp>
* <samp>{{t|letter id}}</samp>
+
| ''(Optional)'' Whether this item can spawn even if the <samp>BaseChance</samp> probability check didn't pass. Default false.
 
+
|-
If no match is found in <samp>Data/mail</samp>, the game will send <samp>passedOut2</samp> instead.
+
| <samp>IsMegaSuccess</samp>
 
+
| ''(Optional)'' Whether to treat this item as a 'mega success' if it's selected, which plays a special <samp>crit</samp> sound and bigger animation. Default false.
If the mail ID starts with <samp>passedOut</samp>, <samp>{0}</samp> in the letter text will be replaced with the gold amount lost, and it won't appear in the [[collections]] page.
   
|-
 
|-
| <samp>MaxPassOutCost</samp>
+
| <samp>IsDoubleMegaSuccess</samp>
| ''(Optional)'' The maximum amount of [[gold]] lost. This is applied after the context's <samp>MaxPassOutCost</samp> (i.e. the context's value is used to calculate the random amount, then this field caps the result). Defaults to unlimited.
+
| ''(Optional)'' Whether to treat this item as an 'double mega success' if it's selected, which plays an explosion sound and dramatic animation. Default false.
 
|-
 
|-
| <samp>Condition</samp>
+
| <samp>AddToInventoryDirectly</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always true.
+
| ''(Optional)'' Whether to add the item to the player's inventory directly, opening an item grab menu if they don't have room in their inventory. If false, the item will be dropped on the ground next to the garbage can instead. Default false.
 
|-
 
|-
| <samp>SkipRandomSelection</samp>
+
| <samp>CreateMultipleDebris</samp>
| ''(Optional)'' If true, send this mail if the <samp>Condition</samp> matches instead of choosing a random valid mail. Default false.
+
| ''(Optional)'' Whether to split the spawned item into multiple stacks which each have a stack size of one. This has no effect if <samp>AddToInventoryDirectly</samp> is enabled. Default false.
 +
|}
 
|}
 
|}
 +
 +
If the garbage can being searched doesn't have its own entry under <samp>GarbageCans</samp>, the game will just use the <samp>BeforeAll</samp> and <samp>AfterAll</samp> fields.
 
|-
 
|-
| <samp>PassOutLocations</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' When the player passes out (due to [[energy|exhaustion]] or at 2am) in this context ''and'' they started the day in a different location context, the locations where they'll wake up. (If the player started the day in the same context, they'll wake up in the last bed they slept in instead.)
+
| The [[#Custom data fields|custom fields]] for this entry.
 +
|}
 +
 
 +
====Example new garbage can====
 +
You can add garbage cans using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. For example, this content pack adds a new garbage can entry with the ID <samp>Example.ModId_Carpenter</samp>:
   −
If the selected location doesn't contain a bed and doesn't have the [[#New map properties|<samp>AllowWakeUpWithoutBed</samp> map property]], the player will wake up in the farmhouse instead.
+
{{#tag:syntaxhighlight|<nowiki>
 +
{
 +
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 +
    "Changes": [
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/GarbageCans",
 +
            "TargetField": [ "GarbageCans" ],
 +
            "Entries": {
 +
                "{{ModId}}_Carpenter": {
 +
                    "Items": [
 +
                        // 25% chance of pufferfish
 +
                        {
 +
                            "ID": "{{ModId}}_Pufferfish",
 +
                            "Condition": "RANDOM 0.25",
 +
                            "ItemId": "(O)128"
 +
                        },
   −
This consists of a list of models with these fields:
+
                        // else guaranteed random House Plant item
{| class="wikitable"
+
                        {
|-
+
                            "ID": "{{ModId}}_RandomHousePlant",
! field
+
                            "ItemID": "RANDOM_ITEMS (F) 1376 1390"
! effect
+
                        }
|-
+
                    ]
| <samp>Location</samp>
+
                }
| The internal location name.
+
            }
|-
+
        }
| <samp>Position</samp>
+
    ]
| The ''default'' tile position within the location, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. If the location has any bed furniture, they'll be placed in the first bed found instead.
+
}</nowiki>|lang=javascript}}
|-
  −
| <samp>Condition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always applied.
  −
|}
     −
If no locations are specified or none match, the player will wake up in their bed at home.
+
Then you'd place an <code>Action: Garbage Example.ModId_Carpenter</code> [[Modding:Maps|map tile property]] to mark a tile as a garbage can using this data.
|-
  −
| <samp>ReviveLocations</samp>
  −
| ''(Optional)'' If the player just got knocked out in combat, the location names where they'll wake up.
     −
This consists of a list of models with these fields:
+
====Example change for existing garbage can====
{| class="wikitable"
+
You can edit an existing garbage cans using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. For example, this content pack adds pufferfish to the Saloon garbage can, and moves it above the dish of the day.
|-
+
 
! field
+
Note that this uses <samp>TargetField</samp> to 'move into' the item list for the saloon, and then treat those items as the entry list being edited. Specifying an ID which isn't in the list will add a new entry, just like when editing a regular list asset.
! effect
  −
|-
  −
| <samp>Location</samp>
  −
| The internal location name.
  −
|-
  −
| <samp>Position</samp>
  −
| The tile position within the location, specified as an object with <samp>X</samp> and <samp>Y</samp> fields.
  −
|-
  −
| <samp>Condition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry is active. Defaults to always applied.
  −
|}
     −
If the selected location has a standard [[Modding:Event data|event]] with the exact key <samp>PlayerKilled</samp> (with no <samp>/</samp> or preconditions in the key), that event will play when the player wakes up and the game will apply the lost items or [[gold]] logic. The game won't track this event, so it'll repeat each time the player is revived. If there's no such event, the player will wake up without an event, and no items or gold will be lost.
+
{{#tag:syntaxhighlight|<nowiki>
 +
{
 +
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 +
    "Changes": [
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/GarbageCans",
 +
            "TargetField": [ "GarbageCans", "Saloon", "Items" ],
 +
            "Entries": {
 +
                // 25% chance of pufferfish
 +
               
 +
                "{{ModId}}_Pufferfish":{
 +
                    "ID": "{{ModId}}_Pufferfish",
 +
                    "Condition": "RANDOM 0.25",
 +
                    "ItemId": "(O)128"
 +
                }
 +
            },
 +
            "MoveEntries": [
 +
                { "ID": "{{ModId}}_Pufferfish", "BeforeId": "Base_DishOfTheDay" }
 +
            ]
 +
        }
 +
    ]
 +
}</nowiki>|lang=javascript}}
   −
If no locations are specified or none match, the player will wake up at [[Harvey's Clinic|Harvey's clinic]].
+
====Changes for C# mods====
|}
+
Previously garbage cans were tracked by <samp>Town.garbageChecked</samp>, an array of boolean fields. That approach doesn't work in Stardew Valley 1.6, since we're no longer limited to a specific set of garbage cans in the town map. This has been replaced by <samp>Game1.netWorldState.Value.CheckedGarbage</samp>, which is a hash set of garbage can IDs.
</dd>
     −
<dt>Season:</dt>
+
To migrate code:
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! action
! effect
+
! code in 1.5.6
 +
! code in 1.6
 +
|-
 +
| check if a garbage can was searched
 +
| <syntaxhighlight lang="js">
 +
Town town = (Town)Game1.getLocationFromName("Town");
 +
if (town.garbageChecked[5])
 +
  ...
 +
</syntaxhighlight>
 +
| <syntaxhighlight lang="js">
 +
if (Game1.netWorldState.Value.CheckedGarbage.Contains("Saloon"))
 +
  ...
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>SeasonOverride</samp>
+
| mark a garbage can searched
| ''(Optional)'' The season which is always active for locations within this context (one of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>). For example, setting <samp>summer</samp> will make it always [[summer]] there regardless of the calendar season. If not set, the calendar season applies.
+
| <syntaxhighlight lang="js">
 +
Town town = (Town)Game1.getLocationFromName("Town");
 +
town.garbageChecked[5] = true;
 +
</syntaxhighlight>
 +
| <syntaxhighlight lang="js">
 +
Game1.netWorldState.Value.CheckedGarbage.Add("Saloon");
 +
</syntaxhighlight>
 
|}
 
|}
</dd>
     −
<dt>Weather:</dt>
+
To migrate former vanilla trash can IDs:
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! position
! effect
+
! ID in 1.5.6
 +
! ID in 1.6
 +
|-
 +
| Near [[Jodi]] and [[Kent]]'s house
 +
| <code>0</code>
 +
| <code>JodiAndKent</code>
 
|-
 
|-
| <samp>WeatherConditions</samp>
+
| Near [[Emily]] and [[Haley]]'s house
| ''(Optional)'' The weather logic to apply for locations in this context (ignored if <samp>CopyWeatherFromLocation</samp> is set). Defaults to always sunny. If multiple are specified, the first matching weather is applied.
+
| <code>1</code>
 
+
| <code>EmilyAndHaley</code>
This consists of a list of models with these fields:
+
|-
{| class="wikitable"
+
| Near [[Lewis]]' house
 +
| <code>2</code>
 +
| <code>Mayor</code>
 +
|-
 +
| Near [[Museum]]
 +
| <code>3</code>
 +
| <code>Museum</code>
 
|-
 
|-
! field
+
| Near [[Blacksmith|Clint's blacksmith]]
! effect
+
| <code>4</code>
 +
| <code>Blacksmith</code>
 
|-
 
|-
| <samp>Weather</samp>
+
| Near [[The Stardrop Saloon|the Saloon]]
| The [[#Custom weather|weather ID]] to set.
+
| <code>5</code>
 +
| <code>Saloon</code>
 
|-
 
|-
| <samp>Condition</samp>
+
| Near [[Evelyn]] and [[George]]'s house
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether to apply the weather. Defaults to always applied.
+
| <code>6</code>
|}
+
| <code>Evelyn</code>
 
|-
 
|-
| <samp>CopyWeatherFromLocation</samp>
+
| Near [[JojaMart]]
| ''(Optional)'' The <samp>Name</samp> (i.e. unique ID) of the location context from which to inherit weather.
+
| <code>7</code>
 +
| <code>JojaMart</code>
 
|}
 
|}
   −
If a [[#Custom passive festivals|passive festival]] is active in any location within this context, the weather is sunny for the entire context regardless of these fields.
+
===Custom map actions===
 +
{{/doc status|[[Modding:Maps]]|done=false}}
   −
</dd>
+
C# mods can now handle custom <samp>Action</samp> & <samp>TouchAction</samp> [[Modding:Maps|map properties]] by calling <samp>GameLocation.RegisterTileAction</samp> & <samp>RegisterTouchAction</samp>, and passing a callback which receives the location, map property arguments, player who activated it, and tile position.
   −
<dt>Music:</dt>
+
For example, let's say you want a locked gate which needs a custom key item. You can add a regular <code>TouchAction Example.ModId_UnlockGate</code> map property (e.g. by adding it directly in the map file, or using [[Modding:Content Patcher|Content Patcher]]'s <samp>EditMap</samp>, or using the [[Modding:Modder Guide/APIs/Content|content API]]). Then you can just handle the logic from your C# mod:
<dd>
+
<syntaxhighlight lang="c#">
{| class="wikitable"
+
internal class ModEntry : Mod
|-
+
{
! field
+
    /// <inheritdoc />
! effect
+
    public override void Entry(IModHelper helper)
|-
+
    {
| <samp>DefaultMusic</samp>
+
        GameLocation.RegisterTouchAction("Example.ModId_UnlockGate", this.HandleUnlockGate);
| ''(Optional)'' The [[#Custom audio|cue ID]] for the music to play when the player is in the location, unless overridden by a <samp>Music</samp> map property. Despite the name, this has a higher priority than the seasonal music fields below. Ignored if omitted.
+
    }
|-
  −
| <samp>DefaultMusicCondition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which returns whether the <samp>DefaultMusic</samp> field should be applied (if more specific music isn't playing). Defaults to always true.
  −
|-
  −
| <samp>DefaultMusicDelayOneScreen</samp>
  −
| ''(Optional)'' When the player warps and the music changes, whether to silence the music and play the ambience (if any) until the next warp (similar to the default valley locations). Default false.
  −
|-
  −
| <samp>SpringMusic</samp><br /><samp>SummerMusic</samp><br /><samp>FallMusic</samp><br /><samp>WinterMusic</samp>
  −
| ''(Optional)'' A list of [[#Custom audio|cue IDs]] to play before noon in this location unless it's raining, there's a <samp>Music</samp> map property, or the context has a <samp>DefaultMusic</samp> value. If multiple values are specified, the game will play one per day in sequence.
  −
|-
  −
| <samp>DayAmbience</samp><br /><samp>NightAmbience</samp>
  −
| ''(Optional)'' The [[#Custom audio|cue ID]] for the background ambience to play when there's no music active, depending on the [[Day Cycle|time of day]]. Both default to none.
  −
|-
  −
| <samp>PlayRandomAmbientSounds</samp>
  −
| ''(Optional)'' Whether to play random outdoor ambience sounds depending on factors like the season and time of day (e.g. birds, crickets, and mysterious groan sounds in the rain). This is unrelated to the <samp>DayAmbience</samp> and <samp>NightAmbience</samp> fields. Default true.
  −
|}
  −
</dd>
     −
<dt>Advanced:</dt>
+
    private void HandleUnlockGate(GameLocation location, string[] args, Farmer player, Vector2 tile)
<dd>
+
    {
{| class="wikitable"
+
        const string mailFlag = "Example.ModId_GateUnlocked";
|-
+
        const string keyId = "Example.ModId_GateKey";
! field
  −
! effect
  −
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
  −
|}
  −
</dd>
  −
</dl>
     −
===Custom garbage cans===
+
        // unlock gate if locked
====Format====
+
        if (!player.mailReceived.Contains(mailFlag))
You can now add or edit [[Garbage Can|garbage cans]] on any map by editing the new <samp>Data/GarbageCans</samp> asset (see examples below).
+
        {
 +
            if (!Game1.player.Items.ContainsId(id, count))
 +
            {
 +
                Game1.activeClickableMenu = new DialogueBox("This gate is locked. I wonder where the key is?");
 +
                return;
 +
            }
   −
The asset consists of a data model with these fields:
+
            player.removeFirstOfThisItemFromInventory(keyId);
 +
            player.mailReceived.Add(mailFlag);
 +
        }
   −
{| class="wikitable"
+
        // apply open-gate map edit
|-
+
        // NOTE: this is a quick example which changes the location's current map. If another mod reloads the map
! field
+
        // (e.g. a content pack editing it), the change will be lost. For persistent changes, you should use the
! effect
+
        // AssetRequested event to apply the change when the map is reloaded.
|-
+
        IAssetDataForMap mapHelper = this.Helper.GameContent.GetPatchHelper(location.map).AsMap();
| <samp>DefaultBaseChance</samp>
+
        mapHelper.PatchMap(
| The probability that an item will be found when searching garbage cans, as a value between 0 (never) and 1 (always). If the probability check fails, only items that set <samp>IgnoreBaseChance</samp> can spawn. This can be overridden by the per-garbage-can <samp>BaseChance</samp> field. Default 0.2.
+
            this.Helper.Content.Load<Map>("assets/unlocked-gate.tmx"),
|-
+
            targetArea: new Rectangle((int)tile.X - 1, (int)tile.Y - 1, 2, 2)
| <samp>BeforeAll</samp><br /><samp>AfterAll</samp>
+
        );
| The items to prepend (<samp>BeforeAll</samp>) or append (<samp>AfterAll</samp>) to the <samp>GarbageCans</samp> → <samp>Items</samp> field for all garbage cans. These work exactly like the items in that field (e.g. subject to the garbage can's base chance).
+
    }
|-
+
}
| <samp>GarbageCans</samp>
+
</syntaxhighlight>
| The data for individual garbage cans. This consists of a string → model lookup with these fields:
     −
{| class="wikitable"
+
As another example, let's say you want the gate to unlock when the player presses the action key. You can add a regular <code>Action Example.ModId_UnlockGate</code> map property (e.g. by adding it directly in the map file, or using [[Modding:Content Patcher|Content Patcher]]'s <samp>EditMap</samp>, or using the [[Modding:Modder Guide/APIs/Content|content API]]). Then you can just handle the logic from your C# mod:
|-
+
<syntaxhighlight lang="c#">
! field
+
internal class ModEntry : Mod
! effect
+
{
|-
+
    /// <inheritdoc />
| ''entry key''
+
    public override void Entry(IModHelper helper)
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this garbage can.
+
    {
|-
+
        GameLocation.RegisterTileAction("Example.ModId_UnlockGate", this.HandleUnlockGate);
| <samp>BaseChance</samp>
+
    }
| ''(Optional)'' If set, overrides the root <samp>DefaultBaseChance</samp> field for this garbage can. Defaults to <samp>DefaultBaseChance</samp>.
+
 
|-
+
    private bool HandleUnlockGate(GameLocation location, string[] args, Farmer player, Microsoft.Xna.Framework.Point point)
| <samp>Items</samp>
+
    {
| ''(Optional)'' The items to try spawning when the player searches the garbage can. The first matching item in <samp>BeforeAll</samp> + <samp>Items</samp> + <samp>AfterAll</samp> will be spawned, and any further items will be ignored. Defaults to none.
+
        const string mailFlag = "Example.ModId_GateUnlocked";
 +
        const string keyId = "Example.ModId_GateKey";
 +
 
 +
        // unlock gate if locked
 +
        if (!player.mailReceived.Contains(mailFlag))
 +
        {
 +
            if (!Game1.player.Items.ContainsId(id, count))
 +
            {
 +
                Game1.activeClickableMenu = new DialogueBox("This gate is locked. I wonder where the key is?");
 +
                return false;
 +
            }
 +
 
 +
            player.removeFirstOfThisItemFromInventory(keyId);
 +
            player.mailReceived.Add(mailFlag);
 +
        }
 +
 
 +
        // apply open-gate map edit
 +
        // NOTE: this is a quick example which changes the location's current map. If another mod reloads the map
 +
        // (e.g. a content pack editing it), the change will be lost. For persistent changes, you should use the
 +
        // AssetRequested event to apply the change when the map is reloaded.
 +
        IAssetDataForMap mapHelper = this.Helper.GameContent.GetPatchHelper(location.map).AsMap();
 +
        mapHelper.PatchMap(
 +
            this.Helper.Content.Load<Map>("assets/unlocked-gate.tmx"),
 +
            targetArea: new Rectangle((int)point.X - 1, (int)point.Y - 1, 2, 2)
 +
        );
 +
 
 +
        return true;
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 
 +
===Custom map layers===
 +
{{/doc status|[[Modding:Maps]]|done=false}}
 +
 
 +
You can now add any number of [[Modding:Maps|map layers]] by suffixing a vanilla layer name (i.e. <samp>Back</samp>, <samp>Buildings</samp>, <samp>Front</samp>, or <samp>AlwaysFront</samp>) with an offset. For example, <samp>Back-1</samp> will be drawn before/under <samp>Back</samp>, and <samp>Back2</samp> will be drawn after/over it. You can increment the number to add more layers.
 +
 
 +
This only affects layer rendering. Tile properties must still be set on the original layers.
 +
 
 +
===Custom minecarts===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
You can now extend [[minecart]]s by editing the <samp>Data\Minecarts</samp> data asset.
 +
 
 +
This consists of a string → model lookup, where...
 +
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the minecart network. When you interact with a minecart, the destinations listed for its network are shown.
 +
* The value is a model with the fields listed below.
   −
This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 3,114: Line 3,176:  
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <samp>Destinations</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported by garbage cans.
+
| The destinations which the player can travel to from minecarts in this network. This consists of a list of model with these fields:
 
+
{| class="wikitable"
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>Id</samp>
 +
| A [[Modding:Common data field types#Unique string ID|unique string ID]] for this destination within the network.
 +
|-
 +
| <samp>DisplayName</samp>
 +
| A [[Modding:Tokenizable strings|tokenizable string]] for the destination name shown in the minecart menu. You can use the location's display name with the <samp>LocationName</samp> token (like <code>[LocationName Desert]</code> for the [[desert]]).
 +
|-
 +
| <samp>TargetLocation</samp>
 +
| The [[#Custom locations|location ID]] for the destination.
 +
|-
 +
| <samp>TargetTile</samp>
 +
| The destination tile position within the location, specified as a model with <samp>X</samp> and <samp>Y</samp> fields.
 
|-
 
|-
| <samp>IgnoreBaseChance</samp>
+
| <samp>TargetDirection</samp>
| ''(Optional)'' Whether this item can spawn even if the <samp>BaseChance</samp> probability check didn't pass. Default false.
+
| The direction the player should face after arrival (one of <samp>down</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>up</samp>).
 
|-
 
|-
| <samp>IsMegaSuccess</samp>
+
| <samp>Condition</samp>
| ''(Optional)'' Whether to treat this item as a 'mega success' if it's selected, which plays a special <samp>crit</samp> sound and bigger animation. Default false.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this minecart destination is available. Defaults to always available.
 
|-
 
|-
| <samp>IsDoubleMegaSuccess</samp>
+
| <samp>Price</samp>
| ''(Optional)'' Whether to treat this item as an 'double mega success' if it's selected, which plays an explosion sound and dramatic animation. Default false.
+
| ''(Optional)'' The gold price that must be paid each time to use this destination. Default none.
 
|-
 
|-
| <samp>AddToInventoryDirectly</samp>
+
| <samp>BuyTicketMessage</samp>
| ''(Optional)'' Whether to add the item to the player's inventory directly, opening an item grab menu if they don't have room in their inventory. If false, the item will be dropped on the ground next to the garbage can instead. Default false.
+
| ''(Optional)'' If the destination costs money to use, a [[Modding:Tokenizable strings|tokenizable string]] for the purchase confirmation message shown. If present, <code>{0}</code> is replaced with the purchase price. Defaults to the network's <samp>BuyTicketMessage</samp> field.
 
|-
 
|-
| <samp>CreateMultipleDebris</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' Whether to split the spawned item into multiple stacks which each have a stack size of one. This has no effect if <samp>AddToInventoryDirectly</samp> is enabled. Default false.
+
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.
 
|}
 
|}
 +
|-
 +
| <samp>UnlockCondition</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this minecart network is unlocked. Default always enabled.
 +
|-
 +
| <samp>LockedMessage</samp>
 +
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the message shown when interacting with a minecart when the <samp>UnlockCondition</samp> false. Defaults to an "''Out of order''" translation.
 +
|-
 +
| <samp>ChooseDestinationMessage</samp>
 +
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the message shown when listing destinations to choose from. Defaults to a "''Choose destination:''" translation.
 +
|-
 +
| <samp>BuyTicketMessage</samp>
 +
| ''(Optional)'' When a destination costs money to use, a [[Modding:Tokenizable strings|tokenizable string]] for the purchase confirmation message shown. If present, <code>{0}</code> is replaced with the purchase price. Defaults to a "''Buy a ticket for {0}g?''" translation.
 
|}
 
|}
   −
If the garbage can being searched doesn't have its own entry under <samp>GarbageCans</samp>, the game will just use the <samp>BeforeAll</samp> and <samp>AfterAll</samp> fields.
+
====Open a minecart menu====
|-
+
You can use an <samp>Action: MinecartTransport {{o|network ID}} {{o|exclude destination ID}}</samp> [[Modding:Maps|map property]] to open the minecart menu. When the player interacts with the tile, it'll open the menu for the {{o|network ID}} network (default <samp>Default</samp>). if {{o|exclude destination ID}} is specified, the matching destination will be hidden from the list (usually because you're at that minecart). For example, the [[Bus Stop|bus stop]] minecart uses <code>Action: MinecartTransport Default Bus</code>.
| <samp>CustomFields</samp>
+
 
| The [[#Custom data fields|custom fields]] for this entry.
+
From a C# mod, you can call <code>Game1.currentLocation.ShowMineCartMenu(networkId, excludeDestinationId)</code> which works the same way (except that <samp>networkId</samp> is required).
|}
     −
====Example new garbage can====
+
====Example====
You can add garbage cans using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. For example, this content pack adds a new garbage can entry with the ID <samp>Example.ModId_Carpenter</samp>:
+
This [[Modding:Content Patcher|Content Patcher]] content pack adds the [[Railroad]] as a minecart destination, complete with a map edit adding a decorative minecart. It is available after the [[Random Events|Earthquake]] has occurred and minecarts have been unlocked.
    
{{#tag:syntaxhighlight|<nowiki>
 
{{#tag:syntaxhighlight|<nowiki>
Line 3,149: Line 3,236:  
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 
     "Changes": [
 
     "Changes": [
 +
        // add minecart destination
 
         {
 
         {
 
             "Action": "EditData",
 
             "Action": "EditData",
             "Target": "Data/GarbageCans",
+
             "Target": "Data/Minecarts",
             "TargetField": [ "GarbageCans" ],
+
             "TargetField": [ "Default", "Destinations" ], // for the "Default" network, edit the "Destinations" field
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Carpenter": {
+
                 "Railroad": {
                     "Items": [
+
                     "Id": "Railroad",
                        // 25% chance of pufferfish
+
                    "DisplayName": "[LocationName Railroad]",
                        {
+
                    "Condition": "LOCATION_ACCESSIBLE Railroad",
                            "ID": "Example.ModId_Pufferfish",
  −
                            "Condition": "RANDOM 0.25",
  −
                            "ItemId": "(O)128"
  −
                        },
     −
                        // else guaranteed random House Plant item
+
                    "TargetLocation": "Railroad",
                        {
+
                    "TargetTile": { "X": 16, "Y": 39 },
                            "ID": "Example.ModId_RandomHousePlant",
+
                     "TargetDirection": "down",
                            "ItemID": "RANDOM_ITEMS (F) 1376 1390"
+
                 }
                        }
+
             }
                     ]
+
         },
                 }
  −
             }
  −
         }
  −
    ]
  −
}</nowiki>|lang=javascript}}
     −
Then you'd place an <code>Action: Garbage Example.ModId_Carpenter</code> [[Modding:Maps|map tile property]] to mark a tile as a garbage can using this data.
+
        // add decorative minecart
 
  −
====Example change for existing garbage can====
  −
You can edit an existing garbage cans using only [[Modding:Content Patcher|Content Patcher]] or [[Modding:Modder Guide/APIs/Content|SMAPI's content API]]. For example, this content pack adds pufferfish to the Saloon garbage can, and moves it above the dish of the day.
  −
 
  −
Note that this uses <samp>TargetField</samp> to 'move into' the item list for the saloon, and then treat those items as the entry list being edited. Specifying an ID which isn't in the list will add a new entry, just like when editing a regular list asset.
  −
 
  −
{{#tag:syntaxhighlight|<nowiki>
  −
{
  −
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
  −
    "Changes": [
   
         {
 
         {
             "Action": "EditData",
+
             "Action": "EditMap",
             "Target": "Data/GarbageCans",
+
             "Target": "Maps/Railroad",
             "TargetField": [ "GarbageCans", "Saloon", "Items" ],
+
             "FromFile": "assets/Custom_Railroad_Minecart.tmx",
             "Entries": {
+
             "ToArea": { "X": 15, "Y": 35, "Width": 4, "Height": 5 }
                // 25% chance of pufferfish
  −
               
  −
                "Example.ModId_Pufferfish":{
  −
                    "ID": "Example.ModId_Pufferfish",
  −
                    "Condition": "RANDOM 0.25",
  −
                    "ItemId": "(O)128"
  −
                }
  −
            },
  −
            "MoveEntries": [
  −
                { "ID": "Example.ModId_Pufferfish", "BeforeId": "Base_DishOfTheDay" }
  −
            ]
   
         }
 
         }
 
     ]
 
     ]
 
}</nowiki>|lang=javascript}}
 
}</nowiki>|lang=javascript}}
   −
===Custom map actions===
+
===Custom passive festivals===
C# mods can now handle custom <samp>Action</samp> & <samp>TouchAction</samp> [[Modding:Maps|map properties]] by calling <samp>GameLocation.RegisterTileAction</samp> & <samp>RegisterTouchAction</samp>, and passing a callback which receives the location, map property arguments, player who activated it, and tile position.
+
{{/doc status|[[Modding:Festival data]] or a new doc page|done=false}}
   −
For example, let's say you want a locked gate which needs a custom key item. You can add a regular <code>TouchAction Example.ModId_UnlockGate</code> map property (e.g. by adding it directly in the map file, or using [[Modding:Content Patcher|Content Patcher]]'s <samp>EditMap</samp>, or using the [[Modding:Modder Guide/APIs/Content|content API]]). Then you can just handle the logic from your C# mod:
+
You can now add or modify passive festivals by editing the <samp>Data/PassiveFestivals</samp> asset.
<syntaxhighlight lang="c#">
  −
internal class ModEntry : Mod
  −
{
  −
    /// <inheritdoc />
  −
    public override void Entry(IModHelper helper)
  −
    {
  −
        GameLocation.RegisterTouchAction("Example.ModId_UnlockGate", this.HandleUnlockGate);
  −
    }
     −
    private void HandleUnlockGate(GameLocation location, string[] args, Farmer player, Vector2 tile)
+
(A ''passive festival'' is a [[festivals|festival]] like the [[Night Market]]. They replace a location for a period of time, the player can enter/leave them anytime, and time continues passing while at the festival.)
    {
  −
        const string mailFlag = "Example.ModId_GateUnlocked";
  −
        const string keyId = "Example.ModId_GateKey";
  −
 
  −
        // unlock gate if locked
  −
        if (!player.mailReceived.Contains(mailFlag))
  −
        {
  −
            if (!Game1.player.Items.ContainsId(id, count))
  −
            {
  −
                Game1.activeClickableMenu = new DialogueBox("This gate is locked. I wonder where the key is?");
  −
                return;
  −
            }
  −
 
  −
            player.removeFirstOfThisItemFromInventory(keyId);
  −
            player.mailReceived.Add(mailFlag);
  −
        }
  −
 
  −
        // apply open-gate map edit
  −
        // NOTE: this is a quick example which changes the location's current map. If another mod reloads the map
  −
        // (e.g. a content pack editing it), the change will be lost. For persistent changes, you should use the
  −
        // AssetRequested event to apply the change when the map is reloaded.
  −
        IAssetDataForMap mapHelper = this.Helper.GameContent.GetPatchHelper(location.map).AsMap();
  −
        mapHelper.PatchMap(
  −
            this.Helper.Content.Load<Map>("assets/unlocked-gate.tmx"),
  −
            targetArea: new Rectangle((int)tile.X - 1, (int)tile.Y - 1, 2, 2)
  −
        );
  −
    }
  −
}
  −
</syntaxhighlight>
  −
 
  −
===Custom map layers===
  −
You can now add any number of [[Modding:Maps|map layers]] by suffixing a vanilla layer name (i.e. <samp>Back</samp>, <samp>Buildings</samp>, <samp>Front</samp>, or <samp>AlwaysFront</samp>) with an offset. For example, <samp>Back-1</samp> will be drawn before/under <samp>Back</samp>, and <samp>Back2</samp> will be drawn after/over it. You can increment the number to add more layers.
  −
 
  −
This only affects layer rendering. Tile properties must still be set on the original layers.
  −
 
  −
===Custom minecarts===
  −
You can now add/edit [[minecart]] destinations by editing the <samp>Data\Minecarts</samp> data asset, which consists of a data model with two relevant fields (listed below).
      +
====Data format====
 +
The <samp>Data/PassiveFestivals</samp> asset consists of a string → model lookup, where...
 +
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the festival.
 +
* The value is a model with the fields listed below.
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 3,263: Line 3,280:  
! effect
 
! effect
 
|-
 
|-
| <samp>MinecartsUnlocked</samp>
+
| <samp>DisplayName</samp>
| A [[Modding:Game state queries|game state query]] which indicates whether minecarts in general are unlocked. You usually shouldn't change this value, unless you're changing the overall game progression (e.g. adding an alternative way to unlock minecart access).
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the display name shown on the [[calendar]].
 
|-
 
|-
| <samp>Destinations</samp>
+
| <samp>Season</samp>
| The destinations which the player can travel to from any minecart. This consists of a string → model lookup, where the key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the destination, and the value is a model with these fields:
+
| The [[season]] when the festival becomes active.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>StartDay</samp><br /><samp>EndDay</samp>
! effect
+
| The days of month when the festival becomes active.
 
|-
 
|-
| <samp>Location</samp>
+
| <samp>StartTime</samp>
| The [[#Custom locations|location ID]] for the destination.
+
| The time of day when the festival opens each day.
 
|-
 
|-
| <samp>Tile</samp>
+
| <samp>StartMessage</samp>
| The destination tile position within the location, specified as a model with <samp>X</samp> and <samp>Y</samp> fields.
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the in-game [[wikipedia:Pop-up notification|toast notification]] shown when the festival begins each day.
 
|-
 
|-
| <samp>Direction</samp>
+
| <samp>MapReplacements</samp>
| The direction the player should face after arrival (one of <samp>down</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>up</samp>).
+
| The locations to swap for the duration of the festival. Despite the field name, this swaps '''locations''' (e.g. as added by <samp>CustomLocations</samp> using [[Modding:Content Patcher|Content Patcher]]), and not the location's map asset.
|-
+
 
| <samp>DisplayName</samp>
+
This is specified as a string → string lookup, where the key is the original location to replace and the value is the new location. Both use the internal location name, as shown by the {{nexus mod|679|Debug Mode}} mod. For example, this swaps the <samp>Beach</samp> location with <samp>BeachNightMarket</samp> during the [[Night Market]]:
| A [[Modding:Tokenizable strings|tokenizable string]] for the destination name shown in the minecart menu. You can use the location's display name with the <samp>LocationName</samp> token (like <code>[LocationName Desert]</code> for the [[desert]]).
+
<syntaxhighlight lang="js">
 +
"MapReplacements": {
 +
    "Beach": "BeachNightMarket"
 +
}
 +
</syntaxhighlight>
 +
|-
 +
| <samp>Condition</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the festival is enabled (subject to the other fields like <samp>StartDay</samp> and <samp>EndDay</samp>). Defaults to always enabled.
 
|-
 
|-
| <samp>Network</samp>
+
| <samp>ShowOnCalendar</samp>
| ''(Optional)'' An arbitrary ID which groups the destination (along with any others having the same ID) into a separate network. Destinations in a network are only visible if the destination list is opened for that network via the <samp>MinecartTransport {{o|network name}}</samp> [[Modding:Maps|action property]]. If omitted, the minecart is part of the implicit default network.
+
| ''(Optional)'' Whether the festival appears on the [[calendar]], using the same iridium-star icon as the [[Calendar#Winter|Night Market]]. Default true.
 
|-
 
|-
| <samp>Condition</samp>
+
| <samp>DailySetupMethod</samp><br /><samp>CleanupMethod</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this minecart destination is available. Defaults to always available.
+
| ''(Optional)'' A C# method which applies custom logic when the day starts (<samp>DailySetupMethod</samp>) and/or overnight after the last day of the festival (<samp>CleanupMethod</samp>).
 +
 
 +
These must be specified in the form <samp>{{t|full type name}}: {{t|method name}}</samp> (like <samp>ExampleMod.Namespace.Type, ExampleMod: MethodName</samp>). The methods must be static, take zero arguments, and return void.
 
|-
 
|-
 
| <samp>CustomFields</samp>
 
| <samp>CustomFields</samp>
 
| The [[#Custom data fields|custom fields]] for this entry.
 
| The [[#Custom data fields|custom fields]] for this entry.
 
|}
 
|}
 +
 +
====NPC schedules====
 +
When a passive festival is active, NPCs will check for [[Modding:Schedule data|a schedule entry]] in this order:
 +
 +
{| class="wikitable"
 +
|-
 +
! syntax
 +
! summary
 +
|-
 +
| <samp>{{t|festival ID}}_{{t|festival day}}</samp>
 +
| Applies on the given date. The {{t|festival day}} is relative, so <samp>1</samp> matches the festival <samp>StartDay</samp>.<br /><small>Example: <samp>NightMarket_3</samp> or <samp>marriage_NightMarket_3</samp></small>
 +
|-
 +
| <samp>{{t|festival ID}}</samp>
 +
| Applies if there's no date-specific entry.<br /><small>Example: <samp>NightMarket</samp> or <samp>marriage_NightMarket</samp></small>
 
|}
 
|}
   −
====Example====
+
If the NPC is married to a player, they'll add a <samp>marriage_</samp> prefix to the keys (like <samp>marriage_{{t|festival ID}}_{{t|festival day}}</samp>) and ignore any entry without the prefix.
This [[Modding:Content Patcher|Content Patcher]] content pack adds the [[Railroad]] as a minecart destination, complete with a map edit adding a decorative minecart. It is available after the [[Random Events|Earthquake]] has occured and minecarts have been unlocked.
     −
{{#tag:syntaxhighlight|<nowiki>
+
===Custom weather===
{
+
{{/doc status|[[Modding:Weather data]]|done=false}}
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
  −
    "Changes": [
  −
        // add minecart destination
  −
        {
  −
            "Action": "EditData",
  −
            "Target": "Data/Minecarts",
  −
            "TargetField": [ "Destinations" ],
  −
            "Entries": {
  −
                "Railroad": {
  −
                    "Location": "Railroad",
  −
                    "Tile": { "X": 16, "Y": 39 },
  −
                    "Direction": "down",
  −
                    "DisplayName": "[LocationName Railroad]"
  −
                }
  −
            },
  −
            "When": {
  −
                "HasFlag": "ccBoilerRoom",
  −
                "query: {{DaysPlayed}} </nowiki>><nowiki>= 32": true
  −
            }
  −
        },
     −
        // add decorative minecart
+
You can now change the weather algorithm by editing [[#Custom location contexts|location context data]], and (with a C# mod) implement custom weathers.
        {
  −
            "Action": "EditMap",
  −
            "Target": "Maps/Railroad",
  −
            "FromFile": "assets/Custom_Railroad_Minecart.tmx",
  −
            "ToArea": { "X": 15, "Y": 35, "Width": 4, "Height": 5 }
  −
        }
  −
    ]
  −
}</nowiki>|lang=javascript}}
     −
===Custom passive festivals===
+
Fields like <samp>Game1.weather</samp> and <samp>Game1.weatherForTomorrow</samp> are now strings to support custom mod weather IDs. The change for vanilla weather has no effect on Content Patcher packs, since the new weather IDs match the ones Content Patcher was using before (i.e. <samp>Sun</samp>, <samp>Rain</samp>, <samp>Snow</samp>, <samp>Storm</samp>, and <samp>Wind</samp>). C# mods may also see a <samp>Festival</samp> weather, while Content Patcher packs will see <samp>Sun</samp> for it. The constants like <samp>Game1.weather_sunny</samp> have the new string values (with new constants like <samp>Game1.legacy_weather_sunny</samp> for the legacy values).
You can now add or modify passive festivals by editing the <samp>Data/PassiveFestivals</samp> asset.
+
 
 +
The base game will treat an invalid weather as sunny. C# mods can implement custom weather effects using [[Modding:Modder Guide/APIs/Events|normal SMAPI events]] like <samp>UpdateTicked</samp>, or by [[Modding:Modder Guide/APIs/Harmony|patching]] methods like <samp>Game1.ApplyWeatherForNewDay</samp> and <samp>Game1.populateDebrisWeatherArray</samp>.
 +
 
 +
===Custom world maps===
 +
{{/doc status|[[Modding:World map]]|done=true}}
 +
 
 +
[[File:Modding map area.png|thumb|The default world map, with the farm map area highlighted.]]
 +
 
 +
You can now change the world map shown in the game menu by editing the <samp>Data/WorldMap</samp> asset. This lets you...
 +
* add custom maps for certain locations;
 +
* apply texture overlays;
 +
* add/edit tooltips;
 +
* set real-time player marker positioning;
 +
* etc.
 +
 
 +
The game's default map is fully defined in <samp>Data/WorldMap</samp>, including all the display text and conditional changes.
 +
 
 +
===New map properties===
 +
{{/doc status|[[Modding:Maps]]|done=false}}
   −
(A ''passive festival'' is a [[festivals|festival]] like the [[Night Market]]. They replace a location for a period of time, the player can enter/leave them anytime, and time continues passing while at the festival.)
+
1.6 adds several new [[Modding:Maps|map properties]].
   −
====Data format====
+
====Building construction====
The <samp>Data/PassiveFestivals</samp> asset consists of a string → model lookup, where...
  −
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the festival.
  −
* The value is a model with the fields listed below.
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! property
! effect
+
! explanation
 
|-
 
|-
| <samp>DisplayName</samp>
+
| <samp>CanBuildHere T</samp><br />''(valid in any outdoor location)''
| A [[Modding:Tokenizable strings|tokenizable string]] for the display name shown on the [[calendar]].
+
| Whether to allow constructing buildings in this location. The game will adjust automatically to account for it (e.g. Robin will let you choose where to build). See [[#Build anywhere|''build anywhere'' in what's new]].
 
|-
 
|-
| <samp>Season</samp>
+
| <samp>BuildConditions {{t|query}}</samp><br />''(valid in any outdoor location)''
| The [[season]] when the festival becomes active.
+
| If <samp>CanBuildHere</samp> is set, an optional [[Modding:Game state queries|game state query]] which indicates whether building is allowed currently.
 
|-
 
|-
| <samp>StartDay</samp><br /><samp>EndDay</samp>
+
| <samp>LooserBuildRestrictions T</samp><br />''(valid in any outdoor location)''
| The days of month when the festival becomes active.
+
| If set, tiles don't need to be marked <samp>Buildable T</samp> or <samp>Diggable T</samp> in their properties. Tiles can be blocked with <samp>Buildable F</samp> instead. The other restrictions still apply.
 
|-
 
|-
| <samp>StartTime</samp>
+
| <samp>ValidBuildRect {{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp><br />''(valid in any outdoor location)''
| The time of day when the festival opens each day.
+
| The tile area within the map where buildings may be placed. If omitted, buildings may be placed in any open space in the map.
 +
|}
 +
 
 +
====Crops====
 +
{| class="wikitable"
 
|-
 
|-
| <samp>StartMessage</samp>
+
! property
| A [[Modding:Tokenizable strings|tokenizable string]] for the in-game [[wikipedia:Pop-up notification|toast notification]] shown when the festival begins each day.
+
! explanation
 
|-
 
|-
| <samp>MapReplacements</samp>
+
| <samp>AllowGiantCrops T</samp>
| The locations to swap for the duration of the festival. Despite the field name, this swaps '''locations''' (e.g. as added by <samp>CustomLocations</samp> using [[Modding:Content Patcher|Content Patcher]]), and not the location's map asset.
+
| If set with any non-blank value, [[Crops#Giant Crops|giant crops]] can grow in this location (if crops are also allowed per the [[#Custom crops|crop data]] or [[#Custom location contexts|<samp>PlantableLocations</samp> context field]]).
 +
|-
 +
| <samp>DirtDecayChance {{t|chance}}</samp>
 +
| The probability that each dirt tile will disappear overnight if it doesn't contain a crop, as a value between 0 (never) and 1 (always). Defaults to 0 (greenhouses), 0.1 (farms), and 1 (anywhere else).
 +
|}
   −
This is specified as a string → string lookup, where the key is the original location to replace and the value is the new location. Both use the internal location name, as shown by the {{nexus mod|679|Debug Mode}} mod. For example, this swaps the <samp>Beach</samp> location with <samp>BeachNightMarket</samp> during the [[Night Market]]:
+
====Farmhouse interior====
<syntaxhighlight lang="js">
+
{| class="wikitable"
"MapReplacements": {
  −
    "Beach": "BeachNightMarket"
  −
}
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>Condition</samp>
+
! property
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the festival is enabled (subject to the other fields like <samp>StartDay</samp> and <samp>EndDay</samp>). Defaults to always enabled.
+
! explanation
 
|-
 
|-
| <samp>ShowOnCalendar</samp>
+
| <samp>FarmHouseStarterGift [{{t|id}} {{o|count}}]+</samp>
| ''(Optional)'' Whether the festival appears on the [[calendar]], using the same iridium-star icon as the [[Calendar#Winter|Night Market]]. Default true.
+
| The items that should appear in the initial gift box placed in the farmhouse when the save is created. This consists of one or more pairs of item ID (which can be qualified or unqualified) and count. The count is optional on the last entry.
|-
+
 
| <samp>DailySetupMethod</samp><br /><samp>CleanupMethod</samp>
+
For example, this will add 10 pufferfish (object 128) and a blobfish mask (hat 56):
| ''(Optional)'' A C# method which applies custom logic when the day starts (<samp>DailySetupMethod</samp>) and/or overnight after the last day of the festival (<samp>CleanupMethod</samp>).
+
<pre>FarmHouseStarterGift (O)128 10 (H)56 1</pre>
   −
These must be specified in the form <samp>{{t|full type name}}.{{t|method name}}</samp>. The methods must be static, take zero arguments, and return void.
+
If omitted, the default items (usually a 15 parsnip seeds) are added instead.
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
   
|}
 
|}
   −
====NPC schedules====
+
====Warps & map positions====
When a passive festival is active, NPCs will check for [[Modding:Schedule data|a schedule entry]] in this order:
  −
 
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! syntax
+
! property
! summary
+
! explanation
 +
|-
 +
| <samp>AllowWakeUpWithoutBed {{t|allow}}</samp>
 +
| Whether the player can wake up in this location without a bed, similar to the island farmhouse. This is typically used with <samp>PassOutLocations</samp> in [[#Custom location contexts|<samp>Data/LocationContexts</samp>]].
 +
|-
 +
| <samp>DefaultWarpLocation {{t|x}} {{t|y}}</samp><br />''(valid in any location)''
 +
| The default arrival tile, used when a player or NPC is added to the location without a target tile (e.g. using [[Modding:Console commands|debug commands]] like <samp>debug warp</samp> or <samp>debug eventbyid</samp>).
 +
|-
 +
| <samp>PetBowlLocation {{t|x}} {{t|y}}</samp><br />''(valid in the farm)''
 +
| The default position of the pet bowl
 
|-
 
|-
| <samp>{{t|festival ID}}_{{t|festival day}}</samp>
+
| <samp>SpouseRoomPosition {{t|x}} {{t|y}}</samp><br />''(valid in farmhouse)''
| Applies on the given date. The {{t|festival day}} is relative, so <samp>1</samp> matches the festival <samp>StartDay</samp>.<br /><small>Example: <samp>NightMarket_3</samp> or <samp>marriage_NightMarket_3</samp></small>
+
| The top-left position at which to place the [[Marriage#Spouse Rooms|spouse room]].
 
|-
 
|-
| <samp>{{t|festival ID}}</samp>
+
| <samp>TravelingCartPosition {{t|x}} {{t|y}}</samp><br />''(valid in the forest)''
| Applies if there's no date-specific entry.<br /><small>Example: <samp>NightMarket</samp> or <samp>marriage_NightMarket</samp></small>
+
| The top-left position at which to place the [[Traveling Cart]]. This is the top-left corner of the collision box, so the roof will extend two tiles above this tile.
 
|}
 
|}
   −
If the NPC is married to a player, they'll add a <samp>marriage_</samp> prefix to the keys (like <samp>marriage_{{t|festival ID}}_{{t|festival day}}</samp>) and ignore any entry without the prefix.
+
===Other map property changes===
 +
{{/doc status|[[Modding:Maps]]|done=false}}
   −
===Custom weather===
+
{| class="wikitable"
You can now change the weather algorithm by editing [[#Custom location contexts|location context data]], and (with a C# mod) implement custom weathers.
+
|-
 
+
! map property
Fields like <samp>Game1.weather</samp> and <samp>Game1.weatherForTomorrow</samp> are now strings to support custom mod weather IDs. The change for vanilla weather has no effect on Content Patcher packs, since the new weather IDs match the ones Content Patcher was using before (i.e. <samp>Sun</samp>, <samp>Rain</samp>, <samp>Snow</samp>, <samp>Storm</samp>, and <samp>Wind</samp>). C# mods may also see a <samp>Festival</samp> weather, while Content Patcher packs will see <samp>Sun</samp> for it. The constants like <samp>Game1.weather_sunny</samp> have the new string values (with new constants like <samp>Game1.legacy_weather_sunny</samp> for the legacy values).
+
! changes
 
+
|-
The base game will treat an invalid weather as sunny. C# mods can implement custom weather effects using [[Modding:Modder Guide/APIs/Events|normal SMAPI events]] like <samp>UpdateTicked</samp>, or by [[Modding:Modder Guide/APIs/Harmony|patching]] methods like <samp>Game1.ApplyWeatherForNewDay</samp> and <samp>Game1.populateDebrisWeatherArray</samp>.
+
| <samp>Arch</samp><br /><samp>asdf</samp><br /><samp>Debris</samp><br /><samp>Fish</samp>
 
+
| Removed (these were unused).
===Custom world maps===
  −
[[File:Modding map area.png|thumb|The default world map, with the farm map area highlighted.]]
  −
 
  −
You can now change the world map shown in the game menu by editing the <samp>Data/WorldMap</samp> asset. This lets you...
  −
* add custom maps for certain locations;
  −
* apply texture overlays;
  −
* add/edit tooltips;
  −
* set real-time player marker positioning;
  −
* etc.
  −
 
  −
The game's default map is fully defined in <samp>Data/WorldMap</samp>, including all the display text and conditional changes.
  −
 
  −
See [[Modding:World map]] for more info.
  −
 
  −
===New map properties===
  −
1.6 adds several new [[Modding:Maps|map properties]].
  −
 
  −
====Building construction====
  −
{| class="wikitable"
   
|-
 
|-
! property
+
| <samp>FarmHouseFlooring</samp><br /><samp>FarmHouseFurniture</samp><br /><samp>FarmHouseStarterSeedsPosition</samp><br /><samp>FarmHouseWallpaper</samp>
! explanation
+
| These now work independently. For example, you can now use <samp>FarmHouseFlooring</samp> without needing to set <samp>FarmHouseFurniture</samp> too.
 
|-
 
|-
| <samp>CanBuildHere T</samp><br />''(valid in any outdoor location)''
+
| <samp>Music</samp>
| Whether to allow constructing buildings in this location. The game will adjust automatically to account for it (e.g. Robin will let you choose where to build). See [[#Build anywhere|''build anywhere'' in what's new]].
+
| Deprecated; use the music fields in [[#Custom locations|<samp>Data/Locations</samp>]] instead. This property is only applied if the location has no music in <samp>Data/Locations</samp>. This was removed from all vanilla maps.
 
|-
 
|-
| <samp>BuildConditions {{t|query}}</samp><br />''(valid in any outdoor location)''
+
| <samp>NPCWarp</samp><br /><samp>Warp</samp>
| If <samp>CanBuildHere</samp> is set, an optional [[Modding:Game state queries|game state query]] which indicates whether building is allowed currently.
+
| Now fault-tolerant. They'll automatically ignore extra spaces, log an informative warning if parsing still fails, and continue with the next warp if possible.
 
|-
 
|-
| <samp>LooserBuildRestrictions T</samp><br />''(valid in any outdoor location)''
+
| <samp>Stumps</samp>
| If set, tiles don't need to be marked <samp>Buildable T</samp> or <samp>Diggable T</samp> in their properties. Tiles can be blocked with <samp>Buildable F</samp> instead. The other restrictions still apply.
+
| Now works in all locations.
 
|-
 
|-
| <samp>ValidBuildRect {{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp><br />''(valid in any outdoor location)''
+
| <samp>UniquePortrait</samp><br /><samp>UniqueSprite</samp>
| The tile area within the map where buildings may be placed. If omitted, buildings may be placed in any open space in the map.
+
| Deprecated; use [[#Custom NPC appearance|custom NPC appearances]] instead. These properties will override NPC appearances. This was removed from all vanilla maps.
 
|}
 
|}
   −
====Crops====
+
===Tile property changes===
 +
{{/doc status|[[Modding:Maps]]|done=false}}
 +
 
 +
<ul>
 +
<li>You can now override a tile index property by setting it as a tile property.</li>
 +
<li>Added new [[Modding:Maps|tile properties]]:
 
{| class="wikitable"
 
{| class="wikitable"
|-
+
! layer
 
! property
 
! property
 
! explanation
 
! explanation
 
|-
 
|-
| <samp>AllowGiantCrops T</samp>
+
| <samp>Paths</samp>
| If set with any non-blank value, [[Crops#Giant Crops|giant crops]] can grow in this location (if crops are also allowed per the [[#Custom crops|crop data]] or [[#Custom location contexts|<samp>PlantableLocations</samp> context field]]).
+
| <samp>SpawnTree {{t|category}} {{t|ID}} {{t|Growth stage}} {{t|Regrowth stage}}</samp>
 +
| Spawns a tree when the map is created. {{t|category}} may be either <samp>wild</samp> or <samp>fruit</samp>. <samp>wild</samp> will spawn a [[Trees|wild tree]], while <samp>fruit</samp> will spawn a [[Fruit Trees|fruit tree]].  
 
|}
 
|}
 
+
</li>
====Farmhouse interior====
+
<li>Added new <samp>Action</samp> [[Modding:Maps|tile properties]]:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 +
! layer
 
! property
 
! property
 
! explanation
 
! explanation
 
|-
 
|-
| <samp>FarmHouseStarterGift [{{t|id}} {{o|count}}]+</samp>
+
| <samp>Buildings</samp>
| The items that should appear in the initial gift box placed in the farmhouse when the save is created. This consists of one or more pairs of item ID (which can be qualified or unqualified) and count. The count is optional on the last entry.
+
| <samp>Action BuildingSilo</samp>
 +
| If a building covers this tile, enables [[silo]] interactions on this tile subject to the building's <samp>HayCapacity</samp> field in <samp>Data/Buildings</samp>.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action BuildingToggleAnimalDoor</samp>
 +
| If a building covers this tile, opens or closes its animal door.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action Dialogue</samp>
 +
| &#32;
 +
* The message can now be a [[Modding:Tokenizable strings|tokenizable string]].
 +
* Fixed the cursor not changing to the inspection icon when hovering on an <samp>Action Dialogue</samp> tile.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action Forge</samp>
 +
| Opens the [[Forge]] menu.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action None</samp>
 +
| Does nothing. This is used to mark the tile interactive if the click will be handled separately.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action ObeliskWarp {{t|location name}} {{t|x}} {{t|y}} {{o|whether to dismount}}</samp>
 +
| Warps the player to the specified location name and position with the [[Warp Totem|Obelisk]] animation/sound effects.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action OpenShop {{t|shop id}} {{o|from direction}} {{o|open time}} {{o|close time}} {{o|owner tile area}}</samp>
 +
| Open the [[#Custom shops|shop]] with the given {{t|shop id}}. All arguments besides the ID are optional:
 +
* {{o|from direction}}: if specified, the player must be standing in this direction relative to the shop (one of <samp>down</samp>, <samp>up</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>none</samp>). Setting this to <samp>none</samp> disables the requirement. The default for most vanilla shops is <samp>down</samp>.
 +
* {{o|open time}} and {{o|close time}}: the start & end times in 26-hour format when the shop is available. Interacting with the tile outside those times does nothing.
 +
* {{o|owner tile area}}: if specified, the tile area which must contain one of the shop owners for the shop to be available. For a custom shop, these are defined by its <samp>Owners</samp> field. This can be specified in two forms: <samp>{{t|x}} {{t|y}}</samp> for a single tile, or <samp>{{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp> for a multi-tile area.
 +
|-
 +
| <samp>Buildings</samp>
 +
| <samp>Action PlayEvent {{t|event id}} {{o|check preconditions}} {{o|skip if seen}} {{o|fallback action}}</samp>
 +
| Immediately start an [[Modding:Event data|event]], subject to the conditions:
 +
* {{o|check preconditions}}: whether to ignore the action if the [[Modding:Event data#Event preconditions|event's preconditions]] don't match (one of <samp>true</samp> or <samp>false</samp>). Default true.
 +
* {{o|skip if seen}}: whether to ignore the action if the player has already seen the given event. Default true.
   −
For example, this will add 10 pufferfish (object 128) and a blobfish mask (hat 56):
+
If the event doesn't start for any reason (including the preceding conditions):
<pre>FarmHouseStarterGift (O)128 10 (H)56 1</pre>
+
* If {{o|fallback action}} is specified, it'll be run as an action. This can be any <samp>Action</samp> tile property (without the "Action " prefix), like <code>Action PlayEvent 60367 true true PlayEvent 520702 false false</code> to play a different event.
 +
* Otherwise the action is silently ignored.
   −
If omitted, the default items (usually a 15 parsnip seeds) are added instead.
+
For example, <code>Action PlayEvent 60367 false false</code> will replay the bus arrival event from the start of the game.
 
|}
 
|}
 
+
</li>
====Warps & map positions====
+
<li>Added new <samp>TouchAction</samp> [[Modding:Maps|tile properties]]:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 +
! layer
 
! property
 
! property
 
! explanation
 
! explanation
 
|-
 
|-
| <samp>AllowWakeUpWithoutBed {{t|allow}}</samp>
+
| <samp>Back</samp>
| Whether the player can wake up in this location without a bed, similar to the island farmhouse. This is typically used with <samp>PassOutLocations</samp> in [[#Custom location contexts|<samp>Data/LocationContexts</samp>]].
+
| <samp>TouchAction PlayEvent {{t|event id}} {{o|check preconditions}} {{o|skip if seen}} {{o|fallback action}}</samp>
|-
+
| Equivalent to <samp>Action PlayEvent</samp>, but activated on touch. Note that {{o|fallback action}} is an <samp>Action</samp> tile property, ''not'' a <samp>TouchAction</samp> tile property.
| <samp>DefaultWarpLocation {{t|x}} {{t|y}}</samp><br />''(valid in any location)''
+
|}</li>
| The default arrival tile, used when a player or NPC is added to the location without a target tile (e.g. using [[Modding:Console commands|debug commands]] like <samp>debug warp</samp> or <samp>debug eventbyid</samp>).
+
<li>Changed existing tile properties:
|-
  −
| <samp>SpouseRoomPosition {{t|x}} {{t|y}}</samp><br />''(valid in farmhouse)''
  −
| The top-left position at which to place the [[Marriage#Spouse Rooms|spouse room]].
  −
|-
  −
| <samp>TravelingCartPosition {{t|x}} {{t|y}}</samp><br />''(valid in the forest)''
  −
| The top-left position at which to place the [[Traveling Cart]]. This is the top-left corner of the collision box, so the roof will extend two tiles above this tile.
  −
|}
  −
 
  −
===Other map property changes===
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! map property
+
! layer
! changes
+
! property
 +
! reason
 
|-
 
|-
| <samp>Arch</samp><br /><samp>asdf</samp><br /><samp>Debris</samp><br /><samp>Fish</samp>
+
|rowspan="4"| <samp>Back</samp>
| Removed (these were unused).
+
| <samp>NoSpawn</samp>
 +
| Added <samp>NoSpawn false</samp> form, which disables any previous <samp>NoSpawn</samp> property on the tile. For example, this can be used to enable spawning on a tile which has a <samp>NoSpawn</samp> tile index property.
 
|-
 
|-
| <samp>FarmHouseFlooring</samp><br /><samp>FarmHouseFurniture</samp><br /><samp>FarmHouseStarterSeedsPosition</samp><br /><samp>FarmHouseWallpaper</samp>
+
| <samp>TouchAction Bus</samp>
| These now work independently. For example, you can now use <samp>FarmHouseFlooring</samp> without needing to set <samp>FarmHouseFurniture</samp> too.
+
| Removed. This wasn't used by the game or mods.
 
|-
 
|-
| <samp>Music</samp>
+
| <samp>TouchAction Emote</samp>
| Deprecated; use the music fields in [[#Custom locations|<samp>Data/Locations</samp>]] instead. This property is only applied if the location has no music in <samp>Data/Locations</samp>. This was removed from all vanilla maps.
+
| Fixed error if the specified NPC isn't found.
 
|-
 
|-
| <samp>NPCWarp</samp><br /><samp>Warp</samp>
+
| <samp>Treasure</samp>
| Now fault-tolerant. They'll automatically ignore extra spaces, log an informative warning if parsing still fails, and continue with the next warp if possible.
+
| Added <samp>Treasure Item {{t|item ID}}</samp> form which accepts a [[#Custom items|qualified or unqualified item ID]].
 
|-
 
|-
| <samp>Stumps</samp>
+
|rowspan="2"| <samp>Buildings</samp>
| Now works in all locations.
+
| <samp>Action ItemChest</samp><br /><samp>Action Minecart</samp><br /><samp>Action RemoveChest</samp>
 +
| Removed. These weren't used by the game or mods.
 
|-
 
|-
| <samp>UniquePortrait</samp><br /><samp>UniqueSprite</samp>
+
| <samp>Action Kitchen</samp>
| Deprecated; use [[#Custom NPC appearance|custom NPC appearances]] instead. These properties will override NPC appearances. This was removed from all vanilla maps.
+
| Now works in any location (including those without a fridge).
 
|}
 
|}
 +
</li>
 +
</ul>
 +
 +
===Other location/map changes===
 +
{{/doc status|[[Modding:Maps]] and other pages as needed|done=false}}
   −
===Tile property changes===
+
* Farm data:
<ul>
+
** Added <samp>SpawnMonstersByDefault</samp> field to <samp>Data/AdditionalFarms</samp> to set the default value of the 'spawn monsters at night' [[Options#Advanced Game Options|advanced save option]].
<li>You can now override a tile index property by setting it as a tile property.</li>
+
** Fixed crash on new-save screen if the farm type's tooltip has no description.
<li>Added new <samp>Action</samp> [[Modding:Maps|tile properties]]:
+
* General location data:
{| class="wikitable"
+
** All locations can now have animals. The <samp>IAnimalLocation</samp> is now obsolete and implemented by <samp>GameLocation</samp>.
|-
+
** Added new [[Modding:Fish data|fishing areas]] to simplify compatibility between fish & map mods (specifically for hilltop farm, wilderness farm, town, and desert).
! layer
+
** Added a descriptive error when a required location or layer isn't found. Mods can use <samp>map.RequireLayer</samp> and <samp>Game1.RequireLocation</samp> to get a location with similar error-checking.
! property
+
** Added <samp>WarpPathfindingCache</samp> for C# mods, which modularizes the NPC warp route logic. You can edit its <samp>IgnoreLocationNames</samp>, <samp>OverrideTargetNames</samp>, and <samp>GenderRestrictions</samp> fields if needed for custom locations.
! explanation
+
** Game logic which checks tile indexes is now more fault-tolerant, so it won't crash if an expected tile was edited.
 +
** Finished migrating <samp>DecoratableLocation</samp> flooring/wallpaper areas to string IDs (started in Stardew Valley 1.5.5).
 +
* General map changes:
 +
** Added validation for [[Modding:Maps|map properties and tile properties]]. If the format is invalid, the game will now log a detailed error and skip it.
 +
** Removed unused [[Modding:Maps#Paths layer|path tiles]] in <samp>Maps/paths</samp> and all map files.
 +
* Location context data:
 +
** Building interiors now inherit their parent's location context by default.
 +
** Added <samp>Game1.locationContextData</samp> to cache the data from <samp>Data/LocationContexts</samp>.
 +
** Added constants for the vanilla context IDs like <samp>LocationContexts.IslandId</samp>.
 +
** Added validation for required location context IDs (and <samp>LocationContexts.Require(id)</samp> for mod logic).
 +
** Removed the <samp>Name</samp> field in <samp>Data/LocationContexts</samp>, which duplicated the ID.
 +
<ul>
 +
<li>Added methods to simplify common operations:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>Buildings</samp>
+
! type
| <samp>Action BuildingSilo</samp>
+
! method
| If a building covers this tile, enables [[silo]] interactions on this tile subject to the building's <samp>HayCapacity</samp> field in <samp>Data/Buildings</samp>.
+
! effect
 
|-
 
|-
| <samp>Buildings</samp>
+
|rowspan="7"| <samp>Building</samp>
| <samp>Action BuildingToggleAnimalDoor</samp>
+
| <samp>GetParentLocation</samp>
| If a building covers this tile, opens or closes its animal door.
+
| Get the location which contains this building.
 
|-
 
|-
| <samp>Buildings</samp>
+
| <samp>IsInCurrentLocation</samp>
| <samp>Action Forge</samp>
+
| Get whether the building is in the same location as the current player.
| Opens the [[Forge]] menu.
   
|-
 
|-
| <samp>Buildings</samp>
+
| <samp>HasIndoors</samp>
| <samp>Action None</samp>
+
| Get whether the building has an interior location.
| Does nothing. This is used to mark the tile interactive if the click will be handled separately.
   
|-
 
|-
| <samp>Buildings</samp>
+
| <samp>GetIndoors</samp>
| <samp>Action ObeliskWarp {{t|location name}} {{t|x}} {{t|y}} {{o|whether to dismount}}</samp>
+
| Get the location within this building, if applicable.
| Warps the player to the specified location name and position with the [[Warp Totem|Obelisk]] animation/sound effects.
   
|-
 
|-
| <samp>Buildings</samp>
+
| <samp>HasIndoorsName</samp>
| <samp>Action OpenShop {{t|shop id}} {{o|from direction}} {{o|open time}} {{o|close time}} {{o|owner tile area}}</samp>
+
| Get whether the building has an interior location and its unique name matches the given value (like <code>building.HasIndoorsName("FarmHouse")</code>).
| Open the [[#Custom shops|shop]] with the given {{t|shop id}}. All arguments besides the ID are optional:
  −
* {{o|from direction}}: if specified, the player must be standing in this direction relative to the shop (one of <samp>down</samp>, <samp>up</samp>, <samp>left</samp>, <samp>right</samp>, or <samp>none</samp>). Setting this to <samp>none</samp> disables the requirement. The default for most vanilla shops is <samp>down</samp>.
  −
* {{o|open time}} and {{o|close time}}: the start & end times in 26-hour format when the shop is available. Interacting with the tile outside those times does nothing.
  −
* {{o|owner tile area}}: if specified, the tile area which must contain one of the shop owners for the shop to be available. For a custom shop, these are defined by its <samp>Owners</samp> field. This can be specified in two forms: <samp>{{t|x}} {{t|y}}</samp> for a single tile, or <samp>{{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp> for a multi-tile area.
   
|-
 
|-
| <samp>Buildings</samp>
+
| <samp>GetIndoorsName</samp>
| <samp>Action PlayEvent {{t|event id}} {{o|check preconditions}} {{o|skip if seen}} {{o|fallback action}}</samp>
+
| Get the unique name of the location within this building, if applicable.
| Immediately start an [[Modding:Event data|event]], subject to the conditions:
  −
* {{o|check preconditions}}: whether to ignore the action if the [[Modding:Event data#Event preconditions|event's preconditions]] don't match (one of <samp>true</samp> or <samp>false</samp>). Default true.
  −
* {{o|skip if seen}}: whether to ignore the action if the player has already seen the given event. Default true.
  −
 
  −
If the event doesn't start for any reason (including the preceding conditions):
  −
* If {{o|fallback action}} is specified, it'll be run as an action. This can be any <samp>Action</samp> tile property (without the "Action " prefix), like <code>Action PlayEvent 60367 true true PlayEvent 520702 false false</code> to play a different event.
  −
* Otherwise the action is silently ignored.
  −
 
  −
For example, <code>Action PlayEvent 60367 false false</code> will replay the bus arrival event from the start of the game.
  −
|}
  −
</li>
  −
<li>Added new <samp>TouchAction</samp> [[Modding:Maps|tile properties]]:
  −
{| class="wikitable"
   
|-
 
|-
! layer
+
| ...
! property
+
| ''see also [[#Other building changes|other building changes]] for non-location methods.''
! explanation
   
|-
 
|-
| <samp>Back</samp>
+
|rowspan="7"|<samp>Cabin</samp><br /><samp>FarmHouse</samp>
| <samp>TouchAction PlayEvent {{t|event id}} {{o|check preconditions}} {{o|skip if seen}} {{o|fallback action}}</samp>
+
| <samp>GetCellar</samp>
| Equivalent to <samp>Action PlayEvent</samp>, but activated on touch. Note that {{o|fallback action}} is an <samp>Action</samp> tile property, ''not'' a <samp>TouchAction</samp> tile property.
+
| Get the [[cellar]] location linked to this cabin, if any.
|}</li>
  −
<li>Changed existing tile properties:
  −
{| class="wikitable"
   
|-
 
|-
! layer
+
| <samp>CanAssignFarmhand</samp><br /><samp>AssignFarmhand</samp>
! property
+
| ''(Cabin only)'' Check whether the cabin is available to assign to a farmhand, or perform the assignment.
! reason
   
|-
 
|-
|rowspan="4"| <samp>Back</samp>
+
| <samp>HasOwner</samp>
| <samp>NoSpawn</samp>
+
| Get whether the home has an assigned player, regardless of whether they've finished creating their character.
| Added <samp>NoSpawn false</samp> form, which disables any previous <samp>NoSpawn</samp> property on the tile. For example, this can be used to enable spawning on a tile which has a <samp>NoSpawn</samp> tile index property.
   
|-
 
|-
| <samp>TouchAction Bus</samp>
+
| <samp>OwnerId</samp>
| Removed. This wasn't used by the game or mods.
+
| Get the unique ID of the player who owns this home, if any.
 
|-
 
|-
| <samp>TouchAction Emote</samp>
+
| <samp>IsOwnedByCurrentPlayer</samp>
| Fixed error if the specified NPC isn't found.
+
| Get whether the cabin belongs to the current player.
 
|-
 
|-
| <samp>Treasure</samp>
+
| <samp>IsOwnerActivated</samp>
| Added <samp>Treasure Item {{t|item ID}}</samp> form which accepts a [[#Custom items|qualified or unqualified item ID]].
+
| Get whether the home has an assigned player and they've finished creating their character.
 
|-
 
|-
|rowspan="2"| <samp>Buildings</samp>
+
| <samp>HasNpcSpouse</samp>
| <samp>Action ItemChest</samp><br /><samp>Action Minecart</samp><br /><samp>Action RemoveChest</samp>
+
| Get whether the player who owns this home is married to any NPC (when used like <samp>HasNpcSpouse()</samp>) or a specific NPC (like <samp>HasNpcSpouse(name)</samp>). This also replaces <samp>shouldShowSpouseRoom()</samp>.
| Removed. These weren't used by the game or mods.
   
|-
 
|-
| <samp>Action Kitchen</samp>
+
|rowspan="2"| <samp>Farm</samp>
| Now works in any location (including those without a fridge).
+
| <samp>GetStarterFarmhouseLocation</samp>
|}
+
| Get the default tile position for the farmhouse. (See also <samp>farm.GetMainFarmHouseEntry()</samp>.)
</li>
+
|-
</ul>
+
| <samp>GetStarterPetBowlLocation</samp>
 +
| Get the default tile position for the pet bowl.
 +
|-
 +
|rowspan="19"| <samp>GameLocation</samp>
 +
| <samp>AddDefaultBuildings</samp>
 +
| Can be overridden to add custom buildings when the location is created and/or loaded. These can either be re-added whenever they're missing (like the vanilla farmhouse), or only built once on save creation (like the vanilla pre-built cabins).
   −
===Other location/map changes===
+
This replaces the former <samp>farm.AddModularShippingBin()</samp> method.
* Farm data:
  −
** Added <samp>SpawnMonstersByDefault</samp> field to <samp>Data/AdditionalFarms</samp> to set the default value of the 'spawn monsters at night' [[Options#Advanced Game Options|advanced save option]].
  −
** Fixed crash on new-save screen if the farm type's tooltip has no description.
  −
* General location data:
  −
** All locations can now have animals. The <samp>IAnimalLocation</samp> is now obsolete and implemented by <samp>GameLocation</samp>.
  −
** Added new [[Modding:Fish data|fishing areas]] to simplify compatibility between fish & map mods (specifically for hilltop farm, wilderness farm, town, and desert).
  −
** Added a descriptive error when a required location or layer isn't found. Mods can use <samp>map.RequireLayer</samp> and <samp>Game1.RequireLocation</samp> to get a location with similar error-checking.
  −
** Added <samp>WarpPathfindingCache</samp> for C# mods, which modularizes the NPC warp route logic. You can edit its <samp>IgnoreLocationNames</samp>, <samp>OverrideTargetNames</samp>, and <samp>GenderRestrictions</samp> fields if needed for custom locations.
  −
** Game logic which checks tile indexes is now more fault-tolerant, so it won't crash if an expected tile was edited.
  −
** Finished migrating <samp>DecoratableLocation</samp> flooring/wallpaper areas to string IDs (started in Stardew Valley 1.5.5).
  −
* General map changes:
  −
** Added validation for [[Modding:Maps|map properties and tile properties]]. If the format is invalid, the game will now log a detailed error and skip it.
  −
** Removed unused [[Modding:Maps#Paths layer|path tiles]] in <samp>Maps/paths</samp> and all map files.
  −
* Location context data:
  −
** Building interiors now inherit their parent's location context by default.
  −
** Added <samp>Game1.locationContextData</samp> to cache the data from <samp>Data/LocationContexts</samp>.
  −
** Added constants for the vanilla context IDs like <samp>LocationContexts.IslandId</samp>.
  −
** Added validation for required location context IDs (and <samp>LocationContexts.Require(id)</samp> for mod logic).
  −
** Removed the <samp>Name</samp> field in <samp>Data/LocationContexts</samp>, which duplicated the ID.
  −
<ul>
  −
<li>Added methods to simplify common operations:
  −
{| class="wikitable"
   
|-
 
|-
! type
+
| <samp>GetFridge</samp><br /><samp>GetFridgePosition</samp>
! method
+
| Get the fridge's chest or tile position, if the location has one.
! effect
   
|-
 
|-
|rowspan="7"| <samp>Building</samp>
+
| <samp>GetSeason</samp><br /><samp>GetSeasonIndex</samp><br /><samp>GetSeasonKey</samp>
| <samp>GetParentLocation</samp>
+
| Get the local season that applies within the location as an enum, number (like <samp>0</samp> for spring), or string (like <samp>spring</samp>) respectively. For example, it's always summer on [[Ginger Island]].
| Get the location which contains this building.
   
|-
 
|-
| <samp>IsInCurrentLocation</samp>
+
| <samp>GetWeather</samp><br /><samp>IsDebrisWeatherHere</samp><br /><samp>IsLightningHere</samp><br /><samp>IsRainingHere</samp><br /><samp>IsSnowingHere</samp>
| Get whether the building is in the same location as the current player.
+
| Get the current weather in this location's context, regardless of whether the player is indoors and sheltered from it.
 
|-
 
|-
| <samp>HasIndoors</samp>
+
| <samp>InDesertContext</samp><br /><samp>InIslandContext</samp><br /><samp>InValleyContext</samp>
| Get whether the building has an interior location.
+
| Get whether this location is within the <samp>Island</samp> or <samp>Default</samp> location context respectively.
|-
  −
| <samp>GetIndoors</samp>
  −
| Get the location within this building, if applicable.
  −
|-
  −
| <samp>HasIndoorsName</samp>
  −
| Get whether the building has an interior location and its unique name matches the given value (like <code>building.HasIndoorsName("FarmHouse")</code>).
  −
|-
  −
| <samp>GetIndoorsName</samp>
  −
| Get the unique name of the location within this building, if applicable.
  −
|-
  −
| ...
  −
| ''see also [[#Other building changes|other building changes]] for non-location methods.''
  −
|-
  −
|rowspan="7"|<samp>Cabin</samp><br /><samp>FarmHouse</samp>
  −
| <samp>GetCellar</samp>
  −
| Get the [[cellar]] location linked to this cabin, if any.
  −
|-
  −
| <samp>CanAssignFarmhand</samp><br /><samp>AssignFarmhand</samp>
  −
| ''(Cabin only)'' Check whether the cabin is available to assign to a farmhand, or perform the assignment.
  −
|-
  −
| <samp>HasOwner</samp>
  −
| Get whether the home has an assigned player, regardless of whether they've finished creating their character.
  −
|-
  −
| <samp>OwnerId</samp>
  −
| Get the unique ID of the player who owns this home, if any.
  −
|-
  −
| <samp>IsOwnedByCurrentPlayer</samp>
  −
| Get whether the cabin belongs to the current player.
  −
|-
  −
| <samp>IsOwnerActivated</samp>
  −
| Get whether the home has an assigned player and they've finished creating their character.
  −
|-
  −
| <samp>HasNpcSpouse</samp>
  −
| Get whether the player who owns this home is married to any NPC (when used like <samp>HasNpcSpouse()</samp>) or a specific NPC (like <samp>HasNpcSpouse(name)</samp>). This also replaces <samp>shouldShowSpouseRoom()</samp>.
  −
|-
  −
|rowspan="2"| <samp>Farm</samp>
  −
| <samp>GetStarterFarmhouseLocation</samp>
  −
| Get the default tile position for the farmhouse. (See also <samp>farm.GetMainFarmHouseEntry()</samp>.)
  −
|-
  −
| <samp>GetStarterPetBowlLocation</samp>
  −
| Get the default tile position for the pet bowl.
  −
|-
  −
|rowspan="19"| <samp>GameLocation</samp>
  −
| <samp>AddDefaultBuildings</samp>
  −
| Can be overridden to add custom buildings when the location is created and/or loaded. These can either be re-added whenever they're missing (like the vanilla farmhouse), or only built once on save creation (like the vanilla pre-built cabins).
  −
 
  −
This replaces the former <samp>farm.AddModularShippingBin()</samp> method.
  −
|-
  −
| <samp>GetFridge</samp><br /><samp>GetFridgePosition</samp>
  −
| Get the fridge's chest or tile position, if the location has one.
  −
|-
  −
| <samp>GetSeason</samp><br /><samp>GetSeasonIndex</samp><br /><samp>GetSeasonKey</samp>
  −
| Get the local season that applies within the location as an enum, number (like <samp>0</samp> for spring), or string (like <samp>spring</samp>) respectively. For example, it's always summer on [[Ginger Island]].
  −
|-
  −
| <samp>GetWeather</samp><br /><samp>IsDebrisWeatherHere</samp><br /><samp>IsLightningHere</samp><br /><samp>IsRainingHere</samp><br /><samp>IsSnowingHere</samp>
  −
| Get the current weather in this location's context, regardless of whether the player is indoors and sheltered from it.
  −
|-
  −
| <samp>InDesertContext</samp><br /><samp>InIslandContext</samp><br /><samp>InValleyContext</samp>
  −
| Get whether this location is within the <samp>Island</samp> or <samp>Default</samp> location context respectively.
   
|-
 
|-
 
| <samp>IsActiveLocation</samp>
 
| <samp>IsActiveLocation</samp>
Line 3,755: Line 3,722:  
|-
 
|-
 
| <samp>TryGetMapPropertyAs</samp>
 
| <samp>TryGetMapPropertyAs</samp>
| Get a map property and parse it into into a <samp>bool</samp>, <samp>Point</samp>, <samp>Rectangle</samp>, or <samp>Vector2</samp> value.
+
| Get a map property and parse it into into a <samp>bool</samp>, <samp>double</samp>, <samp>Point</samp>, <samp>Rectangle</samp>, or <samp>Vector2</samp> value.
    
For example:
 
For example:
Line 3,814: Line 3,781:  
==What's new for buildings==
 
==What's new for buildings==
 
===Custom buildings===
 
===Custom buildings===
 +
{{/doc status|[[Modding:Blueprint data]]|done=false}}
 +
 
You can now add custom buildings by editing the <samp>Data/Buildings</samp> asset. This consists of a string → model lookup, where...
 
You can now add custom buildings by editing the <samp>Data/Buildings</samp> asset. This consists of a string → model lookup, where...
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the building type.
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the building type.
 
* The value is a model with the fields listed below.
 
* The value is a model with the fields listed below.
   Line 3,851: Line 3,820:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| ''(Optional)'' The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list. Defaults to the <samp>ItemId</samp> if not specified.
+
| ''(Optional)'' The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list. Defaults to the <samp>ItemId</samp> if not specified.
 
|-
 
|-
 
| <samp>ItemId</samp>
 
| <samp>ItemId</samp>
Line 3,891: Line 3,860:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>ItemId</samp>
 
| <samp>ItemId</samp>
Line 3,927: Line 3,896:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>Source</samp>
 
| <samp>Source</samp>
Line 4,004: Line 3,973:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the skin.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for the skin.
 
|-
 
|-
 
| <samp>Name</samp><br /><samp>Description</samp>
 
| <samp>Name</samp><br /><samp>Description</samp>
Line 4,045: Line 4,014:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>SourceRect</samp>
 
| <samp>SourceRect</samp>
Line 4,138: Line 4,107:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this rule within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this rule within the current list.
 
|-
 
|-
 
| <samp>RequiredTags</samp>
 
| <samp>RequiredTags</samp>
Line 4,157: Line 4,126:  
|-
 
|-
 
| ''common fields''
 
| ''common fields''
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported by machine output.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported by machine output.
   −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
 
| <samp>Chance</samp>
 
| <samp>Chance</samp>
Line 4,180: Line 4,149:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this chest within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this chest within the current list.
    
This is referenced from the <samp>ItemConversions</samp> field.
 
This is referenced from the <samp>ItemConversions</samp> field.
Line 4,225: Line 4,194:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>Tile</samp>
 
| <samp>Tile</samp>
Line 4,245: Line 4,214:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>Name</samp>
 
| <samp>Name</samp>
Line 4,301: Line 4,270:     
===Build anywhere===
 
===Build anywhere===
Buildings and animals are no longer hardcoded to the [[The Farm|farm]] location (except [[cabin]]s and the [[farmhouse]] which still are). You can allow building construction for any location using the [[#Map/tile property changes|new <samp>CanBuildHere</samp> and related map properties]]. The game will adjust accordingly (e.g. Robin will let you choose where to construct the building).
+
{{/doc status|[[Modding:Blueprint data]] and [[Modding:Maps]]|done=false}}
 +
 
 +
* You can now allow building construction for any location using the [[#Map/tile property changes|new <samp>CanBuildHere</samp> and related map properties]]. The game will adjust accordingly (e.g. Robin will let you choose where to construct the building).
 +
* Buildings and animals are no longer hardcoded to the [[The Farm|farm]] location (except [[cabin]]s and the [[farmhouse]] which still are).
 +
* Scything hay will now add hay to silos in any location, and animals will be auto-fed from hay in any location.
    
===Other building changes===
 
===Other building changes===
 +
{{/doc status|[[Modding:Blueprint data]]|done=false}}
 +
 
: ''See also: [[#Other location/map changes|other location changes]] for location-related building changes.''
 
: ''See also: [[#Other location/map changes|other location changes]] for location-related building changes.''
   Line 4,380: Line 4,355:  
|}
 
|}
 
</li>
 
</li>
 +
<li>In <samp>Data/FishPondData</samp>, the reward <samp>ItemId</samp> can now be an [[Modding:Item queries|item query]].</li>
 
<li>[[Legendary Fish|Legendary fish]] can now be added to [[Fish Pond|fish ponds]] if they have an entry in <samp>Data/FishPondData</samp>.</li>
 
<li>[[Legendary Fish|Legendary fish]] can now be added to [[Fish Pond|fish ponds]] if they have an entry in <samp>Data/FishPondData</samp>.</li>
 
</ul>
 
</ul>
Line 4,385: Line 4,361:  
==What's new for NPCs==
 
==What's new for NPCs==
 
===Custom NPCs===
 
===Custom NPCs===
 +
{{/doc status|[[Modding:NPC data]]|done=false}}
 +
 
[[Modding:NPC data|Custom NPC data]] has been overhauled in 1.6. The new <samp>Data/Characters</samp> asset (which replaces <samp>Data/NPCDispositions</samp> + <samp>Data/spousePatios</samp> + <samp>Data/spouseRooms</samp>) uses a data model format that's easier to edit and understand, and has a lot of fields to customize previously-hardcoded data.
 
[[Modding:NPC data|Custom NPC data]] has been overhauled in 1.6. The new <samp>Data/Characters</samp> asset (which replaces <samp>Data/NPCDispositions</samp> + <samp>Data/spousePatios</samp> + <samp>Data/spouseRooms</samp>) uses a data model format that's easier to edit and understand, and has a lot of fields to customize previously-hardcoded data.
    
====Format====
 
====Format====
 
This consists of a string → model lookup, where...
 
This consists of a string → model lookup, where...
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the NPC like <samp>Example.ModId_NpcName</samp>, which will be used as the internal <samp>Name</samp> (not <samp>DisplayName</samp>).
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the NPC like <samp>Example.ModId_NpcName</samp>, which will be used as the internal <samp>Name</samp> (not <samp>DisplayName</samp>).
 
* The value is a model with the following fields.
 
* The value is a model with the following fields.
   Line 4,512: Line 4,490:  
Defaults to <samp>UnknownUntilMet</samp>.
 
Defaults to <samp>UnknownUntilMet</samp>.
 
|-
 
|-
| <samp>SocialTabIconSourceRect</samp>
+
| <samp>SpouseAdopts</samp>
| ''(Optional)'' The pixel area in the character's sprite texture to show as their icon in the social menu. This should be approximately 24x24 pixels or smaller. Defaults to part of their first sprite.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the player will need to adopt children with this spouse, instead of either the player or NPC giving birth. If null, defaults to true for same-gender and false for opposite-gender spouses.
 +
 
 +
The <samp>Target</samp> player is the one they're married to.
 +
|-
 +
| <samp>SpouseWantsChildren</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the spouse will ask to have children. Defaults to true.
 +
 
 +
The <samp>Target</samp> player is the one they're married to.
 +
|-
 +
| <samp>SpouseGiftJealousy</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the [[Marriage#Jealousy|spouse will get jealous of gifts to other NPCs]]. Defaults to true.
 +
 
 +
The <samp>Target</samp> player is the one they're married to, and the <samp>Target</samp> item is the one that was gifted.
 +
|-
 +
| <samp>SpouseGiftJealousyFriendshipChange</samp>
 +
| ''(Optional)'' The [[Friendship|friendship point]] effect when the <samp>SpouseGiftJealously</samp> is triggered. Default -30.
 
|-
 
|-
 
| <samp>SpouseRoom</samp>
 
| <samp>SpouseRoom</samp>
Line 4,604: Line 4,597:  
|}
 
|}
 
</dd>
 
</dd>
 +
 +
<dt>Dumpster diving:</dt>
 +
<dd>
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>DumpsterDiveEmote</samp>
 +
| ''(Optional)'' The emote ID to show above the NPC's head when they see a player rummaging through trash. See [[Modding:event data#Emotes|emote IDs]]. If omitted or <samp>null</samp>, the default depends on the NPC's age: a child will show sad (28), a teen will show a question mark (8), and an adult will show angry (12).
 +
|-
 +
| <samp>DumpsterDiveFriendshipEffect</samp>
 +
| ''(Optional)'' The friendship point change if this NPC sees a player rummaging through trash. Default -25.
 +
|}</dd>
    
<dt>Festivals:</dt>
 
<dt>Festivals:</dt>
Line 4,611: Line 4,618:  
! field
 
! field
 
! effect
 
! effect
 +
|-
 +
| <samp>FlowerDanceCanDance</samp>
 +
| ''(Optional)'' Whether players can ask the NPC to dance at the Flower Dance festival. The possible values are <samp>true</samp> (can always ask), <samp>false</samp> (can never ask), or <samp>null</samp> (can ask if they're romanceable). Default <samp>null</samp>.
 +
 +
If the NPC can dance, you should also add the [[Modding:NPC data#Overworld_sprites|dance sprite frames]] and <samp>FlowerDance_Decline</samp> [[Modding:Dialogue|dialogue text]]. You can optionally set the <samp>FlowerDance_Accept</samp> dialogue too (though NPCs have a default accept dialogue if not).
 
|-
 
|-
 
| <samp>WinterStarParticipant</samp>
 
| <samp>WinterStarParticipant</samp>
Line 4,625: Line 4,637:  
|-
 
|-
 
| ''common fields''
 
| ''common fields''
| See [[#Item spawn fields|item spawn fields]] for the generic item fields.
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields.
   −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|}
 
|}
 
|}
 
|}
Line 4,654: Line 4,666:  
|-
 
|-
 
| <samp>ID</samp>
 
| <samp>ID</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>Location</samp>
 
| <samp>Location</samp>
Line 4,695: Line 4,707:  
|-
 
|-
 
| <samp>Id</samp>
 
| <samp>Id</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry within the current list.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 
|-
 
|-
 
| <samp>Season</samp>
 
| <samp>Season</samp>
Line 4,724: Line 4,736:     
'''Note:''' the default textures based on <samp>TextureName</samp> must still exist, even if you use this field to override them.
 
'''Note:''' the default textures based on <samp>TextureName</samp> must still exist, even if you use this field to override them.
 +
|-
 +
| <samp>MugShotSourceRect</samp>
 +
| ''(Optional)'' The 16x24-pixel area in the character's sprite texture to show as their mug shot icon in the calendar, social menu, and other contexts. Defaults to part of their first sprite.
 
|-
 
|-
 
| <samp>Size</samp>
 
| <samp>Size</samp>
Line 4,732: Line 4,747:  
| <samp>Breather</samp>
 
| <samp>Breather</samp>
 
| ''(Optional)'' Whether the chest on the NPC's overworld sprite puffs in and out as they breathe. Default true</samp>.
 
| ''(Optional)'' Whether the chest on the NPC's overworld sprite puffs in and out as they breathe. Default true</samp>.
 +
|-
 +
| <samp>BreathChestRect</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Rectangle|rectangle]] pixel area within the spritesheet which expands and contracts to simulate breathing, relative to the top-left corner of the source rectangle for their current sprite. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
 +
|-
 +
| <samp>BreathChestPosition</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset to apply to the NPC's <samp>BreathChestPosition</samp> when drawn over the NPC. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
 +
|-
 +
| <samp>Shadow</samp>
 +
| ''(Optional)'' The options for the shadow to draw under the NPC, or omit to apply the default shadow behavior.
 +
 +
This consists of a model with these fields:
 +
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>Visible</samp>
 +
| ''(Optional)'' Whether the shadow should be drawn. Default true.
 +
|-
 +
| <samp>Offset</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset applied to the shadow position. Default zero.
 +
|-
 +
| <samp>Scale</samp>
 +
| ''(Optional)'' The scale at which to draw the shadow. Default 1.
 +
 +
This is a multiplier applied to the default shadow scale, which can change based on factors like whether the NPC is jumping. For example, <samp>0.5</samp> means half the size it'd be drawn if you didn't specify a scale.
 +
|}
 +
|-
 +
| <samp>EmoteOffset</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset applied to emote drawn over the NPC. Default zero.
 
|-
 
|-
 
| <samp>ShakePortraits</samp>
 
| <samp>ShakePortraits</samp>
Line 4,778: Line 4,824:  
! field
 
! field
 
! effect
 
! effect
 +
|-
 +
| <samp>CustomFields</samp>
 +
| The [[#Custom data fields|custom fields]] for this entry.
 +
|-
 +
| <samp>FormerCharacterNames</samp>
 +
| ''(Optional)'' The former NPC names which may appear in save data. If matched, the game will rename the NPC and update related data (e.g. friendship).
 +
 +
A former name is only applied if:
 +
# it doesn't match a current ID in <samp>Data/Characters</samp>;
 +
# the save has an NPC with the former name;
 +
# the save doesn't already have an NPC with the new name.
 +
 +
For example:
 +
<syntaxhighlight lang="js">
 +
"FormerCharacterNames": [ "SomeOldName" ]
 +
</syntaxhighlight>
 +
 +
Former names can have any format, but they must be '''globally''' unique. They can't match the ID or <samp>FormerCharacterNames</samp> of any other NPC in <samp>Data/Characters</samp> (whether vanilla or custom).
 
|-
 
|-
 
| <samp>FestivalVanillaActorIndex</samp>
 
| <samp>FestivalVanillaActorIndex</samp>
 
| ''(Optional, Specialized)'' The NPC's index in the <samp>Maps/characterSheet</samp> tilesheet, if applicable. This is used for placing vanilla NPCs in festivals from the map; custom NPCs should use the <samp>&lt;layer&gt;_additionalCharacters</samp> field in the festival data instead.
 
| ''(Optional, Specialized)'' The NPC's index in the <samp>Maps/characterSheet</samp> tilesheet, if applicable. This is used for placing vanilla NPCs in festivals from the map; custom NPCs should use the <samp>&lt;layer&gt;_additionalCharacters</samp> field in the festival data instead.
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
   
|}
 
|}
 
</dd>
 
</dd>
Line 4,799: Line 4,860:  
             "Target": "Data/Characters",
 
             "Target": "Data/Characters",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Amabel": {
+
                 "{{ModId}}_Amabel": {
 
                     "DisplayName": "Amabel", // this would normally use {{i18n:}} to support translations
 
                     "DisplayName": "Amabel", // this would normally use {{i18n:}} to support translations
 
                     "BirthSeason": "Fall",
 
                     "BirthSeason": "Fall",
Line 4,836: Line 4,897:  
             "Target": "Data/Characters",
 
             "Target": "Data/Characters",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Belwick": {
+
                 "{{ModId}}_Belwick": {
 
                     "DisplayName": "Belwick", // this would normally use {{i18n:}} to support translations
 
                     "DisplayName": "Belwick", // this would normally use {{i18n:}} to support translations
   Line 4,851: Line 4,912:     
===Custom NPC appearance===
 
===Custom NPC appearance===
 +
{{/doc status|[[Modding:NPC data]]|done=false}}
 +
 
Each NPC can now have any number of custom portraits/sprites in <samp>Data/Characters</samp> with arbitrary conditions. This lets mods add features like indoor/outdoor outfits without the performance impact of reloading textures. If multiple outfits apply, the game will choose between them with a day-stable randomization.
 
Each NPC can now have any number of custom portraits/sprites in <samp>Data/Characters</samp> with arbitrary conditions. This lets mods add features like indoor/outdoor outfits without the performance impact of reloading textures. If multiple outfits apply, the game will choose between them with a day-stable randomization.
   Line 4,900: Line 4,963:     
===Custom farm animals===
 
===Custom farm animals===
You can now create and customize [[Animals|farm animals]] by editing the revamped <samp>Data/FarmAnimals</samp> asset.
+
{{/doc status|[[Modding:Animal data]]|done=true}}
   −
This consists of a string → model lookup, where...
+
You can now create and edit [[Animals|farm animals]] by editing the revamped <samp>Data/FarmAnimals</samp> asset. This changes to a data model, adds built-in support for custom animals, and allows far more customizability per animal (like its size, growth, produce, appearance and sounds, etc).
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the farm animal type.
  −
* The value is a model with the fields listed below.
     −
====Main info====
+
===Custom pets===
{| class="wikitable"
+
{{/doc status|a new doc page|done=false}}
 +
 
 +
====Format====
 +
You can now create and customize [[Animals#Cat or Dog|pet]]s & pet breeds by editing the new <samp>Data/Pets</samp> asset.
 +
 
 +
This consists of a string → model lookup, where...
 +
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the pet (not the pet breed). The vanilla IDs are <samp>Cat</samp> and <samp>Dog</samp>.
 +
* The value is a model with the fields listed below.
 +
 
 +
=====Basic info=====
 +
{| class="wikitable"
 
|-
 
|-
 
! field
 
! field
Line 4,913: Line 4,984:  
|-
 
|-
 
| <samp>DisplayName</samp>
 
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the animal type's display name.
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the pet type's display name (e.g. "cat" or "dog"). For example, the vanilla adoption events show this when Marnie asks if you want to adopt the cat/dog.
|-
+
|}
| <samp>House</samp>
  −
| The [[#Custom buildings|building ID]] for the main building type that houses this animal. The animal will also be placeable in buildings whose <samp>ValidOccupantTypes</samp> field contains this value.
  −
|-
  −
| <samp>Gender</samp>
  −
| ''(Optional)'' The possible genders for the animal type. Currently this only affects the text shown after purchasing the animal, like "''Great! I'll send little &lt;name&gt; to [his/her] new home right away''". Default <samp>Female</samp>.
     −
The possible values are:
+
=====Audio & sprites=====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! value
+
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>Male</samp><br /><samp>Female</samp>
+
| <samp>BarkSound</samp>
| Farm animals of this type are always male or always female.
+
| The [[#Custom audio|cue ID]] for the pet's occasional 'bark' sound.
 +
|-
 +
| <samp>ContentSound</samp>
 +
| The [[#Custom audio|cue ID]] for the sound which the pet makes when you pet it.
 +
|-
 +
| <samp>RepeatContentSoundAfter</samp>
 +
| ''(Optional)'' The number of milliseconds until the <samp>ContentSound</samp> is repeated once. This is used by the dog, who pants twice when pet. Defaults to -1 (disabled).
 
|-
 
|-
| <samp>MaleOrFemale</samp>
+
| <samp>EmoteOffset</samp>
| The gender of each animal is randomized based on its internal unique ID.
+
| ''(Optional)'' A pixel offset for the emote drawn above the pet sprite, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. For example, this affects the heart emote shown after petting it. Default none.
|}
   
|}
 
|}
   −
====Animal shop====
+
=====Events=====
These fields affect how this farm animal type is shown in [[Marnie's Ranch|Marnie's animal shop]]. Animals are automatically listed if they have a valid <samp>PurchasePrice</samp> value.
  −
 
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 4,943: Line 5,012:  
! effect
 
! effect
 
|-
 
|-
| <samp>PurchasePrice</samp>
+
| <samp>EventOffset</samp>
| ''(Optional if not purchaseable)'' Half the cost to purchase the animal (the actual price is double this value), or a negative value to disable purchasing this animal type. Default -1.
+
| ''(Optional)'' The pixel offset for the pet when shown in events like Marnie's adoption event, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. Default none.
 
|-
 
|-
| <samp>ShopTexture</samp>
+
| <samp>AdoptionEventLocation</samp><br /><samp>AdoptionEventId</samp>
| ''(Optional if not purchaseable)'' The asset name for the icon texture to show in shops. Defaults to <samp>LooseSprites/Cursors</samp> or <samp>LooseSprites/Cursors2</samp> based on the animal's position within the loaded data (but using the default isn't recommended if it's purchaseable).
+
| ''(Optional)'' If both fields are set, the location and [[Modding:Event data|event ID]] which lets the player adopt this pet. This forces the event to play after 20 days if its preconditions haven't been met yet. Default <samp>Farm</samp> and none respectively.
 
|-
 
|-
| <samp>ShopSourceRect</samp>
+
| <samp>SummitPerfectionEvent</samp>
| ''(Optional if not purchaseable)'' The pixel area within the <samp>ShopTexture</samp> to draw, specified as an object with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields. This should be 32 pixels wide and 16 high. Ignored if <samp>ShopTexture</samp> isn't set.
+
| ''(Optional)'' How to render the pet during the summit [[perfection]] slideshow. If this isn't set, the pet won't be shown in the slideshow.
 +
 
 +
This consists of a model with these fields:
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <samp>RequiredBuilding</samp>
+
! field
| ''(Optional)'' The building that needs to be built on the farm for this animal to be available to purchase. Buildings that are upgraded from this building are valid too. Default none.
+
! effect
 
|-
 
|-
| <samp>UnlockCondition</samp>
+
| <samp>SourceRect</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the farm animal is available in the shop menu. Default always unlocked.
+
| The source rectangle within the pet's texture to draw.
 
|-
 
|-
| <samp>ShopDisplayName</samp>
+
| <samp>AnimationLength</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the display name shown in the shop menu. Defaults to the <samp>DisplayName</samp> field.
+
| The number of frames to show starting from the <samp>SourceRect</samp>.
 
|-
 
|-
| <samp>ShopDescription</samp>
+
| <samp>Motion</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the tooltip description shown in the shop menu. Defaults to none.
+
| The motion to apply to the pet sprite.
 
|-
 
|-
| <samp>ShopMissingBuildingDescription</samp>
+
| <samp>Flipped</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] which overrides <samp>ShopDescription</samp> if the <samp>RequiredBuilding</samp> isn't built. Defaults to none.
+
| ''(Optional)'' Whether to flip the pet sprite left-to-right. Default false.
 
|-
 
|-
| <samp>AlternatePurchaseTypes</samp>
+
| <samp>PingPong</samp>
| ''(Optional)'' The possible variants for this farm animal (e.g. chickens can be Brown Chicken, Blue Chicken, or White Chicken). This consists of a list of models with these fields:
+
| ''(Optional)'' Whether to apply the 'ping pong' effect to the pet sprite animation. Default false.
 +
|}
 +
|}
 +
 
 +
=====Gifts=====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 4,974: Line 5,051:  
! effect
 
! effect
 
|-
 
|-
| <samp>AnimalIDs</samp>
+
| <samp>GiftChance</samp>
| A list of animal IDs to spawn instead of the main <samp>ID</samp> field. If multiple are listed, one is chosen at random on purchase.
+
| ''(Optional)'' The random probability each day that the pet will give the player a gift from the <samp>Gifts</samp> list when they interact with the pet. Specified as a value between 0 (never) and 1 (always). Default .2 (20% chance).
 
|-
 
|-
| <samp>Condition</samp>
+
| <samp>Gifts</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this variant entry is available. Default always enabled.
+
| ''(Optional)'' The list of gifts that this pet can give if the <samp>GiftChance</samp> is successful. Default none.
|}
+
 
 
+
This consists of a list of models with these fields:
If multiple are listed, the first available variant is returned. Default none.
  −
|}
     −
====Hatching====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 4,990: Line 5,064:  
! effect
 
! effect
 
|-
 
|-
| <samp>EggItemIds</samp>
+
| <samp>Id</samp>
| ''(Optional)'' A list of the [[#Custom items|object IDs]] that can be placed in the [[incubator]] or [[Ostrich Incubator|ostrich incubator]] to hatch this animal. If the animal's <samp>House</samp> field doesn't match the current building, the entry will be ignored. Default none.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
 
|-
 
|-
| <samp>IncubationTime</samp>
+
| <samp>QualifiedItemID</samp>
| ''(Optional)'' How long eggs incubate before they hatch. Default 9000 minutes.
+
| The [[Modding:Common data field types#Item ID|qualified item ID]] for the gift item to create.
 
|-
 
|-
| <samp>IncubatorParentSheetOffset</samp>
+
| <samp>Stack</samp>
| ''(Optional)'' An offset applied to the incubator's sprite index when it's holding an egg. Default 1.
+
| ''(Optional)'' The stack size of the gift item to produce. Default 1.
 
  −
The vanilla values are:
  −
{| class="wikitable"
   
|-
 
|-
! offset
+
| <samp>MinimumFriendshipThreshold</samp>
! [[incubator]]
+
| ''(Optional)'' The friendship level that this pet must be at before it can give this gift. Defaults to 1000 (max friendship).
! [[Ostrich Incubator|ostrich incubator]]
   
|-
 
|-
| 0
+
| <samp>Weight</samp>
| empty incubator
+
| ''(Optional)'' The option's weight when randomly choosing a gift, relative to other gifts in the list (e.g. <samp>2</samp> is twice as likely as <samp>1</samp>). Default 1.
| empty incubator
  −
|-
  −
| 1
  −
| small white egg
  −
| large brown egg
  −
|-
  −
| 2
  −
| small brown egg
  −
| ''invalid'' (will show [[Junimo Chest|Junimo chest]] sprite)
   
|}
 
|}
|-
  −
| <samp>BirthText</samp>
  −
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the message shown when entering the building after the egg hatched. Defaults to the text "<samp>???</samp>".
   
|}
 
|}
   −
====Growth====
+
=====Behavior=====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,029: Line 5,087:  
! effect
 
! effect
 
|-
 
|-
| <samp>DaysToMature</samp>
+
| <samp>Id</samp>
| ''(Optional)'' The number of days until a freshly purchased/born animal becomes an adult and begins producing items. Default 1.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the list.
 +
|-
 +
| <samp>MoveSpeed</samp>
 +
| ''(Optional)'' How quickly the pet can move. Default 2.
 +
|-
 +
| <samp>SleepOnBedChance</samp><br /><samp>SleepNearBedChance</samp><br /><samp>SleepOnRugChance</samp>
 +
| ''(Optional)'' The percentage chances for the locations where the pet will sleep each night, as a decimal value between 0 (never) and 1 (always). Each value is checked in the order listed at left until a match is found. If none of them match, the pet will choose a random empty spot in the farmhouse; if none was found, it'll sleep next to its pet bowl outside.
 
|-
 
|-
| <samp>CanGetPregnant</samp>
+
| <samp>Behaviors</samp>
| ''(Optional)'' Whether an animal can [[Animals#Animal Births|produce a child]] (regardless of gender). Default false.
+
| The pet's possible actions and behaviors, defined as the states in a state machine. Essentially the pet will be in one state at any given time, which also determines which state they can transition to next. For example, a cat can transition from <samp>Walk</samp> to <samp>BeginSitDown</samp>, but it can't skip instantly from <samp>Walk</samp> to <samp>SitDownLick</samp>.
|}
+
 
 +
This consists of a list of models with these fields:
   −
====Produce====
+
<dl>
 +
<dt>Required fields:</dt>
 +
<dd>
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,042: Line 5,109:  
! effect
 
! effect
 
|-
 
|-
| <samp>ProduceItemIds</samp><br /><samp>DeluxeProduceItemIds</samp>
+
| <samp>Id</samp>
| ''(Optional)'' The items produced by the animal when it's an adult. The <samp>DeluxeProduceItemIds</samp> field only applies if the <samp>Deluxe*</samp> fields match. Both default to none.
+
| A unique ID for the state. This only needs to be unique within the pet type (e.g. <samp>Cat</samp> and <samp>Dog</samp> can have different behaviors with the same ID).
 +
|}
 +
</dd>
   −
This consists of a list of models with these fields:
+
<dt>Direction:</dt>
 +
<dd>
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,051: Line 5,121:  
! effect
 
! effect
 
|-
 
|-
| <samp>ItemId</samp>
+
| <samp>Direction</samp>
| The [[#Custom items|''unqualified'' object ID]] of the item to produce.
+
| ''(Optional)'' The specific direction to face at the start of this state (one of <samp>left</samp>, <samp>right</samp>, <samp>up</samp>, or <samp>down</samp>), unless overridden by <samp>RandomizeDirection</samp>.  
 
|-
 
|-
| <samp>Condition</samp>
+
| <samp>RandomizeDirection</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this item can be produced now. Defaults to always true.
+
| ''(Optional)'' Whether to point the pet in a random direction at the start of this state (overriding the <samp>Direction</samp> if specified). Default false.
 
|-
 
|-
| <samp>MinimumFriendship</samp>
+
| <samp>IsSideBehavior</samp>
| ''(Optional)'' The minimum friendship points with the animal needed to produce this item. Default 0.
+
| ''(Optional)'' Whether to constrain the pet's facing direction to left and right while the state is active. Default false.
 
|}
 
|}
 +
</dd>
   −
If multiple items can be produced, one is chosen at random (with deluxe items taking priority if applicable).
+
<dt>Movement:</dt>
 +
<dd>
 +
{| class="wikitable"
 
|-
 
|-
| <samp>DaysToProduce</samp>
+
! field
| ''(Optional)'' The number of days between item productions. For example, setting <samp>1</samp> will produce an item every other day. Default 1.
+
! effect
 
|-
 
|-
| <samp>ProduceOnMature</samp>
+
| <samp>WalkInDirection</samp>
| ''(Optional)'' Whether an item is produced on the day the animal becomes an adult. Default false.
+
| ''(Optional)'' Whether to walk in the pet's facing direction. Default false.
 
|-
 
|-
| <samp>FriendshipForFasterProduce</samp>
+
| <samp>MoveSpeed</samp>
| ''(Optional)'' The minimum friendship points needed to reduce the <samp>DaysToProduce</samp> by one. Defaults to no reduction based on friendship.
+
| ''(Optional)'' Overrides the pet's <samp>MoveSpeed</samp> field while this state is active. Default -1 (which uses the pet's <samp>MoveSpeed</samp> value).
|-
+
|}
| <samp>DeluxeProduceMinimumFriendship</samp>
+
</dd>
| ''(Optional)'' The minimum friendship points needed to produce the <samp>DeluxeProduceItemId</samp>. Default 200.
  −
|-
  −
| <samp>DeluxeProduceCareDivisor</samp><br /><samp>DeluxeProduceLuckMultiplier</samp>
  −
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] which change the probability of producing the <samp>DeluxeProduceItemId</samp>, based on this formula:
  −
<pre>
  −
if happiness > 200:
  −
  happiness_modifier = happiness * 1.5
  −
else if happiness > 100:
  −
  happiness_modifier = 0
  −
else
  −
  happiness_modifier = happiness - 100
     −
((friendship + happiness_modifier) / DeluxeProduceCareDivisor) + (daily_luck * DeluxeProduceLuckMultiplier)
+
<dt>Audio:</dt>
</pre>
+
<dd>
 
  −
Specifically:
  −
* <samp>DeluxeProduceCareDivisor</samp> reduces the bonus from friendship and happiness, so a lower value ''increases'' the probability of producing the deluxe item. Default 1200.
  −
* <samp>DeluxeProduceLuckMultiplier</samp> increases the effect of [[Luck|daily luck]]. Default 0.
  −
 
  −
For example, given a friendship of 102 and happiness of 150, the probability with the default field values will be <code>((102 + 0) / 1200) + (daily_luck * 0) = (102 / 1200) = 0.085</code> or 8.5%.
  −
 
  −
See [[Animals#Produce]] for more info on the calculation.
  −
|-
  −
| <samp>HarvestType</samp>
  −
| ''(Optional)'' How produced items are collected from the animal. The valid values are:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! value
+
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>DropOvernight</samp>
+
| <samp>SoundOnStart</samp>
| The item is placed on the ground in the animal's home building overnight.
+
| ''(Optional)'' The [[#Custom audio|audio cue ID]] for the sound to play when the state starts. If set to <samp>BARK</samp>, the pet's <samp>BarkSound</samp> (or breed's <samp>BarkOverride</samp>) field is used. Defaults to none.
 
|-
 
|-
| <samp>HarvestWithTool</samp>
+
| <samp>SoundRange</samp><br /><samp>SoundRangeFromBorder</samp>
| The item is collected from the animal directly based on the <samp>HarvestTool</samp> field.
+
| ''(Optional)'' When set, the <samp>SoundOnStart</samp> is only audible if the pet is within this many tiles away from the player (<samp>SoundRange</samp>) or past the border of the screen (<samp>SoundRangeFromBorder</samp>). Default -1 (no distance check).
 +
|-
 +
| <samp>SoundIsVoice</samp>
 +
| ''(Optional)'' Whether to mute the <samp>SoundOnStart</samp> when the 'mute animal sounds' option is set. Default false.
 
|}
 
|}
 +
</dd>
   −
Default <samp>DropOvernight</samp>.
+
<dt>Behavior transitions:</dt>
 +
<dd>
 +
{| class="wikitable"
 
|-
 
|-
| <samp>HarvestTool</samp>
+
! field
| ''(Optional)'' The [[#Custom items|tool ID]] with which produced items can be collected from the animal, if the <samp>HarvestType</samp> is set to <samp>HarvestWithTool</samp>. The values recognized by the vanilla tools are <samp>MilkPail</samp> and <samp>Shears</samp>. Default none.
+
! effect
 +
|-
 +
| <samp>AnimationEndBehaviorChanges</samp><br /><samp>TimeoutBehaviorChanges</samp><br /><samp>PlayerNearbyBehaviorChanges</samp><br /><samp>RandomBehaviorChanges</samp><br /><samp>JumpLandBehaviorChanges</samp>
 +
| ''(Optional)'' A list of possible behavior transitions to start when the criteria are achieved. If multiple transitions are listed, a random one will be selected. If omitted, it won't affect behavior transitions.
   −
|}
+
These are triggered when this behavior's animation finishes (<samp>AnimationEndBehaviorChanges</samp>), when the set duration ends (<samp>TimeoutBehaviorChanges</samp>), when the player is within 2 tiles of the pet (<samp>PlayerNearbyBehaviorChanges</samp>), randomly at the start of each frame based on the <samp>RandomBehaviorChangeChance</samp> field (<samp>RandomBehaviorChanges</samp>), and when the pet finishes a jump (<samp>JumpLandBehaviorChanges</samp>).
   −
====Audio & sprite====
+
These consist of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,123: Line 5,183:  
! effect
 
! effect
 
|-
 
|-
| <samp>Sound</samp>
+
| <samp>Behavior</samp><br /><samp>LeftBehavior</samp><br /><samp>RightBehavior</samp><br /><samp>UpBehavior</samp><br /><samp>DownBehavior</samp>
| ''(Optional)'' The [[#Custom audio|audio cue ID]] for the sound produced by the animal (e.g. when pet). Default none.
+
| The ID of the behavior to start. The pet will check for a behavior field matching its current facing direction first, then try the <samp>Behavior</samp>. If none are specified, the current behavior will continue unchanged.
 
|-
 
|-
| <samp>BabySound</samp>
+
| <samp>OutsideOnly</samp>
| ''(Optional)'' Overrides <samp>Sound</samp> field when the animal is a baby. Has no effect if <samp>Sound</samp> isn't specified. Default none.
+
| ''(Optional)'' Whether the transition can only happen if the pet is outside. Default false.
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>Weight</samp>
| ''(Optional)'' The asset name for the animal's spritesheet. Defaults to <samp>Animals/{{t|ID}}</samp> (like <samp>Animals/Goat</samp> for a [[goat]]).
+
| ''(Optional)'' The option's weight when randomly choosing a behavior, relative to other behaviors in the list (e.g. <samp>2</samp> is twice as likely as <samp>1</samp>). Default 1.
 +
|}
 
|-
 
|-
| <samp>HarvestedTexture</samp>
+
| <samp>Duration</samp><br /><samp>MinimumDuration</samp><br /><samp>MaximumDuration</samp>
| ''(Optional)'' Overrides <samp>Texture</samp> if the animal doesn't currently have an item ready to collect (like the [[sheep]]'s sheared sprite). Default none.
+
| ''(Optional)'' The millisecond duration until the pet transitions to a behavior in the <samp>TimeoutBehaviorChanges</samp> field, if set. You must specify either a specific duration, or an inclusive minimum-to-maximum range in which the game will choose a random duration. If omitted, the behavior won't have a duration limit.
 
|-
 
|-
| <samp>BabyTexture</samp>
+
| <samp>RandomBehaviorChangeChance</samp>
| ''(Optional)'' Overrides <samp>Texture</samp> and <samp>HarvestedTexture</samp> when the animal is a baby. Default none.
+
| ''(Optional)'' The random probability at the start of each frame that the pet will transition to a behavior in the <samp>RandomBehaviorChanges</samp> field, if set. Specified as a value between 0 (never) and 1 (always). Default 0.
 +
|}
 +
</dd>
 +
 
 +
<dt>Animation and per-frame sounds:</dt>
 +
<dd>
 +
{| class="wikitable"
 
|-
 
|-
| <samp>UseFlippedRightForLeft</samp>
+
! field
| ''(Optional)'' When the animal is facing left, whether to use a flipped version of their right-facing sprite. Default false.
+
! effect
 
|-
 
|-
| <samp>SpriteWidth</samp><br /><samp>SpriteHeight</samp>
+
| <samp>Animation</samp>
| ''(Optional)'' The pixel height & width of the animal's sprite (before the in-game pixel zoom). Both default to 16.
+
| ''(Optional)'' The animation frames to play while this state is active. This consists of a list of models with these fields:
|-
  −
| <samp>EmoteOffset</samp>
  −
| ''(Optional)'' A pixel offset to apply to emotes from the farm animal, specified as an object with <samp>X</samp> and <samp>Y</samp>. Default zero.
  −
|-
  −
| <samp>Skins</samp>
  −
| ''(Optional)'' A list of alternate appearances. If specified, a skin is chosen at random when the animal is purchased or hatched. This consists of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,154: Line 5,215:  
! effect
 
! effect
 
|-
 
|-
| <samp>ID</samp>
+
| <samp>Frame</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the skin within the current list.
+
| The frame index in the animation. This should be an incremental number starting at 0.
 +
|-
 +
| <samp>Duration</samp>
 +
| The millisecond duration for which the frame should be kept on-screen before continuing to the next frame.
 
|-
 
|-
| <samp>Weight</samp>
+
| <samp>HitGround</samp>
| ''(Optional)'' A multiplier for the probability to choose this skin when an animal is purchased. For example, <samp>2.0</samp> will double the chance this skin is selected relative to the other skins. Default <samp>1.0</samp>.
+
| ''(Optional)'' Whether to play the footstep sound for the tile under the pet when the frame starts. Default false.
 
|-
 
|-
| <samp>Texture</samp><br /><samp>HarvestedTexture</samp><br /><samp>BabyTexture</samp>
+
| <samp>Jump</samp>
| ''(Optional)'' Overrides the equivalent main field when this skin is selected. Defaults to the main field's value.
+
| ''(Optional)'' Whether the pet should perform a small hop when the frame starts, including a 'dwop' sound. Default false.
|}
   
|-
 
|-
| <samp>ShadowWhenBaby</samp><br /><samp>ShadowWhenBabySwims</samp><br /><samp>ShadowWhenAdult</samp><br /><samp>ShadowWhenAdultSwims</samp>
+
| <samp>Sound</samp>
| ''(Optional)'' The shadow to draw under the farm animal. The <samp>Baby</samp> fields only apply when the farm animal is a baby, and <samp>Adult</samp> fields only applies when it's an adult (e.g. a baby animal won't default to the adult fields). When the farm animal swims, it'll use the <samp>Swims</samp> variant if it's set, else default to the non-swim variant.
+
| ''(Optional)'' The [[#Custom audio|audio cue ID]] for the sound to play when the animation starts or loops. If set to <samp>BARK</samp>, the pet's <samp>BarkSound</samp> (or breed's <samp>BarkOverride</samp>) field is used. Defaults to none.
 
  −
These consist of a model with these fields:
  −
 
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>SoundRange</samp><br /><samp>SoundRangeFromBorder</samp><br /><samp>SoundIsVoice</samp>
! effect
+
| See description for the equivalent behavior fields, but applies to the frame's <samp>Sound</samp> field instead.
 +
|}
 
|-
 
|-
| <samp>Visible</samp>
+
| <samp>Shake</samp>
| ''(Optional)'' Whether the shadow should be drawn. Default true.
+
| ''(Optional)'' The millisecond duration for which to shake the pet when the state starts. Default 0.
 
|-
 
|-
| <samp>Offset</samp>
+
| <samp>LoopMode</samp>
| ''(Optional)'' A pixel offset applied to the shadow position, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. Default zero.
+
| ''(Optional)'' What to do when the last animation frame is reached while the behavior is still active. The possible values are <samp>Hold</samp> (keep the last frame visible until the animation ends), <samp>Loop</samp> (restart from the first frame), or <samp>None</samp> (equivalent to <samp>Loop</samp>). Default <samp>None</samp>.
 
|-
 
|-
| <samp>Scale</samp>
+
| <samp>AnimationMinimumLoops</samp><br /><samp>AnimationMaximumLoops</samp>
| ''(Optional)'' The scale at which to draw the shadow. Default 2.5 (swimming baby), 3 (baby), 3.5 (swimming adult), or 4 (adult).
+
| ''(Optional)'' The minimum and maximum number of times to play the animation. Both must be specified to have any effect. The game will choose an inclusive random value between them. Both default to -1 (don't repeat animation).
 
|}
 
|}
 +
</dd>
 +
</dl>
 
|}
 
|}
   −
====Player profession effects====
+
=====Breeds=====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,191: Line 5,253:  
! effect
 
! effect
 
|-
 
|-
| <samp>ProfessionForFasterProduce</samp>
+
| <samp>Breeds</samp>
| ''(Optional)'' The internal ID of a [[Skills|profession]] which reduces the <samp>DaysToProduce</samp> by one. Default none.
+
| The cosmetic breeds which can be selected in the character customization menu when creating a save. This consists of a list of models with these fields:
|-
  −
| <samp>ProfessionForHappinessBoost</samp>
  −
| ''(Optional)'' The internal ID of a [[Skills|profession]] which makes it easier to befriend this animal. Default none.
  −
|-
  −
| <samp>ProfessionForQualityBoost</samp>
  −
| ''(Optional)'' The internal ID of a [[Skills|profession]] which increases the chance of higher-quality produce. Default none.
  −
|}
  −
 
  −
====Behavior====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,207: Line 5,260:  
! effect
 
! effect
 
|-
 
|-
| <samp>CanSwim</samp>
+
| <samp>ID</samp>
| ''(Optional)'' Whether animals on the farm can swim in water once they've been pet. Default false.
+
| The unique ID for the breed within the pet type.
 
|-
 
|-
| <samp>BabiesFollowAdults</samp>
+
| <samp>Texture</samp>
| ''(Optional)'' Whether baby animals can follow nearby adults. Default false.
+
| The asset name for the breed spritesheet for the pet's in-game sprite. This should be 128 pixels wide, and 256 (cat) or 288 (dog) pixels high.
 
|-
 
|-
| <samp>GrassEatAmount</samp>
+
| <samp>IconTexture</samp>
| ''(Optional)'' The amount of grass eaten by this animal each day. Default 2.
+
| The asset name for the breed icon texture, shown on the character customization screen and in-game menu. This should be a 16x16 pixel icon.
 
|-
 
|-
| <samp>HappinessDrain</samp>
+
| <samp>IconSourceRect</samp>
| ''(Optional)'' An amount which affects the daily reduction in happiness if the animal wasn't pet, or didn't have a heater in winter. Default none.
+
| The icon's pixel area within the <samp>IconTexture</samp>, specified as an object with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields.
 
|-
 
|-
| <samp>SellPrice</samp>
+
| <samp>BarkOverride</samp>
| ''(Optional)'' The price when [[Animals#Selling Animals|the player sells the animal]], before it's adjusted for the animal's friendship towards the player. Default 0.
+
| ''(Optional)'' Override the pet's <samp>BarkSound</samp> field for this breed, if set.
 
  −
The actual sell price will be this value multiplied by a number between 0.3 (zero friendship) and 1.3 (max friendship).
   
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>VoicePitch</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| ''(Optional)'' The [[wikipedia:Pitch (music)|pitch]] applied to the pet's bark sound, measured as a decimal value relative to 1. Defaults to 1.
 +
|}
 
|}
 
|}
   −
====Other====
+
=====Advanced=====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,234: Line 5,286:  
! effect
 
! effect
 
|-
 
|-
| <samp>ShowInSummitCredits</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' Whether to show the farm animal in the credit scene on [[The Summit|the summit]] after the player achieves [[perfection]]. Default false.
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
  −
| <samp>StatToIncrementOnProduce</samp>
  −
| ''(Optional)'' The game stat counters to increment when the animal produces an item. Default none. This consists of a list of models with these fields:
  −
{| class="wikitable"
  −
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>StatName</samp>
  −
| The name of the stat counter field on <samp>Game1.stats</samp>.
  −
|-
  −
| <samp>RequiredTags</samp>
  −
| ''(Optional)'' A comma-delimited list of [[Modding:Items#Context tags|context tags]] required on the main input item. The stat is only incremented if the item has ''all'' of these. You can negate a tag with <samp>!</samp> (like <code>bone_item,!fossil_item</code> for bone items that aren't fossils). Defaults to always enabled.
  −
|}
  −
|-
  −
| <samp>UpDownPetHitboxTileSize</samp><br /><samp>LeftRightPetHitboxTileSize</samp>
  −
| ''(Optional)'' The animal sprite's [[Modding:Modder Guide/Game Fundamentals#Tiles|tile]] size in the world when the player is clicking to pet them, specified in the form <samp>{{t|width}}, {{t|height}}</samp>. The <samp>UpDownPetHitboxTileSize</samp> applies when the animal is facing up or down, and <samp>LeftRightPetHitboxTileSize</samp> applies when facing left or right. The values can be fractional (''e.g.'' cows have a width of 1.75). Both default to a 1×1 tile.
  −
|-
  −
| <samp>BabyUpDownPetHitboxTileSize</samp><br /><samp>BabyLeftRightPetHitboxTileSize</samp>
  −
| ''(Optional)'' Overrides <samp>UpDownPetHitboxTileSize</samp> and <samp>LeftRightPetHitboxTileSize</samp> respectively before the animal is an adult. Both default to 1×1 tile.
   
|}
 
|}
   −
===Custom pets===
+
====Other changes====
====Format====
+
* The pet bowl is now a building which can be constructed or moved. Each pet is assigned to an available pet bowl. For C# mods, each pet now has a <samp>guid</samp> field populated with a unique ID, and each pet bowl has a <samp>petGuid</samp> field which tracks its owner (see the <samp>PetBowl::HasPet()</samp> and <samp>PetBowl::FindPet()</samp> methods).
You can now create and customize [[Animals#Cat or Dog|pet]]s & pet breeds by editing the new <samp>Data/Pets</samp> asset.
+
* In the [[Modding:Event data#Basic format|event character setup]], you can now use <samp>pet</samp> to add a pet of the player's selected type. Its actor name will be <samp>PetActor</samp> in other event commands. This supersedes <samp>cat</samp> (with name <samp>Cat</samp>) and <samp>dog</samp> (with name <samp>Dog</samp>), though those still work too.
 +
* For C# mods:
 +
** All pets now use a generic <samp>Pet</samp> class, instead of <samp>Cat</samp> or <samp>Dog</samp>. The pet type is tracked by the pet's <samp>petType</samp> field.
 +
** The player's preferred pet type is tracked by <samp>Game1.player.whichPetType</samp>. The former <samp>catPerson</samp> field is now readonly and checks that field.
 +
** Added <samp>Pet.type_cat</samp> and <samp>Pet.type_dog</samp> constants for the default pet types.
 +
 
 +
===Custom monster eradication goals===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
: ''See also: [[#Monster eradication goal flag changes|Monster eradication goal flag changes]].''
 +
 
 +
You can now add/edit [[Adventurer's Guild]] monster eradication goals by editing the new <samp>Data/MonsterSlayerQuests</samp> data asset.
    
This consists of a string → model lookup, where...
 
This consists of a string → model lookup, where...
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the pet (not the pet breed). The vanilla IDs are <samp>Cat</samp> and <samp>Dog</samp>.
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the monster eradication goal.
 
* The value is a model with the fields listed below.
 
* The value is a model with the fields listed below.
   −
=====Basic info=====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 5,273: Line 5,315:  
|-
 
|-
 
| <samp>DisplayName</samp>
 
| <samp>DisplayName</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the pet type's display name (e.g. "cat" or "dog"). For example, the vanilla adoption events show this when Marnie asks if you want to adopt the cat/dog.
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the goal's display name, shown on the board in the Adventurer's Guild.
|}
  −
 
  −
=====Audio & sprites=====
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>Targets</samp>
! effect
+
| A list of [[Modding:Monster data#Monster IDs|monster IDs]] that are counted towards the <samp>Count</samp>.
 
|-
 
|-
| <samp>BarkSound</samp>
+
| <samp>Count</samp>
| The [[#Custom audio|cue ID]] for the pet's occasional 'bark' sound.
+
| The total number of monsters (matching the <samp>Targets</samp>) which must be defeated to complete this goal.
 
|-
 
|-
| <samp>ContentSound</samp>
+
| <samp>RewardItemId</samp>
| The [[#Custom audio|cue ID]] for the sound which the pet makes when you pet it.
+
| ''(Optional)'' The [[#Custom items|qualified ID]] for the item that can be collected from [[Gil]] when this goal is completed. Default none.
 
|-
 
|-
| <samp>RepeatContentSoundAfter</samp>
+
| <samp>RewardItemPrice</samp>
| ''(Optional)'' The number of milliseconds until the <samp>ContentSound</samp> is repeated once. This is used by the dog, who pants twice when pet. Defaults to -1 (disabled).
+
| ''(Optional)'' The price of the <samp>RewardItemId</samp> in [[Marlon]]'s shop after the goal is completed, or -1 to disable buying it from Marlon. Default -1.
 
|-
 
|-
| <samp>EmoteOffset</samp>
+
| <samp>RewardDialogue</samp><br /><samp>RewardDialogueFlag</samp>
| ''(Optional)'' A pixel offset for the emote drawn above the pet sprite, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. For example, this affects the heart emote shown after petting it. Default none.
+
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for custom [[Gil]] dialogue shown when talking to him after completing the goal, and an optional [[Modding:Mail data|mail flag]] to set when the player has seen the dialogue. Both default to none.
|}
+
 
 +
If there are reward items, they're shown after this dialogue.
 +
 
 +
If <samp>RewardDialogue</samp> is used without <samp>RewardDialogueFlag</samp>, then this dialogue will be shown each time the reward menu is opened after completing the goal, until the player collects the reward items. If the <samp>RewardItems</samp> isn't set, this can safely be omitted since the goal will be marked collected immediately.
   −
=====Events=====
+
This doesn't send a letter; see <samp>RewardMail</samp> or <samp>RewardMailAll</samp> for that.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>RewardFlag</samp><br /><samp>RewardFlagAll</samp>
! effect
+
| ''(Optional)'' The [[Modding:Mail data|mail flag ID]] to set for the current player (<samp>RewardFlag</samp>) or all players (<samp>RewardFlagAll</samp>) when talking to [[Gil]] after completing the goal. Default none.
 +
 
 +
Note that <samp>RewardFlag</samp> is usually not needed, since the game will also set a <samp>Gil_{{t|goal ID}}</samp> flag regardless.
 +
 
 +
This doesn't send a letter; see <samp>RewardMail</samp> or <samp>RewardMailAll</samp> for that.
 
|-
 
|-
| <samp>EventOffset</samp>
+
| <samp>RewardMail</samp><br /><samp>RewardMailAll</samp>
| ''(Optional)'' The pixel offset for the pet when shown in events like Marnie's adoption event, specified as an object with <samp>X</samp> and <samp>Y</samp> fields. Default none.
+
| ''(Optional)'' The mail letter ID to add to the mailbox tomorrow for the current player (<samp>RewardMail</samp>) or all players (<samp>RewardMailAll</samp>). Default none.
 
|-
 
|-
| <samp>AdoptionEventLocation</samp><br /><samp>AdoptionEventId</samp>
+
| <samp>CustomFields</samp>
| ''(Optional)'' If both fields are set, the location and [[Modding:Event data|event ID]] which lets the player adopt this pet. This forces the event to play after 20 days if its preconditions haven't been met yet. Default <samp>Farm</samp> and none respectively.
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
+
|}
| <samp>SummitPerfectionEvent</samp>
+
 
| ''(Optional)'' How to render the pet during the summit [[perfection]] slideshow. If this isn't set, the pet won't be shown in the slideshow.
+
===Custom phone calls===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
Mods can now extend the [[telephone]] with custom calls (both incoming calls, and phone numbers which the player can call).
 +
 
 +
====Incoming calls====
 +
You can add or customize incoming calls by editing the <samp>Data/IncomingPhoneCalls</samp> asset.
   −
This consists of a model with these fields:
+
This consists of a string → model lookup, where...
 +
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the incoming call data.
 +
* The value is a model with the fields listed below.
    
{| class="wikitable"
 
{| class="wikitable"
Line 5,317: Line 5,369:  
! effect
 
! effect
 
|-
 
|-
| <samp>SourceRect</samp>
+
| <samp>Dialogue</samp>
| The source rectangle within the pet's texture to draw.
+
| The dialogue text to show when the player answers the phone. This can use the full [[Modding:Dialogue|dialogue format]] (including questions and different dialogue based on the selected answer).
 +
|-
 +
| <samp>FromNpc</samp>
 +
| ''(Optional)'' The internal name of the NPC making the call. If specified, that NPC's name and portrait will be shown.
 
|-
 
|-
| <samp>AnimationLength</samp>
+
| <samp>FromPortrait</samp>
| The number of frames to show starting from the <samp>SourceRect</samp>.
+
| ''(Optional)'' The asset name for the portrait spritesheet to display (like <samp>Portraits/Abigail</samp>). If <samp>FromNpc</samp> is specified too, this overrides the portrait from that NPC. If both <samp>FromNpc</samp> and <samp>FromDisplayName</samp> are null, this portrait will be shown with the display name "???".
 
|-
 
|-
| <samp>Motion</samp>
+
| <samp>FromDisplayName</samp>
| The motion to apply to the pet sprite.
+
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the calling NPC's display name. If <samp>FromNpc</samp> is specified too, this overrides the display name from that NPC.
 
|-
 
|-
| <samp>Flipped</samp>
+
| <samp>MaxCalls</samp>
| ''(Optional)'' Whether to flip the pet sprite left-to-right. Default false.
+
| ''(Optional)'' The maximum number of times a player can receive this phone call, or <samp>-1</samp> for no limit. Default 1.
 
|-
 
|-
| <samp>PingPong</samp>
+
| <samp>TriggerCondition</samp><br /><samp>RingCondition</samp>
| ''(Optional)'' Whether to apply the 'ping pong' effect to the pet sprite animation. Default false.
+
| ''(Optional)'' If set, a game state query which indicates whether to trigger this phone call (<samp>TriggerCondition</samp>) or whether the phone rings when this call is received (<samp>RingCondition</samp>).
|}
  −
|}
     −
=====Behavior=====
+
Whether a player receives this call depends on both fields: <samp>TriggerCondition</samp> is checked on the main player before sending the call to all players, then <samp>RingCondition</samp> is checked on each player to determine whether the phone rings for them.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>IgnoreBaseChance</samp>
! effect
+
| ''(Optional)'' Whether to ignore the 1% base chance when checking whether to trigger an incoming call. If true, the game will check if this call can be received regardless of the base chance. Default false.
 
|-
 
|-
| <samp>MoveSpeed</samp>
+
| <samp>SimpleDialogueSplitBy</samp>
| ''(Optional)'' How quickly the pet can move. Default 2.
+
| ''(Optional, specialized)'' If set, marks the call as having a simple dialogue string without an NPC name and portrait, with lines split into multiple boxes by this substring. For example, <code>"SimpleDialogueSplitBy": "#"</code> will split <code>Box A#Box B#Box C</code> into three consecutive dialogue boxes.
|-
  −
| <samp>SleepOnBedChance</samp><br /><samp>SleepNearBedChance</samp><br /><samp>SleepOnRugChance</samp>
  −
| ''(Optional)'' The percentage chances for the locations where the pet will sleep each night, as a decimal value between 0 (never) and 1 (always). Each value is checked in the order listed at left until a match is found. If none of them match, the pet will choose a random empty spot in the farmhouse; if none was found, it'll sleep next to its pet bowl outside.
  −
|-
  −
| <samp>Behaviors</samp>
  −
| The pet's possible actions and behaviors, defined as the states in a state machine. Essentially the pet will be in one state at any given time, which also determines which state they can transition to next. For example, a cat can transition from <samp>Walk</samp> to <samp>BeginSitDown</samp>, but it can't skip instantly from <samp>Walk</samp> to <samp>SitDownLick</samp>.
     −
This consists of a list of models with these fields:
+
You should omit this in most cases, and use the regular dialogue format in <samp>Dialogue</samp> to split lines if needed. This is mainly intended to support some older vanilla phone calls.
 
  −
<dl>
  −
<dt>Required fields:</dt>
  −
<dd>
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>CustomFields</samp>
! effect
+
| The [[#Custom data fields|custom fields]] for this entry.
|-
  −
| <samp>Name</samp>
  −
| A unique name for the state. This only needs to be unique within the pet type (e.g. <samp>Cat</samp> and <samp>Dog</samp> can have different behaviors with the same name).
   
|}
 
|}
</dd>
     −
<dt>Direction:</dt>
+
====Custom handlers in C#====
<dd>
+
C# mods can implement <samp>StardewValley.PhoneCalls.IPhoneHandler</samp> and add it to <samp>Phone.PhoneHandlers</samp> for full control over both incoming and outgoing calls:
{| class="wikitable"
  −
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>Direction</samp>
  −
| ''(Optional)'' The specific direction to face at the start of this state (one of <samp>left</samp>, <samp>right</samp>, <samp>up</samp>, or <samp>down</samp>), unless overridden by <samp>RandomizeDirection</samp>.  
  −
|-
  −
| <samp>RandomizeDirection</samp>
  −
| ''(Optional)'' Whether to point the pet in a random direction at the start of this state (overriding the <samp>Direction</samp> if specified). Default false.
  −
|-
  −
| <samp>IsSideBehavior</samp>
  −
| ''(Optional)'' Whether to constrain the pet's facing direction to left and right while the state is active. Default false.
  −
|}
  −
</dd>
     −
<dt>Movement:</dt>
+
<syntaxhighlight lang="c#">
<dd>
+
/// <summary>The mod entry point.</summary>
 +
internal sealed class ModEntry : Mod
 +
{
 +
    /// <inheritdoc />
 +
    public override void Entry(IModHelper helper)
 +
    {
 +
        Phone.PhoneHandlers.Add(new CustomPhoneHandler());
 +
    }
 +
}
 +
 
 +
/// <summary>A custom phone handler.</summary>
 +
internal sealed class CustomPhoneHandler : IPhoneHandler
 +
{
 +
    ...
 +
}
 +
</syntaxhighlight>
 +
 
 +
See <samp>StardewValley.PhoneCalls.DefaultPhoneHandler</samp> in the [[Modding:Modder Guide/Get Started#decompile|decompiled game code]] for an example implementation.
 +
 
 +
===Custom shops===
 +
{{/doc status|[[Modding:Shops]]|done=true}}
 +
 
 +
You can now create and edit shops via the new <samp>Data/Shops</samp> asset. See [[Modding:Shops]] for documentation and examples.
 +
 
 +
===Dialogue changes===
 +
{{/doc status|[[Modding:Dialogue]]|done=false}}
 +
 
 +
<ul>
 +
<li>Added new [[Modding:Dialogue|dialogue]] keys:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! asset
! effect
+
! key format
 +
! description
 
|-
 
|-
| <samp>WalkInDirection</samp>
+
|rowspan="22"| <samp>Characters/Dialogue/&lt;name&gt;</samp>
| ''(Optional)'' Whether to walk in the pet's facing direction. Default false.
   
|-
 
|-
| <samp>MoveSpeed</samp>
+
| <samp>AcceptBirthdayGift_{{t|id}}</samp><br /><samp>AcceptBirthdayGift_{{t|tag}}</samp><br /><samp>AcceptBirthdayGift_{{t|taste}}</samp><br /><samp>AcceptBirthdayGift_Negative</samp><br /><samp>AcceptBirthdayGift_Positive</samp><br /><samp>AcceptBirthdayGift</samp>
| ''(Optional)'' Overrides the pet's <samp>MoveSpeed</samp> field while this state is active. Default -1 (which uses the pet's <samp>MoveSpeed</samp> value).
+
| Shown when receiving a birthday gift from the player. If omitted, defaults to the generic translations for all NPCs.
|}
+
 
</dd>
+
The first matching dialogue is used in this order:
 +
# by item ID (like <samp>AcceptBirthdayGift_(O)128</samp>);
 +
# by context tag (like <samp>AcceptBirthdayGift_category_fish</samp>);
 +
# by gift taste (one of <samp>AcceptBirthdayGift_Loved</samp>, <samp>AcceptBirthdayGift_Liked</samp>, <samp>AcceptBirthdayGift_Neutral</samp>, <samp>AcceptBirthdayGift_Disliked</samp>, or <samp>AcceptBirthdayGift_Hated</samp>);
 +
# <samp>AcceptBirthdayGift_Negative</samp> (hated or disliked gift) or <samp>AcceptBirthdayGift_Positive</samp> (neutral, liked, or loved gift);
 +
# for all items (via <samp>AcceptBirthdayGift</samp>).
   −
<dt>Audio:</dt>
  −
<dd>
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>AcceptBouquet</samp>
! effect
+
| Shown when the NPC accepts a [[bouquet]] from the player. Defaults to a generic dialogue.
 +
|-
 +
| <samp>AcceptGift_{{t|id}}</samp><br /><samp>AcceptGift_{{t|tag}}</samp>
 +
| Shown when receiving a non-birthday gift from the player. This can be by item ID (like <samp>AcceptGift_(O)128</samp>) or context tag (like <samp>AcceptGift_category_fish</samp>). If omitted, defaults to the dialogue in <samp>Data/NPCGiftTastes</samp>.
 
|-
 
|-
| <samp>SoundOnStart</samp>
+
| <samp>DumpsterDiveComment</samp>
| ''(Optional)'' The [[#Custom audio|audio cue ID]] for the sound to play when the state starts. If set to <samp>BARK</samp>, the pet's <samp>BarkSound</samp> (or breed's <samp>BarkOverride</samp>) field is used. Defaults to none.
+
| Shown when the NPC catches the player digging through a trash can. Defaults to a generic dialogue based on the NPC's age.
 
|-
 
|-
| <samp>SoundRange</samp><br /><samp>SoundRangeFromBorder</samp>
+
| <samp>HitBySlingshot</samp>
| ''(Optional)'' When set, the <samp>SoundOnStart</samp> is only audible if the pet is within this many tiles away from the player (<samp>SoundRange</samp>) or past the border of the screen (<samp>SoundRangeFromBorder</samp>). Default -1 (no distance check).
+
| Shown when the player shoots them with a [[slingshot]]. Defaults to a generic dialogue.
 
|-
 
|-
| <samp>SoundIsVoice</samp>
+
| <samp>RejectBouquet_Divorced</samp><br /><samp>RejectBouquet_NotDatable</samp><br /><samp>RejectBouquet_NpcAlreadyMarried</samp><br /><samp>RejectBouquet_VeryLowHearts</samp><br /><samp>RejectBouquet_LowHearts</samp><br /><samp>RejectBouquet</samp>
| ''(Optional)'' Whether to mute the <samp>SoundOnStart</samp> when the 'mute animal sounds' option is set. Default false.
+
| Shown when the NPC rejects a [[bouquet]].
|}
+
 
</dd>
+
A specific dialogue is shown if possible:
 +
* <samp>RejectBouquet_Divorced</samp>: the NPC won't accept this bouquet because you divorced them.
 +
* <samp>RejectBouquet_NotDatable</samp>: the NPC isn't romanceable.
 +
* <samp>RejectBouquet_NpcAlreadyMarried</samp>: the NPC is already married to another player. You can use <samp>{0}</samp> in the dialogue for the other player's name.
 +
* <samp>RejectBouquet_VeryLowHearts</samp>: you have less than 4 hearts with the NPC.
 +
* <samp>RejectBouquet_LowHearts</samp>: you have less than 8 hearts with the NPC.
   −
<dt>Behavior transitions:</dt>
+
If the specific dialogue isn't set, the game will use the <samp>RejectBouquet</samp> dialogue (if set), else it'll default to generic dialogue for each case.
<dd>
+
|-
{| class="wikitable"
+
| <samp>RejectGift_Divorced</samp>
 +
| Shown when the NPC rejects a gift because you divorced them.
 
|-
 
|-
! field
+
| <samp>RejectItem_{{t|id}}</samp><br /><samp>RejectItem_{{t|tag}}</samp>
! effect
+
| If set, the NPC will refuse to accept any matching item and show this dialogue instead. This can be by item ID (like <samp>RejectItem_(O)128</samp>) or context tag (like <samp>RejectItem_category_fish</samp>). This can prevent gifting, movie tickets, bouquets, mermaid pendants, etc. However it won't prevent accepting an item for an active quest or special order.
 
|-
 
|-
| <samp>AnimationEndBehaviorChanges</samp><br /><samp>TimeoutBehaviorChanges</samp><br /><samp>PlayerNearbyBehaviorChanges</samp><br /><samp>RandomBehaviorChanges</samp><br /><samp>JumpLandBehaviorChanges</samp>
+
| <samp>RejectMermaidPendant_Divorced</samp><br /><samp>RejectMermaidPendant_NeedHouseUpgrade</samp><br /><samp>RejectMermaidPendant_NotDatable</samp><br /><samp>RejectMermaidPendant_NpcWithSomeoneElse</samp><br /><samp>RejectMermaidPendant_PlayerWithSomeoneElse</samp><br /><samp>RejectMermaidPendant_Under8Hearts</samp><br /><samp>RejectMermaidPendant_Under10Hearts</samp><br /><samp>RejectMermaidPendant_Under10Hearts_AskedAgain</samp><br /><samp>RejectMermaidPendant</samp>
| ''(Optional)'' A list of possible behavior transitions to start when the criteria are achieved. If multiple transitions are listed, a random one will be selected. If omitted, it won't affect behavior transitions.
+
| Shown when the NPC rejects a [[Mermaid's Pendant|mermaid's pendant]].
   −
These are triggered when this behavior's animation finishes (<samp>AnimationEndBehaviorChanges</samp>), when the set duration ends (<samp>TimeoutBehaviorChanges</samp>), when the player is within 2 tiles of the pet (<samp>PlayerNearbyBehaviorChanges</samp>), randomly at the start of each frame based on the <samp>RandomBehaviorChangeChance</samp> field (<samp>RandomBehaviorChanges</samp>), and when the pet finishes a jump (<samp>JumpLandBehaviorChanges</samp>).
+
A specific dialogue is shown if possible. The cases are checked in this order:
 +
# <samp>RejectMermaidPendant_PlayerWithSomeoneElse</samp>: the player is already engaged or married to someone else. You can use <samp>{0}</samp> in the dialogue for the player's spouse name.
 +
# <samp>RejectMermaidPendant_NotDatable</samp>: the NPC isn't romanceable.
 +
# <samp>RejectMermaidPendant_Divorced</samp>: you divorced them, so they won't accept gifts or proposals from you.
 +
# <samp>RejectMermaidPendant_NpcWithSomeoneElse</samp>: the NPC is already engaged or married to someone else. You can use <samp>{0}</samp> in the dialogue for the other player's name.
 +
# <samp>RejectMermaidPendant_Under8Hearts</samp>: you have under 8 hearts with the NPC.
 +
# <samp>RejectMermaidPendant_Under10Hearts</samp>: you have under 10 hearts with the NPC.
 +
# <samp>RejectMermaidPendant_Under10Hearts_AskedAgain</samp>: you have under 10 hearts with the NPC, and asked again after they already said no. (Defaults to the previous dialogue if not set.)
 +
# <samp>RejectMermaidPendant_NeedHouseUpgrade</samp>: you need to upgrade your house before they can accept.
   −
These consist of a list of models with these fields:
+
If the specific dialogue isn't set, the game will use the <samp>RejectMermaidPendant</samp> dialogue (if set), else it'll default to generic dialogue for each case.
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>RejectMovieTicket_AlreadyInvitedBySomeoneElse</samp><br /><samp>RejectMovieTicket_AlreadyWatchedThisWeek</samp><br /><samp>RejectMovieTicket_Divorced</samp><br /><samp>RejectMovieTicket_DontWantToSeeThatMovie</samp><br /><samp>RejectMovieTicket</samp>
! effect
+
| Show when the NPC rejects a [[Movie Ticket|movie ticket]].
 +
 
 +
A specific dialogue is shown if possible:
 +
* <samp>RejectMovieTicket_AlreadyInvitedBySomeoneElse</samp>: someone else already invited the NPC to a movie. You can use <samp>{0}</samp> in the dialogue for the other player's name.
 +
* <samp>RejectMovieTicket_AlreadyWatchedThisWeek</samp>: the NPC already watched a movie this week.
 +
* <samp>RejectMovieTicket_Divorced</samp>: you divorced the NPC, so they won't accept gifts from you.
 +
* <samp>RejectMovieTicket_DontWantToSeeThatMovie</samp>: the movie data marks that NPC as unwilling to watch it (e.g. kids for horror movies).
 +
 
 +
If the specific dialogue isn't set, the game will use the <samp>RejectMovieTicket</samp> dialogue (if set), else it'll default to generic dialogue for each case.
 
|-
 
|-
| <samp>Behavior</samp><br /><samp>LeftBehavior</samp><br /><samp>RightBehavior</samp><br /><samp>UpBehavior</samp><br /><samp>DownBehavior</samp>
+
| <samp>SpouseFarmhouseClutter</samp>
| The name of the behavior to start. The pet will check for a behavior field matching its current facing direction first, then try the <samp>Behavior</samp>. If none are specified, the current behavior will continue unchanged.
+
| Shown by an NPC spouse when they couldn't pathfind to their kitchen standing spot in the farmhouse.
 
|-
 
|-
| <samp>OutsideOnly</samp>
+
| <samp>SpouseGiftJealous</samp>
| ''(Optional)'' Whether the transition can only happen if the pet is outside. Default false.
+
| Shown by an NPC spouse when you gave a gift to another eligible NPC of the same gender as your spouse (unless it's their birthday). You can use <samp>{0}</samp> in the dialogue for the other NPC's name, and <samp>{1}</samp> for the gifted item name.
 
|-
 
|-
| <samp>Weight</samp>
+
| <samp>Spouse_MonstersInHouse</samp>
| ''(Optional)'' The option's weight when randomly choosing a behavior, relative to other behaviors in the list (e.g. <samp>2</samp> is twice as likely as <samp>1</samp>). Default 1.
+
| Shown by an NPC spouse when they're in the farmhouse and there's a monster close to them.
|}
   
|-
 
|-
| <samp>Duration</samp><br /><samp>MinimumDuration</samp><br /><samp>MaximumDuration</samp>
+
| <samp>SpouseStardrop</samp>
| ''(Optional)'' The millisecond duration until the pet transitions to a behavior in the <samp>TimeoutBehaviorChanges</samp> field, if set. You must specify either a specific duration, or an inclusive minimum-to-maximum range in which the game will choose a random duration. If omitted, the behavior won't have a duration limit.
+
| Shown when receiving the [[stardrop]] from your spouse.
 
|-
 
|-
| <samp>RandomBehaviorChangeChance</samp>
+
| <samp>Fair_Judging</samp>
| ''(Optional)'' The random probability at the start of each frame that the pet will transition to a behavior in the <samp>RandomBehaviorChanges</samp> field, if set. Specified as a value between 0 (never) and 1 (always). Default 0.
+
| Shown at the [[Stardew Valley Fair]] while Lewis is judging the grange displays. If omitted, the NPC will keep their normal festival dialogue.
|}
+
 
</dd>
+
If this is set without <samp>Fair_Judged*</samp>, the NPC will keep this dialogue after judging is done.
   −
<dt>Animation and per-frame sounds:</dt>
+
''This replaces the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp>: <samp>Event.cs.1602</samp> (Marnie), <samp>Event.cs.1604</samp> (Pierre), and <samp>Event.cs.1606</samp> (Willy).''
<dd>
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>Fair_Judged_PlayerLost_PurpleShorts</samp><br /><samp>Fair_Judged_PlayerLost_Skipped</samp><br /><samp>Fair_Judged_PlayerLost</samp><br /><samp>Fair_Judged_PlayerWon</samp><br /><samp>Fair_Judged</samp>
! effect
+
| Shown at the [[Stardew Valley Fair]] after Lewis finishes judging the grange displays.
 +
 
 +
The first matching dialogue is used in this order:
 +
# <samp>Fair_Judged_PlayerLost_PurpleShorts</samp>: the player put the [[Secrets#Lucky Purple Shorts|lucky purple shorts]] in their display (which is an automatic loss).  Defaults to <samp>Fair_Judged_PlayerLost</samp> if omitted.
 +
# <samp>Fair_Judged_PlayerLost_Skipped</samp>: the player didn't put anything in their display. Defaults to <samp>Fair_Judged_PlayerLost</samp> if omitted.
 +
# <samp>Fair_Judged_PlayerLost</samp> or <samp>Fair_Judged_PlayerWon</samp>: the player didn't/did win first place. Defaults to <samp>Fair_Judged</samp> if omitted.
 +
# <samp>Fair_Judged</samp>: shown if a more specific dialogue didn't match. If omitted, the NPC will keep their current dialogue.
 +
 
 +
''These replace the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp>: <samp>Event.cs.1591</samp> (Pierre when he won), <samp>Event.cs.1593</samp> (Pierre when the player won), <samp>Event.cs.1595</samp> (Marnie), <samp>Event.cs.1597</samp> (Willy), and <samp>Event.cs.1600</samp> (Marnie for the purple shorts).''
 
|-
 
|-
| <samp>Animation</samp>
+
| <samp>FlowerDance_Accept_Roommate</samp><br /><samp>FlowerDance_Accept_Spouse</samp><br /><samp>FlowerDance_Accept</samp>
| ''(Optional)'' The animation frames to play while this state is active. This consists of a list of models with these fields:
+
| Shown at the [[Flower Dance]] when the NPC agrees to dance. The game will prefer the <samp>_Roommate</samp> (if roommates) or <samp>_Spouse</samp> (if married) variant if applicable, else it'll check for the normal key. If omitted, defaults to a generic accept dialogue.
{| class="wikitable"
+
 
 +
''This replaces the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp> (<samp>Event.cs.1613</samp>, <samp>Event.cs.1615</samp>, <samp>Event.cs.1617</samp>, <samp>Event.cs.1619</samp>, <samp>Event.cs.1621</samp>, <samp>Event.cs.1623</samp>, <samp>Event.cs.1625</samp>, <samp>Event.cs.1627</samp>, <samp>Event.cs.1629</samp>, and <samp>Event.cs.1631</samp>).''
 
|-
 
|-
! field
+
| <samp>FlowerDance_Decline</samp>
! effect
+
| Shown at the [[Flower Dance]] when the NPC declines to dance. This replaces the former <samp>danceRejection</samp> key (which still works as a fallback).
 
|-
 
|-
| <samp>Frame</samp>
+
| <samp>WinterStar_GiveGift_Before_Roommate</samp><br /><samp>WinterStar_GiveGift_Before_Spouse</samp><br /><samp>WinterStar_GiveGift_Before</samp><br /><samp>WinterStar_GiveGift_After_Roommate</samp><br /><samp>WinterStar_GiveGift_After_Spouse</samp><br /><samp>WinterStar_GiveGift_After</samp>
| The frame index in the animation. This should be an incremental number starting at 0.
+
| Shown at the [[Feast of the Winter Star]] when the NPC gives the player their gift (before and after the player opens it). The game will prefer the <samp>_Roommate</samp> (if roommates) or <samp>_Spouse</samp> (if married) variant if applicable, else it'll check for the normal key. If omitted, the before/after dialogues each separately default to a generic translation for all NPCs.
 
|-
 
|-
| <samp>Duration</samp>
+
| <samp>WinterStar_ReceiveGift_{{t|id}}</samp><br /><samp>WinterStar_ReceiveGift_{{t|tag}}</samp><br /><samp>WinterStar_ReceiveGift</samp>
| The millisecond duration for which the frame should be kept on-screen before continuing to the next frame.
+
| Shown at the [[Feast of the Winter Star]] when receiving their gift from the player. This can be by item ID (like <samp>WinterStar_ReceiveGift_(O)128</samp>), context tag (like <samp>WinterStar_ReceiveGift_category_fish</samp>), or for any item (like <samp>WinterStar_ReceiveGift</samp>). If omitted, defaults to the generic translation for all NPCs.
 
|-
 
|-
| <samp>HitGround</samp>
+
| <samp>WipedMemory</samp>
| ''(Optional)'' Whether to play the footstep sound for the tile under the pet when the frame starts. Default false.
+
| Shown the first time you talk to the NPC after erasing their memory using the [[Dark Shrine of Memory]].
 +
|}
 +
</li>
 +
<li>Added new [[Modding:Dialogue|dialogue]] commands:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>Jump</samp>
+
! command
| ''(Optional)'' Whether the pet should perform a small hop when the frame starts, including a 'dwop' sound. Default false.
+
! description
 +
|- id="gender-switch"
 +
| <samp>${male^female}$</samp><br /><samp>${male^female^non-binary}$</samp>
 +
| Change text depending on the player's gender. This largely supersedes the <samp>^</samp> dialogue token (which still works), and is supported in many more places than that token. This is applied before most other commands or parsing, so it can safely be used in cases where <samp>^</samp> might have a different meaning (e.g. mail text). For example: <code>Ahoy there ${lad^lass}$!</code> or <code>Ahoy there ${lad^lass^matey}$!</code>.
 +
 
 +
You can optionally use <samp>¦</samp> instead of <samp>^</samp>, in which case any <samp>^</samp> characters are left as-is.
 +
 
 +
Note that the non-binary value is only used if a mod overrides the player's gender, since the in-game UI only allows male or female.
 
|-
 
|-
| <samp>Sound</samp>
+
| <samp>$action {{t|action}}</samp>
| ''(Optional)'' The [[#Custom audio|audio cue ID]] for the sound to play when the animation starts or loops. If set to <samp>BARK</samp>, the pet's <samp>BarkSound</samp> (or breed's <samp>BarkOverride</samp>) field is used. Defaults to none.
+
| Run a [[Modding:Trigger actions|trigger action string]], like <samp>$action AddMoney 500</samp> to add {{price|500}} to the current player.
 
|-
 
|-
| <samp>SoundRange</samp><br /><samp>SoundRangeFromBorder</samp><br /><samp>SoundIsVoice</samp>
+
| <samp>$query {{t|query}}#{{t|if true}}&#124;{{t|if false}}</samp>
| See description for the equivalent behavior fields, but applies to the frame's <samp>Sound</samp> field instead.
+
| Show different dialogue text depending on the [[Modding:Game state queries|game state query]] in {{t|query}}. For example:
|}
+
<syntaxhighlight lang="js">
 +
"Mon": "$query !PLAYER_VISITED_LOCATION Current Mine#Did you know there's an old abandoned mine up in the mountain? Apparently it's crawling with monsters!|I heard you went into the old mines up in the mountain!#Did you find anything tasty?$h"
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>Shake</samp>
+
| <samp>$t {{t|topic ID}} {{o|day length}}</samp>
| ''(Optional)'' The millisecond duration for which to shake the pet when the state starts. Default 0.
+
| Add a [[Modding:Dialogue#Conversation topics|conversation topic]] for the next {{o|day length}} days (default 4 days).
 
|-
 
|-
| <samp>LoopMode</samp>
+
| <samp>$v {{t|event id}} {{o|check preconditions}} {{o|skip if seen}}</samp>
| ''(Optional)'' What to do when the last animation frame is reached while the behavior is still active. The possible values are <samp>Hold</samp> (keep the last frame visible until the animation ends), <samp>Loop</samp> (restart from the first frame), or <samp>None</samp> (equivalent to <samp>Loop</samp>). Default <samp>None</samp>.
+
| Immediately start an [[Modding:Event data|event]] and end the current dialogue, subject to the conditions:
|-
+
* {{o|check preconditions}}: whether to ignore the command if the [[Modding:Event data#Event preconditions|event's preconditions]] don't match (one of <samp>true</samp> or <samp>false</samp>). Default true.
| <samp>AnimationMinimumLoops</samp><br /><samp>AnimationMaximumLoops</samp>
+
* {{o|skip if seen}}: whether to ignore the command if the player has already seen the given event. Default true.
| ''(Optional)'' The minimum and maximum number of times to play the animation. Both must be specified to have any effect. The game will choose an inclusive random value between them. Both default to -1 (don't repeat animation).
+
 
 +
If the event is not played, the dialogue continues to the next line instead.
 +
 
 +
For example, <code>$v 60367 false false</code> will replay the bus arrival event from the start of the game. <code>$v SomeMod.Test true false#$b#Wow! Good timing!$1</code> will play the event "SomeMod.Test" if the player meets the precondition requirements. If they do not, the dialogue "Wow! Good timing!$1" will play instead. 
 +
 
 +
Note: The command will only work if it is at the very start of the dialogue. Adding any dialogue or other commands before it will cause it not to trigger the event and display the event commands as dialogue instead.  
 
|}
 
|}
</dd>
+
</li>
</dl>
+
<li>Improved dialogue commands:
|}
  −
 
  −
=====Breeds=====
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! command
! effect
+
! changes
 
|-
 
|-
| <samp>Breeds</samp>
+
| <samp>$p</samp>
| The cosmetic breeds which can be selected in the character customization menu when creating a save. This consists of a list of models with these fields:
+
| You can now check multiple answer IDs. For example, this will show the first dialogue if the player chose dialogue answer 17, 18, or 19:
{| class="wikitable"
+
<pre>$p 17|18|19#I guess you think nothing would happen, right?$u|Maybe a wicked ghost would appear!</pre>
|-
+
|}</li>
! field
+
<li>[[Modding:Dialogue#Response IDs|Dialogue response IDs]] are now [[Modding:Common data field types#Unique string ID|unique string IDs]].</li>
! effect
+
<li>[[Secrets#Item Spawn Cheat|Item spawn codes]] now use string item IDs. That means you can spawn any item using its [[#Custom items|qualified item ID]] (like <code>[(F)1664]</code> for a [[Mystic Rug]]), but can no longer prepend zeros (e.g. <code>[128]</code> is a pufferfish but <code>[0128]</code> is an error item).</li>
|-
+
<li>For C# mods, <samp>Dialogue</samp> now tracks the translation key used to build it (when applicable). For example, you can detect when the player is rejected at the [[Flower Dance]] (derived from {{github|spacechase0/StardewValleyMods|Three-Heart Dance Partner}}):
| <samp>ID</samp>
+
<syntaxhighlight lang="c#">
| The unique ID for the breed within the pet type.
+
private void OnMenuChanged(object sender, MenuChangedEventArgs e)
|-
+
{
| <samp>Texture</samp>
+
    bool isDanceRejection =
| The asset name for the breed spritesheet for the pet's in-game sprite. This should be 128 pixels wide, and 256 (cat) or 288 (dog) pixels high.
+
        Game1.currentLocation?.currentEvent?.FestivalName == "Flower Dance"
|-
+
        && e.NewMenu is DialogueBox dialogueBox
| <samp>IconTexture</samp>
+
        && dialogueBox.characterDialogue is {} dialogue
| The asset name for the breed icon texture, shown on the character customization screen and in-game menu. This should be a 16x16 pixel icon.
+
        && dialogue.TranslationKey == $"Characters\\Dialogue\\{dialogue.speaker?.Name}:danceRejection";
|-
+
}
| <samp>IconSourceRect</samp>
+
</syntaxhighlight>
| The icon's pixel area within the <samp>IconTexture</samp>, specified as an object with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields.
  −
|-
  −
| <samp>BarkOverride</samp>
  −
| ''(Optional)'' Override the pet's <samp>BarkSound</samp> field for this breed, if set.
  −
|-
  −
| <samp>VoicePitch</samp>
  −
| ''(Optional)'' The [[wikipedia:Pitch (music)|pitch]] applied to the pet's bark sound, measured as a decimal value relative to 1. Defaults to 1.
  −
|}
  −
|}
     −
=====Advanced=====
+
For C# mods that create <samp>Dialogue</samp> instances directly, there's a few ways to do it now:
{| class="wikitable"
+
<syntaxhighlight lang="c#">
|-
+
// from a translation key
! field
+
var dialogue = new Dialogue(npc, "Strings\\StringsFromCSFiles:Utility.cs.5360");
! effect
  −
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
  −
|}
     −
====Other changes====
+
// from custom text (with or without a translation key)
* The pet bowl is now a building which can be constructed or moved. Each pet is assigned to an available pet bowl. For C# mods, each pet now has a <samp>guid</samp> field populated with a unique ID, and each pet bowl has a <samp>petGuid</samp> field which tracks its owner (see the <samp>PetBowl::HasPet()</samp> and <samp>PetBowl::FindPet()</samp> methods).
+
var dialogue = new Dialogue(npc, null, "Some arbitrary text to show as-is");
* In the [[Modding:Event data#Basic format|event character setup]], you can now use <samp>pet</samp> to add a pet of the player's selected type. Its actor name will be <samp>PetActor</samp> in other event commands. This supersedes <samp>cat</samp> (with name <samp>Cat</samp>) and <samp>dog</samp> (with name <samp>Dog</samp>), though those still work too.
  −
* For C# mods:
  −
** All pets now use a generic <samp>Pet</samp> class, instead of <samp>Cat</samp> or <samp>Dog</samp>. The pet type is tracked by the pet's <samp>petType</samp> field.
  −
** The player's preferred pet type is tracked by <samp>Game1.player.whichPetType</samp>. The former <samp>catPerson</samp> field is now readonly and checks that field.
  −
** Added <samp>Pet.type_cat</samp> and <samp>Pet.type_dog</samp> constants for the default pet types.
     −
===Custom monster eradication goals===
+
// from a translation with tokens
: ''See also: [[#Monster eradication goal flag changes|Monster eradication goal flag changes]].''
+
var dialogue = Dialogue.FromTranslation(npc, "Data\\ExtraDialogue:PurchasedItem_2_QualityLow_Willy", whatToCallPlayer, particle, i.DisplayName);
 +
</syntaxhighlight>
 +
 
 +
You can also easily add fallback logic using <samp>Dialogue.TryGetDialogue</samp> or <samp>npc.TryGetDialogue</samp>. For example:
 +
<syntaxhighlight lang="c#">
 +
Dialogue dialogue =
 +
    npc.TryGetDialogue($"rejection_{itemId}_{locationName}_{x}_{y}")
 +
    ?? npc.TryGetDialogue($"rejection_{itemId}_{locationName}")
 +
    ?? npc.TryGetDialogue($"rejection_{itemId}")
 +
    ?? new Dialogue(npc, "Strings\\StringsFromCSFiles:NPC.cs.3971");
 +
</syntaxhighlight>
 +
</li>
 +
<li>For C# mods, added a <samp>dialogue.sideEffects</samp> field to run code when the dialogue is displayed.</li>
 +
<li>The 'reveal taste' dialogue command now uses the format <samp>%revealtaste:{{t|npc name}}:{{t|item ID}}</samp> to support item IDs. (The previous <samp>%revealtaste{{t|npc name}}{{t|item index}}</samp> format still works to support old content packs, but the item index can only be a number.)</li>
 +
<li>NPCs no longer override the portrait for a gift taste dialogue that uses a portrait command explicitly.</li>
 +
<li>Fixed unknown [[Modding:Dialogue|dialogue]] commands starting with <samp>$</samp> being parsed as a portrait number when not numeric.</li>
 +
<li>Fixed NPCs only using a <code>{day name}{hearts}_{year}</code> dialogue if they also have a <code>{day name}{hearts}</code> one.</li>
 +
<li>Fixed NPCs only using the <code>MovieInvitation</code> dialogue key in English.</li>
 +
</ul>
 +
 
 +
===Schedule changes===
 +
{{/doc status|[[Modding:Schedule data]]|done=false}}
 +
 
 +
<ul>
 +
<li>Schedule keys are now case-insensitive.</li>
 +
<li>Added a new <samp>{{t|day of week}}_{{t|min hearts}}</samp> schedule key.</li>
 +
<li>Added an <samp>NPC.ScheduleKey</samp> field which always matches their loaded schedule.</li>
 +
<li>Schedule commands now trim surrounding whitespace, so they can be multilined for readability. For example:
 +
<syntaxhighlight lang="js">"Wed": "
 +
    1000 ArchaeologyHouse 11 9 0/
 +
    1800 Town 47 87 0/
 +
    2200 SeedShop 1 9 3 abigail_sleep
 +
"</syntaxHighlight></li>
 +
<li>Removed an unintended schedule fallback to a <samp>{season}_spring_{hearts}</samp> key. It'll skip to the <samp>spring</samp> default instead.</li>
 +
<li>Schedules are now fault-tolerant:
 +
* Fixed crash if a selected schedule can't be parsed. The NPC now logs an error and continues with the next fallback instead.
 +
* Fixed crash if certain hardcoded schedules aren't present (like Penny's <samp>marriageJob</samp> or Pam's <samp>bus</samp>).
 +
* Fixed error if a schedule command is empty.</li>
 +
</ul>
   −
You can now add/edit [[Adventurer's Guild]] monster eradication goals by editing the new <samp>Data/MonsterSlayerQuests</samp> data asset.
+
===Other NPC changes===
 +
{{/doc status|[[Modding:NPC data]] as needed|done=false}}
   −
This consists of a string → model lookup, where...
+
<ul>
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the monster eradication goal.
+
<li>Added <samp>Game1.characterData</samp> and <samp>Game1.farmAnimalData</samp> to read NPC/animal info without constantly reloading the <samp>Data/Characters</samp> or <samp>Data/FarmAnimals</samp> asset.</li>
* The value is a model with the fields listed below.
+
<li>All translated NPC names are now in <samp>Strings/NPCNames</samp>.
 +
<li>Added new fields & methods for C# mods:
    
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! type
 +
! field/method
 
! effect
 
! effect
 
|-
 
|-
| <samp>DisplayName</samp>
+
|rowspan="2"| <samp>AdventureGuild</samp>
| A [[Modding:Tokenizable strings|tokenizable string]] for the goal's display name, shown on the board in the Adventurer's Guild.
+
| <samp>IsComplete(data)</samp>
 +
| Get whether an [[Adventurer's Guild]] monster eradication goal has been completed, regardless of whether the player collected its rewards yet.
 
|-
 
|-
| <samp>Targets</samp>
+
| <samp>HasCollectedReward(player, id)</samp>
| A list of [[Modding:Monster data#Monster IDs|monster IDs]] that are counted towards the <samp>Count</samp>.
+
| Get whether a given player has completed an [[Adventurer's Guild]] monster eradication goal and collected its rewards. For example:
 +
<syntaxhighlight lang="c#">
 +
bool isPhoneUnlocked = AdventureGuild.HasCollectedReward(Game1.player, "Gil_FlameSpirits");
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>Count</samp>
+
| <samp>AnimalHouse</samp>
| The total number of monsters (matching the <samp>Targets</samp>) which must be defeated to complete this goal.
+
| <samp>adoptAnimal</samp>
 +
| Add an animal to this location and set the location as the animal's home.
 
|-
 
|-
| <samp>RewardItemId</samp>
+
| <samp>AnimatedSprite</samp>
| ''(Optional)'' The [[#Custom items|qualified ID]] for the item that can be collected from [[Gil]] when this goal is completed. Default none.
+
| <samp>Owner</samp>
 +
| The NPC which owns the sprite.
 
|-
 
|-
| <samp>RewardItemPrice</samp>
+
|rowspan="3"| <samp>Character</samp>
| ''(Optional)'' The price of the <samp>RewardItemId</samp> in [[Marlon]]'s shop after the goal is completed, or -1 to disable buying it from Marlon. Default -1.
+
| <samp>IsVillager</samp>
 +
| Whether this is an NPC-type villager (i.e. not a monster, horse, pet, player's child, etc). In other words, this checks whether the NPC would use data from <samp>Data/Characters</samp> (regardless of whether they currently have an entry in the asset).
 
|-
 
|-
| <samp>RewardDialogue</samp><br /><samp>RewardDialogueFlag</samp>
+
| <samp>StandingPixel</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for custom [[Gil]] dialogue shown when talking to him after completing the goal, and an optional [[Modding:Mail data|mail flag]] to set when the player has seen the dialogue. Both default to none.
+
| The character's cached pixel position within the current location, based on the center pixel of their bounding box.
 
  −
If there are reward items, they're shown after this dialogue.
  −
 
  −
If <samp>RewardDialogue</samp> is used without <samp>RewardDialogueFlag</samp>, then this dialogue will be shown each time the reward menu is opened after completing the goal, until the player collects the reward items. If the <samp>RewardItems</samp> isn't set, this can safely be omitted since the goal will be marked collected immediately.
  −
 
  −
This doesn't send a letter; see <samp>RewardMail</samp> or <samp>RewardMailAll</samp> for that.
   
|-
 
|-
| <samp>RewardFlag</samp><br /><samp>RewardFlagAll</samp>
+
| <samp>Tile</samp><br /><samp>TilePoint</samp>
| ''(Optional)'' The [[Modding:Mail data|mail flag ID]] to set for the current player (<samp>RewardFlag</samp>) or all players (<samp>RewardFlagAll</samp>) when talking to [[Gil]] after completing the goal. Default none.
+
| The character's cached tile position within their current location. <samp>Tile</samp> is their exact non-integer position, and <samp>TilePoint</samp> is their integer tile position.
 
  −
Note that <samp>RewardFlag</samp> is usually not needed, since the game will also set a <samp>Gil_{{t|goal ID}}</samp> flag regardless.
  −
 
  −
This doesn't send a letter; see <samp>RewardMail</samp> or <samp>RewardMailAll</samp> for that.
   
|-
 
|-
| <samp>RewardMail</samp><br /><samp>RewardMailAll</samp>
+
|rowspan="7"| <samp>FarmAnimal</samp>
| ''(Optional)'' The mail letter ID to add to the mailbox tomorrow for the current player (<samp>RewardMail</samp>) or all players (<samp>RewardMailAll</samp>). Default none.
+
| <samp>isAdult</samp>
 +
| Get whether the farm animal is fully grown (opposite of <samp>isBaby()</samp>).
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>CanGetProduceWithTool</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| Get whether the farm animal's produce can be collected with a given tool (e.g. milk pail for a cow).
|}
  −
 
  −
===Custom phone calls===
  −
Mods can now extend the [[telephone]] with custom calls (both incoming calls, and phone numbers which the player can call).
  −
 
  −
====Incoming calls====
  −
You can add or customize incoming calls by editing the <samp>Data/IncomingPhoneCalls</samp> asset.
  −
 
  −
This consists of a string → model lookup, where...
  −
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the incoming call data.
  −
* The value is a model with the fields listed below.
  −
 
  −
{| class="wikitable"
   
|-
 
|-
! field
+
| <samp>CanLiveIn</samp>
! effect
+
| Get whether the animal can be added to a building.
 
|-
 
|-
| <samp>Dialogue</samp>
+
| <samp>GetDisplayName</samp><br /><samp>GetShopDescription</samp>
| The dialogue text to show when the player answers the phone. This can use the full [[Modding:Dialogue|dialogue format]] (including questions and different dialogue based on the selected answer).
+
| Get the translated display name or shop description for this animal.
 
|-
 
|-
| <samp>FromNpc</samp>
+
| <samp>GetHarvestType</samp>
| ''(Optional)'' The internal name of the NPC making the call. If specified, that NPC's name and portrait will be shown.
+
| Get whether the animal's produce is dropped or collected with a tool.
 +
|-
 +
| <samp>growFully</samp>
 +
| Instantly age the animal to adulthood if it's still a baby.
 +
|-
 +
| <samp>ReloadTextureIfNeeded</samp>
 +
| Update the animal sprite based on the current state + data.
 +
|-
 +
| rowspan="2"| <samp>Farmer</samp>
 +
| <samp>GetDisplayPants</samp><br /><samp>GetDisplayShirt</samp>
 +
| Get the texture and sprite index to draw for the player's pants or shirt. This accounts for override clothing, worn clothing, and the default clothing drawn when the farmer isn't wearing anything.
 +
 
 +
For example:
 +
<syntaxhighlight lang="c#">
 +
Game1.player.GetDisplayShirt(out Texture2D texture, out int spriteIndex);
 +
</syntaxhighlight>
 +
|-
 +
| <samp>CanDyePants</samp><br /><samp>CanDyeShirt</samp>
 +
| Get whether the currently equipped pants or shirt can be [[Dyeing|dyed]].
 +
|-
 +
| <samp>Monster</samp>
 +
| <samp>GetDisplayName(name)</samp>
 +
| Get the translated display name for a monster type.
 
|-
 
|-
| <samp>FromPortrait</samp>
+
|rowspan="4"| <samp>NPC</samp>
| ''(Optional)'' The asset name for the portrait spritesheet to display (like <samp>Portraits/Abigail</samp>). If <samp>FromNpc</samp> is specified too, this overrides the portrait from that NPC. If both <samp>FromNpc</samp> and <samp>FromDisplayName</samp> are null, this portrait will be shown with the display name "???".
+
| <samp>CanReceiveGifts</samp>
 +
| Get whether this NPC can receive gifts from the player (regardless of whether they've already received one today).
 
|-
 
|-
| <samp>FromDisplayName</samp>
+
| <samp>GetData</samp><br /><samp>NPC.TryGetData</samp>
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the calling NPC's display name. If <samp>FromNpc</samp> is specified too, this overrides the display name from that NPC.
+
| Get the underlying data from <samp>Data/Characters</samp> for this NPC, if any.
 
|-
 
|-
| <samp>MaxCalls</samp>
+
| <samp>NPC.GetDisplayName(name)</samp>
| ''(Optional)'' The maximum number of times a player can receive this phone call, or <c>-1</samp> for no limit. Default 1.
+
| Get the translated display name in the current language for an NPC by their internal name.
 
|-
 
|-
| <samp>TriggerCondition</samp><br /><samp>RingCondition</samp>
+
| <samp>hasDarkSkin</samp>
| ''(Optional)'' If set, a game state query which indicates whether to trigger this phone call (<samp>TriggerCondition</samp>) or whether the phone rings when this call is received (<samp>RingCondition</samp>).
+
| Whether this character has dark skin for the purposes of child genetics.
 
  −
Whether a player receives this call depends on both fields: <samp>TriggerCondition</samp> is checked on the main player before sending the call to all players, then <samp>RingCondition</samp> is checked on each player to determine whether the phone rings for them.
   
|-
 
|-
| <samp>IgnoreBaseChance</samp>
+
| <samp>Pet</samp>
| ''(Optional)'' Whether to ignore the 1% base chance when checking whether to trigger an incoming call. If true, the game will check if this call can be received regardless of the base chance. Default false.
+
| <samp>GetPetData</samp><br /><samp>TryGetData</samp>
 +
| Get the underlying data from <samp>Data/Pets</samp> for this pet, if any.
 
|-
 
|-
| <samp>SimpleDialogueSplitBy</samp>
+
| <samp>ShopMenu</samp>
| ''(Optional, specialized)'' If set, marks the call as having a simple dialogue string without an NPC name and portrait, with lines split into multiple boxes by this substring. For example, <code>"SimpleDialogueSplitBy": "#"</code> will split <code>Box A#Box B#Box C</code> into three consecutive dialogue boxes.
+
| <samp>ShopId</samp>
 +
| A key which identifies the current shop. This may be the unique shop ID in <samp>Data/Shops</samp> for a standard shop, <samp>Dresser</samp> or <samp>FishTank</samp> for furniture, etc. This is guaranteed to be set to a relevant shop ID.
   −
You should omit this in most cases, and use the regular dialogue format in <samp>Dialogue</samp> to split lines if needed. This is mainly intended to support some older vanilla phone calls.
+
This replaces the former <samp>shopContext</samp> field, and will usually have the same value in cases where that was set to a unique shop ID.
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>Utility</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| <samp>getAllVillagers</samp>
 +
| Get all villager NPCs (excluding horses, pets, monsters, player children, etc). This works just like <samp>getAllCharacters</samp> with an added filter.
 
|}
 
|}
 
+
</li>
====Custom handlers in C#====
+
<li>NPCs now update on save loaded when their home data changes.</li>
C# mods can implement <samp>StardewValley.PhoneCalls.IPhoneHandler</samp> and add it to <samp>Phone.PhoneHandlers</samp> for full control over both incoming and outgoing calls:
+
<li><samp>NPC.reloadSprite()</samp> now has an argument to only reload the appearance, without changing other data.</li>
 +
<li><samp>Utility.getAllCharacters()</samp> now returns a plain <samp>List&lt;NPC&gt;</samp> value instead of a custom <samp>DisposableList&lt;NPC&gt;</samp>, so you can use normal LINQ querying on it.</li>
 +
<li><samp>Utility.GetHorseWarpRestrictionsForFarmer(player)</samp> now returns an enum (which is more efficient and easier for mods to patch), and added a new <samp>Utility.GetHorseWarpErrorMessage(restrictions)</samp> method to get the error message to show for it.</li>
 +
<li><samp>Farmer.hasAFriendWithHeartLevel</samp> now has an optional max-hearts argument.</li>
 +
<li>Removed most <samp>FarmAnimal</samp> fields/properties which just mirror the underlying data.</li>
 +
<li>Removed invalid item IDs in <samp>Data/NPCGiftTastes</samp>.</li>
 +
<li>Fixed NPCs sometimes duplicated on save load (particularly if their home location changed).</li>
 +
<li>Fixed child NPCs like [[Jas]] or [[Vincent]] ignoring relative titles like "mom" in <samp>Data/NPCDispositions</samp> (now <samp>Data/Characters</samp>) for reveal-gift-taste dialogues.</li>
 +
<li>Fixed custom NPCs ignoring dialogue when they use a subclass of <samp>NPC</samp>.</li>
 +
<li>Fixed monsters not loading their display name from <samp>Data/Monsters</samp> for English players.</li>
 +
<li>Fixed player children not applying the <samp>IsInvisible</samp> flag.</li>
 +
</ul>
 +
 
 +
==What's new for everything else==
 +
===Buff overhaul===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
: ''See also: [[#Custom buffs|custom buffs]].''
 +
 
 +
1.6 rewrites buffs to work more consistently and be more extensible:
 +
 
 +
* Buff logic is unified into <samp>Game1.player.buffs</samp>, which is the single source of truth for buff data. This replaces the previous <samp>player.added*</samp> and <samp>player.appliedBuffs</samp> fields, <samp>BuffsDisplay</samp> logic, enchantment stat bonuses, and boots/ring attribute changes on (un)equip.
 +
* This also removes limitations on buff types (e.g. buffs can add weapon bonuses and weapons can add attribute buffs) and buffable equipment (e.g. equipped tools can have buffs too).
 +
* Buff effects are now fully recalculated when they change, to fix a range of longstanding bugs like attribute drift and double-debuffs. Just like before, the buffs are managed locally; only the buff IDs and aggregate attribute effects are synced.
 +
 
 +
'''For C# mods:'''
 +
* Each buff now has a unique string ID. You can apply a new buff with the same ID to replace it (so you no longer need to manually find and remove previous instances of the buff).
 +
* The buff duration can now be set to <samp>Buff.ENDLESS</samp> to remove the duration. It'll last all day until the player sleeps.
 +
* You can add standard buff effects to any equipment by overriding <samp>Item.AddEquipmentEffects</samp>, or add custom behaviour/buffs by overriding <samp>Item.onEquip</samp> and <samp>Item.onUnequip</samp>.
 +
* You can add custom food or drink buffs by overriding <samp>Item.GetFoodOrDrinkBuffs()</samp>.
 +
* The <samp>Buff</samp> constructor now supports a custom icon texture, sprite index, display name, description, and millisecond duration to fully support custom buffs.
 +
* You can change how buff attributes are displayed (or add new attributes) by extending the <samp>BuffsDisplay.displayAttributes</samp> list.
 +
* You can have invisible buffs by setting <samp>buff.visible = false</samp>.
 +
 
 +
For example, here's how to add a custom buff which adds +3 speed:
    
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
/// <summary>The mod entry point.</summary>
+
Buff buff = new Buff(
internal sealed class ModEntry : Mod
+
    id: "Example.ModId_ZoomZoom",
{
+
    displayName: "Zoom Zoom", // can optionally specify description text too
     /// <inheritdoc />
+
    iconTexture: this.Helper.ModContent.Load<Texture2D>("assets/zoom.png"),
     public override void Entry(IModHelper helper)
+
    iconSheetIndex: 0,
 +
     duration: 30_000, // 30 seconds
 +
     effects: new BuffEffects()
 
     {
 
     {
         Phone.PhoneHandlers.Add(new CustomPhoneHandler());
+
         Speed = { 10 } // shortcut for buff.Speed.Value = 10
 
     }
 
     }
}
+
);
 
+
Game1.player.applyBuff(buff);
/// <summary>A custom phone handler.</summary>
  −
internal sealed class CustomPhoneHandler : IPhoneHandler
  −
{
  −
    ...
  −
}
   
</syntaxhighlight>
 
</syntaxhighlight>
   −
See <samp>StardewValley.PhoneCalls.DefaultPhoneHandler</samp> in the [[Modding:Modder Guide/Get Started#decompile|decompiled game code]] for an example implementation.
+
You can also implement your own custom effects in code by checking if the buff is active, like <code>Game1.player.hasBuff("Example.ModId_ZoomZoom")</code>.
   −
===Custom shops===
+
===Custom audio===
You can now create and edit shops via the new <samp>Data/Shops</samp> asset. See [[Modding:Shops]] for documentation and examples.
+
{{/doc status|[[Modding:Audio]]|done=true}}
   −
===Dialogue changes===
+
You can now add or edit music tracks or sound effects by editing the new <samp>Data/AudioChanges</samp> asset. New cues are added to the game's soundbank, so they can be used anywhere normal audio can be used (e.g. the <samp>Music</samp> [[Modding:Maps|map property]]). This supports <samp>.ogg</samp> and <samp>.wav</samp> files, and the vanilla audio features (e.g. randomizing audio from one ID).
<ul>
  −
<li>Added new [[Modding:Dialogue|dialogue]] keys:
  −
{| class="wikitable"
  −
|-
  −
! asset
  −
! key format
  −
! description
  −
|-
  −
|rowspan="9"| <samp>Characters/Dialogue/&lt;name&gt;</samp>
  −
| <samp>AcceptGift_{{t|id}}</samp><br /><samp>AcceptGift_{{t|tag}}</samp>
  −
| The dialogue shown when receiving a non-birthday gift from the player. This can be by item ID (like <samp>AcceptGift_(O)128</samp>) or context tag (like <samp>AcceptGift_category_fish</samp>). If omitted, defaults to the dialogue in <samp>Data/NPCGiftTastes</samp>.
  −
|-
  −
| <samp>AcceptBirthdayGift_{{t|id}}</samp><br /><samp>AcceptBirthdayGift_{{t|tag}}</samp><br /><samp>AcceptBirthdayGift_{{t|taste}}</samp><br /><samp>AcceptBirthdayGift_Negative</samp><br /><samp>AcceptBirthdayGift_Positive</samp><br /><samp>AcceptBirthdayGift</samp>
  −
| The dialogue shown when receiving a birthday gift from the player. If omitted, defaults to the generic translations for all NPCs.
     −
The first matching dialogue is used in this order:
+
Audio is also more fault-tolerant in 1.6: the game no longer crashes when playing audio which doesn't exist, it now logs an error and returns a default quiet click sound instead. (If you use <code>try..catch</code> to check if an audio cue exists, you should check <code>Game1.soundbank.Exists(name)</code> instead.)
# by item ID (like <samp>AcceptBirthdayGift_(O)128</samp>);
  −
# by context tag (like <samp>AcceptBirthdayGift_category_fish</samp>);
  −
# by gift taste (one of <samp>AcceptBirthdayGift_Loved</samp>, <samp>AcceptBirthdayGift_Liked</samp>, <samp>AcceptBirthdayGift_Neutral</samp>, <samp>AcceptBirthdayGift_Disliked</samp>, or <samp>AcceptBirthdayGift_Hated</samp>);
  −
# <samp>AcceptBirthdayGift_Negative</samp> (hated or disliked gift) or <samp>AcceptBirthdayGift_Positive</samp> (neutral, liked, or loved gift);
  −
# for all items (via <samp>AcceptBirthdayGift</samp>).
     −
Note that any portrait in the dialogue will be overridden based on the gift taste.
+
===Custom buffs===
|-
+
{{/doc status|a new doc page|done=false}}
| <samp>RejectItem_{{t|id}}</samp><br /><samp>RejectItem_{{t|tag}}</samp>
  −
| If set, the NPC will refuse to accept any matching item and show this dialogue instead. This can be by item ID (like <samp>RejectItem_(O)128</samp>) or context tag (like <samp>RejectItem_category_fish</samp>). This can prevent gifting, movie tickets, bouquets, mermaid pendants, etc. However it won't prevent accepting an item for an active quest or special order.
  −
|-
  −
| <samp>Fair_Judging</samp>
  −
| At the [[Stardew Valley Fair]], the dialogue shown while Lewis is judging the grange displays. If omitted, the NPC will keep their normal festival dialogue.
     −
If this is set without <samp>Fair_Judged*</samp>, the NPC will keep this dialogue after judging is done.
+
: ''See also: [[#Buff overhaul|buff overhaul]].''
   −
''This replaces the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp>: <samp>Event.cs.1602</samp> (Marnie), <samp>Event.cs.1604</samp> (Pierre), and <samp>Event.cs.1606</samp> (Willy).''
+
You can now define custom buffs by editing the new <samp>Data/Buffs</samp> asset. You can then use the buff from other places like <samp>Data/Object</samp>'s <samp>Buff</samp> field or the C# <samp>Buff</samp> constructor.
|-
  −
| <samp>Fair_Judged_PlayerLost_PurpleShorts</samp><br /><samp>Fair_Judged_PlayerLost_Skipped</samp><br /><samp>Fair_Judged_PlayerLost</samp><br /><samp>Fair_Judged_PlayerWon</samp><br /><samp>Fair_Judged</samp>
  −
| At the [[Stardew Valley Fair]], the dialogue shown after Lewis finishes judging the grange displays.
     −
The first matching dialogue is used in this order:
+
This consists of a string → model lookup, where...
# <samp>Fair_Judged_PlayerLost_PurpleShorts</samp>: the player put the [[Secrets#Lucky Purple Shorts|lucky purple shorts]] in their display (which is an automatic loss).  Defaults to <samp>Fair_Judged_PlayerLost</samp> if omitted.
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the buff.
# <samp>Fair_Judged_PlayerLost_Skipped</samp>: the player didn't put anything in their display. Defaults to <samp>Fair_Judged_PlayerLost</samp> if omitted.
+
* The value is a model with the fields listed below.
# <samp>Fair_Judged_PlayerLost</samp> or <samp>Fair_Judged_PlayerWon</samp>: the player didn't/did win first place. Defaults to <samp>Fair_Judged</samp> if omitted.
  −
# <samp>Fair_Judged</samp>: shown if a more specific dialogue didn't match. If omitted, the NPC will keep their current dialogue.
     −
''These replace the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp>: <samp>Event.cs.1591</samp> (Pierre when he won), <samp>Event.cs.1593</samp> (Pierre when the player won), <samp>Event.cs.1595</samp> (Marnie), <samp>Event.cs.1597</samp> (Willy), and <samp>Event.cs.1600</samp> (Marnie for the purple shorts).''
+
{| class="wikitable"
 
|-
 
|-
| <samp>FlowerDance_Accept_Roommate</samp><br /><samp>FlowerDance_Accept_Spouse</samp><br /><samp>FlowerDance_Accept</samp>
+
! field
| At the [[Flower Dance]], the dialogue shown when the NPC agrees to dance. The game will prefer the <samp>_Roommate</samp> (if roommates) or <samp>_Spouse</samp> (if married) variant if applicable, else it'll check for the normal key. If omitted, defaults to a generic accept dialogue.
+
! purpose
 
  −
''This replaces the previously hardcoded translations in <samp>Strings/StringsFromCSFiles</samp> (<samp>Event.cs.1613</samp>, <samp>Event.cs.1615</samp>, <samp>Event.cs.1617</samp>, <samp>Event.cs.1619</samp>, <samp>Event.cs.1621</samp>, <samp>Event.cs.1623</samp>, <samp>Event.cs.1625</samp>, <samp>Event.cs.1627</samp>, <samp>Event.cs.1629</samp>, and <samp>Event.cs.1631</samp>).''
   
|-
 
|-
| <samp>FlowerDance_Decline</samp>
+
| <samp>DisplayName</samp>
| At the [[Flower Dance]], the dialogue shown when the NPC declines to dance. This replaces the former <samp>danceRejection</samp> key (which still works as a fallback).
+
| A [[Modding:Tokenizable strings|tokenizable string]] for the buff name.
 
|-
 
|-
| <samp>WinterStar_GiveGift_Before_Roommate</samp><br /><samp>WinterStar_GiveGift_Before_Spouse</samp><br /><samp>WinterStar_GiveGift_Before</samp><br /><samp>WinterStar_GiveGift_After_Roommate</samp><br /><samp>WinterStar_GiveGift_After_Spouse</samp><br /><samp>WinterStar_GiveGift_After</samp>
+
| <samp>Description</samp>
| At the [[Feast of the Winter Star]], the dialogue shown when the NPC gives the player their gift (before and after the player opens it). The game will prefer the <samp>_Roommate</samp> (if roommates) or <samp>_Spouse</samp> (if married) variant if applicable, else it'll check for the normal key. If omitted, the before/after dialogues each separately default to a generic translation for all NPCs.
+
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the buff name. Default none.
 
|-
 
|-
| <samp>WinterStar_ReceiveGift_{{t|id}}</samp><br /><samp>WinterStar_ReceiveGift_{{t|tag}}</samp><br /><samp>WinterStar_ReceiveGift</samp>
+
| <samp>IsDebuff</samp>
| At the [[Feast of the Winter Star]], the dialogue shown when receiving their gift from the player. This can be by item ID (like <samp>WinterStar_ReceiveGift_(O)128</samp>), context tag (like <samp>WinterStar_ReceiveGift_category_fish</samp>), or for any item (like <samp>WinterStar_ReceiveGift</samp>). If omitted, defaults to the generic translation for all NPCs.
+
| ''(Optional)'' >Whether this buff counts as a debuff, so its duration should be halved when wearing a [[Sturdy Ring|sturdy ring]]. Default false.
|}
  −
</li>
  −
<li>Added new [[Modding:Dialogue|dialogue]] commands:
  −
{| class="wikitable"
   
|-
 
|-
! command
+
| <samp>GlowColor</samp>
! description
+
| ''(Optional)'' The glow color to apply to the player. See [[#Color fields|color format]]. Default none.
 
|-
 
|-
| <samp>$f {{t|response IDs}}</samp>
+
| <samp>Duration</samp>
| Forget any number of space-delimited [[Modding:Dialogue#Response IDs|dialogue response IDs]] previously answered by the player.
+
| The duration in milliseconds for which the buff should be active. This can be set to value <samp>-2</samp> for a buff that should last for the rest of the day.
 
|-
 
|-
| <samp>$t {{t|topic ID}} {{o|day length}}</samp>
+
| <samp>MaxDuration</samp>
| Add a [[Modding:Dialogue#Conversation topics|conversation topic]] for the next {{o|day length}} days (default 4 days).
+
| ''(Optional)'' The maximum buff duration in milliseconds. If specified and larger than <samp>Duration</samp>, a random value between <samp>Duration</samp> and <samp>MaxDuration</samp> will be selected for each buff. Default none.
 
|-
 
|-
| <samp>$v {{t|event id}} {{o|check preconditions}} {{o|skip if seen}}</samp>
+
| <samp>IconTexture</samp>
| Immediately start an [[Modding:Event data|event]] and end the current dialogue, subject to the conditions:
+
| The asset name for the texture containing the buff's sprite.
* {{o|check preconditions}}: whether to ignore the command if the [[Modding:Event data#Event preconditions|event's preconditions]] don't match (one of <samp>true</samp> or <samp>false</samp>). Default true.
+
|-
* {{o|skip if seen}}: whether to ignore the command if the player has already seen the given event. Default true.
+
| <samp>IconSpriteIndex</samp>
 +
| ''(Optional)'' The sprite index for the buff icon within the <samp>IconTexture</samp>. Default 0.
 +
|-
 +
| <samp>Effects</samp>
 +
| ''(Optional)'' The buff attributes to apply. Default none.
   −
If the event is skipped, the dialogue continues to the next line instead.
+
This consists of a model with any combination of these fields:
 
+
{| class="wikitable"
For example, <code>$v 60367 false false</code> will replay the bus arrival event from the start of the game.
+
|-
 +
! field
 +
! purpose
 +
|-
 +
| <samp>FarmingLevel</samp><br /><samp>FishingLevel</samp><br /><samp>ForagingLevel</samp><br /><samp>LuckLevel</samp><br /><samp>MiningLevel</samp>
 +
| ''(Optional)'' An amount applied to the matching [[Skills|skill level]] while the buff is active. This can be negative for a debuff. Default 0.
 +
|-
 +
| <samp>Attack</samp><br /><samp>Defense</samp><br /><samp>MagneticRadius</samp><br /><samp>MaxStamina</samp><br /><samp>Speed</samp>
 +
| ''(Optional)'' An amount applied to the player's [[attack]], [[defense]], [[Magnetism|magnetic radius]], maximum [[Energy|stamina]], or [[speed]] while the buff is active. This can be negative for a debuff. Default 0.
 
|}
 
|}
</li>
+
|-
<li>[[Modding:Dialogue#Response IDs|Dialogue response IDs]] are now [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string IDs]].</li>
+
| <samp>ActionsOnApply</samp>
<li>[[Secrets#Item Spawn Cheat|Item spawn codes]] now use string item IDs. That means you can spawn any item using its [[#Custom items|qualified item ID]] (like <code>[(F)1664]</code> for a [[Mystic Rug]]), but can no longer prepend zeros (e.g. <code>[128]</code> is a pufferfish but <code>[0128]</code> is an error item).</li>
+
| ''(Optional)'' Run any number of [[Modding:Trigger actions|trigger action strings]] when the buff is applied to the current player. For example, this increments a player stat:
<li>For C# mods, <samp>Dialogue</samp> now tracks the translation key used to build it (when applicable). For example, you can detect when the player is rejected at the [[Flower Dance]] (derived from {{github|spacechase0/StardewValleyMods|Three-Heart Dance Partner}}):
+
<syntaxhighlight lang="js">
<syntaxhighlight lang="c#">
+
"ActionsOnApply": [
private void OnMenuChanged(object sender, MenuChangedEventArgs e)
+
     "IncrementStat {{ModId}}_NumberEaten 1"
{
+
]
     bool isDanceRejection =
  −
        Game1.currentLocation?.currentEvent?.FestivalName == "Flower Dance"
  −
        && e.NewMenu is DialogueBox dialogueBox
  −
        && dialogueBox.characterDialogue is {} dialogue
  −
        && dialogue.TranslationKey == $"Characters\\Dialogue\\{dialogue.speaker?.Name}:danceRejection";
  −
}
   
</syntaxhighlight>
 
</syntaxhighlight>
 +
|-
 +
| <samp>CustomFields</samp>
 +
| ''(Optional)'' The [[#Custom data fields|custom fields]] for this entry.
 +
|}
   −
For C# mods that create <samp>Dialogue</samp> instances directly, there's a few ways to do it now:
+
===Custom data fields===
<syntaxhighlight lang="c#">
+
{{/doc status|[[Modding:Common data field types#Custom fields]]|done=true}}
// from a translation key
  −
var dialogue = new Dialogue(npc, "Strings\\StringsFromCSFiles:Utility.cs.5360");
     −
// from custom text (with or without a translation key)
+
Many data assets now have a <samp>CustomFields</samp> field. This is ignored by the game, but lets mods add their own data (e.g. to enable mod framework features).
var dialogue = new Dialogue(npc, null, "Some arbitrary text to show as-is");
     −
// from a translation with tokens
+
For example, a content pack can [[#Custom crops|add a crop]] with custom fields:
var dialogue = Dialogue.FromTranslation(npc, "Data\\ExtraDialogue:PurchasedItem_2_QualityLow_Willy", whatToCallPlayer, particle, i.DisplayName);
+
{{#tag:syntaxhighlight|<nowiki>
</syntaxhighlight>
+
{
 
+
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
You can also easily add fallback logic using <samp>Dialogue.TryGetDialogue</samp> or <samp>npc.TryGetDialogue</samp>. For example:
+
    "Changes": [
<syntaxhighlight lang="c#">
+
        {
Dialogue dialogue =
+
            "Action": "EditData",
     npc.TryGetDialogue($"rejection_{itemId}_{locationName}_{x}_{y}")
+
            "Target": "Data/Crops",
     ?? npc.TryGetDialogue($"rejection_{itemId}_{locationName}")
+
            "Entries": {
     ?? npc.TryGetDialogue($"rejection_{itemId}")
+
                "Example.Id_CucumberSeeds": {
    ?? new Dialogue(npc, "Strings\\StringsFromCSFiles:NPC.cs.3971");
+
                    "Seasons": [ "summer" ],
 +
                    "DaysInPhase": [ 1, 2, 2, 2 ],
 +
                    "HarvestItemId": "Example.Id_Cucumber",
 +
                    "Texture": "{{InternalAssetKey: assets/crops.png}}",
 +
                    "SpriteIndex": 0,
 +
 
 +
                    "CustomFields": {
 +
                        "Example.FrameworkMod/WetTexture": "{{InternalAssetKey: assets/crops-wet.png}}"
 +
                    }
 +
                }
 +
            }
 +
        }
 +
    ]
 +
}</nowiki>|lang=javascript}}
 +
 
 +
And then a C# mod could handle the custom field if it's set:
 +
<syntaxhighlight lang="c#">
 +
if (Game1.currentLocation.IsRainingHere())
 +
{
 +
     CropData data = crop.GetData();
 +
     if (data != null && data.CustomFields.TryGetValue("Example.FrameworkMod/WetTexture", out string textureName))
 +
     {
 +
        // do magic
 +
    }
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
</li>
  −
<li>The <samp>reject_{{t|item id}}</samp> dialogue key now also works with [[Movie Ticket|movie tickets]], [[Void Ghost Pendant|void ghost pendants]], [[bouquet]]s, [[Wilted Bouquet|wilted bouquets]], and [[Mermaid's Pendant|mermaids' pendants]].</li>
  −
<li>The 'reveal taste' dialogue command now uses the format <samp>%revealtaste:{{t|npc name}}:{{t|item ID}}</samp> to support item IDs. (The previous <samp>%revealtaste{{t|npc name}}{{t|item index}}</samp> format still works to support old content packs, but the item index can only be a number.)</li>
  −
<li>NPCs no longer override the portrait for a gift taste dialogue that uses a portrait command explicitly.</li>
  −
<li>Fixed unknown [[Modding:Dialogue|dialogue]] commands starting with <samp>$</samp> being parsed as a portrait number when not numeric.</li>
  −
<li>Fixed NPCs only using a <code>{day name}{hearts}_{year}</code> dialogue if they also have a <code>{day name}{hearts}</code> one.</li>
  −
<li>Fixed NPCs only using the <code>MovieInvitation</code> dialogue key in English.</li>
  −
</ul>
     −
===Schedule changes===
+
See <samp>CustomFields</samp> in the docs for each asset type to see if it's supported. Besides the sections listed on this page, custom fields were also added to <samp>Data/AdditionalFarms</samp>, <samp>Data/AdditionalLanguages</samp>, <samp>Data/FishPondData</samp>, <samp>Data/HomeRenovations</samp>, <samp>Data/Movies</samp>, and <samp>Data/SpecialOrders</samp>.
<ul>
  −
<li>Schedule keys are now case-insensitive.</li>
  −
<li>Added a new <samp>{{t|day of week}}_{{t|min hearts}}</samp> schedule key.</li>
  −
<li>Added an <samp>NPC.ScheduleKey</samp> field which always matches their loaded schedule.</li>
  −
<li>Schedule commands now trim surrounding whitespace, so they can be multilined for readability. For example:
  −
<syntaxhighlight lang="js">"Wed": "
  −
    1000 ArchaeologyHouse 11 9 0/
  −
    1800 Town 47 87 0/
  −
    2200 SeedShop 1 9 3 abigail_sleep
  −
"</syntaxHighlight></li>
  −
<li>Removed an unintended schedule fallback to a <samp>{season}_spring_{hearts}</samp> key. It'll skip to the <samp>spring</samp> default instead.</li>
  −
<li>Schedules are now fault-tolerant:
  −
* Fixed crash if a selected schedule can't be parsed. The NPC now logs an error and continues with the next fallback instead.
  −
* Fixed crash if certain hardcoded schedules aren't present (like Penny's <samp>marriageJob</samp> or Pam's <samp>bus</samp>).
  −
* Fixed error if a schedule command is empty.</li>
  −
<li>For C# mods, removed the <samp>dayOfMonth</samp> parameter in <samp>NPC.getSchedule()</samp>. This was misleading since it used <samp>Game1.dayOfMonth</samp> in all but one line regardless.</li>
  −
</ul>
     −
===Other NPC changes===
+
See [[Modding:Common data field types#Custom fields]] for the main docs.
<ul>
+
 
<li>Added <samp>Game1.characterData</samp> and <samp>Game1.farmAnimalData</samp> to read NPC/animal info without constantly reloading the <samp>Data/Characters</samp> or <samp>Data/FarmAnimals</samp> asset.</li>
+
===Custom giant crops===
<li>All translated NPC names are now in <samp>Strings/NPCNames</samp>.
+
{{/doc status|a new doc page|done=false}}
<li>Added new fields & methods for C# mods:
+
 
 +
You can now add/edit [[Crops#Giant Crops|giant crops]] by editing the <samp>Data/GiantCrops</samp> data asset.
 +
 
 +
This consists of a string → model lookup, where...
 +
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the giant crop.
 +
* The value is a model with the fields listed below.
    
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! type
+
! field
! field/method
   
! effect
 
! effect
 
|-
 
|-
|rowspan="2"| <samp>AdventureGuild</samp>
+
| <samp>FromItemId</samp>
| <samp>IsComplete(data)</samp>
+
| The [[#Custom items|item ID]] (qualified or unqualified) for the harvest ID of the regular crop which can turn into this giant crop. For example, <samp>(O)254</samp> is [[melon]].
| Get whether an [[Adventurer's Guild]] monster eradication goal has been completed, regardless of whether the player collected its rewards yet.
+
 
 +
Any number of giant crops can use the same <samp>FromItemId</samp> value. The first giant crop whose other fields match (if any) will spawn.
 
|-
 
|-
| <samp>HasCollectedReward(player, id)</samp>
+
| <samp>HarvestItems</samp>
| Get whether a given player has completed an [[Adventurer's Guild]] monster eradication goal and collected its rewards. For example:
+
| The items which can be dropped when you break the giant crop. If multiple items match, they'll all be dropped.
<syntaxhighlight lang="c#">
+
 
bool isPhoneUnlocked = AdventureGuild.HasCollectedReward(Game1.player, "Gil_FlameSpirits");
+
This consists of a list of models with these fields:
</syntaxhighlight>
+
{| class="wikitable"
 
|-
 
|-
| <samp>AnimalHouse</samp>
+
! field
| <samp>adoptAnimal</samp>
+
! effect
| Add an animal to this location and set the location as the animal's home.
   
|-
 
|-
| <samp>Character</samp>
+
| ''common fields''
| <samp>GetGender</samp>
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for harvest items.
| Get the character's gender as one of the numeric constants (<samp>NPC.female</samp>, <samp>NPC.male</samp>, or <samp>NPC.undefined</samp>). This returns the specific gender for players, villager NPCs, and children; other NPCs (like monsters) return <samp>NPC.undefined</samp>.
+
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
|rowspan="7"| <samp>FarmAnimal</samp>
+
| <samp>Chance</samp>
| <samp>isAdult</samp>
+
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
| Get whether the farm animal is fully grown (opposite of <samp>isBaby()</samp>).
   
|-
 
|-
| <samp>CanGetProduceWithTool</samp>
+
| <samp>ForShavingEnchantment</samp>
| Get whether the farm animal's produce can be collected with a given tool (e.g. milk pail for a cow).
+
| ''(Optional)'' Whether this item is only dropped for [[Enchantments#Tool enchantments|Shaving enchantment]] drops (<samp>true</samp>), only when the giant crop is broken (<samp>false</samp>), or both (<samp>null</samp>). Default both.
 
|-
 
|-
| <samp>CanLiveIn</samp>
+
| <samp>ScaledMinStackWhenShaving</samp><br /><samp>ScaledMaxStackWhenShaving</samp>
| Get whether the animal can be added to a building.
+
| ''(Optional)'' If set, the min/max stack size when this item is dropped due to the [[Forge#Enchantments|shaving enchantment]], scaled to the tool's power level.
 +
 
 +
This value is multiplied by the health deducted by the tool hit which triggered the enchantment. For example, an iridium axe which reduced the giant crop's health by 3 points will produce three times this value per hit.
 +
 
 +
If both fields are set, the stack size is randomized between them. If only one is set, it's applied as a limit after the generic fields. If neither is set, the generic <samp>MinStack</samp>/<samp>MaxStack</samp> fields are applied as usual without scaling.
 +
|}
 
|-
 
|-
| <samp>GetDisplayName</samp><br /><samp>GetShopDescription</samp>
+
| <samp>Texture</samp>
| Get the translated display name or shop description for this animal.
+
| The asset name for the texture containing the giant crop's sprite.
 
|-
 
|-
| <samp>GetHarvestType</samp>
+
| <samp>TexturePosition</samp>
| Get whether the animal's produce is dropped or collected with a tool.
+
| ''(Optional)'' The top-left pixel position of the sprite within the <samp>Texture</samp>, specified as a model with <samp>X</samp> and <samp>Y</samp> fields. Defaults to (0, 0).
 
|-
 
|-
| <samp>growFully</samp>
+
| <samp>TileSize</samp>
| Instantly age the animal to adulthood if it's still a baby.
+
| ''(Optional)'' The area in tiles occupied by the giant crop, specified as a model with <samp>X</samp> and <samp>Y</samp> fields. This affects both its sprite size (which should be 16 pixels per tile) and the grid of crops needed for it to grow. Note that giant crops are drawn with an extra tile's height. Defaults to (3, 3).
 
|-
 
|-
| <samp>ReloadTextureIfNeeded</samp>
+
| <samp>Health</samp>
| Update the animal sprite based on the current state + data.
+
| ''(Optional)'' The health points that must be depleted to break the giant crop. The number of points depleted per [[axe]] chop depends on the axe power level. Default 3.
 
|-
 
|-
| rowspan="3"| <samp>Farmer</samp>
+
| <samp>Chance</samp>
| <samp>GetDisplayPants</samp><br /><samp>GetDisplayShirt</samp>
+
| ''(Optional)'' The percentage chance that a given grid of crops will grow into the giant crop each night, as a value between 0 (never) and 1 (always). Default 0.01 (1%).
| Get the texture and sprite index to draw for the player's pants or shirt. This accounts for override clothing, worn clothing, and the default clothing drawn when the farmer isn't wearing anything.
     −
For example:
+
Note that the chance is checked for each giant crop that applies. If three giant crops each have a 1% chance of spawning for the same crop, then there's a 3% chance that one of them will spawn.
<syntaxhighlight lang="c#">
  −
Game1.player.GetDisplayShirt(out Texture2D texture, out int spriteIndex);
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>CanDyePants</samp><br /><samp>CanDyeShirt</samp>
+
| <samp>Condition</samp>
| Get whether the currently equipped pants or shirt can be [[Dyeing|dyed]].
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this giant crop is available to spawn. Defaults to always true.
 
|-
 
|-
| <samp>WearTemporaryWeddingAttire</samp><br /><samp>RemoveTemporaryWeddingAttire</samp>
+
| <samp>CustomFields</samp>
| Temporarily change the player into or out of their wedding attire. The default logic changes male farmers into the tuxedo, and has no effect on female farmers.
+
| The [[#Custom data fields|custom fields]] for this entry.
 +
|}
 +
 
 +
===Custom jukebox tracks===
 +
{{/doc status|a new doc page|done=false}}
 +
 
 +
You can now change [[jukebox]] audio tracks by editing the new <samp>Data/JukeboxTracks</samp> data asset.
 +
 
 +
This consists of a string → model lookup, where...
 +
* The key is the [[#Custom audio|audio cue ID]] to play (case-sensitive).
 +
* The value is a model with the fields listed below.
 +
 
 +
If the player has heard a music track not listed in <samp>Data/JukeboxTracks</samp>, it's automatically available with the title set to the cue name. To disable a track, add an entry with <samp>"Available": false</samp>.
 +
 
 +
{| class="wikitable"
 
|-
 
|-
|rowspan="4"| <samp>NPC</samp>
+
! field
| <samp>CanReceiveGifts</samp>
+
! effect
| Get whether this NPC can receive gifts from the player (regardless of whether they've already received one today).
   
|-
 
|-
| <samp>GetData</samp><br /><samp>NPC.TryGetData</samp>
+
| <samp>Name</samp>
| Get the underlying data from <samp>Data/Characters</samp> for this NPC, if any.
+
| ''(Optional)'' A [[Modding:Tokenizable strings|tokenizable string]] for the music track's in-game title. Defaults to the ID.
 
|-
 
|-
| <samp>NPC.GetDisplayName(name)</samp>
+
| <samp>Available</samp>
| Get the translated display name in the current language for an NPC by their internal name.
+
| ''(Optional)'' Whether the track should be shown in the jukebox menu. This can be <samp>true</samp> (always shown), <samp>false</samp> (never shown), or <samp>null</samp> (show if the player has heard it before). Default <samp>null</samp>.
 +
 
 +
Tracks with <samp>"Available": true</samp> are listed first in the jukebox menu.
 
|-
 
|-
| <samp>hasDarkSkin</samp>
+
| <samp>AlternativeTrackIds</samp>
| Whether this character has dark skin for the purposes of child genetics.
+
| ''(Optional)'' A list of other cue names for this audio track (not case-sensitive). If the player has heard any of these track IDs, this entry is available in the menu. Default none.
|-
+
 
| <samp>Pet</samp>
+
For example, this can be used when renaming a track to keep it unlocked for existing players:
| <samp>GetPetData</samp><br /><samp>TryGetData</samp>
+
<syntaxhighlight lang="js">
| Get the underlying data from <samp>Data/Pets</samp> for this pet, if any.
+
"{{ModId}}_TrackName": {
|-
+
    "Name": "{{i18n: track-name}}",
| <samp>ShopMenu</samp>
+
    "AlternativeTrackIds": [ "OldTrackName" ]
| <samp>ShopId</samp>
+
}
| A key which identifies the current shop. This may be the unique shop ID in <samp>Data/Shops</samp> for a standard shop, <samp>Dresser</samp> or <samp>FishTank</samp> for furniture, etc. This is guaranteed to be set to a relevant shop ID.
+
</syntaxhighlight>
 
  −
This replaces the former <samp>shopContext</samp> field, and will usually have the same value in cases where that was set to a unique shop ID.
  −
|-
  −
| <samp>Utility</samp>
  −
| <samp>getAllVillagers</samp>
  −
| Get all villager NPCs (excluding horses, pets, monsters, player children, etc). This works just like <samp>getAllCharacters</samp> with an added filter.
   
|}
 
|}
</li>
  −
<li>NPCs now update on save loaded when their home data changes.</li>
  −
<li><samp>NPC.reloadSprite()</samp> now has an argument to only reload the appearance, without changing other data.</li>
  −
<li><samp>Utility.getAllCharacters()</samp> now returns a plain <samp>List&lt;NPC&gt;</samp> value instead of a custom <samp>DisposableList&lt;NPC&gt;</samp>, so you can use normal LINQ querying on it.</li>
  −
<li><samp>Utility.GetHorseWarpRestrictionsForFarmer(player)</samp> now returns an enum (which is more efficient and easier for mods to patch), and added a new <samp>Utility.GetHorseWarpErrorMessage(restrictions)</samp> method to get the error message to show for it.</li>
  −
<li><samp>Farmer.hasAFriendWithHeartLevel</samp> now has an optional max-hearts argument.</li>
  −
<li>Removed most <samp>FarmAnimal</samp> fields/properties which just mirror the underlying data.</li>
  −
<li>Removed invalid item IDs in <samp>Data/NPCGiftTastes</samp>.</li>
  −
<li>Fixed NPCs sometimes duplicated on save load (particularly if their home location changed).</li>
  −
<li>Fixed child NPCs like [[Jas]] or [[Vincent]] ignoring relative titles like "mom" in <samp>Data/NPCDispositions</samp> (now <samp>Data/Characters</samp>) for reveal-gift-taste dialogues.</li>
  −
<li>Fixed custom NPCs ignoring dialogue when they use a subclass of <samp>NPC</samp>.</li>
  −
<li>Fixed monsters not loading their display name from <samp>Data/Monsters</samp> for English players.</li>
  −
<li>Fixed player children not applying the <samp>IsInvisible</samp> flag.</li>
  −
</ul>
     −
==What's new for everything else==
+
===Custom movies===
===Buff overhaul===
+
{{/doc status|[[Modding:Movie theater data]]|done=false}}
1.6 rewrites buffs to work more consistently and be more extensible:
     −
* Buff logic is unified into <samp>Game1.player.buffs</samp>, which is the single source of truth for buff data. This replaces the previous <samp>player.added*</samp> and <samp>player.appliedBuffs</samp> fields, <samp>BuffsDisplay</samp> logic, enchantment stat bonuses, and boots/ring attribute changes on (un)equip.
+
: ''See also: [[#Custom movie concessions|custom movie concessions]].''
* This also removes limitations on buff types (e.g. buffs can add weapon bonuses and weapons can add attribute buffs) and buffable equipment (e.g. equipped tools can have buffs too).
  −
* Buff effects are now fully recalculated when they change, to fix a range of longstanding bugs like attribute drift and double-debuffs. Just like before, the buffs are managed locally; only the buff IDs and aggregate attribute effects are synced.
     −
'''For C# mods:'''
+
[[Modding:Movie theater data#Movie data|Movie data]] was previously very limited and prone to mod conflicts, since (a) we needed incrementing movie IDs like <samp>spring_movie_3</samp>, (b) we were limited to one movie per season, and (c) all sprites for each movie had to be in the vanilla <samp>LooseSprites/Movies</samp> spritesheet.
* Each buff now has a unique string ID. You can apply a new buff with the same ID to replace it (so you no longer need to manually find and remove previous instances of the buff).
  −
* You can add standard buff effects to any equipment by overriding <samp>Item.AddEquipmentEffects</samp>, or add custom behaviour/buffs by overriding <samp>Item.onEquip</samp> and <samp>Item.onUnequip</samp>.
  −
* You can add custom food or drink buffs by overriding <samp>Item.GetFoodOrDrinkBuffs()</samp>.
  −
* The <samp>Buff</samp> constructor now supports a custom icon texture, sprite index, display name, description, and millisecond duration to fully support custom buffs.
  −
* You can change how buff attributes are displayed (or add new attributes) by extending the <samp>BuffsDisplay.displayAttributes</samp> list.
     −
For example, here's how to add a custom buff which adds +3 speed:
+
Stardew Valley 1.6 revamps how movies work to address those limitations.
   −
<syntaxhighlight lang="c#">
+
<dl>
Buff buff = new Buff(
+
<dt>Movie selection</dt>
    id: "Example.ModId/ZoomZoom",
+
<dd><p>Movies were previously selected based on a specific ID pattern: <samp>spring_movie_0</samp> would play in spring the year you built the movie theater, <samp>spring_movie_1</samp> would play in spring the next year, etc. That meant it'd take two in-game years to see the first custom movie, and ID conflicts had to be managed manually.</p>
    displayName: "Zoom Zoom", // can optionally specify description text too
  −
    iconTexture: this.Helper.ModContent.Load<Texture2D>("assets/zoom.png"),
  −
    iconSheetIndex: 0,
  −
    duration: 30_000, // 30 seconds
  −
    effects: new BuffEffects()
  −
    {
  −
        Speed = { 10 } // shortcut for buff.Speed.Value = 10
  −
    }
  −
);
  −
Game1.player.applyBuff(buff);
  −
</syntaxhighlight>
     −
You can also implement your own custom effects in code by checking if the buff is active, like <code>Game1.player.hasBuff("Example.ModId/ZoomZoom")</code>.
+
In 1.6, we can now have multiple movies per month based on the new fields listed below. If multiple movies can play in the same season, each movie will be shown for an equal block of days within the month (e.g. four movies will each play for seven consecutive days). If there are more movies than days, 28 movies will be chosen at random to play that month.</dd>
   −
===Custom audio===
+
<dt>New data fields</dd>
You can now add or edit [[Modding:Audio|music tracks or sound effects]] (called ''cues'') by editing the <samp>Data/AudioChanges</samp> asset. New cues are added to the game's soundbank, so they can be used anywhere normal audio can be used (e.g. the <samp>Music</samp> [[Modding:Maps|map property]]).
+
<dd>
 
+
{| class="wikitable"
====Format====
  −
The <samp>Data/AudioChanges</samp> asset consists of a string → model lookup, where the key matches the <samp>ID</samp>, and the value is a model with the fields below.
  −
 
  −
Entries in this asset describe an '''override''' applied to the soundbank. The override is applied permanently for the current game session, even if the asset is edited to remove it. Overriding a cue will reset all values to the ones specified.
  −
 
  −
{| class="wikitable"
   
|-
 
|-
 
! field
 
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>ID</samp>
+
| <samp>Seasons</samp>
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the audio cue, used when playing the sound in-game.
+
| ''(Optional)'' The seasons when the movie should play, or omit for any season. For example:
 +
<syntaxhighlight lang="js">"Seasons": [ "Spring", "Summer" ]</syntaxhighlight>
 
|-
 
|-
| <samp>FilePaths</samp>
+
| <samp>YearModulus</samp><br /><samp>YearRemainder</samp>
| A list of file paths (not asset names) from which to load the audio. These can be absolute paths or relative to the game's <samp>Content</samp> folder. Each file can be <samp>.ogg</samp> or <samp>.wav</samp>. If you list multiple paths, a random one will be chosen each time it's played.
+
| ''(Optional)'' If set, plays the movie on alternating years based on the formula <samp>theater_age % modulus == remainder</samp>, where <samp>theater_age</samp> is the number of years since the movie theater was built. If omitted, the movie plays in any year.
 +
 
 +
For example:
 +
 
 +
<syntaxhighlight lang="js">
 +
// play in the first year, and every second year thereafter
 +
"YearModulus": 2,
 +
"YearRemainder": 0
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="js">
 +
// play in the second year, and every second year thereafter
 +
"YearModulus": 2,
 +
"YearRemainder": 1
 +
</syntaxhighlight>
 
|-
 
|-
| <samp>Category</samp>
+
| <samp>Texture</samp>
| The [[Modding:Audio#Category list|audio category]], which determines which volume slider in the game options applies. This should be one of <samp>Default</samp>, <samp>Music</samp>, <samp>Sound</samp>, <samp>Ambient</samp>, or <samp>Footsteps</samp> (see [[Modding:Audio#Category list|a description of each category]]). Defaults to <samp>Default</samp>.
+
| ''(Optional)'' The asset name for the movie poster and screen images, or omit to use <samp>LooseSprites\Movies</samp>.
 +
 
 +
This must be a spritesheet with one 490×128 pixel row per movie. A 13×19 area in the top-left corner of the row should contain the movie poster. With a 16-pixel offset from the left edge, there should be two rows of five 90×61 pixel movie screen images, with a six-pixel gap between each image. (The movie doesn't need to use all of the image slots.)
 
|-
 
|-
| <samp>StreamedVorbis</samp>
+
| <samp>CranePrizes</samp>
| Whether the audio should be streamed from disk when it's played, instead of being loaded into memory ahead of time. This is only possible for [[wikipedia:Vorbis|Ogg Vorbis]] (<samp>.ogg</samp>) files, which otherwise will be decompressed in-memory on load. Default false.
+
| ''(Optional)'' The items to add to the [[Movie Theater#Crane Game|crane game]] prize pool on days when this movie is playing, if any.
   −
This is a tradeoff between memory usage and performance, so you should consider which value is best for each audio cue:
+
This consists of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! value
+
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>true</samp>
+
| ''common fields''
| Reduces memory usage when the audio cue isn't active, but increases performance impact when it's played. Playing the audio multiple times will multiply the memory and performance impact while they're active, since each play will stream a new instance. Recommended for longer audio cues (like music or ambient noise), or cues that are rarely used in a specific scenario (e.g. a sound that only plays once in an event).
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields supported for ammo items.
 +
 
 +
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 
|-
 
|-
| <samp>false</samp>
+
| <samp>Rarity</samp>
| Increases memory usage (since it's fully loaded into memory), but reduces performance impact when it's played. It can be played any number of times without affecting memory or performance (it'll just play the cached audio). Recommended for sound effects, or short audio cues that are played occasionally.
+
| ''(Optional)'' The prize pool to add the item to. The possible values are <samp>1</samp> (common), <samp>2</samp> (rare), and <samp>3</samp> (deluxe). Default <samp>1</samp>.
 
|}
 
|}
 
|-
 
|-
| <samp>Looped</samp>
+
| <samp>ClearDefaultCranePrizeGroups</samp>
| Whether the audio cue loops continuously until stopped. Default false.
+
| ''(Optional)'' The prize pools whose default items to discard, so only those specified by <samp>CranePrizes</samp> are available. Default none.
|-
+
 
| <samp>UseReverb</samp>
+
For example:
| Whether to apply a [[wikipedia:Reverberation|reverb]] effect to the audio. Default false.
+
<syntaxhighlight lang="js">"ClearDefaultCranePrizeGroups": [ 2, 3 ]</syntaxhighlight>
|-
  −
| <samp>CustomFields</samp>
  −
| The [[#Custom data fields|custom fields]] for this entry.
   
|}
 
|}
 +
</dd>
   −
====Example====
+
<dt>Other changes</dt>
This content pack adds a new music cue to the game, and plays it when the player enters the bus stop:
+
<dd>
 +
* <samp>Data/Movies</samp>, <samp>Data/Concessions</samp>, and <samp>Data/MoviesReactions</samp> no longer have language variants. Instead translations were moved into <samp>Strings/*</samp> assets, and the data assets use [[Modding:Tokenizable strings|tokenizable strings]] to get text.
 +
* <samp>Data/Movies</samp> is now a list instead of a dictionary. The order determines the order movies are shown within a season. Content packs can edit them the same way as before.
 +
* Added a <samp>debug movieSchedule {{o|year}}</samp> command to help troubleshoot movie selection.
 +
* Added methods for C# mods: <samp>MovieTheater.GetMovieToday()</samp>, <samp>GetUpcomingMovie()</samp>, and <samp>GetUpcomingMovie(afterDate)</samp>.
 +
</dd>
 +
</dl>
    +
For example, this content pack adds a new 'Pufferchick II' movie which plays in winter every third year:
 
{{#tag:syntaxhighlight|<nowiki>
 
{{#tag:syntaxhighlight|<nowiki>
 
{
 
{
 
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 
     "Changes": [
 
     "Changes": [
        // add music cue
   
         {
 
         {
 
             "Action": "EditData",
 
             "Action": "EditData",
             "Target": "Data/AudioChanges",
+
             "Target": "Data/Movies",
 
             "Entries": {
 
             "Entries": {
                 "Example.ModId_Music": {
+
                 "{{ModId}}_PufferchickII": {
                     "ID": "Example.ModId_Music",
+
                     "Id": "{{ModId}}_PufferchickII", // must specify ID again when creating a new entry
                     "Category": "Music",
+
 
                     "FilePaths": [ "{{AbsoluteFilePath: assets/music.ogg}}" ],
+
                    "Seasons": [ "winter" ],
                     "StreamedVorbis": true,
+
                    "YearModulus": 3,
                     "Looped": true
+
                    "YearRemainder": 0,
 +
 
 +
                    "Title": "Pufferchick II", // display text should usually use {{i18n}} for translations in actual usage
 +
                    "Description": "A sequel to the breakthrough adventure anime Pufferchick. The world is saved; what happens next?",
 +
                     "Tags": [ "family", "adventure" ],
 +
 
 +
                     "Texture": "{{InternalAssetKey: assets/movie.png}}", // an image in your content pack
 +
                     "SheetIndex": 0,
 +
 
 +
                     "Scenes": [ ... ]
 
                 }
 
                 }
            }
  −
        },
  −
  −
        // add to bus stop
  −
        {
  −
            "Action": "EditMap",
  −
            "Target": "Maps/BusStop",
  −
            "MapProperties": {
  −
                "Music": "Example.ModId_Music"
   
             }
 
             }
 
         }
 
         }
Line 6,042: Line 6,169:  
}</nowiki>|lang=javascript}}
 
}</nowiki>|lang=javascript}}
   −
====Other changes====
+
===Custom wedding event===
* The game no longer crashes when playing audio which doesn't exist. It now logs an error and returns a default quiet click sound instead. (If you use <code>try..catch</code> to check if an audio cue exists, you should check <code>Game1.soundbank.Exists(name)</code> instead.)
+
{{/doc status|a new doc page|done=false}}
   −
===Custom data fields===
+
The [[Marriage#The Wedding|wedding]] event can now be changed by editing the <samp>Data\Weddings</samp> data asset, which consists of a data model with two relevant fields (listed below).
Many data assets now have a <samp>CustomFields</samp> field. This is ignored by the game, but lets mods add their own data (e.g. to enable mod framework features).
     −
For example, a content pack can [[#Custom crops|add a crop]] with custom fields:
+
{| class="wikitable"
{{#tag:syntaxhighlight|<nowiki>
  −
{
  −
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
  −
    "Changes": [
  −
        {
  −
            "Action": "EditData",
  −
            "Target": "Data/Crops",
  −
            "Entries": {
  −
                "Example.Id_CucumberSeeds": {
  −
                    "Seasons": [ "summer" ],
  −
                    "DaysInPhase": [ 1, 2, 2, 2 ],
  −
                    "HarvestItemId": "Example.Id_Cucumber",
  −
                    "Texture": "{{InternalAssetKey: assets/crops.png}}",
  −
                    "SpriteIndex": 0,
  −
 
  −
                    "CustomFields": {
  −
                        "Example.FrameworkMod/WetTexture": "{{InternalAssetKey: assets/crops-wet.png}}"
  −
                    }
  −
                }
  −
            }
  −
        }
  −
    ]
  −
}</nowiki>|lang=javascript}}
  −
 
  −
And then a C# mod could handle the custom field if it's set:
  −
<syntaxhighlight lang="c#">
  −
if (Game1.currentLocation.IsRainingHere())
  −
{
  −
    CropData data = crop.GetData();
  −
    if (data != null && data.CustomFields.TryGetValue("Example.FrameworkMod/WetTexture", out string textureName))
  −
    {
  −
        // do magic
  −
    }
  −
}
  −
</syntaxhighlight>
  −
 
  −
See <samp>CustomFields</samp> in the docs for each asset type to see if it's supported. Besides the sections listed on this page, custom fields were also added to <samp>Data/AdditionalFarms</samp>, <samp>Data/AdditionalLanguages</samp>, <samp>Data/FishPondData</samp>, <samp>Data/Movies</samp>, and <samp>Data/SpecialOrders</samp>.
  −
 
  −
===Custom giant crops===
  −
You can now add/edit [[Crops#Giant Crops|giant crops]] by editing the <samp>Data/GiantCrops</samp> data asset.
  −
 
  −
This consists of a string → model lookup, where...
  −
* The key is a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for the giant crop.
  −
* The value is a model with the fields listed below.
  −
 
  −
{| class="wikitable"
   
|-
 
|-
 
! field
 
! field
 
! effect
 
! effect
 
|-
 
|-
| <samp>FromItemId</samp>
+
| <samp>EventScript</samp>
| The [[#Custom items|item ID]] (qualified or unqualified) for the harvest ID of the regular crop which can turn into this giant crop. For example, <samp>(O)254</samp> is [[melon]].
+
| The [[Modding:Event data|event scripts]] which play the wedding. The game will use the script for the spouse NPC/player if it exists, otherwise it'll use the default script.
   −
Any number of giant crops can use the same <samp>FromItemId</samp> value. The first giant crop whose other fields match (if any) will spawn.
+
This consists of a string → string dictionary, where...
|-
+
* The key is an NPC internal name (like <samp>Abigail</samp>), unique player ID, or <samp>default</samp> for the default script (which handles marrying either an NPC or player);
| <samp>HarvestItems</samp>
+
* The value is a [[Modding:Tokenizable strings|tokenizable strings]] for the event script to play.
| The items which can be dropped when you break the giant crop. If multiple items match, they'll all be dropped.
     −
This consists of a list of models with these fields:
+
The event scripts also have access to three extra tokens:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! token
 
! effect
 
! effect
 
|-
 
|-
| ''common fields''
+
| <samp>[SetupContextualWeddingAttendees]</samp>
| See [[#Item spawn fields|item spawn fields]] for the generic item fields supported for harvest items.
+
| The concatenated <samp>Setup</samp> values for each of the <samp>Attendees</samp> present in the wedding.
 
  −
If set to an [[#Item queries|item query]] which returns multiple items, one of them will be selected at random.
   
|-
 
|-
| <samp>Chance</samp>
+
| <samp>[ContextualWeddingCelebrations]</samp>
| ''(Optional)'' The probability that this entry is selected, as a value between 0 (never drops) and 1 (always drops). Default 1 (100% chance).
+
| The concatenated <samp>Celebration</samp> values for each of the <samp>Attendees</samp> present in the wedding.
 
|-
 
|-
| <samp>ForShavingEnchantment</samp>
+
| <samp>[SpouseActor]</samp>
| ''(Optional)'' Whether this item is only dropped for [[Enchantments#Tool enchantments|Shaving enchantment]] drops (<samp>true</samp>), only when the giant crop is broken (<samp>false</samp>), or both (<samp>null</samp>). Default both.
+
| The actor ID for the NPC or other player being married (like <samp>Abigail</samp> for an NPC or <samp>farmer2</samp> for a player). This can be used in event commands like <code>faceDirection [SpouseActor] 1</code>.
|-
  −
| <samp>ScaledMinStackWhenShaving</samp><br /><samp>ScaledMaxStackWhenShaving</samp>
  −
| ''(Optional)'' If set, the min/max stack size when this item is dropped due to the [[Forge#Enchantments|shaving enchantment]], scaled to the tool's power level.
     −
This value is multiplied by the health deducted by the tool hit which triggered the enchantment. For example, an iridium axe which reduced the giant crop's health by 3 points will produce three times this value per hit.
+
(You can also use <samp>spouse</samp> as an actor ID, but that will only work when marrying an NPC.)
 
  −
If both fields are set, the stack size is randomized between them. If only one is set, it's applied as a limit after the generic fields. If neither is set, the generic <samp>MinStack</samp>/<samp>MaxStack</samp> fields are applied as usual without scaling.
   
|}
 
|}
 
|-
 
|-
| <samp>Texture</samp>
+
| <samp>Attendees</samp>
| The asset name for the texture containing the giant crop's sprite.
+
| The other NPCs which should attend the wedding (unless they're the spouse). This consists of a string → model lookup, where the key is the internal NPC name, and the value is a model with these fields:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>TexturePosition</samp>
+
! field
| ''(Optional)'' The top-left pixel position of the sprite within the <samp>Texture</samp>, specified as a model with <samp>X</samp> and <samp>Y</samp> fields. Defaults to (0, 0).
+
! effect
 
|-
 
|-
| <samp>TileSize</samp>
+
| <samp>ID</samp>
| ''(Optional)'' The area in tiles occupied by the giant crop, specified as a model with <samp>X</samp> and <samp>Y</samp> fields. This affects both its sprite size (which should be 16 pixels per tile) and the grid of crops needed for it to grow. Note that giant crops are drawn with an extra tile's height. Defaults to (3, 3).
+
| The internal NPC name.
 
|-
 
|-
| <samp>Health</samp>
+
| <samp>Setup</samp>
| ''(Optional)'' The health points that must be depleted to break the giant crop. The number of points depleted per [[axe]] chop depends on the axe power level. Default 3.
+
| The NPC's tile position and facing direction when they attend. This is equivalent to field index 2 in the [[Modding:Event data#Basic format|event basic data]].
 
|-
 
|-
| <samp>Chance</samp>
+
| <samp>Celebration</samp>
| ''(Optional)'' The percentage chance that a given grid of crops will grow into the giant crop each night, as a value between 0 (never) and 1 (always). Default 0.01 (1%).
+
| ''(Optional)'' The [[Modding:Event data|event script]] to run during the celebration, like <samp>faceDirection Pierre 3 true</samp> which makes Pierre turn to face left. This can contain any number of script commands.
 
  −
Note that the chance is checked for each giant crop that applies. If three giant crops each have a 1% chance of spawning for the same crop, then there's a 3% chance that one of them will spawn.
   
|-
 
|-
 
| <samp>Condition</samp>
 
| <samp>Condition</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this giant crop is available to spawn. Defaults to always true.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the NPC should attend. Defaults to true.
 
|-
 
|-
| <samp>CustomFields</samp>
+
| <samp>IgnoreUnlockConditions</samp>
| The [[#Custom data fields|custom fields]] for this entry.
+
| ''(Optional)'' Whether to add the NPC even if their entry in <samp>Data/Characters</samp> has an <samp>UnlockConditions</samp> field which doesn't match. Default false.
 +
|}
 
|}
 
|}
   −
===Custom movies===
+
===Game state queries===
: ''See also: [[#Custom movie concessions|custom movie concessions]].''
+
{{/doc status|[[Modding:Game state queries]]|done=true}}
 +
 
 +
A ''game state query'' is a new vanilla way to specify conditions for some content like [[#Custom shops|shop data]], inspired by [[Modding:Content Patcher|Content Patcher]]'s conditions.
 +
 
 +
===Gender changes===
 +
{{/doc status|[[Modding:Dialogue]]|done=false}}
   −
You could already [[Modding:Movie theater data#Movie data|add/edit movies]] shown in the [[Movie Theater|movie theater]], but conflicts were likely since the poster & screen sprites for each movie had to be in the vanilla <samp>LooseSprites/Movies</samp> spritesheet.
+
* Added an [[#gender-switch|''inline gender-switch token'']] to change text depending on the player's gender. This reduces duplicate text, works in more places than the <samp>^</samp> dialogue token, works in mail and other places where <samp>^</samp> has a different meaning, and supports non-binary gender.
 +
* For C# mod authors, added a unified <samp>Gender</samp> field for players and NPCs with the possible values <samp>Male</samp>, <samp>Female</samp>, and <samp>Unspecified</samp>. This replaces <samp>Farmer.isMale</samp> and the numeric NPC gender constants. Note that vanilla still only sets players to male or female, though mods can override it.
 +
* Gender-specific clothing variants can now be worn by any gender.
 +
* Removed French-only support for using <samp>^</samp> dialogue token in non-dialogue text. This is superseded by the new inline gender-switch command.
   −
Stardew Valley 1.6 adds a new movie field in <samp>Data/Movies</samp> to fix that:
+
===Item queries===
{| class="wikitable"
+
{{/doc status|[[Modding:Item queries]]|done=true}}
|-
+
 
! field
+
''Item queries'' are a new built-in way to choose one or more items dynamically, instead of specifying a single item ID. These are used in various places like [[#Custom machines|machine data]] and [[#Custom shops|shop data]].
! effect
+
 
|-
+
For example, a shop can sell a random [[House Plant|house plant]] using the <samp>RANDOM_ITEMS</samp> query:
| <samp>Texture</samp>
+
<syntaxhighlight lang="js">
| ''(Optional)'' The asset name for the movie poster and screen images, or omit to use <samp>LooseSprites\Movies</samp>.
+
{
 +
    "ItemId": "RANDOM_ITEMS (F) 1376 1390",
 +
    "MaxItems": 1
 +
}
 +
</syntaxhighlight>
 +
 
 +
===Item spawn fields===
 +
{{/doc status|[[Modding:Item queries#Item spawn fields]]|done=true}}
 +
 
 +
Several data assets (like [[#Custom machines|machines]] and [[#Custom shops|shops]]) let you configure items to create using item queries. For consistency, these all share a set of common fields.
   −
This must be a spritesheet with one 490×128 pixel row per movie. A 13×19 area in the top-left corner of the row should contain the movie poster. With a 16-pixel offset from the left edge, there should be two rows of five 90×61 pixel movie screen images, with a six-pixel gap between each image. (The movie doesn't need to use all of the image slots.)
+
===Color fields===
|}
+
{{/doc status|[[Modding:Common data field types#Color]]|done=true}}
   −
The existing <samp>SpriteIndex</samp> field is now an index within that texture.
+
1.6 adds a standardized color format used in various data fields. This can be a color name, hexadecimal color code, or 8-bit RGB color code.
   −
For example, this content pack adds a new 'Pufferchick II' movie:
+
For example, you can set debris color in [[#Custom wild trees|<samp>Data/WildTrees</samp>]]:
{{#tag:syntaxhighlight|<nowiki>
+
<syntaxhighlight lang="js">
{
+
"DebrisColor": "White"
    "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
+
</syntaxhighlight>
    "Changes": [
  −
        {
  −
            "Action": "EditData",
  −
            "Target": "Data/Movies",
  −
            "Entries": {
  −
                "Example.ModId_PufferchickII": {
  −
                    "Id": "Example.ModId_PufferchickII", // must specify ID again when creating a new entry
     −
                    "Title": "Pufferchick II", // display text should usually use {{i18n}} for translations in actual usage
+
===<samp>modData</samp> field changes===
                    "Description": "A sequel to the breakthrough adventure anime Pufferchick. The world is saved; what happens next?",
+
The <samp>modData</samp> fields are dictionaries of arbitrary string values which are synchronized in multiplayer and persisted in the save file, so mods can store custom data about the instances. The game already has the field for buildings, characters (including NPCs and players), items, locations, and terrain features.
                    "Tags": [ "family", "adventure" ],
     −
                    "Texture": "{{InternalAssetKey: assets/movie.png}}", // an image in your content pack
+
Stardew Valley 1.6...
                    "SheetIndex": 0,
+
* Adds <samp>modData</samp> fields to the <samp>Crop</samp>, <samp>Projectile</samp>, and <samp>Quest</samp> types too.
 +
* Moves <samp>ModDataDictionary</samp> into the <samp>StardewValley.Mods</samp> namespace.
 +
* Fixes <samp>Item.modData</samp> not copied when performing special equipment replacement (e.g. for the [[Pans|copper pan]] work as a hat).
   −
                    "Scenes": [ ... ]
+
===Quantity modifiers===
                }
+
{{/doc status|[[Modding:Common data field types]]|done=false}}
            }
  −
        }
  −
    ]
  −
}</nowiki>|lang=javascript}}
     −
===Custom wedding event===
+
''Quantity modifiers'' apply dynamic changes to a numeric field in a data asset like [[#Custom shops|<samp>Data/Shops</samp>]] or [[#Custom machines|<samp>Data/Machines</samp>]]. For example, you can multiply a shop item's price or increase a machine output's quality. You can specify any number of modifiers for the same field.
The [[Marriage#The Wedding|wedding]] event can now be changed by editing the <samp>Data\Weddings</samp> data asset, which consists of a data model with two relevant fields (listed below).
      +
====Modifier format====
 +
These consist of a list of models with these fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 6,209: Line 6,289:  
! effect
 
! effect
 
|-
 
|-
| <samp>EventScript</samp>
+
| <samp>Id</samp>
| The [[Modding:Event data|event scripts]] which play the wedding. The game will use the script for the spouse NPC/player if it exists, otherwise it'll use the default script.
+
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this modifier within the current list.
 
  −
This consists of a string → string dictionary, where...
  −
* The key is an NPC internal name (like <samp>Abigail</samp>), unique player ID, or <samp>default</samp> for the default script (which handles marrying either an NPC or player);
  −
* The value is a [[Modding:Tokenizable strings|tokenizable strings]] for the event script to play.
  −
 
  −
The event scripts also have access to three extra tokens:
  −
{| class="wikitable"
   
|-
 
|-
! token
+
| <samp>Modification</samp>
! effect
+
| The type of change to apply. The possible values are <samp>Add</samp>, <samp>Subtract</samp>, <samp>Multiply</samp>, <samp>Divide</samp>, and <samp>Set</samp>.
 
|-
 
|-
| <samp>[SetupContextualWeddingAttendees]</samp>
+
| <samp>Amount</samp>
| The concatenated <samp>Setup</samp> values for each of the <samp>Attendees</samp> present in the wedding.
+
| ''(Optional if <samp>RandomAmount</samp> specified)'' The operand applied to the target value (e.g. the multiplier if used with <samp>Multiply</samp>).
 
|-
 
|-
| <samp>[ContextualWeddingCelebrations]</samp>
+
| <samp>RandomAmount</samp>
| The concatenated <samp>Celebration</samp> values for each of the <samp>Attendees</samp> present in the wedding.
+
| ''(Optional)'' A list of possible amounts to randomly choose from. If set, <samp>Amount</samp> is optional and ignored. Each entry in the list has an equal probability of being chosen, and the choice is persisted for the current day. For example:
|-
+
<syntaxhighlight lang="js">
| <samp>[SpouseActor]</samp>
+
"RandomAmount": [ 1, 2, 3.5, 4 ]
| The actor ID for the NPC or other player being married (like <samp>Abigail</samp> for an NPC or <samp>farmer2</samp> for a player). This can be used in event commands like <code>faceDirection [SpouseActor] 1</code>.
+
</syntaxhighlight>
 
  −
(You can also use <samp>spouse</samp> as an actor ID, but that will only work when marrying an NPC.)
  −
|}
  −
|-
  −
| <samp>Attendees</samp>
  −
| The other NPCs which should attend the wedding (unless they're the spouse). This consists of a string → model lookup, where the key is the internal NPC name, and the value is a model with these fields:
  −
{| class="wikitable"
  −
|-
  −
! field
  −
! effect
  −
|-
  −
| <samp>ID</samp>
  −
| The internal NPC name.
  −
|-
  −
| <samp>Setup</samp>
  −
| The NPC's tile position and facing direction when they attend. This is equivalent to field index 2 in the [[Modding:Event data#Basic format|event basic data]].
  −
|-
  −
| <samp>Celebration</samp>
  −
| ''(Optional)'' The [[Modding:Event data|event script]] to run during the celebration, like <samp>faceDirection Pierre 3 true</samp> which makes Pierre turn to face left. This can contain any number of script commands.
   
|-
 
|-
 
| <samp>Condition</samp>
 
| <samp>Condition</samp>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the NPC should attend. Defaults to true.
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this change should be applied. Defaults to always true.
|-
  −
| <samp>IgnoreUnlockConditions</samp>
  −
| ''(Optional)'' Whether to add the NPC even if their entry in <samp>Data/Characters</samp> has an <samp>UnlockConditions</samp> field which doesn't match. Default false.
  −
|}
   
|}
 
|}
   −
===Game state queries===
+
====Modifier mode====
A ''game state query'' is a new vanilla way to specify conditions for some content like [[#Custom shops|shop data]], inspired by [[Modding:Content Patcher|Content Patcher]]'s conditions.
+
Quality modifier fields are often accompanied by a ''mode'' field (like <samp>PriceModifiers</samp> and <samp>PriceModifierMode</samp>), which indicate what to do when multiple modifiers apply to the same value. Available modes:
   −
See [[Modding:Game state queries]] for more information.
  −
  −
===Item queries===
  −
''Item queries'' choose one or more items dynamically, instead of specifying a single item ID. These are used in various places like [[#Custom machines|machine data]] and [[#Custom shops|shop data]].
  −
  −
====Available queries====
  −
The supported item queries are:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! query
+
! value
 
! effect
 
! effect
 
|-
 
|-
| <samp>ALL_ITEMS {{o|type ID}}</samp>
+
| <samp>Stack</samp>
| Every item provided by the [[#Custom items|item data definitions]]. If {{o|type ID}} is set to an item type identifier (like <samp>(O)</samp> for object), only returns items from the matching item data definition.
+
| Apply each modifier to the result of the previous one. For example, two modifiers which double a value will quadruple it.
 
|-
 
|-
| <samp>DISH_OF_THE_DAY</samp>
+
| <samp>Minimum</samp>
| The [[The Stardrop Saloon#Rotating Stock|Saloon's dish of the day]].
+
| Apply the modifier which results in the lowest value.
 
|-
 
|-
| <samp>FLAVORED_ITEM {{t|type}} {{t|ingredient ID}} {{o|ingredient flavor ID}}</samp>
+
| <samp>Maximum</samp>
| A flavored item like Apple Wine. The {{t|type}} can be one of [[Aged Roe|<samp>AgedRoe</samp>]], [[Honey|<samp>Honey</samp>]], [[Jellies and Pickles|<samp>Jelly</samp>]], [[Juice|<samp>Juice</samp>]], [[Jellies and Pickles|<samp>Pickle</samp>]], [[Roe|<samp>Roe</samp>]], or [[Wine|<samp>Wine</samp>]]. The {{t|ingredient ID}} is the qualified or unqualified item ID which provides the flavor (like Apple in Apple Wine). For <samp>Honey</samp>, you can set the {{t|flavor ID}} to <samp>-1</samp> for Wild Honey.
+
| Apply the modifier which results in the highest value.
 +
|}
   −
For aged roe only, the {{o|ingredient flavor ID}} is the flavor of the {{t|ingredient ID}}. For example, <samp>FLAVORED_ITEM AgedRoe (O)812 128</samp> creates Aged Pufferfish Roe (812 is [[roe]] and 128 is [[pufferfish]]).
+
====Examples====
|-
+
For example, this will double the price of a shop item in <samp>Data/Shops</samp>:
| <samp>ITEMS_SOLD_BY_PLAYER {{t|shop location}}</samp>
  −
| Random items the player has recently sold to the {{t|shop location}}, which can be one of <samp>SeedShop</samp> (Pierre's store) or <samp>FishShop</samp> (Willy's fish shop).
  −
|-
  −
| <samp>LOCATION_FISH {{t|location}} {{t|bobber tile}} {{t|depth}}</samp>
  −
| A random item that can be found by fishing in the given location. The {{t|location}} should be the internal name of the location, {{t|bobber tile}} is the position of the fishing rod's bobber in the water (in the form <samp>{{t|x}} {{t|y}}</samp>), and {{t|depth}} is the bobber's distance from the nearest shore measured in tiles (where 0 is directly adjacent to the shore).
  −
 
  −
'''Careful:''' since the target location might use <samp>LOCATION_FISH</samp> queries in its list, it's easy to cause a circular reference by mistake (e.g. location A gets fish from B, which gets fish from A). If this happens, the game will log an error and return no item.
  −
|-
  −
| <samp>LOST_BOOK_OR_ITEM {{o|alternate query}}</samp>
  −
| Returns a [[Lost Books|lost book]] if the player hasn't found them all yet, else the result of the {{o|alternate query}} if specified, else nothing.
  −
 
  −
For example, <code>LOST_BOOK_OR_ITEM (O)770</code> returns [[Mixed Seeds|mixed seeds]] if the player found every book already.
  −
|-
  −
| <samp>RANDOM_ARTIFACT_FOR_DIG_SPOT</samp>
  −
| A random item which is defined in <samp>Data/Objects</samp> with the <samp>Arch</samp> (artifact) type, and whose spawn rules in the <samp>Miscellaneous</samp> field match the current location and whose random probability passes. This is mainly used by [[Artifact Spot|artifact spots]].
  −
|-
  −
| <samp>RANDOM_BASE_SEASON_ITEM</samp>
  −
| A random seasonal vanilla item which can be found by searching garbage cans, breaking containers in the mines, etc.
  −
|-
  −
| <samp>RANDOM_ITEMS {{t|type definition ID}} {{o|min ID}} {{o|max ID}} {{o|require price}}</samp>
  −
| All items from the given [[#Item types|type definition ID]] in randomized order, optionally filtered to those with a numeric ID in the given {{o|min ID}} and {{o|max ID}} range (inclusive). If {{o|require price}} is <samp>true</samp>, items with a sell-to-shop price below {{price|1}} won't be returned.
  −
 
  −
For example, you can sell a random [[wallpaper]] for {{price|200}} in <samp>Data/Shops</samp>:
   
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
{
+
"PriceModifiers": [
    "ItemId": "RANDOM_ITEMS (WP)",
+
    {
    "MaxItems": 1,
+
        "Modification": "Multiply",
     "Price": 200
+
        "Amount": 2.0
}
+
     }
 +
]
 
</syntaxhighlight>
 
</syntaxhighlight>
   −
Or a random [[House Plant|house plant]]:
+
This will set the price to a random value between 100–1000, ''or'' 3–5 times the item's normal sell price, whichever is higher (like the [[Traveling Cart]]):
 
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
{
+
"PriceModifierMode": "Maximum",
     "ItemId": "RANDOM_ITEMS (F) 1376 1390",
+
"PriceModifiers": [
    "MaxItems": 1
+
    {
}
+
        "Modification": "Set",
 +
        "RandomAmount": [ 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ]
 +
     },
 +
    {
 +
        "Modification": "Multiply",
 +
        "RandomAmount": [ 3, 4, 5 ]
 +
    }
 +
]
 
</syntaxhighlight>
 
</syntaxhighlight>
   −
Or a random [[#Custom items|custom item]] added by a mod by its item ID prefix:
+
===Tokenizable string format===
 +
{{/doc status|[[Modding:Tokenizable strings]]|done=true}}
 +
 
 +
Stardew Valley 1.6 adds ''tokenizable strings'', which support any combination of literal text and token values. That includes a set of built-in tokens like <samp>FarmName</samp>, <samp>LocalizedText</samp>, etc.
 +
 
 +
For example, previously you often needed to load text from a [[Modding:Common data field types#Translation key|translation key]]. With this new format, you can use the literal text directly in the asset instead (including [[Modding:Content Patcher|Content Patcher]] tokens):
 +
 
 
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
{
+
// before
    "ItemId": "RANDOM_ITEMS (O)",
+
"Dialogue": "Strings\\StringsFromCSFiles:ShopMenu.cs.11488",
    "MaxItems": 1,
  −
    "PerItemCondition": "ITEM_ID_PREFIX Target AuthorName_ModName_"
  −
}
  −
</syntaxhighlight>
     −
Or 10 random objects with any category except <samp>-13</samp> or <samp>-14</samp>:
+
// after: any combination of literal text and tokens
<syntaxhighlight lang="js">
+
"Dialogue": "Welcome to Pierre's, {{PlayerName}}! How is [FarmName] doing?",
{
  −
    "ItemId": "RANDOM_ITEMS (O)",
  −
    "MaxItems": 10,
  −
    "PerItemCondition": "ITEM_CATEGORY, !ITEM_CATEGORY Target -13 -14"
  −
}
   
</syntaxhighlight>
 
</syntaxhighlight>
|-
  −
| <samp>SECRET_NOTE_OR_ITEM {{o|alternate query}}</samp>
  −
| Returns a [[Secret Notes|secret note]] (or [[Journal Scraps|journal scrap]] on the island) if the player hasn't found them all yet, else the result of the {{o|alternate query}} if specified, else nothing.
     −
For example, <code>SECRET_NOTE_OR_ITEM (O)390</code> returns [[clay]] if the player found every secret note already.
+
Tokenizable strings are only usable in specific fields (as indicated in their wiki or code docs).
|-
  −
| <samp>SHOP_TOWN_KEY</samp>
  −
| The special [[Key To The Town|town key]] item. This is only valid in shops.
  −
|-
  −
| <samp>TOOL_UPGRADES {{o|tool ID}}</samp>
  −
| The tool upgrades listed in <samp>Data/Shops</samp> whose conditions match the player's inventory (i.e. the same rules as [[Blacksmith|Clint's tool upgrade shop]]). If {{o|tool ID}} is specified, only upgrades which consume that tool ID are shown.
  −
|}
     −
====Item spawn fields====
+
See [[Modding:Tokenizable strings]] for usage.
Several data assets (like [[#Custom machines|machines]] and [[#Custom shops|shops]]) let you configure items to create. For consistency, these all share a set of common fields (internally represented by <samp>ISpawnItemData</samp>, and <samp>GenericSpawnItemData</samp> or <samp>GenericSpawnItemDataWithCondition</samp>):
     −
{| class="wikitable"
+
===[[Modding:Event data|Event]] changes===
|-
+
{{/doc status|[[Modding:Event data]]|done=false}}
! field
  −
! effect
  −
|-
  −
| <samp>ID</samp>
  −
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this entry (not the item itself) within the current list.
     −
This is semi-optional — if omitted, it'll be auto-generated from the <samp>ItemId</samp>, <samp>RandomItemId</samp>, and <samp>IsRecipe</samp> fields. However multiple entries with the same ID may cause unintended behavior (e.g. shop items reducing each others' stock limits), so it's often a good idea to set a globally unique ID instead.
+
====High-level changes====
|-
+
* Event IDs are now [[Modding:Common data field types#Unique string ID|unique string IDs]], so mods can use a unique key instead of hoping no other mod uses the same number. Unconditional events must have an empty precondition in their key (like <samp>"Example.ModId_EventName/"</samp>) to distinguish them from forks.
| <samp>ItemId</samp>
+
* Event/festival commands with a direction argument now allow both case-insensitive names (like <samp>up</samp>) and numeric values.
| One of:
+
* Event script errors are now logged (in addition to being shown in the chatbox like before).
* the [[#Custom items|qualified or unqualified item ID]] (like <samp>(O)128</samp> for a [[pufferfish]]);
+
* For C# mods:
* or an [[#Item queries|item query]] to dynamically choose one or more items.
+
** You can now add custom event preconditions & commands using new <samp>Event</samp> methods (<samp>RegisterPrecondition</samp>, <samp>RegisterPreconditionAlias</samp>, <samp>RegisterCommand</samp>, and <samp>RegisterCommandAlias</samp>).
|-
+
** Added <samp>Event.fromAssetName</samp>, which indicates which data asset (if any) the event was loaded from.
| <samp>RandomItemId</samp>
+
** Added <samp>Game1.eventsSeenSinceLastLocationChange</samp> to track the events that played since the player arrived in their current location.
| ''(Optional)'' A list of item IDs to randomly choose from, using the same format as <samp>ItemId</samp> (including item queries). If set, <samp>ItemId</samp> is optional and ignored. Each entry in the list has an equal probability of being chosen. For example:
  −
<syntaxhighlight lang="js">
  −
// wood, stone, or pizza
  −
"RandomItemId": [ "(O)388", "(O)390", "(O)206" ]
  −
</syntaxhighlight>
  −
|-
  −
| <samp>Condition</samp>
  −
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry should be applied. Defaults to always true.
     −
'''Note:''' not supported for weapon projectiles.
+
====Precondition changes====
|-
+
<ul>
| <samp>PerItemCondition</samp>
+
<li>Added validation for preconditions. If a format or assumption is invalid, the game now logs a detailed error.</li>
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether an item produced from the other fields should be returned. Defaults to always true.
+
<li>Added case-insensitive readable names for all preconditions. For example, <code>j 4/t 800 1300/a 0 54/H</code> can now optionally be written <code>daysPlayed 4/time 800 1300/tile 0 54/isHost</code>.
 
+
{{collapse|list of new names|content=
For example, this can be used to filter queries like <samp>RANDOM_ITEMS</samp>:
+
List of new event precondition names:
<syntaxhighlight lang="js">
+
<pre>
// random mineral
+
alias | readable name
"ItemId": "RANDOM_ITEMS (O)",
+
----- | ------------------------------
"PerItemCondition": "ITEM_CATEGORY Target -12"
+
*    | WorldState
</syntaxhighlight>
+
*n    | HostOrLocalMail
|-
+
a    | Tile
| <samp>MaxItems</samp>
+
b    | ReachedMineBottom
| ''(Optional)'' If this entry produces multiple separate item stacks, the maximum number to return. (This does ''not'' affect the size of each stack; see <samp>MinStack</samp> and <samp>MaxStack</samp> for that.) Default unlimited.
+
B    | SpouseBed
|-
+
C    | CommunityCenterOrWarehouseDone
| <samp>IsRecipe</samp>
+
c    | FreeInventorySlots
| ''(Optional)'' Whether to get the crafting/cooking recipe for the item, instead of the item itself. Default false.
+
D    | Dating
|-
+
e     | SawEvent
| <samp>Quality</samp>
+
f    | Friendship
| ''(Optional)'' The quality of the item to find. One of <samp>0</samp> (normal), <samp>1</samp> (silver), <samp>2</samp> (gold), or <samp>4</samp> (iridium). Invalid values will snap to the closest valid one (e.g. <samp>7</samp> will become iridium). Default -1, which keeps the value set by the item query (usually 0).
+
g     | Gender
|-
+
H    | IsHost
| <samp>MinStack</samp>
+
h    | MissingPet
| ''(Optional)'' The item's minimum and default stack size. Default -1, which keeps the value set by the item query (usually 1).
+
Hn    | HostMail
|-
+
i    | HasItem
| <samp>MaxStack</samp>
+
j    | DaysPlayed
| ''(Optional)'' If set to a value higher than <samp>MinStack</samp>, the stack is set to a random value between them (inclusively). Default -1.
+
J    | JojaBundlesDone
|-
+
L    | InUpgradedHouse
| <samp>ObjectDisplayName</samp>
+
m    | EarnedMoney
| ''(Optional)'' For objects only, a [[Modding:Tokenizable strings|tokenizable string]] for the item's display name. Defaults to the item's display name in <samp>Data/Objects</samp>. This can optionally contain <code>%DISPLAY_NAME</code> (the item's default display name) and <code>%PRESERVED_DISPLAY_NAME</code> (the preserved item's display name if applicable, ''e.g.'' if set via <samp>PreserveId</samp> in [[#Custom machines|machine data]]).
+
M    | HasMoney
 
+
N    | GoldenWalnuts
'''Careful:''' text in this field will be saved permanently in the object's info and won't be updated when the player changes language or the content pack changes. That includes Content Patcher translations (like <code><nowiki>%DISPLAY_NAME {{i18n: wine}}</nowiki></code>), which will save the translated text for the current language. Instead, add the text to a strings asset like <samp>Strings/Objects</samp> and then use the [[Modding:Tokenizable strings|<samp>[LocalizedText]</samp> token]].
+
n    | LocalMail
{{collapse|For example, here's how you'd create flavored oils with Content Patcher:|content=
+
O    | Spouse
<ol>
+
p    | NpcVisibleHere
<li>Add the display name to [[Modding:Translations|your <samp>i18n/default.json</samp> file]] (with <samp>{0}</samp> where you want the flavor name):
+
q    | ChoseDialogueAnswers
<syntaxhighlight lang="json">
+
r    | Random
{
+
R    | Roommate
     "flavored-oil": "{0} Oil"
+
S    | SawSecretNote
}
+
s     | Shipped
</syntaxhighlight></li>
+
t    | Time
<li>Add the text to a strings asset visible to the game:
+
u    | DayOfMonth
{{#tag:syntaxhighlight|<nowiki>
+
v    | NpcVisible
{
+
w    | Weather
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
+
x    | SendMail
     "Changes": [
+
y    | Year
        {
+
</pre>
            "Action": "EditData",
+
And for deprecated preconditions (e.g. <code>NotSeason</code> is superseded by <code>!Season</code>):
            "Target": "Strings/Objects",
+
<pre>
            "Entries": {
+
alias | readable name
                "Example.ModId_Oil": "{{i18n: flavored-oil}}"
+
----- | ---------------------------------
            }
+
*l    | NotHostOrLocalMail
        }
+
A     | NotActiveDialogueEvent
}</nowiki>|lang=javascript}}</li>
+
d    | NotDayOfWeek
<li>Use the [[Modding:Tokenizable strings|<samp>[LocalizedText]</samp> token]] to get your translation, and pass in the flavor as an argument:
+
F    | NotFestivalDay
<syntaxhighlight lang="json">
+
Hl    | NotHostMail
"ObjectDisplayName": "[LocalizedText Strings/Objects:Example.ModId_Oil %PRESERVED_DISPLAY_NAME]",
+
k    | NotSawEvent
</syntaxhighlight>
+
l     | NotLocalMail
</ol>
+
o     | NotSpouse
 
+
Rf    | NotRoommate
Now when the player changes language, the object will automatically get the new translation from <samp>Strings/Object</samp>.
+
U    | NotUpcomingFestival
 +
X    | NotCommunityCenterOrWarehouseDone
 +
z    | NotSeason
 +
</pre>
 
}}
 
}}
 +
</li>
 +
<li>Event & preconditions are now quote-aware, so you can escape spaces and slashes in arguments like <code>/G "SEASON Spring"/</code>.</li>
 +
<li>Added new preconditions:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>ToolUpgradeLevel</samp>
+
! precondition
| ''(Optional)'' For tools only, the initial upgrade level for the tool when created (like [[Axes|Copper vs Gold Axe]], or [[Training Rod]] vs [[Iridium Rod]]). Default -1, which keeps the value set by the item query (usually 0).
+
! description
 
|-
 
|-
| <samp>QualityModifiers</samp><br /><samp>StackModifiers</samp>
+
| <samp>!</samp>
| ''(Optional)'' [[#Quantity modifiers|Quantity modifiers]] applied to the <samp>Quality</samp> or <samp>Stack</samp> value. Default none.
+
| Prefixing <samp>!</samp> to any other precondition will now invert it. For example, <code>!spouse Abigail</code> will match if the player is ''not'' married to Abigail.
 
  −
The quality modifiers operate on the numeric quality values (''i.e.'' <samp>0</samp> = normal, <samp>1</samp> = silver, <samp>2</samp> = gold, and <samp>4</samp> = iridium). For example, silver × 2 is gold.
   
|-
 
|-
| <samp>QualityModifierMode</samp><br /><samp>StackModifierMode</samp>
+
| <samp>ActiveDialogueEvent {{t|id}}</samp>
| ''(Optional)'' [[#Quantity modifiers|quantity modifier modes]] which indicate what to do if multiple modifiers in the <samp>QualityModifiers</samp> or <samp>StackModifiers</samp> field apply at the same time. Default <samp>Stack</samp>.
+
| The special dialogue event with the given ID (including [[Modding:Dialogue#Conversation_topics|Conversation Topics]]) is in progress.
|}
+
|-
 
+
| <samp>DayOfWeek {{t|day}}+</samp>
===Color fields===
+
| Today is one of the specified days (may specify multiple days). This can be a case-insensitive three-letter abbreviation (like <samp>Mon</samp>) or full name (like <samp>Monday</samp>).
1.6 adds a standardized color format for data fields in assets like [[#Custom wild trees|<samp>Data/WildTrees</samp>]]:
+
|-
<syntaxhighlight lang="js">
+
| <samp>FestivalDay</samp>
"DebrisColor": "White"
+
| Today is a [[Festivals|festival]] day.
</syntaxhighlight>
  −
 
  −
This supports colors in any of these formats:
  −
{| class="wikitable"
   
|-
 
|-
! format
+
| <samp>GameStateQuery {{t|query}}</samp>
! example
+
| A [[Modding:Game state queries|game state query]] matches, like <code>G !WEATHER Here Sun</code> for 'not sunny in this location'.
 
|-
 
|-
| A [https://docs.monogame.net/api/Microsoft.Xna.Framework.Color.html#properties <samp>Color</samp> property name].
+
| <samp>Season {{t|season}}+</samp>
| <samp>ForestGreen</samp>
+
| The current season is one of the given values (may specify multiple seasons).
 
|-
 
|-
| A [https://en.wikipedia.org/wiki/Web_colors#Hex_triplet hexadecimal color code]. The optional alpha is a value between <samp>00</samp> (transparent) and <samp>FF</samp> (opaque).
+
| <samp>Skill {{t|skill name}} {{t|min level}}</samp>
| <samp>#228B22</samp><br /><samp>#228B22FF</samp>
+
| The current farmer has reached at least {{t|min level}} for the given {{t|skill name}} (one of <samp>Combat</samp>, <samp>Farming</samp>, <samp>Fishing</samp>, <samp>Foraging</samp>, <samp>Luck</samp>, or <samp>Mining</samp>).
 
|-
 
|-
| An [https://en.wikipedia.org/wiki/RGB_color_model#Numeric_representations 8-bit RGB color code]. The optional alpha is a value between <samp>0</samp> (transparent) and <samp>255</samp> (opaque).
+
| <samp>UpcomingFestival {{t|day offset}}</samp>
| <samp>34 139 34</samp><br /><samp>34 139 34 255</samp>
+
| A [[Festivals|festival]] day will occur within the given number of days.
|}
+
|}</li>
 
+
<li>Changed specific preconditions:
C# mods can parse a color like <code>Utility.StringToColor("White")</code>.
  −
 
  −
===More <samp>modData</samp> fields===
  −
The <samp>modData</samp> fields are dictionaries of arbitrary string values which are synchronized in multiplayer and persisted in the save file, so mods can store custom data about the instances. The game already has the field for buildings, characters (including NPCs and players), items, locations, and terrain features.
  −
 
  −
Stardew Valley 1.6 adds <samp>modData</samp> fields to the <samp>Projectile</samp> and <samp>Quest</samp> types too, to support custom projectile/quest mods.
  −
 
  −
===Quantity modifiers===
  −
''Quantity modifiers'' apply dynamic changes to a numeric field in a data asset like [[#Custom shops|<samp>Data/Shops</samp>]] or [[#Custom machines|<samp>Data/Machines</samp>]]. For example, you can multiply a shop item's price or increase a machine output's quality. You can specify any number of modifiers for the same field.
  −
 
  −
====Modifier format====
  −
These consist of a list of models with these fields:
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! field
+
! name
! effect
+
! changes
 
|-
 
|-
| <samp>Id</samp>
+
| <samp>ChoseDialogueAnswers</samp> (<samp>q</samp>)
| The [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]] for this modifier within the current list.
+
| &#32;
 +
* Fixed precondition ignoring every second answer ID.
 
|-
 
|-
| <samp>Modification</samp>
+
| <samp>InUpgradedHouse</samp> (<samp>L</samp>)
| The type of change to apply. The possible values are <samp>Add</samp>, <samp>Subtract</samp>, <samp>Multiply</samp>, <samp>Divide</samp>, and <samp>Set</samp>.
+
| &#32;
 +
* Added optional argument for the min upgrade level.
 
|-
 
|-
| <samp>Amount</samp>
+
| <samp>MissingPet</samp> (<samp>h</samp>)
| ''(Optional if <samp>RandomAmount</samp> specified)'' The operand applied to the target value (e.g. the multiplier if used with <samp>Multiply</samp>).
+
| &#32;
 +
* You can now specify any pet type ID.
 +
* You can now omit the argument to check for a pet of any type.
 
|-
 
|-
| <samp>RandomAmount</samp>
+
| <samp>NotDayOfWeek</samp> (<samp>d</samp>)
| ''(Optional)'' A list of possible amounts to randomly choose from. If set, <samp>Amount</samp> is optional and ignored. Each entry in the list has an equal probability of being chosen, and the choice is persisted for the current day. For example:
+
| &#32;
<syntaxhighlight lang="js">
+
* You can now specify a full name like <samp>Monday</samp>.
"RandomAmount": [ 1, 2, 3.5, 4 ]
+
* The day of week is now case-insensitive.
</syntaxhighlight>
   
|-
 
|-
| <samp>Condition</samp>
+
| <samp>NotSeason</samp> (<samp>z</samp>)
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this change should be applied. Defaults to always true.
+
| &#32;
|}
+
* You can now list values (like <code>notSeason spring summer fall</code> instead of <code>notSeason fall/notSeason winter/notSeason fall</code>).
 
  −
====Modifier mode====
  −
Quality modifier fields are often accompanied by a ''mode'' field (like <samp>PriceModifiers</samp> and <samp>PriceModifierMode</samp>), which indicate what to do when multiple modifiers apply to the same value. Available modes:
  −
 
  −
{| class="wikitable"
   
|-
 
|-
! value
+
| <samp>ReachedMineBottom</samp> (<samp>b</samp>)
! effect
+
| &#32;
 +
* Argument is now optional (default 1).
 
|-
 
|-
| <samp>Stack</samp>
+
| <samp>SendMail</samp> (<samp>x</samp>)
| Apply each modifier to the result of the previous one. For example, two modifiers which double a value will quadruple it.
+
| &#32;
 +
* Deprecated; see [[#Send-mail (x) precondition deprecated|''Send-mail (x) precondition deprecated'']] for more info.
 
|-
 
|-
| <samp>Minimum</samp>
+
| <samp>Tile</samp> (<samp>a</samp>)
| Apply the modifier which results in the lowest value.
+
| &#32;
|-
+
* Now also works when the player isn't currently warping, in which case it checks their current tile instead of their warp arrival tile.
| <samp>Maximum</samp>
+
|}</li>
| Apply the modifier which results in the highest value.
+
</ul>
|}
     −
====Examples====
+
====Command changes====
For example, this will double the price of a shop item in <samp>Data/Shops</samp>:
+
<ul>
 +
<li>Added validation for event commands. If a format or assumption is invalid, the game now logs a detailed error and (if applicable) skips the command, instead of crashing or silently ignoring it. This also means event arguments are stricter (e.g. you can no longer set a true/false field to an invalid value, inner quotes in quoted arguments now need to be escaped, etc).</li>
 +
<li>Event commands are now quote-aware, so you can escape spaces and slashes in arguments like <code>/speak "I'm running A/B tests"/</code>.</li>
 +
<li>Event commands now trim surrounding whitespace, so they can be multilined for readability. Line breaks must be before or after the <samp>/</samp> delimiter. For example:
 
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
"PriceModifiers": [
+
"SomeEventId/": "
     {
+
     none/
        "Modification": "Multiply",
+
    -1000 -1000/
        "Amount": 2.0
+
    farmer 5 7 0/
     }
+
     ...
]
+
"
</syntaxhighlight>
+
</syntaxHighlight>
 
+
This can be also combined with the [[Modding:Event data#Comments|comment syntax]] to add notes. For example:
This will set the price to a random value between 100–1000, ''or'' 3–5 times the item's normal sell price, whichever is higher (like the [[Traveling Cart]]):
   
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
"PriceModifierMode": "Maximum",
+
"SomeEventId/": "
"PriceModifiers": [
+
    none/            -- music/
    {
+
    -1000 -1000/    -- initial viewport position/
        "Modification": "Set",
+
    farmer 5 7 0/    -- actor positions/
        "RandomAmount": [ 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 ]
+
    ...
    },
+
"
    {
+
</syntaxHighlight>
        "Modification": "Multiply",
+
</li>
        "RandomAmount": [ 3, 4, 5 ]
+
<li>You can now mark NPCs optional in event commands by suffixing their name with <code>?</code>. For example, <code>jump Kent?</code> won't log an error if Kent is missing. When used in the initial event positions, the NPC is only added in they exist in <samp>Data/Characters</samp> and their <samp>UnlockConditions</samp> match.</li>
    }
+
<li>Added new event commands:
]
+
{| class="wikitable"
</syntaxhighlight>
+
|-
 +
! command
 +
! description
 +
|-
 +
| <samp>action {{t|action}}</samp>
 +
| Run a [[Modding:Trigger actions|trigger action string]], like <samp>action AddMoney 500</samp> to add {{price|500}} to the current player.
 +
|-
 +
| <samp>addItem {{t|item ID}} {{o|count}} {{o|quality}}</samp>
 +
| Add an item to the player inventory (or open a grab menu if their inventory is full). The {{t|item ID}} is the [[#Custom items|qualified or unqualified item ID]], and {{o|quality}} is a [[Modding:Items#Quality|numeric quality value]].
 +
|-
 +
| <samp>addSpecialOrder {{t|order ID}}</samp><br /><samp>removeSpecialOrder {{t|order ID}}</samp>
 +
| Add or remove a special order to the player team. This affects all players, since special orders are shared.
 +
|-
 +
| <samp>eventSeen {{t|event ID}} {{o|seen}}</samp>
 +
| Add or remove an event ID from the player's list of seen events, based on {{o|seen}} (default <samp>true</samp> to add).
   −
===Tokenizable string format===
+
An event can mark ''itself'' unseen using <samp>eventSeen {{t|event ID}} false</samp>. This takes effect immediately (i.e. the event won't be added to the list when it completes), but the game will prevent the event from playing again until the player changes location to avoid event loops. The event will still replay when re-entering the location.
Stardew Valley 1.6 adds ''tokenizable strings'', which support any combination of literal text and token values. That includes a set of built-in tokens like <samp>FarmName</samp>, <samp>LocalizedText</samp>, etc.
+
|-
 
+
| <samp>mailToday {{t|mail key}}</samp>
For example, previously you often needed to load text from a [[Modding:Modder Guide/Game Fundamentals#String keys|translation string key]]. With this new format, you can use the literal text directly in the asset instead (including [[Modding:Content Patcher|Content Patcher]] tokens):
+
| Adds a letter to the mailbox immediately, given the {{t|mail key}} in <samp>Data/Mail</samp>.
 +
|-
 +
| <samp>questionAnswered {{t|answer ID}} {{o|answered}}</samp>
 +
| Add or remove an answer ID from the player's list of chosen dialogue answers, based on {{o|answered}} (default <samp>true</samp> to add).
 +
|-
 +
| <samp>replaceWithClone {{t|NPC name}}</samp>
 +
| Replace an NPC already in the event with a temporary copy. This allows changing the NPC for the event without affecting the real NPC.
    +
For example, this event changes Marnie's name/portrait only within the event:
 
<syntaxhighlight lang="js">
 
<syntaxhighlight lang="js">
// before
+
"Some.ModId_ExampleEvent/": "continue/64 15/farmer 64 15 2 Marnie 64 17 0/replaceWithClone Marnie/changeName Marnie Pufferchick/changePortrait Marnie Pufferchick/[...]/end"
"Dialogue": "Strings\\StringsFromCSFiles:ShopMenu.cs.11488",
  −
 
  −
// after: any combination of literal text and tokens
  −
"Dialogue": "Welcome to Pierre's, {{PlayerName}}! How is [FarmName] doing?",
   
</syntaxhighlight>
 
</syntaxhighlight>
 +
|-
 +
| <samp>setSkipActions {{o|actions}}</samp>
 +
| Set [[Modding:Trigger actions|trigger actions]] that should run if the player skips the event. You can list multiple actions delimited with <samp>#</samp>, or omit {{o|actions}} so no actions are run. When the player skips, the last <samp>setSkipActions</samp> before that point is applied.
   −
Tokenizable strings are only usable in specific fields (as indicated in their wiki or code docs).
+
For example, this adds the [[Garden Pot|garden pot]] recipe and item to the player if the event is skipped, but avoids adding the item if the event already did it:
 +
<pre>
 +
/setSkipActions AddCraftingRecipe Current "Garden Pot"#AddItem (BC)62
 +
/skippable
 +
/...
 +
/addItem (BC)62
 +
/setSkipActions AddCraftingRecipe Current "Garden Pot"
 +
</pre>
   −
See [[Modding:Tokenizable strings]] for usage.
+
Skip actions aren't applied if the event completes normally without being skipped.
 +
|-
 +
| <samp>stopSound {{t|sound ID}} {{o|immediate}}</samp>
 +
| Stop a sound started with the <samp>startSound</samp> command. This has no effect if the sound has already stopped playing on its own (or hasn't been started). If you started multiple sounds with the same ID, this will stop all of them (e.g. <code>startSound fuse/startSound fuse/stopSound fuse</code>).
   −
===[[Modding:Event data|Event]] changes===
+
By default the sound will stop immediately. For looping sounds, you can pass <samp>false</samp> to the {{o|immediate}} argument to stop the sound when it finishes playing the current iteration instead (e.g. <code>stopSound fuse false</code>).
====High-level changes====
+
|-
* Event IDs are now [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string IDs]], so mods can use a unique key instead of hoping no other mod uses the same number. Unconditional events must have an empty precondition in their key (like <samp>"Example.ModId_EventName/"</samp>) to distinguish them from forks.
+
| <samp>temporaryAnimatedSprite ...</samp>
* Event/festival commands with a direction argument now allow both case-insensitive names (like <samp>up</samp>) and numeric values.
+
| Add a temporary animated sprite to the event, using these space-delimited fields:
* C# mods can now add custom event preconditions & commands using <samp>Event.RegisterCustomPrecondition</samp> and <samp>Event.RegisterCustomCommand</samp> respectively.
+
{| class="wikitable"
* For C# mods, the new <samp>Event.fromAssetName</samp> field indicates which data asset (if any) the event was loaded from.
+
|-
* Event script errors are now logged (in addition to being shown in the chatbox like before).
+
! index
 
+
! field
====Precondition changes====
+
! effect
<ul>
+
|-
<li>Added validation for preconditions. If a format or assumption is invalid, the game now logs a detailed error.</li>
+
| 0
<li>Added case-insensitive readable names for all preconditions. For example, <code>j 4/t 800 1300/a 0 54/H</code> can now optionally be written <code>daysPlayed 4/time 800 1300/tile 0 54/isHost</code>.
+
| <samp>texture</samp>
{{collapse|list of new names|content=
+
| The asset name for texture to draw.
List of new event precondition names:
+
|-
<pre>
+
| 1&ndash;4
alias | readable name
+
| <samp>rectangle</samp>
----- | ------------------------------
+
| The pixel area within the <samp>texture</samp> to draw, in the form <samp>{{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp>.
*    | WorldState
+
|-
*n    | HostOrLocalMail
+
| 5
a    | Tile
+
| <samp>interval</samp>
b    | ReachedMineBottom
+
| The millisecond duration for each frame in the animation.
B    | SpouseBed
+
|-
C    | CommunityCenterOrWarehouseDone
+
| 6
c    | FreeInventorySlots
+
| <samp>frames</samp>
D    | Dating
+
| The number of frames in the animation.
e    | SawEvent
+
|-
f    | Friendship
+
| 7
g    | Gender
+
| <samp>loops</samp>
H    | IsHost
+
| The number of times to repeat the animation.
h    | MissingPet
  −
Hn    | HostMail
  −
i    | HasItem
  −
j    | DaysPlayed
  −
J    | JojaBundlesDone
  −
L    | InUpgradedHouse
  −
m    | EarnedMoney
  −
M    | HasMoney
  −
N    | GoldenWalnuts
  −
n    | LocalMail
  −
O    | Spouse
  −
p    | NpcVisibleHere
  −
q    | ChoseDialogueAnswers
  −
r    | Random
  −
R    | Roommate
  −
S    | SawSecretNote
  −
s    | Shipped
  −
t    | Time
  −
u    | DayOfMonth
  −
v    | NpcVisible
  −
w    | Weather
  −
x    | SendMail
  −
y    | Year
  −
</pre>
  −
And for deprecated preconditions (e.g. <code>NotSeason</code> is superseded by <code>!Season</code>):
  −
<pre>
  −
alias | readable name
  −
----- | ---------------------------------
  −
*l    | NotHostOrLocalMail
  −
A    | NotActiveDialogueEvent
  −
d    | NotDayOfWeek
  −
F    | NotFestivalDay
  −
Hl    | NotHostMail
  −
k    | NotSawEvent
  −
l    | NotLocalMail
  −
o    | NotSpouse
  −
Rf    | NotRoommate
  −
U    | NotUpcomingFestival
  −
X    | NotCommunityCenterOrWarehouseDone
  −
z    | NotSeason
  −
</pre>
  −
}}
  −
</li>
  −
<li>Event & preconditions are now quote-aware, so you can escape spaces and slashes in arguments like <code>/G "SEASON Spring"/</code>.</li>
  −
<li>Added new preconditions:
  −
{| class="wikitable"
   
|-
 
|-
! precondition
+
| 8&ndash;9
! description
+
| <samp>tile</samp>
 +
| The tile position at which to draw the sprite, in the form <samp>{{t|x}} {{t|y}}</samp>.
 
|-
 
|-
| <samp>!</samp>
+
| 10
| Prefixing <samp>!</samp> to any other precondition will now invert it. For example, <code>!spouse Abigail</code> will match if the player is ''not'' married to Abigail.
+
| <samp>flicker</samp>
 +
| Causes the sprite to flicker in and out of view repeatedly. (one of <samp>true</samp> or <samp>false</samp>).
 
|-
 
|-
| <samp>ActiveDialogueEvent {{t|id}}</samp>
+
| 11
| The special dialogue event with the given ID (including [[Modding:Dialogue#Conversation_topics|Conversation Topics]]) is in progress.
+
| <samp>flip</samp>
 +
| Whether to flip the sprite horizontally when it's drawn (one of <samp>true</samp> or <samp>false</samp>).
 +
|-
 +
| 12
 +
| <samp>sort tile Y</samp>
 +
| The tile Y position to use in the layer depth calculation, which affects which sprite is drawn on top if two sprites overlap. The larger the number, the higher layer the sprite is on.
 +
|-
 +
| 13
 +
| <samp>alpha fade</samp>
 +
| Fades out the sprite based on alpha set. The larger the number, the faster the fade out. 1 is instant.
 +
|-
 +
| 14
 +
| <samp>scale</samp>
 +
| A multiplier applied to the sprite size (in addition to the normal 4× pixel zoom).
 
|-
 
|-
| <samp>DayOfWeek {{t|day}}+</samp>
+
| 15
| Today is one of the specified days (may specify multiple days). This can be a case-insensitive three-letter abbreviation (like <samp>Mon</samp>) or full name (like <samp>Monday</samp>).
+
| <samp>scale change</samp>
 +
| Changes the scale based on the multiplier applied on top of the normal zoom. Continues endlessly.
 
|-
 
|-
| <samp>FestivalDay</samp>
+
| 16
| Today is a [[Festivals|festival]] day.
+
| <samp>rotation</samp>
 +
| The rotation to apply to the sprite, measured in [[wikipedia:radians|radians]].
 
|-
 
|-
| <samp>GameStateQuery {{t|query}}</samp>
+
| 17
| A [[Modding:Game state queries|game state query]] matches, like <code>G !WEATHER Here Sun</code> for 'not sunny in this location'.
+
| <samp>rotation change</samp>
 +
| Continuously rotates the sprite, causing it to spin. The speed is determined by input value.  
 
|-
 
|-
| <samp>Season {{t|season}}+</samp>
+
| 18+
| The current season is one of the given values (may specify multiple seasons).
+
| ''flags''
 +
| Any combination of these space-delimited flags:
 +
* <samp>color {{t|color}}</samp>: apply a [[#Color fields|standard color]] to the sprite.
 +
* <samp>hold_last_frame</samp>: after playing the animation once, freeze the last frame as long as the sprite is shown.
 +
* <samp>ping_pong</samp>: Causes the animation frames to play forwards and backwards alternatingly. Example: An animation with the frames 0, 1, 2 will play "0 1 2 0 1 2" without the ping_pong flag and play "0 1 2 1 0" with the ping_pong flag.
 +
* <samp>motion {{t|x}} {{t|y}}</samp>: Sprite moves based on the values set. Numbers can be decimals or negative.
 +
* <samp>acceleration {{t|x}} {{t|y}}</samp>: '''[TODO: document what this does]'''
 +
* <samp>acceleration_change {{t|x}} {{t|y}}</samp>: '''[TODO: document what this does]'''
 +
|}
 
|-
 
|-
| <samp>Skill {{t|skill name}} {{t|min level}}</samp>
+
| <samp>translateName {{t|actor}} {{t|translation key}}</samp>
| The current farmer has reached at least {{t|min level}} for the given {{t|skill name}} (one of <samp>Combat</samp>, <samp>Farming</samp>, <samp>Fishing</samp>, <samp>Foraging</samp>, <samp>Luck</samp>, or <samp>Mining</samp>).
+
| Set the display name for an NPC in the event to match the given translation key.
 
|-
 
|-
| <samp>UpcomingFestival {{t|day offset}}</samp>
+
| <samp>warpFarmers [{{t|x}} {{t|y}} {{t|direction}}]+ {{t|default offset}} {{t|default x}} {{t|default}} {{t|direction}}</samp>
| A [[Festivals|festival]] day will occur within the given number of days.
+
| Warps connected players to the given [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinates]] and [[Modding:Event data#Directions|numeric directions]]. The {{t|x}} {{t|y}} {{t|direction}} triplet is repeated for each connected player (e.g. the first triplet is for the main player, second triplet is for the first farmhand, etc). The triplets are followed by an offset direction (one of <samp>up</samp>, <samp>down</samp>, <samp>left</samp>, or <samp>right</samp>), and a final triplet which defines the default values used by any other player.
|}</li>
+
|}
<li>Changed specific preconditions:
+
</li>
 +
<li>Fixed some commands assuming a boolean argument is true if present, regardless of its value. This affects the <samp>changeToTemporaryMap</samp>, <samp>emote</samp>, <samp>extendSourceRect</samp>, <samp>faceDirection</samp>, <samp>globalFade</samp>, <samp>globalFadeToClear</samp>, <samp>positionOffset</samp>, and <samp>warp</samp> commands.</li>
 +
<li>Fixed some commands assuming any value except the exact case-sensitive string <samp>true</samp> is false. This affects the <samp>animate</samp>, <samp>glow</samp>, <samp>hideShadow</samp>, <samp>ignoreMovementAnimation</samp>, <samp>temporaryAnimatedSprite</samp>, <samp>temporarySprite</samp>, and <samp>viewport</samp> commands.</li>
 +
<li>Fixed some commands silently ignoring values they can't parse as the expected type. This affects the <samp>addItem</samp>, <samp>makeInvisible</samp>, and <samp>removeItem</samp> commands.</li>
 +
<li>Fixed crash when some commands are passed <samp>farmer[number]</samp> for a player who's not available, or <samp>farmer[number]</samp> when they expect <samp>farmer</samp>.</li>
 +
<li>Fixed some commands not taking into account custom farmer actors when checking <samp>farmer*</samp> actor IDs.</li>
 +
<li>Fixed warp-out event commands able to use NPC-only or gendered warps. They now use a valid warp for the player if possible.</li>
 +
<li>Changed specific commands:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! name
+
! command
 
! changes
 
! changes
 
|-
 
|-
| <samp>ChoseDialogueAnswers</samp> (<samp>q</samp>)
+
| <samp>addCookingRecipe</samp>
 +
| Fixed error if player already knows the recipe.
 +
|-
 +
| <samp>addMailReceived</samp>
 
| &#32;
 
| &#32;
* Fixed precondition ignoring every second answer ID.
+
* Renamed to <samp>mailReceived</samp>. (The old name is now an alias, so it'll still work.)
 +
* You can now remove a mail received by setting the optional third argument to false, like <samp>mailReceived {{t|id}} false</samp>.
 
|-
 
|-
| <samp>InUpgradedHouse</samp> (<samp>L</samp>)
+
| <samp>addTemporaryActor</samp>
 
| &#32;
 
| &#32;
* Added optional argument for the min upgrade level.
+
* Underscores in the asset name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>addTemporaryActor "White Chicken" …</code>.
 +
* Underscores in the display name are no longer replaced with spaces. You should quote arguments containing spaces instead.
 +
* Argument 9 ({{o|animal name}}) is now {{o|override name}}, and can be used to set the name for non-animals too.
 +
|-
 +
| <samp>animate</samp>
 +
| Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>animate "Mr Qi" …</code>.
 +
|-
 +
| <samp>ambientLight</samp>
 +
| Removed four-argument form (which was unused and had confusing behavior). The other versions of <samp>ambientLight</samp> still work like before.
 +
|-
 +
| <samp>awardFestivalPrize</samp>
 +
| Added support for arbitrary item IDs, like <code>awardFestivalPrize (O)128</code> for a pufferfish.
 +
|-
 +
| <samp>changeLocation</samp>
 +
| It now updates the event position offset if needed.
 +
|-
 +
| <samp>changeName</samp>
 +
| Underscores in the NPC name are no longer replaced with spaces. You should quote arguments containing spaces instead, like <code>changeName Leo "Neo Leo"</code>.
 +
|-
 +
| <samp>changePortrait</samp><br /><samp>changeSprite</samp>
 +
| You can now omit the suffix argument to reset the NPC back to their normal portrait/sprite.
 +
|-
 +
| <samp>faceDirection</samp>
 +
| You can now specify the direction in words, like <samp>faceDirection up</samp>
 
|-
 
|-
| <samp>MissingPet</samp> (<samp>h</samp>)
+
| <samp>ignoreMovementAnimation</samp>
 
| &#32;
 
| &#32;
* You can now specify any pet type ID.
+
* Fixed its ''ignore'' argument being ignored.
* You can now omit the argument to check for a pet of any type.
+
* Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>ignoreMovementAnimation "Mr Qi" …</code>.
 +
|-
 +
| <samp>itemAboveHead</samp>
 +
| Added support for arbitrary item IDs, like <code>itemAboveHead (O)128</code> for a pufferfish.
 
|-
 
|-
| <samp>NotDayOfWeek</samp> (<samp>d</samp>)
+
| <samp>makeInvisible</samp>
| &#32;
+
| Fixed terrain features not hidden when using the default area size.
* You can now specify a full name like <samp>Monday</samp>.
  −
* The day of week is now case-insensitive.
   
|-
 
|-
| <samp>NotSeason</samp> (<samp>z</samp>)
+
| <samp>playSound</samp>
| &#32;
+
| Sounds started via <samp>playSound</samp> now stop automatically when the event ends.
* You can now list values (like <code>notSeason spring summer fall</code> instead of <code>notSeason fall/notSeason winter/notSeason fall</code>).
   
|-
 
|-
| <samp>ReachedMineBottom</samp> (<samp>b</samp>)
+
| <samp>removeItem</samp>
| &#32;
+
| Added argument for an optional count, like <code>removeItem (O)128 10</code> to remove 10 pufferfish.
* Argument is now optional (default 1).
   
|-
 
|-
| <samp>Tile</samp> (<samp>a</samp>)
+
| <samp>speak</samp>
| &#32;
+
| Fixed friendship & socialize quest not updated when calling it with a translation key.
* Now also works when the player isn't currently warping, in which case it checks their current tile instead of their warp arrival tile.
   
|}</li>
 
|}</li>
</ul>
+
<li>Removed some commands:
 
+
{| class="wikitable"
====Command changes====
  −
<ul>
  −
<li>Added validation for event commands. If a format or assumption is invalid, the game now logs a detailed error and (if applicable) skips the command, instead of crashing or silently ignoring it. This also means event arguments are stricter (e.g. you can no longer set a true/false field to an invalid value, inner quotes in quoted arguments now need to be escaped, etc).</li>
  −
<li>Event commands are now quote-aware, so you can escape spaces and slashes in arguments like <code>/speak "I'm running A/B tests"/</code>.</li>
  −
<li>Event commands now trim surrounding whitespace, so they can be multilined for readability. Line breaks must be before or after the <samp>/</samp> delimiter. For example:
  −
<syntaxhighlight lang="js">
  −
"SomeEventId/": "
  −
    none/
  −
    -1000 -1000/
  −
    farmer 5 7 0/
  −
    ...
  −
"
  −
</syntaxHighlight>
  −
This can be also combined with the [[Modding:Event data#Comments|comment syntax]] to add notes. For example:
  −
<syntaxhighlight lang="js">
  −
"SomeEventId/": "
  −
    none/            -- music/
  −
    -1000 -1000/    -- initial viewport position/
  −
    farmer 5 7 0/    -- actor positions/
  −
    ...
  −
"
  −
</syntaxHighlight>
  −
</li>
  −
<li>Added new event commands:
  −
{| class="wikitable"
   
|-
 
|-
 
! command
 
! command
! description
+
! changes
 
|-
 
|-
| <samp>addItem {{t|item ID}} {{o|count}} {{o|quality}}</samp>
+
| <samp>addToTable</samp>
| Add an item to the player inventory (or open a grab menu if their inventory is full). The {{t|item ID}} is the [[#Custom items|qualified or unqualified item ID]], and {{o|quality}} is a [[Modding:Items#Quality|numeric quality value]].
+
| Removed (it was unused and worked in counterintuitive ways).
 
|-
 
|-
| <samp>addSpecialOrder {{t|order ID}}</samp><br /><samp>removeSpecialOrder {{t|order ID}}</samp>
+
| <samp>addTool</samp>
| Add or remove a special order to the player team. This affects all players, since special orders are shared.
+
| Removed (it was unused and only supported the [[Return Scepter|return scepter]]). Use <samp>addItem</samp> instead, which supports adding tools.
 
|-
 
|-
| <samp>mailToday {{t|mail key}}</samp>
+
| <samp>grabObject</samp>
| Adds a letter to the mailbox immediately, given the {{t|mail key}} in <samp>Data/Mail</samp>.
+
| Removed (it was unused and broken).
 
|-
 
|-
| <samp>replaceWithClone {{t|NPC name}}</samp>
+
| <samp>showRivalFrame</samp><br /><samp>taxVote</samp>
| Replace an NPC already in the event with a temporary copy. This allows changing the NPC for the event without affecting the real NPC.
+
| Removed (they were part of unimplemented features).
 
  −
For example, this event changes Marnie's name/portrait only within the event:
  −
<syntaxhighlight lang="js">
  −
"Some.ModId_ExampleEvent/": "continue/64 15/farmer 64 15 2 Marnie 64 17 0/replaceWithClone Marnie/changeName Marnie Pufferchick/changePortrait Marnie Pufferchick/[...]/end"
  −
</syntaxhighlight>
   
|-
 
|-
| <samp>stopSound {{t|sound ID}} {{o|immediate}}</samp>
+
| <samp>weddingSprite</samp>
| Stop a sound started with the <samp>startSound</samp> command. This has no effect if the sound has already stopped playing on its own (or hasn't been started). If you started multiple sounds with the same ID, this will stop all of them (e.g. <code>startSound fuse/startSound fuse/stopSound fuse</code>).
+
| Removed (it was broken and unused).
 +
|}
 +
</ul>
   −
By default the sound will stop immediately. For looping sounds, you can pass <samp>false</samp> to the {{o|immediate}} argument to stop the sound when it finishes playing the current iteration instead (e.g. <code>stopSound fuse false</code>).
+
====Festival changes====
 +
* Festivals can now have a custom festival-started notification message by setting the <samp>startedMessage</samp> field in <samp>Data/Festivals/*</samp> to a [[Modding:Tokenizable strings|tokenizable string]].
 +
* Festivals now set the event ID to a value like <samp>festival_fall16</samp>, instead of <samp>-1</samp>.
 +
* All in-festival data fields now support [[Modding:Festival data#Year variants|year variants]].
 +
* Fixed NPCs getting duplicated in festivals if they're added to the <samp>set-up</samp> fields multiple times. Subsequent entries now move them instead.
 +
* Fixed [[Modding:Festival data#Year variants|year variants]] for festival <samp>set-up</samp> field being appended to the main script instead of replacing it.
 +
 
 +
====Send-mail (<samp>x</samp>) precondition deprecated====
 +
Using the <samp>x</samp> event precondition as a way to send mail is now deprecated (but still works). You should use [[#Trigger actions|trigger actions]] instead to perform actions like that.
 +
 
 +
All vanilla events which used it have been replaced by equivalent trigger actions. This event IDs below no longer exist; if you check them (e.g. via <samp>HasSeenEvent</samp>), you'll need to check the new action or the mail flag they set instead.
 +
{| class="wikitable"
 
|-
 
|-
| <samp>temporaryAnimatedSprite ...</samp>
+
! old event ID
| Add a temporary animated sprite to the event, using these space-delimited fields:
+
! new action ID
{| class="wikitable"
+
! mail flag
 
|-
 
|-
! index
+
| <samp>68</samp>
! field
+
| <samp>Mail_Mom_5K</samp>
! effect
+
| <samp>mom1</samp>
 
|-
 
|-
| 0
+
| <samp>69</samp>
| <samp>texture</samp>
+
| <samp>Mail_Mom_15K</samp>
| The asset name for texture to draw.
+
| <samp>mom2</samp>
 
|-
 
|-
| 1&ndash;4
+
| <samp>70</samp>
| <samp>rectangle</samp>
+
| <samp>Mail_Mom_32K</samp>
| The pixel area within the <samp>texture</samp> to draw, in the form <samp>{{t|x}} {{t|y}} {{t|width}} {{t|height}}</samp>.
+
| <samp>mom3</samp>
 
|-
 
|-
| 5
+
| <samp>71</samp>
| <samp>interval</samp>
+
| <samp>Mail_Mom_120K</samp>
| The millisecond duration for each frame in the animation.
+
| <samp>mom4</samp>
 
|-
 
|-
| 6
+
| <samp>72</samp>
| <samp>frames</samp>
+
| <samp>Mail_Dad_5K</samp>
| The number of frames in the animation.
+
| <samp>dad1</samp>
 
|-
 
|-
| 7
+
| <samp>73</samp>
| <samp>loops</samp>
+
| <samp>Mail_Dad_15K</samp>
| The number of times to repeat the animation.
+
| <samp>dad2</samp>
 
|-
 
|-
| 8&ndash;9
+
| <samp>74</samp>
| <samp>tile</samp>
+
| <samp>Mail_Dad_32K</samp>
| The tile position at which to draw the sprite, in the form <samp>{{t|x}} {{t|y}}</samp>.
+
| <samp>dad3</samp>
 
|-
 
|-
| 10
+
| <samp>75</samp>
| <samp>flicker</samp>
+
| <samp>Mail_Dad_120K</samp>
| '''[TODO: document what this does]''' (one of <samp>true</samp> or <samp>false</samp>).
+
| <samp>dad4</samp>
 
|-
 
|-
| 11
+
| <samp>76</samp>
| <samp>flip</samp>
+
| <samp>Mail_Tribune_UpAndComing</samp>
| Whether to flip the sprite horizontally when it's drawn (one of <samp>true</samp> or <samp>false</samp>).
+
| <samp>newsstory</samp>
 
|-
 
|-
| 12
+
| <samp>706</samp>
| <samp>sort tile Y</samp>
+
| <samp>Mail_Pierre_Fertilizers</samp>
| The tile Y position to use in the layer depth calculation, which affects which sprite is drawn on top if two sprites overlap.
+
| <samp>fertilizers</samp>
 
|-
 
|-
| 13
+
| <samp>707</samp>
| <samp>alpha fade</samp>
+
| <samp>Mail_Pierre_FertilizersHighQuality</samp>
| '''[TODO: document what this does]'''
+
| <samp>fertilizers2</samp>
 
|-
 
|-
| 14
+
| <samp>909</samp>
| <samp>scale</samp>
+
| <samp>Mail_Robin_Woodchipper</samp>
| A multiplier applied to the sprite size (in addition to the normal 4× pixel zoom).
+
| <samp>WoodChipper</samp>
 
|-
 
|-
| 15
+
| <samp>2111194</samp>
| <samp>scale change</samp>
+
| <samp>Mail_Emily_8heart</samp>
| '''[TODO: document what this does]'''
+
| <samp>EmilyClothingTherapy</samp>
 
|-
 
|-
| 16
+
| <samp>2111294</samp>
| <samp>rotation</samp>
+
| <samp>Mail_Emily_10heart</samp>
| The rotation to apply to the sprite, measured in [[wikipedia:radians|radians]].
+
| <samp>EmilyCamping</samp>
 
|-
 
|-
| 17
+
| <samp>2346091</samp>
| <samp>rotation change</samp>
+
| <samp>Mail_Alex_10heart</samp>
| '''[TODO: document what this does]'''
+
| <samp>joshMessage</samp>
 
|-
 
|-
| 18+
+
| <samp>2346092</samp>
| ''flags''
+
| <samp>Mail_Sam_10heart</samp>
| Any combination of these space-delimited flags:
+
| <samp>samMessage</samp>
* <samp>color {{t|color}}</samp>: apply a [[#Color fields|standard color]] to the sprite.
  −
* <samp>hold_last_frame</samp>: after playing the animation once, freeze the last frame as long as the sprite is shown.
  −
* <samp>ping_pong</samp>: '''[TODO: document what this does]'''
  −
* <samp>motion {{t|x}} {{t|y}}</samp>: '''[TODO: document what this does]'''
  −
* <samp>acceleration {{t|x}} {{t|y}}</samp>: '''[TODO: document what this does]'''
  −
* <samp>acceleration_change {{t|x}} {{t|y}}</samp>: '''[TODO: document what this does]'''
  −
|}
   
|-
 
|-
| <samp>translateName {{t|actor}} {{t|translation key}}</samp>
+
| <samp>2346093</samp>
| Set the display name for an NPC in the event to match the given translation key.
+
| <samp>Mail_Harvey_10heart</samp>
 +
| <samp>harveyBalloon</samp>
 
|-
 
|-
| <samp>warpFarmers [{{t|x}} {{t|y}} {{t|direction}}]+ {{t|default offset}} {{t|default x}} {{t|default}} {{t|direction}}</samp>
+
| <samp>2346094</samp>
| Warps connected players to the given [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinates]] and [[Modding:Event data#Directions|numeric directions]]. The {{t|x}} {{t|y}} {{t|direction}} triplet is repeated for each connected player (e.g. the first triplet is for the main player, second triplet is for the first farmhand, etc). The triplets are followed by an offset direction (one of <samp>up</samp>, <samp>down</samp>, <samp>left</samp>, or <samp>right</samp>), and a final triplet which defines the default values used by any other player.
+
| <samp>Mail_Elliott_10heart</samp>
|}
+
| <samp>elliottBoat</samp>
</li>
  −
<li>Fixed some commands assuming a boolean argument is true if present, regardless of its value. This affects the <samp>changeToTemporaryMap</samp>, <samp>emote</samp>, <samp>extendSourceRect</samp>, <samp>faceDirection</samp>, <samp>globalFade</samp>, <samp>globalFadeToClear</samp>, <samp>positionOffset</samp>, and <samp>warp</samp> commands.</li>
  −
<li>Fixed some commands assuming any value except the exact case-sensitive string <samp>true</samp> is false. This affects the <samp>animate</samp>, <samp>glow</samp>, <samp>hideShadow</samp>, <samp>ignoreMovementAnimation</samp>, <samp>temporaryAnimatedSprite</samp>, <samp>temporarySprite</samp>, and <samp>viewport</samp> commands.</li>
  −
<li>Fixed some commands silently ignoring values they can't parse as the expected type. This affects the <samp>addItem</samp>, <samp>makeInvisible</samp>, and <samp>removeItem</samp> commands.</li>
  −
<li>Fixed crash when some commands are passed <samp>farmer[number]</samp> for a player who's not available, or <samp>farmer[number]</samp> when they expect <samp>farmer</samp>.</li>
  −
<li>Fixed some commands not taking into account custom farmer actors when checking <samp>farmer*</samp> actor IDs.</li>
  −
<li>Changed specific commands:
  −
{| class="wikitable"
   
|-
 
|-
! command
+
| <samp>2346095</samp>
! changes
+
| <samp>Mail_Elliott_8heart</samp>
 +
| <samp>elliottReading</samp>
 
|-
 
|-
| <samp>addCookingRecipe</samp>
+
| <samp>2346096</samp>
| Fixed error if player already knows the recipe.
+
| <samp>Mail_Penny_10heart</samp>
 +
| <samp>pennySpa</samp>
 
|-
 
|-
| <samp>addTemporaryActor</samp>
+
| <samp>2346097</samp>
| &#32;
+
| <samp>Mail_Abigail_8heart</samp>
* Underscores in the asset name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>addTemporaryActor "White Chicken" …</code>.
+
| <samp>abbySpiritBoard</samp>
* Underscores in the display name are no longer replaced with spaces. You should quote arguments containing spaces instead.
   
|-
 
|-
| <samp>animate</samp>
+
| <samp>3333094</samp>
| Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>animate "Mr Qi" …</code>.
+
| <samp>Mail_Pierre_ExtendedHours</samp>
 +
| <samp>pierreHours</samp>
 
|-
 
|-
| <samp>ambientLight</samp>
+
| <samp>3872126</samp>
| Removed four-argument form (which was unused and had confusing behavior). The other versions of <samp>ambientLight</samp> still work like before.
+
| <samp>Mail_Willy_BackRoomUnlocked</samp>
 +
| <samp>willyBackRoomInvitation</samp>
 +
|}
 +
 
 +
===[[Modding:Mail data|Mail]] changes===
 +
{{/doc status|[[Modding:Mail data]]|done=false}}
 +
 
 +
<ul>
 +
<li>Mail can now have multiple items attached (using multiple <samp>%item</samp> commands). When the player grabs the top item, the next one will appear in the slot to grab next.</li>
 +
<li>Added mail commands:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>awardFestivalPrize</samp>
+
! command
| Added support for arbitrary item IDs, like <code>awardFestivalPrize (O)128</code> for a pufferfish.
+
! effect
 
|-
 
|-
| <samp>changeName</samp>
+
| <samp>%action {{t|action}}%%</samp>
| Underscores in the NPC name are no longer replaced with spaces. You should quote arguments containing spaces instead, like <code>changeName Leo "Neo Leo"</code>.
+
| Run a [[Modding:Trigger actions|trigger action string]], like <samp>%action AddMoney 500%%</samp> to add {{price|500}} to the current player.
 +
|}</li>
 +
<li>Improved mail commands:
 +
{| class="wikitable"
 
|-
 
|-
| <samp>changePortrait</samp><br /><samp>changeSprite</samp>
+
! command
| You can now omit the suffix argument to reset the NPC back to their normal portrait/sprite.
+
! changes
 
|-
 
|-
| <samp>faceDirection</samp>
+
| <samp>%item</samp>
| You can now specify the direction in words, like <samp>faceDirection up</samp>
  −
|-
  −
| <samp>ignoreMovementAnimation</samp>
   
| &#32;
 
| &#32;
* Fixed its ''ignore'' argument being ignored.
+
* Added <samp>%item id {{t|item id}} {{o|count}}</samp> form which accepts a [[#Custom items|qualified or unqualified item ID]]. If multiple items are listed (''e.g.,'' <samp>%item id (BC)12 3 (O)34 5 %%</samp>) one set will be picked randomly. This deprecates the <samp>bigobject</samp>, <samp>furniture</samp>, <samp>object</samp>, and <samp>tools</samp> options.
* Underscores in the NPC name are now only replaced with spaces if an exact match wasn't found. You should quote arguments containing spaces instead, like <code>ignoreMovementAnimation "Mr Qi" …</code>.
+
* Added <samp>%item specialOrder {{t|order id}} {{o|immediately}}</samp> form to attach a special order to the letter.
|-
+
* Added optional {{t|key}} argument to <samp>%item cookingRecipe {{t|key}}</samp>, to learn a specific [[Modding:Recipe data|cooking recipe]]. The previous <samp>%item cookingRecipe</samp> form (without a key) works the same way as before.
| <samp>itemAboveHead</samp>
+
* The type argument is now case-insensitive.
| Added support for arbitrary item IDs, like <code>itemAboveHead (O)128</code> for a pufferfish.
  −
|-
  −
| <samp>makeInvisible</samp>
  −
| Fixed terrain features not hidden when using the default area size.
  −
|-
  −
| <samp>removeItem</samp>
  −
| Added argument for an optional count, like <code>removeItem (O)128 10</code> to remove 10 pufferfish.
  −
|-
  −
| <samp>speak</samp>
  −
| Fixed friendship & socialize quest not updated when calling it with a translation key.
  −
|}</li>
  −
<li>Removed some commands:
  −
{| class="wikitable"
  −
|-
  −
! command
  −
! changes
  −
|-
  −
| <samp>addToTable</samp>
  −
| Removed (it was unused and worked in counterintuitive ways).
  −
|-
  −
| <samp>addTool</samp>
  −
| Removed (it was unused and only supported the [[Return Scepter|return scepter]]). Use <samp>addItem</samp> instead, which supports adding tools.
  −
|-
  −
| <samp>grabObject</samp>
  −
| Removed (it was unused and broken).
  −
|-
  −
| <samp>showRivalFrame</samp><br /><samp>taxVote</samp>
  −
| Removed (they were part of unimplemented features).
  −
|-
  −
| <samp>weddingSprite</samp>
  −
| Removed (it was broken and unused).
  −
|}
  −
</ul>
  −
 
  −
====Festival changes====
  −
* Festivals can now have a custom festival-started notification message by setting the <samp>startedMessage</samp> field in <samp>Data/Festivals/*</samp> to a [[Modding:Tokenizable strings|tokenizable string]].
  −
* Festivals now set the event ID to a value like <samp>festival_fall16</samp>, instead of <samp>-1</samp>.
  −
* All in-festival data fields now support [[Modding:Festival data#Year variants|year variants]].
  −
* Fixed NPCs getting duplicated in festivals if they're added to the <samp>set-up</samp> fields multiple times. Subsequent entries now move them instead.
  −
* Fixed [[Modding:Festival data#Year variants|year variants]] for festival <samp>set-up</samp> field being appended to the main script instead of replacing it.
  −
 
  −
===[[Modding:Mail data|Mail]] changes===
  −
<ul>
  −
<li>Mail can now have multiple items attached (using multiple <samp>%item</samp> commands). When the player grabs the top item, the next one will appear in the slot to grab next.</li>
  −
<li>Improved mail commands:
  −
{| class="wikitable"
  −
|-
  −
! command
  −
! changes
  −
|-
  −
| <samp>%item</samp>
  −
| &#32;
  −
* Added <samp>%item id {{t|item id}} {{o|count}}</samp> form which accepts a [[#Custom items|qualified or unqualified item ID]]. If multiple items are listed (''e.g.,'' <samp>%item id (BC)12 3 (O)34 5 %%</samp>) one set will be picked randomly. This deprecates the <samp>bigobject</samp>, <samp>furniture</samp>, <samp>object</samp>, and <samp>tools</samp> options.
  −
* Added <samp>%item specialOrder {{t|order id}} {{o|immediately}}</samp> form to attach a special order to the letter.
  −
* Added optional {{t|key}} argument to <samp>%item cookingRecipe {{t|key}}</samp>, to learn a specific [[Modding:Recipe data|cooking recipe]]. The previous <samp>%item cookingRecipe</samp> form (without a key) works the same way as before.
  −
* The type argument is now case-insensitive.
   
* Fixed <samp>%item craftingRecipe</samp> not supporting recipe IDs containing underscores. It now checks for an exact match first, then tries replacing underscores with spaces like before, then logs a warning if neither was found instead of adding an invalid recipe.
 
* Fixed <samp>%item craftingRecipe</samp> not supporting recipe IDs containing underscores. It now checks for an exact match first, then tries replacing underscores with spaces like before, then logs a warning if neither was found instead of adding an invalid recipe.
 
|}</li>
 
|}</li>
Line 7,060: Line 7,019:     
This isn't idempotent (e.g. calling it twice will result in double-escaped quotes).
 
This isn't idempotent (e.g. calling it twice will result in double-escaped quotes).
|}
+
|-
 +
| <samp>UnsplitQuoteAware</samp>
 +
| Combine an array of arguments into a single string with a custom delimiter, using quotes where needed to escape delimiters within an argument. Calling <samp>SplitQuoteAware</samp> on the resulting string with the same delimiter will produce the original values.
 +
 
 +
For example:
 +
<syntaxhighlight lang="c#">
 +
string args = ArgUtility.UnsplitQuoteAware(new[] { "A", "B C", "D" }, ' '); // A "B C" D
 +
</syntaxhighlight>
 +
 
 +
This isn't idempotent (e.g. calling it twice will result in double-escaped quotes).
 +
|}
    
; Reading arrays&#58;
 
; Reading arrays&#58;
Line 7,120: Line 7,089:  
else
 
else
 
     this.Helper.Monitor.Log($"Failed getting remainder: {error}", LogLevel.Warn);
 
     this.Helper.Monitor.Log($"Failed getting remainder: {error}", LogLevel.Warn);
 +
</syntaxhighlight>
 +
|-
 +
| <samp>GetSubsetOf</samp>
 +
| Get a slice of the input array. For example:
 +
<syntaxhighlight lang="c#">
 +
string[] subset1 = ArgUtility.GetSubsetOf(new[] { "A", "B", "C", "D" }, startAt: 1); // B, C, D
 +
string[] subset2 = ArgUtility.GetSubsetOf(new[] { "A", "B", "C", "D" }, startAt: 1, length: 2); // B, C
 +
</syntaxhighlight>
 +
 +
This is fault-tolerant as long as <samp>startAt</samp> isn't negative. For example:
 +
<syntaxhighlight lang="c#">
 +
string[] subset2 = ArgUtility.GetSubsetOf(new[] { "A", "B", "C", "D" }, startAt: 100); // <empty array>
 +
string[] subset1 = ArgUtility.GetSubsetOf(new[] { "A", "B", "C", "D" }, startAt: 1, length: 100); // B, C, D
 
</syntaxhighlight>
 
</syntaxhighlight>
 
|}
 
|}
Line 7,234: Line 7,216:  
</syntaxhighlight>
 
</syntaxhighlight>
    +
Or you could replace all instances of an obsolete item with a new one:
 +
<syntaxhighlight lang="c#">
 +
Utility.ForEachItem((item, remove, replaceWith) =>
 +
{
 +
    if (item.QualifiedItemId == "(O)OldId")
 +
    {
 +
        Item newItem = ItemRegistry.Create("(O)NewId", item.Stack, item.Quality);
 +
        replaceWith(newItem);
 +
    }
 +
 +
    return true;
 +
});
 +
</syntaxhighlight>
 
C# mods which add custom item types can override <samp>Item.ForEachItem</samp> to add support for nested items.
 
C# mods which add custom item types can override <samp>Item.ForEachItem</samp> to add support for nested items.
   Line 7,295: Line 7,290:  
! method
 
! method
 
! effect
 
! effect
 +
|-
 +
| <samp>Game1.getOfflineFarmhands()</samp>
 +
| Get all farmhands who aren't connected to the game.
 +
|-
 +
| <samp>Game1.PerformActionWhenPlayerFree</samp>
 +
| Calls the provided callback next time the player is free (e.g. no menu or event is up, not using a tool, etc). If the player is already free, it's run immediately.
 +
 +
For example, if you receive your first geode from a fishing chest, this is used to show the geode-received animation & animation when it closes.
 +
|-
 +
| <samp>Game1.createRadialDebris_MoreNatural</samp>
 +
| Scatter item debris around a position with a more randomized distribution than <samp>createRadialDebris</samp>.
 +
|-
 +
| <samp>Object.GetCategoryColor</samp><br /><samp>Object.GetCategoryDisplayName</samp>
 +
| Get the color and display name for the given category number when it's shown in a tooltip.
 
|-
 
|-
 
| <samp>Utility.distanceFromScreen</samp>
 
| <samp>Utility.distanceFromScreen</samp>
Line 7,320: Line 7,329:  
</syntaxhighlight>
 
</syntaxhighlight>
 
|-
 
|-
| <samp>Utility.isFestivalDay</samp><br /><samp>Utility.IsPassiveFestivalDay</samp>
+
| <samp>Utility.isFestivalDay</samp>
| These methods existed before 1.6, but now have versions with no arguments to check today:
+
| This method existed before 1.6, but you can now omit arguments to check today instead of a specific date:
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
 
bool festivalToday = Utility.isFestivalToday();
 
bool festivalToday = Utility.isFestivalToday();
 
</syntaxhighlight>
 
</syntaxhighlight>
   −
<samp>IsPassiveFestivalDay</samp> also has a new form to check for a specific festival today:
+
Or check for a festival in specific location context:
 +
<syntaxhighlight lang="c#">
 +
bool desertFestivalToday = Utility.isFestivalToday(LocationContexts.DesertId);
 +
</syntaxhighlight>
 +
|-
 +
| <samp>Utility.IsPassiveFestivalDay</samp>
 +
| This method existed before 1.6, but now can now omit arguments to check today instead of a specific date:
 +
<syntaxhighlight lang="c#">
 +
bool passiveFestivalToday = Utility.IsPassiveFestivalDay();
 +
</syntaxhighlight>
 +
 
 +
Or check for a specific passive festival:
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
 
bool nightMarketToday = Utility.IsPassiveFestivalDay("NightMarket");
 
bool nightMarketToday = Utility.IsPassiveFestivalDay("NightMarket");
Line 7,441: Line 7,461:     
====Debug commands====
 
====Debug commands====
 +
{{/doc status|[[Modding:Console commands]]|done=false}}
 +
 
<ul>
 
<ul>
 
<li>All debug commands are now quote-aware, so you can pass spaces in arguments like <code>debug build "Junimo Hut"</code>.</li>
 
<li>All debug commands are now quote-aware, so you can pass spaces in arguments like <code>debug build "Junimo Hut"</code>.</li>
Line 7,448: Line 7,470:  
! command
 
! command
 
! description
 
! description
 +
|-
 +
| <samp>action {{t|action}}</samp>
 +
| Run a [[Modding:Trigger actions|trigger action string]], like <samp>action AddMoney 500</samp> to add {{price|500}} to the current player.
 
|-
 
|-
 
| <samp>artifactSpots</samp>
 
| <samp>artifactSpots</samp>
Line 7,480: Line 7,505:  
| ''Syntax:'' <samp>iq {{t|query}}</samp>
 
| ''Syntax:'' <samp>iq {{t|query}}</samp>
   −
Open a shop menu with all the items matching an [[#Item queries|item query]] (all items free). For example:
+
Open a shop menu with all the items matching an [[Modding:Item queries|item query]] (all items free). For example:
 
* <samp>debug iq ALL_ITEMS</samp> shows all items;
 
* <samp>debug iq ALL_ITEMS</samp> shows all items;
 
* <samp>debug iq ALL_ITEMS (W)</samp> shows all weapons;
 
* <samp>debug iq ALL_ITEMS (W)</samp> shows all weapons;
Line 7,486: Line 7,511:  
* <samp>debug iq FLAVORED_ITEM Wine (O)128</samp> shows Pufferfish Wine.
 
* <samp>debug iq FLAVORED_ITEM Wine (O)128</samp> shows Pufferfish Wine.
 
|-
 
|-
| <samp>legacyTimeouts</samp>
+
| <samp>logFile</samp>
| Switches the multiplayer timeout behavior between legacy (timeouts are based on both ping time and last sync time like in 1.5.6) and non-legacy (timeouts are only based on ping time).
+
| Begin writing debug messages to a log file at <samp>%appdata%/StardewValley/ErrorLogs/game-latest.txt</samp> to simplify troubleshooting. You can also enter <samp>/logtext</samp> into the in-game chatbox to enable it.
 +
 
 +
This does nothing if SMAPI is installed, since the debug messages are already saved to SMAPI's log.
 
|-
 
|-
 
| <samp>logSounds</samp>
 
| <samp>logSounds</samp>
 
| Log info about each sound effect played to the SMAPI console window.
 
| Log info about each sound effect played to the SMAPI console window.
 +
|-
 +
| <samp>movieSchedule {{o|year}}</samp>
 +
| Lists the movies that will play in a given {{o|year}} (default this year), with the dates they'll play.
 
|-
 
|-
 
| <samp>qualifiedid</samp>
 
| <samp>qualifiedid</samp>
Line 7,503: Line 7,533:  
     - Backpack
 
     - Backpack
 
     - FillBackpack (fbp, fill, fillbp)</pre>
 
     - FillBackpack (fbp, fill, fillbp)</pre>
 +
|-
 +
| <samp>setFarmEvent</samp> / <samp>sfe</samp>
 +
| ''Syntax:'' <samp>setFarmEvent {{t|event id}}</samp>
 +
 +
Queue an [[Random Events#Farm events|overnight farm event]] if one doesn't plan naturally instead. The {{t|event id}} can be one of...
 +
* <samp>dogs</samp>;
 +
* [[Random Events#Earthquake|<samp>earthquake</samp>]];
 +
* [[Random Events#The Crop Fairy|<samp>fairy</samp>]];
 +
* [[Random Events#Meteorite|<samp>meteorite</samp>]];
 +
* [[Random Events#Stone Owl|<samp>owl</samp>]];
 +
* [[Random Events#Strange Capsule|<samp>ufo</samp>]];
 +
* [[Random Events#The Witch|<samp>witch</samp>]].
 +
 +
Note that even if the farm event runs, it may exit without doing anything (e.g. rare events like <samp>ufo</samp> have extra condition checks when the start).
 
|-
 
|-
 
| <samp>shop</samp>
 
| <samp>shop</samp>
Line 7,513: Line 7,557:  
|-
 
|-
 
| <samp>testwedding</samp>
 
| <samp>testwedding</samp>
| Immediately play the [[Marriage#The Wedding|wedding]] event.
+
| Immediately play the [[Marriage#The Wedding|wedding]] event. This requires the player to be married first - to test specific NPCs, <samp>debug marry</samp> the NPC followed by this command.
 
|-
 
|-
 
| <samp>thishouseupgrade</samp> / <samp>thishouse</samp> / <samp>thu</samp>
 
| <samp>thishouseupgrade</samp> / <samp>thishouse</samp> / <samp>thu</samp>
 
| Equivalent to <samp>houseupgrade</samp>, but can be used to upgrade another player's house by running it from inside or just south of its exterior.
 
| Equivalent to <samp>houseupgrade</samp>, but can be used to upgrade another player's house by running it from inside or just south of its exterior.
 +
|-
 +
| <samp>toggleCheats</samp>
 +
| Enable or disable entering debug commands into the in-game chat (prefixed with <samp>/</samp>).
 
|-
 
|-
 
| <samp>tokens</samp>
 
| <samp>tokens</samp>
Line 7,608: Line 7,655:  
| <samp>playSound</samp>
 
| <samp>playSound</samp>
 
| Added an optional pitch argument, like <samp>debug playSound barrelBreak 1200</samp>. The pitch is a value from 1 (low pitch) to 2400 (high pitch) inclusively.
 
| Added an optional pitch argument, like <samp>debug playSound barrelBreak 1200</samp>. The pitch is a value from 1 (low pitch) to 2400 (high pitch) inclusively.
 +
|-
 +
| <samp>question</samp>
 +
| You can now forget a selected answer (instead of adding it) by setting the second argument to false, like <samp>question {{t|id}} false</samp>.
 +
|-
 +
| <samp>runTestEvent</samp>
 +
| Fixed support for Unix line endings.
 +
|-
 +
| <samp>seenEvent</samp>
 +
| You can now forget an event (instead of adding it) by setting the second argument to false, like <samp>seenEvent {{t|id}} false</samp>.
 +
|-
 +
| <samp>seenMail</samp>
 +
| You can now remove a mail received (instead of adding it) by setting the second argument to false, like <samp>seenMail {{t|id}} false</samp>.
 
|-
 
|-
 
| <samp>skinBuilding</samp>
 
| <samp>skinBuilding</samp>
Line 7,650: Line 7,709:  
|-
 
|-
 
| <samp>ax</samp><br /><samp>bigItem</samp>/<samp>b</samp>/<samp>bi</samp>/<samp>big</samp><br /><samp>boots</samp><br /><samp>clothes</samp><br /><samp>hoe</samp><br /><samp>milkPail</samp>/<samp>mp</samp><br /><samp>pan</samp><br /><samp>pickaxe</samp>/<samp>pick</samp>/<samp>pickax</samp><br /><samp>ring</samp>/<samp>addRing</samp><br /><samp>shears</samp>/<samp>scissors</samp><br /><samp>slingshot</samp><br /><samp>tool</samp><br /><samp>wateringCan</samp>/<samp>can</samp><br /><samp>wand</samp><br /><samp>weapon</samp>
 
| <samp>ax</samp><br /><samp>bigItem</samp>/<samp>b</samp>/<samp>bi</samp>/<samp>big</samp><br /><samp>boots</samp><br /><samp>clothes</samp><br /><samp>hoe</samp><br /><samp>milkPail</samp>/<samp>mp</samp><br /><samp>pan</samp><br /><samp>pickaxe</samp>/<samp>pick</samp>/<samp>pickax</samp><br /><samp>ring</samp>/<samp>addRing</samp><br /><samp>shears</samp>/<samp>scissors</samp><br /><samp>slingshot</samp><br /><samp>tool</samp><br /><samp>wateringCan</samp>/<samp>can</samp><br /><samp>wand</samp><br /><samp>weapon</samp>
| These are replaced by more general commands like <code>item (O)128</code> (spawn item by ID), <code>fuzzyItemNamed pufferfish</code> (spawn by item name), or <code>itemQuery FLAVORED_ITEM Wine (O)128</code> (spawn by [[#Item queries|item query]]).
+
| These are replaced by more general commands like <code>item (O)128</code> (spawn item by ID), <code>fuzzyItemNamed pufferfish</code> (spawn by item name), or <code>itemQuery FLAVORED_ITEM Wine (O)128</code> (spawn by [[Modding:Item queries|item query]]).
 
|-
 
|-
 
| <samp>addQuartz</samp><br /><samp>blueBook</samp><br /><samp>blueprint</samp><br /><samp>end</samp>
 
| <samp>addQuartz</samp><br /><samp>blueBook</samp><br /><samp>blueprint</samp><br /><samp>end</samp>
Line 7,660: Line 7,719:  
| <samp>ee</samp><br /><samp>endEvent</samp>/<samp>leaveEvent</samp><br /><samp>eventOver</samp>
 
| <samp>ee</samp><br /><samp>endEvent</samp>/<samp>leaveEvent</samp><br /><samp>eventOver</samp>
 
| Replaced by the new <samp>endEvent</samp> command.
 
| Replaced by the new <samp>endEvent</samp> command.
 +
|-
 +
| <samp>everythingshop</samp>
 +
| Removed. You can get all items like <code>debug iq ALL_ITEMS</code>, or all items of a given type like <code>debug iq ALL_ITEMS (O)</code>.
 
|-
 
|-
 
| <samp>oldMineGame</samp>
 
| <samp>oldMineGame</samp>
Line 7,678: Line 7,740:  
====Menus & UI====
 
====Menus & UI====
 
* Rewrote calendar menu (<samp>Billboard</samp>) to simplify custom events & event types. C# mods can now edit <samp>billboard.calendarDayData</samp> or patch <samp>billboard.GetEventsForDay</samp> to add new events.
 
* Rewrote calendar menu (<samp>Billboard</samp>) to simplify custom events & event types. C# mods can now edit <samp>billboard.calendarDayData</samp> or patch <samp>billboard.GetEventsForDay</samp> to add new events.
* The <samp>SpriteText</samp> methods now accept arbitrary <samp>Color</samp> tints instead of a few predefined color IDs.
   
* Added <samp>Game1.textShadowDarkerColor</samp> field for the colors previously hardcoded in <samp>Utility.drawTextWithShadow</samp>.
 
* Added <samp>Game1.textShadowDarkerColor</samp> field for the colors previously hardcoded in <samp>Utility.drawTextWithShadow</samp>.
 
* Added <samp>MoneyDial.ShouldShakeMainMoneyBox</samp> field to simplify custom dials.
 
* Added <samp>MoneyDial.ShouldShakeMainMoneyBox</samp> field to simplify custom dials.
 +
* Partly de-hardcoded <samp>ShopMenu</samp> filter tabs. You can now change filter tabs by setting the <samp>shopMenu.tabButtons</samp> field with arbitrary <samp>Func&lt;ISalable, bool&gt; Filter</samp> values, or by using a predefined set of tabs like <samp>shopMenu.UseDresserTabs()</samp>.
 +
* The <samp>SpriteText</samp> methods now accept arbitrary <samp>Color</samp> tints instead of a few predefined color IDs.
 +
* The <samp>DiscreteColorPicker.getColorFromSelection</samp> methods are now static for reuse.
 +
* Fixed <samp>DiscreteColorPicker</samp> constructor ignoring the initial color argument, and added a constructor which takes a <samp>Color</samp> value.
 
* Fixed an edge case where a custom language's fonts wouldn't be loaded when switching language.
 
* Fixed an edge case where a custom language's fonts wouldn't be loaded when switching language.
    
====[[Modding:Modder Guide/Game Fundamentals#Net fields|Net fields]]====
 
====[[Modding:Modder Guide/Game Fundamentals#Net fields|Net fields]]====
* Removed implicit conversion operators for most types (except <samp>NetBool</samp>, <samp>NetInt</samp>, and <samp>NetString</samp>).
+
* Removed implicit conversion operators for most types due to their sometimes counter-intuitive behavior. The only ones left are <samp>NetBool</samp>, <samp>NetInt</samp>, and <samp>NetString</samp>; those are now marked obsolete and will raise build warnings on use.
 
* <samp>NetLocationRef</samp> now has a public <samp>LocationName</samp> and <samp>IsStructure</samp>, and its <samp>Update</samp> method allows forcing an update.
 
* <samp>NetLocationRef</samp> now has a public <samp>LocationName</samp> and <samp>IsStructure</samp>, and its <samp>Update</samp> method allows forcing an update.
    
====Quests====
 
====Quests====
 +
{{/doc status|[[Modding:Quest data]]|done=false}}
 +
 
* Quests now have string IDs, to simplify custom quest frameworks.
 
* Quests now have string IDs, to simplify custom quest frameworks.
 
* Added validation for quest data parsing.
 
* Added validation for quest data parsing.
Line 7,714: Line 7,781:  
* All terrain features now have <samp>Tile</samp> and <samp>Location</samp> properties, and their methods no longer have location/tile parameters in most cases.
 
* All terrain features now have <samp>Tile</samp> and <samp>Location</samp> properties, and their methods no longer have location/tile parameters in most cases.
 
* All [[Modding:Modder Guide/Game Fundamentals#Net fields|net fields]] now have <samp>Name</samp> and <samp>Owner</samp> fields, which are used to show informative error messages when there's a sync issue and validate common mistakes (e.g. a net field not added to the <samp>NetFields</samp> collection).
 
* All [[Modding:Modder Guide/Game Fundamentals#Net fields|net fields]] now have <samp>Name</samp> and <samp>Owner</samp> fields, which are used to show informative error messages when there's a sync issue and validate common mistakes (e.g. a net field not added to the <samp>NetFields</samp> collection).
 +
* The game now tracks the locations a player has visited. Mods can check the list in C# (via <samp>Game1.player.locationsVisited</samp>) or [[Modding:Game state queries|game state queries]] (via <samp>PLAYER_VISITED_LOCATION</samp>). For pre-existing saves, the list is retroactively populated based on accessible locations, events seen, mail flags set, etc.
 
* Added menu queuing (via <samp>Game1.nextClickableMenu</samp> in C#). For example, this applies if you try to take an item from a mail letter when your inventory is full.
 
* Added menu queuing (via <samp>Game1.nextClickableMenu</samp> in C#). For example, this applies if you try to take an item from a mail letter when your inventory is full.
 
* Added C# code docs in many places.
 
* Added C# code docs in many places.
Line 7,723: Line 7,791:  
* The game now uses <samp>[XmlInclude]</samp> on its types more consistently. That means the default save serializer can handle more types (e.g. all monsters), and it's easier to create custom serializers.
 
* The game now uses <samp>[XmlInclude]</samp> on its types more consistently. That means the default save serializer can handle more types (e.g. all monsters), and it's easier to create custom serializers.
 
* Refactored many parts of the code to make it more moddable for C# mods. This includes marking all classes public, changing <samp>private</samp> members to <samp>protected</samp> or <samp>public</samp>, marking members <samp>virtual</samp>, rewriting or splitting code so it's easier to extend, etc.
 
* Refactored many parts of the code to make it more moddable for C# mods. This includes marking all classes public, changing <samp>private</samp> members to <samp>protected</samp> or <samp>public</samp>, marking members <samp>virtual</samp>, rewriting or splitting code so it's easier to extend, etc.
 +
* The <samp>startup_preferences</samp> file is now formatted to simplify troubleshooting.
 
* Fixed many cases where the game used <samp>Game1.player</samp> instead of the provided player.
 
* Fixed many cases where the game used <samp>Game1.player</samp> instead of the provided player.
   Line 7,797: Line 7,866:  
* When referencing numeric IDs, you usually just need to convert them into a string (like <code>Game1.player.hasBuff("1590166")</code> or <code>Game1.player.eventsSeen.Contains("1590166")</code>).
 
* When referencing numeric IDs, you usually just need to convert them into a string (like <code>Game1.player.hasBuff("1590166")</code> or <code>Game1.player.eventsSeen.Contains("1590166")</code>).
 
* When creating buffs, see [[#Buff overhaul|buff overhaul]] for how to create buffs now.
 
* When creating buffs, see [[#Buff overhaul|buff overhaul]] for how to create buffs now.
 +
* For pre-existing content pack data, see migration steps in the ''[[#Unique string IDs|unique string IDs]]'' section.
    
===Building and animal changes===
 
===Building and animal changes===
Line 7,823: Line 7,893:  
| Use <samp>Attack</samp> and <samp>Immunity</samp> instead.
 
| Use <samp>Attack</samp> and <samp>Immunity</samp> instead.
 
|-
 
|-
| <samp>addedCombatLevel</samp><br /><samp>addedFarmingLevel</samp><br /><samp>addedFishingLevel</samp><br /><samp>addedForagingLevel</samp><br /><samp>addedLuckLevel</samp><br /><samp>addedMiningLevel</samp><br /><samp>attackIncreaseModifier</samp><br /><samp>critChanceModifier</samp><br /><samp>critPowerModifier</samp><br /><samp>knockbackModifier</samp><br /><samp>resilience</samp><br /><samp>weaponPrecisionModifier</samp><br /><samp>weaponSpeedModifier</samp>
+
| <samp>addedCombatLevel</samp><br /><samp>addedFarmingLevel</samp><br /><samp>addedFishingLevel</samp><br /><samp>addedForagingLevel</samp><br /><samp>addedLuckLevel</samp><br /><samp>addedMiningLevel</samp><br /><samp>attackIncreaseModifier</samp><br /><samp>critChanceModifier</samp><br /><samp>critPowerModifier</samp><br /><samp>knockbackModifier</samp><br /><samp>weaponPrecisionModifier</samp><br /><samp>weaponSpeedModifier</samp>
 
| Use equivalent properties under <samp>Game1.player.buffs</samp> instead (e.g. <samp>Game1.player.buffs.CombatLevel</code>).
 
| Use equivalent properties under <samp>Game1.player.buffs</samp> instead (e.g. <samp>Game1.player.buffs.CombatLevel</code>).
 +
|-
 +
| <samp>resilience</samp>
 +
| Use <samp>buffs.Defense</samp> instead.
 
|-
 
|-
 
| <samp>addedSpeed</samp><br /><samp>CombatLevel</samp><br /><samp>CraftingTime</samp><br /><samp>FarmingLevel</samp><br /><samp>FishingLevel</samp><br /><samp>ForagingLevel</samp><br /><samp>LuckLevel</samp><br /><samp>MagneticRadius</samp><br /><samp>MaxStamina</samp><br /><samp>MiningLevel</samp><br /><samp>Stamina</samp>
 
| <samp>addedSpeed</samp><br /><samp>CombatLevel</samp><br /><samp>CraftingTime</samp><br /><samp>FarmingLevel</samp><br /><samp>FishingLevel</samp><br /><samp>ForagingLevel</samp><br /><samp>LuckLevel</samp><br /><samp>MagneticRadius</samp><br /><samp>MaxStamina</samp><br /><samp>MiningLevel</samp><br /><samp>Stamina</samp>
| These are now readonly and can't be set directly. You can change them by [[#Buff overhaul|adding a buff]], equipment bonus, etc instead.
+
| These are now readonly and can't be set directly. You can change them by [[#Buff overhaul|adding a buff]] (which can be invisible), equipment bonus, etc instead.
 
|}</li>
 
|}</li>
 
<li>Buffs are now recalculated automatically, and you can reset a buff by just reapplying it. See [[#Buff overhaul|buff overhaul]] for more info.</li>
 
<li>Buffs are now recalculated automatically, and you can reset a buff by just reapplying it. See [[#Buff overhaul|buff overhaul]] for more info.</li>
Line 8,067: Line 8,140:  
| <samp>NPC</samp>
 
| <samp>NPC</samp>
 
| &#32;
 
| &#32;
* <samp>canReceiveThisItemAsGift(…)</samp>
   
* <samp>idForClones</samp>
 
* <samp>idForClones</samp>
 
|-
 
|-
Line 8,198: Line 8,270:  
|rowspan="3"| <samp>Bush</samp>
 
|rowspan="3"| <samp>Bush</samp>
 
| <samp>overrideSeason</samp>
 
| <samp>overrideSeason</samp>
| Removed; use <code>bush.currentLocation.GetSeason()</code> instead.
+
| Removed; use <code>bush.Location.GetSeason()</code> instead.
 
|-
 
|-
 
| <samp>greenhouseBush</samp>
 
| <samp>greenhouseBush</samp>
Line 8,219: Line 8,291:  
| <samp>MoveToSafePosition</samp>
 
| <samp>MoveToSafePosition</samp>
 
| Replaced by the simpler <samp>TryMoveToSafePosition</samp>
 
| Replaced by the simpler <samp>TryMoveToSafePosition</samp>
 +
|-
 +
|rowspan="2"| <samp>Dialogue</samp>
 +
| <samp>dialogues</samp>
 +
| Changed from <code>List&lt;string&gt;</code> to <code>List&lt;DialogueLine&gt;</code>. The <samp>Text</samp> field on each dialogue line is equivalent to the old value.
 +
|-
 +
| <samp>isOnFinalDialogue()</samp>
 +
| This now indicates whether it's showing the last dialogue ''with message text''; there may still be entries in <samp>dialogues</samp> which apply side-effects without message text.
 
|-
 
|-
 
|rowspan="3"| <samp>Farmer</samp>
 
|rowspan="3"| <samp>Farmer</samp>
Line 8,252: Line 8,331:  
| Overhauled into [[#Custom objects|<samp>Game1.objectData</samp>]].
 
| Overhauled into [[#Custom objects|<samp>Game1.objectData</samp>]].
 
|-
 
|-
|rowspan="2"| <samp>GameLocation</samp>
+
|rowspan="3"| <samp>GameLocation</samp>
 
| <samp>getCharacters</samp>
 
| <samp>getCharacters</samp>
 
| Removed; use the <samp>characters</samp> field instead.
 
| Removed; use the <samp>characters</samp> field instead.
 +
|-
 +
| <samp>GetMapPropertyPosition</samp>
 +
| Replaced by <samp>TryGetMapPropertyAs</samp>, which supports multiple data types (not just <samp>Point</samp>).
 
|-
 
|-
 
| <samp>isTileOccupied</samp><br /><samp>isTileOccupiedForPlacement</samp><br /><samp>isTileOccupiedIgnoreFloors</samp><br /><samp>isTileLocationOpenIgnoreFrontLayers</samp><br /><samp>isTileLocationTotallyClearAndPlaceable</samp><br /><samp>isTileLocationTotallyClearAndPlaceableIgnoreFloors</samp>
 
| <samp>isTileOccupied</samp><br /><samp>isTileOccupiedForPlacement</samp><br /><samp>isTileOccupiedIgnoreFloors</samp><br /><samp>isTileLocationOpenIgnoreFrontLayers</samp><br /><samp>isTileLocationTotallyClearAndPlaceable</samp><br /><samp>isTileLocationTotallyClearAndPlaceableIgnoreFloors</samp>
Line 8,340: Line 8,422:  
Note that the second argument (<samp>name</samp>) should usually be omitted, since it'll be auto-populated from the value passed to the first argument.
 
Note that the second argument (<samp>name</samp>) should usually be omitted, since it'll be auto-populated from the value passed to the first argument.
 
|-
 
|-
|rowspan="4"| <samp>NPC</samp>
+
|rowspan="7"| <samp>NPC</samp>
 +
| <samp>canReceiveThisItemAsGift(…)</samp>
 +
| Removed. The closest equivalent is <code>item.canBeGivenAsGift()</code>, or you can check if the NPC will accept the player's held object (as a gift or otherwise) using <code>npc.tryReceiveActiveObject(Game1.player, probe: true)</code>.
 +
|-
 +
| <samp>Gender</samp><br /><samp>female</samp><br /><samp>male</samp><br /><samp>undefined</samp>
 +
| The <samp>Gender</samp> field now uses a <samp>Gender</samp> enum instead of numeric constants. For example, <code>npc.Gender == NPC.female</code> becomes <code>npc.Gender == Gender.Female</code> in 1.6.
 +
|-
 
| <samp>homeRegion</samp>
 
| <samp>homeRegion</samp>
 
| Removed; use <samp>npc.GetData()?.HomeRegion</samp> instead. Change <samp>0</samp> to <samp>"Other"</samp> or <samp>NPC.region_other</samp>, <samp>1</samp> to <samp>"Desert"</samp> or <samp>NPC.region_desert</samp>, and <samp>2</samp> to <samp>"Town"</samp> or <samp>NPC.region_town</samp>.
 
| Removed; use <samp>npc.GetData()?.HomeRegion</samp> instead. Change <samp>0</samp> to <samp>"Other"</samp> or <samp>NPC.region_other</samp>, <samp>1</samp> to <samp>"Desert"</samp> or <samp>NPC.region_desert</samp>, and <samp>2</samp> to <samp>"Town"</samp> or <samp>NPC.region_town</samp>.
Line 8,346: Line 8,434:  
| <samp>isBirthday</samp>
 
| <samp>isBirthday</samp>
 
| Remove the arguments, like <code>npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth)</code> → <code>npc.isBirthday()</code>.
 
| Remove the arguments, like <code>npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth)</code> → <code>npc.isBirthday()</code>.
 +
|-
 +
| <samp>isVillager()</samp>
 +
| Deprecated; use the <samp>character.IsVillager</samp> property instead.
 
|-
 
|-
 
| <samp>populateRoutesFromLocationToLocationList</samp>
 
| <samp>populateRoutesFromLocationToLocationList</samp>
Line 8,353: Line 8,444:  
| No longer assignable, use one of the <samp>TryLoadSchedule</samp> overloads instead.
 
| No longer assignable, use one of the <samp>TryLoadSchedule</samp> overloads instead.
 
|-
 
|-
| <samp>Object</samp>
+
|rowspan="3"| <samp>Object</samp>
 +
| <samp>GetContextTagList()</samp>
 +
| Replaced by <samp>GetContextTags()</samp>, which returns a hash set instead of a list.
 +
|-
 +
| <samp>HasBeenPickedUpByPlayer</samp>
 +
| Removed; use <samp>HasBeenInInventory</samp> instead.
 +
|-
 
| <samp>isPotentialBasicShippedCategory</samp>
 
| <samp>isPotentialBasicShippedCategory</samp>
 
| The second argument should now be an integer (like <samp>-75</samp> or <samp>Object.VegetableCategory</samp>) instead of a string (like <samp>"-75"</samp>).
 
| The second argument should now be an integer (like <samp>-75</samp> or <samp>Object.VegetableCategory</samp>) instead of a string (like <samp>"-75"</samp>).
Line 8,420: Line 8,517:  
| <samp>stat_dictionary</samp>
 
| <samp>stat_dictionary</samp>
 
| Renamed to <samp>Values</samp>. See [[#Stat changes for C# mods|stat changes for C# mods]].
 
| Renamed to <samp>Values</samp>. See [[#Stat changes for C# mods|stat changes for C# mods]].
 +
|-
 +
| <samp>Woods</samp>
 +
| <samp>stumps</samp>
 +
| Moved into <samp>resourceClumps</samp>.
 
|}
 
|}
   Line 8,475: Line 8,576:  
When updating to Stardew Valley 1.6, replace the synthetic ID (<samp>item_cloth|item_pufferchick</samp>) with a real one:
 
When updating to Stardew Valley 1.6, replace the synthetic ID (<samp>item_cloth|item_pufferchick</samp>) with a real one:
 
* To edit an existing entry, unpack the asset and get its new <samp>Id</samp> value.
 
* To edit an existing entry, unpack the asset and get its new <samp>Id</samp> value.
* To add a custom entry, use a [[Modding:Modder Guide/Game Fundamentals#Unique string IDs|unique string ID]].
+
* To add a custom entry, use a [[Modding:Common data field types#Unique string ID|unique string ID]].
    
For example:
 
For example:
Line 8,498: Line 8,599:     
===Event ID changes===
 
===Event ID changes===
 +
{{/doc status|[[Modding:Event data]]|done=false}}
 +
 
: ''See also: [[#String event IDs|string event IDs in what's new]].''
 
: ''See also: [[#String event IDs|string event IDs in what's new]].''
   Line 8,514: Line 8,617:     
===Monster eradication goal flag changes===
 
===Monster eradication goal flag changes===
 +
{{/doc status|a new doc page|done=false}}
 +
 
: ''See also: [[#Custom monster eradication goals|Custom monster eradication goals]].''
 
: ''See also: [[#Custom monster eradication goals|Custom monster eradication goals]].''
   Line 8,561: Line 8,666:     
===XNB impact===
 
===XNB impact===
Here's a summary of the XNB files which changed in Stardew Valley 1.6. This doesn't include new files (since they won't impact existing mods), or changes in non-English files.
+
====Overview====
 +
This section provides a summary of the XNB files which changed in Stardew Valley 1.6. This doesn't include new files (since they won't impact existing mods), or text changes in non-English files.
 +
 
 +
[[Modding:Using XNB mods|XNB mods]] are disproportionately affected, since...
 +
# they replace the entire file;
 +
# they're loaded through the MonoGame content pipeline which is less tolerant of format changes;
 +
# they don't benefit from the compatibility rewrites [[Modding:Content Patcher|Content Patcher]] provides for its content packs.
   −
Shorthand:
+
Content Patcher packs are typically unaffected (and Content Patcher will try to rewrite content packs automatically). However if a content pack replaces an entire asset instead of editing, it's more likely to be affected like an XNB mod.
* 'broken' means removing new content or potentially important changes, or potentially causing significant display bugs. This is a broad category — the game may work fine without it or crash, depending how it uses that specific content.
  −
* 'mostly unaffected' means mods will only be affected if they edit specific entries or fields.
  −
* Blank means no expected impact for the vast majority of mods.
     −
XNB mods are disproportionately affected since (a) they replace the entire file and (b) they're loaded through the MonoGame content pipeline which is less tolerant of format changes.
+
====Changed assets====
 +
Compatibility is broadly grouped into four categories:
 +
* "'''✘ broken'''": mods will remove new content or significant changes, or the mod's intended changes will no longer work. Effects may range from display bugs to crashes, depending how the game uses that specific content.
 +
* "✘ will remove changes": mods will remove minor changes in 1.6 (e.g. typo fixes).
 +
* "✓ mostly unaffected": mods will only be affected if they replace the entire asset, or edit specific entries or fields.
 +
* Blank: no expected impact for the vast majority of mods.
    
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! content file
+
!rowspan="2"| content asset
! changes
+
!rowspan="2"| changes in 1.6
! XNB
+
!colspan="2"| compatibility for pre-1.6 mods
! Content Patcher
+
|-
 +
! XNB mods
 +
! Content Patcher packs
 
|-
 
|-
 
| <samp>Buildings/houses</samp>
 
| <samp>Buildings/houses</samp>
| fixed missing pixels
+
| &#32;
 +
* fixed missing pixels
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/Abigail</samp><br /><samp>Characters/Dialogue/Alex</samp><br /><samp>Characters/Dialogue/Caroline</samp><br /><samp>Characters/Dialogue/Demetrius</samp>
+
| <samp>Characters/Dialogue/Abigail</samp><br /><samp>Characters/Dialogue/Alex</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/Emily</samp>
+
| <samp>Characters/Dialogue/Caroline</samp><br /><samp>Characters/Dialogue/Demetrius</samp>
| fixed typos, updated <samp>%revealtaste</samp> format (backwards-compatible)
+
| &#32;
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/Gus</samp><br /><samp>Characters/Dialogue/Haley</samp><br /><samp>Characters/Dialogue/Jodi</samp>
+
| <samp>Characters/Dialogue/Elliott</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/Lewis</samp>
+
| <samp>Characters/Dialogue/Emily</samp>
| updated <samp>%revealtaste</samp> format (backwards-compatible)
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 +
* updated <samp>%revealtaste</samp> format (backwards-compatible)
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/Linus</samp><br /><samp>Characters/Dialogue/MarriageDialogueAbigail</samp><br /><samp>Characters/Dialogue/MarriageDialogueElliott</samp>
+
| <samp>Characters/Dialogue/George</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|Winter Star gift exchange dialogue]]
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/MarriageDialogueEmily</samp>
+
| <samp>Characters/Dialogue/Gus</samp>
| changed <samp>spring_Maru</samp> key to <samp>spring_Emily</samp>, fixed typos
+
| &#32;
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/Dialogue/MarriageDialogueMaru</samp><br /><samp>Characters/Dialogue/MarriageDialoguePenny</samp><br /><samp>Characters/Dialogue/MarriageDialogueSam</samp><br /><samp>Characters/Dialogue/Maru</samp><br /><samp>Characters/Dialogue/Pierre</samp><br /><samp>Characters/Dialogue/Robin</samp><br /><samp>Characters/Dialogue/Sam</samp><br /><samp>Characters/Dialogue/Sebastian</samp>
+
| <samp>Characters/Dialogue/Haley</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/schedules/Elliott</samp>
+
| <samp>Characters/Dialogue/Harvey</samp>
| fixed order of <samp>Fri_6</samp> and <samp>Fri</samp> entries
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
|
+
| '''broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/schedules/Lewis</samp>
+
| <samp>Characters/Dialogue/Jas</samp><br /><samp>Characters/Dialogue/Jodi</samp>
| fixed <samp>winter_Sun</samp> schedule
+
| &#32;
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
|
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/schedules/Maru</samp>
+
| <samp>Characters/Dialogue/Krobus</samp>
| fixed <samp>summer_Mon</samp> and <samp>summer_Sun</samp> schedules
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|roommate stardrop dialogue]]
|
+
| '''broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/schedules/Penny</samp>
+
| <samp>Characters/Dialogue/Leah</samp>
| fixed <samp>summer_Sun</samp> schedule
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
|
+
| '''broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Characters/shirts</samp><br /><samp>Characters/WeddingOutfits</samp>
+
| <samp>Characters/Dialogue/Lewis</samp>
| asset removed (they were unused)
+
| &#32;
 +
* updated <samp>%revealtaste</samp> format (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Data/AquariumFish</samp>
+
| <samp>Characters/Dialogue/Linus</samp>
| [[#Custom items|changed key type]], added hat position for [[Sea Urchin]]
+
| &#32;
 +
* added [[#Dialogue changes|dumpster dive dialogue]]
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/BigCraftablesInformation</samp>
+
| <samp>Characters/Dialogue/Marnie</samp>
| asset removed (replaced by [[#Custom big craftables|<samp>Data/BigCraftables</samp>]]: migrated to data model format, added new features, [[#Custom items|changed key type]])
+
| &#32;
 +
* added [[#Dialogue changes|Stardew Valley Fair dialogue]]
 
| '''✘ broken'''
 
| '''✘ broken'''
| '''likely broken'''
+
| ✓ mostly unaffected
 +
|-
 +
| <samp>Characters/Dialogue/MarriageDialogue</samp><br /><samp>Characters/Dialogue/MarriageDialogueAbigail</samp><br /><samp>Characters/Dialogue/MarriageDialogueElliott</samp>
 +
| &#32;
 +
* fixed typos
 +
| will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Blueprints</samp>
+
| <samp>Characters/Dialogue/MarriageDialogueEmily</samp>
| asset removed (replaced by [[#Custom buildings|<samp>Data/Buildings</samp>]])
+
| &#32;
| '''✘ broken'''
+
* changed <samp>spring_Maru</samp> key to <samp>spring_Emily</samp>
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Boots</samp>
+
| <samp>Characters/Dialogue/MarriageDialogueKrobus</samp><br /><samp>Characters/Dialogue/MarriageDialogueLeah</samp><br /><samp>Characters/Dialogue/MarriageDialogueMaru</samp><br /><samp>Characters/Dialogue/MarriageDialoguePenny</samp><br /><samp>Characters/Dialogue/MarriageDialogueSam</samp>
| [[#Custom items|changed key type]], added display name
+
| &#32;
| '''broken'''
+
* fixed typos
| '''✘ likely broken'''
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Bundles</samp>
+
| <samp>Characters/Dialogue/Maru</samp>
| can no longer omit empty fields before display name, added display name field in English, removed meat items in animal bundle
+
| &#32;
 +
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
| '''✘ likely broken'''
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/ClothingInformation</samp>
+
| <samp>Characters/Dialogue/Penny</samp>
| asset removed (replaced by [[#Custom pants|<samp>Data/Pants</samp>]] and [[#Custom shirts|<samp>Data/Shirts</samp>]])
+
| &#32;
 +
* added [[#Dialogue changes|flower dance dialogue]]
 
| '''✘ broken'''
 
| '''✘ broken'''
| '''✘ likely broken'''
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/ConcessionTastes</samp>
+
| <samp>Characters/Dialogue/Pierre</samp>
| [[#Custom movie concessions|added new required fields (<samp>Texture</samp> and <samp>SpriteIndex</samp>)]], added automatic <samp>ID</samp> field
+
| &#32;
 +
* added [[#Dialogue changes|Stardew Valley Fair dialogue]]
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(✘ broken if they add new concessions)</small>
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/CookingRecipes</samp>
+
| <samp>Characters/Dialogue/Robin</samp>
| no longer has per-language versions, removed display names (now default to item name)
+
| &#32;
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/CraftingRecipes</samp>
+
| <samp>Characters/Dialogue/Sam</samp>
| no longer has per-language versions, added <samp>default</samp> unlock condition, removed display names (now default to item name), fixed typo in Cookout Kit entry
+
| &#32;
 +
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Crops</samp>
+
| <samp>Characters/Dialogue/Sandy</samp>
| [[#Custom crops|completely overhauled]]
+
| &#32;
| '''broken'''
+
* fixed typos
| '''✘ broken'''
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/Farm</samp>
+
| <samp>Characters/Dialogue/Sebastian</samp>
| updated pet event to support custom pet types
+
| &#32;
 +
* added [[#Dialogue changes|flower dance dialogue]]
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/FishShop</samp>
+
| <samp>Characters/Dialogue/Willy</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|Stardew Valley Fair dialogue]]
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/Forest</samp>
+
| <samp>Characters/Dialogue/Shane</samp>
| fixed typos, updated Jas <samp>faceDirection</samp> command for sewer event
+
| &#32;
| ✘ will remove changes
+
* added [[#Dialogue changes|flower dance dialogue]]
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/IslandHut</samp>
+
| <samp>Characters/Farmer/hats</samp>
| updated how Leo's name is translated
+
| &#32;
 +
* removed stray pixel on chicken mask
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/IslandNorth</samp>
+
| <samp>Characters/schedules/Elliott</samp>
| updated quote format
+
| &#32;
 +
* fixed order of <samp>Fri_6</samp> and <samp>Fri</samp> entries
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(✘ likely broken if they edit the <samp>6497421</samp> event)</small>
  −
|-
  −
| <samp>Data/Events/IslandSouth</samp>
  −
| changed event music field from blank to <samp>none</samp> (backwards-compatible)
  −
|
   
|
 
|
 
|-
 
|-
| <samp>Data/Events/LeahHouse</samp>
+
| <samp>Characters/schedules/Lewis</samp>
| fixed <samp>move</samp> command format in Leah's 2-heart event
+
| &#32;
 +
* fixed <samp>winter_Sun</samp> schedule
 
| '''✘ broken'''
 
| '''✘ broken'''
|
  −
|-
  −
| <samp>Data/Events/Mountain</samp>
  −
| fixed broken dialogue in Maru's 14-heart event, fixed typos
  −
| ✘ will remove changes
   
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/Saloon</samp><br /><samp>Data/Events/SebastianRoom</samp>
+
| <samp>Characters/schedules/Maru</samp>
| fixed typos
+
| &#32;
| will remove changes
+
* fixed <samp>summer_Mon</samp> and <samp>summer_Sun</samp> schedules
 +
| '''broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Events/Town</samp>
+
| <samp>Characters/schedules/Penny</samp>
| fixed <samp>warp</samp> command format in community center completed event, fixed typos
+
| &#32;
 +
* fixed <samp>summer_Sun</samp> schedule
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/FarmAnimals</samp>
+
| <samp>Characters/Schedules/Shane</samp>
| [[#Custom farm animals|completely overhauled]]
+
| &#32;
| '''broken'''
+
* fixed dialogue key
|  
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Festivals/fall27</samp>
+
| <samp>Data/animationDescriptions</samp>
| removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
+
| &#32;
|
+
* fixed frame in Lewis' Saloon drinking animation
|
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Festivals/spring13</samp>
+
| <samp>Data/AquariumFish</samp>
| migrated to new <samp>warpFarmers</samp> command, removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]]), fixed typos
+
| &#32;
 +
* [[#Custom items|changed key type]]
 +
* added hat position for [[Sea Urchin]]
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(✘ broken if they edit event script fields)</small>
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Festivals/spring24</samp><br /><samp>Data/Festivals/summer11</samp><br /><samp>Data/Festivals/summer28</samp><br /><samp>Data/Festivals/winter8</samp>
+
| <samp>Data/BigCraftablesInformation</samp>
| migrated to new <samp>warpFarmers</samp> command, removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
+
| &#32;
 +
* asset replaced by [[#Custom big craftables|<samp>Data/BigCraftables</samp>]]:
 +
** migrated to data model format
 +
** added new features
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(✘ broken if they edit event script fields)</small>
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Data/Festivals/winter25</samp>
+
| <samp>Data/Blueprints</samp>
| removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
+
| &#32;
|
+
* asset replaced by [[#Custom buildings|<samp>Data/Buildings</samp>]]:
|
+
** migrated to data model format
|-
+
** added new features
| <samp>Data/Fish</samp>
  −
| no longer has per-language versions, [[#Custom items|changed key type]], field 13 now refers to whether fish can be tutorial catch
   
| '''✘ broken'''
 
| '''✘ broken'''
| ✘ likely broken
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Data/FishPondData</samp>
+
| <samp>Data/Boots</samp>
| added required <samp>Id</samp> field, added optional <samp>Precedence</samp> field, [[#Custom items|changed <samp>ItemId</samp> field type]], moved fallback entries to bottom
+
| &#32;
 +
* [[#Custom items|changed key type]]
 +
* added display name
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✘ likely broken
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Data/fruitTrees</samp>
+
| <samp>Data/Bundles</samp>
| [[#Custom fruit trees|completely overhauled]]
+
| &#32;
| '''✘ broken'''
+
* can no longer omit empty fields before display name
 +
* added display name field in English
 +
* removed meat items in animal bundle
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| '''✘ likely broken'''
 
|-
 
|-
| <samp>Data/Furniture</samp>
+
| <samp>Data/ClothingInformation</samp>
| [[#Custom items|changed key type]], can no longer omit empty fields before display name, added display name field in English
+
| &#32;
 +
* asset replaced by [[#Custom pants|<samp>Data/Pants</samp>]] and [[#Custom shirts|<samp>Data/Shirts</samp>]]:
 +
** migrated to data model format
 +
** added new features
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| '''✘ likely broken'''
 
| '''✘ likely broken'''
 
|-
 
|-
| <samp>Data/hats</samp>
+
| <samp>Data/Concessions</samp>
| [[#Custom items|changed key type]], can no longer omit empty fields before display name, added display name field in English
+
| &#32;
 +
* [[#Custom movie concessions|added new required fields (<samp>Texture</samp> and <samp>SpriteIndex</samp>)]]
 +
* replaced translations with [[Modding:Tokenizable strings|tokenizable strings]]
 +
* changed IDs to strings
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| '''✘ likely broken'''
 
| '''✘ likely broken'''
 
|-
 
|-
| <samp>Data/Locations</samp>
+
| <samp>Data/ConcessionTastes</samp>
| [[#Custom locations|completely overhauled]]
+
| &#32;
 +
* added automatic <samp>ID</samp> field
 
| '''✘ broken'''
 
| '''✘ broken'''
|  
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/mail</samp>
+
| <samp>Data/CookingRecipes</samp>
| migrated to <samp>%item id</samp> (backwards-compatible), removed unused tax entries, fixed typos
+
| &#32;
 +
* replaced translations with [[Modding:Tokenizable strings|tokenizable strings]]
 +
* display names can now be omitted to use item name
 
| ✘ will remove changes
 
| ✘ will remove changes
| ✓ mostly unaffected
+
| ✓ may remove unaffected
 
|-
 
|-
| <samp>Data/Monsters</samp>
+
| <samp>Data/CraftingRecipes</samp>
| renamed ''Dust Spirit'' to ''Dust Sprite''
+
| &#32;
| ✘ will remove changes
+
* replaced translations with [[Modding:Tokenizable strings|tokenizable strings]]
 +
* display names can now be omitted to use item name
 +
* added <samp>default</samp> unlock condition
 +
* fixed typo in Cookout Kit entry
 +
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Movies</samp>
+
| <samp>Data/Crops</samp>
| added optional <samp>CustomFields</samp> and <samp>Textures</samp> fields
+
| &#32;
 +
* [[#Custom crops|completely overhauled]]
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 +
|-
 +
| <samp>Data/Events/AnimalShop</samp>
 +
| &#32;
 +
* updated command syntax (backwards-compatible)
 +
|
 
|
 
|
 
|-
 
|-
| <samp>Data/MoviesReactions</samp>
+
| <samp>Data/Events/Farm</samp>
| added automatic <samp>ID</samp> field, fixed typo
+
| &#32;
 +
* replaced send-mail events with [[Modding:Trigger actions|trigger actions]]
 +
* updated pet event to support custom pet types
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(✘ may cause duplicate mail if they edit<br />send-mail events)</small>
 +
|-
 +
| <samp>Data/Events/FishShop</samp>
 +
| &#32;
 +
* fixed typos
 +
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/NPCDispositions</samp>
+
| <samp>Data/Events/Forest</samp>
| asset removed (replaced by [[#Custom NPCs|<samp>Data/Characters</samp>]])
+
| &#32;
| '''broken'''
+
* fixed typos
| '''✘ broken'''
+
* updated Jas <samp>faceDirection</samp> command for sewer event
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/ObjectContextTags</samp>
+
| <samp>Data/Events/IslandHut</samp>
| asset removed (replaced by <samp>ContextTags</samp> field in [[#Custom big craftables|<samp>Data/BigCraftables</samp>]] and [[#Custom objects|<samp>Data/Objects</samp>]])
+
| &#32;
| '''broken'''
+
* updated how Leo's name is translated
| '''✘ broken'''
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/ObjectInformation</samp>
+
| <samp>Data/Events/IslandNorth</samp>
| asset removed (replaced by [[#Custom objects|<samp>Data/Objects</samp>]]: migrated to data model format, added new features, added new entries, adjusted [[#Other item changes|litter items]], [[#Custom items|changed key type]], fixed typos)
+
| &#32;
| '''✘ broken'''
+
* updated quote format
 +
* fixed blank music field (backwards-compatible)
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(✘ likely broken if they edit the <samp>6497421</samp> event)</small>
 
|-
 
|-
| <samp>Data/PainData</samp>
+
| <samp>Data/Events/IslandSouth</samp>
| fixed trailing slash in <samp>Deluxe Barn</samp> entry
+
| &#32;
|  
+
* fixed blank music field (backwards-compatible)
|  
+
* fixed typos
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/Quests</samp>
+
| <samp>Data/Events/JoshHouse</samp>
| changed item fields to use item IDs (backwards-compatible), changed key type to string, fixed typo
+
| &#32;
| '''broken'''
+
* fixed typos
 +
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/RandomBundles</samp>
+
| <samp>Data/Events/LeahHouse</samp>
| add optional <samp>ID</samp> field
+
| &#32;
 +
* fixed <samp>move</samp> command format in Leah's 2-heart event
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/SecretNotes</samp>
+
| <samp>Data/Events/Mountain</samp>
| updated <samp>%revealtaste</samp> format (backwards-compatible)
+
| &#32;
 +
* fixed skipped dialogue in Maru's 14-heart event
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/SpecialOrders</samp>
+
| <samp>Data/Events/Saloon</samp><br /><samp>Data/Events/ScienceHouse</samp><br /><samp>Data/Events/SebastianRoom</samp>
| changed type of <samp>Repeatable</samp> and <samp>Duration</samp> fields, added optional <samp>CustomFields</samp> and <samp>Conditions</samp> fields
+
| &#32;
| '''broken'''
+
* fixed typos
|  
+
| will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/TailoringRecipes</samp>
+
| <samp>Data/Events/Town</samp>
| changed to [[#Custom items|string item IDs]] (backwards-compatible), added optional <samp>ID</samp> and <samp>CraftedItemIdFeminine</samp> fields,<br />adjusted recipes for gender-variant shirts, renamed <samp>*ID</samp> to <samp>*Id</samp>
+
| &#32;
 +
* fixed <samp>warp</samp> command format in community center completed event
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected<br /><small>(<samp>MoveEntries</samp> may break, but fallback entries are now<br />checked last automatically)</small>
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/TV/CookingChannel</samp><br /><samp>Data/TV/TipChannel</samp>
+
| <samp>Data/Events/WizardHouse</samp>
| fixed typos
+
| &#32;
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Data/weapons</samp>
+
| <samp>Data/ExtraDialogue</samp>
| [[#Custom melee weapons|completely overhauled]]
+
| &#32;
 +
* split <samp>SummitEvent_Dialogue1_Spouse</samp> entry
 +
* fixed event command formats in some summit dialogue
 +
* moved [[#Dialogue changes|dumpster dive dialogue into NPC files]]
 +
* removed unused entries
 +
* fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
| '''✘ likely broken'''
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Effects/BrightWhite</samp>
+
| <samp>Data/FarmAnimals</samp>
| asset removed
+
| &#32;
|
+
* [[#Custom farm animals|completely overhauled]]
|
  −
|-
  −
| <samp>LooseSprites/Cursors</samp>
  −
| new sprites in empty area, moved mailbox to <samp>Buildings/Mailbox</samp>
   
| '''✘ broken'''
 
| '''✘ broken'''
| ✓ mostly unaffected
  −
|-
  −
| <samp>LooseSprites/Cursors2</samp>
  −
| new sprite in empty area
   
| '''✘ broken'''
 
| '''✘ broken'''
|
   
|-
 
|-
| <samp>LooseSprites/map</samp>
+
| <samp>Data/Festivals/fall16</samp>
| redrawn to better match in-game locations and be more detailed
+
| &#32;
 +
* updated command syntax (backwards-compatible)
 +
* fixed typos
 
| ✘ will remove changes
 
| ✘ will remove changes
| ✘ will likely remove changes
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/AnimalShop</samp>
+
| <samp>Data/Festivals/fall27</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
|
+
| ✓ mostly unaffected
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/ArchaeologyHouse</samp>
+
| <samp>Data/Festivals/spring13</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* migrated to new <samp>warpFarmers</samp> command
|
+
* removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
 +
* updated <samp>faceDirection</samp> syntax
 +
* fixed typos
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(✘ broken if they edit <samp>mainEvent</samp> or<br /><samp>afterEggHunt</samp> fields)</small>
 
|-
 
|-
| <samp>Maps/Barn</samp><br /><samp>Maps/Barn2</samp>
+
| <samp>Data/Festivals/spring24</samp><br /><samp>Data/Festivals/summer11</samp><br /><samp>Data/Festivals/summer28</samp>
| removed unused map properties
+
| &#32;
|
+
* migrated to new <samp>warpFarmers</samp> command
|
+
* removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(✘ broken if they edit <samp>mainEvent</samp> field)</small>
 
|-
 
|-
| <samp>Maps/Barn3</samp>
+
| <br /><samp>Data/Festivals/winter8</samp>
| added <samp>AutoFeed</samp> map property, removed unused map properties
+
| &#32;
 +
* migrated to new <samp>warpFarmers</samp> command
 +
* removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
 +
* removed broken <samp>loadActors MainEvent</samp> command
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected<br /><small>(✘ broken if they edit <samp>mainEvent</samp> or<br /><samp>afterIceFishing</samp> field)</small>
 
|-
 
|-
| <samp>Maps/BathHouse_Entry</samp><br /><samp>Maps/BathHouse_MensLocker</samp>
+
| <samp>Data/Festivals/winter25</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* removed <samp>shop</samp> field (moved into [[#Custom shops|<samp>Data/Shops</samp>]])
|
+
| ✓ mostly unaffected
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/BathHouse_Pool</samp>
+
| <samp>Data/Fish</samp>
| removed unused map & tile properties, removed unused pathfinding tiles
+
| &#32;
|
+
* no longer has per-language versions
|
+
* [[#Custom items|changed key type]]
 +
* field 13 now refers to whether fish can be tutorial catch
 +
| '''✘ broken'''
 +
| ✘ likely broken
 
|-
 
|-
| <samp>Maps/BathHouse_WomensLocker</samp>
+
| <samp>Data/FishPondData</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* added required <samp>Id</samp> & optional <samp>Precedence</samp> fields
|
+
* standardized <samp>ID</samp>→<samp>Id</samp> naming
 +
* changed to qualified item IDs
 +
* moved fallback entries to bottom
 +
| '''✘ broken'''
 +
| ✘ likely broken
 
|-
 
|-
| <samp>Maps/Beach</samp>
+
| <samp>Data/fruitTrees</samp>
| removed unused map properties, removed unused pathfinding tiles
+
| &#32;
|
+
* [[#Custom fruit trees|completely overhauled]]
|
+
| '''✘ broken'''
 +
| '''✘ broken'''
 
|-
 
|-
| <samp>Maps/Beach-Jellies</samp><br /><samp>Maps/Beach-Luau</samp><br /><samp>Maps/Beach-NightMarket</samp>
+
| <samp>Data/Furniture</samp>
| updated for festival shops now in <samp>Data/Shops</samp>, removed unused map/tile properties, removed unused pathfinding tiles
+
| &#32;
 +
* [[#Custom items|changed key type]]
 +
* replaced translations with [[Modding:Tokenizable strings|tokenizable strings]]
 +
* [[#Custom items|changed key type]]
 +
* can no longer omit empty fields before display name
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Maps/Blacksmith</samp>
+
| <samp>Data/hats</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* [[#Custom items|changed key type]]
|
+
* can no longer omit empty fields before display name
 +
* added display name field in English
 +
| '''✘ broken'''
 +
| '''✘ likely broken'''
 
|-
 
|-
| <samp>Maps/BusStop</samp>
+
| <samp>Data/Locations</samp>
| removed unused map/tile properties, removed unused pathfinding tiles
+
| &#32;
|
+
* [[#Custom locations|completely overhauled]]
|
+
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Maps/Cabin</samp><br /><samp>Maps/Cabin1</samp><br /><samp>Maps/Cabin1_marriage</samp><br /><samp>Maps/Cabin2</samp><br /><samp>Maps/Cabin2_marriage</samp>
+
| <samp>Data/mail</samp>
| removed assets (they were unused)
+
| &#32;
|
+
* migrated to <samp>%item id</samp> (backwards-compatible)
|
+
* removed unused entries
 +
* fixed typos
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Caldera</samp>
+
| <samp>Data/Monsters</samp>
| removed unused map property
+
| &#32;
|
+
* changed ''Dust Spirit'' display name to ''Dust Sprite''
|
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Club</samp>
+
| <samp>Data/Movies</samp>
| added <samp>LocationContext</samp> map property
+
| &#32;
 +
* [[#Custom movies|significantly overhauled]]
 +
| '''✘ broken'''
 
| '''✘ broken'''
 
| '''✘ broken'''
|
   
|-
 
|-
| <samp>Maps/Coop</samp><br /><samp>Maps/Coop2</samp>
+
| <samp>Data/MoviesReactions</samp>
| removed unused map properties
+
| &#32;
|
+
* replaced translations with [[Modding:Tokenizable strings|tokenizable strings]]
|
+
* standardized <samp>ID</samp><samp>Id</samp> naming
 +
* fixed typo
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Data/NPCDispositions</samp>
 +
| &#32;
 +
* asset replaced by [[#Custom NPCs|<samp>Data/Characters</samp>]]
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Maps/Coop3</samp>
+
| <samp>Data/NPCGiftTastes</samp>
| removed unused map properties, added <samp>AutoFeed</samp> map property
+
| &#32;
 +
* removed invalid item IDs
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Data/ObjectContextTags</samp>
 +
| &#32;
 +
* asset removed (replaced by <samp>ContextTags</samp> field in [[#Custom big craftables|<samp>Data/BigCraftables</samp>]] and [[#Custom objects|<samp>Data/Objects</samp>]])
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration,<br />except context tags defined<br />before their objects and context<br />tags for bigcraftables.)
 +
</small>
 
|-
 
|-
| <samp>Maps/Desert</samp>
+
| <samp>Data/ObjectInformation</samp>
| added <samp>LocationContext</samp> map property, removed unused map/tile properties, removed unused pathfinding tiles
+
| &#32;
 +
* asset replaced by [[#Custom objects|<samp>Data/Objects</samp>]]:
 +
** migrated to data model format
 +
** added new features
 +
** added new entries
 +
** adjusted [[#Other item changes|litter items]]
 +
** fixed typos
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Maps/ElliottHouse</samp>
+
| <samp>Data/PaintData</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* fixed trailing slash in <samp>Deluxe Barn</samp> entry
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Farm</samp><br /><samp>Maps/Farm_Combat</samp><br /><samp>Maps/Farm_Fishing</samp><br /><samp>Maps/Farm_Foraging</samp><br /><samp>Maps/Farm_FourCorners</samp><br /><samp>Maps/Farm_Island</samp><br /><samp>Maps/Farm_Mining</samp>
+
| <samp>Data/Quests</samp>
 
| &#32;
 
| &#32;
* added new tilesheet;
+
* changed key type to string
* added <samp>PetBowlLocation</samp> map property (for <samp>Maps/Four_Corners</samp> and <samp>Farm/Island</samp> only);
+
* migrated to use item IDs (backwards-compatible)
* significant tile & tile property changes;
+
* fixed typo
* removed farmhouse + pet bowl areas (now moveable);
  −
* removed unused map/tile properties;
   
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Farm_Greenhouse_Dirt</samp><br /><samp>Maps/Farm_Greenhouse_Dirt_FourCorners</samp>
+
| <samp>Data/RandomBundles</samp>
| removed unused map properties
+
| &#32;
|
+
* add optional <samp>Id</samp> field
|
+
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/FarmHouse</samp>
+
| <samp>Data/SecretNotes</samp>
| removed unused map properties
+
| &#32;
|
+
* updated <samp>%revealtaste</samp> format (backwards-compatible)
|
  −
|-
  −
| <samp>Maps/FarmHouse_Bedroom_Normal</samp><br /><samp>Maps/FarmHouse_Bedroom_Open</samp><br /><samp>Maps/FarmHouse_Cellar</samp><br /><samp>Maps/FarmHouse_ChildBed_0</samp><br /><samp>Maps/FarmHouse_ChildBed_1</samp><br /><samp>Maps/FarmHouse_CornerRoom_Add</samp><br /><samp>Maps/FarmHouse_CornerRoom_Remove</samp><br /><samp>Maps/FarmHouse_SouthernRoom_Add</samp><br /><samp>Maps/FarmHouse_SouthernRoom_Remove</samp><br /><samp>Maps/FarmHouse1</samp><br /><samp>Maps/FarmHouse1_marriage</samp><br /><samp>Maps/FarmHouse2</samp><br /><samp>Maps/FarmHouse2_marriage</samp>
  −
| removed unused map properties
  −
|
  −
|
  −
|-
  −
| <samp>Maps/FishShop</samp>
  −
| fixed broken <samp>DayTiles</samp> and <samp>NightTiles</samp> values, removed unused pathfinding tiles
   
| ✘ will remove changes
 
| ✘ will remove changes
|
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Forest</samp>
+
| <samp>Data/SpecialOrders</samp>
| removed unused map/tile properties, removed unused pathfinding tiles
+
| &#32;
|
+
* changed type of <samp>Repeatable</samp> and <samp>Duration</samp> fields
|
+
* added optional <samp>CustomFields</samp> and <samp>Conditions</samp> fields
 +
| '''✘ broken'''
 +
|  
 
|-
 
|-
| <samp>Maps/Forest-FlowerFestival</samp>
+
| <samp>Data/SpousePatios</samp><br /><samp>Data/SpouseRooms</samp>
| updated for festival shops now in <samp>Data/Shops</samp>, removed unused map properties
+
| &#32;
 +
* removed asset (merged into [[#Custom NPCs|<samp>Data/Characters</samp>]])
 +
| '''✘ broken'''
 
| '''✘ broken'''
 
| '''✘ broken'''
|
   
|-
 
|-
| <samp>Maps/Forest-IceFestival</samp>
+
| <samp>Data/TailoringRecipes</samp>
| updated for festival shops now in <samp>Data/Shops</samp>, fixed warp positions, removed unused map/tile properties, removed unused pathfinding tiles
+
| &#32;
 +
* changed to [[#Custom items|string item IDs]] (backwards-compatible)
 +
* added optional <samp>Id</samp> and <samp>CraftedItemIdFeminine</samp> fields
 +
* removed <samp>CraftedItemColor</samp> field
 +
* adjusted recipes for gender-variant shirts
 +
* standardized <samp>ID</samp>→<samp>Id</samp> naming
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected<br /><small>(<samp>MoveEntries</samp> may break, but fallback entries<br />are now checked last automatically)</small>
 
|-
 
|-
| <samp>Maps/Forest-SewerClean</samp>
+
| <samp>Data/TV/CookingChannel</samp><br /><samp>Data/TV/TipChannel</samp>
| removed unused map/tile properties
+
| &#32;
|
+
* fixed typos
|
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/HaleyHouse</samp><br /><samp>Maps/HarveyRoom</samp>
+
| <samp>Data/weapons</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* [[#Custom melee weapons|completely overhauled]]
|
+
| '''✘ broken'''
 +
| ✓ mostly unaffected<br /><small>(covered by runtime migration)</small>
 
|-
 
|-
| <samp>Maps/Hospital</samp>
+
| <samp>LooseSprites/Cursors</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* new sprites in empty area
|
+
* moved mailbox to <samp>Buildings/Mailbox</samp>
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Island_Bridge_Broken</samp><br /><samp>Maps/Island_Bridge_Repaired</samp><br /><samp>Maps/Island_House_Cave</samp>
+
| <samp>LooseSprites/Cursors2</samp>
| removed unused map properties
+
| &#32;
|
+
* new sprite in empty area
|
+
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Island_N</samp>
+
| <samp>LooseSprites/map</samp>
| update walnut bush tile so it still works in 1.6, removed unused tile property
+
| &#32;
 +
* redrawn to better match in-game locations
 +
* added more detail
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✘ likely broken
 
|-
 
|-
| <samp>Maps/Island_N_Trader</samp><br /><samp>Maps/Island_Secret</samp><br /><samp>Maps/Island_W</samp>
+
| <samp>Maps/AbandonedJojaMart</samp><br /><samp>Maps/AdventureGuild</samp>
| removed unused tile property
+
| &#32;
|
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
|
+
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/IslandFarmHouse</samp>
+
| <samp>Maps/AnimalShop</samp>
| removed unused tile properties
+
| &#32;
 +
* removed unused pathfinding tiles
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/JojaMart</samp>
+
| <samp>Maps/ArchaeologyHouse</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused pathfinding tiles
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/JoshHouse</samp>
+
| <samp>Maps/Backwoods</samp><br /><samp>Maps/Backwoods_GraveSite</samp><br /><samp>Maps/Backwoods_Staircase</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/LeahHouse</samp>
+
| <samp>Maps/Barn</samp><br /><samp>Maps/Barn2</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused map properties
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/ManorHouse</samp>
+
| <samp>Maps/Barn3</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* added <samp>AutoFeed</samp> map property
 +
* removed unused map properties
 +
| '''✘ broken'''
 
|
 
|
 
|-
 
|-
| <samp>Maps/MarnieBarn</samp><br /><samp>Maps/Mine</samp>
+
| <samp>Maps/BathHouse_Entry</samp><br /><samp>Maps/BathHouse_MensLocker</samp>
| removed unused map properties
+
| &#32;
|
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
|
+
* removed unused pathfinding tiles
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Mountain</samp>
+
| <samp>Maps/BathHouse_Pool</samp>
| removed unused map properties, removed unused pathfinding tiles
+
| &#32;
 +
* removed unused pathfinding tiles
 +
* removed unused map & tile properties
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Mountain-BridgeFixed</samp><br /><samp>Maps/Mountain_Shortcuts</samp>
+
| <samp>Maps/BathHouse_WomensLocker</samp>
| removed unused map properties
+
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* removed unused pathfinding tiles
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Beach</samp>
 +
| &#32;
 +
* removed unused map properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/MovieTheaterScreen</samp>
+
| <samp>Maps/Beach-Jellies</samp><br /><samp>Maps/Beach-Luau</samp><br /><samp>Maps/Beach-NightMarket</samp>
| updated for tilesheet changes
+
| &#32;
| ✘ broken visuals (e.g. missing chairs)
+
* updated for festival shops now in <samp>Data/Shops</samp>
| ✓ mostly unaffected<br /><small>(✘ broken visuals if they edit the affected tiles)</small>
+
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/MovieTheaterScreen_TileSheet</samp>
+
| <samp>Maps/Blacksmith</samp>
| improved light cone, moved chair sprite to make room for new light cone
+
| &#32;
| ✘ broken visuals (e.g. missing chairs)
+
* removed unused pathfinding tiles
| ✓ mostly unaffected<br /><small>(✘ broken visuals if they edit the affected sprites)</small>
  −
|-
  −
| <samp>Maps/paths</samp>
  −
| added icon for [[#Custom wild trees|custom wild tree spawn]], removed unused pathfinding tiles
   
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/qiNutRoom_tilesheet_0</samp>
+
| <samp>Maps/BoatTunnel</samp>
| removed asset (unused)
+
| &#32;
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Railroad</samp>
+
| <samp>Maps/BugLand</samp>
| removed unused map property, removed unused pathfinding tiles
+
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/BusStop</samp>
 +
| &#32;
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* changed <samp>Action BusTicket</samp> to <samp>Action None</samp>
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Saloon</samp>
+
| <samp>Maps/Caldera</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused map property
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/SamHouse</samp>
+
| <samp>Maps/Cellar</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/SandyHouse</samp>
+
| <samp>Maps/Club</samp>
| added <samp>LocationContext</samp> map property
+
| &#32;
 +
* added <samp>LocationContext</samp> map property
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 
| '''✘ broken'''
 
| '''✘ broken'''
|
+
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/ScienceHouse</samp>
+
| <samp>Maps/Coop</samp><br /><samp>Maps/Coop2</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused map properties
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/SebastianRoom</samp>
+
| <samp>Maps/Coop3</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* added <samp>AutoFeed</samp> map property
 +
* removed unused map properties
 +
| '''✘ broken'''
 
|
 
|
 +
|-
 +
| <samp>Maps/Desert</samp>
 +
| &#32;
 +
* added <samp>LocationContext</samp> map property
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 
|
 
|
 
|-
 
|-
| <samp>Maps/SeedShop</samp>
+
| <samp>Maps/ElliottHouse</samp>
| removed unused tile properties, removed unused pathfinding tiles
+
| &#32;
 +
* removed unused pathfinding tiles
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Shed</samp>
+
| <samp>Maps/Farm</samp><br /><samp>Maps/Farm_Combat</samp><br /><samp>Maps/Farm_Fishing</samp><br /><samp>Maps/Farm_Foraging</samp><br /><samp>Maps/Farm_FourCorners</samp><br /><samp>Maps/Farm_Island</samp><br /><samp>Maps/Farm_Mining</samp>
| added <samp>FloorIDs</samp> and <samp>WallIDs</samp> map properties
+
| &#32;
 +
* added new tilesheet
 +
* added cabin positions for players 5–8
 +
* added <samp>PetBowlLocation</samp> map property (for <samp>Maps/Four_Corners</samp> and <samp>Farm/Island</samp> only)
 +
* added <samp>SpouseAreaLocation</samp> map property (for <samp>Maps/Farm_Island</samp> only)
 +
* significant tile & tile property changes
 +
* removed farmhouse + pet bowl areas (now moveable)
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
| '''✘ broken'''
 
| '''✘ broken'''
 +
| ✘ may remove changes
 +
|-
 +
| <samp>Maps/Farm_Greenhouse_Dirt</samp><br /><samp>Maps/Farm_Greenhouse_Dirt_FourCorners</samp>
 +
| &#32;
 +
* removed unused map properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
|-
  −
| <samp>Maps/SkullCave</samp>
  −
| added <samp>LocationContext</samp> map property
  −
| '''✘ broken'''
   
|
 
|
 
|-
 
|-
| <samp>Maps/SlimeHutch</samp>
+
| <samp>Maps/FarmHouse</samp><br /><samp>Maps/FarmHouse_Bedroom_Normal</samp><br /><samp>Maps/FarmHouse_Bedroom_Open</samp><br /><samp>Maps/FarmHouse_Cellar</samp><br /><samp>Maps/FarmHouse_ChildBed_0</samp><br /><samp>Maps/FarmHouse_ChildBed_1</samp><br /><samp>Maps/FarmHouse_CornerRoom_Add</samp><br /><samp>Maps/FarmHouse_CornerRoom_Remove</samp><br /><samp>Maps/FarmHouse_SouthernRoom_Add</samp><br /><samp>Maps/FarmHouse_SouthernRoom_Remove</samp><br /><samp>Maps/FarmHouse1</samp><br /><samp>Maps/FarmHouse1_marriage</samp><br /><samp>Maps/FarmHouse2</samp><br /><samp>Maps/FarmHouse2_marriage</samp>
| removed unused tile property
+
| &#32;
 +
* removed unused map properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/spousePatios</samp>
+
| <samp>Maps/FishingGame</samp>
| removed unused map properties
+
| &#32;
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/spring_outdoorsTileSheet</samp><br /><samp>Maps/summer_outdoorsTileSheet</samp><br /><samp>Maps/fall_outdoorsTileSheet</samp><br /><samp>Maps/winter_outdoorsTileSheet</samp>
+
| <samp>Maps/FishShop</samp>
| Pet bowl moved to <samp>Buildings/Pet Bowl</samp>.
+
| &#32;
| ✓ mostly unaffected
+
* fixed broken <samp>DayTiles</samp> and <samp>NightTiles</samp> values
 +
* removed unused pathfinding tiles
 +
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Submarine</samp>
+
| <samp>Maps/Forest</samp>
| removed unused tile property
+
| &#32;
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Tent</samp>
+
| <samp>Maps/Forest-FlowerFestival</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* updated for festival shops now in <samp>Data/Shops</samp>
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Forest-IceFestival</samp>
 +
| &#32;
 +
* updated for festival shops now in <samp>Data/Shops</samp>
 +
* fixed warp positions
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Forest-SewerClean</samp>
 +
| &#32;
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Town</samp>
+
| <samp>Maps/HaleyHouse</samp><br /><samp>Maps/HarveyRoom</samp>
| removed unused map properties, changed to [[#Custom garbage cans|new garbage can IDs]] (backwards-compatible), removed unused pathfinding tiles
+
| &#32;
 +
* removed unused pathfinding tiles
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Town-Christmas</samp>
+
| <samp>Maps/Hospital</samp>
| updated for festival shops now in <samp>Data/Shops</samp>, removed unused map properties, removed unused pathfinding tiles
+
| &#32;
| '''broken'''
+
* removed deprecated <samp>UniquePortrait</samp> & <samp>UniqueSprite</samp> map properties
 +
* removed unused pathfinding tiles
 +
| ✘ will remove changes<br /><small>(This may cause mod conflicts)</samp>
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Town-DogHouse</samp>
+
| <samp>Maps/Island_Bridge_Broken</samp><br /><samp>Maps/Island_Bridge_Repaired</samp><br /><samp>Maps/Island_House_Cave</samp>
| removed unused map properties
+
| &#32;
 +
* removed unused map properties
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Town-EggFestival</samp>
+
| <samp>Maps/Island_N</samp>
| fixed Elliott appearing twice during egg hunt, updated for festival shops now in <samp>Data/Shops</samp>, removed unused map properties
+
| &#32;
 +
* update walnut bush tile so it still works in 1.6
 +
* removed unused tile property
 
| '''✘ broken'''
 
| '''✘ broken'''
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Town-Fair</samp>
+
| <samp>Maps/IslandNorthCave1</samp><br /><samp>Maps/IslandSouthEastCave</samp><br /><samp>Maps/IslandSouthEastCave_pirates</samp><br /><samp>Maps/IslandWestCave1</samp>
| removed unused map properties
+
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Island_Bridge_Broken</samp><br /><samp>Maps/Island_Bridge_Repaired</samp>
 +
| &#32;
 +
* removed unused map property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Town-Halloween</samp>
+
| <samp>Maps/Island_E</samp><br /><samp>Maps/IslandFarmCave</samp>
| updated for festival shops now in <samp>Data/Shops</samp>, removed unused map properties, removed unused pathfinding tiles
+
| &#32;
| '''broken'''
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 
| ✓ mostly unaffected
 
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Town-Theater</samp><br /><samp>Maps/Town-TheaterCC</samp><br /><samp>Maps/Town-TrashGone</samp>
+
| <samp>Maps/Island_House_Cave</samp>
| removed unused map properties
+
| &#32;
 +
* removed unused map property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/Trailer</samp>
+
| <samp>Maps/Island_Hut</samp>
| removed unused tile property, removed unused pathfinding tiles
+
| &#32;
|
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
|
+
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Trailer_big</samp>
+
| <samp>Maps/Island_N</samp>
| removed unused pathfinding tiles
+
| &#32;
|
+
* added a <samp>NowSpawn False</samp> tile property to fix tree that hides a golden walnut
|
+
* removed unused tile property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Island_N_Trader</samp><br /><samp>Maps/Island_Secret</samp>
 +
| &#32;
 +
* removed unused tile property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Island_Shrine</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Island_W</samp>
 +
| &#32;
 +
* removed unused tile property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/IslandFarmHouse</samp>
 +
| &#32;
 +
* removed unused tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/JojaMart</samp><br /><samp>Maps/JoshHouse</samp><br /><samp>Maps/LeahHouse</samp><br /><samp>Maps/ManorHouse</samp>
 +
| &#32;
 +
* removed unused pathfinding tiles
 +
|
 +
|
 +
|-
 +
| <samp>Maps/MarnieBarn</samp>
 +
| &#32;
 +
* removed unused map properties
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Mine</samp>
 +
| &#32;
 +
* updated for [[#Custom minecarts|minecart changes]]
 +
* removed unused map properties
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 
|-
 
|-
| <samp>Maps/Tunnel</samp>
+
| <samp>Maps/Mountain</samp>
| removed unused map property
+
| &#32;
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/WizardHouse</samp>
+
| <samp>Maps/Mountain-BridgeFixed</samp><br /><samp>Maps/Mountain_Shortcuts</samp>
| removed unused pathfinding tiles
+
| &#32;
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 
|
 
|
 
|
 
|
 
|-
 
|-
| <samp>Maps/WizardHouseBasement</samp>
+
| <samp>Maps/MovieTheater</samp>
| removed unused map property
+
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/MovieTheaterScreen</samp>
 +
| &#32;
 +
* updated for tilesheet changes
 +
| ✘ broken visuals (e.g. missing chairs)
 +
| ✓ mostly unaffected<br /><small>(✘ broken visuals if they edit the affected tiles)</small>
 +
|-
 +
| <samp>Maps/MovieTheaterScreen_TileSheet</samp>
 +
| &#32;
 +
* improved light cone
 +
* moved chair sprite to make room for new light cone
 +
| ✘ broken visuals (e.g. missing chairs)
 +
| ✓ mostly unaffected<br /><small>(✘ broken visuals if they edit the affected sprites)</small>
 +
|-
 +
| <samp>Maps/paths</samp>
 +
| &#32;
 +
* added icon for [[#Custom wild trees|custom wild tree spawn]]
 +
* removed unused pathfinding tiles
 +
|
 
|
 
|
|
+
|-
|-
+
| <samp>Maps/QiNutRoom</samp>
| <samp>Maps/Woods</samp>
+
| &#32;
| removed unused tile property
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
|
+
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
|
+
| ✘ will remove changes
|-
+
| ✓ mostly unaffected
| <samp>Strings/Buildings</samp><br /><samp>Strings/Characters</samp>
+
|-
| added new entries
+
| <samp>Maps/Railroad</samp>
| '''✘ broken'''
+
| &#32;
|
+
* removed unused map property
|-
+
* removed unused pathfinding tiles
| <samp>Strings/credits</samp>
+
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
| updated credit line
+
|
| ✘ will remove changes
+
|
| ✓ mostly unaffected
+
|-
|-
+
| <samp>Maps/Saloon</samp><br /><samp>Maps/SamHouse</samp>
| <samp>Strings/FarmAnimals</samp>
+
| &#32;
| added new entries
+
* removed unused pathfinding tiles
| '''✘ broken'''
+
|
|
+
|
|-
+
|-
| <samp>Strings/Locations</samp>
+
| <samp>Maps/SandyHouse</samp>
| replaced bus price with placeholder, updated how Professor Snail's name is translated, removed unused entries, fixed typos
+
| &#32;
| '''✘ broken'''
+
* added <samp>LocationContext</samp> map property
| ✓ mostly unaffected
+
| '''✘ broken'''
|-
+
|
| <samp>Strings/NPCNames</samp>
+
|-
| added new entries
+
| <samp>Maps/ScienceHouse</samp><br /><samp>Maps/SebastianRoom</samp>
| '''✘ broken'''
+
| &#32;
|
+
* removed unused pathfinding tiles
|-
+
|
| <samp>Strings/Objects</samp><br /><samp>Strings/schedules/Caroline</samp>
+
|
| fixed typos
+
|-
| ✘ will remove changes  
+
| <samp>Maps/SeedShop</samp>
| ✓ mostly unaffected
+
| &#32;
|-
+
* removed unused tile properties
| <samp>Strings/SpecialOrderStrings</samp>
+
* removed unused pathfinding tiles
| renamed ''Dust Spirit'' to ''Dust Sprite''
+
|
| ✘ will remove changes  
+
|
| ✓ mostly unaffected
+
|-
|-
+
| <samp>Maps/Sewer</samp>
| <samp>Strings/StringsFromCSFiles</samp>
+
| &#32;
| added new entries, removed unused entries, fixed typos
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
| '''✘ broken'''
+
| ✘ will remove changes
| ✓ mostly unaffected
+
| ✓ mostly unaffected
|-
+
|-
| <samp>Strings/StringsFromMaps</samp>
+
| <samp>Maps/Shed</samp><br /><samp>Maps/Shed2</samp>
| fixed typos
+
| &#32;
| ✘ will remove changes
+
* added <samp>FloorIDs</samp> and <samp>WallIDs</samp> map properties
|  
+
| '''✘ broken'''
|-
+
|
| <samp>Strings/UI</samp>
+
|-
| added new entries, fixed typos
+
| <samp>Maps/SkullCave</samp>
| '''✘ broken'''
+
| &#32;
| ✓ mostly unaffected
+
* added <samp>LocationContext</samp> map property
|}
+
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/SlimeHutch</samp>
 +
| &#32;
 +
* removed unused tile property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/spousePatios</samp>
 +
| &#32;
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/spring_outdoorsTileSheet</samp><br /><samp>Maps/summer_outdoorsTileSheet</samp><br /><samp>Maps/fall_outdoorsTileSheet</samp><br /><samp>Maps/winter_outdoorsTileSheet</samp>
 +
| &#32;
 +
* pet bowl moved to <samp>Buildings/Pet Bowl</samp>
 +
| ✓ mostly unaffected
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Submarine</samp>
 +
| &#32;
 +
* removed unused tile property
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Sunroom</samp>
 +
| &#32;
 +
* added <samp>IsGreenhouse</samp map property
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Maps/Tent</samp>
 +
| &#32;
 +
* removed unused pathfinding tiles
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Town</samp>
 +
| &#32;
 +
* updated [[#Custom garbage cans|garbage can IDs]] (backwards-compatible)
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Town-Christmas</samp>
 +
| &#32;
 +
* updated for festival shops now in <samp>Data/Shops</samp>
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Town-DogHouse</samp>
 +
| &#32;
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Town-EggFestival</samp>
 +
| &#32;
 +
* updated for festival shops now in <samp>Data/Shops</samp>
 +
* fixed Elliott appearing twice during egg hunt
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Town-Fair</samp>
 +
| &#32;
 +
* removed unused map/tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Town-Halloween</samp>
 +
| &#32;
 +
* updated for festival shops now in <samp>Data/Shops</samp>
 +
* removed unused map/tile properties
 +
* removed unused pathfinding tiles
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Town-Theater</samp><br /><samp>Maps/Town-TheaterCC</samp><br /><samp>Maps/Town-TrashGone</samp>
 +
| &#32;
 +
* removed unused tile properties
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Trailer</samp>
 +
| &#32;
 +
* removed unused tile property
 +
* removed unused pathfinding tiles
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Trailer_big</samp>
 +
| &#32;
 +
* removed unused pathfinding tiles
 +
|
 +
|
 +
|-
 +
| <samp>Maps/Tunnel</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* removed unused map property
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/WitchHut</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/WitchSwamp</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/WitchWarpCave</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/WizardHouse</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* removed unused pathfinding tiles
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/WizardHouseBasement</samp>
 +
| &#32;
 +
* moved <samp>Music</samp> property into <samp>Data/Locations</samp>
 +
* removed unused map property
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Woods</samp>
 +
| &#32;
 +
* removed unused tile property
 +
* standardized <samp>T</samp> for boolean tile property values (backwards-compatible)
 +
|
 +
|
 +
|-
 +
| <samp>Minigames/boatJourneyMap</samp>
 +
| &#32;
 +
* asset replaced by redrawn seasonal variants like <samp>fall_boatJourneyMap</samp>
 +
| '''✘ broken'''
 +
| '''✘ broken'''
 +
|-
 +
| <samp>Strings/Characters</samp>
 +
| &#32;
 +
* added new entries
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Strings/BundleNames</samp>
 +
| &#32;
 +
* removed unused entries
 +
|
 +
|
 +
|-
 +
| <samp>Strings/Characters</samp>
 +
| &#32;
 +
* added new entries
 +
* removed unused entry
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Strings/credits</samp>
 +
| &#32;
 +
* updated for 1.6
 +
* various changes
 +
| ✘ will remove changes
 +
| ✘ will remove changes
 +
|-
 +
| <samp>Strings/Events</samp>
 +
| &#32;
 +
* moved [[#Dialogue changes|flower dance dialogue]] for Emily and Shane to their NPC dialogue files
 +
| ✓ mostly unaffected
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/FarmAnimals</samp>
 +
| &#32;
 +
* added new entries
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Strings/Lexicon</samp>
 +
| &#32;
 +
* removed unused entries
 +
|
 +
|
 +
|-
 +
| <samp>Strings/Locations</samp>
 +
| &#32;
 +
* added new entries
 +
* added placeholder to <samp>BusStop_BuyTicketToDesert</samp>
 +
* renamed <samp>BoatTunnel_BuyTicket</samp> to <samp>BuyTicket</samp>
 +
* updated how Professor Snail's name is translated, removed unused entries
 +
* fixed typos
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/NPCNames</samp>
 +
| &#32;
 +
* added new entries
 +
* removed unused entry
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Strings/Notes</samp>
 +
| &#32;
 +
* trimmed trailing whitespace
 +
|
 +
|
 +
|-
 +
| <samp>Strings/Objects</samp>
 +
| &#32;
 +
* added new entries
 +
* removed unused entries
 +
| '''✘ broken'''
 +
|
 +
|-
 +
| <samp>Strings/schedules/Caroline</samp>
 +
| &#32;
 +
* fixed typo
 +
| ✘ will remove changes  
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/SpecialOrderStrings</samp>
 +
| &#32;
 +
* renamed ''Dust Spirits'' to ''Dust Sprites''
 +
* fixed typos
 +
| ✘ will remove changes  
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/StringsFromCSFiles</samp>
 +
| &#32;
 +
* added new entries
 +
* removed unused entries
 +
* reworked <samp>FarmComputer_*</samp> translations
 +
* merged some gendered translations
 +
* merged <samp>ItemDeliveryQuest.cs.13533</samp> into <samp>ItemDeliveryQuest.cs.13534</samp>–<samp>13536</samp>
 +
* changed some player names from <samp>{0}</samp> to <samp>@</samp>
 +
* fixed typo
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/StringsFromMaps</samp>
 +
| &#32;
 +
* fixed typos
 +
* removed unused entries
 +
| ✘ will remove changes
 +
|  
 +
|-
 +
| <samp>Strings/UI</samp>
 +
| &#32;
 +
* added new entries
 +
* added placeholder for cabin count in <samp>Character_CoopHelpString</samp>
 +
* fixed typos
 +
* removed unused entries
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|}
 +
 
 +
====Removed unused assets====
 +
Stardew Valley 1.6 deletes assets which weren't used by the game. Mods usually aren't affected by this.
 +
 
 +
Removed assets:
 +
* <samp>Characters/Dana</samp>
 +
* <samp>Characters/Dick</samp>
 +
* <samp>Characters/femaleRival</samp>
 +
* <samp>Characters/maleRival</samp>
 +
* <samp>Characters/shirts</samp>
 +
* <samp>Characters/WeddingOutfits</samp>
 +
* <samp>Data/TV/InterviewShow</samp>
 +
* <samp>Effects/BrightWhite</samp>
 +
* <samp>Fonts/tinyFontBorder</samp>
 +
* <samp>Maps/Cabin</samp>
 +
* <samp>Maps/Cabin1</samp>
 +
* <samp>Maps/Cabin1_marriage</samp>
 +
* <samp>Maps/Cabin2</samp>
 +
* <samp>Maps/Cabin2_marriage</samp>
 +
* <samp>Maps/Island_Boulder_Removed</samp>
 +
* <samp>Maps/qiNutRoom_tilesheet_0</samp>
 +
* <samp>Maps/spring_outrdoorsTileSheet_lightergrass</samp>
 +
* <samp>Portraits/Dobson</samp>
 +
* <samp>TerrainFeatures/DiggableWall_basic</samp>
 +
* <samp>TerrainFeatures/DiggableWall_basic_dark</samp>
 +
* <samp>TerrainFeatures/DiggableWall_frost</samp>
 +
* <samp>TerrainFeatures/DiggableWall_frost_dark</samp>
 +
* <samp>TerrainFeatures/DiggableWall_lava</samp>
 +
* <samp>TerrainFeatures/DiggableWall_lava_dark</samp>
 +
* <samp>TerrainFeatures/Quartz</samp>
    
==Vanilla release notes==
 
==Vanilla release notes==
{{note box|'''These are unofficial release notes for the 1.6 mod author alpha.'''<br />The [https://twitter.com/ConcernedApe new content announced by ConcernedApe] hasn't been revealed yet and isn't listed below.|type=warning}}
+
''Moved to [[Version History#1.6]].''
 
  −
This is a draft for the [[Version History]] section when 1.6 is released. Feel free to edit or suggest anything that was missed.
  −
 
  −
<blockquote>
  −
<big>'''1.6.0'''</big><br />
  −
Stardew Valley 1.6.0 was released to the Steam beta branch on XX XX 20XX, and released on XX XXXX 20XX.
  −
 
  −
; New content & features
  −
:* Added a world map for [[Ginger Island]], visible when visiting the island.
  −
:* The world map now shows your actual position within the world in real-time (instead of showing you at a fixed point for each location). In multiplayer, you'll see other players' position in real-time too.
  −
:* The farmhouse and pet bowl can now be moved through Robin's menu.
  −
:* The [[Farm Computer|farm computer]] can now be used anywhere to see a summary of that location, instead of only the farm.
  −
:* The [[Mini-Jukebox|mini-jukebox]] can now be used on the [[Ginger Island]] farm.
  −
 
  −
; Balance changes
  −
:* You can no longer lose the Golden Scythe, Infinity weapons, or tools when dying.
  −
:* Added [[wikipedia:Coyote time|grace jumps]] in Junimo Kart: when you run off the track, you can still jump for a short time to recover.
  −
:* Increased the [[Forge#Enchantments|shaving enchantment]]'s effect on [[Crops#Giant Crops|giant crops]].<br /><small>Each giant crop now has a 60% chance of dropping an extra six crops while the shaving enchantment is equipped, spread across the number of hits needed to break it. For example, a base axe which breaks the giant crop in three hits gets three 20% chances of dropping 2 crops.</small>
  −
:* The [[The Cave|mushroom cave]] now provides mushrooms every second day. It was unintentionally changed to daily in Stardew Valley 1.5.
  −
:* Randomization no longer produces simple repeating patterns in many cases (e.g. clay farming, mushroom level prediction, crab pot fish offset, etc).<br /><small>You can enable "Use Legacy Randomization" in the [[Options|advanced save options]] to use the old randomization, though some specific patterns may still change due to the underlying changes. That option is mainly intended for speedrunners; most players should keep it disabled for the intended experience.</small>
  −
:* Spreading [[weeds]] can no longer destroy [[Artifact Spot|artifact spots]].
  −
 
  −
; Quality of life changes
  −
:* NPCs now shove chests out of their way instead of destroying them.
  −
:* Redrew the world map to better match the in-game locations and be more detailed.
  −
:* Shops now have a slight delay before you can buy/sell items, to help avoid double-clicks doing it accidentally.
  −
:* Planting [[Cactus Seeds|cactus seeds]] on the farm now fails with a message, instead of the seeds dying overnight.
  −
:* [[Marnie's Ranch|Marnie's animal menu]] now shows prices in the tooltip, in case the tooltip covers the price display.
  −
:* Holding a [[Tea Sapling|tea sapling]] or [[Crops|seed]] over a [[Garden Pot|garden pot]] now shows the green/red placement tile.
  −
:* The museum reward menu now prevents picking up a reward that won't fit in your inventory.
  −
:* The museum reward menu now lets you exit while holding a reward. It'll be added to your inventory if possible, otherwise it'll drop at your feet.
  −
:* If an item menu exits while you're holding an item, the item is now always retrieved. (Previously only some item menus like chests would do it.)
  −
:* If a default farm building (like the greenhouse) is somehow removed, it'll now be rebuilt next time you load the save.
  −
:* You can no longer pick up rugs if there's something on it.
  −
:* You can now refill slingshot ammo by right-clicking it with the same ammo. Previously that would just swap the item stacks.
  −
:* Positional sounds now fade with distance when off-screen, instead of cutting off abruptly.
  −
:* Made more sounds positional (mainly player and tool sounds).
  −
:* Deleting a save on PC is now much faster.
  −
:* Significantly reduced save loading time when there are many custom locations.
  −
:* Performance improvements.
  −
 
  −
; Other changes
  −
:* Raised multiplayer limit to 8 players (on desktop only).
  −
:* Gender-specific clothing variants can now be worn by any gender.
  −
:* After reaching six hearts with some NPCs, they won't visit their rival love interest anymore. This affects [[Alex]] visiting [[Haley]], [[Elliott]] visiting [[Leah]], and Haley visiting Alex.
  −
:* The about page now shows the build number.
  −
:* The about page no longer hides the version if a tip message is shown.
  −
:* The [[Ginger Island#Gem Birds|Ginger Island shrine]] item pedestals are now normal items. Modded players can spawn them to display items decoratively (though they're not obtainable in vanilla currently).
  −
:* Fixed some NPC schedules not being applied:
  −
:** [[Lewis]] visiting the library on winter Sundays;
  −
:** [[Maru]] and [[Penny]] hanging out on summer Sundays;
  −
:** and [[Maru]] tinkering on summer Mondays.
  −
 
  −
; Fixes for gameplay
  −
:* Fixed issues with buffs:
  −
:** Fixed a range of bugs like attribute drift and double-debuff.
  −
:** Fixed food/drink buffs discarded if they have a balanced total of effects (e.g. +2 attack and -2 speed).
  −
:** Fixed negative custom buffs shown with a double-negative (e.g. "--2 speed").
  −
:** Fixed Squid Ink Ravioli buff not remaining active if another food buff is added later (although the buff icon was still shown).
  −
:** Fixed Squid Ink Ravioli not resetting the buff duration when you eat another one, unlike other food buffs.
  −
:** Fixed Squid Ink Ravioli description having an extra blank line.
  −
:** Fixed Burnt not showing the -3 Attack effect.
  −
:* Fixed unable to leave the [[Festival of Ice]] until it ends.
  −
:* Fixed player stuck in swimsuit if they collapse from damage while wearing it.
  −
:* Fixed gates popping off when opening or closing them while the player overlaps the tile.
  −
:* Fixed broken event if the player is defeated in the mines and their name contains a slash.
  −
:* Fixed fishing crash if a treasure chest appears while the player has a large number of stacked fishing buffs.
  −
:* Fixed issue where breaking a [[Bee House|bee house]] containing honey would drop a generic "Honey" item, instead of the flavored honey it would produce when harvested.
  −
:* Fixed issue where using the [[Rain Totem|rain totem]] during a storm would make the next day stormy too, instead of rainy.
  −
:* Fixed issue where you could clear a forest-themed [[The Mines|mine level]] without finding a ladder.
  −
:* Fixed issue where clicking an item attached to a letter could exit the letter if your inventory was full.
  −
:* Fixed [[Magic Bait|magic bait]] disabling some fish area checks (e.g. so you could catch river fish in the forest pond).
  −
:* Fixed random seeds on [[Ginger Island]] being based on the valley's season.
  −
:* Fixed dropped tools not recovered if they're inside a constructed building.
  −
:* Fixed potted [[Tea Bush|tea bushes]] planted in town not being harvestable.
  −
:* Fixed [[Heavy Tapper|heavy tappers]] not tracked correctly. That caused issues like heavy-tapped trees not ignored when creating [[Mushroom Tree|mushroom trees]] in fall.
  −
:* Fixed [[Secret Notes|Secret Note #2]] not revealing [[Kent]]'s gift taste if he hasn't returned yet.
  −
:* Fixed [[Wedding Ring|wedding rings]] being giftable to NPCs.
  −
:* Fixed exploit where you could keep temporary items like Qi Fruit by selling them to Pierre and buying them back later.
  −
:* Fixed fruit trees being plantable on stone tiles outside the greenhouse.
  −
:* Fixed artifacts found while fishing not counting for the collections tab, and many other cases where item-received logic wasn't always applied.
  −
 
  −
; Fixes for NPC dialogue
  −
:* Enabled some dialogues that were accidentally never shown. That includes:
  −
:** Emily and Shane's [[Flower Dance]] custom accept-dance dialogues when married to the player.
  −
:** Shane's dialogue when browsing the Saloon vending machine.
  −
:** Lewis congratulating female farmers after their wedding.
  −
:** A line in Maru's 14-heart event.
  −
:** Three dialogues from Sam related to Kent<!--Thu6_1, Thu6_2, summer_Thu6_1-->.
  −
:** Two randomized dialogues when an NPC buys an item you sold to a shop.
  −
:** Two speech bubbles from Marnie and Robin when you enter their shop building.
  −
:** A fortune teller dialogue for your potential spouse.
  −
:* Fixed NPCs not having custom dialogue when accepting a movie invite for non-English players.
  −
:* Fixed Lewis skipping his final dialogue at the [[Festival of Ice]] on subsequent player wins.
  −
:* Fixed the [[Stardew Valley Fair|fortune teller]] nearly always showing the text for your combat skill, instead of your highest skill.
  −
:* Fixed issue where an NPC who bought an iridium-quality item you sold to a shop could show a low-item-quality dialogue for it.
  −
:* Fixed [[Abigail#Fourteen Hearts|monster grave text]] only shown in English.
  −
:* Fixed wrong message shown when placing indoors-only furniture outside.
  −
 
  −
; Fixes for visual or cosmetic issues
  −
:* The submerged [[fishing]] bobber is now recolored automatically to match the water.
  −
:* Removed phantom action cursor over island farmhouse drawer.
  −
:* Removed phantom action cursor over backwoods gravestone if the current player hasn't seen [[Abigail#Fourteen Hearts|the related event]] yet.
  −
:* Fixed cursor over NPCs sometimes showing a gift icon when they won't accept or react to the held item.
  −
:* Fixed [[Quality Fertilizer|quality fertilizer]] showing a green tile on sprouted crops, even though it can't be placed there.
  −
:* Fixed the <code>!</code> fish bite icon not shown when fishing in the [[Stardew Valley Fair]] and [[Festival of Ice]].
  −
:* Fixed some in-game error messages not having an error icon.
  −
:* Fixed inventory & crafting menus misaligned if you resize the window while they're open.
  −
:* Fixed fruit tree leaves not rustling in winter even if they're in a non-seasonal location like the [[greenhouse]].
  −
:* Fixed weeds being less varied than intended in summer.
  −
:* Fixed intro cutscene position not adjusted when the farmhouse is moved by a mod.
  −
:* Fixed cosmetic issues with the title & shipping screens for higher-resolution displays.
  −
:* Fixed calendar tooltip when a modded festival and birthday occur on the same day.
  −
:* Fixed beds or chests that were hidden for an event not reappearing afterwards.
  −
:* Fixed pre-built cabins sometimes placed on top of a bush or log.
  −
:* Fixed furniture drawn over sitting players if it has no front texture.
  −
:* Fixed the [[forge]] preview always showing soul level one for a [[Galaxy Soul|galaxy soul]] forge.
  −
:* Fixed many things on [[Ginger Island]] applying the valley's season or weather (including [[Fiber Seeds|fiber seeds]], [[Seasonal Decor|seasonal decor]], [[Seasonal Plant|seasonal plants]], [[Tea Bush|tea bushes]], and [[Tub o' Flowers|tubs o' flowers]]).
  −
:* Fixed [[Options|advanced save option]] tooltips being able to extend off-screen, and not shown for some field labels.
  −
:* Fixed Elliott appearing twice during the [[Egg Festival|egg hunt]].
  −
:* Fixed bombs being invisible when placed on [[The Summit|the summit]].
  −
:* Fixed speech bubbles sometimes shown over invisible NPCs.
  −
:* Fixed HUD messages sometimes overlapping.
  −
 
  −
; Fixes for display text and localization
  −
:* Spanish prices are now formatted like ''15o'' instead of ''15g'' to match the translated term (''oro'' instead of ''gold'').
  −
:* Fixed ''many'' issues in dialogue, events, and other display text (including typos, broken tokens, translations that don't match the original, etc).
  −
:* Fixed NPC name translations applied to horses/pets that share a name with that NPC.
  −
:* Fixed unlocalized text shown for...
  −
:** the building paint menu's region names (like "Roof" or "Trim");
  −
:** NPC names in some movie theater dialogue;
  −
:** Professor Snail's name after his first event;
  −
:** Leo's name in his introductory event for some languages;
  −
:** fish names for some languages in certain cases;
  −
:** the 'Miss' text when an attack misses.
  −
:* Fixed random name generator able to produce words similar to certain slurs.
  −
:* Fixed [[Dust Sprite|dust sprites]] called ''dust spirits'' in Clint's special order and the summit cutscene.
  −
:* Fixed Lewis' letter for Feast of the Winter Star saying it starts at 10am instead of 9am.
  −
:* Fixed some recipe names not matching the items they produce.
  −
:* Fixed the hats added in 1.5 translating their internal name instead of setting the display name in some languages.
  −
:* Fixed issue where NPC dialogue could reveal gift tastes for an invalid item.
  −
:* Fixed French formatting times past midnight like "26h" instead of "02h" (e.g. on the fishing TV channel).
  −
:* Fixed French and Turkish showing broken dialogues about another NPC's gift tastes.
  −
:* Fixed German truncating Professor Snail's name in his intro event.
  −
:* Fixed Japanese and Korean formatting buff effects inconsistently.
  −
:* Fixed Korean credit line missing in other languages.
  −
:* Fixed Russian event for Professor Snail's intro freezing.
  −
 
  −
; Fixes for multiplayer
  −
:* Possibly fixed frequent disconnections for some players.
  −
:* Fixed [[Egg Festival|egg festival]] requiring 12 eggs to win if there are 5+ players. It now applies the four-player requirement to any player count beyond that.
  −
:* Fixed farmhands sometimes able to walk out of bounds at festivals.
  −
:* Fixed various cases where values weren't correctly synced between players.
  −
:* Fixed watered dirt edges not updated for farmhands when they change overnight.
  −
:* Fixed 'caught snooping' chat message not triggered when Marnie sees the player searching her trash bin.
  −
:* Fixed cleared-landslide mail only sent to the main player.
  −
 
  −
; Fixes for modded players
  −
:* Monsters no longer [[Options#Advanced Game Options|spawn at night]] by default on custom farm types.
  −
:* Non-binary NPCs can now pathfind through any gendered route (e.g. men's or women's locker room), instead of defaulting to female routes.
  −
:* Fixed crashes when...
  −
:** loading a save with unknown locations, an invalid farm type, NPCs with no sprite texture, or null world objects.
  −
:** the farm map has no grass spawn tile and you walk through crops or grass.
  −
:** the data for an item, animal, tree, etc no longer exists.
  −
:** [[Carpenter's Shop#Painting|painting a building]] if its sprite changed to a smaller one since it was last painted.
  −
:** playing audio which doesn't exist (it now logs an error and plays a default 'quiet click' sound instead).
  −
:** a farmhand warps to a location which doesn't exist locally yet.
  −
:** an NPC can't parse its dialogue (it now logs the error and defaults to "..." instead).
  −
:** a [[Mini-Jukebox|mini-jukebox]] has an invalid track selected (it now turns off instead).
  −
:** a [[Mini-Shipping Bin|mini-shipping bin]] has null items.
  −
:** a [[Statue Of Endless Fortune|statue of endless fortune]] tries to produce a gift for an NPC whose first loved gift is a category or context tag (it now now chooses the first valid gift taste, and falls back to a non-birthday gift if none was found);
  −
:** a farm animal warps home in rare cases;
  −
:** the player's NPC spouse no longer exists (e.g. the mod which added it was removed).
  −
:* Fixed calendar support for multiple events on the same day (including multiple weddings, multiple birthdays, birthdays on a festival day, etc).
  −
:* Fixed horses in indoor locations or [[The Mines|mine]]/[[Volcano Dungeon|volcano]] levels unable to return home.
  −
:* Fixed event setup not allowing more than 9 players.
  −
:* Fixed events not exiting correctly if they crash before the first script command.
  −
:* Fixed event errors not logged to the console.
  −
:* Fixed potential event crash if a custom NPC name contains 'farmer'.
  −
:* Fixed save loading very slowly if it has a broken outdoors location in some cases.
  −
:* Fixed some items being unremovable when spawned by players. This affects [[Incubator|incubators]], [[The Cave#Mushrooms|mushroom boxes]], [[Slime Ball|slime balls]], and three unused items (locked doors and alternate [[Wicked Statue|wicked statue]]).
  −
:* Fixed issue when warping to [[Sandy]] early using mods where she could give daily quests as soon as you met her, but didn't accept items until you fixed the bus.
  −
 
  −
; Other bug fixes
  −
:* Fixed crashes when...
  −
:** taking a screenshot on macOS if the <samp>~/.local</samp> folder doesn't exist.
  −
:** a farmhand warps just as certain things happen (e.g. pet sounds).
  −
:* Fixed window resize on character creation resetting profit margins & starting cabins, and desyncing the 'skip intro' checkbox.
  −
:* Fixed able to equip a [[staircase]] as pants to obtain [[Trimmed Lucky Purple Shorts|trimmed lucky purple shorts]].
  −
:* Fixed being able to place a [[Yellow Couch|yellow couch]] in a [[loom]].
  −
:* Fixed wilderness farm spawning a stone in water.
  −
:* Fixed hilltop farm spawning grass inside of stumps.
  −
:* Fixed [[Trash Bear]] treated as a villager (e.g. it could theoretically be picked for quests).
  −
:* Fixed save folder collision if you set the save's name & seed to the same value as an existing save.
  −
:* Fixed issue where viewing a letter with multiple pages and positioning the cursor directly above the skip button could cause the next viewed event to be skipped when the A button is pressed to progress text.
  −
:* Fixed the [[Secrets#Lonely Stone|lonely stone]] map tooltip not accessible with a gamepad.
  −
:* Fixed the build number not set on Linux/macOS.
  −
 
  −
; Other changes
  −
:* See [[Modding:Migrate to Stardew Valley 1.6|changes for mod authors]].
  −
</blockquote>
      
==See also==
 
==See also==
5

edits