A schedule tells the NPC where to be and when. It is a [Schedule] table in Schedule.toml (or in the NPC file). Each key says which days the routine is for, and its value is a list of stops.
[Schedule]
Weekday = [
"600 Hospital 1 18 1",
"a1200 Town 29 54 2",
"1800 Saloon 37 23 0 sit_down \"Good evening!\"",
"2200 bed",
]
summer_12 = ["900 Beach 20 20 2"]
Rain = "GOTO spring"
Step 1: Write a stop#
A stop is one quoted text. There are two ways to write it. Use either, or mix them in one file.
The game's own form:
TIME MAP X Y FACING
"600 Town 3 8 2" means: at 6:00, be in the Town at tile 3, 8, facing down.
The spelled-out form:
"6:00 Town x=3 y=8 face=down"
Both forms accept the same optional extras after the position: an animation and a message.
"1800 Saloon 37 23 0 sit_down \"Evening!\""
"by 12:00 Beach x=4 y=5 face=up sit_down \"Hi!\""
The parts of a stop#
| Part | What it means |
|---|---|
| Time | The game's 600 to 2600 in 10-minute steps, or a clock time: 6:00, 13:30, 1:30pm, 12:30am (half past midnight, the end of the day). 0 places the NPC at the stop when the day starts. A time such as 605 can never happen and is rejected. |
| Arrival | Put a in front of the time (a1200, a12:00) or the word by before it (by 12:00) to mean the NPC must have arrived by that time. The game starts the walk early enough. |
| Location | The game's name for a location. Leave it out (700 5 6 3) to stay where the NPC already is. bed sends the NPC to bed and needs no tile. |
| Tile | Two numbers (10 12), or x=10 y=12 in either order. |
| Facing | up, right, down, left, or 0 to 3 (0 up, 1 right, 2 down, 3 left), alone or as face=left. Optional, and defaults to down. |
| Animation | One animation name from the game's data (sit_down), or anim=sit_down. Optional. |
| Message | Text in double quotes, shown if the player is nearby when the NPC arrives. Optional. Do not put quotes inside it. |
Location names, animation names, and festival IDs come from the game and from other mods, so they are not listed here.
Rules for stops#
- Stops of one key are sorted by time.
- Two stops at the same time make the game reject the whole key, so NPC Helper 2 keeps the first and reports the second.
- A stop that cannot be read is skipped with a warning that names it.
Step 2: Choose the key#
The key decides when the routine runs.
| Key | Applies to |
|---|---|
Mon to Sun |
That day of the week. Full names (Monday) work too. |
Weekday |
Monday to Friday. |
Weekend |
Saturday and Sunday. |
"Mon,Wed" |
A comma-separated group of days. |
Rain, Rain2, GreenRain |
Rainy days. Rain2 is used on half of the rainy days when present. GreenRain is green rain. |
spring, summer, fall, winter |
That season. spring is also the fallback for any day with nothing better. |
fall_Mon |
One day of the week in one season. |
summer_12 |
A date. |
12 |
The 12th of every season. |
Mon_4, 12_6, fall_Mon_4 |
The same, but only from this many hearts. |
fall27, fall27_3 |
A festival ID, with an optional day suffix. |
| anything else | Used as the game key exactly as written (for example bus). |
Hearts run from 1 to 14. The game picks the highest level the player has reached.
Step 3: Understand which schedule the game uses#
The game tries these keys in order and uses the first one that exists. If none exists, the NPC has no schedule that day. NPC Helper 2 can write every one of them.
GreenRain(green rain, first year only).- A festival ID, with day suffix then without it, for each currently active festival.
<season>_<day>, for examplesummer_12.<day>_<hearts>, then<day>.Rain2(on half of rainy days, if present), thenRain.<season>_<weekday>_<hearts>, then<season>_<weekday>.<weekday>_<hearts>, then<weekday>.<season>.spring_<weekday>, thenspring: the fallback.
Practical effects:
- A date key such as
summer_12beats the ordinary weekday routine, so use it for a birthday or special day. Rainbeats the weekday key on rainy days.- Write a
springschedule as the general fallback, for days nothing else matches. - Heart-level keys for weekdays are only tested at every second level counting down from the player's hearts (6, 4, 2, and so on), so a weekday key for an odd or even level can be skipped. NPC Helper 2 warns about this. Prefer an ordinary weekday key unless you need heart-gated routines.
- Some game keys are only used by particular vanilla NPCs. For example the game tries
busfor one villager only, andmarriageJobonly for three. NPC Helper 2 warns if you use them on another NPC.
Step 4: Use whole-key commands#
A value that is a single text instead of a list is a command for the whole key.
[Schedule]
Rain = "GOTO spring"
| Value | Effect |
|---|---|
"GOTO spring" |
Use the spring schedule. Also "GOTO season", "GOTO NO_SCHEDULE", or "GOTO <key>". |
| any other text | Passed to the game exactly as written, for commands such as MAIL. |
A list can start with a friendship check:
spring = [
"NOT friendship Sam 6 Abigail 4",
"900 Town 10 12 2",
]
If any player has that many hearts with a listed NPC (here Sam at 6 or Abigail at 4), the spring schedule is used instead.
A worked example#
[Schedule]
# Monday to Friday
Weekday = [
"6:00 Hospital x=1 y=18 face=right",
"by 12:00 Town x=29 y=54 face=down",
"18:00 Saloon x=37 y=23 face=up sit_down \"Evening!\"",
"22:00 bed",
]
# Saturday and Sunday
Weekend = [
"9:00 Beach x=20 y=20 face=down",
"20:00 Hospital x=3 y=7 face=left",
]
# The birthday (summer 12) overrides everything else
summer_12 = ["10:00 Town x=5 y=5 face=down"]
# Rainy days: stay on the spring routine
Rain = "GOTO spring"
# Fallback for any day nothing else matches
spring = ["7:00 Hospital x=2 y=3 face=down"]
Step 5: Test#
- Start the game through SMAPI and read the summary. Schedule warnings name the key and the stop.
- Watch the NPC through a day. Use a day skip or a time-changing mod to reach the times you wrote.
- Check that every walk fits its time. An NPC that has too little time to reach the next stop will arrive late.
- If an NPC gets stuck or vanishes, the tile may be inside a wall or unreachable. Pick a tile the NPC can walk to.
The spouse schedule#
Once the player marries the NPC, a different set of keys is used. They go in a [Marriage] table in the same file. See Marriage.
Translating a schedule#
A translated [Schedule] with at least one valid entry replaces the base schedule rather than adding to it. Most translations should leave the schedule out. See Localization.