Changes

Jump to navigation Jump to search
Fix query name (see GameStateQuery.cs)
Line 1: Line 1: −
{{upcoming|1.6}}
  −
   
← [[Modding:Index|Index]]
 
← [[Modding:Index|Index]]
   −
This page documents '''game state queries''', a built-in way to specify conditions in some of the game's data assets.
+
This page documents '''game state queries''', a built-in way to specify conditions in some of the game's data assets inspired by [[Modding:Content Patcher|Content Patcher]]'s conditions.
   −
==From migration guide==
+
==Overview==
A ''game state query'' is a vanilla way to specify conditions for some content like [[#Custom shops|shop data]], inspired by [[Modding:Content Patcher|Content Patcher]]'s conditions. A query consists of a comma-delimited list of conditions in the form {{t|type}} {{o|arguments}}. The type can be prefixed with <code>!</code> to negate it. The query is true if it's null/blank, or if every listed condition exists and is true. For example, <code>!SEASON Spring, WEATHER Here Sun</code> is true on sunny non-[[spring]] days.
+
===Query format===
 +
A query consists of a comma-delimited list of conditions in the form {{t|type}} {{o|arguments}}. The type can be prefixed with <code>!</code> to negate it. The query is true if it's null/blank, or if every listed condition exists and is true. For example, <code>!SEASON Spring, WEATHER Here Sun</code> is true on sunny non-[[spring]] days.
    
'''⚠''' Game state queries are partly case-sensitive. While some values are case-insensitive (e.g. both <code>SEASON Spring</code> and <code>SEASON spring</code> will work), this isn't consistent. Using the exact capitalization is recommended to avoid issues.
 
'''⚠''' Game state queries are partly case-sensitive. While some values are case-insensitive (e.g. both <code>SEASON Spring</code> and <code>SEASON spring</code> will work), this isn't consistent. Using the exact capitalization is recommended to avoid issues.
   −
====Argument format====
+
===Argument format===
Game state queries take space-delimited arguments. For example, <code>BUILDINGS_CONSTRUCTED Here Cabins</code> has two arguments: <code>Here</code> and <code>Cabins</code>.
+
Game state queries can take space-delimited arguments. For example, <code>BUILDINGS_CONSTRUCTED Here Cabins</code> has two arguments: <code>Here</code> and <code>Cabins</code>.
 +
 
 +
If you have spaces within an argument, you can surround it with quotes to keep it together. For example, <code>BUILDINGS_CONSTRUCTED Here "Junimo Hut"</code> passes <code>Junimo Hut</code> as one argument. You can escape inner quotes with backslashes, like <code>ANY "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""</code>.
 +
 
 +
Remember that quotes and backslashes inside JSON strings need to be escaped too. For example, <code>"Condition": "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""</code> will send <code>BUILDINGS_CONSTRUCTED Here "Junimo Hut"</code> to the game code. Alternatively, you can use single-quotes for the JSON string instead, like <code>"Condition": 'BUILDINGS_CONSTRUCTED Here "Junimo Hut"'</code>.
 +
 
 +
===Queries versus Content Patcher conditions===
 +
When making [[Modding:Content Patcher|Content Patcher packs]], you may be able to achieve a certain effect with either <samp>When</samp> conditions or game state queries (with different formatting in either case, but the same end result).
   −
You can add quotes to keep spaces within an argument. For example, <code>BUILDINGS_CONSTRUCTED Here "Junimo Hut"</code> passes <code>Junimo Hut</code> as one argument. You can escape inner quotes with backslashes like <code>ANY "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""</code>. Remember that quotes and backslashes inside JSON strings need to be escaped too, like <code>"Condition": "BUILDINGS_CONSTRUCTED Here \"Junimo Hut\""</code>.
+
Which you use is mainly a performance tradeoff:
 +
* Content Patcher's <samp>When</samp> conditions are highly optimized and cached, so thousands of patches can check the same condition without impacting performance and the resulting changes are written once to the asset. Then there's no performance impact after the asset edit, since it's just plain unconditional data. However the asset is reloaded when patches are added/removed, which may impact performance if they change often in some cases (like reloading a map or indoor/outdoor NPC appearance).
 +
* A game state query has no caching, so it can significantly affect performance when it's checked often. For example, a thousand game state queries checked each update tick means sixty thousand condition evaluations per second. On the other hand, game state queries are faster in cases where the conditions are checked rarely and doing so avoids reloading textures or maps (like <samp>Appearance</samp> in <samp>Data/Characters</samp> or <samp>Music</samp> in <samp>Data/Locations</samp>).
   −
====Conditions====
+
==Built-in queries==
<dl>
+
===Meta===
<dt>Meta</dt>
  −
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 27: Line 33:  
| Get whether at least one of the listed game state queries match, where each argument is a query. For example, <code>ANY "SEASON Winter" "SEASON Spring, DAY_OF_WEEK Friday"</code> is true if (a) it's winter or (b) it's a spring Friday. You can list any number of queries to check.
 
| Get whether at least one of the listed game state queries match, where each argument is a query. For example, <code>ANY "SEASON Winter" "SEASON Spring, DAY_OF_WEEK Friday"</code> is true if (a) it's winter or (b) it's a spring Friday. You can list any number of queries to check.
 
|}
 
|}
</dd>
     −
<dt>Date & time</dt>
+
You can nest ANY tokens inside of ANY tokens, but you're likely to get yourself into quote escaping madness if you try. Instead, approach as Sum of Products.
<dd>
+
 
 +
Here's an example.
 +
 
 +
<pre> "ANY \"LOCATION_NAME Here BathHouse_Pool\" \"LOCATION_NAME Here BathHouse_MensLocker\" \"LOCATION_NAME Here BathHouse_WomensLocker\" \"LOCATION_NAME Here Beach, WEATHER Sun Wind, SEASON Summer\" \"IS_EVENT festival_summer5, {{HasMod|contains=spacechase0.SurfingFestival}}\""</pre>
 +
 
 +
Broken down, this means:
 +
 
 +
