Stardew Valley Reference

NPC Helper

Runtime custom NPC importer for Stardew Valley content packs.

Stardew Valley 1.6+SMAPI 4.0+Content packsTOML

Introduction

NPC Helper is a Stardew Valley mod for creating custom NPCs with simple TOML configuration files. No C# coding is required for normal content packs.

  • TOML-based NPC definitions with readable files.
  • Dynamic dialogue using Stardew Valley native dialogue keys, including daily, heart-level, location, time, festival, question, and gift response keys.
  • Day, season, exact date, weekday, weekend, and named weekday schedule filtering.
  • Location, season, weather, festival, and birthday sprite or portrait variants with fallback handling.
  • Gift tastes, gift response messages, localization overlays, and a small API for mod integrations.

Installation

Prerequisites

NPC Helper requires Stardew Valley 1.6 or higher and SMAPI 4.0 or higher.

1
Install SMAPI

Download and install SMAPI from smapi.io.

2
Download NPC Helper

Download the latest version from Nexus Mods.

3
Extract to Mods

Extract the NPC Helper folder to Stardew Valley/Mods/.

4
Launch through SMAPI

Start Stardew Valley through SMAPI and check the console for [NpcHelper] Loaded.

Quick Start Guide

Before you begin

Make sure NPC Helper is installed and loading before creating your first custom NPC content pack.

Mods/
└── MyFirstNPC/              # Your content pack folder
    ├── manifest.json        # Required: SMAPI metadata
    ├── mod.toml             # Required: NPC list
    └── NPCs/
        └── Alex/            # Example NPC name
            ├── Alex.toml    # NPC definition
            ├── sprite.png   # Character sprite, 16x32 per frame
            └── portrait.png # Portrait, 64x64 per expression
{
  "Name": "My First NPC",
  "Author": "YourName",
  "Version": "1.0.0",
  "Description": "Adds a custom NPC to Stardew Valley",
  "UniqueID": "YourName.MyFirstNPC",
  "ContentPackFor": {
    "UniqueID": "TamKungZ.NpcHelper"
  },
  "UpdateKeys": []
}
# List NPC definition files relative to this content pack.
NPCs = ["NPCs/Alex/Alex.toml"]
# Basic Identity
Name = "Alex"
DisplayName = "Alex the Adventurer"
Gender = "male"
Age = "adult"

# Birthday
BirthdaySeason = "spring"
BirthdayDay = 13

# Starting Location
DefaultMap = "Town"
DefaultX = 52
DefaultY = 87
DefaultFacing = 2

# Assets
CustomSpritePath = "sprite.png"
CustomPortraitPath = "portrait.png"
1
Launch the game

Start Stardew Valley with SMAPI.

2
Check registration

Look for [NpcHelper] Registered NPC definition: Alex in the SMAPI console.

3
Load a save

Look for the NPC at the configured map and tile coordinates.

4
Interact

Talk to the NPC to verify portrait, sprite, and dialogue assets load.

Configuration Files

