Stardew Valley Reference
NPC Helper
Runtime custom NPC importer for Stardew Valley content packs.
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
NPC Helper requires Stardew Valley 1.6 or higher and SMAPI 4.0 or higher.
Download and install SMAPI from smapi.io.
Download the latest version from Nexus Mods.
Extract the NPC Helper folder to Stardew Valley/Mods/.
Start Stardew Valley through SMAPI and check the console for [NpcHelper] Loaded.
Quick Start Guide
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"Start Stardew Valley with SMAPI.
Look for [NpcHelper] Registered NPC definition: Alex in the SMAPI console.
Look for the NPC at the configured map and tile coordinates.
Talk to the NPC to verify portrait, sprite, and dialogue assets load.
Configuration Files
| File | Required | Purpose |
|---|---|---|
| manifest.json | Yes | SMAPI content pack metadata. Must reference TamKungZ.NpcHelper. |
| mod.toml | Yes | Entry file that lists NPC definition files relative to the content pack root. |
| NPCs/<Name>/<Name>.toml | Yes | Main NPC definition: identity, location, relationship flags, assets, dialogue path, schedule path, variants, and gifts. |
| Dialogue.toml | Optional | Separate Stardew Valley dialogue keys and gift response messages. |
| Schedule.toml | Optional | Daily movement routes with day, season, and date filters. |
| sprite.png | Required unless CustomSpritePath points elsewhere | Default sprite sheet. Each frame follows the standard Stardew NPC sprite size. |
| portrait.png | Required unless CustomPortraitPath points elsewhere | Default portrait sheet. Each expression follows the standard Stardew portrait size. |
| locale/<language-code>/*.toml | Optional | Localized 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"]| Property | Allowed Values | Description |
|---|---|---|
| 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. |
| BirthdayDay | 1-28 | Day of the season for the NPC birthday. |
| HomeRegion | Game region name | Region used by game logic and map grouping. |
| DefaultMap | Valid map name | Map where the NPC starts if no schedule overrides it. |
| DefaultX, DefaultY | Tile coordinates | Starting tile coordinates on DefaultMap. |
| DefaultFacing | 0, 1, 2, 3 | 0: Up, 1: Right, 2: Down, 3: Left. |
| Datable | true, false | Whether the NPC can receive bouquet dating state. |
| Marriageable | true, false | Whether the NPC can be married. |
| DialoguePath | Relative TOML path | External dialogue file relative to the NPC folder. |
| SchedulePath | Relative TOML path | External schedule file relative to the NPC folder. |
Dialogue System
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 Command | Purpose |
|---|---|
| Introduction | First meeting dialogue. |
| Mon, Tue, Wed, Thu, Fri, Sat, Sun | Day-of-week dialogue. |
| 2, 4, 6, 8, 10 | Heart-level dialogue keys. Stardew Valley uses numeric friendship suffixes. |
| spring_1, winter_24 | Season and day keys using season_day. |
| Hospital, Town | Location-specific dialogue. |
| Hospital_Tue | Location plus day combination. |
| Town_2000 | Location plus time combination. |
| EggFestival | Festival-specific dialogue. |
| Default | Fallback dialogue. |
| breakUp | Dialogue after breaking up. |
| divorced | Dialogue after divorce. |
| RejectBouquet | Dialogue when rejecting a bouquet. |
| DumpsterDiveComment | Dialogue when the player digs in trash nearby. |
| AcceptGift_Loved, AcceptGift_Liked | Gift reaction keys. |
| $h, $s, $u | Portrait emotes. |
| $q, $r | Question dialogue and response options. |
| || | Weekly rotation separator. |
| @ | Player name replacement. |
| ${male^female} | Gender-specific text. |
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!"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 intent | Use this Stardew-style key |
|---|---|
| Friendship at 2 hearts | 2 |
| Friendship at 4 hearts on Monday | Mon4 |
| Dialogue at Town | Town |
| Dialogue at Town after 8:00 PM | Town_2000 |
| Spring day 1 dialogue | spring_1 |
| Winter Star dialogue | winter_24 or the relevant festival key. |
| Multiple possible greetings | Greeting = "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."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.
Search dialogue files for bracketed conditions such as [friendship >= 4], [time >= 1800], or [season = summer].
Use heart-level keys, day keys, location keys, time keys, seasonal keys, festival keys, or Default whenever they match the intended behavior.
Use AcceptGift_* and AcceptBirthdayGift_* keys in Dialogue.toml instead of old message fields under [GiftTastes].
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_LikedSchedule 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| Field | Required | Meaning |
|---|---|---|
| Time | Yes | Game time as an integer, such as 600, 1200, or 1800. |
| Map | Yes | Target map name. It must exist in the current game and installed mods. |
| X, Y | Yes | Target tile coordinates on the map. |
| Facing | Recommended | Facing direction after arriving: 0 up, 1 right, 2 down, 3 left. |
| Action | Optional | Human-readable action text or description for the schedule stop. |
| Days | Optional | Weekday, Weekend, or comma-separated day names. |
| Season | Optional | Restricts the entry to spring, summer, fall, or winter. |
| Day | Optional | Restricts the entry to a day of the season, usually 1-28. |
| Filter | Meaning |
|---|---|
| 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 = 12 | Only on day 12 of the month. |
| Season = "winter", Day = 24 | Only on Winter 24. |
| No Days or date filters | Applies every matching day. |
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
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"| Format | Meaning |
|---|---|
| "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 Key | Purpose |
|---|---|
| AcceptGift_Loved | Loved gifts, +80 friendship. |
| AcceptGift_Liked | Liked gifts, +45 friendship. |
| AcceptGift_Neutral | Neutral gifts, +20 friendship. |
| AcceptGift_Disliked | Disliked gifts, -20 friendship. |
| AcceptGift_Hated | Hated gifts, -40 friendship. |
| AcceptBirthdayGift_* | Birthday-specific responses. |
| AcceptGift_(O)72 | Specific item responses. |
| AcceptGift_category_gem | Category 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"Stardew Valley checks gift response priority in this order: specific item, context tag, gift taste, then default.
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.
The NPC current location is checked first, such as Hospital or Beach.
The current season is checked next: spring, summer, fall, or winter.
Weather keys such as rainy or snow, plus special keys such as festival or birthday, can point to dedicated assets.
If no variant matches, custom sprite or portrait paths from TOML are used.
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"| Asset | Requirement |
|---|---|
| Sprites | 16x32 pixels per frame, standard Stardew NPC size. |
| Portraits | 64x64 pixels per expression. |
| Format | PNG recommended, with transparency support. |
| Paths | Relative to the NPC folder, or absolute paths. |
| Naming | File 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 oldLoveMessageorLikeMessagefields.
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);
}
}| Area | Details |
|---|---|
| Runtime requirement | NPC Helper must be installed and loaded before the integration mod registers NPC data. |
| Reference requirement | The mod must reference the NpcHelper namespace and API types. |
| Content pack target | Content packs must set ContentPackFor.UniqueID to TamKungZ.NpcHelper. |
| Minimum API | SMAPI MinimumApiVersion should be 4.0.0 or higher. |
| Asset loading | Assets must be loaded through SMAPI content APIs or content-pack relative paths. |
| Limitations | NPC Helper manages schedule execution and does not expose direct NPC instance control. |
Troubleshooting
Most setup problems are visible in SMAPI output. Search for [NpcHelper], the content pack UniqueID, and the NPC Name from the TOML file.
| Problem | Check |
|---|---|
| NPC not appearing | Check SMAPI logs for [NpcHelper] messages. If no messages appear, NPC Helper or the content pack is not loading. |
| Wrong content pack target | Verify manifest.json has ContentPackFor.UniqueID exactly set to TamKungZ.NpcHelper. |
| NPC definition not found | Confirm mod.toml paths such as NPCs = ["NPCs/Alex/Alex.toml"] are correct and point to files that exist. |
| NPC spawns nowhere | Confirm DefaultMap exists in the game version and installed mods, and confirm DefaultX and DefaultY are valid, walkable tile coordinates. |
| NPC name conflict | Ensure Name does not conflict with vanilla NPC names or other modded NPC names. |
| Dialogue not showing | Verify Stardew dialogue keys such as Mon, Introduction, 4, Town_2000, or Default. Include [Dialogue] in separate dialogue files. |
| Old condition dialogue ignored | Convert old [friendship >= 4] or [season = summer] lines to Stardew keys. Bracket condition syntax is not supported. |
| Gift response not showing | Move LoveMessage, LikeMessage, and related old fields out of [GiftTastes]. Use AcceptGift_Loved, AcceptGift_Liked, and birthday keys in Dialogue.toml. |
| Assets show red question mark | Use 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 found | Check asset paths in TOML and confirm files exist in the content pack folder. |
| Invalid TOML syntax | Validate the TOML file and check quotes, arrays, and table headers. |
| Duplicate NPC name | Change Name to a unique value that does not conflict with vanilla or modded NPCs. |
| Missing dependency | Install NPC Helper and confirm SMAPI loads it before content packs. |
| Failed to load texture | Verify the image exists, is PNG, and uses the expected dimensions. |
| Case-sensitive paths | On Linux and macOS, sprite.png, Sprite.png, and SPRITE.PNG are different file names. Match TOML paths exactly. |
| Cache issue | Restart the game after content changes. If assets still look stale, clear the SMAPI cache such as Mods/.cache. |
Compatibility
| Feature | Stardew 1.5 | Stardew 1.6 | Notes |
|---|---|---|---|
| Basic NPC Creation | Limited | Full | Stardew 1.6 has better character data support. |
| Advanced Schedules | Basic | Full | Day and season filters are optimized for Stardew 1.6. |
| Asset Variants | Yes | Yes | Location and season-based sprites work in both. |
| Dynamic Dialogue | Yes | Yes | Uses Stardew Valley dialogue keys. |
| Multiplayer Support | Limited | Full | Full sync is intended for Stardew 1.6 multiplayer. |
| Gift Tastes System | Yes | Yes | Customizable gift preferences. |
| Localization | Yes | Yes | Automatic locale folder detection. |
| Mod | Compatibility |
|---|---|
| Content Patcher | Can coexist but may have asset conflicts if both modify the same NPC data. |
| Json Assets | Compatible. Custom items can be used as gifts. |
| Custom NPC Mods | May conflict if modifying the same NPC records or names. |
Frequently Asked Questions
| Question | Answer |
|---|---|
| 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. |