* ANY of the following locations: BathHouse_Pool, BathHouse_MensLocker, BathHouse_WomensLocker.
 +
* The location Beach but only if it's sunny or windy, and it's summer
 +
* The event (in this case festival) summer5 is active, and spacechase0.SurfingFestival is installed, as the <samp><nowiki>{{</nowiki>HasMod|contains=spacechase0.SurfingFestival}}</samp> token will either resolve to true or false, which are valid tokens.
 +
 
 +
Remember: you can token inside GSQ!
 +
 
 +
===Date & time===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 45: Line 63:  
| Whether {{t|min}} to {{o|max}} (default unlimited) days have been played in the current save (including the current one). This always increments in sync with the date in the base game, but when mods change the in-game date, they may or may not update this value.
 
| Whether {{t|min}} to {{o|max}} (default unlimited) days have been played in the current save (including the current one). This always increments in sync with the date in the base game, but when mods change the in-game date, they may or may not update this value.
 
|-
 
|-
| <samp>IS_FESTIVAL_DAY {{o|day offset}}</samp>
+
| <samp>IS_FESTIVAL_DAY {{o|location context}} {{o|day offset}}</samp>
 
| Whether there's a festival today, with an optional {{o|day offset}} (e.g. 1 for tomorrow).
 
| Whether there's a festival today, with an optional {{o|day offset}} (e.g. 1 for tomorrow).
 +
 +
