Modding:Shops: Difference between revisions
imported>Pathoschild →Format: update for 1.6.0 build 24075 (added ActionsOnPurchase) |
imported>Tlitookilakin →Format: removed PerItemCondition, as it is included in common fields |
||
| (20 intermediate revisions by 12 users not shown) | |||
| Line 1: | Line 1: | ||
← [[Modding:Index|Index]] | ← [[Modding:Index|Index]] | ||
| Line 14: | Line 12: | ||
! effect | ! effect | ||
|- | |- | ||
| <samp>Items</samp> | |valign="top"| <samp>Items</samp> | ||
| The items to add to the shop inventory. This consists of a list of values with these fields: | | The items to add to the shop inventory. This consists of a list of values with these fields: | ||
{| class="wikitable" | {| class="wikitable" | ||
| Line 61: | Line 59: | ||
| ''(Optional)'' The maximum number of the item which can be purchased in one day. Default unlimited. | | ''(Optional)'' The maximum number of the item which can be purchased in one day. Default unlimited. | ||
|- | |- | ||
| <samp>AvailableStockLimit</samp> | |valign="top"| <samp>AvailableStockLimit</samp> | ||
| ''(Optional)'' If <samp>Stock</samp> is set, how the limit is applied in multiplayer. This has no effect on recipes. | | ''(Optional)'' If <samp>Stock</samp> is set, how the limit is applied in multiplayer. This has no effect on recipes. | ||
| Line 81: | Line 79: | ||
Default <samp>Global</samp>. | Default <samp>Global</samp>. | ||
|- | |- | ||
| <samp>ActionsOnPurchase</samp> | | <samp>ActionsOnPurchase</samp> | ||
| Line 89: | Line 84: | ||
For example, this can be used to start a [[Modding:Dialogue#Conversation topics|conversation topic]] when it's purchased: | For example, this can be used to start a [[Modding:Dialogue#Conversation topics|conversation topic]] when it's purchased: | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="json"> | ||
"ActionsOnPurchase": [ | "ActionsOnPurchase": [ | ||
"AddConversationTopic {{ModId}}_PurchasedItem 5" | "AddConversationTopic {{ModId}}_PurchasedItem 5" | ||
| Line 97: | Line 92: | ||
|- | |- | ||
| <samp>SalableItemTags</samp> | | <samp>SalableItemTags</samp> | ||
| ''(Optional)'' A list of [[Modding: | | ''(Optional)'' A list of [[Modding:Context tags|context tags]] for items which the player can sell to to this shop. Default none. | ||
|- | |- | ||
| <samp>Owners</samp> | |valign="top"| <samp>Owners</samp> | ||
| ''(Optional)'' The portrait and dialogue | | ''(Optional)'' The 'owner' data to apply when the shop is opened. This affects the portrait and dialogue shown, and whether the shop is closed. This field is checked ''after'' conditions specified in the [[Modding:Maps#Action|<samp>Action OpenShop</samp> tile property]]. | ||
The behavior depends on whether <samp>Owners</samp> is set: | |||
* If omitted, the shop is opened regardless of whether an NPC is present, and no portrait or dialogue is shown. | |||
* If it's specified, this consists of an ''ordered'' list. When the player opens the shop, the first matching entry is applied. When searching for an NPC, each entry checks either the {{o|owner tile area}} from the [[Modding:Maps#Action|<samp>Action OpenShop</samp> tile property]] (if set), else the whole location. If no entries are matched, the shop isn't opened. | |||
For example, let's say a shop has these owners: | |||
<syntaxhighlight lang="js"> | |||
"Owners": [ | |||
{ | |||
"Name": "AnyOrNone", | |||
"ClosedMessage": "The shop opens from 1pm to 2pm.", | |||
"Condition": "!TIME 1300 1400" | |||
}, | |||
{ | |||
"Name": "Any", | |||
"Dialogues": [ "Hi there!" ] | |||
}, | |||
{ | |||
"Name": "Abigail", | |||
"Dialogues": [ "This entry is never selected." ] | |||
}, | |||
] | |||
</syntaxhighlight> | |||
Here's what happens when the player clicks the shop: | |||
# If it's not 1pm to 2pm, the first entry matches. The <samp>ClosedMessage</samp> shows a matching dialogue box and the shop isn't opened. | |||
# Else if any NPC is present, the second entry applies. The third entry is always ignored, since Abigail would match the <code>"Name": "Any"</code> check. | |||
# Else the shop isn't opened. | |||
Each model in the list can specify these fields: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
| Line 132: | Line 154: | ||
If drawn, it'll use the 64x64 pixel area in the top-left corner of the texture. | If drawn, it'll use the 64x64 pixel area in the top-left corner of the texture. | ||
Note : it is possible that name of "none" prevents any portrait to be used. | |||
|- | |- | ||
| <samp>Dialogues</samp> | | <samp>Dialogues</samp> | ||
| ''(Optional)'' A list of possible | | ''(Optional)'' A list of possible dialogue lines the shop will display for this Owner. The first entry with a matching condition will be chosen. Each entry consists of a model with these fields: | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
| Line 149: | Line 172: | ||
|- | |- | ||
| <samp>RandomDialogue</samp> | | <samp>RandomDialogue</samp> | ||
| ''(Optional)'' A list of dialogue | | ''(Optional)'' A list of dialogue lines to randomly choose from, using the same format as <samp>Dialogue</samp>. If set, <samp>Dialogue</samp> is optional and ignored. Each entry in the list has an equal probability of being chosen every time the shop is opened (see <samp>RandomizeDialogueOnOpen</samp> below for how to change this to randomize daily). For example: | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="json"> | ||
"RandomDialogue": [ | "RandomDialogue": [ | ||
"[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11469]", | "[LocalizedText Strings\StringsFromCSFiles:ShopMenu.cs.11469]", | ||
| Line 163: | Line 186: | ||
This can be set to an empty list (<code>"Dialogues": []</code>) to disable the dialogue text entirely. If omitted, defaults to a generic "''Have a look at my wares''" text. | This can be set to an empty list (<code>"Dialogues": []</code>) to disable the dialogue text entirely. If omitted, defaults to a generic "''Have a look at my wares''" text. | ||
|- | |||
| <samp>RandomizeDialogueOnOpen</samp> | |||
| ''(Optional)'' If a <samp>Dialogues</samp> entry is using <samp>RandomDialogue</samp>, whether to re-randomize which line is selected each time the shop is opened (<samp>true</samp>) or once per day (<samp>false</samp>). Default <samp>true</samp>. | |||
|- | |- | ||
| <samp>ClosedMessage</samp> | | <samp>ClosedMessage</samp> | ||
| ''(Optional)'' If set, a [[Modding:Tokenizable strings|tokenizable string]] for a 'shop is closed'-style message to | | ''(Optional)'' If set, a [[Modding:Tokenizable strings|tokenizable string]] for a 'shop is closed'-style message to display when this entry is selected. | ||
'''Notes:''' | |||
| | * This only applies if the <samp>Owners</samp> list is checked (i.e. the [[#Open a custom shop|<samp>Action OpenShop</samp> conditions]] match). If you want to customize the message shown for the shop opening hours, remove the conditions from <samp>Action OpenShop</samp> and set them on this entry instead. | ||
* If the selected entry sets this field, the shop is closed regardless of any other fields or whether the shop owner is present. When you set the <samp>Name</samp> field, that affects whether this entry is selected (i.e. whether the shop is closed). | |||
|} | |} | ||
|- | |- | ||
| Line 213: | Line 240: | ||
| ''(Optional)'' A [[Modding:Migrate to Stardew Valley 1.6#Quantity modifiers|quantity modifier mode]] which indicates what to do if multiple modifiers in the <samp>PriceModifiers</samp> field apply at the same time. This only affects that specific field, it won't affect price modifiers under <samp>Items</samp>. Default <samp>Stack</samp>. | | ''(Optional)'' A [[Modding:Migrate to Stardew Valley 1.6#Quantity modifiers|quantity modifier mode]] which indicates what to do if multiple modifiers in the <samp>PriceModifiers</samp> field apply at the same time. This only affects that specific field, it won't affect price modifiers under <samp>Items</samp>. Default <samp>Stack</samp>. | ||
|- | |- | ||
| <samp>VisualTheme</samp> | |valign="top"| <samp>VisualTheme</samp> | ||
| ''(Optional)'' The visual theme to apply to the shop UI, or omit to use the default theme. The first matching theme is applied. All fields are optional and will fallback to the default theme. | | ''(Optional)'' The visual theme to apply to the shop UI, or omit to use the default theme. The first matching theme is applied. All fields are optional and will fallback to the default theme. | ||
| Line 269: | Line 296: | ||
You can add or replace entire shops. For example, this content pack adds a shop that sells ice cream in summer, and pufferfish all year: | You can add or replace entire shops. For example, this content pack adds a shop that sells ice cream in summer, and pufferfish all year: | ||
{{Content Patcher example|<nowiki> | |||
"Changes": [ | "Changes": [ | ||
{ | { | ||
| Line 319: | Line 344: | ||
} | } | ||
] | ] | ||
</nowiki>}} | |||
You can also add, replace, edit, or reorder items in a specific shop by targeting the shop's <samp>Items</samp> field. For example, this removes Trout Soup (item #219) and adds Pufferfish above bait (item #685): | You can also add, replace, edit, or reorder items in a specific shop by targeting the shop's <samp>Items</samp> field. For example, this removes Trout Soup (item #219) and adds Pufferfish above bait (item #685): | ||
{{Content Patcher example|<nowiki> | |||
"Changes": [ | "Changes": [ | ||
{ | { | ||
| Line 343: | Line 366: | ||
} | } | ||
] | ] | ||
</nowiki>}} | |||
===Vanilla shop IDs=== | ===Vanilla shop IDs=== | ||
The base game's shops are defined in <samp>Data/Shops</samp> too (except a few special cases like [[:Category:Dressers|dressers]] and home renovations). | |||
See <samp>Data/Shops</samp> for a full list, but here are the main shop IDs for convenience: | See <samp>Data/Shops</samp> for a full list, but here are the main shop IDs for convenience: | ||
| Line 360: | Line 383: | ||
| [[Adventurer's Guild]] | | [[Adventurer's Guild]] | ||
| <samp>AdventureShop</samp> (regular shop)<br /><samp>AdventureGuildRecovery</samp> (item recovery service) | | <samp>AdventureShop</samp> (regular shop)<br /><samp>AdventureGuildRecovery</samp> (item recovery service) | ||
|- | |||
| [[Bookseller]] | |||
| <samp>Bookseller</samp> (regular shop)<br /><samp>BooksellerTrade</samp> (book trades) | |||
|- | |- | ||
| [[Casino]] | | [[Casino]] | ||
| Line 396: | Line 422: | ||
| [[Pierre's General Store|Pierre's general store]] | | [[Pierre's General Store|Pierre's general store]] | ||
| <samp>SeedShop</samp> | | <samp>SeedShop</samp> | ||
|- | |||
| [[Qi's Walnut Room|Qi's gem shop]] | |||
| <samp>QiGemShop<samp> | |||
|- | |||
| [[Giant Stump#Raccoon Wife's Shop|Raccoon Wife's Shop]] | |||
| <samp>Raccoon</samp> | |||
|- | |- | ||
| [[Carpenter's Shop|Robin's carpenter shop]] | | [[Carpenter's Shop|Robin's carpenter shop]] | ||
| Line 408: | Line 440: | ||
| [[Traveling Cart|Traveling cart]] | | [[Traveling Cart|Traveling cart]] | ||
| <samp>Traveler</samp> | | <samp>Traveler</samp> | ||
|- | |||
| [[Volcano Dungeon#Shop|Volcano dwarf shop]] | |||
| <samp>VolcanoShop</samp> | |||
|- | |- | ||
| [[Fish Shop|Willy's fish shop]] | | [[Fish Shop|Willy's fish shop]] | ||
| Line 413: | Line 448: | ||
|} | |} | ||
And the main festival shops: | |||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
| Line 421: | Line 456: | ||
| [[Dance of the Moonlight Jellies]] | | [[Dance of the Moonlight Jellies]] | ||
| <samp>Festival_DanceOfTheMoonlightJellies_Pierre</samp> | | <samp>Festival_DanceOfTheMoonlightJellies_Pierre</samp> | ||
|- | |||
|- | |||
| [[Desert Festival#Calico Egg Merchant|Desert Festival (egg merchant)]] | |||
| <samp>DesertFestival_EggShop</samp> | |||
|- | |||
|- | |||
| [[Desert Festival#Villager Shops|Desert Festival (villager shops)]] | |||
| <samp>DesertFestival_{{t|name}}</samp><br />(e.g. <samp>DesertFestival_Abigail)</samp> | |||
|- | |- | ||
| [[Egg Festival]] | | [[Egg Festival]] | ||
| Line 437: | Line 480: | ||
| <samp>Festival_Luau_Pierre</samp> | | <samp>Festival_Luau_Pierre</samp> | ||
|- | |- | ||
| [[Night Market | | [[Night Market#Decoration Boat|Night Market (decoration boat)]] | ||
| <samp>Festival_NightMarket_DecorationBoat</samp> | | <samp>Festival_NightMarket_DecorationBoat</samp> | ||
|- | |- | ||
| [[Night Market | | [[Night Market#Magic Shop Boat|Night Market (magic boat)]] | ||
| <samp>Festival_NightMarket_MagicBoat_Day1</samp><br /><samp>Festival_NightMarket_MagicBoat_Day2</samp><br /><samp>Festival_NightMarket_MagicBoat_Day3</samp> | | <samp>Festival_NightMarket_MagicBoat_Day1</samp><br /><samp>Festival_NightMarket_MagicBoat_Day2</samp><br /><samp>Festival_NightMarket_MagicBoat_Day3</samp> | ||
|- | |- | ||
| Line 450: | Line 493: | ||
|} | |} | ||
And | And several 'shops' for the catalogues: | ||
{| class="wikitable sortable" | {| class="wikitable sortable" | ||
|- | |- | ||
| Line 461: | Line 504: | ||
| [[Furniture Catalogue]] | | [[Furniture Catalogue]] | ||
| <samp>Furniture Catalogue</samp> | | <samp>Furniture Catalogue</samp> | ||
|- | |||
| [[Joja Furniture Catalogue]] | |||
| <samp>JojaFurnitureCatalogue</samp> | |||
|- | |||
| [[Junimo Catalogue]] | |||
| <samp>JunimoFurnitureCatalogue</samp> | |||
|- | |||
| [[Retro Catalogue]] | |||
| <samp>RetroFurnitureCatalogue</samp> | |||
|- | |||
| [[Trash Catalogue]] | |||
| <samp>TrashFurnitureCatalogue</samp> | |||
|- | |||
| [[Wizard Catalogue]] | |||
| <samp>WizardFurnitureCatalogue</samp> | |||
|} | |} | ||
==Open a custom shop== | ==Open a custom shop== | ||
You can place an [[Modding: | You can place an [[Modding:Maps#Action|<samp>Action OpenShop</samp> tile property]] on the map, which will open the given shop ID when the player clicks it. | ||
In C# code, you can get the inventory for a custom shop using <code>Utility.GetShopStock("shop id here")</code>, open a shop menu using <code>Utility.TryOpenShopMenu("shop id", …)</code>, and add temporary items to an open menu using <code>shopMenu.AddForSale(…)</code>. The ID of the opened shop is stored in the shop menu's <samp>ShopId</samp> field. | In C# code, you can get the inventory for a custom shop using <code>Utility.GetShopStock("shop id here")</code>, open a shop menu using <code>Utility.TryOpenShopMenu("shop id", …)</code>, and add temporary items to an open menu using <code>shopMenu.AddForSale(…)</code>. The ID of the opened shop is stored in the shop menu's <samp>ShopId</samp> field. | ||
[[Category:Modding]] | [[Category:Modding]] | ||
[[ru:Модификации:Магазины]] | |||
[[zh:模组:商店]] | |||
Latest revision as of 17:44, 13 October 2026
← Index
This page explains how to edit shop data.
Data
Format
You can create and change shops by editing the Data/Shops asset. This consists of a string → model lookup, where the key is a unique string ID for the shop, and the value is a model with these fields.
| field | effect | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Items | The items to add to the shop inventory. This consists of a list of values with these fields:
| ||||||||||||||||||||||||||||||||||
| SalableItemTags | (Optional) A list of context tags for items which the player can sell to to this shop. Default none. | ||||||||||||||||||||||||||||||||||
| Owners | (Optional) The 'owner' data to apply when the shop is opened. This affects the portrait and dialogue shown, and whether the shop is closed. This field is checked after conditions specified in the Action OpenShop tile property.
The behavior depends on whether Owners is set:
For example, let's say a shop has these owners: "Owners": [
{
"Name": "AnyOrNone",
"ClosedMessage": "The shop opens from 1pm to 2pm.",
"Condition": "!TIME 1300 1400"
},
{
"Name": "Any",
"Dialogues": [ "Hi there!" ]
},
{
"Name": "Abigail",
"Dialogues": [ "This entry is never selected." ]
},
]
Here's what happens when the player clicks the shop:
Each model in the list can specify these fields:
| ||||||||||||||||||||||||||||||||||
| Currency | (Optional) The currency in which all items in the shop should be priced. The valid values are 0 (money), 1 (star tokens), 2 (Qi coins), and 4 (Qi gems). Default 0. For item trading, see TradeItemId for each item. | ||||||||||||||||||||||||||||||||||
| ApplyProfitMargins | (Optional) The default value for ApplyProfitMargins under Items, if set. This can be true (always apply it), false (never apply it), or null (apply for certain items like saplings). This is applied before any quantity modifiers. Default null. | ||||||||||||||||||||||||||||||||||
| StackSizeVisibility | (Optional) How to draw stack size numbers in the shop list by default. If omitted, the default shop logic is applied (usually equivalent to Show).
The possible values are:
This is ignored in some special cases (e.g. recipes can't have a stack size). | ||||||||||||||||||||||||||||||||||
| OpenSound | (Optional) The audio cue ID to play when the shop menu is opened. Defaults to dwop. | ||||||||||||||||||||||||||||||||||
| PurchaseSound | (Optional) The audio cue ID to play when an item is purchased normally. Defaults to purchaseClick. | ||||||||||||||||||||||||||||||||||
| purchaseRepeatSound | (Optional) The audio cue ID to play when accumulating a stack to purchase (e.g. by holding right-click on PC). Defaults to purchaseRepeat. | ||||||||||||||||||||||||||||||||||
| PriceModifiers | (Optional) Quantity modifiers applied to the sell price for items in this shop. See also PriceModifiers under Items. | ||||||||||||||||||||||||||||||||||
| PriceModifierMode | (Optional) A quantity modifier mode which indicates what to do if multiple modifiers in the PriceModifiers field apply at the same time. This only affects that specific field, it won't affect price modifiers under Items. Default Stack. | ||||||||||||||||||||||||||||||||||
| VisualTheme | (Optional) The visual theme to apply to the shop UI, or omit to use the default theme. The first matching theme is applied. All fields are optional and will fallback to the default theme.
This consists of a list of models with these fields:
| ||||||||||||||||||||||||||||||||||
| CustomFields | The custom fields for this entry. |
Examples
You can add or replace entire shops. For example, this content pack adds a shop that sells ice cream in summer, and pufferfish all year:
{
"Format": "2.8.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/Shops",
"Entries": {
"Example.ModId_CustomShop": {
"Owners": [
{
"Name": "Any",
"Dialogues": [
// dialogue on sunny summer days
{
"Id": "Example.ModId_SunnySummer",
"Condition": "SEASON Summer, WEATHER Here Sun",
"Dialogue": "Ice-cream is perfect for a day like this."
},
// dialogue any other time
{
"Id": "Example.ModId_Default",
"Dialogue": "Welcome to the only place in town for pufferfish!"
}
]
}
],
"Items": [
// ice-cream in summer, default price
{
"Id": "Example.ModId_IceCream",
"Condition": "SEASON Summer",
"ItemId": "(O)233"
},
// pufferfish for 1000g, limited to one per day per player
{
"Id": "Example.ModId_PufferFish",
"ItemId": "(O)128",
"Price": 1000,
"AvailableStock": 1,
"AvailableStockLimit": "Player"
}
]
}
}
}
]
}
You can also add, replace, edit, or reorder items in a specific shop by targeting the shop's Items field. For example, this removes Trout Soup (item #219) and adds Pufferfish above bait (item #685):
{
"Format": "2.8.0",
"Changes": [
{
"Action": "EditData",
"Target": "Data/Shops",
"TargetField": [ "FishShop", "Items" ],
"Entries": {
"(O)219": null,
"Example.ModId_Pufferfish": {
"Id": "Example.ModId_Pufferfish",
"ItemId": "(O)128",
"Price": 2000
}
},
"MoveEntries": [
{ "Id": "Example.ModId_Pufferfish", "BeforeId": "(O)685" }
]
}
]
}
Vanilla shop IDs
The base game's shops are defined in Data/Shops too (except a few special cases like dressers and home renovations).
See Data/Shops for a full list, but here are the main shop IDs for convenience:
| shop | ID |
|---|---|
| Abandoned house shop | HatMouse |
| Adventurer's Guild | AdventureShop (regular shop) AdventureGuildRecovery (item recovery service) |
| Bookseller | Bookseller (regular shop) BooksellerTrade (book trades) |
| Casino | Casino |
| Clint's blacksmith shop | Blacksmith (regular shop) ClintUpgrade (tool upgrades) |
| Desert trader | DesertTrade |
| Dwarf's shop | Dwarf |
| Harvey's clinic | Hospital |
| Ice-cream stand | IceCreamStand |
| Island resort | ResortBar |
| Island trader | IslandTrade |
| Joja Mart | Joja |
| Krobus' shop | ShadowShop |
| Marnie's ranch | AnimalShop |
| Pierre's general store | SeedShop |
| Qi's gem shop | QiGemShop |
| Raccoon Wife's Shop | Raccoon |
| Robin's carpenter shop | Carpenter |
| Stardrop Saloon | Saloon |
| Sandy's Oasis shop | Sandy |
| Traveling cart | Traveler |
| Volcano dwarf shop | VolcanoShop |
| Willy's fish shop | FishShop |
And the main festival shops:
| festival shop | ID |
|---|---|
| Dance of the Moonlight Jellies | Festival_DanceOfTheMoonlightJellies_Pierre |
| Desert Festival (egg merchant) | DesertFestival_EggShop |
| Desert Festival (villager shops) | DesertFestival_<name>(e.g. DesertFestival_Abigail) |
| Egg Festival | Festival_EggFestival_Pierre |
| Festival of Ice | Festival_FestivalOfIce_TravelingMerchant |
| Feast of the Winter Star | Festival_FeastOfTheWinterStar_Pierre |
| Flower Dance | Festival_FlowerDance_Pierre |
| Luau | Festival_Luau_Pierre |
| Night Market (decoration boat) | Festival_NightMarket_DecorationBoat |
| Night Market (magic boat) | Festival_NightMarket_MagicBoat_Day1 Festival_NightMarket_MagicBoat_Day2 Festival_NightMarket_MagicBoat_Day3 |
| Spirit's Eve | Festival_SpiritsEve_Pierre |
| Stardew Valley Fair | Festival_StardewValleyFair_StarTokens |
And several 'shops' for the catalogues:
| item | ID |
|---|---|
| Catalogue | Catalogue |
| Furniture Catalogue | Furniture Catalogue |
| Joja Furniture Catalogue | JojaFurnitureCatalogue |
| Junimo Catalogue | JunimoFurnitureCatalogue |
| Retro Catalogue | RetroFurnitureCatalogue |
| Trash Catalogue | TrashFurnitureCatalogue |
| Wizard Catalogue | WizardFurnitureCatalogue |
Open a custom shop
You can place an Action OpenShop tile property on the map, which will open the given shop ID when the player clicks it.
In C# code, you can get the inventory for a custom shop using Utility.GetShopStock("shop id here"), open a shop menu using Utility.TryOpenShopMenu("shop id", …), and add temporary items to an open menu using shopMenu.AddForSale(…). The ID of the opened shop is stored in the shop menu's ShopId field.