NPC Helper 2/Docs

Create an NPC

Heart Events & Festivals

Write heart events in plain words with Events.toml and add festival lines with Festivals.toml.

Two optional files in an NPC's folder, both found by name. A pack that uses them must require NPC Helper 2.4.0 or later in manifest.json (ContentPackFor.MinimumVersion).

Step by step: add a heart event#

  1. Create Events.toml in the NPC's folder, next to the NPC file.
  2. Add one table named after your event, for example [RainyClinic]. The name must be unique in the file.
  3. Say when it plays: Location and Hearts are required. Add Weather, Time, Days, or After to narrow it.
  4. Say where everyone stands: Farmer and Npc are required, as "x y facing".
  5. Write the Steps, one entry per line: speech, walking, emotes, and so on (see the step table below).
  6. Start the game through SMAPI and check the log. An event with a problem is skipped and the message names the step.
  7. To see it, give the NPC enough hearts, then enter the Location under the conditions you set.

Events.toml: heart events#

A heart event is a cutscene that plays once the player has enough hearts with the NPC. You describe the scene in plain words and NPC Helper turns it into the game's event script, so you never write the game's /-separated format, event IDs or friendship numbers. Each event is one table named after the event:

toml
[RainyClinic]
Location = "Hospital"
Hearts = 4
Weather = "rainy"
Time = "900-1500"
Farmer = "10 18 up"
Npc = "8 12 down"
Steps = [
  "wait 500",
  "Rei: You came in out of the rain. Sit down, I'll find you a towel.$h",
  "Rei walks down 2",
  "farmer faces left",
  "Rei emotes heart",
  "Rei: ...Don't tell the senior doctor I said that.$9",
]

That is the whole event. NPC Helper adds the music (none), the camera (on the NPC), the actors, skippable and the final end, and registers it in the game's Data/Events/Hospital with the right conditions.

When it plays#

Key Meaning
Location Where it plays: Town, Hospital, FarmHouse, Beach ... Required.
Hearts 1 to 14. Required.
Weather sunny, rainy ... Optional.
Time A range, 900-1500. Optional.
Days ["Mon", "Tue"]. Optional.
After The name of another event in this file that the player must have seen first. Optional.
Conditions Anything else, in the game's own condition format (["f Harvey 500"]). Optional.

The scene#

Key Meaning
Farmer Where the player starts: "x y facing", facing is up, right, down or left. Required.
Npc Where the NPC starts. Required.
Others More characters, ["Harvey 7 10 left"]. Optional.
Music A track name. Default: none.
Camera "x y". Default: on the NPC.
Steps What happens, one step per entry. Required (or Script).

Steps#

Step What it does
Rei: text The character says it. The player does not speak in events; use message. Portrait codes ($h, $9) work as in dialogue.
wait 500 Pauses (milliseconds).
Rei walks down 2 Walks that many tiles in up, right, down or left.
Rei faces up / farmer faces left Turns.
Rei emotes heart An emote: question, angry, exclamation, heart, sleep, sad, happy, x, pause, videogame, music or blush.
Rei jumps A small jump.
music name / sound name Plays a track or a sound.
fade / unfade Fades the screen out and back in.
message text A message box.
raw command A command in the game's event format, for anything above does not cover.
end Ends the event. Added for you when left out.

Every name in a step must be in the scene: farmer, the NPC, or someone in Others. A step that is not understood, an unknown emote, a bad direction or a / in the text makes NPC Helper skip that event and say which step it was; the other events and the NPC still load. NPC Helper also notes when the NPC never speaks in her event.

The game's event ID is <Npc>_<EventName> (for example Rei_RainyClinic), so it cannot clash with another mod's. If the game or another mod already has that ID, yours is left out and a warning says so.

If you already have a game script#

Script takes the whole script the game's own way, one command per entry (music, viewport, actors, then the commands, with end last). It replaces Music, Camera, the actors and Steps; the conditions above still apply. See the Stardew Valley wiki page "Modding:Event data" for every command.

Festivals.toml: festival lines#

What the NPC says at a festival. Each table is named after the festival's ID:

toml
[spring13]
Dialogue = "I never find an egg. I only eat them."
SpouseDialogue = "Hold my basket, dear. I'm going to try this egg hunt thing."

[winter25]
Dialogue = "The punch is not from the clinic's cabinet. I checked."

The festival IDs of the game are spring13 (Egg Festival), spring24 (Flower Dance), summer11 (Luau), summer28 (Moonlight Jellies), fall16 (Stardew Valley Fair), fall27 (Spirit's Eve), winter8 (Festival of Ice) and winter25 (Feast of the Winter Star). Dialogue is shown when the player talks to the NPC at the festival and SpouseDialogue when she is the player's spouse; either can be left out. They are added to the festival's data under the NPC's name and <Name>_spouse, like the game's own NPCs. A festival ID that is not one of these is accepted with a note, for a festival another mod adds.

Translating events and festivals#

A translation pack can carry locale/<code>/Events.toml (a Texts list per event, in the order the lines are said) and locale/<code>/Festivals.toml (same tables as the base file). See Localization.

What is not supported yet#

NPC Helper adds the lines of a festival, but it does not yet place the NPC on the festival map. The game places festival actors with tile markers in the festival map's Set-Up and MainEvent layers, so an NPC without a marker talks only when she happens to be in her normal schedule. Placing NPCs there, and festival events that the NPC takes part in, are planned.

From C##

csharp
new NpcBuilder("Rei")
    .HeartEvent("RainyClinic", "Hospital", 4, e => e
        .Weather("rainy").Between(900, 1500)
        .Farmer(10, 18, Facing.Up).Npc(8, 12, Facing.Down)
        .Wait(500)
        .Say("You came in out of the rain.$h")
        .Walk("Rei", Facing.Down, 2)
        .Emote("Rei", "heart"))
    .FestivalDialogue("spring13", "I only eat them.", spouseDialogue: "Hold my basket, dear.");

The SDK writes Events.toml and Festivals.toml and reports a bad heart level, an incomplete scene or a bad festival ID when the NPC is validated.