Changes

→‎Portraits: remove broken hotlinked image (images should be uploaded to the wiki with an open license instead)
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}} (with some caveats).
+
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===
 
===Basic info===
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\NPCDispositions</samp> asset contains basic information for your character, including their name, birthday, relations to other characters, personality, and whether they can be dated.
    
The file has one row per NPC like this:
 
The file has one row per NPC like this:
<source lang="yaml">
+
<syntaxhighlight lang="yaml">
 
   Abigail: "teen/rude/outgoing/neutral/female/datable/Sebastian/Town/fall 13/Caroline 'mom' Pierre 'dad'/SeedShop 1 9/Abigail"
 
   Abigail: "teen/rude/outgoing/neutral/female/datable/Sebastian/Town/fall 13/Caroline 'mom' Pierre 'dad'/SeedShop 1 9/Abigail"
</source>
+
</syntaxhighlight>
    
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:
 
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:
Line 27: Line 27:  
| 0
 
| 0
 
| age
 
| age
| <tt>teen</tt>
+
| <samp>teen</samp>
| Whether the NPC is a <tt>child</tt>, <tt>teen</tt>, or <tt>adult</tt>. <span color="red">TODO</span>: what does this affect?
+
| Whether the NPC is a <samp>child</samp>, <samp>teen</samp>, or <samp>adult</samp>. 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
 
| 1
 
| manners
 
| manners
| <tt>rude</tt>
+
| <samp>rude</samp>
| Whether the NPC is <tt>polite</tt>, <tt>rude</tt>, or <tt>neutral</tt>. This affects some generic dialogue lines.
+
| Whether the NPC is <samp>polite</samp>, <samp>rude</samp>, or <samp>neutral</samp>. This affects some generic dialogue lines.
 
|-
 
|-
 
| 2
 
| 2
 
| social anxiety
 
| social anxiety
| <tt>outgoing</tt>
+
| <samp>outgoing</samp>
| Whether the NPC is <tt>outgoing</tt>, <tt>shy</tt>, or <tt>neutral</tt>. This affects some generic dialogue lines.
+
| Whether the NPC is <samp>outgoing</samp>, <samp>shy</samp>, or <samp>neutral</samp>. This affects some generic dialogue lines.
 
|-
 
|-
 
| 3
 
| 3
 
| optimism
 
| optimism
| <tt>neutral</tt>
+
| <samp>neutral</samp>
| Whether the NPC is <tt>positive</tt>, <tt>negative</tt>, or <tt>neutral</tt>. <span color="red">TODO</span>: what does this affect?
+
| Whether the NPC is <samp>positive</samp>, <samp>negative</samp>, or <samp>neutral</samp>. ''Unused.''
 
|-
 
|-
 
| 4
 
| 4
 
| gender
 
| gender
| <tt>female</tt>
+
| <samp>female</samp>
| Whether the NPC is <tt>male</tt> or <tt>female</tt>. This affects dialogue, whether children in marriage are obtained through adoption or pregnancy, and the reserved frames' positions on the spritesheet.
+
| Whether the NPC is <samp>male</samp>, <samp>female</samp>, or <samp>undefined</samp>. This affects dialogue, whether children in marriage are obtained through adoption or pregnancy, and the reserved frames' positions on the spritesheet.
 
|-
 
|-
 
| 5
 
| 5
 
| datable
 
| datable
| <tt>datable</tt>
+
| <samp>datable</samp>
| Whether the NPC is <tt>datable</tt> or <tt>non-datable</tt>. This toggles the romance features (e.g. 'single' label in the social menu, bouquet gifting, and marriage).
+
| Whether the NPC is <samp>datable</samp>, <samp>not-datable</samp>, or <samp>secret</samp>. The former two toggle the romance features (''e.g.,'' 'single' label in the social menu, bouquet gifting, and marriage), while <samp>secret</samp> is used exclusively for Krobus, who cannot be married but can be made a roommate.
 
|-
 
|-
 
| 6
 
| 6
 
| love interest
 
| love interest
| <tt>Sebastian</tt>
+
| <samp>Sebastian</samp>
| ''unused''
+
| ''Unused.''
 
|-
 
|-
 
| 7
 
| 7
 
| home region
 
| home region
| <tt>Town</tt>
+
| <samp>Town</samp>
| 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).
+
| Whether the NPC lives in the <samp>Desert</samp>, <samp>Town</samp>, or <samp>Other</samp>. 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 <samp>Town</samp> region).
 
|-
 
|-
 
| 8
 
| 8
 
| birthday
 
| birthday
| <tt>fall 13</tt>
+
| <samp>fall 13</samp>
 
| The season and day for the NPC's birthday.
 
