Line 542: |
Line 542: |
| | One of... | | | One of... |
| * the [[#Custom items|qualified or unqualified item ID]] for the produced item; | | * the [[#Custom items|qualified or unqualified item ID]] for the produced item; |
− | * ''or'' an [[#Item search query|item query]] which returns the produced item (if the query returns multiple items, only the first one is used); | + | * ''or'' an [[#Item queries|item query]] which returns the produced item (if the query returns multiple items, only the first one is used); |
| * ''or'' <samp>DROP_IN</samp> for the item placed into the machine. | | * ''or'' <samp>DROP_IN</samp> for the item placed into the machine. |
| | | |
Line 1,799: |
Line 1,799: |
| | One of: | | | One of: |
| * the [[#Custom items|qualified item ID]] (like <samp>(O)128</samp> for a [[pufferfish]]); | | * the [[#Custom items|qualified item ID]] (like <samp>(O)128</samp> for a [[pufferfish]]); |
− | * or a [[#Item search query|search query]] to dynamically choose an item (if it returns multiple items, only the first one will be used). | + | * or a [[#Item queries|search query]] to dynamically choose an item (if it returns multiple items, only the first one will be used). |
| |- | | |- |
| | <samp>RandomItemId</samp> | | | <samp>RandomItemId</samp> |
Line 3,728: |
Line 3,728: |
| | One of: | | | One of: |
| * the [[#Custom items|qualified item ID]] (like <samp>(O)128</samp> for a [[pufferfish]]); | | * the [[#Custom items|qualified item ID]] (like <samp>(O)128</samp> for a [[pufferfish]]); |
− | * or a [[#Item search query|search query]] to dynamically choose one or more items. | + | * or an [[#Item queries|item query]] to dynamically choose one or more items. |
| |- | | |- |
| | <samp>RandomItemId</samp> | | | <samp>RandomItemId</samp> |
Line 3,941: |
Line 3,941: |
| |} | | |} |
| | | |
− | ====Item search query==== | + | ====Open a custom shop==== |
− | ''Item search queries'' in a [[#Format|shop item's <samp>ItemId</samp> or <samp>RandomItemId</samp> field]] choose one or more items dynamically, instead of specifying an item ID.
| + | You can place an [[#Map/tile property changes|<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.OpenShopMenu("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>storeContext</samp> field. |
| | | |
− | The supported search queries are:
| + | ====Examples==== |
− | {| class="wikitable"
| + | 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: |
− | |-
| |
− | ! query
| |
− | ! effect
| |
− | |-
| |
− | | <samp>ALL_ITEMS {{o|type ID}}</samp>
| |
− | | Every item provided by the [[#Custom items|item data definitions]]. If {{o|type ID}} is set to an item type identifier (like <samp>(O)</samp> for object), only returns items from the matching item data definition.
| |
− | |-
| |
− | | <samp>DISH_OF_THE_DAY</samp>
| |
− | | The [[The Stardrop Saloon#Rotating Stock|Saloon's dish of the day]].
| |
− | |-
| |
− | | <samp>FLAVORED_ITEM {{t|type}} {{t|flavor ID}}</samp>
| |
− | | A flavored item like Apple Wine. The {{t|type}} can be one of [[Aged Roe|<samp>AgedRoe</samp>]], [[Honey|<samp>Honey</samp>]], [[Jellies and Pickles|<samp>Jelly</samp>]], [[Juice|<samp>Juice</samp>]], [[Jellies and Pickles|<samp>Pickle</samp>]], [[Roe|<samp>Roe</samp>]], or [[Wine|<samp>Wine</samp>]]. The {{t|flavor ID}} is the qualified or unqualified item ID which provides the flavor (like Apple in Apple Wine). For <samp>Honey</samp>, you can set the {{t|flavor ID}} to <samp>-1</samp> for Wild Honey.
| |
− | |-
| |
− | | <samp>ITEMS_SOLD_BY_PLAYER {{t|shop location}}</samp>
| |
− | | Random items the player has recently sold to the {{t|shop location}}, which can be one of <samp>SeedShop</samp> (Pierre's store) or <samp>FishShop</samp> (Willy's fish shop).
| |
− | |-
| |
− | | <samp>RANDOM_BASE_SEASON_ITEM</samp>
| |
− | | A random seasonal vanilla item which can be found by searching garbage cans, breaking containers in the mines, etc.
| |
− | |-
| |
− | | <samp>RANDOM_ITEMS {{t|type definition ID}} {{o|options}}</samp>
| |
− | | Random items from the given [[#Item types|type definition ID]], with any combination of the following criteria and options (in any order, all optional):
| |
| | | |
− | {| class="wikitable" | + | {{#tag:syntaxhighlight|<nowiki> |
− | |-
| + | { |
− | ! format
| + | "Format": "</nowiki>{{Content Patcher version}}<nowiki>", |
− | ! item criteria
| + | "Changes": [ |
− | |-
| + | { |
− | !colspan="2"| search criteria
| + | "Action": "EditData", |
− | |-
| + | "Target": "Data/Shops", |
− | | <samp>@has_category {{o|category}}</samp>
| + | "Entries": { |
− | | Must have one of the given [[Modding:Items#Categories|object categories]] (space-delimited), or any valid category if none specified. Can be negated with <samp>@!has_category</samp>.
| + | "Example.ModId_CustomShop": { |
− | |-
| + | "Owners": [ |
− | | <samp>@has_id {{t|id}}+</samp>
| + | { |
− | | Must have one of the given unqualified item IDs. Can be negated with <samp>@!has_id</samp>.
| + | "Name": "Any", |
− | |-
| + | "Dialogues": [ |
− | | <samp>@has_id_in_base_range {{t|min}} {{t|max}}</samp>
| + | // dialogue on sunny summer days |
− | | Must have a numeric ID between the {{t|min}} and {{t|max}} values (inclusive). Can be negated with <samp>@!has_id_in_base_range </samp>.
| + | { |
− | |-
| + | "Id": "Example.ModId_SunnySummer", |
− | | <samp>@has_id_prefix {{t|prefix}}+</samp>
| + | "Condition": "SEASON Summer, WEATHER Sun", |
− | | Must have an unqualified item ID starting with one of the given prefixes. For example, <samp>@has_id_prefix ExampleAuthor_ExampleMod_</samp> for a mod's items. Can be negated with <samp>@!has_id_prefix</samp>.
| + | "Dialogue": "Ice-cream is perfect for a day like this." |
− | |-
| + | }, |
− | | <samp>@has_object_type {{o|type}}+</samp>
| |
− | | Must have one of the given object ty pes (space-delimited), or any valid type if none specified. Can be negated with <samp>@!has_object_type</samp>.
| |
− | |-
| |
− | !colspan="2"| options
| |
− | |-
| |
− | | <samp>@allow_missing_price</samp>
| |
− | | Allow items with a base sell price of 0 or lower. If omitted, those items are skipped.
| |
− | |-
| |
− | | <samp>@count {{t|count}}</samp>
| |
− | | The number of random items to add to the shop. Default 1.
| |
− | |}
| |
| | | |
− | For example, you can sell a random [[wallpaper]] for {{price|200}}:
| + | // dialogue any other time |
− | <syntaxhighlight lang="js">
| + | { |
− | { | + | "Id": "Example.ModId_Default", |
− | "ItemId": "RANDOM_ITEMS (WP)",
| + | "Dialogue": "Welcome to the only place in town for pufferfish!" |
− | "Price": 200
| + | } |
− | } | + | ] |
− | </syntaxhighlight>
| + | } |
| + | ], |
| | | |
− | Or a random [[House Plant|house plant]]:
| + | "Items": [ |
− | <syntaxhighlight lang="js">
| + | // ice-cream in summer, default price |
− | {
| + | { |
− | "ItemId": "RANDOM_ITEMS (F) @has_id_in_base_range 1376 1390"
| + | "Id": "Example.ModId_IceCream", |
− | } | + | "Condition": "SEASON Summer", |
− | </syntaxhighlight>
| + | "ItemId": "(O)233" |
| + | }, |
| | | |
− | Or a random [[#Custom items|custom item]] added by a mod by its item ID prefix:
| + | // pufferfish for 1000g, limited to one per day per player |
− | <syntaxhighlight lang="js">
| + | { |
− | {
| + | "Id": "Example.ModId_PufferFish", |
− | "ItemId": "RANDOM_ITEMS (O) @has_id_prefix AuthorName_ModName_"
| + | "ItemId": "(O)128", |
− | } | + | "Price": 1000, |
− | </syntaxhighlight> | + | "AvailableStock": 1, |
| + | "AvailableStockLimit": "Player" |
| + | } |
| + | ] |
| + | } |
| + | } |
| + | } |
| + | ] |
| + | }</nowiki>|lang=javascript}} |
| | | |
− | Or 10 random objects with any category except <samp>-13</samp> or <samp>-14</samp>:
| + | 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): |
− | <syntaxhighlight lang="js"> | + | {{#tag:syntaxhighlight|<nowiki> |
| { | | { |
− | "ItemId": "RANDOM_ITEMS (O) @has_category @!has_category -13 -14 @count 10"
| + | "Format": "</nowiki>{{Content Patcher version}}<nowiki>", |
− | }
| + | "Changes": [ |
− | </syntaxhighlight>
| + | { |
− | |-
| |
− | | <samp>SHOP_TOWN_KEY</samp>
| |
− | | The special [[Key To The Town|town key]] item. This is only valid in shops.
| |
− | |-
| |
− | | <samp>TOOL_UPGRADES {{o|tool ID}}</samp>
| |
− | | The tool upgrades listed in <samp>Data/Shops</samp> whose conditions match the player's inventory (i.e. the same rules as [[Blacksmith|Clint's tool upgrade shop]]). If {{o|tool ID}} is specified, only upgrades which consume that tool ID are shown.
| |
− | |}
| |
− | | |
− | ====Open a custom shop====
| |
− | You can place an [[#Map/tile property changes|<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.OpenShopMenu("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>storeContext</samp> field.
| |
− | | |
− | ====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:
| |
− | | |
− | {{#tag:syntaxhighlight|<nowiki>
| |
− | {
| |
− | "Format": "</nowiki>{{Content Patcher version}}<nowiki>", | |
− | "Changes": [ | |
− | { | |
| "Action": "EditData", | | "Action": "EditData", |
| "Target": "Data/Shops", | | "Target": "Data/Shops", |
| + | "TargetField": [ "FishShop", "Items" ], |
| "Entries": { | | "Entries": { |
− | "Example.ModId_CustomShop": { | + | "(O)219": null, |
− | "Owners": [
| + | "Example.ModId_Pufferfish": { |
− | {
| + | "Id": "Example.ModId_Pufferfish", |
− | "Name": "Any",
| + | "ItemId": "(O)128", |
− | "Dialogues": [
| + | "Price": 2000 |
− | // dialogue on sunny summer days
| + | } |
− | {
| + | }, |
− | "Id": "Example.ModId_SunnySummer",
| + | "MoveEntries": [ |
− | "Condition": "SEASON Summer, WEATHER Sun",
| + | { "Id": "Example.ModId_Pufferfish", "BeforeId": "(O)685" } |
− | "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"
| |
− | }
| |
− | ]
| |
− | }
| |
− | }
| |
− | } | |
| ] | | ] |
| }</nowiki>|lang=javascript}} | | }</nowiki>|lang=javascript}} |
| | | |
− | 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):
| + | ====Vanilla shop IDs==== |
− | {{#tag:syntaxhighlight|<nowiki>
| + | Vanilla shops are now defined in <samp>Data/Shops</samp> too (except a few special cases like [[:Category:Dressers|dressers]] and home renovations), using these shop IDs: |
− | {
| + | |
− | "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
| + | {| class="wikitable sortable" |
− | "Changes": [
| + | |- |
− | {
| + | ! shop |
− | "Action": "EditData",
| + | ! ID |
− | "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" }
| |
− | ]
| |
− | }
| |
− | ]
| |
− | }</nowiki>|lang=javascript}}
| |
− | | |
− | ====Vanilla shop IDs==== | |
− | Vanilla shops are now defined in <samp>Data/Shops</samp> too (except a few special cases like [[:Category:Dressers|dressers]] and home renovations), using these shop IDs: | |
− | | |
− | {| class="wikitable sortable" | |
− | |- | |
− | ! shop | |
− | ! ID | |
− | |- | |
| | [[Abandoned House|Abandoned house shop]] | | | [[Abandoned House|Abandoned house shop]] |
| | <samp>HatMouse</samp> | | | <samp>HatMouse</samp> |
Line 4,957: |
Line 4,863: |
| ====Extensibility==== | | ====Extensibility==== |
| C# mods can define custom conditions by calling <code>GameStateQuery.RegisterQueryType("condition name", (string[] fields) => ...)</code>. To avoid conflicts, prefixing custom condition names with your mod ID (like <samp>Example.ModId_SomeCondition</samp>) is strongly recommended. | | C# mods can define custom conditions by calling <code>GameStateQuery.RegisterQueryType("condition name", (string[] fields) => ...)</code>. To avoid conflicts, prefixing custom condition names with your mod ID (like <samp>Example.ModId_SomeCondition</samp>) is strongly recommended. |
| + | |
| + | ===Item queries=== |
| + | ''Item queries'' in a [[#Format|shop item's <samp>ItemId</samp> or <samp>RandomItemId</samp> field]] choose one or more items dynamically, instead of specifying an item ID. |
| + | |
| + | The supported search queries are: |
| + | {| class="wikitable" |
| + | |- |
| + | ! query |
| + | ! effect |
| + | |- |
| + | | <samp>ALL_ITEMS {{o|type ID}}</samp> |
| + | | Every item provided by the [[#Custom items|item data definitions]]. If {{o|type ID}} is set to an item type identifier (like <samp>(O)</samp> for object), only returns items from the matching item data definition. |
| + | |- |
| + | | <samp>DISH_OF_THE_DAY</samp> |
| + | | The [[The Stardrop Saloon#Rotating Stock|Saloon's dish of the day]]. |
| + | |- |
| + | | <samp>FLAVORED_ITEM {{t|type}} {{t|flavor ID}}</samp> |
| + | | A flavored item like Apple Wine. The {{t|type}} can be one of [[Aged Roe|<samp>AgedRoe</samp>]], [[Honey|<samp>Honey</samp>]], [[Jellies and Pickles|<samp>Jelly</samp>]], [[Juice|<samp>Juice</samp>]], [[Jellies and Pickles|<samp>Pickle</samp>]], [[Roe|<samp>Roe</samp>]], or [[Wine|<samp>Wine</samp>]]. The {{t|flavor ID}} is the qualified or unqualified item ID which provides the flavor (like Apple in Apple Wine). For <samp>Honey</samp>, you can set the {{t|flavor ID}} to <samp>-1</samp> for Wild Honey. |
| + | |- |
| + | | <samp>ITEMS_SOLD_BY_PLAYER {{t|shop location}}</samp> |
| + | | Random items the player has recently sold to the {{t|shop location}}, which can be one of <samp>SeedShop</samp> (Pierre's store) or <samp>FishShop</samp> (Willy's fish shop). |
| + | |- |
| + | | <samp>RANDOM_BASE_SEASON_ITEM</samp> |
| + | | A random seasonal vanilla item which can be found by searching garbage cans, breaking containers in the mines, etc. |
| + | |- |
| + | | <samp>RANDOM_ITEMS {{t|type definition ID}} {{o|options}}</samp> |
| + | | Random items from the given [[#Item types|type definition ID]], with any combination of the following criteria and options (in any order, all optional): |
| + | |
| + | {| class="wikitable" |
| + | |- |
| + | ! format |
| + | ! item criteria |
| + | |- |
| + | !colspan="2"| search criteria |
| + | |- |
| + | | <samp>@has_category {{o|category}}</samp> |
| + | | Must have one of the given [[Modding:Items#Categories|object categories]] (space-delimited), or any valid category if none specified. Can be negated with <samp>@!has_category</samp>. |
| + | |- |
| + | | <samp>@has_id {{t|id}}+</samp> |
| + | | Must have one of the given unqualified item IDs. Can be negated with <samp>@!has_id</samp>. |
| + | |- |
| + | | <samp>@has_id_in_base_range {{t|min}} {{t|max}}</samp> |
| + | | Must have a numeric ID between the {{t|min}} and {{t|max}} values (inclusive). Can be negated with <samp>@!has_id_in_base_range </samp>. |
| + | |- |
| + | | <samp>@has_id_prefix {{t|prefix}}+</samp> |
| + | | Must have an unqualified item ID starting with one of the given prefixes. For example, <samp>@has_id_prefix ExampleAuthor_ExampleMod_</samp> for a mod's items. Can be negated with <samp>@!has_id_prefix</samp>. |
| + | |- |
| + | | <samp>@has_object_type {{o|type}}+</samp> |
| + | | Must have one of the given object ty pes (space-delimited), or any valid type if none specified. Can be negated with <samp>@!has_object_type</samp>. |
| + | |- |
| + | !colspan="2"| options |
| + | |- |
| + | | <samp>@allow_missing_price</samp> |
| + | | Allow items with a base sell price of 0 or lower. If omitted, those items are skipped. |
| + | |- |
| + | | <samp>@count {{t|count}}</samp> |
| + | | The number of random items to add to the shop. Default 1. |
| + | |} |
| + | |
| + | For example, you can sell a random [[wallpaper]] for {{price|200}}: |
| + | <syntaxhighlight lang="js"> |
| + | { |
| + | "ItemId": "RANDOM_ITEMS (WP)", |
| + | "Price": 200 |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | Or a random [[House Plant|house plant]]: |
| + | <syntaxhighlight lang="js"> |
| + | { |
| + | "ItemId": "RANDOM_ITEMS (F) @has_id_in_base_range 1376 1390" |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | Or a random [[#Custom items|custom item]] added by a mod by its item ID prefix: |
| + | <syntaxhighlight lang="js"> |
| + | { |
| + | "ItemId": "RANDOM_ITEMS (O) @has_id_prefix AuthorName_ModName_" |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | Or 10 random objects with any category except <samp>-13</samp> or <samp>-14</samp>: |
| + | <syntaxhighlight lang="js"> |
| + | { |
| + | "ItemId": "RANDOM_ITEMS (O) @has_category @!has_category -13 -14 @count 10" |
| + | } |
| + | </syntaxhighlight> |
| + | |- |
| + | | <samp>SHOP_TOWN_KEY</samp> |
| + | | The special [[Key To The Town|town key]] item. This is only valid in shops. |
| + | |- |
| + | | <samp>TOOL_UPGRADES {{o|tool ID}}</samp> |
| + | | The tool upgrades listed in <samp>Data/Shops</samp> whose conditions match the player's inventory (i.e. the same rules as [[Blacksmith|Clint's tool upgrade shop]]). If {{o|tool ID}} is specified, only upgrades which consume that tool ID are shown. |
| + | |} |
| | | |
| ===More <samp>modData</samp> fields=== | | ===More <samp>modData</samp> fields=== |
Line 5,343: |
Line 5,343: |
| | ''Syntax:'' <samp>iq {{t|query}}</samp> | | | ''Syntax:'' <samp>iq {{t|query}}</samp> |
| | | |
− | Open a shop menu with all the items matching an [[#Item search query|item query]] (all items free). For example: | + | Open a shop menu with all the items matching an [[#Item queries|item query]] (all items free). For example: |
| * <samp>debug iq ALL_ITEMS</samp> shows all items; | | * <samp>debug iq ALL_ITEMS</samp> shows all items; |
| * <samp>debug iq ALL_ITEMS (W)</samp> shows all weapons; | | * <samp>debug iq ALL_ITEMS (W)</samp> shows all weapons; |