The {{o|location context}} (default <samp>Any</samp>) must be one of these values:
 +
{| class="wikitable"
 +
|-
 +
! value
 +
! effect
 +
|-
 +
| <samp>Any</samp>
 +
| Check for a festival anywhere.
 +
|-
 +
| <samp>Here</samp>
 +
| Check for a festival in the location context containing the player.
 +
|-
 +
| <samp>Target</samp>
 +
| Check for a festival in the location context containing [[#Target location|the target location]].
 +
|-
 +
| ''any other''
 +
| Check for a festival in the given location context ID.
 +
|}
 
|-
 
|-
 
| <samp>IS_PASSIVE_FESTIVAL_OPEN {{t|id}}</samp>
 
| <samp>IS_PASSIVE_FESTIVAL_OPEN {{t|id}}</samp>
| Whether a [[#Custom passive festivals|passive festival]] with the given ID is active today, and the current time is within its opening hours.
+
| Whether a [[Modding:Migrate to Stardew Valley 1.6#Custom passive festivals|passive festival]] with the given ID is active today, and the current time is within its opening hours.
 
|-
 
|-
 
| <samp>IS_PASSIVE_FESTIVAL_TODAY {{t|id}}</samp>
 
| <samp>IS_PASSIVE_FESTIVAL_TODAY {{t|id}}</samp>
| Whether a [[#Custom passive festivals|passive festival]] with the given ID is active today.
+
| Whether a [[Modding:Migrate to Stardew Valley 1.6#Custom passive festivals|passive festival]] with the given ID is active today.
 
|-
 
|-
 
| <samp>SEASON {{t|season}}+</samp>
 
| <samp>SEASON {{t|season}}+</samp>
Line 66: Line 103:  
| Whether the current year is between {{t|min}} and {{o|max}} (default unlimited) inclusively.
 
| Whether the current year is between {{t|min}} and {{o|max}} (default unlimited) inclusively.
 
|}
 
|}
</dd>
     −
<dt>Events</dt>
+
===Events===
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 75: Line 110:  
! effect
 
! effect
 
|-
 
|-
| <samp>EVENT_ID {{t|event ID}}+</samp>
+
| <samp>IS_EVENT</samp>
| Whether one of the the given [[Modding:Event data|event]] IDs are currently playing.
+
| Whether the player is viewing any [[Modding:Event data|event]] or attending any active festival. This doesn't cover passive festivals like the [[Night Market]].
 +
|-
 +
| <samp>IS_EVENT {{t|event ID}}+</samp>
 +
| Whether the player is viewing an [[Modding:Event data|event]] or attending an active festival whose ID matches one of the specified {{t|event ID}} values. Festivals have IDs in the form <samp>festival_{{t|season}}{{t|day}}</samp> (like <samp>festival_spring13</samp> for the [[Egg Festival]]).
 
|}
 
|}
</dd>
     −
<dt>World</dt>
+
===World===
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 107: Line 143:  
| Whether there are fewer of the given building constructed than there are cabins.
 
| Whether there are fewer of the given building constructed than there are cabins.
 
|-
 
|-
| <samp>FARM_CAVE {{t|type}}</samp>
+
| <samp>FARM_CAVE {{t|type}}+</samp>
 
| The current [[The Farm#The Cave|farm cave]] (one of <samp>Bats</samp>, <samp>Mushrooms</samp>, or <samp>None</samp>).
 
| The current [[The Farm#The Cave|farm cave]] (one of <samp>Bats</samp>, <samp>Mushrooms</samp>, or <samp>None</samp>).
 
|-
 
|-
Line 113: Line 149:  
| The name of the farm.
 
| The name of the farm.
 
|-
 
|-
| <samp>FARM_TYPE {{t|type}}</samp>
+
| <samp>FARM_TYPE {{t|type}}+</samp>
 
| The [[Farm Maps|farm type]]. The {{t|type}} can be one of...
 
| The [[Farm Maps|farm type]]. The {{t|type}} can be one of...
 
* a numeric ID for a vanilla farm type: <samp>1</samp> (standard), <samp>2</samp> (riverland), <samp>3</samp> (forest), <samp>4</samp> (hilltop), <samp>5</samp> (combat), <samp>6</samp> (four corners), or <samp>7</samp> (beach);
 
* a numeric ID for a vanilla farm type: <samp>1</samp> (standard), <samp>2</samp> (riverland), <samp>3</samp> (forest), <samp>4</samp> (hilltop), <samp>5</samp> (combat), <samp>6</samp> (four corners), or <samp>7</samp> (beach);
Line 121: Line 157:  
| <samp>FOUND_ALL_LOST_BOOKS</samp>
 
| <samp>FOUND_ALL_LOST_BOOKS</samp>
 
| Whether all the [[Lost Books]] for the [[museum]] have been found.
 
| Whether all the [[Lost Books]] for the [[museum]] have been found.
 +
|-
 +
| <samp>HAS_TARGET_LOCATION</samp>
 +
| Whether the [[#Target location|'<samp>Target</samp>' location]] is explicitly set for the current context (ignoring the fallback to the current player's location).
 
|-
 
|-
 
| <samp>IS_COMMUNITY_CENTER_COMPLETE</samp>
 
| <samp>IS_COMMUNITY_CENTER_COMPLETE</samp>
Line 146: Line 185:  
| Whether the [[#Target location|given location]] is accessible. For vanilla locations, this is relevant to <samp>CommunityCenter</samp>, <samp>JojaMart</samp>, or <samp>Railroad</samp>; any other location will return true unless a mod customizes the query.
 
| Whether the [[#Target location|given location]] is accessible. For vanilla locations, this is relevant to <samp>CommunityCenter</samp>, <samp>JojaMart</samp>, or <samp>Railroad</samp>; any other location will return true unless a mod customizes the query.
 
|-
 
|-
| <samp>LOCATION_CONTEXT {{t|location}}</samp>
+
| <samp>LOCATION_CONTEXT {{t|location}} {{t|context ID}}+</samp>
| The location context name for the [[#Target location|given location]].
+
| The location context ID for the [[#Target location|given location]].
 +
|-
 +
| <samp>LOCATION_HAS_CUSTOM_FIELD {{t|location}} {{t|key}} {{o|value}}</samp>
 +
| Checks to see if the location has a given value in its CustomFields. If the value is omitted, checks to see if the key exists at all.
 
|-
 
|-
 
| <samp>LOCATION_IS_INDOORS {{t|location}}</samp><br /><samp>LOCATION_IS_OUTDOORS {{t|location}}</samp><br /><samp>LOCATION_IS_MINES {{t|location}}</samp><br /><samp>LOCATION_IS_SKULL_CAVE {{t|location}}</samp>
 
| <samp>LOCATION_IS_INDOORS {{t|location}}</samp><br /><samp>LOCATION_IS_OUTDOORS {{t|location}}</samp><br /><samp>LOCATION_IS_MINES {{t|location}}</samp><br /><samp>LOCATION_IS_SKULL_CAVE {{t|location}}</samp>
Line 156: Line 198:  
|-
 
|-
 
| <samp>LOCATION_SEASON {{t|location}} [{{t|season}}]+</samp>
 
| <samp>LOCATION_SEASON {{t|location}} [{{t|season}}]+</samp>
| Whether the [[#Target location|given location]] is in one of the given seasons (which can be <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>). This accounts for the <samp>SeasonOverride</samp> field in the [[#Custom location contexts|location's context data]].
+
| Whether the [[#Target location|given location]] is in one of the given seasons (which can be <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>). This accounts for the <samp>SeasonOverride</samp> field in the [[Modding:Migrate to Stardew Valley 1.6#Custom location contexts|location's context data]].
    
For example, this is valid in spring ''or'' summer: <code>LOCATION_SEASON Here spring summer</code>.
 
For example, this is valid in spring ''or'' summer: <code>LOCATION_SEASON Here spring summer</code>.
Line 164: Line 206:  
|-
 
|-
 
| <samp>WEATHER {{t|location}} {{t|weather}}</samp>
 
| <samp>WEATHER {{t|location}} {{t|weather}}</samp>
| The weather ID in the [[#Target location|given location]]. The weather can be one of <samp>Festival</samp>, <samp>Rain</samp>, <samp>Snow</samp>, <samp>Storm</samp>, <samp>Sun</samp>, <samp>Wind</samp>, or a [[#Custom weather|custom weather ID]].
+
| The weather ID in the [[#Target location|given location]]. The weather can be one of <samp>Festival</samp>, <samp>Rain</samp>, <samp>Snow</samp>, <samp>Storm</samp>, <samp>Sun</samp>, <samp>Wind</samp>, or a [[Modding:Migrate to Stardew Valley 1.6#Custom weather|custom weather ID]].
 
|-
 
|-
 
| <samp>WORLD_STATE_FIELD {{t|name}} {{t|value}}</samp>
 
| <samp>WORLD_STATE_FIELD {{t|name}} {{t|value}}</samp>
Line 216: Line 258:  
| For numeric properties only, whether a property on <samp>Game1.netWorldState</samp> has a value between {{t|min}} and {{o|max}} (default unlimited). If {{o|max}} is omitted or the properties isn't numeric, the previous form is used. See the previous entry for a list of useful properties.
 
| For numeric properties only, whether a property on <samp>Game1.netWorldState</samp> has a value between {{t|min}} and {{o|max}} (default unlimited). If {{o|max}} is omitted or the properties isn't numeric, the previous form is used. See the previous entry for a list of useful properties.
 
|-
 
|-
| <samp>WORLD_STATE_ID {{t|id}}</samp>
+
| <samp>WORLD_STATE_ID {{t|id}}+</samp>
| Whether any world state flag with the given {{t|id}} is set.
+
| Whether any world state flag matching the given {{t|id}} values is set.
 
|}
 
|}
</dd>
     −
<dt>Player info & progress</dt>
+
===Player info & progress===
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 248: Line 288:  
| <samp>PLAYER_HAS_ALL_ACHIEVEMENTS {{t|player}}</samp>
 
| <samp>PLAYER_HAS_ALL_ACHIEVEMENTS {{t|player}}</samp>
 
| Whether the [[#Target player|specified player(s)]] have unlocked every achievement listed in [[Modding:Achievement data|<samp>Data/Achievements</samp>]]. This doesn't count the extra Steam achievement IDs that aren't listed in that file.
 
| Whether the [[#Target player|specified player(s)]] have unlocked every achievement listed in [[Modding:Achievement data|<samp>Data/Achievements</samp>]]. This doesn't count the extra Steam achievement IDs that aren't listed in that file.
 +
|-
 +
| <samp>PLAYER_HAS_BUFF {{t|player}} {{t|id}}</samp>
 +
| Whether the [[#Target player|specified player(s)]] have a given buff ID currently applied.
 
|-
 
|-
 
| <samp>PLAYER_HAS_CAUGHT_FISH {{t|player}} {{t|id}}</samp>
 
| <samp>PLAYER_HAS_CAUGHT_FISH {{t|player}} {{t|id}}</samp>
Line 255: Line 298:  
| Whether the [[#Target player|specified player(s)]] have a [[Modding:Dialogue#Conversation topics|conversation topic]] with the ID {{t|id}} active.
 
| Whether the [[#Target player|specified player(s)]] have a [[Modding:Dialogue#Conversation topics|conversation topic]] with the ID {{t|id}} active.
 
|-
 
|-
| <samp>PLAYER_HAS_CRAFTING_RECIPE {{t|player}} {{t|recipe name}}</samp><br /><samp>PLAYER_HAS_COOKING_RECIPE {{t|player}} {{t|recipe name}}</samp>
+
| <samp>PLAYER_HAS_COOKING_RECIPE {{t|player}} {{t|recipe name}}</samp><br /><samp>PLAYER_HAS_CRAFTING_RECIPE {{t|player}} {{t|recipe name}}</samp>
 
| Whether the [[#Target player|specified player(s)]] know the crafting/cooking recipe identified by its internal name (spaces allowed). For example, <code>PLAYER_HAS_CRAFTING_RECIPE Current Field Snack</code>.
 
| Whether the [[#Target player|specified player(s)]] know the crafting/cooking recipe identified by its internal name (spaces allowed). For example, <code>PLAYER_HAS_CRAFTING_RECIPE Current Field Snack</code>.
 
|-
 
|-
Line 261: Line 304:  
| Whether the [[#Target player|specified player(s)]] have chosen the given dialogue answer in a previous dialogue.
 
| Whether the [[#Target player|specified player(s)]] have chosen the given dialogue answer in a previous dialogue.
 
|-
 
|-
| <samp>PLAYER_HAS_FLAG {{t|player}} {{t|id}}</samp>
+
| <samp>PLAYER_HAS_HEARD_SONG {{t|player}} {{t|id}}</samp>
| Whether the [[#Target player|specified player(s)]] have the given [[Modding:Mail data|mail flag]] set (with spaces allowed in the {{t|id}}).
+
| Whether the [[#Target player|specified player(s)]] have heard a song track's cue name (e.g. for the [[jukebox]] track selection).
 
|-
 
|-
 
| <samp>PLAYER_HAS_ITEM {{t|player}} {{t|item}} {{o|min}} {{o|max}}</samp>
 
| <samp>PLAYER_HAS_ITEM {{t|player}} {{t|item}} {{o|min}} {{o|max}}</samp>
| Whether the [[#Target player|specified player(s)]] have between {{o|min}} and {{o|max}} (default unlimited) matching items in their inventory, inclusively. The {{t|item}} can be <samp>858</samp> or <samp>(O)858</samp> (Qi Gems), <samp>73</samp> or <samp>(O)73</samp> (Walnuts), or the [[#Custom items|qualified or unqualified item ID]].
+
| Whether the [[#Target player|specified player(s)]] have between {{o|min}} and {{o|max}} (default unlimited) matching items in their inventory, inclusively. The {{t|item}} can be <samp>858</samp> or <samp>(O)858</samp> (Qi Gems), <samp>73</samp> or <samp>(O)73</samp> (Walnuts), or the [[Modding:Common data field types#Item ID|qualified or unqualified item ID]].
 +
|-
 +
| <samp>PLAYER_HAS_MAIL {{t|player}} {{t|mail id}} {{o|type}}</samp>
 +
| Whether the [[#Target player|specified player(s)]] have the given [[Modding:Mail data|mail flag]] set.
 +
 
 +
The {{o|type}} (default <samp>Any</samp>) can be one of:
 +
{| class="wikitable"
 +
|-
 +
! type
 +
! effect
 +
|-
 +
| <samp>Any</samp>
 +
| Mail in [[The Farm#Mailbox|the mailbox]], in the queue for tomorrow's mailbox, or already received.
 +
|-
 +
| <samp>Mailbox</samp>
 +
| Mail in the mailbox.
 +
|-
 +
| <samp>Tomorrow</samp>
 +
| Mail in the queue for tomorrow's mailbox.
 +
|-
 +
| <samp>Received</samp>
 +
| Mail which either:
 +
* was in the mailbox and read by the player;
 +
* or has no letter in <samp>Data/mail</samp>, so it was added to the received list directly.
 +
|}
 
|-
 
|-
 
| <samp>PLAYER_HAS_PROFESSION {{t|player}} {{t|profession id}}</samp>
 
| <samp>PLAYER_HAS_PROFESSION {{t|player}} {{t|profession id}}</samp>
 
| Whether the [[#Target player|specified player(s)]] have the given [[Skills|profession]] ID.
 
| Whether the [[#Target player|specified player(s)]] have the given [[Skills|profession]] ID.
 
|-
 
|-
| <samp>PLAYER_HAS_READ_LETTER {{t|player}} {{t|id}}</samp>
+
| <samp>PLAYER_HAS_RUN_TRIGGER_ACTION {{t|player}} {{t|id}}</samp>
| Whether the [[#Target player|specified player(s)]] have read a letter, where {{t|id}} is the internal mail ID (spaces allowed). For example, <code>PLAYER_HAS_READ_LETTER Any Visited_Island</code>.
+
| Whether the [[#Target player|specified player(s)]] have applied the [[Modding:Trigger actions|trigger action]] with the given {{t|id}}.
 
|-
 
|-
 
| <samp>PLAYER_HAS_SECRET_NOTE {{t|player}} {{t|id}}</samp>
 
| <samp>PLAYER_HAS_SECRET_NOTE {{t|player}} {{t|id}}</samp>
Line 277: Line 344:  
|-
 
|-
 
| <samp>PLAYER_HAS_SEEN_EVENT {{t|player}} {{t|id}}</samp>
 
| <samp>PLAYER_HAS_SEEN_EVENT {{t|player}} {{t|id}}</samp>
| Whether the [[#Target player|specified player(s)]] have seen the event with given {{t|id}}.
+
| Whether the [[#Target player|specified player(s)]] have seen the event with the given {{t|id}}.
 
|-
 
|-
 
| <samp>PLAYER_HAS_TOWN_KEY {{t|player}}</samp>
 
| <samp>PLAYER_HAS_TOWN_KEY {{t|player}}</samp>
Line 286: Line 353:  
|-
 
|-
 
| <samp>PLAYER_LOCATION_CONTEXT {{t|player}} {{t|location context}}</samp>
 
| <samp>PLAYER_LOCATION_CONTEXT {{t|player}} {{t|location context}}</samp>
| Whether the [[#Target player|specified player(s)]] are in the given [[#Custom location contexts|location context]].
+
| Whether the [[#Target player|specified player(s)]] are in the given [[Modding:Migrate to Stardew Valley 1.6#Custom location contexts|location context]].
 
|-
 
|-
| <samp>PLAYER_LOCATION_NAME {{t|player}} {{t|location name}}</samp><br /><samp>PLAYER_LOCATION_UNIQUE_NAME {{t|player}} {{t|location name}}</samp>
+
| <samp>PLAYER_LOCATION_NAME {{t|player}} {{t|location name}}+</samp><br /><samp>PLAYER_LOCATION_UNIQUE_NAME {{t|player}} {{t|location name}}+</samp>
 
| Whether the [[#Target player|specified player(s)]] are in the given location, using the name or unique instanced name (you can see both names in-game using the {{nexus mod|679|Debug Mode}} mod). The {{t|location name}} value doesn't recognize [[#Target location|target location keywords]] like <samp>Here</samp>.
 
| Whether the [[#Target player|specified player(s)]] are in the given location, using the name or unique instanced name (you can see both names in-game using the {{nexus mod|679|Debug Mode}} mod). The {{t|location name}} value doesn't recognize [[#Target location|target location keywords]] like <samp>Here</samp>.
 
|-
 
|-
Line 296: Line 363:  
| <samp>PLAYER_MONEY_EARNED {{t|player}} {{t|min}} {{o|max}}</samp>
 
| <samp>PLAYER_MONEY_EARNED {{t|player}} {{t|min}} {{o|max}}</samp>
 
| Whether the [[#Target player|specified player(s)]] have earned between {{t|min}} and {{o|max}} (default unlimited) gold inclusively.
 
| Whether the [[#Target player|specified player(s)]] have earned between {{t|min}} and {{o|max}} (default unlimited) gold inclusively.
 +
|-
 +
| <samp>PLAYER_KILLED_MONSTERS {{t|player}} {{t|monster name}}+ {{o|min count}} {{o|max count}}</samp>
 +
| Whether the [[#Target player|specified player(s)]] have killed the given monster(s) between {{o|min count}} (default 1) and {{o|max count}} (default unlimited) times inclusively. If you list multiple monsters, it'll check the combined count for all of them.
 +
 +
For example:
 +
<syntaxhighlight lang="js">
 +
// killed 50+ slimes, skeletons, and bugs combined
 +
PLAYER_KILLED_MONSTERS Current "Green Slime" Skeleton Bug 50
 +
</syntaxhighlight>
 
|-
 
|-
 
| <samp>PLAYER_SHIPPED_BASIC_ITEM {{t|player}} {{t|item ID}} {{o|min count}} {{o|max count}}</samp>
 
| <samp>PLAYER_SHIPPED_BASIC_ITEM {{t|player}} {{t|item ID}} {{o|min count}} {{o|max count}}</samp>
Line 302: Line 378:  
| <samp>PLAYER_SPECIAL_ORDER_ACTIVE {{t|player}} {{t|order id}}</samp>
 
| <samp>PLAYER_SPECIAL_ORDER_ACTIVE {{t|player}} {{t|order id}}</samp>
 
| Whether the [[#Target player|specified player(s)]] have the given [[Special Orders|special order]] active.
 
| Whether the [[#Target player|specified player(s)]] have the given [[Special Orders|special order]] active.
 +
|-
 +
| <samp>PLAYER_SPECIAL_ORDER_COMPLETE {{t|player}} {{t|order id}}</samp>
 +
| Whether the [[#Target player|specified player(s)]] have completed the given [[Special Orders|special order]].
 
|-
 
|-
 
| <samp>PLAYER_SPECIAL_ORDER_RULE_ACTIVE {{t|player}} {{t|rule id}}</samp>
 
| <samp>PLAYER_SPECIAL_ORDER_RULE_ACTIVE {{t|player}} {{t|rule id}}</samp>
| Whether the [[#Target player|specified player(s)]] have a special rule active for a [[Special Orders|special order]]. Some vanilla rules are...
+
| Whether the [[#Target player|specified player(s)]] have a [[Modding:Special orders#Special rules|special rule]] active.
 
  −
{| class="wikitable"
  −
|-
  −
! rule ID
  −
! effect
  −
|-
  −
| <samp>DROP_QI_BEANS</samp>
  −
| The player can find [[Qi Beans]] for the ''Qi's Crop'' order.
  −
|-
  −
| <samp>LEGENDARY_FAMILY</samp>
  −
| The player catch the new legendary fish for the ''Extended Family'' order.
  −
|-
  −
| <samp>MINE_HARD</samp><br /><samp>SC_HARD</samp>
  −
| Raises the difficulty level of the mines or [[Skull Cavern]].
  −
|-
  −
| <samp>SC_NO_FOOD</samp>
  −
| The player can't eat food in the [[Skull Cavern]].
  −
|}
   
|-
 
|-
 
| <samp>PLAYER_STAT {{t|player}} {{t|stat name}} {{t|min value}} {{o|max value}}</samp>
 
| <samp>PLAYER_STAT {{t|player}} {{t|stat name}} {{t|min value}} {{o|max value}}</samp>
Line 386: Line 447:  
* <samp>walnutsFound</samp>;
 
* <samp>walnutsFound</samp>;
 
* <samp>weedsEliminated</samp>.
 
* <samp>weedsEliminated</samp>.
 +
|-
 +
| <samp>PLAYER_VISITED_LOCATION {{t|player}} {{t|location name}}+</samp>
 +
| Whether the [[#Target player|specified player(s)]] have visited one of the given location names. For example, <code>PLAYER_VISITED_LOCATION Current IslandWest</code> checks whether the current player has ever visited [[Ginger Island#Island West|Ginger Island West]].
 +
 +
Notes:
 +
* Some locations have both a common name (like <samp>Barn</samp>) and unique name (like <samp>Barn{unique ID}</samp>). This tracks the common name.
 +
* Generated mine and volcano dungeon levels aren't tracked.
 
|}
 
|}
</dd>
     −
<dt>Player relationships</dt>
+
===Player relationships===
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Condition
 
! Condition
 
! effect
 
! effect
 +
|-
 +
| <samp>PLAYER_FRIENDSHIP_POINTS {{t|player}} {{t|npc}} {{t|min points}} {{o|max points}}</samp>
 +
| Whether the [[#Target player|specified player(s)]] have a friend with [[friendship|friendship points]] between {{t|min points}} and {{o|max points}} (default unlimited) inclusively. The {{t|npc}} can be an NPC's internal name, <samp>Any</samp> (check every NPC), or <samp>AnyDateable</samp> (check every romanceable NPC).
 +
 +
For example, this checks if the current player has 750 or more points (i.e. 3+ hearts) with Abigail:
 +
<pre>PLAYER_FRIENDSHIP_POINTS Current Abigail 750</pre>
 
|-
 
|-
 
| <samp>PLAYER_HAS_CHILDREN {{t|player}} {{o|min}} {{o|max}}</samp>
 
| <samp>PLAYER_HAS_CHILDREN {{t|player}} {{o|min}} {{o|max}}</samp>
Line 403: Line 475:  
|-
 
|-
 
| <samp>PLAYER_HEARTS {{t|player}} {{t|npc}} {{t|min hearts}} {{o|max hearts}}</samp>
 
| <samp>PLAYER_HEARTS {{t|player}} {{t|npc}} {{t|min hearts}} {{o|max hearts}}</samp>
| Whether the [[#Target player|specified player(s)]] have a friend with a [[friendship]] level between {{t|min hearts}} and {{o|max hearts}} (default unlimited) inclusively. The {{t|npc}} can be an NPC's internal name, <samp>Any</samp> (check every NPC), or <samp>AnyDateable</samp> (check every romanceable NPC).
+
| Whether the [[#Target player|specified player(s)]] have a friend with a [[friendship|heart level]] between {{t|min hearts}} and {{o|max hearts}} (default unlimited) inclusively. The {{t|npc}} can be an NPC's internal name, <samp>Any</samp> (check every NPC), or <samp>AnyDateable</samp> (check every romanceable NPC).
 +
 
 +
For example, this checks if the current player has 3 or more hearts with Abigail:
 +
<pre>PLAYER_HEARTS Current Abigail 3</pre>
 +
|-
 +
| <samp>PLAYER_HAS_MET {{t|player}} {{t|npc}}+</samp>
 +
| Whether the [[#Target player|specified player(s)]] have talked to one of the given NPCs at least once. The {{t|npc}} is an NPC's internal name.
 +
|-
 +
| <samp>PLAYER_NPC_RELATIONSHIP {{t|player}} {{t|npc}} {{t|type}}+</samp>
 +
| Whether the [[#Target player|specified player(s)]] have one of the relationship statuses with an NPC. The {{t|npc}} can be an NPC's internal name or <samp>Any</samp> (match any NPC).
 +
 
 +
{{t|type}} can be any combination of these values:
 +
{| class="wikitable"
 +
|-
 +
! type
 +
! effect
 +
|-
 +
| <samp>Friendly</samp>
 +
| Met the NPC, but no other status applies.
 
|-
 
|-
| <samp>PLAYER_HAS_MET {{t|player}} {{t|npc}}</samp>
+
| <samp>Roommate</samp>
| Whether the [[#Target player|specified player(s)]] have talked to an NPC at least once. The {{t|npc}} is an NPC's internal name.
+
| The NPC has moved in with the player as a roommate.
 
|-
 
|-
| <samp>PLAYER_IS_DATING {{t|player}} {{t|npc}}</samp><br /><samp>PLAYER_IS_ENGAGED {{t|player}} {{t|target}}</samp><br /><samp>PLAYER_IS_MARRIED {{t|player}} {{t|target}}</samp><br /><samp>PLAYER_IS_DIVORCED {{t|player}} {{t|npc}}</samp>
+
| <samp>Dating</samp>
| Whether the [[#Target player|specified player(s)]] have this relationship status with an NPC. The player is dating after giving the NPC a [[bouquet]], and engaged after giving a [[Mermaid's Pendant]] but before the marriage. The {{t|npc}} can be an NPC's internal name, or <samp>Any</samp> (check every romanceable NPC).
+
| The player has given a [[bouquet]] to the NPC, but haven't yet given them a [[Mermaid's Pendant|mermaid's pendant]].
 
|-
 
|-
| <samp>PLAYER_IS_ROOMMATE {{t|player}} {{t|target}}</samp>
+
| <samp>Engaged</samp>
| Whether the [[#Target player|specified player(s)]] have a roommate. The {{t|target}} can be an NPC's internal name, <samp>Any</samp> (with any NPC), or <samp>Player</samp> (always false).
+
| The player has given a [[Mermaid's Pendant|mermaid's pendant]] to the NPC, but the marriage hasn't happened yet.
 
|-
 
|-
| <samp>PLAYER_PREFERRED_PET {{t|player}} {{t|pet}}</samp>
+
| <samp>Married</samp>
| Whether the preferred pet for the [[#Target player|specified player(s)]] is <samp>Cat</samp>, <samp>Dog</samp>, or a specified custom pet type.
+
| The NPC has moved in with the player as a spouse.
 +
|-
 +
| <samp>Divorced</samp>
 +
| The player has dissolved their marriage with the NPC.
 
|}
 
|}
</dd>
+
|-
 +
| <samp>PLAYER_PLAYER_RELATIONSHIP {{t|player}} {{t|other player}} {{t|type}}+</samp>
 +
| Whether the [[#Target player|specified player(s)]] have one of the relationship types with the other specified player(s). The {{t|other player}} can be a [[#Target player|target player]] or <samp>Any</samp> (match any player).
   −
<dt>Randomization</dt>
+
{{t|type}} can be any combination of these values:
<dd>
+
{| class="wikitable"
 +
|-
 +
! type
 +
! effect
 +
|-
 +
| <samp>Friendly</samp>
 +
| No other status applies.
 +
|-
 +
| <samp>Engaged</samp>
 +
| One of the players has given a [[Wedding Ring|wedding ring]] to the other, but the marriage hasn't happened yet.
 +
|-
 +
| <samp>Married</samp>
 +
| The players are married.
 +
|}
 +
|-
 +
| <samp>PLAYER_PREFERRED_PET {{t|player}} {{t|pet type}}+</samp>
 +
| Whether the preferred pet for the [[#Target player|specified player(s)]] is one of the given types. The vanilla pet types are <samp>Cat</samp> and <samp>Dog</samp>.
 +
|}
 +
 
 +
===Randomization===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 429: Line 543:  
| A random probability check which is re-rolled each time it's called. For example, <code>RANDOM 0.4</code> is true 40% of the time.
 
| A random probability check which is re-rolled each time it's called. For example, <code>RANDOM 0.4</code> is true 40% of the time.
   −
If the exact text <samp>@addDailyLuck</samp> is specified, the current player's [[Daily Luck|daily luck]] is added to the probability.
+
If the exact text <samp>@addDailyLuck</samp> is specified, the current player's daily [[luck]] is added to the probability.
 
|-
 
|-
 
| <samp>SYNCED_CHOICE {{t|interval}} {{t|key}} {{t|min}} {{t|max}} {{t|choices}}+</samp>
 
| <samp>SYNCED_CHOICE {{t|interval}} {{t|key}} {{t|min}} {{t|max}} {{t|choices}}+</samp>
Line 443: Line 557:  
For example, <samp>SYNCED_RANDOM day cart_rare_seed 0.4</samp> has a 40% chance to be true the first time it's called that day, and will always be the same value if called again with the same key on the same day.
 
For example, <samp>SYNCED_RANDOM day cart_rare_seed 0.4</samp> has a 40% chance to be true the first time it's called that day, and will always be the same value if called again with the same key on the same day.
   −
If the exact text <samp>@addDailyLuck</samp> is specified, the current player's [[Daily Luck|daily luck]] is added to the probability.
+
If the exact text <samp>@addDailyLuck</samp> is specified, the current player's daily [[luck]] is added to the probability.
 
|-
 
|-
 
| <samp>SYNCED_SUMMER_RAIN_RANDOM {{t|base chance}} {{t|day multiplier}}</samp>
 
| <samp>SYNCED_SUMMER_RAIN_RANDOM {{t|base chance}} {{t|day multiplier}}</samp>
 
| A specialized variant of <samp>SYNCED_DAY_RANDOM</samp> used to calculate the chance of rain in summer, which increases with the day number.
 
| A specialized variant of <samp>SYNCED_DAY_RANDOM</samp> used to calculate the chance of rain in summer, which increases with the day number.
 
|}
 
|}
</dd>
     −
<dt>For items only</dt>
+
===For items only===
<dd>
   
These queries apply in cases where there's an item (e.g. machine recipes, shops, etc); they'll return false if not applicable. They take a {{t|type}} argument which can be <samp>Input</samp> (the machine input item) or <samp>Target</samp> (the machine output, tree fruit, shop item, etc).
 
These queries apply in cases where there's an item (e.g. machine recipes, shops, etc); they'll return false if not applicable. They take a {{t|type}} argument which can be <samp>Input</samp> (the machine input item) or <samp>Target</samp> (the machine output, tree fruit, shop item, etc).
   Line 459: Line 571:  
! effect
 
! effect
 
|-
 
|-
| <samp>ITEM_HAS_EDIBILITY {{t|target}} {{o|min}} {{o|max}}</samp>
+
| <samp>ITEM_CATEGORY {{t|target}}</samp>
| Whether the item's edibility is between {{o|min}} (default -299) and {{o|max}} (default unlimited) inclusively. A value of -300 is inedible, so <samp>ITEM_HAS_EDIBILITY {{t|target}}</samp> without min/max values checks if the item is edible.
+
| Whether the item has a non-zero [[Modding:Items#Category|category]].
 +
|-
 +
| <samp>ITEM_CATEGORY {{t|target}} {{o|category}}+</samp>
 +
| Whether the item's [[Modding:Items#Category|category]] number matches one of the given values.
 +
|-
 +
| <samp>ITEM_CONTEXT_TAG {{t|target}} {{t|tags}}</samp>
 +
| Whether the item has all of the given space-delimited tags. For example, <code>ITEM_CONTEXT_TAG Target bone_item marine_item</code> will only match items with both tags.
 +
|-
 +
| <samp>ITEM_EDIBILITY {{t|target}} {{o|min}} {{o|max}}</samp>
 +
| Whether the item's edibility is between {{o|min}} (default -299) and {{o|max}} (default unlimited) inclusively. A value of -300 is inedible, so <samp>ITEM_EDIBILITY {{t|target}}</samp> without min/max values checks if the item is edible.
 +
|-
 +
| <samp>ITEM_ID {{t|target}} {{t|item ID}}+</samp>
 +
| Whether the item has one of the given [[Modding:Common data field types#Item ID|qualified or unqualified item IDs]].
 
|-
 
|-
| <samp>ITEM_HAS_TAG {{t|target}} {{t|tags}}</samp>
+
| <samp>ITEM_ID_PREFIX {{t|target}} {{t|prefix}}</samp>
| Whether the item has all of the given space-delimited tags. For example, <code>ITEM_HAS_TAG Target bone_item marine_item</code> will only match items with both tags.
+
| Whether the item's [[Modding:Common data field types#Item ID|qualified or unqualified item ID]] starts with the given prefix.
 
|-
 
|-
| <samp>ITEM_ID {{t|target}} {{t|item ID}}</samp>
+
| <samp>ITEM_NUMERIC_ID {{t|target}} {{o|min}} {{o|max}}</samp>
| Whether the item has the given [[#Custom items|qualified or unqualified item ID]]. The item ID is qualified before checking, so <samp>128</samp> will match pufferfish (<samp>(O)128</samp>) but not mushroom boxes (<samp>(BC)128</samp>).
+
| Whether the item has a numeric [[Modding:Common data field types#Item ID|unqualified item ID]] which is between {{o|min}} and {{o|max}} (both defaulting to the lowest and highest possible value).
 +
|-
 +
| <samp>ITEM_OBJECT_TYPE {{t|target}} {{t|type}}+</samp>
 +
| Whether the item has one of the given [[Modding:Items#Objects|object types]].
 +
|-
 +
| <samp>ITEM_PRICE {{t|target}} {{t|min}} {{o|max}}</samp>
 +
| Whether the item has a purchase-from-shop price between {{t|min}} and {{o|max}} (default highest possible value).
 
|-
 
|-
 
| <samp>ITEM_QUALITY {{t|target}} {{t|min}} {{o|max}}</samp>
 
| <samp>ITEM_QUALITY {{t|target}} {{t|min}} {{o|max}}</samp>
Line 474: Line 604:  
| Whether the item stack size is between {{t|min}} and {{o|max}} (default unlimited) inclusively. Note that this only applies to the target item, it doesn't include other stacks in the inventory.
 
| Whether the item stack size is between {{t|min}} and {{o|max}} (default unlimited) inclusively. Note that this only applies to the target item, it doesn't include other stacks in the inventory.
 
|-
 
|-
| <samp>ITEM_TYPE {{t|target}} {{t|type}}</samp>
+
| <samp>ITEM_TYPE {{t|target}} {{t|type}}+</samp>
| Whether the [[#Custom items|item's type definition ID]] matches the given value. For example, <samp>ITEM_TYPE Target (BC)</samp> matches bigcraftables.
+
| Whether the [[Modding:Common data field types#Item ID|item's type definition ID]] matches one of the given values. For example, <samp>ITEM_TYPE Target (BC)</samp> matches bigcraftables.
 +
|-
 +
| <samp>ITEM_HAS_EXPLICIT_OBJECT_CATEGORY {{t|target}}</samp>
 +
| ''(Specialized)'' Whether the item has an explicit category set in <samp>Data/Objects</samp>, ignoring categories assigned dynamically in code (e.g. for rings). Items without an explicit category are often (but not always) special items like [[Secret Notes|secret notes]] or unimplemented items.
 
|}
 
|}
</dd>
     −
<dt>Immutable</dt>
+
===Immutable===
<dd>
   
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 492: Line 623:  
| A condition which never matches.
 
| A condition which never matches.
 
|}
 
|}
</dd>
  −
</dl>
     −
====Target location====
+
==Common values==
 +
===Target location===
 
Some conditions have a {{t|location}} argument. This can be one of...
 
Some conditions have a {{t|location}} argument. This can be one of...
 
{| class="wikitable"
 
{| class="wikitable"
Line 511: Line 641:  
|-
 
|-
 
| ''any other''
 
| ''any other''
| The [[#Custom locations|location ID]] (i.e. internal name) for the location to check.
+
| The [[Modding:Migrate to Stardew Valley 1.6#Custom locations|location ID]] (i.e. internal name) for the location to check.
 
|}
 
|}
   −
====Target player====
+
===Target player===
 
Some conditions have a {{t|player}} argument. This can be one of...
 
Some conditions have a {{t|player}} argument. This can be one of...
 
{| class="wikitable"
 
{| class="wikitable"
Line 560: Line 690:  
|}
 
|}
   −
====Using queries elsewhere====
+
==For C# mod authors==
C# code can use the <samp>GameStateQuery</samp> class to work with queries, like <code>GameStateQuery.CheckConditions(query)</code>.
+
===Using queries elsewhere===
 
+
C# code can work with queries using the <samp>GameStateQuery</samp> class, which provides utility methods like <code>GameStateQuery.CheckConditions(query)</code> or <code>GameStateQuery.IsImmutablyTrue(query)</code>.
You can also use game state queries in [[Modding:Event data|event preconditions]] using the new <samp>G</samp> condition flag, like <code>some_event_id/G !SEASON Spring, WEATHER Here Sun</code>.
     −
====Extensibility====
+
You can also use game state queries in [[Modding:Event data|event preconditions]] using the new precondition flag, like <code>some_event_id/gameStateQuery !SEASON Spring, WEATHER Here Sun</code>.
C# mods can check if a query exists using <code>GameStateQuery.Exists("Example.ModId_ConditionName")</code>, and define custom conditions using <code>GameStateQuery.Register("Example.ModId_ConditionName", handleQueryMethod)</code>. To avoid conflicts, prefixing custom condition names with your mod ID is strongly recommended.
      +
===Extensibility===
 +
C# mods can...
 +
* check if a query exists using <code>GameStateQuery.Exists("Example.ModId_ConditionName")</code>;
 +
* define custom queries using <code>GameStateQuery.Register("Example.ModId_ConditionName", handleQueryMethod)</code> (using a [[Modding:Common data field types#Unique string ID|unique string ID]] for the query name);
 +
* and add query aliases using <code>GameStateQuery.RegisterAlias("Example.ModId_AliasName", "Example.ModId_ConditionName")</code> (ideally using a [[Modding:Common data field types#Unique string ID|unique string ID]] for the alias).
    
[[Category:Modding]]
 
[[Category:Modding]]
28

edits

Navigation menu