2.4.1#
- Translations are checked against their NPC when the game starts. NPC Helper 2 compares the NPC's own texts with every translation folder it finds, for every language that has files and not only the language the game is set to, one NPC at a time. It compares dialogue, engagement dialogue, spouse dialogue, heart events (by event name and number of lines) and festival lines (by festival ID). See Translation checks at startup.
- A translation that lacks lines the NPC has gets a warning that counts what is missing and what is extra.
INCOMPLETE TRANSLATIONmeans the missing lines stay in the original language.OUTDATED TRANSLATIONmeans the translation or the NPC mod is an old version; it appears when the translation's oldest file is more than 60 days older than the newest file of the NPC mod, or when many lines are missing (10 or more, or 5 or more that make up a quarter of the NPC's texts). It says how many days apart the files are and which one is behind. - Extra lines that only the translation has are a plain note in the log, not a warning, because a translator may add lines on purpose.
- The startup log lists the languages each NPC has translation files for, and where each comes from, for example
NPC 'Rei' has translations: es-ES (embed), th (Dr. Rei - Thai Translate).It does not say whether they are complete. - A language folder inside the NPC mod's own pack is an embedded translation. A separate content pack with the same language folder for the same NPC now replaces it instead of being merged line by line over it, and the startup log says so. Lines the separate pack does not translate show in the NPC's original language. Other languages keep their embedded translation.
- A language folder in the NPC mod's own pack that was copied in by hand from a separate download is marked
(legacy).mod.tomltakes a new optionalEmbedLocaleslist to say which languages the NPC mod ships itself; the other folders there are legacy. Without it, a folder that does not match the NPC and is older than the NPC's files is taken for legacy. A pack that setsEmbedLocalesshould require NPC Helper 2.4.1 or later. See Embedded or legacy. - Several translations of one language (a language folder and its regional folder, or folders from several mods) are judged together, as the game reads them, and the warning names the mods involved.
- An empty language folder in an NPC mod is no longer reported as translating nothing when another mod provides that language for the same NPC.
- Changing the game's language now logs the problems of the reload as one entry for that language, grouped by NPC in name order, instead of one line each. Nothing is logged when there is nothing to report.
- File dates used by the checks follow symbolic links, so mod managers that link files (such as Vortex) do not make every file look new.
2.4.0#
- Adds heart events. An NPC folder can have an
Events.tomlwith one table per event, written in plain words (Location,Hearts, optionalWeather,Time,DaysandAfter, where theFarmerand theNpcstand, andStepssuch asRei: Hello.,Rei walks down 2,Rei emotes heart). NPC Helper compiles it to the game's event script and key (event ID<Npc>_<EventName>, thef <Npc> <hearts x 250>condition, music, camera, actors,skippable,end) and adds it toData/Events/<Location>. An event with a problem is skipped with a message that names the step. A whole game script can still be given asScript. - Adds festival lines. A
Festivals.tomlwith one table per festival ID (spring13,summer11...) gives the NPC herDialogueandSpouseDialogueat that festival, added toData/Festivals/<id>the way the game's own NPCs have theirs. Placing the NPC on the festival map is not supported yet. See events. - A marriageable NPC whose sprite sheet has nothing drawn in the spouse-kiss frame (28) or the wedding frames (36-38), or whose sheet ends before them, now gets a warning that names the frame (the game shows an invisible NPC there). Generated placeholder sprite sheets are now 64x320 so they include the wedding frames.
- A heart event that gives both
ScriptandStepsnow says that onlyScriptis used. - Heart events and festival lines can be translated. A
locale/<code>/Events.tomlhas a[EventName]table withTexts, the translated lines in the order they are said (the scene stays the base pack's), and alocale/<code>/Festivals.tomlreplaces the festivalDialogueandSpouseDialogue. A wrong number of lines, an unknown event or an unknown festival is reported. Translation templates (TranslationPack.BuildTemplate),TranslationPackBuilder.FromNpcand the SDK'sLocaleBuilder.EventLines/Festivalinclude them, andTranslationPack.Validatecompares them with the base pack. - The pack-structure check ignores files a mod manager leaves in a pack (Vortex's
*.vortex_backup,__folder_managed_by_vortex,vortex.deployment.json, Mod Organizer'smeta.ini,desktop.ini,Thumbs.db,.DS_Store), so installing through Vortex no longer logs warnings, and a language folder holding only such files is not reported as empty. - The pack-structure check no longer reports ordinary folders such as
docsas a misspelledNPCsfolder.
2.3.0#
- The TOML parser now supports all of TOML 1.0: dotted keys and nested tables, inline tables, hex/octal/binary integers,
inf/nan, and date-time values, with a strict mode (TomlParseOptions.Strict). NPC files still load leniently. An unquoted key with a dot (a.b = 1) is now a dotted key; quote it to keep the dot. - Locale folders are now layered: a regional folder such as
locale/pt-BRonly needs the texts that differ fromlocale/pt, which in turn override the base text. Previously only the most specific folder was read, so a partialpt-BRfolder hid the rest ofpt. Switching betweenen,en-USand an empty locale no longer reloads every NPC. - Packs laid out by hand are checked for misspelled or misplaced folders and files (
NPCs,locale,sprites,portraits, language codes such asth_TH,Dialog.toml, non-.tomlfiles, top-level.tomlfiles, a misnamedmanifest.jsonormod.toml), for NPC files missing from theNPCslist, and for a pack that loads nothing. At startup NPC Helper also warns when a pack has translations for an NPC that is not loaded and suggests the NPC it probably meant. mod.tomltakes more optional settings:Exclude(skip drafts),LocalesandTranslates(declare a translation pack's languages and NPCs, so a translation whose NPC mod is missing is reported at startup), andStrictToml(read the pack as strict TOML 1.0). Every setting is optional, none repeatsmanifest.json(a copy there is reported and ignored), and unknown settings are now reported.- Translations in other mods are now found through SMAPI's list of content packs for NPC Helper instead of walking the whole Mods folder. Only
NPCs/<Npc>/locale/<code>inside those packs is checked. A translation mod that is not a content pack for NPC Helper, or sits in a folder without a manifest, is no longer detected; use the Manual install into the NPC's own mod folder or the Manager (content pack) archive. - A content pack that only holds translations no longer warns "No NPCs found"; it logs which NPCs it translates.
- The startup log is now one grouped entry (NPCs per pack, language, errors and warnings) without file-system paths.
- Fixes external locale packs not being found when the Mods folder is a symbolic link or junction.
2.2.1#
2.2.0#
- Adds combined location-and-season sprite and portrait variants, named
<Location>_<Season>.png(for example,Hospital_Summer.png), with selection priority: location + season, location, season, then the default image. - Supports 2× portrait source sheets with
PortraitScale = 2in the content pack's rootmod.toml; NPC Helper downsamples every selected portrait, including seasonal/location variants and marriage portraits, to the game's native 64×64 face tiles. - Bumps NPC Helper, the SDK and CLI packages to
2.2.0.
2.1.1#
- Avoids the no-NPC warning for translation-only content packs that declare
NPCs = []inmod.toml. - Packages a translation pack's
mod.tomlbeside its manifest when the manifest is placed in a separate folder.
2.1.0#
- Changes the runtime SMAPI
UniqueIDtoFramework.Mod.NpcHelper; content pack host references and SDK-generated manifests/API lookups use the new ID. The SDK and CLI package IDs remain unchanged. - Groups the NPC Helper startup summary and diagnostics into one SMAPI log entry.
- Fixes startup in Thai by supplying the English
Data/NPCGiftTastesasset using the game's explicit English language code when the Thai translation mod requests its missing localized asset; translation-mod edits still apply afterward. - Supplies custom NPC sprites and portraits for localized asset requests, avoiding fallback attempts to load nonexistent game
.xnbfiles. - Detects Thai from the localized asset suffix or locale code without treating the nested English fallback load as Thai.
- Finds separate NPC locale packs across supported renamed/wrapped mod-manager layouts, while stopping at each mod manifest and reading only
NPCs/<NpcName>/locale.
2.0.0#
Renamed: NPC Helper 2#
At the 2.0.0 release, the mod was renamed NPC Helper 2 (with a new logo in assets/branding/); only its display name changed then, while identifiers remained unchanged. The runtime ID was subsequently changed to Framework.Mod.NpcHelper.
A hardening and refactor release, plus an SDK and a cleaner file format. The NPC files are not compatible with 1.x: the format change is listed first, then the other breaking changes.
New file format (breaking)#
The NPC files were reorganised so they are shorter to write and easier to read. Nothing about what an NPC can do was removed except the path keys, which were not needed.
-
<Name>.tomlis grouped into tables. The flat keys moved:1.x key now Gender,Age,Manner,SocialAnxiety,Optimism[Personality]with the same namesBirthdaySeason,BirthdayDay[Birthday]Season,DayHomeRegion,DefaultMap,DefaultX,DefaultY,DefaultFacing[Home]Region,Map,X,Y,FacingDatable,Marriageable[Romance]with the same namesLanguage,SocialTab,Calendar,EndSlideShow,IsDarkSkinned,CanReceiveGifts,CanGreetNearbyCharacters,PerfectionScore,CanCommentOnPurchasedShopItems,IntroductionsQuest,FlowerDanceCanDance[Options]with the same namesName,DisplayName,[Dialogue],[GiftTastes]unchanged -
Schedules are lists of stops.
[[Schedule]]blocks (seven lines per stop) became one[Schedule]table: the key is the schedule key and each stop is one string in the game's own syntax,Weekday = ["600 Town 10 12 2", "2200 bed"].Days/Season/Day/Heartsmoved into the key (fall_Mon_4,summer_12),Arrivalis theaprefix,ActionandEndMessagefollow the facing,GotoandRaware plain string values andNotFriendshipis a first list item. The scheduler itself is unchanged; the same game strings come out. -
No path keys, and the images are in folders.
CustomSpritePath,CustomPortraitPath,DialoguePath,SchedulePath,[Sprites]and[Portraits]are gone. The files are found by name:Dialogue.toml,Schedule.toml,Marriage.toml, and all images insprites/andportraits/:Default.pngis the main sprite sheet / portrait (wassprite.png/portrait.png),portraits/Marriage.pngthe wedding portrait (wasportrait_marriage.png), any other name a variant by location or season. Asprite.png,portrait.pngorportrait_marriage.pngleft in the NPC folder is reported. -
A second, easier way to write a schedule stop. Besides the game's
"600 Town 10 12 2", a stop can be spelled out:"6:00 Town x=10 y=12 face=down", with clock times (6:00,1:30pm,12:30am),x=/y=,up/right/down/left(orface=),anim=, andby 12:00for "must have arrived by". Both forms can be mixed and give the same game schedule. -
One marriage file. The
marriage/folder (engagement.toml,spouse_dialogue.toml,spouse_schedule.toml) is nowMarriage.tomlnext to the NPC file, with[Engagement]and[Dialogue]tables; the spouse schedule is the[Marriage]table ofSchedule.toml(next to[Schedule], with the same stop syntax);portrait_marriage.pngsits in the NPC folder.locale/<lang>/Marriage.tomlworks the same way. The unsupportedwedding_event.toml,spouse_room.tomlandpatio.tomlare no longer even looked for. -
mod.tomlis no longer written by the SDK and the CLI (every NPC inNPCs/loads); it is still read when a pack has one. -
Every key of the old format is reported when the NPC loads, with where it lives now, so a half-converted file tells you what is left.
-
NpcDefinition.CustomSpritePath,CustomPortraitPath,DialoguePath,SchedulePath,SpriteVariantsandPortraitVariantsand the SDK'sSpriteVariant(...)/PortraitVariant(...)(the ones that took a path) were removed;SpriteVariantFileandPortraitVariantFileremain.
New: every fixed game option is available (checked against the real game)#
Values the game itself defines now offer the game's complete real set, with the game's own names (game-options). Friendlier spellings are aliases on top of the real values.
- New NPC options:
Language(Default/Dwarvish),SocialTab(all four values; it was fixed atAlwaysShown, which is still the default),Calendar,EndSlideShow,IsDarkSkinned,CanReceiveGifts,CanGreetNearbyCharacters,PerfectionScore,CanCommentOnPurchasedShopItems,IntroductionsQuest,FlowerDanceCanDance. All reach the game'sCharacterData. - Item categories: all 39 the game defines, by name (
category:Gem, orItemCategory.Gemin the SDK) or number. A negative number that is not a real category is reported. - Schedules now cover the game's whole vocabulary, read from the game's own parser:
<day>keys (every season), heart-gated keys,rain2,GreenRain, passive-festival keys,bed, location omitted, time0(start of day), arrival (a), end message, and theGOTO,NOT friendshipand raw/MAILcommands. Spouse keys include festivals. - The SDK enums mirror the catalog exactly (a test enforces it), and the schedule DSL has a scope for every key kind.
Changed behaviour from this (breaking)#
DaywithoutSeasonis the game's plain<day>key (every season). 1.x wrotespring_<day>.- Stop times must be
0or600-2600in 10-minute steps. A time such as605is rejected; the game matches times exactly against its 10-minute clock, so it could never fire. - Two stops at the same time: the later one is skipped with a warning (the game rejects the whole key, leaving the NPC with no schedule that day). Before, both were written.
Actionmust be a single animation name (the game splits on spaces); a numericMapis rejected (the game would read it as "location omitted").Mapis now optional on a stop, andX/Yare not needed forbed.marriageJobandbusare tied to specific vanilla NPCs; using them on a custom NPC is flagged.
New: SDK, CLI and a standard pack structure#
NpcHelper.StardewValley.Sdk(NuGet, no SMAPI/game dependency): define NPCs in C# withNpcBuilderand produce either a TOML content pack (NpcPackBuilder) or a DLL mod (api.Register(npc, folder)). Both run on the normal NPC Helper 2 runtime mod from Nexus.npchelperCLI (NpcHelper.StardewValley.Cli, dotnet tool):new pack,new npc,new dll-mod,validate,inspect,pack.- Schedule problems (invalid time, map, facing, unusable spouse keys) are now reported when the NPC loads (at launch, in
npchelper validate) instead of the first time the game asks for the schedule. - The runtime's API class is now
public, and the SDK'sINpcHelperApiis a strict subset of it using framework types only (checked by a test).
Breaking changes#
- Strict validation. An NPC with an invalid
Name,Gender,Age,Manner,SocialAnxiety,Optimism,BirthdaySeason,BirthdayDay,DefaultMaporDefaultFacingis rejected with a clear error. Before,Enum.Parsethrew inside theData/Charactersedit, which broke every NPC. - NPC names may only contain letters (any language), digits,
_and-. - Paths are sandboxed.
mod.tomlentries must be relative and stay inside the content pack. Absolute paths and..escapes are ignored with a warning. (The NPC files have no path keys any more.) - A stop needs a time and a tile (
X Y; not forbed). Stops missing them (previously silently sent to Town 10,10), or with invalid times/maps/facings, are skipped with a warning. HomeRegionmust be one of the game's three regions,Town,DesertorOther(NPC.region_*). Anything else becomesOtherwith a warning, because no game code would ever match it.Marriageable = trueimpliesDatable = true(1.6 has one flag,CanBeRomanced).- Spouse schedule is written under the game's
marriage_keys. In 1.x it replaced the NPC's whole schedule with plain keys that the game ignores for spouses. Seasonal weekday overrides (Days+Season) are expanded into the date keys the game reads, because it has nomarriage_<season>_<weekday>key; spouseRainand no-Daysentries are skipped with a warning. Details in the Marriage reference. - No longer injected (the game does not read them in 1.6):
Data/NPCDispositions,Data/SpouseRooms,Data/SpousePatios, and the per-NPCwedding_<Name>event inData/Events/Farm. The fileswedding_event.toml,spouse_room.tomlandpatio.tomlare no longer read. (The old wedding injection used a key without conditions and a shifted event script, so it could fire a malformed event on the farm.) - TOML escapes are now standard:
\n,\t,\uXXXXare interpreted (1.x only handled\"and\\). Locale files that define[Schedule]now replace the base schedule instead of appending to it. - API:
INpcHelperApigainedRegisterNpcFromToml,IsNpcRegistered,GetRegisteredNpcNames.RegisterNpcstill exists, but it now validates and deep-copies its argument. NpcDefinition.AbsoluteSpritePath/AbsolutePortraitPathwere replaced byResolved*Pathproperties.
Bug fixes#
-
Own
NPCs/folder: marriage files (spouse_dialogue.toml,Engagement.toml…) were registered as NPCs. -
mod.tomlwith several entries on one line (NPCs = ["a", "b"]) was read as a single bad path; multi-line arrays were dropped. -
Multi-line arrays and multi-line (
""") strings in NPC files were silently dropped; table headers with a trailing# commentattached their keys to the wrong table; quoted keys kept their quotes. -
Manner,SocialAnxietyandOptimismwere never written toData/Characters. -
Gift tastes: item names (
"Joja Cola") are now resolved to IDs (previously they were passed through and split on the space);Universal_*placeholders in empty lists were removed; a/in a gift message no longer corrupts the entry. -
Characters/Dialogue/MarriageDialogue<Name>usedEditon an asset that does not exist for custom NPCs; it is now loaded. -
Engagement dialogue keys that belong to other NPCs (e.g.
Abigail0in Rei's file) are no longer injected. -
Images are loaded through each pack's SMAPI
ModContenthelper (correct decoding and alpha premultiplication for SMAPI 4.4) instead of rawTexture2D.FromStream, which gave dark fringes on soft edges. -
Sprites/portraits were reloaded every time an NPC changed location and dialogue/schedule caches were flushed with them. Now only the affected image is reloaded, and only when the chosen file actually changes.
-
NPCs are spawned with the game's own
Game1.AddCharacterIfNecessaryinstead of a hand-builtNPC(the game already spawnsSpawnIfMissingNPCs on load and every morning). Farmhands no longer try to spawn/warp NPCs in multiplayer. -
OnAssetRequestedno longer builds ~10 strings per NPC per asset; an exception in one NPC no longer affects the others. -
Locale overlay files are read in a stable order.
-
Spouses were warped out of the farmhouse on every load. The 1.x "early morning" warp moved any NPC that was not at its
DefaultMapwhenevertimeOfDay < 630, and a loaded save always starts at 6:00. The warp was redundant (the game already places NPCs) and has been removed; the schedule bootstrap now only runs for an NPC NPC Helper 2 itself just added. -
A deeply nested array (
[[[[…) overflowed the stack and killed the game. Nesting is limited to 16 levels and TOML files to 4 MB. -
An unexpected exception while loading one NPC is now logged for that NPC instead of aborting
Entry(which makes SMAPI disable the whole mod). -
Gift tastes accept item context tags (
egg_item,category_fruit) without a misleading warning; the game matches them against the gifted item. -
After a language change, live NPCs drop their cached schedule data.
-
Data/Characters,Data/NPCGiftTastesandData/EngagementDialogueare edited atEarlypriority so Content Patcher patches apply to NPC Helper 2's NPCs. -
A
marriage/folder on an NPC that is notMarriageablenow logs a warning instead of being silently ignored.
Known limitations (verified against the 1.6.15 game code)#
Portraits/<Name>_Marriageis shown only while the NPC speaks their wedding vows; the game never selects it anywhere else by itself.MarriageDialogue<Name>Roommate, spouse rooms and patios are not provided (see the Marriage reference).- Gift reaction text comes from
AcceptGift_*keys in the NPC's dialogue, not from the gift-taste string.
[HP] ReiMod#
- Version
2.0.0, requires NPC Helper 22.0.0. - Gift taste
Algae→Green Algae(the real item name).
1.2.0#
NpcHelper#
- Bumped mod version to
1.2.0. - Added automatic deployment for
[HP] ReiModduring build whenEnableModDeploy=true. - Improved marriage systems:
- Correct engagement data target (
Data/EngagementDialogue). - Added spouse schedule asset injection and runtime cache invalidation.
- Added case-insensitive marriage file resolution.
- Added locale-aware marriage file loading (
locale/<lang>/marriage). - Reloads marriage data on locale change.
- Correct engagement data target (
- Improved schedule key generation for seasonal day patterns.
[HP] ReiMod#
- Bumped content pack version to
1.2.0. - Updated required
NpcHelperminimum version to1.2.0. - Cleaned and standardized marriage data files:
marriage/engagement.tomlmarriage/spouse_dialogue.tomlmarriage/spouse_schedule.tomlmarriage/wedding_event.toml
- Added file-by-file locale coverage for marriage content:
locale/th/marriage/*locale/es-ES/marriage/*
- Normalized dialogue key parity in locale files to match base dialogue keys.