Routines
This page uses Vector3 from Unity. The glossary says what each one is.
A routine is a weekly timetable for one mod NPC. You build it with NpcRoutine, then store it with ModNpcRoutines.Set. A routine lasts for the game session only. It is not written to the player’s save, so you set it again each time the game starts.
ModNpcRoutines stores, removes and reads routines
Call Set with your mod’s id, the NPC’s id and an NpcRoutine to store a timetable, and Remove or Clear to take it away. Current tells you which step the NPC is in.
public static partial class ModNpcRoutines
{
public static event Action<NpcStepArgs> StepChanged;
public static bool Set(string modId, string npcId, int sourceCharacterId, string name, string lastName, NpcRoutine routine, bool keepSourceDialogue = false);
public static bool Remove(string modId, string npcId);
public static bool Clear(string modId);
public static NpcStepKind Current(string modId, string npcId);
}
| Method | Returns | What it does |
|---|---|---|
Set(modId, npcId, sourceCharacterId, name, lastName, routine, keepSourceDialogue) | bool | Stores a timetable for an NPC. |
Remove(modId, npcId) | bool | Removes one timetable, and its NPC. |
Clear(modId) | bool | Removes all of your mod’s timetables. |
Current(modId, npcId) | NpcStepKind | The step the clock says the NPC is in now. |
| Event | Gives you | When it fires |
|---|---|---|
StepChanged | NpcStepArgs | An NPC’s timetable has moved to a different step. |
NpcStepArgs what you are told when the NPC changes step
StepChanged gives you one of these when an NPC moves to another step. From and To are the old and new steps, and ModId and NpcId say which NPC.
public sealed class NpcStepArgs
{
public string ModId { get; }
public string NpcId { get; }
public NpcStepKind From { get; }
public NpcStepKind To { get; }
public string Scene { get; }
public int CharacterId { get; }
}
| Property | Type | What it means |
|---|---|---|
ModId | string | Your mod’s id. |
NpcId | string | The id you gave the NPC. |
From | NpcStepKind | The step it was in. |
To | NpcStepKind | The step it is in now. |
Scene | string | The scene the new step is in. |
CharacterId | int | The NPC’s character number. 0 when it is not in the loaded scene. |
NpcRoutine a weekly timetable, built one step at a time
You build one with new NpcRoutine(), then add steps with Stand, Wander, Patrol, Sit or Sleep. Hand it to ModNpcRoutines.Set to store it.
public sealed class NpcRoutine
{
public NpcRoutine();
public int Count { get; }
public NpcRoutine Stand(NpcDays days, TimeSpan from, TimeSpan to, string scene, Vector3 point, float yaw);
public NpcRoutine Wander(NpcDays days, TimeSpan from, TimeSpan to, string scene, Vector3 center, float radius);
public NpcRoutine Patrol(NpcDays days, TimeSpan from, TimeSpan to, string scene, IList<Vector3> points);
public NpcRoutine Sit(NpcDays days, TimeSpan from, TimeSpan to, string scene, Vector3 seat);
public NpcRoutine Sleep(NpcDays days, TimeSpan from, TimeSpan to, string scene, Vector3 bed);
public NpcRoutine Door(string scene, Vector3 point);
}
| Method | Returns | What it does |
|---|---|---|
NpcRoutine() | NpcRoutine | Makes an empty timetable. |
Stand(days, from, to, scene, point, yaw) | NpcRoutine | Adds a step where the NPC stands at a point, facing yaw. |
Wander(days, from, to, scene, center, radius) | NpcRoutine | Adds a step where the NPC wanders around a spot. |
Patrol(days, from, to, scene, points) | NpcRoutine | Adds a step where the NPC patrols along points. |
Sit(days, from, to, scene, seat) | NpcRoutine | Adds a step where the NPC sits on the chair near this point. |
Sleep(days, from, to, scene, bed) | NpcRoutine | Adds a step where the NPC sleeps in the bed near this point. |
Door(scene, point) | NpcRoutine | Sets where the NPC walks in and out of this scene. |
| Property | Type | What it means |
|---|---|---|
Count | int | How many steps it has. |
NpcStepKind what the NPC is doing in a step
Current and NpcStepArgs.From and To give you one of these.
public enum NpcStepKind
{
Away,
Stand,
Wander,
Patrol,
Sit,
Sleep
}
| Value | Meaning |
|---|---|
Away | The NPC is in no scene. |
Stand | Standing at a point. |
Wander | Wandering around a spot. |
Patrol | Walking between points. |
Sit | Sitting on a chair. |
Sleep | Sleeping in a bed. |
NpcDays the days a step covers
Pass one of these to each step method. It is a flags value, so NpcDays.Monday | NpcDays.Friday is a valid set.
[Flags]
public enum NpcDays
{
None = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64,
Weekdays = 31,
Weekend = 96,
Every = 127
}
| Value | Meaning |
|---|---|
None | No days. Not allowed in a step. |
Monday | Monday. |
Tuesday | Tuesday. |
Wednesday | Wednesday. |
Thursday | Thursday. |
Friday | Friday. |
Saturday | Saturday. |
Sunday | Sunday. |
Weekdays | Monday to Friday. |
Weekend | Saturday and Sunday. |
Every | Every day of the week. |
Building a routine
- Each step method adds one step and gives the routine back, so you can chain calls. A step covers the time from
fromup totoon each day indays. Seconds are dropped, so a step works in whole minutes. daysis a set of days, and the week starts on Monday, like the game’s own calendar.NpcDays.Noneis not allowed.frommust be 00:00 to 23:59, andtomust be 00:01 to 24:00. They must not be the same. Iftois earlier thanfrom, the step goes past midnight. The part after midnight belongs to the start day: a Sunday 23:00 to 02:00 step is active on Sunday night only. Its part after midnight covers Monday 00:00 to 02:00.- When steps overlap, the step you added first wins. This is how the game’s own timetable works.
- A minute that no step covers is
Away. The NPC is in no scene at that time. - Wrong values throw an
ArgumentException. The scene name must not be empty. Points, centres, seats, beds, doors andyawmust be real numbers.radiusmust be 0.5 to 50. A patrol needs 2 to 32 points. A routine holds at most 64 steps. Door(scene, point)says where an NPC walks in and out of a scene. There is one door point for each scene, and callingDooragain for the same scene replaces the first. A door is not a level change: the NPC walks to the door and disappears, and then appears in the other scene when that scene’s step says so.
Setting and removing
- A routine spawns its NPC the same way
ModNpcs.Spawndoes. If the source character has no body of its own with the current rig, the NPC gets the default body. See Mod NPCs. Setstores a copy of the routine for your mod and the NPC id. Changing yourNpcRoutineafterwards does not change the stored copy. CallingSetagain with the same id replaces the routine. You can call it at any time, even on the main menu. The NPC appears once a save is loaded and its scene is active.Setthrows anArgumentExceptionfor wrong values. That means an invalidmodId, annpcIdthat is empty or longer than 64 characters, an emptyname, anullroutine, or a routine with no steps.Setreturnsfalsewhen it did not store the routine. That happens when mod NPCs are off (IsAvailableisfalse), when your mod already has 64 routines, when an NPC that no routine started already uses the id, and when a saved mod NPC (fromModNpcs.SpawnSaved) uses the id, even if that NPC is not in the loaded scene. So never use the same id forSpawnSavedand for a routine.Removeforgets the routine and removes its NPC if a routine spawned it.Cleardoes the same for every routine of your mod. Both returnfalsewhen there was nothing to remove.Currenttells you the step the game clock puts the NPC in, whether or not the NPC is in the loaded scene. It givesAwayfor an id it does not know.StepChangedfires once when the step in effect changes. Loading a scene alone does not fire it. The first check afterSetalways fires, soFromandTocan both beAway.
What the framework does each minute
The framework checks each routine once for every in-game minute, after a scene loads, and after Set. This is what it does for the scene that is loaded:
- If the step in effect is this scene and the NPC is not in this scene, the NPC appears at the step’s point. If the step changed while the player was already in this scene, and the scene has a door point, the NPC appears at the door and walks in.
- If the step in effect is this scene and the NPC is in this scene, the step’s order starts, unless a one-off order or the routine’s own order is already running. A new step ends the routine’s previous order first.
- If the step in effect is another scene or
Awayand the NPC is in this scene, and a routine spawned it, the NPC waits while someone is talking to it. If this scene has a door point, it walks there and is then removed. Otherwise it is removed at once. -
If the step in effect is another scene or
Awayand the NPC is not in this scene, nothing happens. - A routine step walks by the same rules as the orders above. A one-off order (
WalkTo,Wander,Patrol,SitorSleep) pauses the routine until the order ends. A step change does not end it, and the NPC does not leave its scene while it runs.Stopends any order, including the routine’s own. The routine then starts its step again at the next check, one in-game minute later. - A routine walk that runs out of time moves the NPC to the step’s point. This keeps the routine on time.
- A
SitorSleepstep with no chair or bed in range stands the NPC at the step’s point instead. One line goes to the log. - A routine NPC that dies stays dead until its scene loads again. It then appears alive at the step’s point. Call
Removeto stop it for good. - A routine NPC cannot go through a locked door, the same as for orders.
- Nothing is saved for a routine. After a reload the NPC is placed where the clock says it should be. A new game works the same way once its first level has loaded.
- If the NPC has not started its first order within 300 frames of appearing, the framework tries again each in-game minute.