Changes

Jump to navigation Jump to search
→‎Custom mail formatting: fix captioning on image
Line 1: Line 1:  
←[[Modding:Index|Index]]
 
←[[Modding:Index|Index]]
   −
{{SMAPI upcoming|3.13.0}}
   
{{Modder compatibility header}}
 
{{Modder compatibility header}}
    
This page explains how to update your mods for compatibility with {{version|1.5.5|Stardew Valley 1.5.5}}, and documents some of the changes and new functionality.
 
This page explains how to update your mods for compatibility with {{version|1.5.5|Stardew Valley 1.5.5}}, and documents some of the changes and new functionality.
   −
==For SMAPI mods==
+
==Breaking changes for SMAPI mods==
===Stardew Valley compatibility branch===
  −
Stardew Valley 1.5.5 is available in two branches on each OS (with identical content for players): the ''main branch'' which is installed by default, and an optional ''compatibility branch'' for [https://www.stardewvalley.net/compatibility older systems]. These have identical content for players, but use different technologies:
  −
 
  −
{| class="wikitable"
  −
|-
  −
! branch
  −
! OS
  −
! game framework
  −
! runtime
  −
|- style="color: #090;"
  −
|rowspan="2"| main
  −
| Linux/macOS
  −
| MonoGame 3.8
  −
| 64-bit .NET 5
  −
|- style="color: #090;"
  −
| Windows
  −
| MonoGame 3.8
  −
| 64-bit .NET 5
  −
|- style="color: #900;"
  −
|rowspan="2"| compatibility
  −
| Linux/macOS
  −
| MonoGame 3.5.1
  −
| 64-bit Mono 4.5
  −
|- style="color: #900;"
  −
| Windows
  −
| XNA Framework 4.0
  −
| 32-bit .NET Framework 4.5
  −
|}
  −
 
  −
Unfortunately '''SMAPI only supports the main branch of the game.''' There are formidable difficulties across all mods in supporting all three variations, the [https://store.steampowered.com/hwsurvey Steam hardware stats] show that ≈99.69% of players have 64-bit, and 32-bit imposes significant restrictions on what mods can do.
  −
 
   
===64-bit MonoGame and .NET 5===
 
===64-bit MonoGame and .NET 5===
 
Stardew Valley 1.5.5 migrates to 64-bit MonoGame and .NET 5 on all platforms. SMAPI rewrites mods so they should mostly still work, but posting an update for every C# mod is strongly recommended to avoid edge cases.
 
Stardew Valley 1.5.5 migrates to 64-bit MonoGame and .NET 5 on all platforms. SMAPI rewrites mods so they should mostly still work, but posting an update for every C# mod is strongly recommended to avoid edge cases.
Line 44: Line 12:  
<ol>
 
<ol>
 
<li>[[Modding:Migrate to 64-bit on Windows#How do I update mod code for 64-bit?|Enable 64-bit compatibility]] if you haven't already. (Unless you explicitly changed the project settings, mods are 64-bit ready by default.)</li>
 
<li>[[Modding:Migrate to 64-bit on Windows#How do I update mod code for 64-bit?|Enable 64-bit compatibility]] if you haven't already. (Unless you explicitly changed the project settings, mods are 64-bit ready by default.)</li>
<li>Migrate your <tt>.csproj</tt> files to the new format if you haven't already:<ol>
+
<li>Migrate your <samp>.csproj</samp> files to the new format if you haven't already:<ol>
<li>Replace your mod's <tt>.csproj</tt> file with this:
+
<li>Replace your mod's <samp>.csproj</samp> file with this:
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
<Project Sdk="Microsoft.NET.Sdk">
 
<Project Sdk="Microsoft.NET.Sdk">
Line 52: Line 20:  
     <RootNamespace>EXAMPLE_MOD_NAME</RootNamespace>
 
     <RootNamespace>EXAMPLE_MOD_NAME</RootNamespace>
 
     <Version>1.0.0</Version>
 
     <Version>1.0.0</Version>
     <TargetFramework>net452</TargetFramework>
+
     <TargetFramework>net5.0</TargetFramework>
 +
    <LangVersion>Latest</LangVersion>
 
   </PropertyGroup>
 
   </PropertyGroup>
    
   <ItemGroup>
 
   <ItemGroup>
     <PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="3.3.0" />
+
     <PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.1.1" />
 
   </ItemGroup>
 
   </ItemGroup>
 
</Project>
 
</Project>
Line 62: Line 31:  
</li>
 
</li>
 
<li>If the mod uses [[Modding:Modder Guide/APIs/Harmony|Harmony]], add <code><nowiki><EnableHarmony>true</EnableHarmony></nowiki></code> to the property group.</li>
 
<li>If the mod uses [[Modding:Modder Guide/APIs/Harmony|Harmony]], add <code><nowiki><EnableHarmony>true</EnableHarmony></nowiki></code> to the property group.</li>
<li>Update the <tt>AssemblyName</tt>, <tt>RootNamespace</tt>, and <tt>Version</tt> tags. (You can delete the <tt>AssemblyName</tt> and <tt>RootNamespace</tt> tags if they just match the project name.)</li>
+
<li>Update the <samp>AssemblyName</samp>, <samp>RootNamespace</samp>, and <samp>Version</samp> tags. (You can delete the <samp>AssemblyName</samp> and <samp>RootNamespace</samp> tags if they just match the project name.)</li>
 
<li>Add any other NuGet packages you used, if any.</li>
 
<li>Add any other NuGet packages you used, if any.</li>
<li>Delete the <tt>Properties/AssemblyInfo.cs</tt> file, <tt>packages</tt> folder, and <tt>packages.config</tt> file (if present).</li>
+
</ol>
 +
 
 +
If you're using the simplified format already, you just need to update version numbers in the .csproj file:
 +
<ol>
 +
<li>Replace <code><nowiki><TargetFramework>net452</TargetFramework></nowiki></code> with <code><nowiki><TargetFramework>net5.0</TargetFramework></nowiki></code>.</li>
 +
<li>Replace <code><nowiki><PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="3.3.0" /></nowiki></code> with <code><nowiki><PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.1.1" /></nowiki></code></li>
 
</ol>
 
</ol>
 
</li>
 
</li>
<li>Edit your mod's <tt>.csproj</tt> file, and replace <code><nowiki><TargetFramework>net452</TargetFramework></nowiki></code> with <code><nowiki><TargetFramework>net5.0</TargetFramework></nowiki></code>.</li>
+
<li>Delete the <samp>Properties/AssemblyInfo.cs</samp> file, <samp>packages</samp> folder, and <samp>packages.config</samp> file (if present).</li>
<li>Update the mod build package to the prerelease 3.4.0 version.</li>
   
<li>Exit Visual Studio.</li>
 
<li>Exit Visual Studio.</li>
<li>Delete your solution's hidden <tt>.vs</tt> folder, and every project's <tt>bin</tt> and <tt>obj</tt> folders.</li>
+
<li>Delete your solution's hidden <samp>.vs</samp> folder, and every project's <samp>bin</samp> and <samp>obj</samp> folders.</li>
 
<li>Reopen the solution in Visual Studio, click ''Build > Rebuild Solution'', fix any errors, and test the mod in-game.</li>
 
<li>Reopen the solution in Visual Studio, click ''Build > Rebuild Solution'', fix any errors, and test the mod in-game.</li>
 
</ol>
 
</ol>
    
Specific things to check for:
 
Specific things to check for:
* [[Modding:Modder Guide/APIs/Utilities#Constants|<code>Constants.GameFramework</code>]] now always returns <tt>MonoGame</tt>. Any code which checks for <tt>Xna</tt> can be removed or rewritten.
+
* [[Modding:Modder Guide/APIs/Utilities#Constants|<code>Constants.GameFramework</code>]] now always returns <samp>MonoGame</samp>. Any code which checks for <samp>Xna</samp> can be removed or rewritten.
    
If you need help, feel free to ask in [[Modding:Community#Discord|#making-mods on the Stardew Valley Discord]]!
 
If you need help, feel free to ask in [[Modding:Community#Discord|#making-mods on the Stardew Valley Discord]]!
Line 103: Line 76:  
|}
 
|}
   −
===Consistent game assembly name===
+
===Game compatibility branch===
 +
{{main article|Modding:Player Guide/Troubleshooting#SMAPI doesn't work with compatibility branch}}
 +
 
 +
Stardew Valley 1.5.5 is available in two branches on each OS: the ''main branch'' which is installed by default, and an optional [https://www.stardewvalley.net/compatibility''compatibility branch'' for older systems]. These have identical content for players, but use different frameworks:
 +
 
 +
{| class="wikitable"
 +
|-
 +
! branch
 +
! OS
 +
! game framework
 +
! runtime
 +
|- style="color: #090;"
 +
|rowspan="2"| main
 +
| Linux/macOS
 +
| MonoGame 3.8
 +
| 64-bit .NET 5
 +
|- style="color: #090;"
 +
| Windows
 +
| MonoGame 3.8
 +
| 64-bit .NET 5
 +
|- style="color: #900;"
 +
|rowspan="2"| compatibility
 +
| Linux/macOS
 +
| MonoGame 3.5.1
 +
| 64-bit Mono 4.5
 +
|- style="color: #900;"
 +
| Windows
 +
| XNA Framework 4.0
 +
| 32-bit .NET Framework 4.5
 +
|}
 +
 
 +
Unfortunately '''SMAPI only supports the main branch of the game currently.''' There are formidable difficulties across all mods in supporting all three variations, 32-bit imposes significant restrictions on what mods can do, and the [https://store.steampowered.com/hwsurvey Steam hardware stats] show that ≈99.69% of players have 64-bit.
 +
 
 +
Having two versions of SMAPI (like we do for Linux/macOS vs Windows compatibility) wouldn't be enough in this case. Every C# mod author would need to manually port two versions of every update of every mod forever, which is prohibitively unfeasible. It's possible that in the future we'll either figure out how SMAPI can automatically rewrite mods for the compatibility branch, or some modders may port SMAPI and individual mods to the compatibility branch.
 +
 
 +
===Game assembly name===
 
Previously the game assembly was <code>Stardew Valley</code> on Windows, and <code>StardewValley</code> on Linux and macOS. The assembly is now named <code>Stardew Valley</code> on all platforms. Most mods shouldn't be affected once you update the mod build package.
 
Previously the game assembly was <code>Stardew Valley</code> on Windows, and <code>StardewValley</code> on Linux and macOS. The assembly is now named <code>Stardew Valley</code> on all platforms. Most mods shouldn't be affected once you update the mod build package.
 +
 +
===New assembly reference model===
 +
If your mod references a <samp>.dll</samp> file manually, note that assembly references are handled differently in .NET 5. Custom assemblies are no longer copied into your mod's folder by default, which may break your mod. In that case you need to explicitly enable assembly bundling in your project file; see <code>BundleExtraAssemblies</code> in the [https://smapi.io/package mod build package] documentation for details.
 +
 +
==Breaking changes for Content Patcher packs==
 +
===XNB impact===
 +
Here's a summary of the XNB files which changed in Stardew Valley 1.5.5.
 +
 +
Notes:
 +
* This ignores text changes in non-English files for simplicity.
 +
* New content files aren't listed, since they won't impact existing mods.
 +
* XNB mods are disproportionately affected, since they replace the entire file. Content Patcher packs are typically unaffected unless they replace the entire file (in which case see the XNB mod column).
 +
 +
Shorthand:
 +
* '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.
 +
 +
{| class="wikitable"
 +
|-
 +
! content file
 +
! changes
 +
! XNB
 +
! Content Patcher
 +
|-
 +
| <samp>Data/TV/TipChannel</samp>
 +
| fixed typo
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Effects/BloomCombine</samp><br /><samp>Effects/BloomExtract</samp><br /><samp>Effects/GaussianBlur</samp>
 +
| deleted
 +
|
 +
|
 +
|-
 +
| <samp>Fonts/*</samp>
 +
| no changes<br />([[Modding:Editing XNB files#unpack|unpacked format]] may differ on Windows due to [[#64-bit MonoGame and .NET 5|MonoGame]])
 +
|
 +
|
 +
|-
 +
| <samp>LooseSprites/Cursors2</samp>
 +
| new sprite in empty area
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/Desert</samp>
 +
| cosmetic fixes
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Maps/ElliottHouse</samp>
 +
| minor fixes
 +
| ✘ will remove changes
 +
| ✓ mostly unaffected
 +
|-
 +
| <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>
 +
| cave and shipping areas now use tile properties to disable building, instead of being hardcoded
 +
| ✘ will remove those build restrictions
 +
| ✘ may remove those build restrictions
 +
|-
 +
| <samp>Maps/FarmHouse</samp><br /><samp>Maps/FarmHouse1</samp><br /><samp>Maps/FarmHouse1_marriage</samp><br /><samp>Maps/FarmHouse2</samp><br /><samp>Maps/FarmHouse2_marriage</samp><br /><samp>Maps/Farmhouse_*</samp> renovation maps<br /><samp>Maps/IslandFarmHouse</samp><br /><samp>Maps/Shed</samp><br /><samp>Maps/Shed2</samp>
 +
| added new [[#Custom floors/walls|wall/flooring properties]]
 +
| '''✘ broken''' (will disable most floor/walls when renovations applied)
 +
| ✘ may disable some floor/walls when renovations applied
 +
|-
 +
| <samp>Maps/spouseRooms</samp>
 +
| added [[#Custom spouse rooms|spouse standing spots]] (defaults to old offset if not set)
 +
| ✓ mostly unaffected
 +
| ✓ mostly unaffected
 +
|-
 +
| <samp>Strings/Locations</samp>
 +
| changed <samp>ManorHouse_DivorceBook_*</samp> entries to support [[#Non-Krobus roommates|Non-Krobus roommates]]
 +
| '''✘ broken'''
 +
| ✓ mostly unaffected
 +
|}
 +
 +
==New features for SMAPI mods==
 +
: ''See also [[#New features for Content Patcher packs|new features for Content Patcher packs]], which apply for C# mods too.
    
===Scarecrow changes===
 
===Scarecrow changes===
Line 110: Line 196:     
===Horse footstep changes===
 
===Horse footstep changes===
You can now override the footstep logic for a horse by setting its <tt>onFootstepAction</tt> field. For example:
+
You can now override the footstep logic for a horse by setting its <samp>onFootstepAction</samp> field. For example:
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
 
Horse horse = ...; // get the horse instance you want to change
 
Horse horse = ...; // get the horse instance you want to change
Line 119: Line 205:  
</syntaxhighlight>
 
</syntaxhighlight>
   −
===Content changes===
+
==New features for Content Patcher packs==
See ''[[#For Content Patcher packs|For Content Patcher packs]]'' below, which applies for C# mods too.
  −
 
  −
==For Content Patcher packs==
   
Stardew Valley 1.5.5 has no known breaking changes for content packs. All content packs should work fine once the framework mod that loads them is updated.
 
Stardew Valley 1.5.5 has no known breaking changes for content packs. All content packs should work fine once the framework mod that loads them is updated.
    
===Custom farm types===
 
===Custom farm types===
You can now add custom farm types by editing the <tt>Data/AdditionalFarms</tt> asset. Each entry consists of an object with these fields:
+
You can now add custom farm types by editing the <samp>Data/AdditionalFarms</samp> asset. Each entry consists of an object with these fields:
    
{| class="wikitable"
 
{| class="wikitable"
Line 133: Line 216:  
! description
 
! description
 
|-
 
|-
| <tt>ID</tt>
+
| <samp>ID</samp>
| A unique ID value. This must be '''globally''' unique across all mods, so you should prefix your mod ID (e.g. <tt>Example.PineapplesAnywhere/PineappleFarm</tt>). You should avoid commas for compatibility with Content Patcher packs checking the <tt><nowiki>{{FarmType}}</nowiki></tt> token. This is not shown in-game.
+
| A unique ID value. This must be '''globally''' unique across all mods, so you should prefix your mod ID (''e.g.,'' <samp>Example.PineapplesAnywhere/PineappleFarm</samp>). You should avoid commas for compatibility with Content Patcher packs checking the <samp><nowiki>{{FarmType}}</nowiki></samp> token. This is not shown in-game.
 
|-
 
|-
| <tt>TooltipStringPath</tt>
+
| <samp>TooltipStringPath</samp>
| Where to get the translatable farm name and description. This must be a key in the form <tt>{{t|asset name}}:{{t|key}}</tt>; for example, <tt>Strings/UI:Farm_Description</tt> will get it from the <tt>Farm_Description</tt> entry in the <tt>Strings/UI</tt> file. The translated text must be in the form "<tt>{{t|name}}_{{t|description}}</tt>", like "Pineapple Farm_A farm shaped like a pineapple".
+
| Where to get the translatable farm name and description. This must be a key in the form <samp>{{t|asset name}}:{{t|key}}</samp>; for example, <samp>Strings/UI:Farm_Description</samp> will get it from the <samp>Farm_Description</samp> entry in the <samp>Strings/UI</samp> file. The translated text must be in the form "<samp>{{t|name}}_{{t|description}}</samp>", like "Pineapple Farm_A farm shaped like a pineapple".
 
|-
 
|-
| <tt>MapName</tt>
+
| <samp>MapName</samp>
| The map asset name relative to the <tt>Maps</tt> folder. For example, <tt>Farm_Pineapple</tt> would load <tt>Maps/Farm_Pineapple</tt>.
+
| The map asset name relative to the <samp>Maps</samp> folder. For example, <samp>Farm_Pineapple</samp> would load <samp>Maps/Farm_Pineapple</samp>.
 
|-
 
|-
| <tt>IconTexture</tt>
+
| <samp>IconTexture</samp>
 
| ''(optional)'' The asset name for a 22x20 pixel icon texture, shown on the 'New Game' and co-op join screens.
 
| ''(optional)'' The asset name for a 22x20 pixel icon texture, shown on the 'New Game' and co-op join screens.
 
|-
 
|-
| <tt>WorldMapTexture</tt>
+
| <samp>WorldMapTexture</samp>
 
| ''(optional)'' The asset name for a 131x61 pixel texture that's drawn over the farm area in the in-game world map.
 
| ''(optional)'' The asset name for a 131x61 pixel texture that's drawn over the farm area in the in-game world map.
 
|-
 
|-
| <tt>ModData</tt>
+
| <samp>ModData</samp>
| ''(optional)'' A string→string dictionary of mod-specific metadata for the farm, which can be accessed in C# code via <tt>Game1.GetFarmTypeModData(key)</tt>.
+
| ''(optional)'' A string→string dictionary of mod-specific metadata for the farm, which can be accessed in C# code via <samp>Game1.GetFarmTypeModData(key)</samp>.
 
|}
 
|}
   Line 162: Line 245:  
             "Target": "Data/AdditionalFarms",
 
             "Target": "Data/AdditionalFarms",
 
             "Entries": {
 
             "Entries": {
                 "Pathoschild.PineappleFarm/PineappleFarm": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
+
                 "ExampleAuthor.PineappleFarm/PineappleFarm": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
                     "ID": "Pathoschild.PineappleFarm/PineappleFarm",
+
                     "ID": "ExampleAuthor.PineappleFarm/PineappleFarm",
                     "TooltipStringPath": "Strings/UI:Pathoschild_PineappleFarm",
+
                     "TooltipStringPath": "Strings/UI:ExampleAuthor_PineappleFarm",
                     "MapName": "Pathoschild_PineappleFarm",
+
                     "MapName": "ExampleAuthor_PineappleFarm",
                     "IconTexture": "Mods/Pathoschild.PineappleFarm/Icon",
+
                     "IconTexture": "Mods/ExampleAuthor.PineappleFarm/Icon",
                     "WorldMapTexture": "Mods/Pathoschild.PineappleFarm/WorldMap"
+
                     "WorldMapTexture": "Mods/ExampleAuthor.PineappleFarm/WorldMap"
 
                 }
 
                 }
 
             }
 
             }
Line 177: Line 260:  
             "Target": "Strings/UI",
 
             "Target": "Strings/UI",
 
             "Entries": {
 
             "Entries": {
                 "Pathoschild_PineappleFarm": "Pineapple Farm_A farm shaped like a pineapple!" // tip: use <nowiki>{{i18n}}</nowiki> to translate it
+
                 "ExampleAuthor_PineappleFarm": "Pineapple Farm_A farm shaped like a pineapple!" // tip: use <nowiki>{{i18n}}</nowiki> to translate it
 
             }
 
             }
 
         },
 
         },
Line 184: Line 267:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Maps/Pathoschild_PineappleFarm",
+
             "Target": "Maps/ExampleAuthor_PineappleFarm",
 
             "FromFile": "assets/map.tmx"
 
             "FromFile": "assets/map.tmx"
 
         },
 
         },
Line 191: Line 274:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Mods/Pathoschild.PineappleFarm/Icon, Mods/Pathoschild.PineappleFarm/WorldMap",
+
             "Target": "Mods/ExampleAuthor.PineappleFarm/Icon, Mods/ExampleAuthor.PineappleFarm/WorldMap",
 
             "FromFile": "assets/<nowiki>{{TargetWithoutPath}}</nowiki>.png"
 
             "FromFile": "assets/<nowiki>{{TargetWithoutPath}}</nowiki>.png"
 
         }
 
         }
Line 198: Line 281:     
===Custom languages===
 
===Custom languages===
You can now add custom languages by editing the <tt>Data/AdditionalLanguages</tt> asset. Each entry consists of an object with these fields:
+
{{main article|Modding:Custom languages}}
 +
 
 +
You can now add custom languages by editing the <samp>Data/AdditionalLanguages</samp> asset. Each entry consists of an object with these fields:
    
{| class="wikitable"
 
{| class="wikitable"
Line 205: Line 290:  
! description
 
! description
 
|-
 
|-
| <tt>ID</tt>
+
| <samp>ID</samp>
 
| A unique ID value. This is not shown in-game.
 
| A unique ID value. This is not shown in-game.
 
|-
 
|-
| <tt>LanguageCode</tt>
+
| <samp>LanguageCode</samp>
| The language code for this localization. This should ideally be a [[wikipedia:List of ISO 639-1 codes|ISO 639-1 code]]. You should avoid commas for compatibility with Content Patcher packs checking the <tt><nowiki>{{Language}}</nowiki></tt> token.
+
| The language code for this localization. This should ideally be a [[wikipedia:List of ISO 639-1 codes|ISO 639-1 code]]. You should avoid commas for compatibility with Content Patcher packs checking the <samp><nowiki>{{Language}}</nowiki></samp> token.
 
|-
 
|-
| <tt>ButtonTexture</tt>
+
| <samp>ButtonTexture</samp>
 
| The asset name for a 174x78 pixel texture containing the button of the language for language selection menu. The top half of the sprite is the default state, while the bottom half is the hover state.
 
| The asset name for a 174x78 pixel texture containing the button of the language for language selection menu. The top half of the sprite is the default state, while the bottom half is the hover state.
 
|-
 
|-
| <tt>UseLatinFont</tt>
+
| <samp>UseLatinFont</samp>
| Whether the language uses the same Latin character font as English. If set to <tt>false</tt>, you must set the next field.
+
| Whether the language uses the same Latin character font as English. If set to <samp>false</samp>, you must set the <samp>FontFile</samp> field.
 
|-
 
|-
| <tt>FontFile</tt>
+
| <samp>TimeFormat</samp>
| ''(optional)'' The asset name for the font file to use (if <tt>UseLatinFont</tt> is <tt>false</tt>).
  −
|-
  −
| <tt>FontPixelZoom</tt>
  −
| ''(optional)'' A factor by while to multiply the font size.
  −
|-
  −
| <tt>FontApplyYOffset</tt>
  −
| ''(optional)'' Whether to shift the font up by four pixels (multiplied by the <tt>FontPixelZoom</tt>), to better align languages with larger characters like Chinese and Japanese.
  −
|-
  −
| <tt>SmallFontLineSpacing</tt>
  −
| ''(optional)'' The line spacing value used by <tt>smallFont</tt>. Defaults to 26.
  −
|-
  −
| <tt>TimeFormat</tt>
   
| A string which describes the in-game time format, with tokens replaced by in-game values. For example, <code>[HOURS_12]:[MINUTES] [AM_PM]</code> would show <code>12:00 PM</code> at noon.
 
| A string which describes the in-game time format, with tokens replaced by in-game values. For example, <code>[HOURS_12]:[MINUTES] [AM_PM]</code> would show <code>12:00 PM</code> at noon.
   Line 240: Line 313:  
* <code>[AM_PM]</code>: the localized text for "am" or "pm" (taken from <code>Strings\\StringsFromCSFiles:DayTimeMoneyBox.cs.10370</code> and <code>DayTimeMoneyBox.cs.10371</code> respectively). The game shows "pm" between noon and 11:59pm inclusively; it shows "am" otherwise.
 
* <code>[AM_PM]</code>: the localized text for "am" or "pm" (taken from <code>Strings\\StringsFromCSFiles:DayTimeMoneyBox.cs.10370</code> and <code>DayTimeMoneyBox.cs.10371</code> respectively). The game shows "pm" between noon and 11:59pm inclusively; it shows "am" otherwise.
 
|-
 
|-
| <tt>ClockTimeFormat</tt>
+
| <samp>ClockTimeFormat</samp>
| A string which describes the in-game time format. Equivalent to <tt>TimeFormat</tt>, but used for the in-game clock.
+
| A string which describes the in-game time format. Equivalent to <samp>TimeFormat</samp>, but used for the in-game clock.
 
|-
 
|-
| <tt>ClockDateFormat</tt>
+
| <samp>ClockDateFormat</samp>
 
| A string which describes the in-game date format as shown in the in-game clock, with tokens replaced by in-game values. For example, <code>[DAY_OF_WEEK]. [DAY_OF_MONTH]</code> would show <code>Mon. 1</code>.
 
| A string which describes the in-game date format as shown in the in-game clock, with tokens replaced by in-game values. For example, <code>[DAY_OF_WEEK]. [DAY_OF_MONTH]</code> would show <code>Mon. 1</code>.
    
The valid tokens are:
 
The valid tokens are:
* <code>[DAY_OF_WEEK]</code>: the abbreviated day of week as returned by <code>Game1.shortDayDisplayNameFromDayOfSeason</code> (like <tt>Mon</tt> for Monday).
+
* <code>[DAY_OF_WEEK]</code>: the abbreviated day of week as returned by <code>Game1.shortDayDisplayNameFromDayOfSeason</code> (like <samp>Mon</samp> for Monday).
 
* <code>[DAY_OF_MONTH]</code>: the numerical day of the month.
 
* <code>[DAY_OF_MONTH]</code>: the numerical day of the month.
 +
|-
 +
| <samp>FontFile</samp>
 +
| ''(optional)'' The asset name for the font file to use (if <samp>UseLatinFont</samp> is <samp>false</samp>).
 +
|-
 +
| <samp>FontPixelZoom</samp>
 +
| ''(optional)'' A factor by while to multiply the font size.
 +
|-
 +
| <samp>FontApplyYOffset</samp>
 +
| ''(optional)'' Whether to shift the font up by four pixels (multiplied by the <samp>FontPixelZoom</samp>), to better align languages with larger characters like Chinese and Japanese.
 +
|-
 +
| <samp>NumberComma</samp>
 +
| ''(optional)'' The string to use as the thousands separator (''e.g.,'' <code>","</code> for <code>5,000,000</code>). Defaults to a comma.
 +
|-
 +
| <samp>SmallFontLineSpacing</samp>
 +
| ''(optional)'' The line spacing value used by <samp>smallFont</samp>. Defaults to 26.
 +
|-
 +
| <samp>UseGenderedCharacterTranslations</samp>
 +
| ''(optional)'' Whether the social tab and gift log will use gender-specific translations (like the vanilla Portuguese language). Defaults to false.
 +
 +
Specifically, this affects the <samp>Strings\StringsFromCSFiles:SocialPage.cs.11635</samp> translation ("''(Single)''"). When enabled, it can contain male and female translations separated by <code>/</code>, like the vanilla Portuguese translation: "''(solteiro)/(solteira)''".
 
|}
 
|}
   Line 261: Line 354:  
             "Target": "Data/AdditionalLanguages",
 
             "Target": "Data/AdditionalLanguages",
 
             "Entries": {
 
             "Entries": {
                 "Pathoschild.Esperanto": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
+
                 "ExampleAuthor.Esperanto": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
                     "ID": "Pathoschild.Esperanto",
+
                     "ID": "ExampleAuthor.Esperanto",
 
                     "LanguageCode": "eo",
 
                     "LanguageCode": "eo",
                     "ButtonTexture": "Mods/Pathoschild.Esperanto/Button",
+
                     "ButtonTexture": "Mods/ExampleAuthor.Esperanto/Button",
 
                     "UseLatinFont": true,
 
                     "UseLatinFont": true,
 
                     "TimeFormat": "[HOURS_24_00]:[MINUTES]",
 
                     "TimeFormat": "[HOURS_24_00]:[MINUTES]",
Line 276: Line 369:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Mods/Pathoschild.Esperanto/Button",
+
             "Target": "Mods/ExampleAuthor.Esperanto/Button",
 
             "FromFile": "assets/button.png"
 
             "FromFile": "assets/button.png"
 
         }
 
         }
Line 299: Line 392:     
===Custom festival location names===
 
===Custom festival location names===
The location name in the festival-started message (e.g. "''The Luau has begun on the beach''") was previously hardcoded, so it would always show the internal name for non-vanilla festival locations. You can now add a <tt>locationDisplayName</tt> field in the <tt>Data/Festivals/*</tt> file to set the display name.
+
The location name in the festival-started message (''e.g.,'' "''The Luau has begun on the beach''") was previously hardcoded, so it would always show the internal name for non-vanilla festival locations. You can now add a <samp>locationDisplayName</samp> field in the <samp>Data/Festivals/*</samp> file to set the display name.
    
===Custom spouse rooms===
 
===Custom spouse rooms===
 
Adding spouse rooms for custom NPCs is now much easier.  
 
Adding spouse rooms for custom NPCs is now much easier.  
 
<ul>
 
<ul>
<li>You can edit the <tt>Data/SpouseRooms</tt> asset to add the spouse room info in this format: <code>"{{t|NPC name}}": "{{t|map name}}/{{t|map index}}"</code>.
+
<li>You can edit the <samp>Data/SpouseRooms</samp> asset to add the spouse room info in this format: <code>"{{t|NPC name}}": "{{t|map name}}/{{t|map index}}"</code>.
    
{| class="wikitable"
 
{| class="wikitable"
Line 312: Line 405:  
|-
 
|-
 
| <code>{{t|NPC name}}</code>
 
| <code>{{t|NPC name}}</code>
| The internal name of the NPC (i.e. their key in <tt>Data/NPCDispositions</tt>).
+
| The internal name of the NPC (''i.e.,'' their key in <samp>Data/NPCDispositions</samp>).
 
|-
 
|-
 
| <code>{{t|map name}}</code>
 
| <code>{{t|map name}}</code>
| The asset name of the map in the game's <tt>Content/Maps</tt> folder. This can be a custom map loaded through Content Patcher's <tt>Load</tt> action or SMAPI's <tt>IAssetLoader</tt> API.
+
| The asset name of the map in the game's <samp>Content/Maps</samp> folder. This can be a custom map loaded through Content Patcher's <samp>Load</samp> action or SMAPI's <samp>IAssetLoader</samp> API.
 
|-
 
|-
 
| <code>{{t|map index}}</code>
 
| <code>{{t|map index}}</code>
 
| The index of the spouse room within the map file, to allow multiple spouse rooms in the same file. Each spouse room is 6 tiles across by 9 tiles down, starting with index 0 in the top-left corner. You can have any number of rows and columns (the index will wrap at the end of the row), as long as they fit an integer number of spouse rooms.
 
| The index of the spouse room within the map file, to allow multiple spouse rooms in the same file. Each spouse room is 6 tiles across by 9 tiles down, starting with index 0 in the top-left corner. You can have any number of rows and columns (the index will wrap at the end of the row), as long as they fit an integer number of spouse rooms.
 
|}</li>
 
|}</li>
<li>You can mark where the spouse stands in their spouse room by placing the red circle path tile (tile index 7) on [[Modding:Maps#Paths layer|the <tt>Paths</tt> layer]].</li>
+
<li>You can mark where the spouse stands in their spouse room by placing the red circle path tile (tile index 7) on [[Modding:Maps#Paths layer|the <samp>Paths</samp> layer]].</li>
 
<li>The spouse room maps are now applied using the game's newer map override system, so tile properties and custom tilesheets in the spouse room map are copied over automatically.</li>
 
<li>The spouse room maps are now applied using the game's newer map override system, so tile properties and custom tilesheets in the spouse room map are copied over automatically.</li>
<li>Some of the game's spouse room code (e.g. positions for Sebastian's 14-heart frog terrarium) was updated to potentially allow moving spouse rooms around. However, some things like event positions are still hardcoded and will need to be fixed to fully support this feature.</li>
+
<li>Some of the game's spouse room code (''e.g.,'' positions for Sebastian's 14-heart frog terrarium) was updated to potentially allow moving spouse rooms around. However, some things like event positions are still hardcoded and will need to be fixed to fully support this feature.</li>
 
</ul>
 
</ul>
 +
 +
For example, this Content Patcher pack would add a spouse room for a new Akila NPC:
 +
{{#tag:syntaxhighlight|
 +
{
 +
    "Format": "{{Content Patcher version}}",
 +
    "Changes": [
 +
        // register spouse room
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/SpouseRooms",
 +
            "Entries": {
 +
                "Akila": "ExampleAuthor_ExampleAkilaMod_SpouseRoom/0"
 +
            }
 +
        },
 +
 +
        // load spouse room map
 +
        {
 +
            "Action": "Load",
 +
            "Target": "Maps/ExampleAuthor_ExampleAkilaMod_SpouseRoom",
 +
            "FromFile": "assets/spouse-room.tmx"
 +
        }
 +
    ]
 +
}|lang=javascript}}
    
===Custom spouse outside areas===
 
===Custom spouse outside areas===
You can now customize the [[Marriage#Spouse Outside Area|spouse outside area]] for any NPC by editing <tt>Data/SpousePatios</tt>, which has four slash-delimited fields:
+
You can now customize the [[Marriage#Spouse Outside Area|spouse outside area]] for any NPC by editing <samp>Data/SpousePatios</samp>, which has four slash-delimited fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 332: Line 448:  
! effect
 
! effect
 
|-
 
|-
| <tt>map asset name</tt>
+
| <samp>map asset name</samp>
| The asset name relative to the <tt>Content/Maps</tt> folder which contains the spouse area map. The map must contain one or more 4x4 tile areas, with any number of rows and columns.
+
| The asset name relative to the <samp>Content/Maps</samp> folder which contains the spouse area map. The map must contain one or more 4x4 tile areas, with any number of rows and columns.
 
|-
 
|-
| <tt>index</tt>
+
| <samp>index</samp>
 
| The index (starting at zero) within the map for the 4x4 area to use as the outdoor area.
 
| The index (starting at zero) within the map for the 4x4 area to use as the outdoor area.
 
|-
 
|-
| <tt>NPC animation frames</tt>
+
| <samp>NPC animation frames</samp>
 
| ''(Optional)'' The spouse's animation frames, as a sequence of space-delimited frame indexes in their sprite's spritesheet each lasting 100 milliseconds. If not set, vanilla spouses will use their hardcoded animations and custom spouses won't be animated.
 
| ''(Optional)'' The spouse's animation frames, as a sequence of space-delimited frame indexes in their sprite's spritesheet each lasting 100 milliseconds. If not set, vanilla spouses will use their hardcoded animations and custom spouses won't be animated.
 
|-
 
|-
| <tt>{{t|NPC offset X}} {{t|NPC offset Y}}</tt>
+
| <samp>{{t|NPC offset X}} {{t|NPC offset Y}}</samp>
 
| ''(Optional)'' A pixel X and Y offset applied to the NPC's position when they're in their outdoor area.
 
| ''(Optional)'' A pixel X and Y offset applied to the NPC's position when they're in their outdoor area.
 
|}
 
|}
   −
For example, <code>"Abigail": "spousePatios/0/16 16 16 16 17 17 17 17 17 17 18 18 18 18 18 19 19 19 19 19/1 5"</code> sets Abigail's outdoor area to the first one defined in the <tt>Maps/spousePatios</tt> asset, cycles her sprite through spritesheet indexes 16&ndash;19 for 500 milliseconds each, and offsets her 1 pixel to the right and 5 pixels down in the outdoor area.
+
You can mark where the spouse stands in their spouse area by placing the red circle path tile (tile index 7) on [[Modding:Maps#Paths layer|the <samp>Paths</samp> layer]].
 +
 
 +
For example, this Content Patcher pack would add the outside area for a new Akila NPC. When in the outside area, their sprite would cycle through spritesheet indexes 16&ndash;19 for 300 milliseconds each, and be offset by 1 pixel to the right and 5 pixels down.
 +
{{#tag:syntaxhighlight|
 +
{
 +
    "Format": "{{Content Patcher version}}",
 +
    "Changes": [
 +
        // register outside area
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/SpousePatios",
 +
            "Entries": {
 +
                "Akila": "ExampleAuthor_ExampleAkilaMod_OutsideArea/0/16 16 16 17 17 17 18 18 18 19 19 19/1 5"
 +
            }
 +
        },
 +
 
 +
        // load spouse map
 +
        {
 +
            "Action": "Load",
 +
            "Target": "Maps/ExampleAuthor_ExampleAkilaMod_OutsideArea",
 +
            "FromFile": "assets/outside-area.tmx"
 +
        }
 +
    ]
 +
}|lang=javascript}}
    
===Custom farmhouse renovations===
 
===Custom farmhouse renovations===
Line 357: Line 496:  
|-
 
|-
 
| farmhouse
 
| farmhouse
| <tt>AdditionalRenovations {{t|renovation}}+</tt>
+
| <samp>AdditionalRenovations {{t|renovation}}+</samp>
| A comma-separated list of renovations to apply, each in the form <tt>{{t|map patch ID}} {{t|required mail flag}} {{t|map asset if active}} {{t|map asset if inactive}} {{o|area rectangle}}</tt>. Fields:
+
| A comma-separated list of renovations to apply, each in the form <samp>{{t|map patch ID}} {{t|required mail flag}} {{t|map asset if active}} {{t|map asset if inactive}} {{o|area rectangle}}</samp>. Fields:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 364: Line 503:  
! effect
 
! effect
 
|-
 
|-
| <tt>map patch ID</tt>
+
| <samp>map patch ID</samp>
 
| A unique ID for the patch being applied. This is usually similar to the renovation name, but can be any unique value. If a renovation applies multiple map patches, each one must have unique ID.
 
| A unique ID for the patch being applied. This is usually similar to the renovation name, but can be any unique value. If a renovation applies multiple map patches, each one must have unique ID.
 
|-
 
|-
| <tt>required mail flag</tt>
+
| <samp>required mail flag</samp>
 
| The [[Modding:Mail data#Mail flags|mail flag]] that is checked on the house's owner  to decide whether the patch should be applied.
 
| The [[Modding:Mail data#Mail flags|mail flag]] that is checked on the house's owner  to decide whether the patch should be applied.
 
|-
 
|-
| <tt>map asset if active</tt>
+
| <samp>map asset if active</samp>
| The asset name for the map applied when the mail flag is set, relative to the <tt>Maps</tt> folder.
+
| The asset name for the map applied when the mail flag is set, relative to the <samp>Maps</samp> folder.
 
|-
 
|-
| <tt>map asset if inactive</tt>
+
| <samp>map asset if inactive</samp>
| The asset name for the map applied when the mail flag is not set, relative to the <tt>Maps</tt> folder.
+
| The asset name for the map applied when the mail flag is not set, relative to the <samp>Maps</samp> folder.
 
|-
 
|-
| <tt>area rectangle</tt>
+
| <samp>area rectangle</samp>
| ''(Optional)'' The tile area in the map to patch, specified as <tt>{{t|X}} {{t|Y}} {{t|width}} {{t|height}}</tt>. If {{t|X}} isn't set, this defaults to the top-left corner of the map. If it is, you must specify all four values.
+
| ''(Optional)'' The tile area in the map to patch, specified as <samp>{{t|X}} {{t|Y}} {{t|width}} {{t|height}}</samp>. If {{t|X}} isn't set, this defaults to the top-left corner of the map. If it is, you must specify all four values.
 
|}
 
|}
 
|}
 
|}
   −
For example, this Content Patcher pack would add a renovation to the fully-upgraded farmhouse based on a custom <tt>Pathoschild_PineapplesEverywhere_HasRenovation</tt> flag. Note that <tt>TextOperations</tt> is used to avoid overwriting any renovations added by another mod, and <tt>Pathoschild_PineapplesEverywhere_</tt> is a unique prefix for the hypothetical mod to avoid conflicts with other mods.
+
For example, this Content Patcher pack would add a renovation to the fully-upgraded farmhouse based on a custom <samp>ExampleAuthor_PineapplesEverywhere_HasRenovation</samp> flag. Note that <samp>TextOperations</samp> is used to avoid overwriting any renovations added by another mod, and <samp>ExampleAuthor_PineapplesEverywhere_</samp> is a unique prefix for the hypothetical mod to avoid conflicts with other mods.
 
{{#tag:syntaxhighlight|
 
{{#tag:syntaxhighlight|
 
{
 
{
Line 394: Line 533:  
                     "Operation": "Append",
 
                     "Operation": "Append",
 
                     "Target": [ "MapProperties", "AdditionalRenovations" ],
 
                     "Target": [ "MapProperties", "AdditionalRenovations" ],
                     "Value": "Pathoschild_PineapplesEverywhere_KitchenUpgrade Pathoschild_PineapplesEverywhere_HasRenovation Pathoschild_PineapplesEverywhere_Kitchen Pathoschild_PineapplesEverywhere_Empty 0 19 3 3",
+
                     "Value": "ExampleAuthor_PineapplesEverywhere_KitchenUpgrade ExampleAuthor_PineapplesEverywhere_HasRenovation ExampleAuthor_PineapplesEverywhere_Kitchen ExampleAuthor_PineapplesEverywhere_Empty 0 19 3 3",
 
                     "Delimiter": "," // if there are already renovations, add a comma before this one
 
                     "Delimiter": "," // if there are already renovations, add a comma before this one
 
                 }
 
                 }
Line 403: Line 542:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Maps/Pathoschild_PineapplesEverywhere_Kitchen",
+
             "Target": "Maps/ExampleAuthor_PineapplesEverywhere_Kitchen",
 
             "FromFile": "assets/kitchen-upgrade.tmx"
 
             "FromFile": "assets/kitchen-upgrade.tmx"
 
         },
 
         },
Line 410: Line 549:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Maps/Pathoschild_PineapplesEverywhere_Empty",
+
             "Target": "Maps/ExampleAuthor_PineapplesEverywhere_Empty",
 
             "FromFile": "assets/kitchen-upgrade-empty.tmx"
 
             "FromFile": "assets/kitchen-upgrade-empty.tmx"
 
         }
 
         }
Line 429: Line 568:  
|-
 
|-
 
| ''decoratable locations''
 
| ''decoratable locations''
| <tt>FloorIDs {{o|area}}+</tt><br /><tt>WallIDs {{o|area}}+</tt><br />
+
| <samp>FloorIDs {{o|area}}+</samp><br /><samp>WallIDs {{o|area}}+</samp><br />
| A comma-separated list of the distinct areas which have flooring or walls. The <tt>FloorIDs</tt> and <tt>WallIDs</tt> don't need to match. Each area has the form <code>{{t|area ID}} {{o|default flooring/wallpaper ID}}</code>, where:
+
| A comma-separated list of the distinct areas which have flooring or walls. The <samp>FloorIDs</samp> and <samp>WallIDs</samp> don't need to match. Each area has the form <code>{{t|area ID}} {{o|default flooring/wallpaper ID}}</code>, where:
* <tt>{{t|area ID}}</tt> uniquely identifies the area or room.
+
* <samp>{{t|area ID}}</samp> uniquely identifies the area or room.
* <tt>{{o|default flooring/wallpaper ID}}</tt> (optional) sets the initial flooring/wallpaper ID if that area hasn't been customized by the player yet. This can be defined in three forms:
+
* <samp>{{o|default flooring/wallpaper ID}}</samp> (optional) sets the initial flooring/wallpaper ID if that area hasn't been customized by the player yet. This can be defined in three forms:
** <code>{{t|index}}</code>: get the floor/wallpaper matching that index in the vanilla <tt>Maps/walls_and_floors</tt> tilesheet.
+
** <code>{{t|index}}</code>: get the floor/wallpaper matching that index in the vanilla <samp>Maps/walls_and_floors</samp> tilesheet.
** <code>{{t|tilesheet}}:{{t|index}}</code>: add <tt>Maps/{{t|tilesheet}}</tt> to the map, and match the index in that tilesheet.
+
** <code>{{t|tilesheet}}:{{t|index}}</code>: add <samp>Maps/{{t|tilesheet}}</samp> to the map, and match the index in that tilesheet.
** <code>{{t|area ID}}</code>: inherit the default floor/wallpaper from the named area. For example, <tt>Hallway_Bedroom Bedroom</tt> applies the bedroom wallpaper to the hallway between the bedroom and living room when the farmhouse is first upgraded.
+
** <code>{{t|area ID}}</code>: inherit the default floor/wallpaper from the named area. For example, <samp>Hallway_Bedroom Bedroom</samp> applies the bedroom wallpaper to the hallway between the bedroom and living room when the farmhouse is first upgraded.
 
** If omitted, the default will be flooring/wallpaper #0.
 
** If omitted, the default will be flooring/wallpaper #0.
   Line 441: Line 580:  
WallIDs: LivingRoom, Hallway_Bedroom Bedroom, Bedroom</pre>
 
WallIDs: LivingRoom, Hallway_Bedroom Bedroom, Bedroom</pre>
   −
You don't need to add every area to the <tt>FloorIDs</tt>/<tt>WallIDs</tt> list; assigning a flooring/wall to an unlisted value will be handled correctly. You only really need to add an area to <tt>FloorIDs</tt>/<tt>WallIDs</tt> to set the default flooring/wallpaper value, or for cases where the order of the walls/floors is important (for backwards compatibility with code that sets wallpaper/flooring by an integer room index, as is the case with the floors/walls in the vanilla farmhouse).
+
You don't need to add every area to the <samp>FloorIDs</samp>/<samp>WallIDs</samp> list; assigning a flooring/wall to an unlisted value will be handled correctly. You only really need to add an area to <samp>FloorIDs</samp>/<samp>WallIDs</samp> to set the default flooring/wallpaper value, or for cases where the order of the walls/floors is important (for backwards compatibility with code that sets wallpaper/flooring by an integer room index, as is the case with the floors/walls in the vanilla farmhouse).
 
|}
 
|}
   Line 452: Line 591:  
! effect
 
! effect
 
|-
 
|-
| <tt>Back</tt>
+
| <samp>Back</samp>
| <tt>WallID {{t|area ID}}</tt><br /><tt>FloorID {{t|area ID}}</tt>
+
| <samp>WallID {{t|area ID}}</samp><br /><samp>FloorID {{t|area ID}}</samp>
| Adds this tile to the given floor/wall area. Each floor tile should have the <tt>FloorID</tt> property, but only the top edge of the wall should have <tt>WallID</tt>.
+
| Adds this tile to the given floor/wall area. Each floor tile should have the <samp>FloorID</samp> property, but only the top edge of the wall should have <samp>WallID</samp>.
 
|}
 
|}
    
====In the furniture catalogue====
 
====In the furniture catalogue====
You can also add new flooring/wallpaper options to the furniture catalogue by adding it to <tt>Data/AdditionalWallpaperFlooring</tt>. Each entry consists of an object with these fields:
+
You can also add new flooring/wallpaper options to the furniture catalogue by adding it to <samp>Data/AdditionalWallpaperFlooring</samp>. Each entry consists of an object with these fields:
    
{| class="wikitable"
 
{| class="wikitable"
Line 465: Line 604:  
! description
 
! description
 
|-
 
|-
| <tt>ID</tt>
+
| <samp>ID</samp>
 
| A unique ID value. This is not shown in-game.
 
| A unique ID value. This is not shown in-game.
 
|-
 
|-
| <tt>Texture</tt>
+
| <samp>Texture</samp>
 
| The asset name which contains 32x32 pixel (flooring) or 16x48 pixel (wallpaper) sprites. The tilesheet must be 256 pixels wide, but can have any number of flooring/wallpaper rows.
 
| The asset name which contains 32x32 pixel (flooring) or 16x48 pixel (wallpaper) sprites. The tilesheet must be 256 pixels wide, but can have any number of flooring/wallpaper rows.
 
|-
 
|-
| <tt>IsFlooring</tt>
+
| <samp>IsFlooring</samp>
 
| Whether this is a flooring tilesheet; else it's a wallpaper tilesheet.
 
| Whether this is a flooring tilesheet; else it's a wallpaper tilesheet.
 
|-
 
|-
| <tt>Count</tt>
+
| <samp>Count</samp>
 
| The number of flooring or wallpaper sprites in the tilesheet.
 
| The number of flooring or wallpaper sprites in the tilesheet.
 
|}
 
|}
Line 488: Line 627:  
             "Target": "Data/AdditionalWallpaperFlooring",
 
             "Target": "Data/AdditionalWallpaperFlooring",
 
             "Entries": {
 
             "Entries": {
                 "Pathoschild.CustomWallpapers": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
+
                 "ExampleAuthor.CustomWallpapers": { // for technical reasons, you need to specify the ID here *and* in the "ID" field
                     "ID": "Pathoschild.CustomWallpapers",
+
                     "ID": "ExampleAuthor.CustomWallpapers",
                     "Texture": "Mods/Pathoschild.CustomWallpapers/Wallpapers",
+
                     "Texture": "Mods/ExampleAuthor.CustomWallpapers/Wallpapers",
 
                     "IsFlooring": false,
 
                     "IsFlooring": false,
 
                     "Count": 3
 
                     "Count": 3
Line 500: Line 639:  
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Mods/Pathoschild.CustomWallpapers/Wallpapers",
+
             "Target": "Mods/ExampleAuthor.CustomWallpapers/Wallpapers",
 
             "FromFile": "assets/wallpapers.png"
 
             "FromFile": "assets/wallpapers.png"
 
         }
 
         }
Line 507: Line 646:     
===Map property changes===
 
===Map property changes===
 +
{{main article|Modding:Maps#Known_properties}}
 
Stardew Valley 1.5.5 adds several map properties (in addition to those listed in their own sections):
 
Stardew Valley 1.5.5 adds several map properties (in addition to those listed in their own sections):
   Line 516: Line 656:  
|-
 
|-
 
| ''any''
 
| ''any''
| <tt>ForceAllowTreePlanting T</tt>
+
| <samp>AllowGrassGrowInWinter T</samp>
| Whether to allow planting trees (both wild and fruit) in this location, even if it normally wouldn't be allowed.
+
| Allows [[grass]] to spread in winter.
 +
|-
 +
| ''any''
 +
| <samp>AllowGrassSurviveInWinter T</samp>
 +
| Allows [[grass]] that's alive on the last day of fall to survive through to winter.
 +
|-
 +
| ''any''
 +
| <samp>ClearEmptyDirtOnNewMonth T</samp>
 +
| Destroy most tilled dirt that doesn't contain crops when a new year starts.
 +
|-
 +
| ''any''
 +
| <samp>EnableGrassSpread T</samp>
 +
| Gives [[grass]] in the location a chance to spread each day.
 +
|-
 +
| ''any''
 +
| <samp>ForceAllowTreePlanting T</samp>
 +
| Allows planting trees (both wild and fruit) in this location, even if it normally wouldn't be allowed.
 +
|-
 +
| ''any''
 +
| <samp>IsFarm T</samp>
 +
| Marks the location as a farm. This only affects generic location/interaction logic which checks the in-code <code>location.IsFarm</code> property; logic hardcoded into the game's <code>Farm</code> class (''e.g.,'' farm animals, pets, crows/scarecrows, greenhouse, farm buildings, etc) is still limited to the actual farm.
 +
|-
 +
| ''any''
 +
| <samp>IsGreenhouse T</samp>
 +
| Marks the location as a greenhouse.
 
|-
 
|-
 
| ''any''
 
| ''any''
| <tt>IsFarm T</tt>
+
| <samp>SpawnGrassFromPathsOnNewYear T</samp>
| Whether to mark the location as a farm. This only affects generic location/interaction logic which checks the in-code <code>location.IsFarm</code> property; logic hardcoded into the game's <code>Farm</code> class (e.g. farm animals, pets, crows/scarecrows, greenhouse, farm buildings, etc) is still limited to the actual farm.
+
| Spawns grass on every tile with index 22 on the <samp>Paths</samp> layer when a new year starts. See also <samp>SpawnRandomGrassOnNewYear</samp>.
 
|-
 
|-
 
| ''any''
 
| ''any''
| <tt>IsGreenhouse T</tt>
+
| <samp>SpawnDebrisOnNewMonth T</samp><br /><samp>SpawnDebrisOnNewYear T</samp>
| Whether to mark the location as a greenhouse.
+
| Spawns weeds, stones, or twigs at random positions when a new month/year starts (subject to their usual spawn rules).
 +
|-
 +
| ''any''
 +
| <samp>SpawnRandomGrassOnNewYear T</samp>
 +
| Spawns grass at random positions when a new year starts (subject to its usual spawn rules). See also <samp>SpawnGrassFromPathsOnNewYear</samp>.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmFishLocationOverride {{t|location name}} {{t|chance}}</tt>
+
| <samp>FarmFishLocationOverride {{t|location name}} {{t|chance}}</samp>
| Adds an alternative location name when catching fish, where the {{t|chance}} is a decimal value between 0 (never happens) and 1 (always happens). For example, <tt>FarmFishLocationOverride Mountain 0.5</tt> adds a 50% chance of catching mountain fish instead of the normal fish for that location. The location name is case-sensitive, and matches those shown by the {{nexus mod|679|Debug Mode mod}}.
+
| Adds an alternative location name when catching fish, where the {{t|chance}} is a decimal value between 0 (never happens) and 1 (always happens). For example, <samp>FarmFishLocationOverride Mountain 0.5</samp> adds a 50% chance of catching mountain fish instead of the normal fish for that location. The location name is case-sensitive, and matches those shown by the {{nexus mod|679|Debug Mode mod}}.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmHouseFurniture [{{t|furniture ID}} {{t|tile X}} {{t|tile Y}} {{t|rotations}}]+</tt>
+
| <samp>FarmHouseFurniture [{{t|furniture ID}} {{t|tile X}} {{t|tile Y}} {{t|rotations}}]+</samp>
| Spawns initial furniture in the farmhouse when creating a new save. If you add multiple furniture to the same tile, the first one will be placed on the ground and the last one will be placed on the first one.<br />This is also required to enable the <tt>FarmHouseWallpaper</tt>, <tt>FarmHouseFlooring</tt>, and <tt>FarmHouseStarterSeedsPosition</tt> properties. You can enable it without spawning any furniture with <tt>FarmHouseFurniture -1 0 0 0</tt>.
+
| Spawns initial furniture in the farmhouse when creating a new save. If you add multiple furniture to the same tile, the first one will be placed on the ground and the last one will be placed on the first one.<br />This is also required to enable the <samp>FarmHouseWallpaper</samp>, <samp>FarmHouseFlooring</samp>, and <samp>FarmHouseStarterSeedsPosition</samp> properties. You can enable it without spawning any furniture with <samp>FarmHouseFurniture -1 0 0 0</samp>.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmHouseFlooring {{t|flooring id}}</tt>
+
| <samp>FarmHouseFlooring {{t|flooring id}}</samp>
| Sets the initial farmhouse floor to the given ID when creating a new save. These are mapped to the 4x4 tile areas in the <tt>Maps/walls_and_floors</tt> tilesheet starting at tile index 336 (where index 0 is mapped to the top-left square).<br />This is only enabled if <tt>FarmHouseFurniture</tt> is set.
+
| Sets the initial farmhouse floor to the given ID when creating a new save. These are mapped to the 4x4 tile areas in the <samp>Maps/walls_and_floors</samp> tilesheet starting at tile index 336 (where index 0 is mapped to the top-left square).<br />This is only enabled if <samp>FarmHouseFurniture</samp> is set.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmHouseWallpaper {{t|wallpaper id}}</tt>
+
| <samp>FarmHouseWallpaper {{t|wallpaper id}}</samp>
| Sets the initial farmhouse wallpaper to the given ID when creating a new save. These are mapped to the 1x4 tile areas in the <tt>Maps/walls_and_floors</tt> tilesheet starting from the top-left.<br />This is only enabled if <tt>FarmHouseFurniture</tt> is set.
+
| Sets the initial farmhouse wallpaper to the given ID when creating a new save. These are mapped to the 1x4 tile areas in the <samp>Maps/walls_and_floors</samp> tilesheet starting from the top-left.<br />This is only enabled if <samp>FarmHouseFurniture</samp> is set.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmHouseStarterSeedsPosition {{t|tile X}} {{t|tile Y}}</tt>
+
| <samp>FarmHouseStarterSeedsPosition {{t|tile X}} {{t|tile Y}}</samp>
| Sets the tile position in the farmhouse where the seed package is placed when creating a new save.<br />This is only enabled if <tt>FarmHouseFurniture</tt> is set.
+
| Sets the tile position in the farmhouse where the seed package is placed when creating a new save.<br />This is only enabled if <samp>FarmHouseFurniture</samp> is set.
 
|-
 
|-
 
| farm
 
| farm
| <tt>FarmOceanCrabPotOverride T</tt>
+
| <samp>FarmOceanCrabPotOverride T</samp>
| Whether crab pots on the farm should catch ocean fish.
+
| Causes crab pots on the farm should catch ocean fish.
 
|-
 
|-
 
| farm
 
| farm
| <tt>SpawnBeachFarmForage T</tt>
+
| <samp>SpawnBeachFarmForage T</samp>
| Whether to randomly spawn beach forage and [[Supply Crate|supply crates]] on the farm (like the [[Farm Maps|vanilla beach farm]]). Forage and crates will only appear on tiles which have the <tt>BeachSpawn T</tt> property on the <tt>Back</tt> layer, are clear for placement, and don't have a tile on the <tt>AlwaysFront</tt> layer.
+
| Randomly spawns beach forage and [[Supply Crate|supply crates]] on the farm (like the [[Farm Maps|vanilla beach farm]]). Forage and crates will only appear on tiles which have the <samp>BeachSpawn T</samp> property on the <samp>Back</samp> layer, are clear for placement, and don't have a tile on the <samp>AlwaysFront</samp> layer.
 
|-
 
|-
 
| farm
 
| farm
| <tt>SpawnForestFarmForage T</tt>
+
| <samp>SpawnForestFarmForage T</samp>
| Whether to randomly spawn forest forage on the farm (like the [[Farm Maps|vanilla forest farm]]). Forage will only spawn on tiles which have the <tt>Type Grass</tt> tile property, are clear for placement, and don't have a tile on the <tt>AlwaysFront</tt> layer.
+
| Randomly spawns forest forage on the farm (like the [[Farm Maps|vanilla forest farm]]). Forage will only spawn on tiles which have the <samp>Type Grass</samp> tile property, are clear for placement, and don't have a tile on the <samp>AlwaysFront</samp> layer.
 
|-
 
|-
 
| farm
 
| farm
| <tt>SpawnMountainFarmOreRect {{t|tile X}} {{t|tile Y}} {{t|tile width}} {{t|tile height}}</tt>
+
| <samp>SpawnMountainFarmOreRect {{t|tile X}} {{t|tile Y}} {{t|tile width}} {{t|tile height}}</samp>
| The tile area on the farm map where ores should randomly spawn (like the [[Farm Maps|vanilla hilltop farm]]). Ores will only spawn on tiles which have the <tt>Type Dirt</tt> tile property and are clear for object placement.
+
| The tile area on the farm map where ores should randomly spawn (like the [[Farm Maps|vanilla hilltop farm]]). Ores will only spawn on tiles which have the <samp>Type Dirt</samp> tile property and are clear for object placement.
 
|-
 
|-
 
| farmhouse
 
| farmhouse
| <tt>EntryLocation {{t|tile X}} {{t|tile Y}}</tt>
+
| <samp>EntryLocation {{t|tile X}} {{t|tile Y}}</samp>
 
| Sets the tile on which the player appears when they warp into the farmhouse.
 
| Sets the tile on which the player appears when they warp into the farmhouse.
 
|}
 
|}
Line 576: Line 744:  
! effect
 
! effect
 
|-
 
|-
| <tt>Back</tt>
+
| <samp>Back</samp>
| <tt>TouchAction Warp {{t|area}} {{t|x}} {{t|y}} {{o|string prerequisite}}</tt>
+
| <samp>TouchAction Warp {{t|area}} {{t|x}} {{t|y}} {{o|string prerequisite}}</samp>
| Adds a player-only warp on the tile to the specified location name and position. This is exactly equivalent to <tt>TouchAction MagicWarp</tt>, but without the magic sound/visual effect.
+
| Adds a player-only warp on the tile to the specified location name and position. This is exactly equivalent to <samp>TouchAction MagicWarp</samp>, but without the magic sound/visual effect.
 
|}
 
|}
   Line 588: Line 756:  
! effect
 
! effect
 
|-
 
|-
| <tt>Back</tt>
+
| <samp>Back</samp>
| <tt>Water</tt>
+
| <samp>Water</samp>
| Setting the value to <tt>I</tt> (uppercase i) will make the tile behave like normal water, but won't render the water animation overlay for it.
+
| Setting the value to <samp>I</samp> (uppercase i) will make the tile behave like normal water, but won't render the water animation overlay for it.
 
|}
 
|}
   Line 598: Line 766:  
Specifically:
 
Specifically:
 
<ul>
 
<ul>
<li>Items with the "<tt>propose_roommate_{{t|NPC name}}</tt>" [[Modding:Context tags|context tag]] will trigger a roommate proposal when given to the named NPC. The NPC name must be lowercase with underscores instead of spaces (e.g. <tt>propose_roommate_dwarf</tt>).</li>
+
<li>Items with the "<samp>propose_roommate_{{t|NPC name}}</samp>" [[Modding:Items#Context tags|context tag]] will trigger a roommate proposal when given to the named NPC. The NPC name must be lowercase with underscores instead of spaces (''e.g.,'' <samp>propose_roommate_dwarf</samp>).</li>
 
<li>These [[Modding:Dialogue|dialogue keys]] apply before they move in:
 
<li>These [[Modding:Dialogue|dialogue keys]] apply before they move in:
 
{| class="wikitable"
 
{| class="wikitable"
Line 606: Line 774:  
! effect
 
! effect
 
|-
 
|-
| <tt>Strings/StringsFromCSFiles</tt>
+
| <samp>Strings/StringsFromCSFiles</samp>
| <tt>{{t|NPC name}}_EngagedRoommate</tt>
+
| <samp>{{t|NPC name}}_EngagedRoommate</samp>
| The NPC's roommate proposal accept dialogue.<br />⚠ Ignored if you don't specify <tt>Data/EngagementDialogue:{{t|NPC name}}Roommate0</tt>.<br />For example: ''A Void Ghost pendant! How did you...?$3#$b#Oh, wow.$7#$b#@... yes, I'll come live with you, if you like. But we have to keep it secret from everyone.#$b#I'll be at your house in a few days... okay?$h''
+
| The NPC's roommate proposal accept dialogue.<br />⚠ Ignored if you don't specify <samp>Data/EngagementDialogue:{{t|NPC name}}Roommate0</samp>.<br />For example: ''A Void Ghost pendant! How did you...?$3#$b#Oh, wow.$7#$b#@... yes, I'll come live with you, if you like. But we have to keep it secret from everyone.#$b#I'll be at your house in a few days... okay?$h''
 
|-
 
|-
| <tt>Strings/Characters</tt>
+
| <samp>Strings/Characters</samp>
| <tt>MovieInvite_NoTheater</tt>
+
| <samp>MovieInvite_NoTheater</samp>
| The NPC's roommate proposal rejection text when you don't meet the requirements (i.e. min friendship + house upgrade level, and not already having a roommate/spouse). This is the same dialogue used when you can't invite someone to the movies.
+
| The NPC's roommate proposal rejection text when you don't meet the requirements (''i.e.,'' min friendship + house upgrade level, and not already having a roommate/spouse). This is the same dialogue used when you can't invite someone to the movies.
 
|-
 
|-
| <tt>Data/EngagementDialogue</tt>
+
| <samp>Data/EngagementDialogue</samp>
| <tt>{{t|NPC name}}Roommate0</tt><br /><tt>{{t|NPC name}}Roommate1</tt>
+
| <samp>{{t|NPC name}}Roommate0</samp><br /><samp>{{t|NPC name}}Roommate1</samp>
| The NPC's normal dialogue after accepting the proposal, but before moving in. The <tt>Roommate0</tt> variant is always used on the day the NPC accepted; on subsequent days the NPC randomly chooses <tt>Roommate0</tt> or <tt>Roommate1</tt>. If the <tt>Roommate0</tt> variant isn't defined, the NPC will use the normal <tt>{{t|NPC Name}}0</tt> and <tt>{{t|NPC Name}}1</tt> keys. If the <tt>Roommate0</tt> variant is defined, <tt>Roommate1</tt> must be set too to avoid errors.<br />For example: ''@... I'm afraid we'll have to keep this a secret... Neither my people nor yours would accept us living together.''
+
| The NPC's normal dialogue after accepting the proposal, but before moving in. The <samp>Roommate0</samp> variant is always used on the day the NPC accepted; on subsequent days the NPC randomly chooses <samp>Roommate0</samp> or <samp>Roommate1</samp>. If the <samp>Roommate0</samp> variant isn't defined, the NPC will use the normal <samp>{{t|NPC Name}}0</samp> and <samp>{{t|NPC Name}}1</samp> keys. If the <samp>Roommate0</samp> variant is defined, <samp>Roommate1</samp> must be set too to avoid errors.<br />For example: ''@... I'm afraid we'll have to keep this a secret... Neither my people nor yours would accept us living together.''
 
|}
 
|}
   Line 626: Line 794:  
! effect
 
! effect
 
|-
 
|-
| <tt>Characters/Dialogue/MarriageDialogue{{t|NPC name}}Roommate</tt>
+
| <samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}Roommate</samp>
 
| ''all keys''
 
| ''all keys''
| Equivalent to <tt>Characters/Dialogue/MarriageDialogue{{t|NPC name}}</tt>, but only applies if the NPC is a roommate. If the file exists, it completely replaces the spouse version; otherwise the game defaults to the spouse version.
+
| Equivalent to <samp>Characters/Dialogue/MarriageDialogue{{t|NPC name}}</samp>, but only applies if the NPC is a roommate. If the file exists, it completely replaces the spouse version; otherwise the game defaults to the spouse version.
 
|-
 
|-
| <tt>Characters/Dialogue/MarriageDialogue</tt>
+
| <samp>Characters/Dialogue/MarriageDialogue</samp>
| <tt>*Roommate</tt>
+
| <samp>*Roommate</samp>
| Keys with the <tt>Roommate</tt> suffix take priority if they exist (only in this file, not the <tt>MarriageDialogue{{t|NPC name}}</tt> files).
+
| Keys with the <samp>Roommate</samp> suffix take priority if they exist (only in this file, not the <samp>MarriageDialogue{{t|NPC name}}</samp> files).
 
|-
 
|-
| <tt>Data/Festivals/*</tt>
+
| <samp>Data/Festivals/*</samp>
| <tt>{{t|NPC name}}_roommate</tt>
+
| <samp>{{t|NPC name}}_roommate</samp>
| The NPC's normal dialogue at the festival if they're a roommate. If the key isn't defined, they'll use <tt>{{t|NPC name}}_spouse</tt> instead.
+
| The NPC's normal dialogue at the festival if they're a roommate. If the key isn't defined, they'll use <samp>{{t|NPC name}}_spouse</samp> instead.
 
|}
 
|}
   Line 646: Line 814:  
! effect
 
! effect
 
|-
 
|-
| <tt>Characters/Dialogue/*</tt>
+
| <samp>Characters/Dialogue/*</samp>
| <tt>*_roommate_*</tt>
+
| <samp>*_roommate_*</samp>
| Equivalent to the <tt>*_inlaw_*</tt> infix in [[Modding:Dialogue#Generic dialogue|generic dialogue]], used if you're a roommate with the NPC. If not defined, the game will fallback to the non-infixed dialogue (it won't use the <tt>*_inlaw_*</tt> variant).
+
| Equivalent to the <samp>*_inlaw_*</samp> infix in [[Modding:Dialogue#Generic dialogue|generic dialogue]], used if you're a roommate with the NPC. If not defined, the game will fallback to the non-infixed dialogue (it won't use the <samp>*_inlaw_*</samp> variant).
 
|}</li>
 
|}</li>
 
<li>Roommates will sleep in a [[Single Bed]] if one is available and unused in the house; otherwise they'll use a double bed like a normal spouse. (Krobus is an exception, since he doesn't sleep in a bed.)</li>
 
<li>Roommates will sleep in a [[Single Bed]] if one is available and unused in the house; otherwise they'll use a double bed like a normal spouse. (Krobus is an exception, since he doesn't sleep in a bed.)</li>
<li>Added [[Modding:Event data#Event preconditions|event preconditions]] to check whether the local player has a roommate (<tt>R</tt>) or doesn't have a roommate (<tt>Rf</tt>). This can be combined with <tt>O {{t|NPC name}}</tt> to check for a specific roommate, like <tt>R/O Abigail</tt>.</li>
+
<li>Added [[Modding:Event data#Event preconditions|event preconditions]] to check whether the local player has a roommate (<samp>R</samp>) or doesn't have a roommate (<samp>Rf</samp>). This can be combined with <samp>O {{t|NPC name}}</samp> to check for a specific roommate, like <samp>R/O Abigail</samp>.</li>
 
</ul>
 
</ul>
    
===Custom mail formatting===
 
===Custom mail formatting===
You can now customize [[Modding:Mail data|mail]] and [[Secret Notes|secret notes]] by including three custom commands in the letter text (including the <tt>[]</tt> characters):
+
You can now customize [[Modding:Mail data|mail]] and [[Secret Notes|secret notes]] by including three custom commands in the letter text (including the <samp>[]</samp> characters):
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 661: Line 829:  
! effect
 
! effect
 
|-
 
|-
| <tt>[letterbg {{t|index}}]</tt>
+
| <samp>[letterbg {{t|index}}]</samp>
| Changes the default letter background to a vanilla background from <tt>LooseSprites/letterBG</tt>. The index can be 0 (default letter), 1 (Sandy's lined paper), 2 (Wizard style), or 3 (Krobus style). This will also set the default text color for that style, unless overridden by <tt>textcolor</tt>.
+
| Changes the default letter background to a vanilla background from <samp>LooseSprites/letterBG</samp>. The index can be 0 (default letter), 1 (Sandy's lined paper), 2 (Wizard style), or 3 (Krobus style). This will also set the default text color for that style, unless overridden by <samp>textcolor</samp>.
 
|-
 
|-
| <tt>[letterbg {{t|asset name}} {{t|index}}]</tt>
+
| <samp>[letterbg {{t|asset name}} {{t|index}}]</samp>
 
| Changes the default letter background to the given texture. The asset name should match a texture containing two rows: one with 320x180 pixel letter background images, and one with 24x24 pixel button backgrounds shown behind attached items. The index is the sprite to use from those rows, starting at 0 for the first one.
 
| Changes the default letter background to the given texture. The asset name should match a texture containing two rows: one with 320x180 pixel letter background images, and one with 24x24 pixel button backgrounds shown behind attached items. The index is the sprite to use from those rows, starting at 0 for the first one.
 +
Only the first 4 letter background images of a row will be properly displayed.
 +
Only one row of button may exist.
 +
See image below
 
|-
 
|-
| <tt>[textcolor {{t|color}}]</tt>
+
| <samp>[textcolor {{t|color}}]</samp>
| Changes the letter text color. The valid colors are <tt>black</tt>, <tt>blue</tt>, <tt>cyan</tt>, <tt>gray</tt>, <tt>green</tt>, <tt>orange</tt>, <tt>purple</tt>, <tt>red</tt>, and <tt>white</tt>.
+
| Changes the letter text color. The valid colors are <samp>black</samp>, <samp>blue</samp>, <samp>cyan</samp>, <samp>gray</samp>, <samp>green</samp>, <samp>orange</samp>, <samp>purple</samp>, <samp>red</samp>, and <samp>white</samp>.
 
|}
 
|}
 +
 +
 +
[[File:Lettersbglayers.png|center|thumb|Example : the letters  background images can go on the pale pink, pink and purple spaces, while the buttons can only go on the orange line.]]
    
===Custom scarecrows===
 
===Custom scarecrows===
You can now mark any placeable item as a [[scarecrow]] with two new [[Modding:Context tags|context tags]]:
+
You can now mark any placeable item as a [[scarecrow]] with two new [[Modding:Items#Context tags|context tags]]:
    
{| class="wikitable"
 
{| class="wikitable"
Line 679: Line 853:  
! effect
 
! effect
 
|-
 
|-
| <tt>crow_scare</tt>
+
| <samp>crow_scare</samp>
 
| Sets the item as a placeable scarecrow. If not set, the item is considered a scarecrow if its default name contains the substring <code>arecrow</code> (like before).
 
| Sets the item as a placeable scarecrow. If not set, the item is considered a scarecrow if its default name contains the substring <code>arecrow</code> (like before).
 
|-
 
|-
| <tt>crow_scare_radius_{{t|radius}}</tt>
+
| <samp>crow_scare_radius_{{t|radius}}</samp>
 
| If the item is a scarecrow, sets the radius that it covers. If not set, the scarecrow defaults to 17 if the default name contains the substring <code>Deluxe</code> and 9 otherwise.
 
| If the item is a scarecrow, sets the radius that it covers. If not set, the scarecrow defaults to 17 if the default name contains the substring <code>Deluxe</code> and 9 otherwise.
 
|}
 
|}
    
===Improved map seats===
 
===Improved map seats===
When defining map seats via <tt>Data\ChairTiles</tt> (see [[Modding:Migrate to Stardew Valley 1.5#Sitting on non-furniture chairs|docs in the 1.5 migration guide]]), you can now set the type field to <tt>custom {{t|offset_x}} {{t|offset_y}} {{t|extra_height}}</tt> to override the hardcoded offset and height values in code. The three values are measured in tiles (e.g. an X offset value of 0.5 would shift the sitting location by half a tile).
+
{{main article|Modding:Maps#Sitting on non-furniture chairs}}
   −
===Update impact===
+
When defining map seats via <samp>Data\ChairTiles</samp> (see [[Modding:Migrate to Stardew Valley 1.5#Sitting on non-furniture chairs|docs in the 1.5 migration guide]]), you can now set the type field to <samp>custom {{t|offset_x}} {{t|offset_y}} {{t|extra_height}}</samp> to override the hardcoded offset and height values in code. The three values are measured in tiles (''e.g.,'' an X offset value of 0.5 would shift the sitting location by half a tile).
Stardew Valley 1.5.5 only has technical changes; there are no known changes to the player-visible content. Known changes:
  −
 
  −
{| class="wikitable"
  −
|-
  −
! content file
  −
! changes
  −
|-
  −
| <tt>Effects/BloomCombine</tt><br /><tt>Effects/BloomExtract</tt><br /><tt>Effects/GaussianBlur</tt>
  −
| These files were deleted.
  −
|-
  −
| <tt>Fonts/*</tt>
  −
| The actual font files are unchanged, but the JSON output for some fonts when unpacked by StardewXnbHack is a bit different due to the XNA Framework → MonoGame change.
  −
|}
      
==See also==
 
==See also==
Line 709: Line 870:  
[[Category:Modding]]
 
[[Category:Modding]]
    +
[[es:Modding:Migrar a Stardew Valley 1.5.5]]
 
[[zh:模组:迁移至游戏本体1.5.5]]
 
[[zh:模组:迁移至游戏本体1.5.5]]

Navigation menu