Difference between revisions of "Modding:NPC data"

From Stardew Valley Wiki
Jump to navigation Jump to search
(update for Stardew Valley 1.6 (based on docs from Modding:Migrate to Stardew Valley 1.5.5 and Modding:Migrate to Stardew Valley 1.6; I'm the only author for the copied docs))
 
(33 intermediate revisions by 8 users not shown)
Line 6: Line 6:
  
 
==Files to edit==
 
==Files to edit==
To create a new NPC, you need to edit a number of different files. However, you don't need any programming experience and it can be done with {{nexus mod|1915|Content Patcher}}.
+
To create a new NPC, you need to edit a number of different files. However, you don't need any programming experience and it can be done with [[Modding:Content Patcher|Content Patcher]].
  
===Basic info===
+
===Main data===
The <tt>Data\NPCDispositions</tt> asset contains basic information for your character, including their name, birthday, relations to other characters, personality, and whether they can be dated.
+
The <samp>Data/Characters</samp> asset contains most of the data about an NPC. That includes their name, social info (e.g. personality, birthday, and romance), appearance, spouse room & patio, festival participation, etc.
  
The file has one row per NPC like this:
+
This consists of a string → model lookup, where...
<syntaxhighlight lang="yaml">
+
* The key is a [[Modding:Common data field types#Unique string ID|unique string ID]] for the NPC like <samp>Example.ModId_NpcName</samp>, which will be used as the internal <samp>Name</samp> (not <samp>DisplayName</samp>).
  Abigail: "teen/rude/outgoing/neutral/female/datable/Sebastian/Town/fall 13/Caroline 'mom' Pierre 'dad'/SeedShop 1 9/Abigail"
+
* The value is a model with the following fields.
 +
 
 +
====Basic info====
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>DisplayName</samp>
 +
| A [[Modding:Tokenizable strings|tokenizable string]] for the NPC's display name.
 +
|-
 +
| <samp>Language</samp>
 +
| ''(Optional)'' The language spoken by the NPC. One of <samp>Default</samp> (the default language understood by the player) or <samp>Dwarvish</samp> (which the player can only understand after finding the [[Dwarvish Translation Guide|Dwarvish translation guide]]). Default <samp>Default</samp>.
 +
|-
 +
| <samp>Gender</samp>
 +
| ''(Optional)'' The NPC's gender identity. One of <samp>Female</samp>, <samp>Male</samp>, or <samp>Undefined</samp>. Default <samp>Undefined</samp>.
 +
|-
 +
| <samp>Age</samp>
 +
| ''(Optional)'' The general age of the NPC. One of <samp>Child</samp>, <samp>Teen</samp>, or <samp>Adult</samp>. Default <samp>Adult</samp>.
 +
 
 +
This affects generated dialogue lines (e.g. a child might say "stupid" and an adult might say "depressing"), generic dialogue (e.g. a child might respond to dumpster diving with "''Eww... What are you doing?''" and a teen would say "''Um... Why are you digging in the trash?''"), and the gift they choose as [[Feast of the Winter Star]] gift-giver. Children are also excluded from item delivery quests.
 +
|-
 +
| <samp>Manner</samp>
 +
| ''(Optional)'' A measure of the character's general politeness, which affects some generic dialogue lines. One of <samp>Neutral</samp>, <samp>Polite</samp>, or <samp>Rude</samp>. Default <samp>Neutral</samp>.
 +
|-
 +
| <samp>SocialAnxiety</samp>
 +
| ''(Optional)'' A measure of the character's comfort with social situations, which affects some generic dialogue lines. One of <samp>Neutral</samp>, <samp>Outgoing</samp>, or <samp>Shy</samp>. Default <samp>Neutral</samp>.
 +
|-
 +
| <samp>Optimism</samp>
 +
| ''(Optional)'' A measure of the character's overall optimism. One of <samp>Neutral</samp>, <samp>Negative</samp>, or <samp>Positive</samp>. Default <samp>Neutral</samp>.
 +
|-
 +
| <samp>BirthSeason</samp>
 +
| ''(Optional if non-social)'' The season name (case-sensitive) for the NPC's birthday. One of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>. Default none.
 +
|-
 +
| <samp>BirthDay</samp>
 +
| ''(Optional if non-social)'' The day number for the NPC's birthday. Default 0.
 +
|-
 +
| <samp>HomeRegion</samp>
 +
| ''(Optional)'' The region of the world in which the NPC lives (one of <samp>Desert</samp>, <samp>Town</samp>, or <samp>Other</samp>). For example, only <samp>Town</samp> NPCs are counted for the introductions [[Quests#List of Story Quests|quest]], can be selected as a secret santa for the [[Feast of the Winter Star]], or get a friendship boost from the [[Luau]]. Default <samp>Other</samp>.
 +
|-
 +
| <samp>IsDarkSkinned</samp>
 +
| ''(Optional)'' Whether the NPC has dark skin, which affects the chance of children with the player having dark skin too. Default false.
 +
|}
 +
 
 +
====Social features====
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>CanSocialize</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether to enable social features (like birthdays, gift giving, [[friendship]], and an entry in the social tab). Default true.
 +
|-
 +
| <samp>CanBeRomanced</samp>
 +
| ''(Optional)'' Whether the NPC can be dated and romanced. This enables romance features for this NPC (like a 'single' label in the social menu, bouquet gifting, and marriage). Default false.
 +
|-
 +
| <samp>CanReceiveGifts</samp>
 +
| ''(Optional)'' Whether players can give gifts to this NPC. Default true.
 +
 
 +
The NPC must also be social per <samp>CanSocialize</samp> and have an entry in <samp>Data/NPCGiftTastes</samp> to be giftable, regardless of this value.
 +
|-
 +
| <samp>CanCommentOnPurchasedShopItems</samp>
 +
| ''(Optional)'' Whether this NPC can comment on items that a player sold to a shop which then resold it to them. If null (or omitted), this will default to true if their <samp>HomeRegion</samp> is set to <samp>Town</samp>.
 +
 
 +
The NPC must also be social per <samp>CanSocialize</samp> to allow it, regardless of this value.
 +
|-
 +
| <samp>CanGreetNearbyCharacters</samp>
 +
| ''(Optional)'' Whether this NPC can show a speech bubble greeting nearby players or NPCs, and or be greeted by other NPCs. Default true.
 +
|-
 +
| <samp>CanVisitIsland</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the NPC can visit the [[Ginger Island]] resort once it's unlocked. Default true.
 +
 
 +
The NPC must also be social per <samp>CanSocialize</samp> to visit the island, regardless of this value.
 +
|-
 +
| <samp>LoveInterest</samp>
 +
| ''(Optional)'' Unused.
 +
|-
 +
| <samp>Calendar</samp>
 +
| ''(Optional)'' Determines when the NPC's birthday is shown in the [[calendar]]. Possible values:
 +
{| class="wikitable"
 +
|-
 +
! value
 +
! effect
 +
|-
 +
| <samp>HiddenAlways</samp>
 +
| They never appear in the calendar.
 +
|-
 +
| <samp>HiddenUntilMet</samp>
 +
| Until the player meets them, they don't appear in the calendar.
 +
|-
 +
| <samp>AlwaysShown</samp>
 +
| They always appear in the calendar.
 +
|}
 +
 
 +
Defaults to <samp>AlwaysShown</samp>.
 +
|-
 +
| <samp>SocialTab</samp>
 +
| ''(Optional)'' Determines how the NPC is shown on the [[friendship|social tab]] when unlocked. Possible values:
 +
{| class="wikitable"
 +
|-
 +
! value
 +
! effect
 +
|-
 +
| <samp>HiddenAlways</samp>
 +
| They never appear in the social tab.
 +
|-
 +
| <samp>HiddenUntilMet</samp>
 +
| Until the player meets them, they don't appear on the social tab.
 +
|-
 +
| <samp>UnknownUntilMet</samp>
 +
| Until the player meets them, their name on the social tab is replaced with "???".
 +
|-
 +
| <samp>AlwaysShown</samp>
 +
| They always appear in the social tab (including their name).
 +
|}
 +
 
 +
Defaults to <samp>UnknownUntilMet</samp>.
 +
|-
 +
| <samp>SpouseAdopts</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the player will need to adopt children with this spouse, instead of either the player or NPC giving birth. If null, defaults to true for same-gender and false for opposite-gender spouses.
 +
 
 +
The <samp>Target</samp> player is the one they're married to.
 +
|-
 +
| <samp>SpouseWantsChildren</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the spouse will ask to have children. Defaults to true.
 +
 
 +
The <samp>Target</samp> player is the one they're married to.
 +
|-
 +
| <samp>SpouseGiftJealousy</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the [[Marriage#Jealousy|spouse will get jealous of gifts to other NPCs]]. Defaults to true.
 +
 
 +
The <samp>Target</samp> player is the one they're married to, and the <samp>Target</samp> item is the one that was gifted.
 +
|-
 +
| <samp>SpouseGiftJealousyFriendshipChange</samp>
 +
| ''(Optional)'' The [[Friendship|friendship point]] effect when the <samp>SpouseGiftJealously</samp> is triggered. Default -30.
 +
|-
 +
| <samp>SpouseRoom</samp>
 +
| ''(Optional)'' The [[Marriage#Spouse Rooms|NPC's spouse room]] in the farmhouse when the player marries them, if applicable. If this is omitted for a marriageable NPC, they'll use Abigail's spouse room by default.
 +
 
 +
This consists of a model with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>MapAsset</samp>
 +
| ''(Optional)'' The asset name for the spouse room map. The <samp>Maps/</samp> prefix is added automatically and shouldn't be included. Defaults to <samp>spouseRooms</samp>.
 +
|-
 +
| <samp>MapSourceRect</samp>
 +
| ''(Optional)'' The tile area within the <samp>MapAsset</samp> containing the spouse's room. This should usually be a 6x9 tile area, though the game will try to adjust to a different size. Specified as a model with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields. Defaults to <samp>(0, 0, 6, 9)</samp>.
 +
|}
 +
 
 +
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]].
 +
|-
 +
| <samp>SpousePatio</samp>
 +
| ''(Optional)'' The [[Marriage#Spouse Outside Area|NPC's patio area]] on the farm when the player marries them, if any. Default none.
 +
 
 +
This consists of a model with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>MapAsset</samp>
 +
| ''(Optional)'' The asset name for the patio area. The <samp>Maps/</samp> prefix is added automatically and shouldn't be included. Defaults to <samp>spousePatios</samp>.
 +
|-
 +
| <samp>MapSourceRect</samp>
 +
| ''(Optional)'' The tile area within the <samp>MapAsset</samp> containing the spouse's patio area. This must be a 4x4 tile area. Specified as a model with <samp>X</samp>, <samp>Y</samp>, <samp>Width</samp>, and <samp>Height</samp> fields. Defaults to <samp>(0, 0, 4, 4)</samp>.
 +
|-
 +
| <samp>SpriteAnimationFrames</samp>
 +
| ''(Optional)'' The spouse's animation frames when they're in the patio. Each frame is an array containing [0] the sprite index in their spritesheet, and [1] the optional duration in milliseconds (default 100). If omitted or empty, the NPC won't be animated.
 +
 
 +
For example, here is Abigail playing the flute:
 +
<syntaxhighlight lang="js">
 +
"SpriteAnimationFrames": [
 +
    [16, 500], // show index 16 for 500ms
 +
    [17, 500],
 +
    [18, 500],
 +
    [19]      // if duration is omitted, defaults to 100ms
 +
]
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
|-
 +
| <samp>SpriteAnimationPixelOffset</samp>
 +
| ''(Optional)'' The pixel offset to apply to the NPC's sprite when they're animated in the patio, specified as a model with <samp>X</samp> and <samp>Y</samp> fields. This is ignored if the NPC isn't animated via <samp>SpriteAnimationFrames</samp>. Default none.
 +
|}
 +
|-
 +
| <samp>SpouseFloors</samp><br /><samp>SpouseWallpapers</samp>
 +
| ''(Optional)'' The floors and wallpapers which the NPC may randomly apply to the farmhouse when married to the player. If omitted or empty, the NPC will randomly choose a base floor (0–39) or wallpaper (0–111).
 +
|-
 +
| <samp>IntroductionsQuest</samp>
 +
| ''(Optional)'' Whether to include this NPC in [[Quests#List of Story Quests|the ''introductions'' quest]]. If <samp>null</samp> (or omitted), this will default to true if the <samp>HomeRegion</samp> field is set to <samp>Town</samp>.
 +
|-
 +
| <samp>ItemDeliveryQuests</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this NPC can give item delivery quests. If <samp>null</samp> (or omitted), this will default to true if the <samp>HomeRegion</samp> field is set to <samp>Town</samp>.
 +
 +
The NPC must also be social per <samp>CanSocialize</samp> to allow it, regardless of this value.
 +
|-
 +
| <samp>PerfectionScore</samp>
 +
| ''(Optional)'' Whether to include this NPC when checking whether the player has max friendships with every NPC for the perfection score. Default true.
 +
 +
The NPC must also be social per <samp>CanSocialize</samp> to be counted, regardless of this value.
 +
|-
 +
| <samp>EndSlideShow</samp>
 +
| ''(Optional)'' How the NPC appears in the end-game perfection slide show. Possible values:
 +
{| class="wikitable"
 +
|-
 +
! value
 +
! effect
 +
|-
 +
| <samp>Hidden</samp>
 +
| The NPC doesn't appear in the slide show.
 +
|-
 +
| <samp>MainGroup</samp>
 +
| The NPC is added to the main group of NPCs which walk across the screen.
 +
|-
 +
| <samp>TrailingGroup</samp>
 +
| The NPC is added to the trailing group of NPCs which follow the main group.
 +
|}
 +
 +
Defaults to <samp>MainGroup</samp>.
 +
|-
 +
| <samp>FriendsAndFamily</samp>
 +
| ''(Optional)'' The NPC's closest friends and family, as a dictionary where the key is the other NPC's internal name and the value is an optional tokenizable string for the name to use in dialogue text (like 'mom'). Default none.
  
The key (before the colon) is the internal name which uniquely identifies that NPC. This name isn't shown to the player, but will be used when referencing the NPC in other files. The value contains the following fields:
+
This affects generic dialogue for revealing likes and dislikes to family members, and may affect <samp>inlaw_&lt;NPC&gt;</samp> dialogues. This isn't necessarily comprehensive.
 +
|}
  
 +
====Dumpster diving====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! index
 
 
! field
 
! field
! example
+
! effect
! purpose
 
 
|-
 
|-
| 0
+
| <samp>DumpsterDiveEmote</samp>
| age
+
| ''(Optional)'' The emote ID to show above the NPC's head when they see a player rummaging through trash. See [[Modding:event data#Emotes|emote IDs]]. If omitted or <samp>null</samp>, the default depends on the NPC's age: a child will show sad (28), a teen will show a question mark (8), and an adult will show angry (12).
| <tt>teen</tt>
 
| Whether the NPC is a <tt>child</tt>, <tt>teen</tt>, or <tt>adult</tt>. This affects generated dialogue lines (e.g. a child would say ''stupid'' and an adult would say ''depressing''), generic dialogue (e.g. a child would respond to dumpster diving with "''Eww... What are you doing?''" and a teen would say "''Um... Why are you digging in the trash?''"), and the gift they choose as [[Feast of the Winter Star|a secret gift-giver]]. Children are also excluded from item delivery quests.
 
 
|-
 
|-
| 1
+
| <samp>DumpsterDiveFriendshipEffect</samp>
| manners
+
| ''(Optional)'' The friendship point change if this NPC sees a player rummaging through trash. Default -25.
| <tt>rude</tt>
+
|}
| Whether the NPC is <tt>polite</tt>, <tt>rude</tt>, or <tt>neutral</tt>. This affects some generic dialogue lines.
+
 
 +
====Festivals====
 +
{| class="wikitable"
 
|-
 
|-
| 2
+
! field
| social anxiety
+
! effect
| <tt>outgoing</tt>
 
| Whether the NPC is <tt>outgoing</tt>, <tt>shy</tt>, or <tt>neutral</tt>. This affects some generic dialogue lines.
 
 
|-
 
|-
| 3
+
| <samp>FlowerDanceCanDance</samp>
| optimism
+
| ''(Optional)'' Whether players can ask the NPC to dance at the Flower Dance festival. The possible values are <samp>true</samp> (can always ask), <samp>false</samp> (can never ask), or <samp>null</samp> (can ask if they're romanceable). Default <samp>null</samp>.
| <tt>neutral</tt>
+
 
| Whether the NPC is <tt>positive</tt>, <tt>negative</tt>, or <tt>neutral</tt>. ''Unused.''
+
If the NPC can dance, you should also add the [[Modding:NPC data#Overworld_sprites|dance sprite frames]] and <samp>FlowerDance_Decline</samp> [[Modding:Dialogue|dialogue text]]. You can optionally set the <samp>FlowerDance_Accept</samp> dialogue too (though NPCs have a default accept dialogue if not).
 
|-
 
|-
| 4
+
| <samp>WinterStarParticipant</samp>
| gender
+
| ''(Optional)''  A [[Modding:Game state queries|game state query]] which indicates whether this NPC can give and receive gifts at the [[Feast of the Winter Star]]. If <samp>null</samp> (or omitted), this will default to true if the <samp>HomeRegion</samp> field is set to <samp>Town</samp>.
| <tt>female</tt>
 
| Whether the NPC is <tt>male</tt>, <tt>female</tt>, or <tt>undefined</tt>. This affects dialogue, whether children in marriage are obtained through adoption or pregnancy, and the reserved frames' positions on the spritesheet.
 
 
|-
 
|-
| 5
+
| <samp>WinterStarGifts</samp>
| datable
+
| At the [[Feast of the Winter Star]], the possible gifts this NPC can give to players. A matching entry is selected at random.
| <tt>datable</tt>
+
 
| Whether the NPC is <tt>datable</tt> or <tt>not-datable</tt>. This toggles the romance features (e.g. 'single' label in the social menu, bouquet gifting, and marriage).
+
This consists of a list of models with these fields:
 +
{| class="wikitable"
 
|-
 
|-
| 6
+
! field
| love interest
+
! effect
| <tt>Sebastian</tt>
 
| ''Unused.''
 
 
|-
 
|-
| 7
+
| ''common fields''
| home region
+
| See [[Modding:Item queries#Item spawn fields|item spawn fields]] for the generic item fields.
| <tt>Town</tt>
+
 
| Whether the NPC lives in the <tt>Desert</tt>, <tt>Town</tt>, or <tt>Other</tt>. This is used when improving friendship points for all NPCs in a given region, which is currently only used for the [[Luau]] friendship boost (which only affects NPCs in the <tt>Town</tt> region).
+
If set to an [[Modding:Item queries|item query]] which returns multiple items, one of them will be selected at random.
 +
|}
 +
|}
 +
 
 +
====Spawn rules====
 +
{| class="wikitable"
 
|-
 
|-
| 8
+
! field
| birthday
+
! effect
| <tt>fall 13</tt>
 
| The season and day for the NPC's birthday.
 
 
|-
 
|-
| 9
+
| <samp>UnlockConditions</samp>
| relationships
+
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether the NPC should be added to the world, checked when loading a save and when ending each day. This only affects whether the NPC is added when missing; returning false won't remove an NPC that's already been added. Defaults to true.
| <tt>Caroline 'mom' Pierre 'dad'</tt>
 
| This affects generic dialogue for revealing likes and dislikes to family members. May also affect the inlaw_<NPC> dialogue. Can be empty if not applicable (e.g. <code>/fall 13//SeedShop 1 9/</code>).
 
 
|-
 
|-
| 10
+
| <samp>SpawnIfMissing</samp>
| default map & position
+
| ''(Optional)'' Whether to add this NPC to the world if they're missing (if the <samp>UnlockConditions</samp> match and <samp>HomeLocation</samp> is valid). Default true.
| <tt>SeedShop 1 9</tt>
 
| The location name and [[Modding:Modder Guide/Game Fundamentals#Tiles|tile position]] where the NPC starts and ends each day.
 
 
|-
 
|-
| 11
+
| <samp>Home</samp>
| display name
+
| ''(Optional)'' The default place where this NPC spawns and returns each day. If there are multiple entries, the first matching one is used.
| <tt>Abigail</tt>
+
 
| The NPC name shown to the player.
+
This consists of a list of models with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>ID</samp>
 +
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 +
|-
 +
| <samp>Location</samp>
 +
| ''(Optional)'' The internal name for the home location where this NPC spawns and returns each day. Default none.
 +
|-
 +
| <samp>Tile</samp>
 +
| ''(Optional)'' The tile position within the home location where this NPC spawns and returns each day. Specified as a model with <samp>X</samp> and <samp>Y</samp> fields. Defaults to <samp>(0, 0)</samp>.
 +
|-
 +
| <samp>Direction</samp>
 +
| ''(Optional)'' The default direction the NPC faces when they start each day. The possible values are <samp>down</samp>, <samp>left</samp>, <samp>right</samp>, and <samp>up</samp>. Defaults to <samp>up</samp>.
 +
|-
 +
| <samp>Condition</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry can be selected. Default true.
 +
|}
 
|}
 
|}
  
===Gift tastes===
+
====Appearance & sprite====
The <tt>Data\NPCGiftTastes</tt> asset contains their gift preferences (e.g. which gifts they love or hate), and their responses when they receive one. See [[Modding:Gift taste data]] for more info.
+
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>TextureName</samp>
 +
| ''(Optional)'' The '''last segment''' of the NPC's portrait and sprite asset names. For example, set to <samp>Abigail</samp> to use <samp>Portraits/Abigail</samp> and <samp>Characters/Abigail</samp> respectively. Defaults to the internal NPC name.
 +
|-
 +
| <samp>Appearance</samp>
 +
| ''(Optional)'' The portrait/sprite textures to use.
 +
 
 +
This can list any number of appearance options. They'll be sorted by <samp>Precedence</samp> value (with lower values taking priority), then filtered to those whose fields match. If multiple matching appearances have precedence, one entry is randomly chosen based on their relative weight. This randomization is stable per day, so the NPC always makes the same choice until the next day. If a portrait/sprite can't be loaded (or no appearances match), the NPC will use the default asset based on <samp>TextureName</samp>.
 +
 
 +
The NPC rechecks this field each time they change location.
 +
 
 +
This consists of a list of models with these fields:
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>Id</samp>
 +
| The [[Modding:Common data field types#Unique string ID|unique string ID]] for this entry within the current list.
 +
|-
 +
| <samp>Season</samp>
 +
| ''(Optional)'' The season in which this appearance should be used (one of <samp>spring</samp>, <samp>summer</samp>, <samp>fall</samp>, or <samp>winter</samp>), or omit for any season. Defaults to any season.
 +
|-
 +
| <samp>Indoors</samp><br /><samp>Outdoors</samp>
 +
| ''(Optional)'' Whether this appearance should be used when indoors and/or outdoors. Both default to true.
 +
|-
 +
| <samp>Condition</samp>
 +
| ''(Optional)'' A [[Modding:Game state queries|game state query]] which indicates whether this entry can be selected. Default true.
 +
|-
 +
| <samp>Portrait</samp><br /><samp>Sprite</samp>
 +
| ''(Optional)'' The asset name for the portraits and/or sprites texture to load. If omitted or it can't be loaded, it will default to the default asset per the <samp>Texture</samp> field.
 +
|-
 +
| <samp>IsIslandAttire</samp>
 +
| ''(Optional)'' Whether this is island beach attire worn at the resort. Default false.
 +
 
 +
This is mutually exclusive: NPCs will never wear it in other contexts if it's true, and will never wear it as island attire if it's false.
 +
|-
 +
| <samp>Precedence</samp>
 +
| ''(Optional)'' The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Default 0.
 +
|-
 +
| <samp>Weight</samp>
 +
| ''(Optional)'' If multiple entries with the same <samp>Precedence</samp> match, the relative weight to use when randomly choosing one. Default 1.
 +
 
 +
For example, let's say two appearance entries match: one has a weight of 2, and the other has a weight of 1. Their probability of being chosen is 2/3 and 1/3 respectively.
 +
|}
 +
 
 +
'''Note:''' the default textures based on <samp>TextureName</samp> must still exist, even if you use this field to override them.
 +
|-
 +
| <samp>MugShotSourceRect</samp>
 +
| ''(Optional)'' The 16x24-pixel area in the character's sprite texture to show as their mug shot icon in the calendar, social menu, and other contexts. Defaults to part of their first sprite.
 +
|-
 +
| <samp>Size</samp>
 +
| ''(Optional)'' The pixel size of the individual sprites in their overworld sprite spritesheet. Specified as a model with <samp>X</samp> and <samp>Y</samp> fields. Defaults to <samp>(16, 32)</samp>.
 +
 
 +
'''Note:''' sizes bigger than 16×32 will cause issues like broken spawning, pathfinding, misalignment in the [[perfection]] end-game slide show, etc.
 +
|-
 +
| <samp>Breather</samp>
 +
| ''(Optional)'' Whether the chest on the NPC's overworld sprite puffs in and out as they breathe. Default true</samp>.
 +
|-
 +
| <samp>BreathChestRect</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Rectangle|rectangle]] pixel area within the spritesheet which expands and contracts to simulate breathing, relative to the top-left corner of the source rectangle for their current sprite. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
 +
|-
 +
| <samp>BreathChestPosition</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset to apply to the NPC's <samp>BreathChestPosition</samp> when drawn over the NPC. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
 +
|-
 +
| <samp>Shadow</samp>
 +
| ''(Optional)'' The options for the shadow to draw under the NPC, or omit to apply the default shadow behavior.
  
The file has one row per NPC like this:
+
This consists of a model with these fields:
<syntaxhighlight lang="yaml">
 
  Abigail: "I seriously love this! You're the best, @!/66 128 220 226 276 611/Hey, how'd you know I was hungry? This looks delicious!//What am I supposed to do with this?/-5 -75 -79 16 245 246/What were you thinking? This is awful!/330/You brought me a present? Thanks.// " #!String
 
</syntaxhighlight>
 
  
The line can be broken down into 5 pairs of dialogue + item IDs in this order: Love, Like, Neutral, Dislike, Hate. If a dialogue field is empty, the game will use a generic dialogue text. See [[Modding:Object data]] for the item IDs.
+
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 +
|-
 +
| <samp>Visible</samp>
 +
| ''(Optional)'' Whether the shadow should be drawn. Default true.
 +
|-
 +
| <samp>Offset</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset applied to the shadow position. Default zero.
 +
|-
 +
| <samp>Scale</samp>
 +
| ''(Optional)'' The scale at which to draw the shadow. Default 1.
  
====Birthday gift responses====
+
This is a multiplier applied to the default shadow scale, which can change based on factors like whether the NPC is jumping. For example, <samp>0.5</samp> means half the size it'd be drawn if you didn't specify a scale.
The <tt>Strings\StringsFromCSFiles</tt> asset contains the generic responses given by NPCs to birthday gifts based on their gift preferences and manners. These shared strings can be customized for a specific NPC by editing them conditionally, such as only on the NPC's (non-shared) birthday. The following criteria are used to select from among the strings:
+
|}
 +
|-
 +
| <samp>EmoteOffset</samp>
 +
| ''(Optional)'' A [[Modding:Common data field types#Point|point]] pixel offset applied to emote drawn over the NPC. Default zero.
 +
|-
 +
| <samp>ShakePortraits</samp>
 +
| ''(Optional)'' The portrait indexes which should shake when displayed. Default none.
 +
|-
 +
| <samp>KissSpriteIndex</samp>
 +
| ''(Optional)'' If the NPC can be married, the sprite index within their <samp>Texture</samp> to use when kissing a player. Default 28.
 +
|-
 +
| <samp>KissSpriteFacingDirection</samp>
 +
| ''(Optional)'' Whether the character is facing right (true) or left (false) in their <samp>KissSpriteIndex</samp>. The sprite will be flipped as needed to face the player. Default true.
 +
|}
  
 +
====[[Secrets#Gift Log|Hidden gift log emote]]====
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! gift taste
+
! field
! manners
+
! effect
! chance
 
! string
 
 
|-
 
|-
| rowspan="4" | love, like
+
| <samp>HiddenProfileEmoteSound</samp>
| rowspan="2" | rude
+
| ''(Optional)'' For the [[Secrets#Gift Log|hidden gift log emote]], the [[#Custom audio|cue ID]] for the sound played when clicking the sprite. Defaults to <samp>drumkit6</samp>.
| 50%
 
| <tt>NPC.cs.4274</tt>
 
 
|-
 
|-
| 50%
+
| <samp>HiddenProfileEmoteDuration</samp>
| <tt>NPC.cs.4276</tt>
+
| ''(Optional)'' For the [[Secrets#Gift Log|hidden gift log emote]], how long the animation plays measured in milliseconds. Defaults to 4000 (4 seconds).
 
|-
 
|-
| rowspan="2" | polite, neutral
+
| <samp>HiddenProfileEmoteStartFrame</samp>
| 50%
+
| ''(Optional)'' For the [[Secrets#Gift Log|hidden gift log emote]], the index within the NPC's overworld sprite spritesheet at which the animation starts. If omitted for a vanilla NPC, the game plays a default animation specific to that NPC; if omitted for a custom NPC, the game just shows them walking while facing down.
| <tt>NPC.cs.4275</tt>
 
 
|-
 
|-
| 50%
+
| <samp>HiddenProfileEmoteFrameCount</samp>
| <tt>NPC.cs.4277</tt>
+
| ''(Optional)'' For the [[Secrets#Gift Log|hidden gift log emote]], the number of frames in the animation. The first frame corresponds to <samp>HiddenProfileEmoteStartFrame</samp>, and each subsequent frame will use the next sprite in the spritesheet. Default 1.
 +
 
 +
This has no effect if <samp>HiddenProfileEmoteStartFrame</samp> isn't set.
 
|-
 
|-
| rowspan="2" | dislike, hate
+
| <samp>HiddenProfileEmoteFrameDuration</samp>
| rude
+
| ''(Optional)'' For the [[Secrets#Gift Log|hidden gift log emote]], how long each animation frame is shown on-screen before switching to the next one, measured in milliseconds. Default 200.
| 100%
+
 
| <tt>NPC.cs.4278</tt>
+
This has no effect if <samp>HiddenProfileEmoteStartFrame</samp> isn't set.
 +
|}
 +
 
 +
====Advanced====
 +
{| class="wikitable"
 +
|-
 +
! field
 +
! effect
 
|-
 
|-
| polite, neutral
+
| <samp>CustomFields</samp>
| 100%
+
| The [[#Custom data fields|custom fields]] for this entry.
| <tt>NPC.cs.4279</tt>
 
 
|-
 
|-
| rowspan="2" | neutral
+
| <samp>FormerCharacterNames</samp>
| rude
+
| ''(Optional)'' The former NPC names which may appear in save data. If matched, the game will rename the NPC and update related data (e.g. friendship).
| 100%
+
 
| <tt>NPC.cs.4280</tt>
+
A former name is only applied if:
 +
# it doesn't match a current ID in <samp>Data/Characters</samp>;
 +
# the save has an NPC with the former name;
 +
# the save doesn't already have an NPC with the new name.
 +
 
 +
For example:
 +
<syntaxhighlight lang="js">
 +
"FormerCharacterNames": [ "SomeOldName" ]
 +
</syntaxhighlight>
 +
 
 +
Former names can have any format, but they must be '''globally''' unique. They can't match the ID or <samp>FormerCharacterNames</samp> of any other NPC in <samp>Data/Characters</samp> (whether vanilla or custom).
 
|-
 
|-
| polite, neutral
+
| <samp>FestivalVanillaActorIndex</samp>
| 100%
+
| ''(Optional, Specialized)'' The NPC's index in the <samp>Maps/characterSheet</samp> tilesheet, if applicable. This is used for placing vanilla NPCs in festivals from the map; custom NPCs should use the <samp>&lt;layer&gt;_additionalCharacters</samp> field in the festival data instead.
| <tt>NPC.cs.4281</tt>
 
 
|}
 
|}
 +
 +
===Gift tastes===
 +
; main gift data
 +
: The <samp>Data/NPCGiftTastes</samp> asset contains their gift preferences (''e.g.,'' which gifts they love or hate), and their responses when they receive one. See [[Modding:Gift taste data]] for more info.
 +
 +
: The file has one row per NPC like this:
 +
: <syntaxhighlight lang="yaml">Abigail: "I seriously love this! You're the best, @!/66 128 220 226 276 611/Hey, how'd you know I was hungry? This looks delicious!//What am I supposed to do with this?/-5 -75 -79 16 245 246/What were you thinking? This is awful!/330/You brought me a present? Thanks.//" </syntaxhighlight>
 +
 +
: The line can be broken down into 5 pairs of dialogue + item IDs in this order: Love, Like, Dislike, Hate, Neutral. If a dialogue field is empty, the game will use a generic dialogue text. See [[Modding:Items]] for the object IDs.
 +
 +
; gift dialogue
 +
: When you gift an NPC, they'll show a dialogue [[Modding:Dialogue|dialogue]] in this order:
 +
:# on their birthday, an <samp>AcceptBirthdayGift</samp> dialogue key, else a default dialogue like <samp>NPC.cs.4274</samp> ("''You remembered my birthday? I'm impressed. Thanks.$h''");
 +
:# an <samp>AcceptGift_*</samp> dialogue;
 +
:# else the dialogue in <samp>Data/NPCGiftTastes</samp> with a default portrait (which can be overridden with [[Modding:Dialogue#Portrait commands|portrait commands]] like <samp>$h</samp>).
  
 
===Overworld sprites===
 
===Overworld sprites===
The overworld sprites are stored in <tt>Characters/NpcName</tt>, including movement and animation frames. Each frame is exactly 16x32 pixels. Here's an [https://cdn.discordapp.com/attachments/156109690059751424/729807097835028540/unknown.png example sprite guide], courtesy of TheLimeyDragon#1993 on Discord. Some positions are reserved for certain actions:
+
[[File:Abigail-sprite-sheet.png|thumb|The sprite sheet for Abigail.]]
 +
 
 +
The overworld sprites are stored in <samp>Characters/NpcName</samp>, including movement and animation frames. Each frame is exactly 16x32 pixels. Here's an [https://cdn.discordapp.com/attachments/156109690059751424/729807097835028540/unknown.png example sprite guide], courtesy of TheLimeyDragon#1993 on Discord. Some positions are reserved for certain actions:
 
<ul>
 
<ul>
 
<li>the first sixteen frames are generic movement (four frames per direction);</li>
 
<li>the first sixteen frames are generic movement (four frames per direction);</li>
Line 204: Line 561:
  
 
===Portraits===
 
===Portraits===
The dialogue portraits are stored in <tt>Portraits/NpcName</tt>. Each frame is exactly 64x64 per portrait. The first six represent specific emotions (see [[Modding:Dialogue#Portrait commands]]), followed by any number of custom portraits. The first portrait is used when the dialogue doesn't specify one. Here's an [https://cdn.discordapp.com/attachments/156109690059751424/729820558966915122/unknown.png example portrait guide], courtesy of TheLimeyDragon#1993 on Discord.
+
[[File:Modding - creating an XNB mod - example portraits.png|thumb|Abigail's portrait sprite sheet.]]
 +
 
 +
The dialogue portraits are stored in <samp>Portraits/NpcName</samp>. Each frame is exactly 64x64 per portrait. The first six represent specific emotions (see [[Modding:Dialogue#Portrait commands]]), followed by any number of custom portraits. The first portrait is used when the dialogue doesn't specify one.
  
 
===Schedule===
 
===Schedule===
 
Their schedule file tells the game where the NPC starts and moves based on on the time. You need to add strings to a separate schedules file found in the Strings folder to allow custom dialogue. See [[Modding:Schedule data]] for more info.
 
Their schedule file tells the game where the NPC starts and moves based on on the time. You need to add strings to a separate schedules file found in the Strings folder to allow custom dialogue. See [[Modding:Schedule data]] for more info.
  
===Dialogue and events===
+
===Dialogue===
The NPC dialogue and events are stored in several files; see [[Modding:Dialogue]] and [[Modding:Event data]] for more info.
+
The NPC dialogue and events are stored in several files; see [[Modding:Dialogue]].
 +
 
 +
===Sleep animation===
 +
When the NPC goes to bed, they'll play the looping sleep animation set via <samp>{{t|lowercase NPC name}}_sleep</samp> in <samp>Data/animationDescriptions</samp>, if it exists. For example, this content pack adds a sleep animation for an NPC named 'Pufferbob':
 +
{{#tag:syntaxhighlight|
 +
{
 +
    "Format": "{{Content Patcher version}}",
 +
    "Changes": [
 +
        {
 +
            "Action": "EditData",
 +
            "Target": "Data/animationDescriptions",
 +
            "Entries": {
 +
                "pufferbob_sleep": "50/50/50" // note: make name lowercase
 +
            }
 +
        }
 +
    ]
 +
}
 +
|lang=json}}
 +
 
 +
===Secondary assets===
 +
* See [[Modding:Event data|event data]] for the NPC's cutscenes.
 +
* See [[Modding:Festival data|festival data]] for an NPC's positions (via the <samp>Set-Up_additionalCharacters</samp> and <samp>MainEvent_additionalCharacters</samp> fields) and dialogue in festivals.
 +
* See [[Modding:Movie theater data|movie theater data]] for an NPC's taste in movies and concessions.
  
===Festivals===
+
==Example==
Festivals are tricky things. Everyone in the vanilla game is added to the festival map by placing tiles on the Set-Up and MainEvent map layers from a character tilesheet that draws from NPCDispositions to get exactly who to place. This is not ideal for custom NPCs, since you have no way of knowing where on the NPCDispositions data list your NPC goes when a player is using multiple custom NPCs. For this reason, it is recommended to use {{nexus mod|1820|TMXLoader}}, as it has a festival addition function to add your character to the Festival Maps, since it will draw upon your character's internal name instead of their position on the list. It's fairly easy to do, and there's an explanation on the {{nexus mod|1820|TMXLoader}} Nexus Description.
+
Here's how you'd create an example NPC named Dobson with full social features.
  
==Adding your NPC==
+
Note that <code><nowiki>{{ModId}}</nowiki></code> is a Content Patcher token, which will be replaced with your mod ID automatically for the [[Modding:Common data field types#Unique string ID|unique string ID]] convention.
Here's how you'd create an example NPC we'll name Dobson:
 
  
 
<ol>
 
<ol>
<li>[https://github.com/Pathoschild/StardewMods/blob/develop/ContentPatcher/docs/author-guide.md#format Create an empty Content Patcher content pack]. By convention, we'll name the folder <tt>[CP] Dobson</tt>.</li>
+
<li>[https://github.com/Pathoschild/StardewMods/blob/develop/ContentPatcher/docs/author-guide.md#format Create an empty Content Patcher content pack]. By convention, we'll name the folder <samp>[CP] Dobson</samp>.</li>
 
<li>Create the following files:
 
<li>Create the following files:
* <tt>assets/dialogue.json</tt> containing the dialogue.
+
* <samp>assets/dialogue.json</samp> containing the dialogue.
* <tt>assets/marriageDialogue.json</tt> containing the marriage dialogue (if applicable).
+
* <samp>assets/marriageDialogue.json</samp> containing the marriage dialogue (if applicable).
* <tt>assets/sprites.png</tt> containing their overworld sprites.
+
* <samp>assets/sprites.png</samp> containing their overworld sprites.
* <tt>assets/portraits.png</tt> containing their portraits.
+
* <samp>assets/portraits.png</samp> containing their portraits.
* <tt>assets/schedule.json</tt> containing their schedule data.
+
* <samp>assets/schedule.json</samp> containing their schedule data.
 
</li>
 
</li>
<li>Edit the <tt>content.json</tt> to load the files:
+
<li>Edit the <samp>content.json</samp> to load the files:
{{#tag:syntaxhighlight|
+
{{#tag:syntaxhighlight|<nowiki>
 
{
 
{
     "Format": "{{Content Patcher version}}",
+
     "Format": "</nowiki>{{Content Patcher version}}<nowiki>",
 
     "Changes": [
 
     "Changes": [
 
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Characters/Dobson",
+
             "Target": "Characters/{{ModId}}_Dobson",
             "FromFile": "assets/sprites.png",
+
             "FromFile": "assets/sprites.png"
 
         },
 
         },
 
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Portraits/Dobson",
+
             "Target": "Portraits/{{ModId}}_Dobson",
             "FromFile": "assets/portraits.png",
+
             "FromFile": "assets/portraits.png"
 
         },
 
         },
 
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Characters/Dialogue/Dobson",
+
             "Target": "Characters/Dialogue/{{ModId}}_Dobson",
             "FromFile": "assets/dialogue.json",
+
             "FromFile": "assets/dialogue.json"
 
         },
 
         },
 
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Characters/Dialogue/MarriageDialogueDobson",
+
             "Target": "Characters/Dialogue/MarriageDialogue{{ModId}}_Dobson",
             "FromFile": "assets/marriageDialogue.json",
+
             "FromFile": "assets/marriageDialogue.json"
 
         },
 
         },
 
         {
 
         {
 
             "Action": "Load",
 
             "Action": "Load",
             "Target": "Characters/schedules/Dobson",
+
             "Target": "Characters/schedules/{{ModId}}_Dobson",
             "FromFile": "assets/schedule.json",
+
             "FromFile": "assets/schedule.json"
 
         },
 
         },
 
         {
 
         {
 
             "Action": "EditData",
 
             "Action": "EditData",
             "Target": "Data/NPCDispositions",
+
             "Target": "Data/Characters",
 
             "Entries": {
 
             "Entries": {
                 "Dobson": "adult/rude/neutral/positive/male/datable//Town/summer 7//BusStop 19 4/Dobson"
+
                 "{{ModId}}_Dobson": {
             },
+
                    "DisplayName": "Dobson", // this can use {{i18n:}} to support translations
 +
                    "BirthSeason": "Summer",
 +
                    "BirthDay": 7,
 +
                    "HomeRegion": "Town",
 +
                    "Gender": "Male",
 +
                    "Age": "Adult",
 +
                    "Manner": "Rude",
 +
                    "SocialAnxiety": "Neutral",
 +
                    "Optimism": "Positive",
 +
 
 +
                    "CanBeRomanced": true,
 +
 
 +
                    "Home": [
 +
                        {
 +
                            "Id": "Default",
 +
                            "Location": "BusStop",
 +
                            "Tile": "19, 4"
 +
                        }
 +
                    ]
 +
                }
 +
             }
 
         },
 
         },
 
         {
 
         {
Line 268: Line 668:
 
             "Target": "Data/NPCGiftTastes",
 
             "Target": "Data/NPCGiftTastes",
 
             "Entries": {
 
             "Entries": {
                 "Dobson": "You're giving this to me? This is amazing!/207 232 233 400/Thank you! This is a very interesting specimen./-5 -79 422/...What is this?/80 330/This is disgusting./2/That was very thoughtful of you./-4/ ",
+
                 "{{ModId}}_Dobson": "You're giving this to me? This is amazing!/207 232 233 400/Thank you! This is a very interesting specimen./-5 -79 422/...What is this?/80 330/This is disgusting./2/That was very thoughtful of you./-4/ "
             },
+
             }
 
         },
 
         },
 
         {
 
         {
Line 275: Line 675:
 
             "Target": "Data/EngagementDialogue",
 
             "Target": "Data/EngagementDialogue",
 
             "Entries": {
 
             "Entries": {
                 "Dobson0": "I can't believe I am about to be married!$h",
+
                 "{{ModId}}_Dobson0": "I can't believe I am about to be married!$h",
                 "Dobson1": "I hope I don't get cold feet",
+
                 "{{ModId}}_Dobson1": "I hope I don't get cold feet"
             },
+
             }
         },
+
         }
 
     ]
 
     ]
 
}
 
}
|lang=json}}
+
</nowiki>|lang=json}}
 
</li>
 
</li>
 
</ol>
 
</ol>
 
That's it! If you load your game, the NPC should appear. If you want to create events, don't forget to add that file too.
 
That's it! If you load your game, the NPC should appear. If you want to create events, don't forget to add that file too.
==Guidance on pixel art==
+
 
If you'd like additional guidance on pixel art:
+
==See also==
* Check out the [https://sundrop.kvdk.net/art-guide Stardew Valley art style guide] some modders created.
+
* See [[Modding:Index#See also]] for recommended guides on pixel art.
* rhubarb#4755 on Discord wrote a [https://discord.com/channels/137344473976799233/156109690059751424/740854008469520434 few tips specific to hair for portraits].
 
  
 
[[Category:Modding]]
 
[[Category:Modding]]
  
 +
[[es:Modding:Datos de NPC]]
 
[[pt:Modificações:Dados do NPC]]
 
[[pt:Modificações:Dados do NPC]]
 +
[[ru:Модификации:О NPC]]

Latest revision as of 23:36, 13 September 2024

Index

This page provides an overview of what's needed to create a custom NPC. This is an advanced guide for mod developers.

Before reading this page, see Modding:Editing XNB files for the basic concepts.

Files to edit

To create a new NPC, you need to edit a number of different files. However, you don't need any programming experience and it can be done with Content Patcher.

Main data

The Data/Characters asset contains most of the data about an NPC. That includes their name, social info (e.g. personality, birthday, and romance), appearance, spouse room & patio, festival participation, etc.

This consists of a string → model lookup, where...

  • The key is a unique string ID for the NPC like Example.ModId_NpcName, which will be used as the internal Name (not DisplayName).
  • The value is a model with the following fields.

Basic info

field effect
DisplayName A tokenizable string for the NPC's display name.
Language (Optional) The language spoken by the NPC. One of Default (the default language understood by the player) or Dwarvish (which the player can only understand after finding the Dwarvish translation guide). Default Default.
Gender (Optional) The NPC's gender identity. One of Female, Male, or Undefined. Default Undefined.
Age (Optional) The general age of the NPC. One of Child, Teen, or Adult. Default Adult.

This affects generated dialogue lines (e.g. a child might say "stupid" and an adult might say "depressing"), generic dialogue (e.g. a child might respond to dumpster diving with "Eww... What are you doing?" and a teen would say "Um... Why are you digging in the trash?"), and the gift they choose as Feast of the Winter Star gift-giver. Children are also excluded from item delivery quests.

Manner (Optional) A measure of the character's general politeness, which affects some generic dialogue lines. One of Neutral, Polite, or Rude. Default Neutral.
SocialAnxiety (Optional) A measure of the character's comfort with social situations, which affects some generic dialogue lines. One of Neutral, Outgoing, or Shy. Default Neutral.
Optimism (Optional) A measure of the character's overall optimism. One of Neutral, Negative, or Positive. Default Neutral.
BirthSeason (Optional if non-social) The season name (case-sensitive) for the NPC's birthday. One of spring, summer, fall, or winter. Default none.
BirthDay (Optional if non-social) The day number for the NPC's birthday. Default 0.
HomeRegion (Optional) The region of the world in which the NPC lives (one of Desert, Town, or Other). For example, only Town NPCs are counted for the introductions quest, can be selected as a secret santa for the Feast of the Winter Star, or get a friendship boost from the Luau. Default Other.
IsDarkSkinned (Optional) Whether the NPC has dark skin, which affects the chance of children with the player having dark skin too. Default false.

Social features

field effect
CanSocialize (Optional) A game state query which indicates whether to enable social features (like birthdays, gift giving, friendship, and an entry in the social tab). Default true.
CanBeRomanced (Optional) Whether the NPC can be dated and romanced. This enables romance features for this NPC (like a 'single' label in the social menu, bouquet gifting, and marriage). Default false.
CanReceiveGifts (Optional) Whether players can give gifts to this NPC. Default true.

The NPC must also be social per CanSocialize and have an entry in Data/NPCGiftTastes to be giftable, regardless of this value.

CanCommentOnPurchasedShopItems (Optional) Whether this NPC can comment on items that a player sold to a shop which then resold it to them. If null (or omitted), this will default to true if their HomeRegion is set to Town.

The NPC must also be social per CanSocialize to allow it, regardless of this value.

CanGreetNearbyCharacters (Optional) Whether this NPC can show a speech bubble greeting nearby players or NPCs, and or be greeted by other NPCs. Default true.
CanVisitIsland (Optional) A game state query which indicates whether the NPC can visit the Ginger Island resort once it's unlocked. Default true.

The NPC must also be social per CanSocialize to visit the island, regardless of this value.

LoveInterest (Optional) Unused.
Calendar (Optional) Determines when the NPC's birthday is shown in the calendar. Possible values:
value effect
HiddenAlways They never appear in the calendar.
HiddenUntilMet Until the player meets them, they don't appear in the calendar.
AlwaysShown They always appear in the calendar.

Defaults to AlwaysShown.

SocialTab (Optional) Determines how the NPC is shown on the social tab when unlocked. Possible values:
value effect
HiddenAlways They never appear in the social tab.
HiddenUntilMet Until the player meets them, they don't appear on the social tab.
UnknownUntilMet Until the player meets them, their name on the social tab is replaced with "???".
AlwaysShown They always appear in the social tab (including their name).

Defaults to UnknownUntilMet.

SpouseAdopts (Optional) A game state query which indicates whether the player will need to adopt children with this spouse, instead of either the player or NPC giving birth. If null, defaults to true for same-gender and false for opposite-gender spouses.

The Target player is the one they're married to.

SpouseWantsChildren (Optional) A game state query which indicates whether the spouse will ask to have children. Defaults to true.

The Target player is the one they're married to.

SpouseGiftJealousy (Optional) A game state query which indicates whether the spouse will get jealous of gifts to other NPCs. Defaults to true.

The Target player is the one they're married to, and the Target item is the one that was gifted.

SpouseGiftJealousyFriendshipChange (Optional) The friendship point effect when the SpouseGiftJealously is triggered. Default -30.
SpouseRoom (Optional) The NPC's spouse room in the farmhouse when the player marries them, if applicable. If this is omitted for a marriageable NPC, they'll use Abigail's spouse room by default.

This consists of a model with these fields:

field effect
MapAsset (Optional) The asset name for the spouse room map. The Maps/ prefix is added automatically and shouldn't be included. Defaults to spouseRooms.
MapSourceRect (Optional) The tile area within the MapAsset containing the spouse's room. This should usually be a 6x9 tile area, though the game will try to adjust to a different size. Specified as a model with X, Y, Width, and Height fields. Defaults to (0, 0, 6, 9).

You can mark where the spouse stands in their spouse room by placing the red circle path tile (tile index 7) on the Paths layer.

SpousePatio (Optional) The NPC's patio area on the farm when the player marries them, if any. Default none.

This consists of a model with these fields:

field effect
MapAsset (Optional) The asset name for the patio area. The Maps/ prefix is added automatically and shouldn't be included. Defaults to spousePatios.
MapSourceRect (Optional) The tile area within the MapAsset containing the spouse's patio area. This must be a 4x4 tile area. Specified as a model with X, Y, Width, and Height fields. Defaults to (0, 0, 4, 4).
SpriteAnimationFrames (Optional) The spouse's animation frames when they're in the patio. Each frame is an array containing [0] the sprite index in their spritesheet, and [1] the optional duration in milliseconds (default 100). If omitted or empty, the NPC won't be animated.

For example, here is Abigail playing the flute:

"SpriteAnimationFrames": [
    [16, 500], // show index 16 for 500ms
    [17, 500],
    [18, 500],
    [19]       // if duration is omitted, defaults to 100ms
]
SpriteAnimationPixelOffset (Optional) The pixel offset to apply to the NPC's sprite when they're animated in the patio, specified as a model with X and Y fields. This is ignored if the NPC isn't animated via SpriteAnimationFrames. Default none.
SpouseFloors
SpouseWallpapers
(Optional) The floors and wallpapers which the NPC may randomly apply to the farmhouse when married to the player. If omitted or empty, the NPC will randomly choose a base floor (0–39) or wallpaper (0–111).
IntroductionsQuest (Optional) Whether to include this NPC in the introductions quest. If null (or omitted), this will default to true if the HomeRegion field is set to Town.
ItemDeliveryQuests (Optional) A game state query which indicates whether this NPC can give item delivery quests. If null (or omitted), this will default to true if the HomeRegion field is set to Town.

The NPC must also be social per CanSocialize to allow it, regardless of this value.

PerfectionScore (Optional) Whether to include this NPC when checking whether the player has max friendships with every NPC for the perfection score. Default true.

The NPC must also be social per CanSocialize to be counted, regardless of this value.

EndSlideShow (Optional) How the NPC appears in the end-game perfection slide show. Possible values:
value effect
Hidden The NPC doesn't appear in the slide show.
MainGroup The NPC is added to the main group of NPCs which walk across the screen.
TrailingGroup The NPC is added to the trailing group of NPCs which follow the main group.

Defaults to MainGroup.

FriendsAndFamily (Optional) The NPC's closest friends and family, as a dictionary where the key is the other NPC's internal name and the value is an optional tokenizable string for the name to use in dialogue text (like 'mom'). Default none.

This affects generic dialogue for revealing likes and dislikes to family members, and may affect inlaw_<NPC> dialogues. This isn't necessarily comprehensive.

Dumpster diving

field effect
DumpsterDiveEmote (Optional) The emote ID to show above the NPC's head when they see a player rummaging through trash. See emote IDs. If omitted or null, the default depends on the NPC's age: a child will show sad (28), a teen will show a question mark (8), and an adult will show angry (12).
DumpsterDiveFriendshipEffect (Optional) The friendship point change if this NPC sees a player rummaging through trash. Default -25.

Festivals

field effect
FlowerDanceCanDance (Optional) Whether players can ask the NPC to dance at the Flower Dance festival. The possible values are true (can always ask), false (can never ask), or null (can ask if they're romanceable). Default null.

If the NPC can dance, you should also add the dance sprite frames and FlowerDance_Decline dialogue text. You can optionally set the FlowerDance_Accept dialogue too (though NPCs have a default accept dialogue if not).

WinterStarParticipant (Optional) A game state query which indicates whether this NPC can give and receive gifts at the Feast of the Winter Star. If null (or omitted), this will default to true if the HomeRegion field is set to Town.
WinterStarGifts At the Feast of the Winter Star, the possible gifts this NPC can give to players. A matching entry is selected at random.

This consists of a list of models with these fields:

field effect
common fields See item spawn fields for the generic item fields.

If set to an item query which returns multiple items, one of them will be selected at random.

Spawn rules

field effect
UnlockConditions (Optional) A game state query which indicates whether the NPC should be added to the world, checked when loading a save and when ending each day. This only affects whether the NPC is added when missing; returning false won't remove an NPC that's already been added. Defaults to true.
SpawnIfMissing (Optional) Whether to add this NPC to the world if they're missing (if the UnlockConditions match and HomeLocation is valid). Default true.
Home (Optional) The default place where this NPC spawns and returns each day. If there are multiple entries, the first matching one is used.

This consists of a list of models with these fields:

field effect
ID The unique string ID for this entry within the current list.
Location (Optional) The internal name for the home location where this NPC spawns and returns each day. Default none.
Tile (Optional) The tile position within the home location where this NPC spawns and returns each day. Specified as a model with X and Y fields. Defaults to (0, 0).
Direction (Optional) The default direction the NPC faces when they start each day. The possible values are down, left, right, and up. Defaults to up.
Condition (Optional) A game state query which indicates whether this entry can be selected. Default true.

Appearance & sprite

field effect
TextureName (Optional) The last segment of the NPC's portrait and sprite asset names. For example, set to Abigail to use Portraits/Abigail and Characters/Abigail respectively. Defaults to the internal NPC name.
Appearance (Optional) The portrait/sprite textures to use.

This can list any number of appearance options. They'll be sorted by Precedence value (with lower values taking priority), then filtered to those whose fields match. If multiple matching appearances have precedence, one entry is randomly chosen based on their relative weight. This randomization is stable per day, so the NPC always makes the same choice until the next day. If a portrait/sprite can't be loaded (or no appearances match), the NPC will use the default asset based on TextureName.

The NPC rechecks this field each time they change location.

This consists of a list of models with these fields:

field effect
Id The unique string ID for this entry within the current list.
Season (Optional) The season in which this appearance should be used (one of spring, summer, fall, or winter), or omit for any season. Defaults to any season.
Indoors
Outdoors
(Optional) Whether this appearance should be used when indoors and/or outdoors. Both default to true.
Condition (Optional) A game state query which indicates whether this entry can be selected. Default true.
Portrait
Sprite
(Optional) The asset name for the portraits and/or sprites texture to load. If omitted or it can't be loaded, it will default to the default asset per the Texture field.
IsIslandAttire (Optional) Whether this is island beach attire worn at the resort. Default false.

This is mutually exclusive: NPCs will never wear it in other contexts if it's true, and will never wear it as island attire if it's false.

Precedence (Optional) The order in which this entry should be checked, where lower values are checked first. This can be a negative value. Default 0.
Weight (Optional) If multiple entries with the same Precedence match, the relative weight to use when randomly choosing one. Default 1.

For example, let's say two appearance entries match: one has a weight of 2, and the other has a weight of 1. Their probability of being chosen is 2/3 and 1/3 respectively.

Note: the default textures based on TextureName must still exist, even if you use this field to override them.

MugShotSourceRect (Optional) The 16x24-pixel area in the character's sprite texture to show as their mug shot icon in the calendar, social menu, and other contexts. Defaults to part of their first sprite.
Size (Optional) The pixel size of the individual sprites in their overworld sprite spritesheet. Specified as a model with X and Y fields. Defaults to (16, 32).

Note: sizes bigger than 16×32 will cause issues like broken spawning, pathfinding, misalignment in the perfection end-game slide show, etc.

Breather (Optional) Whether the chest on the NPC's overworld sprite puffs in and out as they breathe. Default true.
BreathChestRect (Optional) A rectangle pixel area within the spritesheet which expands and contracts to simulate breathing, relative to the top-left corner of the source rectangle for their current sprite. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
BreathChestPosition (Optional) A point pixel offset to apply to the NPC's BreathChestPosition when drawn over the NPC. Omit to calculate it automatically. This should be omitted for most NPCs, unless they have a non-standard size.
Shadow (Optional) The options for the shadow to draw under the NPC, or omit to apply the default shadow behavior.

This consists of a model with these fields:

field effect
Visible (Optional) Whether the shadow should be drawn. Default true.
Offset (Optional) A point pixel offset applied to the shadow position. Default zero.
Scale (Optional) The scale at which to draw the shadow. Default 1.

This is a multiplier applied to the default shadow scale, which can change based on factors like whether the NPC is jumping. For example, 0.5 means half the size it'd be drawn if you didn't specify a scale.

EmoteOffset (Optional) A point pixel offset applied to emote drawn over the NPC. Default zero.
ShakePortraits (Optional) The portrait indexes which should shake when displayed. Default none.
KissSpriteIndex (Optional) If the NPC can be married, the sprite index within their Texture to use when kissing a player. Default 28.
KissSpriteFacingDirection (Optional) Whether the character is facing right (true) or left (false) in their KissSpriteIndex. The sprite will be flipped as needed to face the player. Default true.

Hidden gift log emote

field effect
HiddenProfileEmoteSound (Optional) For the hidden gift log emote, the cue ID for the sound played when clicking the sprite. Defaults to drumkit6.
HiddenProfileEmoteDuration (Optional) For the hidden gift log emote, how long the animation plays measured in milliseconds. Defaults to 4000 (4 seconds).
HiddenProfileEmoteStartFrame (Optional) For the hidden gift log emote, the index within the NPC's overworld sprite spritesheet at which the animation starts. If omitted for a vanilla NPC, the game plays a default animation specific to that NPC; if omitted for a custom NPC, the game just shows them walking while facing down.
HiddenProfileEmoteFrameCount (Optional) For the hidden gift log emote, the number of frames in the animation. The first frame corresponds to HiddenProfileEmoteStartFrame, and each subsequent frame will use the next sprite in the spritesheet. Default 1.

This has no effect if HiddenProfileEmoteStartFrame isn't set.

HiddenProfileEmoteFrameDuration (Optional) For the hidden gift log emote, how long each animation frame is shown on-screen before switching to the next one, measured in milliseconds. Default 200.

This has no effect if HiddenProfileEmoteStartFrame isn't set.

Advanced

field effect
CustomFields The custom fields for this entry.
FormerCharacterNames (Optional) The former NPC names which may appear in save data. If matched, the game will rename the NPC and update related data (e.g. friendship).

A former name is only applied if:

  1. it doesn't match a current ID in Data/Characters;
  2. the save has an NPC with the former name;
  3. the save doesn't already have an NPC with the new name.

For example:

"FormerCharacterNames": [ "SomeOldName" ]

Former names can have any format, but they must be globally unique. They can't match the ID or FormerCharacterNames of any other NPC in Data/Characters (whether vanilla or custom).

FestivalVanillaActorIndex (Optional, Specialized) The NPC's index in the Maps/characterSheet tilesheet, if applicable. This is used for placing vanilla NPCs in festivals from the map; custom NPCs should use the <layer>_additionalCharacters field in the festival data instead.

Gift tastes

main gift data
The Data/NPCGiftTastes asset contains their gift preferences (e.g., which gifts they love or hate), and their responses when they receive one. See Modding:Gift taste data for more info.
The file has one row per NPC like this:
Abigail: "I seriously love this! You're the best, @!/66 128 220 226 276 611/Hey, how'd you know I was hungry? This looks delicious!//What am I supposed to do with this?/-5 -75 -79 16 245 246/What were you thinking? This is awful!/330/You brought me a present? Thanks.//"
The line can be broken down into 5 pairs of dialogue + item IDs in this order: Love, Like, Dislike, Hate, Neutral. If a dialogue field is empty, the game will use a generic dialogue text. See Modding:Items for the object IDs.
gift dialogue
When you gift an NPC, they'll show a dialogue dialogue in this order:
  1. on their birthday, an AcceptBirthdayGift dialogue key, else a default dialogue like NPC.cs.4274 ("You remembered my birthday? I'm impressed. Thanks.$h");
  2. an AcceptGift_* dialogue;
  3. else the dialogue in Data/NPCGiftTastes with a default portrait (which can be overridden with portrait commands like $h).

Overworld sprites

The sprite sheet for Abigail.

The overworld sprites are stored in Characters/NpcName, including movement and animation frames. Each frame is exactly 16x32 pixels. Here's an example sprite guide, courtesy of TheLimeyDragon#1993 on Discord. Some positions are reserved for certain actions:

  • the first sixteen frames are generic movement (four frames per direction);
  • frames 40–47 (female) and 44–47 (male) must be the Flower Dance dance, if they participate;
  • frames 36–38 (female) 48–50 (male) are reserved for marriageable NPCs (Contains Wedding sprite);
  • and the kissing sprite/direction varies depending on NPC:
    character kissing frame facing direction
    Abigail and Emily 33 left
    Alex 42 right
    Elliott 35 left
    Haley 28 right
    Harvey 31 left
    Leah 25 right
    Maru 28 left
    Penny 35 right
    Sam 36 right
    Sebastian 40 left
    Shane 34 left
    any other NPC 28 right

Portraits

Abigail's portrait sprite sheet.

The dialogue portraits are stored in Portraits/NpcName. Each frame is exactly 64x64 per portrait. The first six represent specific emotions (see Modding:Dialogue#Portrait commands), followed by any number of custom portraits. The first portrait is used when the dialogue doesn't specify one.

Schedule

Their schedule file tells the game where the NPC starts and moves based on on the time. You need to add strings to a separate schedules file found in the Strings folder to allow custom dialogue. See Modding:Schedule data for more info.

Dialogue

The NPC dialogue and events are stored in several files; see Modding:Dialogue.

Sleep animation

When the NPC goes to bed, they'll play the looping sleep animation set via <lowercase NPC name>_sleep in Data/animationDescriptions, if it exists. For example, this content pack adds a sleep animation for an NPC named 'Pufferbob':

{
    "Format": "2.3.0",
    "Changes": [
        {
            "Action": "EditData",
            "Target": "Data/animationDescriptions",
            "Entries": {
                "pufferbob_sleep": "50/50/50" // note: make name lowercase
            }
        }
    ]
}

Secondary assets

  • See event data for the NPC's cutscenes.
  • See festival data for an NPC's positions (via the Set-Up_additionalCharacters and MainEvent_additionalCharacters fields) and dialogue in festivals.
  • See movie theater data for an NPC's taste in movies and concessions.

Example

Here's how you'd create an example NPC named Dobson with full social features.

Note that {{ModId}} is a Content Patcher token, which will be replaced with your mod ID automatically for the unique string ID convention.

  1. Create an empty Content Patcher content pack. By convention, we'll name the folder [CP] Dobson.
  2. Create the following files:
    • assets/dialogue.json containing the dialogue.
    • assets/marriageDialogue.json containing the marriage dialogue (if applicable).
    • assets/sprites.png containing their overworld sprites.
    • assets/portraits.png containing their portraits.
    • assets/schedule.json containing their schedule data.
  3. Edit the content.json to load the files:
    {
        "Format": "2.3.0",
        "Changes": [
            {
                "Action": "Load",
                "Target": "Characters/{{ModId}}_Dobson",
                "FromFile": "assets/sprites.png"
            },
            {
                "Action": "Load",
                "Target": "Portraits/{{ModId}}_Dobson",
                "FromFile": "assets/portraits.png"
            },
            {
                "Action": "Load",
                "Target": "Characters/Dialogue/{{ModId}}_Dobson",
                "FromFile": "assets/dialogue.json"
            },
            {
                "Action": "Load",
                "Target": "Characters/Dialogue/MarriageDialogue{{ModId}}_Dobson",
                "FromFile": "assets/marriageDialogue.json"
            },
            {
                "Action": "Load",
                "Target": "Characters/schedules/{{ModId}}_Dobson",
                "FromFile": "assets/schedule.json"
            },
            {
                "Action": "EditData",
                "Target": "Data/Characters",
                "Entries": {
                    "{{ModId}}_Dobson": {
                        "DisplayName": "Dobson", // this can use {{i18n:}} to support translations
                        "BirthSeason": "Summer",
                        "BirthDay": 7,
                        "HomeRegion": "Town",
                        "Gender": "Male",
                        "Age": "Adult",
                        "Manner": "Rude",
                        "SocialAnxiety": "Neutral",
                        "Optimism": "Positive",
    
                        "CanBeRomanced": true,
    
                        "Home": [
                            {
                                "Id": "Default",
                                "Location": "BusStop",
                                "Tile": "19, 4"
                            }
                        ]
                    }
                }
            },
            {
                "Action": "EditData",
                "Target": "Data/NPCGiftTastes",
                "Entries": {
                    "{{ModId}}_Dobson": "You're giving this to me? This is amazing!/207 232 233 400/Thank you! This is a very interesting specimen./-5 -79 422/...What is this?/80 330/This is disgusting./2/That was very thoughtful of you./-4/ "
                }
            },
            {
                "Action": "EditData",
                "Target": "Data/EngagementDialogue",
                "Entries": {
                    "{{ModId}}_Dobson0": "I can't believe I am about to be married!$h",
                    "{{ModId}}_Dobson1": "I hope I don't get cold feet"
                }
            }
        ]
    }
    

That's it! If you load your game, the NPC should appear. If you want to create events, don't forget to add that file too.

See also