| The season and day for the NPC's birthday.
 
|-
 
|-
 
| 9
 
| 9
 
| relationships
 
| relationships
| <tt>Caroline 'mom' Pierre 'dad'</tt>
+
| <samp>Caroline 'mom' Pierre 'dad'</samp>
| This determines special generic Dialogue for revealing likes and dislikes to family members. May also affect the inlaw_<NPC> dialogue.
+
| 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
 
| 10
 
| default map & position
 
| default map & position
| <tt>SeedShop 1 9</tt>
+
| <samp>SeedShop 1 9</samp>
 
| The location name and [[Modding:Modder Guide/Game Fundamentals#Tiles|tile position]] where the NPC starts and ends each day.
 
| The location name and [[Modding:Modder Guide/Game Fundamentals#Tiles|tile position]] where the NPC starts and ends each day.
 
|-
 
|-
 
| 11
 
| 11
 
| display name
 
| display name
| <tt>Abigail</tt>
+
| <samp>Abigail</samp>
 
| The NPC name shown to the player.
 
| The NPC name shown to the player.
 
|}
 
|}
    
===Gift tastes===
 
===Gift tastes===
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.
+
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:
 
The file has one row per NPC like this:
<source lang="yaml">
+
<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
 
   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
</source>
+
</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.
+
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.
 +
 
 +
====Birthday gift responses====
 +
The <samp>Strings\StringsFromCSFiles</samp> 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:
 +
 
 +
{| class="wikitable"
 +
|-
 +
! gift taste
 +
! manners
 +
! chance
 +
! string
 +
! english string
 +
|-
 +
| rowspan="4" | love, like
 +
| rowspan="2" | rude
 +
| 50%
 +
| <samp>NPC.cs.4274</samp>
 +
| <samp>"You remembered my birthday? I'm impressed. Thanks.$h"</samp>
 +
|-
 +
| 50%
 +
| <samp>NPC.cs.4276</samp>
 +
| <samp>"Oh, is it my birthday today? I guess it is. Thanks. This is nice.$h/Oh, is it my birthday today? I guess it is. Thanks. This is nice.$h"</samp>
 +
|-
 +
| rowspan="2" | polite, neutral
 +
| 50%
 +
| <samp>NPC.cs.4275</samp>
 +
| <samp>"A birthday gift? That's very kind of you! I love it.$h"</samp>
 +
|-
 +
| 50%
 +
| <samp>NPC.cs.4277</samp>
 +
| <samp>"You remembered my birthday! Thank you. This is great.$h"</samp>
 +
|-
 +
| rowspan="2" | dislike, hate
 +
| rude
 +
| 100%
 +
| <samp>NPC.cs.4278</samp>
 +
| <samp>"It's my birthday and you give me this? Is this some kind of joke?$s/It's my birthday and you give me this? Is this some kind of joke?$s"</samp>
 +
|-
 +
| polite, neutral
 +
| 100%
 +
| <samp>NPC.cs.4279</samp>
 +
| <samp>"Oh... It's for my birthday? ... Thanks.$s/Oh... It's for my birthday? ... Thanks.$s"</samp>
 +
|-
 +
| rowspan="2" | neutral
 +
| rude
 +
| 100%
 +
| <samp>NPC.cs.4280</samp>
 +
| <samp>"For my birthday? Thanks."</samp>
 +
|-
 +
| polite, neutral
 +
| 100%
 +
| <samp>NPC.cs.4281</samp>
 +
| <samp>"Oh, a birthday gift! Thank you./Oh, a birthday gift! Thank you."</samp>
 +
|}
 +
 
 +
The <samp>$h</samp> and <samp>$s</samp> are [[Modding:Dialogue#Portrait_commands|portrait commands]] that select the portrait image of the character to use.
    
===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, and some positions are reserved for certain actions:
+
 
* the first sixteen frames are generic movement (four frames per direction);
+
[[File:Abigail-sprite-sheet.png|thumb|The sprite sheet for Abigail.]]
* frames 33 (female) and 35 (male) must be the kissing sprite if they're marriageable;
+
 
* frames 40&ndash;47 (female) and 44&ndash;47 (male) must be the Flower Dance dance, if they participate;
+
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:
* frames 36&ndash;38 (female) 48&ndash;50 (male) are reserved for marriageable NPCs (Contains Wedding sprite).
+
<ul>
 +
<li>the first sixteen frames are generic movement (four frames per direction);</li>
 +
<li>frames 40–47 (female) and 44–47 (male) must be the Flower Dance dance, if they participate;</li>
 +
<li>frames 36–38 (female) 48–50 (male) are reserved for marriageable NPCs (Contains Wedding sprite);</li>
 +
<li>and the kissing sprite/direction varies depending on NPC:
 +
{| class="wikitable"
 +
|-
 +
! 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
 +
|}</li>
 +
</ul>
    
===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. Each NPC can have up to 12 portraits.
+
[[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===
Line 113: Line 229:     
===Festivals===
 
===Festivals===
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.
+
Custom NPCs should be added to festivals via the <samp>Set-Up_additionalCharacters</samp> and <samp>MainEvent_additionalCharacters</samp> fields in the [[Modding:Festival_data#Data_file|festival's data file]]. You may also want to visit [https://stardewmodding.wiki.gg/wiki/Custom_NPC_Tiles Custom NPC festival tile positions] to check the positions of various existing NPCs for compatibility purposes.
 +
 
 +
(Prior to Stardew Valley 1.5, {{nexus mod|1820|TMXL}} was the recommended tool for adding festival spots.)
 +
 
 +
===Movie theater===
 +
An NPC's taste in movies and concessions are stored in <samp>Data\MoviesReactions.xnb</samp> and <samp>Data\ConcessionTastes.xnb</samp>, respectively. See [[Modding:Movie theater data]] for details on how these function.
 +
 
 +
===Spouse room===
 +
If your NPC will be a marriage candidate, note that you can add a spouse room for them much more easily after game version 1.5.5. See [[Modding:Migrate_to_Stardew_Valley_1.5.5#Custom_spouse_rooms]] for details.
 +
 
 +
===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}}
 +
}
    
==Adding your NPC==
 
==Adding your NPC==
Line 119: Line 261:     
<ol>
 
<ol>
<li>[https://github.com/Pathoschild/StardewMods/tree/develop/ContentPatcher#create-a-content-pack 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:
<source lang="json">
+
{{#tag:syntaxhighlight|
 
{
 
{
  "Format": "1.5",
+
    "Format": "{{Content Patcher version}}",
  "Changes": [
+
    "Changes": [
    {
+
        {
      "LogName": "Sprites",
+
            "Action": "Load",
      "Action": "Load",
+
            "Target": "Characters/Dobson",
      "Target": "Characters/Dobson",
+
            "FromFile": "assets/sprites.png"
      "FromFile": "assets/sprites.png",
+
        },
    },
+
        {
    {
+
            "Action": "Load",
      "LogName": "Portraits",
+
            "Target": "Portraits/Dobson",
      "Action": "Load",
+
            "FromFile": "assets/portraits.png"
      "Target": "Characters/Portraits/Dobson",
+
        },
      "FromFile": "assets/portraits.png",
+
        {
    },
+
            "Action": "Load",
    {
+
            "Target": "Characters/Dialogue/Dobson",
      "LogName": "Marriage Dialogue",
+
            "FromFile": "assets/dialogue.json"
      "Action": "Load",
+
        },
      "Target": "Characters/Dialogue/MarriageDialogueDobson",
+
        {
      "FromFile": "assets/marriageDialogue.json",
+
            "Action": "Load",
    },
+
            "Target": "Characters/Dialogue/MarriageDialogueDobson",
    {
+
            "FromFile": "assets/marriageDialogue.json"
      "LogName": "Schedule",
+
        },
      "Action": "Load",
+
        {
      "Target": "Characters/schedules/Dobson",
+
            "Action": "Load",
      "FromFile": "assets/schedule.json",
+
            "Target": "Characters/schedules/Dobson",
    },
+
            "FromFile": "assets/schedule.json"
    {
+
        },
      "LogName": "NPC Dispositions",
+
        {
      "Action": "EditData",
+
            "Action": "EditData",
      "Target": "Data/NPCDispositions",
+
            "Target": "Data/NPCDispositions",
      "Entries": {
+
            "Entries": {
        "Dobson": "adult/rude/neutral/positive/male/datable//Town/summer 7//BusStop 19 4/Dobson"
+
                "Dobson": "adult/rude/neutral/positive/male/datable//Town/summer 7//BusStop 19 4/Dobson"
      },
+
            }
    },
+
        },
    {
+
        {
      "LogName": "Gift tastes",
+
            "Action": "EditData",
      "Action": "EditData",
+
            "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/ "
        "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": {
 +
                "Dobson0": "I can't believe I am about to be married!$h",
 +
                "Dobson1": "I hope I don't get cold feet"
 +
            }
 +
        }
 +
    ]
 
}
 
}
</source>
+
|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 [[Modding:Index#See_also]] for some recommended guides.
    
[[Category:Modding]]
 
[[Category:Modding]]
 +
 +
[[es:Modding:Datos de NPC]]
 +
[[pt:Modificações:Dados do NPC]]
 +
[[ru:Модификации:О NPC]]
translators
8,404

edits