Features Beyond the Bindings
SkyrimForge has two layers. The bindings, generated from CommonLibSSE-NG's headers, expose the game's own types in the
SkyrimForge.Game namespace. Each type is a view: a struct that stores the address of an object in the game's memory, with members
that call the game's code or read its fields. The framework's own features are built on the bindings, and most of them are services
a plugin declares in its constructor. This page summarizes those features. Services lists every service,
and the API reference documents each member.
Plugins and Services
- A plugin class implements IPlugin, and its one public constructor declares the services it uses.
- Each plugin has a log and saved state of its own, stored under its identity: the full name of its class, or the name PluginIdentityAttribute states.
- A plugin that cannot be loaded does not prevent the others from loading. A message box at the main menu names it and the reason.
- IPluginCollection gives one plugin access to another's public members, and IPluginServiceSource lets a library add services of its own.
Threads
The game calls plugins on its own thread and on worker threads, and the documentation of each event in IGameEvents
states where it is raised. A handler on a worker thread that changes the game first awaits WaitForGameThreadAsync, an extension of
IUtility declared in UtilityExtensions, or queues the work through ITaskQueue.
A task that a framework member returns completes where the game can be called, so the code after awaiting it can call the game directly.
IUtility also provides waits and cooldowns measured in time that does not advance while a menu pauses the game.
Events
Each event's Subscribe returns an ISubscription, whose Unsubscribe removes the handler.
- IGameEvents: about a hundred events, from each frame and the SKSE messages (data loaded, save loaded, new game) to menus, input, combat, and quests.
- IStoryEvents: the story manager's events, such as crafting, an arrest, or a killing.
- IAnimationEvents: the annotations on an actor's animations.
- IPlayerLocationEvents and ITriggerZoneFactory: the player entering a location, and the player entering and leaving zones around references.
- IModEvents and IPapyrusEvents: events between plugins and Papyrus scripts.
Forms and Saved State
- FormId<TForm> is a form ID typed by its view, so an ID of a weapon cannot be passed where an actor's is expected. KnownForms names forms from Skyrim.esm by editor ID.
- IPerPluginSavedState stores a plugin's state in the SKSE co-save beside the player's save. A form ID stored there is mapped through the load order the save recorded, so it still names the same form after the load order changes.
- ICalendarTimerFactory creates timers on the game's calendar that are saved with the game.
Papyrus
- The game's Papyrus script functions can be called from C#. A function on a form is a member of the form's
Papyrusproperty, such asplayer.Papyrus.AddItem(...). A global function is a static method of the script's class, such asGameScript.AdvanceSkill(...)in the SkyrimForge.Papyrus namespace. Each returns a task that completes when the script function returns. - A class marked PapyrusScriptAttribute implements a script's native functions in C#, and the build writes the
script's
.psc. Papyrus Native Functions covers it. - IPapyrusFunctionRegistrar registers native functions directly, for the cases the attribute does not cover.
Game Content without an .esp File
These services create content at runtime that would otherwise be records in an .esp file:
- IRuntimeQuestFactory: quests that the journal lists.
- IDialogueBranchFactory: dialogue branches built from DialogueTopic trees.
- IUnvoicedSpeech: dialogue lines without voice recordings, shown as subtitles with a timed mouth animation.
- IForceGreet, IFollowers, and IGreetingSilencer: an actor approaching the player to talk, followers, and silencing an actor's greetings and remarks.
- IWorldMapMarkers, IReadableNotes, and ICourier: map markers the player can fast travel to, notes with runtime text, and items delivered by the courier.
User Interface
- IMessageBoxPrompter: a question with buttons, reporting which button was pressed.
- IBookMenuPresenter: runtime text in the book menu.
- ICustomMenuRegistrar and IScaleformFunctionRegistrar: menus of the plugin's own, and ActionScript calling into the plugin.
- IConsoleCommandRegistrar: console commands that run C# handlers.
- IDebug: notifications and the game's other debug functions.
Native Code
- IFunctionHooks: hooks a game function at a virtual method table entry, a call instruction, or the function's entry.
- ICodePatcher: changes the game's machine code where it matches the bytes each patch expects.
- ISksePluginMessenger: messages to and from native SKSE plugins.
Compiler Warnings
One build runs on Skyrim Special Edition, Anniversary Edition, and Skyrim VR, and CurrentGameEdition reports which one is running. The compiler warns where a call needs attention:
- SKYRIMFORGE0001: a bound member that does not work as declared, on some editions or, through a fault in CommonLibSSE-NG, on all of them. The warning states the fault and the alternative, if there is one. A warning that names editions applies only to those editions.
- SKYRIMFORGE0002: a Papyrus function that has an equivalent member on the view, which calls the game without the Papyrus virtual machine. The warning names that member.
- SKYRIMFORGE0003: a Papyrus function that its own script marks deprecated.
- SFPS001 to SFPS003: a declaration that Papyrus cannot represent, in a class marked PapyrusScriptAttribute. Papyrus Native Functions lists them.