FileRequiredPurpose
manifest.jsonYesSMAPI content pack metadata. Must reference TamKungZ.NpcHelper.
mod.tomlYesEntry file that lists NPC definition files relative to the content pack root.
NPCs/<Name>/<Name>.tomlYesMain NPC definition: identity, location, relationship flags, assets, dialogue path, schedule path, variants, and gifts.
Dialogue.tomlOptionalSeparate Stardew Valley dialogue keys and gift response messages.
Schedule.tomlOptionalDaily movement routes with day, season, and date filters.
sprite.pngRequired unless CustomSpritePath points elsewhereDefault sprite sheet. Each frame follows the standard Stardew NPC sprite size.
portrait.pngRequired unless CustomPortraitPath points elsewhereDefault portrait sheet. Each expression follows the standard Stardew portrait size.
locale/<language-code>/*.tomlOptionalLocalized overlays for translated names, dialogue, and gift response messages.

manifest.json

This file defines your content pack metadata. ContentPackFor.UniqueID must be exactly TamKungZ.NpcHelper.

{
  "Name": "My Custom NPC Pack",
  "Author": "YourName",
  "Version": "1.0.0",
  "UniqueID": "YourName.MyCustomNPCs",
  "Description": "Adds custom NPCs to Stardew Valley",
  "ContentPackFor": {
    "UniqueID": "TamKungZ.NpcHelper"
  },
  "UpdateKeys": []
}

mod.toml

Lists all NPC definition files relative to the content pack root.

# List all NPC definition files
NPCs = [
  "NPCs/Rei/Rei.toml",
  "NPCs/Alex/Alex.toml",
  "NPCs/Sophia/Sophia.toml"
]

NPC Definition (.toml)

The main TOML file defines an NPC. Place it inside the NPC folder and reference it from mod.toml.

# Basic Identity
Name = "Rei"                    # Internal name: unique and no spaces
DisplayName = "Rei"             # Name shown to players

# Core Properties
Gender = "female"               # "male" or "female"
Age = "adult"                   # "child", "teen", or "adult"
Manner = "polite"               # "polite", "rude", or "neutral"
SocialAnxiety = "neutral"       # "outgoing", "shy", or "neutral"
Optimism = "positive"           # "positive", "negative", or "neutral"

# Birthday
BirthdaySeason = "summer"       # "spring", "summer", "fall", or "winter"
BirthdayDay = 12                # 1-28

# Spawn Location
HomeRegion = "Town"             # Region for game logic
DefaultMap = "Hospital"         # Starting map
DefaultX = 9                    # X tile coordinate
DefaultY = 7                    # Y tile coordinate
DefaultFacing = 2               # 0=Up, 1=Right, 2=Down, 3=Left

# Relationship Flags
Datable = true                  # Can be dated
Marriageable = true             # Can be married

# Asset Paths
CustomSpritePath = "sprite.png"             # Default sprite
CustomPortraitPath = "portrait.png"         # Default portrait

# External Files
DialoguePath = "Dialogue.toml"              # Separate dialogue file
SchedulePath = "Schedule.toml"              # Separate schedule file

# Sprite Variants
[Sprites]
Hospital = "sprite_Hospital.png"           # When at Hospital
Beach = "sprite_Beach.png"                 # When at Beach
summer = "sprite_Summer.png"               # During summer
rainy = "sprite_Rainy.png"                 # When raining

# Portrait Variants
[Portraits]
Hospital = "portrait_Hospital.png"         # When at Hospital
summer = "portrait_Summer.png"             # During summer

# Gift Tastes
[GiftTastes]
# Item IDs, names, universal taste keys, or context tags
Love = ["Diamond", "Coffee", "Universal_Love"]
Like = ["Blueberry", "Universal_Like"]
Neutral = ["Universal_Neutral"]
Dislike = ["Universal_Dislike"]
Hate = ["Universal_Hate"]
PropertyAllowed ValuesDescription
Gender"male", "female"Determines pronouns and base sound effects.
Age"child", "teen", "adult"Affects walking speed, height, and events.
Manner"neutral", "polite", "rude"Changes speech bubble shape and default reactions.
SocialAnxiety"neutral", "outgoing", "shy"Affects idle animations and social behavior.
Optimism"neutral", "positive", "negative"General personality bias.
BirthdaySeason"spring", "summer", "fall", "winter"Season of the NPC birthday.
BirthdayDay1-28Day of the season for the NPC birthday.
HomeRegionGame region nameRegion used by game logic and map grouping.
DefaultMapValid map nameMap where the NPC starts if no schedule overrides it.
DefaultX, DefaultYTile coordinatesStarting tile coordinates on DefaultMap.
DefaultFacing0, 1, 2, 30: Up, 1: Right, 2: Down, 3: Left.
Databletrue, falseWhether the NPC can receive bouquet dating state.
Marriageabletrue, falseWhether the NPC can be married.
DialoguePathRelative TOML pathExternal dialogue file relative to the NPC folder.
SchedulePathRelative TOML pathExternal schedule file relative to the NPC folder.

Dialogue System

Follows Stardew Valley Standards

NPC Helper uses Stardew Valley native dialogue system. All dialogue keys and formats must follow the official Stardew Valley format. View complete documentation on Stardew Valley Wiki. The older [condition] syntax is not supported; use Stardew Valley key formats such as 4, Mon4, Town_2000, and festival keys.

Dialogue is defined in TOML files. NPC Helper passes the dialogue to the game engine, which handles selection, friendship levels, dates, locations, and special commands.

[Dialogue]
Introduction = "Hi, I'm Rei. Nice to meet you!"

# Day of week
Mon = "Mondays are tough, but we'll get through it."
Tue = "Tuesday already? Time flies."

# Heart levels
2 = "You're becoming a familiar face."
4 = "Good to see you again!"
6 = "I'm glad we're friends."

# Location-based
Hospital = "I'm on duty today. Please don't distract me too much."
Town = "The town looks peaceful today."

# Seasonal and date dialogue
spring_1 = "Spring is finally here!"
winter_24 = "Happy Winter Star!"

# Time-based
Town_2000 = "It's getting late. You should head home soon."

# Weekly rotation
Greeting = "Hello! || Hi there! || Good to see you!"

# Festival dialogue
EggFestival = "Egg hunting isn't really my thing."
FlowerDance = "The flowers are beautiful this year."

# Questions and response options
Question = "$q 100/101 Do you like medicine?#$b#I'm just curious."
AnswerYes = "$r 100 10 Yes, I find it fascinating!"
AnswerNo = "$r 101 0 Not really, it's not for me."

# Relationship and gift keys
breakUp = "This is for the best..."
divorced = "Please, just leave me alone."
AcceptGift_Loved = "This is wonderful! Thank you!"
AcceptGift_Liked = "Thanks, I appreciate it."
Key or CommandPurpose
IntroductionFirst meeting dialogue.
Mon, Tue, Wed, Thu, Fri, Sat, SunDay-of-week dialogue.
2, 4, 6, 8, 10Heart-level dialogue keys. Stardew Valley uses numeric friendship suffixes.
spring_1, winter_24Season and day keys using season_day.
Hospital, TownLocation-specific dialogue.
Hospital_TueLocation plus day combination.
Town_2000Location plus time combination.
EggFestivalFestival-specific dialogue.
DefaultFallback dialogue.
breakUpDialogue after breaking up.
divorcedDialogue after divorce.
RejectBouquetDialogue when rejecting a bouquet.
DumpsterDiveCommentDialogue when the player digs in trash nearby.
AcceptGift_Loved, AcceptGift_LikedGift reaction keys.
$h, $s, $uPortrait emotes.
$q, $rQuestion dialogue and response options.
||Weekly rotation separator.
@Player name replacement.
${male^female}Gender-specific text.
Dialogue priority

Stardew Valley checks more specific keys before generic ones. In practice, location-specific, seasonal, heart-level, day-of-week, and generic fallback keys compete based on the vanilla dialogue resolver.

Old format (not supported):
[friendship >= 6] Hello friend! || Hi there.
[time >= 1800] Good evening! || Hello.
[season = summer] It's hot today!

New Stardew Valley format:
6 = "Hello friend!"
Default = "Hi there."
Town_1800 = "Good evening!"
Town = "Hello."
summer = "It's hot today!"
Migration notice

Existing NPCs using old [condition] dialogue must be converted to Stardew Valley dialogue keys. Use the Dialogue Converter notes below or manually update your TOML files before release.

Conditional Dialogue Migration

Older NPC Helper content sometimes used custom [condition] dialogue lines. Current NPC Helper expects Stardew Valley native dialogue keys instead, so conditions should be represented as key names whenever possible.

Old condition intentUse this Stardew-style key
Friendship at 2 hearts2
Friendship at 4 hearts on MondayMon4
Dialogue at TownTown
Dialogue at Town after 8:00 PMTown_2000
Spring day 1 dialoguespring_1
Winter Star dialoguewinter_24 or the relevant festival key.
Multiple possible greetingsGreeting = "Hello! || Hi there! || Good to see you!"
# Do not use this old custom condition syntax:
# [friendship >= 4] Good to see you again.
# [time >= 1800] Good evening.
# [season = summer] It is hot today.

# Use native Stardew Valley keys:
[Dialogue]
4 = "Good to see you again."
Town_1800 = "Good evening."
summer = "It is hot today."
Default = "Hello."
No bracket conditions

Do not mix old bracketed conditions with Stardew dialogue keys in release content. If a condition cannot be represented by a vanilla key, implement it through a mod integration instead of the content-pack dialogue table.

Dialogue Converter Notes

The legacy page linked to #dialogue-converter, but that anchor did not have a full section in the old HTML. This section keeps the migration guidance visible in the new documentation.

1
Find old condition lines

Search dialogue files for bracketed conditions such as [friendship >= 4], [time >= 1800], or [season = summer].

2
Map conditions to native keys

Use heart-level keys, day keys, location keys, time keys, seasonal keys, festival keys, or Default whenever they match the intended behavior.

3
Move gift response text

Use AcceptGift_* and AcceptBirthdayGift_* keys in Dialogue.toml instead of old message fields under [GiftTastes].

4
Test small first

Start with Introduction, one weekday key, and Default, then add more specific keys after the NPC is confirmed to load.

Search targets:
[friendship
[time
[season
LoveMessage
LikeMessage
NeutralMessage
DislikeMessage
HateMessage

Common replacements:
[friendship >= 2] -> 2
[friendship >= 4 on Monday] -> Mon4
[time >= 2000 in Town] -> Town_2000
[season = spring day = 1] -> spring_1
LoveMessage -> AcceptGift_Loved
LikeMessage -> AcceptGift_Liked

Schedule System

Schedules define NPC movement patterns throughout the day. Entries can be filtered by weekday/weekend, specific days, season, or exact date.

# Separate Schedule.toml file structure

# Weekday schedule
[[Schedule]]
Time = 600              # 6:00 AM
Map = "Hospital"
X = 1
Y = 18
Facing = 2              # Facing down
Days = "Weekday"        # Monday through Friday

[[Schedule]]
Time = 1200             # 12:00 PM
Map = "Town"
X = 29
Y = 54
Facing = 2
Days = "Weekday"
Action = "Having lunch" # Optional description

[[Schedule]]
Time = 1800             # 6:00 PM
Map = "Hospital"
X = 13
Y = 5
Facing = 0              # Facing up
Days = "Weekday"

# Weekend schedule
[[Schedule]]
Time = 900              # 9:00 AM
Map = "Beach"
X = 20
Y = 20
Facing = 2
Days = "Weekend"        # Saturday and Sunday

[[Schedule]]
Time = 1700             # 5:00 PM
Map = "Saloon"
X = 21
Y = 17
Facing = 1
Days = "Weekend"

# Specific day schedule
[[Schedule]]
Time = 1000             # 10:00 AM
Map = "ArchaeologyHouse"
X = 15
Y = 8
Facing = 2
Season = "spring"
Day = 1                 # Only on Spring 1

# Birthday schedule
[[Schedule]]
Time = 1400             # 2:00 PM
Map = "Saloon"
X = 21
Y = 17
Season = "summer"       # Rei's birthday is Summer 12
Day = 12

# Specific days of week
[[Schedule]]
Time = 800
Map = "Forest"
X = 45
Y = 32
Facing = 2
Days = "Mon,Wed,Fri"    # Only on Monday, Wednesday, Friday
FieldRequiredMeaning
TimeYesGame time as an integer, such as 600, 1200, or 1800.
MapYesTarget map name. It must exist in the current game and installed mods.
X, YYesTarget tile coordinates on the map.
FacingRecommendedFacing direction after arriving: 0 up, 1 right, 2 down, 3 left.
ActionOptionalHuman-readable action text or description for the schedule stop.
DaysOptionalWeekday, Weekend, or comma-separated day names.
SeasonOptionalRestricts the entry to spring, summer, fall, or winter.
DayOptionalRestricts the entry to a day of the season, usually 1-28.
FilterMeaning
Days = "Weekday"Monday through Friday.
Days = "Weekend"Saturday and Sunday.
Days = "Mon,Tue,Wed"Specific days.
Days = "Mon,Wed,Fri"Multiple specific days.
Season = "spring"Only in spring.
Day = 12Only on day 12 of the month.
Season = "winter", Day = 24Only on Winter 24.
No Days or date filtersApplies every matching day.
Schedule matching

Use specific season and day entries for one-off schedules such as birthdays or festivals, and use broad weekday/weekend entries for normal routines. Keep tile coordinates valid, because invalid maps or blocked tiles are common causes of NPCs not appearing where expected.

Gift Tastes System

Breaking change

LoveMessage, LikeMessage, and similar message keys inside [GiftTastes] are no longer supported. Gift response messages must be in Dialogue.toml using AcceptGift_* keys.

Gift tastes define what items your NPC loves, likes, is neutral about, dislikes, or hates using Stardew Valley gift rules. Gift response messages are defined separately in the dialogue file.

# In your main NPC TOML file, for example Rei.toml

[GiftTastes]
# Use item names, qualified IDs, universal taste keys, or context tags
Love = [
  "Diamond",      # Specific item name
  "(O)395",       # Qualified item ID: Coffee
  "Starfruit"
  # "Universal_Love"
]

Like = [
  "Blueberry",
  "Coconut",
  "Salmon",
  "Cheese"
  # "Universal_Like"
]

Neutral = [
  "Stone",
  "Wood",
  "Wheat"
  # "Universal_Neutral"
]

Dislike = [
  "Clay",
  "Copper Ore",
  "Algae"
  # "Universal_Dislike"
]

Hate = [
  "Joja Cola",
  "Trash",
  "Broken Glasses"
  # "Universal_Hate"
]

# Deprecated - do not use here:
# LoveMessage = "Old format - no longer works!"
# LikeMessage = "Use AcceptGift_* in Dialogue.toml instead"
# In Dialogue.toml - gift response messages
# These keys follow Stardew Valley's standard format.

# Regular gift reactions
AcceptGift_Loved = "Oh wow! Is this for me? I love it! $h"
AcceptGift_Liked = "Thanks! This is nice. I appreciate it. $h"
AcceptGift_Neutral = "Thank you."
AcceptGift_Disliked = "Oh... um, thanks? $u"
AcceptGift_Hated = "Eww, why would you give me this? $a"

# Birthday gift reactions
AcceptBirthdayGift_Loved = "You remembered my birthday! This is amazing! $h"
AcceptBirthdayGift = "A birthday gift? Thank you! $h"

# Optional: specific item reactions
AcceptGift_(O)72 = "A diamond! How extravagant... $h"
AcceptGift_Coffee = "Coffee! Exactly what I needed. $h"
AcceptGift_(O)395 = "More coffee? You know me too well. $h"

# Optional: context tag reactions
AcceptGift_category_gem = "A gemstone! Very thoughtful. $h"
AcceptGift_category_cooking = "Homemade food? You shouldn't have! $h"
FormatMeaning
"Diamond"Item name, useful for unique items.
"(O)72"Qualified item ID, Object 72 is Diamond.
"(O)Starfruit"Qualified ID with internal name.
"(BC)17"Building or other item type.
"Universal_Love"All universally loved items.
"Universal_Like"All universally liked items.
"Universal_Neutral"All universally neutral items.
"Universal_Dislike"All universally disliked items.
"Universal_Hate"All universally hated items.
"category_fruit"All fruit items by context tag.
"category_gem"All gem items by context tag.
Response KeyPurpose
AcceptGift_LovedLoved gifts, +80 friendship.
AcceptGift_LikedLiked gifts, +45 friendship.
AcceptGift_NeutralNeutral gifts, +20 friendship.
AcceptGift_DislikedDisliked gifts, -20 friendship.
AcceptGift_HatedHated gifts, -40 friendship.
AcceptBirthdayGift_*Birthday-specific responses.
AcceptGift_(O)72Specific item responses.
AcceptGift_category_gemCategory responses.
Old format (deprecated):
[GiftTastes]
Love = ["Diamond", "Coffee"]
LoveMessage = "I love this! $h"
LikeMessage = "Thanks! $h"

New format:
[GiftTastes]
Love = ["Diamond", "Coffee"]
Like = ["Blueberry", "Coconut"]

# In Dialogue.toml:
AcceptGift_Loved = "I love this! $h"
AcceptGift_Liked = "Thanks! $h"
AcceptBirthdayGift = "A birthday gift! $h"
Gift priority

Stardew Valley checks gift response priority in this order: specific item, context tag, gift taste, then default.

How the systems connect

GiftTastes in the main NPC TOML controls what items the NPC likes or dislikes. AcceptGift_* keys in Dialogue.toml control what the NPC says. Stardew Valley handles friendship points, birthday bonuses, and response selection.

Asset Variants

NPC Helper switches sprites and portraits based on location, season, weather, festival, birthday, or configured asset paths. The older documentation emphasized the fallback order, which is included below.

1
Location variant

The NPC current location is checked first, such as Hospital or Beach.

2
Season variant

The current season is checked next: spring, summer, fall, or winter.

3
Weather and occasion variant

Weather keys such as rainy or snow, plus special keys such as festival or birthday, can point to dedicated assets.

4
Custom path

If no variant matches, custom sprite or portrait paths from TOML are used.

5
Default asset

If no custom path exists, sprite.png and portrait.png in the NPC folder are used.

# In your main NPC TOML file

[Sprites]
# Location-based variants
Hospital = "sprite_Hospital.png"
Beach = "sprite_Beach.png"
Saloon = "sprite_Saloon.png"

# Season-based variants
spring = "sprite_Spring.png"
summer = "sprite_Summer.png"
fall = "sprite_Fall.png"
winter = "sprite_Winter.png"

# Weather-based variants
rainy = "sprite_Rainy.png"
snow = "sprite_Snow.png"

# Special occasion variants
festival = "sprite_Festival.png"
birthday = "sprite_Birthday.png"

[Portraits]
# Same structure for portraits
Hospital = "portrait_Hospital.png"
summer = "portrait_Summer.png"
rainy = "portrait_Rainy.png"
festival = "portrait_Festival.png"
AssetRequirement
Sprites16x32 pixels per frame, standard Stardew NPC size.
Portraits64x64 pixels per expression.
FormatPNG recommended, with transparency support.
PathsRelative to the NPC folder, or absolute paths.
NamingFile names are case-sensitive on Linux and macOS.

Localization

NPC Helper loads localized TOML overlays based on the current game language. Create a locale folder inside the NPC folder with language-specific TOML files.

NPCs/
└── Rei/
    ├── Rei.toml                    # Default definition
    ├── sprite.png
    ├── portrait.png
    └── locale/                     # Localization folder
        ├── es-ES/                  # Spanish, Spain
        │   └── Rei.toml            # Spanish translation overlay
        ├── fr-FR/                  # French
        │   └── Rei.toml
        └── de/                     # Generic German
            └── Rei.toml
# locale/es-ES/Rei.toml - Spanish translation
# Only include properties that need translation.

DisplayName = "Rei"  # Spanish display name

[Dialogue]
Introduction = "Hola. Soy Rei, medico en practicas en la clinica."
Mon = "Los lunes no me asustan. Solo necesitan el cafe adecuado."
Default = "Si me necesitas, estoy en la clinica."

# Gift messages can also be localized.
AcceptGift_Loved = "Oh, vaya! Esto es para mi? Me encanta!"
AcceptGift_Liked = "Gracias! Esto esta bien."
AcceptGift_Disliked = "Oh... um, gracias?"
  • Locale detection uses SMAPI translation locale values, such as es-ES or fr-FR.
  • If es-ES does not exist, NPC Helper can fall back to es.
  • Localized TOML merges with the base definition as an overlay.
  • No code is required; create locale folders and matching TOML files.
  • Assets reload automatically when language-specific data changes.
  • Gift messages should use AcceptGift_* keys in localized dialogue data, not old LoveMessage or LikeMessage fields.

API Reference

Other mods can register NPC definitions programmatically with NPC Helper through its API interface.

using StardewModdingAPI;
using NpcHelper;

public class MyMod : Mod
{
    public override void Entry(IModHelper helper)
    {
        // Get the NPC Helper API
        var npcHelper = helper.ModRegistry.GetApi<INpcHelperApi>("TamKungZ.NpcHelper");

        if (npcHelper != null)
        {
            // Create NPC definition programmatically
            var customNpc = new NpcDefinition
            {
                DisplayName = "Programmatic NPC",
                Gender = "female",
                Age = "adult",
                DefaultMap = "Town",
                DefaultX = 35,
                DefaultY = 42,
                DefaultFacing = 2,
                Datable = true,
                Marriageable = false
            };

            // Add dialogue
            customNpc.Dialogue["Introduction"] = "Hello from code!";
            customNpc.Dialogue["Mon"] = "Monday dialogue from API.";

            // Add gift tastes
            customNpc.GiftTastes["Love"] = new List<string> { "Diamond", "Prismatic Shard" };
            customNpc.GiftTastes["Hate"] = new List<string> { "Joja Cola" };

            // Register the NPC
            npcHelper.RegisterNpc("CustomNPC", customNpc);
        }
    }
}
public interface INpcHelperApi
{
    /// <summary>
    /// Register a new NPC programmatically.
    /// </summary>
    /// <param name="name">Unique NPC name with no spaces.</param>
    /// <param name="data">NPC definition data.</param>
    void RegisterNpc(string name, NpcDefinition data);
}

public class NpcHelperApi : INpcHelperApi
{
    private readonly NpcManager _manager;
    public NpcHelperApi(NpcManager manager) => _manager = manager;

    // Implementation in ModEntry.cs
    public void RegisterNpc(string name, NpcDefinition data)
    {
        data.Name = name;
        _manager.Register(data);
    }
}
AreaDetails
Runtime requirementNPC Helper must be installed and loaded before the integration mod registers NPC data.
Reference requirementThe mod must reference the NpcHelper namespace and API types.
Content pack targetContent packs must set ContentPackFor.UniqueID to TamKungZ.NpcHelper.
Minimum APISMAPI MinimumApiVersion should be 4.0.0 or higher.
Asset loadingAssets must be loaded through SMAPI content APIs or content-pack relative paths.
LimitationsNPC Helper manages schedule execution and does not expose direct NPC instance control.

Troubleshooting

Start with the SMAPI log

Most setup problems are visible in SMAPI output. Search for [NpcHelper], the content pack UniqueID, and the NPC Name from the TOML file.

ProblemCheck
NPC not appearingCheck SMAPI logs for [NpcHelper] messages. If no messages appear, NPC Helper or the content pack is not loading.
Wrong content pack targetVerify manifest.json has ContentPackFor.UniqueID exactly set to TamKungZ.NpcHelper.
NPC definition not foundConfirm mod.toml paths such as NPCs = ["NPCs/Alex/Alex.toml"] are correct and point to files that exist.
NPC spawns nowhereConfirm DefaultMap exists in the game version and installed mods, and confirm DefaultX and DefaultY are valid, walkable tile coordinates.
NPC name conflictEnsure Name does not conflict with vanilla NPC names or other modded NPC names.
Dialogue not showingVerify Stardew dialogue keys such as Mon, Introduction, 4, Town_2000, or Default. Include [Dialogue] in separate dialogue files.
Old condition dialogue ignoredConvert old [friendship >= 4] or [season = summer] lines to Stardew keys. Bracket condition syntax is not supported.
Gift response not showingMove LoveMessage, LikeMessage, and related old fields out of [GiftTastes]. Use AcceptGift_Loved, AcceptGift_Liked, and birthday keys in Dialogue.toml.
Assets show red question markUse PNG files with transparency, verify sprite and portrait dimensions, check relative paths, match case-sensitive file names, and clear SMAPI cache if needed.
Content file not foundCheck asset paths in TOML and confirm files exist in the content pack folder.
Invalid TOML syntaxValidate the TOML file and check quotes, arrays, and table headers.
Duplicate NPC nameChange Name to a unique value that does not conflict with vanilla or modded NPCs.
Missing dependencyInstall NPC Helper and confirm SMAPI loads it before content packs.
Failed to load textureVerify the image exists, is PNG, and uses the expected dimensions.
Case-sensitive pathsOn Linux and macOS, sprite.png, Sprite.png, and SPRITE.PNG are different file names. Match TOML paths exactly.
Cache issueRestart the game after content changes. If assets still look stale, clear the SMAPI cache such as Mods/.cache.

Compatibility

FeatureStardew 1.5Stardew 1.6Notes
Basic NPC CreationLimitedFullStardew 1.6 has better character data support.
Advanced SchedulesBasicFullDay and season filters are optimized for Stardew 1.6.
Asset VariantsYesYesLocation and season-based sprites work in both.
Dynamic DialogueYesYesUses Stardew Valley dialogue keys.
Multiplayer SupportLimitedFullFull sync is intended for Stardew 1.6 multiplayer.
Gift Tastes SystemYesYesCustomizable gift preferences.
LocalizationYesYesAutomatic locale folder detection.
ModCompatibility
Content PatcherCan coexist but may have asset conflicts if both modify the same NPC data.
Json AssetsCompatible. Custom items can be used as gifts.
Custom NPC ModsMay conflict if modifying the same NPC records or names.

Frequently Asked Questions

QuestionAnswer
Can I use NPC Helper with existing Content Patcher NPCs?Yes, but they may conflict if they modify the same NPC data. Use one system per NPC when possible.
How do I make my NPC appear in a specific location?Set DefaultMap, DefaultX, and DefaultY in the NPC TOML. Use Schedule.toml for movement patterns.
Can NPCs have custom events or cutscenes?NPC Helper focuses on runtime NPC creation and management. Use SMAPI events or Content Patcher for complex events and cutscenes.
How do I update an existing NPC without breaking saves?You can update TOML and assets between launches, but changing Name creates a different NPC and can break existing friendship data.
What is the performance impact of many NPCs?Each NPC has minimal overhead off-screen. Large packs should simplify schedules and split very large NPC sets into separate packs.