Skyrim Platform
Last updated
Was this helpful?
Last updated
Was this helpful?
Skyrim Platform is a modding tool for Skyrim allowing writing scripts with JavaScript/TypeScript. One of the mods built on Skyrim Platform is skymp client. Yes, client of Skyrim Multiplayer is technically a mod for Skyrim Special Edition implemented using Skyrim Platform.
All types in SkyrimPlatform have the same name as in Papyrus, for example: Game
,Actor
, Form
,Spell
, Perk
, etc.
To use types from Papyrus, including calling methods and static functions that they have, they need to be imported:
Most types have a list of native functions, they are divided into static functions (Native Global
in Papyrus) and methods (Native
).
Static functions are called on the type:
Methods are called on the object:
A list of original game types with documentation can be found here:
Calling functions from the original game is only available inside the update
event handler (see below). If you try to do this in a different context, an exception will be thrown.
Form (Form
) is inherited by most game types, which have methods such asActor
, Weapon
, etc.
Each form has an ID, which is a 32-bit unsigned number (uint32_t
). In SkyrimPlatform, represented by the type number
.
If you need to find a form by its ID, use Game.getFormEx
. Note that it is Game.getFormEx
, notGame.getForm
. The latter always returns null
for IDs above 0x80000000 (the behavior of the original game).
You can get the form ID using the getFormID
method. It is guaranteed that Game.getFormEx
will find the form by the ID returned by this method if the form was not destroyed by the game.
After you get the object, you need to make sure that it is not null
:
Or
It is guaranteed that Game.getPlayer
never returnsnull
.
Unhandled JS exceptions will be logged to the console along with the call stack.
Raw Promise rejections are also output to the console.
Do not release plugins that have known bugs that are not handled. SkyrimPlatform performance is not guaranteed with unhandled exceptions.
To compare objects in SkyrimPlatform, you need to compare their IDs:
Types ported from Papyrus have limited support for a number of operations normal for regular JS objects such as toString
,toJSON
.
If you have a Form
object that is a weapon, and you need aWeapon
object, you can use casting:
If you specify an ID for a form that is not actually a weapon, the weapon
variable will benull
.
Passing null
to the function for casting types as an argument will not throw an exception, but will returnnull
:
An attempt to cast to a type that has no instances or is incompatible in the inheritance hierarchy will also return null
:
You can also use typecasting to get an object of the base type, including Form
:
Casting an object to its own type will return the original object:
SkyrimPlatform currently only adds one type: TESModPlatform
. Instances of this type do not exist by analogy with Game
. Its static functions are listed below.
moveRefrToPosition
- teleports the object to the specified location and position.
setWeaponDrawnMode
- forces the actor to always keep the weapon drawn / removed.
getNthVtableElement
- gets the offset of the function from the virtual table (for reverse engineering).
getSkinColor
- gets the skin color of the ActorBase.
createNpc
- creates a new form of type ActorBase.
setNpcSex
- changes the gender of the ActorBase.
setNpcRace
- changes the race of the ActorBase.
setNpcSkinColor
- changes the skin color of the ActorBase.
setNpcHairColor
- changes the hair color of the ActorBase.
resizeHeadpartsArray
- resizes the array of head parts ActorBase.
resizeTintsArray
- resizes the main character's TintMasks array.
setFormIdUnsafe
- changes the form ID. Unsafe, use at your own risk.
clearTintMasks
- remove TintMasks for the given Actor or the Player Character if the Actor is not passed.
pushTintMask
- add TintMask with def. parameters for the given Actor or the Player Character, if Actor is not passed.
pushWornState
,addItemEx
- add / remove items from def. ExtraData.
updateEquipment
- update equipment (unstable).
resetContainer
- clear the base container.
Some game functions take time and happen in the background. Such functions in SkyrimPlatform return Promise
:
When called asynchronously, execution continues immediately:
You can use async
/await
to make the code look synchronous:
At the moment, SkyrimPlatform has the ability to subscribe to your own events: update
andtick
.
update
is an event that is called once for every frame in the game (60 times per second at 60 FPS) after you've loaded a save or started a new game.
tick
is an event that is called once for every frame in the game immediately after the game starts.
And also for game events such as effectStart
,effectFinish
, magicEffectApply
,equip
, unequip
,hit
, containerChanged
,deathStart
, deathEnd
,loadGame
, combatState
, reset
,scriptInit
, trackedStats
,uniqueIdChange
, switchRaceComplete
,cellFullyLoaded
, grabRelease
,lockChanged
, moveAttachDetach
,objectLoaded
, waitStop
,activate
...
With on
, you can subscribe to the event forever.
Using once
, you can add a handler that will be called once the next time the event is fired.
The variable even
always contains variables related to the event to which you are subscribed.
Hooks allow you to intercept the start and end of some functions of the game engine.
Currently supported hooks: sendAnimationEvent
enter
is called before starting the function. ctx
contains the arguments passed to the function and alsostorage
(see below).
leave
is called before the function ends. ctx
contains the return value of the function, in addition to what was after the completion ofenter
.
ctx
is the same object for calls toenter
and leave
.
ctx.storage
is used to store data between calls toenter
and leave
.
Script functions are not available inside the enter
andleave
handlers.
There are methods such as printConsole ()
that can be called immediately after import. They do not belong to any of the game types.
printConsole (... arguments: any []): void
- output to the game console, opened by the ~
key.
worldPointToScreenPoint
- convert an array of points in the game world to an array of points on the user's screen. The dot on the screen is indicated by 3 numbers from -1 to 1.
on (eventName: string, callback: any): void
- subscribe to an event namedeventName
.
callNative (className: string, functionName: string, self ?: object, ... args: any): any
- call a function from the original game by name.
getJsMemoryUsage (): number
- get the amount of RAM used by the embedded JS engine, in bytes.
storage
- an object used to save data between reloading scripts.
browser
is an object providing access to the Chromium Embedded Framework.
getExtraContainerChanges
- get ExtraContainerChanges of the given ObjectReference...
getContainer
- get all the items of the base container.
settings
- an object that provides access to plugin settings:
The plugin settings file is named plugin-settings.txt
and should be located in theData / Platform / Plugins
folder. File format - JSON, extension .txt
- for the convenience of users.
SkyrimPlatform allows you to change the implementation of any game console command, for such a modification you need to get the console command object by passing the command name to the findConsoleCommand (commandName)
method, short or long.
Having received such an object, you can change the short (shortName
) or long (longName
) command name, as well as the number of accepted arguments (numArgs
) and the function (execute
) that will be executed when this console command is called via game console.
The return value of your new implementation indicates whether the original function of this command will be executed.
The first argument is the FormId of the object on which the console command is called, or 0 if it is absent.
The rest of the parameters will be the arguments with which the console command was called, of type string
ornumber
.
Since game functions are not available in this context, you must register an update
event handler withonce
if you want to call a game function when you invoke a console command:
SkyrimPlatform provides limited support for HTTP requests. At the moment only get
is available.
In case the request fails, response.body
will be empty.
Hot Reload for SkyrimPlatform plugins is supported. Changing the contents of Data / Platform / Plugins
will reload all plugins without restarting the game.
When reloading plugins, the added event and hook handlers are removed, asynchronous operations are interrupted and all variables are reset, except for storage
and its properties.
SkyrimPlatform has built-in functionality that allows you to output information about game functions to the file Data / Platform / Output / DumpFunctions.txt
(key combination 9 + O + L). The game pauses for a few seconds while DumpFunctions is running.
For full use, these are features, i.e. reload your plugin with Ctrl + S, take the example plugin as a basis