### Example: Replacing Main Menu Start Game Action
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Demonstrates how to register a wrapper type, instantiate it, set a command handler, and replace an existing DataContext.
```APIDOC
## Example: Main Menu Start Game Action
### Description
This example illustrates a practical use case: replacing the main menu's start game action by registering a wrapper ViewModel, instantiating it, assigning a custom handler to its command, and updating the widget's DataContext.
### Method
N/A (Illustrative Script)
### Endpoint
N/A (Client-side Script)
### Code Example
```lua
-- Register a wrapper type for the main menu DataContext
Ext.UI.RegisterType("SAMPLE_MainMenuCtx", {
StartGameCommand = {Type = "Command"} -- builtin command to start game
}, "gui::DCMainMenu") -- gui::DCMainMenu is the name of the ingame main menu DataContext
-- Jank sample code for getting a widget, DON'T DO IT LIKE THIS!
local mainMenu = Ext.UI.GetRoot():Find("ContentRoot"):VisualChild(1)
-- Create a wrapper around the original main menu DataContext
local ctx = Ext.UI.Instantiate("se::SAMPLE_MainMenuCtx", mainMenu.DataContext)
ctx.StartGameCommand:SetHandler(function ()
print("do stuff")
end)
-- Overwrite datacontext with our wrapper
mainMenu.DataContext = ctx
```
```
--------------------------------
### Complete TileSet Configuration Example
Source: https://github.com/norbyte/bg3se/blob/main/Docs/VirtualTextures.md
A full example of a tile set configuration XML including paths, textures, layers, and build settings.
```xml
Public\YOUR_MOD_NAME\Assets\Textures
Public\YOUR_MOD_NAME\Assets\VirtualTextures
Best
false
true
true
```
--------------------------------
### Get and Modify Skill Data
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
This example demonstrates how to retrieve all skill data entries, iterate through them, and modify a specific attribute (`DamageType`). It uses `Ext.Stats.GetStats` to get a list of stat names and `Ext.Stats.Get` to access individual stat objects.
```lua
-- Swap DamageType from Poison to Air on all skills
for i,name in pairs(Ext.Stats.GetStats("SkillData")) do
local stat = Ext.Stats.Get(name)
if stat.DamageType == "Poison" then
stat.DamageType = "Air"
end
end
```
--------------------------------
### Create NetChannel
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Example of creating a new NetChannel with a unique module identifier and channel name. This should be done in shared files.
```lua
-- Shared: create channels for both server and client
Channels = {}
Channels.TemplateAddTo = Ext.Net.CreateChannel(ModuleUUID, "TemplateAddTo")
return Channels
```
--------------------------------
### Client-side Send Message to Server
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Example of a client sending a message to the server using `SendToServer`. This is a fire-and-forget operation.
```lua
-- Client side: send message to server
Channels.TemplateAddTo:SendToServer({
Items = { {"item-template-guid-1", 1}, {"item-template-guid-2", 2} },
Target = someEntityId
})
```
--------------------------------
### Create Mod Directory Symlinks
Source: https://github.com/norbyte/bg3se/blob/main/Docs/Debugger.md
Commands to link your VS Code project mod folder to the game's installation directory for testing.
```shell
mklink /D "\Data\Mods\" "\Mods\"
```
```shell
ln -s /Mods// /Data/Mods/
```
--------------------------------
### Accessing Static Game Resources
Source: https://context7.com/norbyte/bg3se/llms.txt
Use these methods to retrieve resource GUIDs or full resource objects from the game's static data tables.
```lua
-- Get all resources of a type
local raceGuids = Ext.StaticData.GetAll("Race")
local classGuids = Ext.StaticData.GetAll("ClassDescription")
local backgroundGuids = Ext.StaticData.GetAll("Background")
-- Get specific resource
local race = Ext.StaticData.Get("race-uuid", "Race")
print(race.Name)
-- Get resources by mod
local modRaces = Ext.StaticData.GetByModId("Race", ModuleUUID)
```
--------------------------------
### Check Mod Load Status
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Verify if a specific module is loaded using its GUID.
```lua
if (Ext.Mod.IsModLoaded("5cc23efe-f451-c414-117d-b68fbc53d32d"))
_P("Mod loaded")
end
```
--------------------------------
### Get mod load order and details
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves the load order of all mods and detailed information for a specific mod using its UUID. Includes name, author, version, and directory.
```lua
local loadOrder = Ext.Mod.GetLoadOrder()
for i, uuid in ipairs(loadOrder) do
local mod = Ext.Mod.GetMod(uuid)
print(i .. ": " .. mod.Info.Name .. " (" .. uuid .. ")")
end
local mod = Ext.Mod.GetMod("your-mod-uuid")
print("Name: " .. mod.Info.Name)
print("Author: " .. mod.Info.Author)
print("Version: " .. mod.Info.ModVersion)
print("Directory: " .. mod.Info.Directory)
```
--------------------------------
### Server-side Handler for Template Addition
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Example of a server-side handler that processes incoming messages to add items. It uses `SetHandler` and does not expect a reply.
```lua
-- Server side: handle requests
-- Using SetHandler: note there's no reply callback
Channels.TemplateAddTo:SetHandler(function(data, user)
for _, v in pairs(data.Items) do
local template, amount = table.unpack(v)
_P("Adding " .. template .. " to " .. data.Target .. " with amount " .. amount)
Osi.TemplateAddTo(template, data.Target, amount or 1)
end
end)
```
--------------------------------
### Read Osiris Databases
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Retrieve rows from databases using the Get method with optional column filters.
```lua
-- Fetch all rows from DB_GiveTemplateFromNpcToPlayerDialogEvent
local rows = Osi.DB_GiveTemplateFromNpcToPlayerDialogEvent:Get(nil, nil, nil)
-- Fetch rows where the first column is CON_Drink_Cup_A_Tea_080d0e93-12e0-481f-9a71-f0e84ac4d5a9
local rows = Osi.DB_GiveTemplateFromNpcToPlayerDialogEvent:Get("CON_Drink_Cup_A_Tea_080d0e93-12e0-481f-9a71-f0e84ac4d5a9", nil, nil)
```
--------------------------------
### Get current game state
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves the current state of the game, such as whether it's in the main menu, in-game, or loading.
```lua
local state = Ext.Utils.GetGameState()
print("Game State: " .. tostring(state))
```
--------------------------------
### Get game version
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves the version string of the running Baldur's Gate 3 game. Essential for ensuring mod compatibility with the game version.
```lua
local gameVersion = Ext.Utils.GameVersion()
print("Game Version: " .. gameVersion)
```
--------------------------------
### Get and Update Localized Strings
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use Ext.Loca.GetTranslatedString to retrieve localized text and Ext.Loca.UpdateTranslatedString to override it at runtime. Ensure you have the correct localization handle.
```lua
local text = Ext.Loca.GetTranslatedString("h1234567890abcdef1234567890abcdefg")
Ext.Loca.UpdateTranslatedString("h1234567890abcdef1234567890abcdefg", text .. " (modified)")
```
--------------------------------
### Multiline Console Input
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Enter multiline code into the console by starting input with '--[[' and closing with ']]--'. This is useful for longer scripts or loops.
```lua
--[[
someTable={1,2,3,4,5}
for key,value in pairs(someTable) do
print(value)
end
]]--
```
--------------------------------
### Get All Components Attached to an Entity
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Fetches all components known to the Script Extender that are attached to a given entity. Note that components with unknown structures are omitted.
```lua
local entity = Ext.Entity.Get(GetHostCharacter())
_D(entity:GetAllComponents())
-- Prints:
-- {
-- "ActionResources" :
-- {
-- "Entity" : "Entity (02c0000100000180)",
-- "GetReplicationFlags" : "function: 00007FFDE482D5E0",
-- ...
-- }
-- }
```
--------------------------------
### Get Script Extender version
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves the version string of the installed Script Extender. Useful for compatibility checks.
```lua
local version = Ext.Utils.Version()
print("SE Version: " .. version)
```
--------------------------------
### Ext.Entity.OnCreate
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Subscription for component creation events.
```lua
OnCreate(componentName, callback, [entity], [opt1], [opt2])
```
--------------------------------
### Ext.Entity.OnCreateOnce
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
One-shot create subscription that auto-unsubscribes after the first match.
```lua
OnCreateOnce(componentName, callback, [entity])
```
--------------------------------
### Define Bootstrap Scripts
Source: https://context7.com/norbyte/bg3se/llms.txt
Entry points for server-side and client-side Lua logic. Use Ext.Require to load additional modular scripts.
```lua
-- Mods/YourMod/ScriptExtender/Lua/BootstrapServer.lua
Ext.Require("Server/Main.lua")
Ext.Require("Server/Combat.lua")
-- Mods/YourMod/ScriptExtender/Lua/BootstrapClient.lua
Ext.Require("Client/UI.lua")
Ext.Require("Client/Effects.lua")
```
--------------------------------
### Utilities - Ext.Utils
Source: https://context7.com/norbyte/bg3se/llms.txt
General utility functions for version checking, game state management, and handle conversions.
```APIDOC
## Ext.Utils
### Description
General purpose helper functions for debugging and system information.
### Methods
- **Ext.Utils.Version()**: Returns the Script Extender version.
- **Ext.Utils.GameVersion()**: Returns the game version.
- **Ext.Utils.GetGameState()**: Returns the current game state.
- **Ext.Utils.Print/PrintWarning/PrintError**: Logging utilities.
- **Ext.Utils.HandleToInteger/IntegerToHandle**: Handle conversion utilities.
```
--------------------------------
### Ext.Entity.OnCreateDeferredOnce
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Deferred and one-shot variant of OnCreate.
```lua
OnCreateDeferredOnce(componentName, callback, [entity])
```
--------------------------------
### Verify Debugger Server Startup
Source: https://github.com/norbyte/bg3se/blob/main/Docs/Debugger.md
Expected output in the extender console log when the debugger server initializes successfully.
```text
Starting Lua debugger server
Debugger::Debugger(): Starting Lua debugger
Lua debugger listening on 127.0.0.1:9998; DBG protocol version 3
```
--------------------------------
### I/O - Ext.IO
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Provides server and client filesystem helper functions for loading, saving, and redirecting file access.
```APIDOC
## I/O - `Ext.IO`
Server and client filesystem helpers.
### Methods
- `Ext.IO.LoadFile(path, [context]): string?`
Reads file contents. Returns `nil` if the file cannot be read.
- `Ext.IO.SaveFile(path, content): boolean`
Writes content to a file. Creates missing parent directories.
- `Ext.IO.AddPathOverride(originalPath, newPath)`
Redirects game file access from `originalPath` to `newPath`.
- `Ext.IO.GetPathOverride(path): string?`
Returns active override target for `path`, if any.
`AddPathOverride` should be called as early as possible (typically `ModuleLoadStarted`), before the original resource is loaded.
Example:
```lua
Ext.IO.AddPathOverride("Public/Game/GUI/enemyHealthBar.swf", "Public/YourMod/GUI/enemyHealthBar.swf")
```
```
--------------------------------
### Configure Launch Task Integration
Source: https://github.com/norbyte/bg3se/blob/main/Docs/Debugger.md
Fields to add to your launch.json configuration to link the game process lifecycle with the debugger.
```json
...
"configurations": [
{
"preLaunchTask": "bg3Continue",
"postDebugTask": "bg3Kill",
"internalConsoleOptions": "openOnSessionStart",
...
```
--------------------------------
### Subscribe to SessionLoaded Event
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Fires after a game session has been successfully set up.
```lua
Ext.Events.SessionLoaded:Subscribe(function()
-- Code to run after a session is loaded
end)
```
--------------------------------
### Get All Component Names for an Entity
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Retrieves a list of all component type names attached to an entity. Useful for inspecting an entity's capabilities.
```lua
local char = Ext.Entity.Get(GetHostCharacter())
_D(char:GetAllComponentNames())
-- Prints:
-- {
-- "eoc::ActionResourcesComponent" : "eoc::ActionResourcesComponent Object (1c4000010000039e)",
-- "eoc::BackgroundComponent" : "eoc::BackgroundComponent Object (1e000001000003ff)",
-- "eoc::BackgroundPassivesComponent" : "eoc::BackgroundPassivesComponent Object (66c00001000003ff)",
-- ...
-- }
```
--------------------------------
### File I/O - Ext.IO
Source: https://context7.com/norbyte/bg3se/llms.txt
Enables reading and writing files within the Script Extender directory and managing game file path overrides.
```APIDOC
## Ext.IO
### Description
Provides file system access for reading/writing configuration files and overriding game asset paths.
### Methods
- **Ext.IO.SaveFile(path, content)**: Saves a string to a file in the Script Extender directory.
- **Ext.IO.LoadFile(path)**: Loads the content of a file from the Script Extender directory.
- **Ext.IO.AddPathOverride(originalPath, overridePath)**: Redirects game file requests to a custom path.
- **Ext.IO.GetPathOverride(path)**: Retrieves the current override path for a given file.
```
--------------------------------
### Subscribe to ModuleLoadStarted Event
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use this to add filesystem-level hooks before mod data is loaded. Most mod editing functionality is unavailable at this stage.
```lua
Ext.Events.ModuleLoadStarted:Subscribe(function()
-- Code to run when module loading starts
end)
```
--------------------------------
### Get a Specific Component from an Entity
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Retrieves a specific component by its name from an entity. Returns nil if the component is not found or its structure is unknown to the Script Extender.
```lua
local entity = Ext.Entity.Get(GetHostCharacter())
_D(entity:GetComponent("DisplayName"))
-- Prints:
-- {
-- "Entity" : "Entity (02c0000100000180)",
-- "Name" : "Tav",
-- "NameKey" : "ResStr_669727657",
-- ...
-- }
```
--------------------------------
### Load Scripts with Ext.Require
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use Ext.Require to load additional Lua files during module startup. Paths are relative to the mod's Lua folder.
```lua
Ext.Require("Server/SkillMechanics.lua")
```
--------------------------------
### Ext.Entity.OnSystemPostUpdate
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Subscribes to ECS system post-update hooks.
```lua
OnSystemPostUpdate(systemType, callback, [once])
```
--------------------------------
### Get translated string by handle
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves a translated string from the game's localization data using its unique handle. Fallback text can be provided.
```lua
local text = Ext.Loca.GetTranslatedString("h1234567890abcdef1234567890abcdefg")
print(text)
local textWithFallback = Ext.Loca.GetTranslatedString("h123...", "Default Text")
```
--------------------------------
### Configure Event Subscription
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use an options table to set priority or execution frequency for event handlers.
```lua
Ext.Events.GameStateChanged:Subscribe(handler, {
Priority = 50,
Once = true
})
```
--------------------------------
### Console Commands - Ext.RegisterConsoleCommand
Source: https://context7.com/norbyte/bg3se/llms.txt
Allows registration of custom console commands that can be triggered via the game console.
```APIDOC
## Ext.RegisterConsoleCommand
### Description
Registers a custom command handler that can be invoked using the '!' prefix in the console.
### Parameters
- **commandName** (string) - Required - The name of the command.
- **callback** (function) - Required - The function to execute when the command is called.
```
--------------------------------
### Iterate and Modify Spell Autocast
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Loop through all spells and disable autocast if it's currently enabled. This example demonstrates reading and writing stat properties in a loop.
```lua
for i,name in pairs(Ext.Stats.GetStats("SpellData")) do
local spell = Ext.Stats.Get(name)
if spell.Autocast == "Yes" then
spell.Autocast = "No"
end
end
```
--------------------------------
### Replace Main Menu DataContext
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Demonstrates wrapping an existing DataContext to intercept and handle UI commands.
```lua
-- Register a wrapper type for the main menu DataContext
Ext.UI.RegisterType("SAMPLE_MainMenuCtx", {
StartGameCommand = {Type = "Command"} -- builtin command to start game
}, "gui::DCMainMenu") -- gui::DCMainMenu is the name of the ingame main menu DataContext
-- Jank sample code for getting a widget, DON'T DO IT LIKE THIS!
local mainMenu = Ext.UI.GetRoot():Find("ContentRoot"):VisualChild(1)
-- Create a wrapper around the original main menu DataContext
local ctx = Ext.UI.Instantiate("se::SAMPLE_MainMenuCtx", mainMenu.DataContext)
ctx.StartGameCommand:SetHandler(function ()
print("do stuff")
end)
-- Overwrite datacontext with our wrapper
mainMenu.DataContext = ctx
```
--------------------------------
### Handle Networking with Ext.Net
Source: https://context7.com/norbyte/bg3se/llms.txt
Facilitate communication between client and server using channels for messages, requests, and broadcasts.
```lua
-- Create channels (do in shared code loaded by both client and server)
local Channels = {}
Channels.MyAction = Ext.Net.CreateChannel(ModuleUUID, "MyAction")
Channels.SyncData = Ext.Net.CreateChannel(ModuleUUID, "SyncData")
-- Server: Handle incoming messages
Channels.MyAction:SetHandler(function(data, user)
print("Received from client: " .. data.action)
Osi.TemplateAddTo(data.template, data.target, data.amount)
end)
-- Client: Send message to server
Channels.MyAction:SendToServer({
action = "addItem",
template = "item-template-guid",
target = characterUuid,
amount = 5
})
-- Server: Handle request with reply
Channels.SyncData:SetRequestHandler(function(data, user)
local entity = Ext.Entity.Get(data.target)
return {
health = entity.Health.Hp,
maxHealth = entity.Health.MaxHp
}
end)
-- Client: Request with callback
Channels.SyncData:RequestToServer({ target = characterUuid }, function(response)
print("Health: " .. response.health .. "/" .. response.maxHealth)
end)
-- Server: Broadcast to all clients
Channels.SyncData:Broadcast({ globalState = "updated" })
-- Server: Send to specific client
Channels.SyncData:SendToClient({ message = "hello" }, clientUserId)
-- Check if host
if Ext.Net.IsHost() then
print("This client is the host")
end
```
--------------------------------
### Get game object template by ID
Source: https://context7.com/norbyte/bg3se/llms.txt
Retrieves a specific game object template (e.g., character, item definition) using its unique identifier. Also provides access to root templates and all root templates.
```lua
local template = Ext.Template.GetTemplate("template-uuid")
local rootTemplate = Ext.Template.GetRootTemplate("template-uuid")
local allTemplates = Ext.Template.GetAllRootTemplates()
for id, template in pairs(allTemplates) do
print(id, template.Name)
end
-- Server-only: local and cache templates
local localTemplate = Ext.Template.GetLocalTemplate("template-uuid")
local cacheTemplate = Ext.Template.GetCacheTemplate("template-uuid")
```
--------------------------------
### Measure Execution Time with Ext.Timer
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use monotonic time to profile code execution duration in milliseconds.
```lua
local startTime = Ext.Timer.MonotonicTime()
DoLongTask()
local endTime = Ext.Timer.MonotonicTime()
_P("Took: " .. tostring(endTime - startTime) .. " ms")
```
--------------------------------
### Static Data - Ext.StaticData
Source: https://context7.com/norbyte/bg3se/llms.txt
Access static game resources such as races, classes, and backgrounds.
```APIDOC
## Static Data - Ext.StaticData
### Description
Access static game resources like races, classes, and backgrounds.
### Method
Various (Lua functions)
### Endpoint
N/A (Lua API)
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
```lua
-- Get all resources of a type
local raceGuids = Ext.StaticData.GetAll("Race")
local classGuids = Ext.StaticData.GetAll("ClassDescription")
local backgroundGuids = Ext.StaticData.GetAll("Background")
-- Get specific resource
local race = Ext.StaticData.Get("race-uuid", "Race")
print(race.Name)
-- Get resources by mod
local modRaces = Ext.StaticData.GetByModId("Race", ModuleUUID)
```
### Response
#### Success Response (200)
Returns Lua tables containing static data.
#### Response Example
```json
{
"example": "race.Name (string)"
}
```
```
--------------------------------
### Instantiating a ViewModel
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Constructs a new instance of a registered ViewModel type. Can optionally wrap an existing DataContext.
```APIDOC
## POST /api/viewmodels/instantiate
### Description
Constructs and returns a new instance of a specified ViewModel type. If wrapping an existing DataContext, it should be provided as the second argument.
### Method
POST
### Endpoint
/api/viewmodels/instantiate
### Parameters
#### Query Parameters
- **type** (String) - Required - The registered name of the ViewModel type to instantiate.
- **wrappedViewModel** (Object) - Optional - The existing DataContext object to wrap.
#### Request Body
*Note: The request body is not explicitly defined for this operation in the provided text, but conceptually it would contain the parameters passed to the function.*
### Request Example (No Wrapper)
```lua
local vm = Ext.UI.Instantiate("PREFIX_YourTypeName")
vm.MyStringProperty = "whatever"
```
### Request Example (With Wrapper)
```lua
local vm = Ext.UI.Instantiate("se::PREFIX_YourTypeName", mainMenu.DataContext)
mainMenu.DataContext = vm
```
### Response
#### Success Response (200)
- **instance** (Object) - The newly created ViewModel instance.
#### Response Example
```json
{
"instance": ""
}
```
```
--------------------------------
### Ext.Entity.OnDestroyOnce
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
One-shot destroy subscription that auto-unsubscribes after the first match.
```lua
OnDestroyOnce(componentName, callback, [entity])
```
--------------------------------
### Ext.Entity.OnDestroyDeferredOnce
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Deferred and one-shot variant of OnDestroy.
```lua
OnDestroyDeferredOnce(componentName, callback, [entity])
```
--------------------------------
### Subscribe to SessionLoading Event
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
This event is triggered when the engine begins setting up a game session, including new games, loading saves, or joining multiplayer.
```lua
Ext.Events.SessionLoading:Subscribe(function()
-- Code to run when a session starts loading
end)
```
--------------------------------
### Execute User Queries
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Invoke user-defined queries (QRY) which return a success boolean.
```lua
local succeeded = Osi.Qry_IsHealingStatus("DAMAGE")
```
--------------------------------
### Ext.Entity.OnSystemUpdate
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Subscribes to ECS system update hooks.
```lua
OnSystemUpdate(systemType, callback, [once])
```
--------------------------------
### Manage Mod Variables with Ext.Vars
Source: https://context7.com/norbyte/bg3se/llms.txt
Register and access persistent mod-wide data that syncs between client and server.
```lua
-- Register mod variable (in bootstrap)
Ext.Vars.RegisterModVariable(ModuleUUID, "GlobalSettings", {
Server = true,
Client = true,
SyncToClient = true,
Persistent = true
})
-- Access mod variables
local vars = Ext.Vars.GetModVariables(ModuleUUID)
-- Write data
vars.GlobalSettings = {
difficulty = "hard",
enableFeatureX = true,
playerScores = {}
}
-- Read data
local settings = vars.GlobalSettings
if settings.enableFeatureX then
print("Feature X is enabled")
end
-- Force sync
Ext.Vars.SyncModVariables(ModuleUUID)
```
--------------------------------
### Configure JSON Serialization
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use an options table to customize JSON output, such as enabling beautification or setting recursion limits.
```lua
Ext.Json.Stringify(val, {
Beautify = true,
MaxDepth = 4
})
```
--------------------------------
### Entity Component Access Shorthand
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Illustrates the shorthand syntax for accessing a component using dot notation, which is equivalent to calling GetComponent.
```lua
local entity = Ext.Entity.Get(GetHostCharacter())
-- The two below are equivalent
local displayName = entity:GetComponent("DisplayName")
local displayName = entity.DisplayName
```
--------------------------------
### Utilities
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
General utility functions for script extender and game version checks, state retrieval, and command line arguments.
```APIDOC
## Utils - `Ext.Utils`
### Description
General utility helpers.
### Common Methods
- `Ext.Utils.Version(): int32` - Returns the Script Extender API version.
- `Ext.Utils.GameVersion(): string?` - Returns the game version string.
- `Ext.Utils.GetGameState()` - Returns the current game state enum.
- `Ext.Utils.GetGlobalSwitches(): GlobalSwitches` - Returns a settings object including fields like `AiEnableSwarm`, `CanAutoSave`, `NrOfAutoSaves`, etc.
- `Ext.Utils.GetCommandLineParams(): string[]` - Returns the command line arguments used to launch the game.
- `Ext.Utils.HandleToInteger(handle): int64` - Converts a handle to an integer.
- `Ext.Utils.IntegerToHandle(value): EntityHandle` - Converts an integer to an entity handle.
- `Ext.Utils.IsValidHandle(handle): boolean` - Checks if a handle is valid.
- `Ext.Utils.ProfileBegin(name)` - Starts a profiling block.
- `Ext.Utils.ProfileEnd()` - Ends a profiling block.
### Example Usage (Command Line Params)
```lua
local params = Ext.Utils.GetCommandLineParams()
for _, param in ipairs(params) do
_P(param)
end
```
```
--------------------------------
### Subscribe to Engine Events
Source: https://context7.com/norbyte/bg3se/llms.txt
Register handlers for game state changes using Ext.Events. Supports priority levels and one-shot execution.
```lua
-- Subscribe to game state changes
Ext.Events.GameStateChanged:Subscribe(function(e)
print("State changed from " .. tostring(e.FromState) .. " to " .. tostring(e.ToState))
end)
-- Subscribe with priority (lower = called first) and one-shot flag
Ext.Events.SessionLoaded:Subscribe(function(e)
print("Session loaded - initializing mod...")
-- Initialize your mod here
end, { Priority = 50, Once = false })
-- Unsubscribe later using the returned handler ID
local handlerId = Ext.Events.StatsLoaded:Subscribe(function(e)
print("Stats loaded - applying modifications...")
end)
-- Later: Ext.Events.StatsLoaded:Unsubscribe(handlerId)
-- Common events:
-- ModuleLoadStarted - Before mod data loads (use for Ext.IO.AddPathOverride)
-- StatsLoaded - After stats entries loaded (apply stat modifications here)
-- SessionLoading - Game session starting
-- SessionLoaded - Game session ready
-- Tick - Every game tick (~30hz on server)
-- ResetCompleted - After Lua state reset
```
--------------------------------
### Instantiate a ViewModel
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Constructs a new instance of a registered ViewModel type. Supports both standalone instances and those wrapping existing DataContext objects.
```lua
local vm = Ext.UI.Instantiate("PREFIX_YourTypeName")
vm.MyStringProperty = "whatever"
```
```lua
local vm = Ext.UI.Instantiate("se::PREFIX_YourTypeName", mainMenu.DataContext)
mainMenu.DataContext = vm
```
--------------------------------
### Listen for NetMessages on Client
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Subscribe to Ext.Events.NetMessage to receive messages. Parse the payload if it was stringified. Ext.RegisterNetListener provides a convenient wrapper.
```lua
--Client context
local channel = "MyModChannel_SomethingSpecific"
Ext.Events.NetMessage:Subscribe(function(data)
if data.Channel == channel then
--Parse the string back into a table if it was stringified
local data = Ext.Json.Parse(data.Payload)
--Do whatever you want with the data in the client context
someFunction(data)
end
end)
```
```lua
--wrapper for Ext.Events.NetMessage:Subscribe(function(data) ...end)
--which removes the need to check for the channel
Ext.RegisterNetListener(channel, function(channel, payload, userID)
--Parse the string back into a table
local data = Ext.Json.Parse(payload)
--Do whatever you want with the data in the client context
someFunction(data)
end)
```
--------------------------------
### Iterate Loaded Mods
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Retrieve the current load order and inspect details for each loaded module.
```lua
local loadOrder = Ext.Mod.GetLoadOrder()
for k,uuid in pairs(loadOrder) do
local mod = Ext.Mod.GetMod(uuid)
_D(mod)
end
```
--------------------------------
### Ext.Math Library Functions
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
A collection of mathematical utility functions for vector and matrix operations.
```APIDOC
## Ext.Math Library
### Description
The Ext.Math library provides various functions for arithmetic, vector, and matrix calculations.
### Functions
- **Add** (a: any, b: any) -> any: Adds two operands.
- **Sub** (a: any, b: any) -> any: Subtracts two operands.
- **Mul** (a: any, b: any) -> any: Multiplies two operands.
- **Div** (a: any, b: any) -> any: Divides two operands.
- **Reflect** (I: vec3|vec4, N: vec3|vec4) -> vec3|vec4: Returns reflection direction.
- **Angle** (a: vec3|vec4, b: vec3|vec4) -> float: Returns absolute angle between two normalized vectors.
- **Cross** (x: vec3, y: vec3) -> vec3: Returns the cross product.
- **Distance** (p0: vec3, p1: vec3) -> float: Returns distance between p0 and p1.
- **Dot** (x: vec3, y: vec3) -> float: Returns the dot product.
- **Length** (x: vec3|vec4) -> float: Returns the length of x.
- **Normalize** (x: vec3|vec4) -> vec3|vec4: Returns a normalized vector.
- **Determinant** (x: mat3|mat4) -> float: Returns the determinant of a matrix.
- **Inverse** (x: mat3|mat4) -> mat3|mat4: Returns the inverse of a matrix.
- **Transpose** (x: mat3|mat4) -> mat3|mat4: Returns the transposed matrix.
- **OuterProduct** (c: vec3|vec4, r: vec3|vec4) -> mat: Returns outer product.
- **Rotate** (m: mat3|mat4, angle: float, axis: vec4) -> void: Builds a rotation matrix.
- **Translate** (m: mat4, translation: vec3) -> void: Transforms a matrix with translation.
- **Scale** (m: mat4, translation: vec3) -> void: Transforms a matrix with scale.
- **BuildRotation4** (v: vec3, angle: float) -> mat4: Builds a 4x4 rotation matrix.
- **BuildRotation3** (v: vec3, angle: float) -> mat3: Builds a 3x3 rotation matrix.
- **BuildTranslation** (v: vec3) -> mat4: Builds a 4x4 translation matrix.
- **BuildScale** (v: vec3) -> mat4: Builds a 4x4 scale matrix.
- **ExtractEulerAngles** (m: mat3|mat4) -> vec3: Extracts Euler angles.
- **BuildFromEulerAngles4** (angles: vec3) -> mat4: Creates a 4x4 rotation matrix from Euler angles.
- **BuildFromEulerAngles3** (angles: vec3) -> mat3: Creates a 3x3 rotation matrix from Euler angles.
- **Decompose** (m: mat4, scale: vec3, yawPitchRoll: vec3, translation: vec3) -> void: Decomposes a model matrix.
- **ExtractAxisAngle** (m: mat3|mat4, axis: vec3) -> float: Extracts axis-angle representation.
- **BuildFromAxisAngle3** (axis: vec3, angle: float) -> mat3: Builds a 3x3 rotation matrix from axis-angle.
- **BuildFromAxisAngle4** (axis: vec3, angle: float) -> mat4: Builds a 4x4 rotation matrix from axis-angle.
- **Perpendicular** (x: vec3|vec4, normal: vec3|vec4) -> vec3|vec4: Projects x on a perpendicular axis.
- **Project** (x: vec3|vec4, normal: vec3|vec4) -> vec3|vec4: Projects x on normal.
- **Fract** (x: float) -> float: Returns x - floor(x).
- **Trunc** (x: float) -> float: Returns nearest integer.
- **Sign** (x: float) -> float: Returns sign of x.
- **Clamp** (val: float, minVal: float, maxVal: float) -> float: Clamps value.
- **Lerp** (x: float, y: float, a: float) -> float: Linear blend.
- **Acos** (x: float) -> float: Arc cosine.
- **Asin** (x: float) -> float: Arc sine.
- **Atan** (y_over_x: float) -> float: Arc tangent.
- **Atan2** (x: float, y: float) -> float: Arc tangent of y/x.
```
--------------------------------
### Ext.Entity.OnDestroy
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Subscription for component destruction events.
```lua
OnDestroy(componentName, callback, [entity], [opt1], [opt2])
```
--------------------------------
### Send Request to Client with Reply Callback
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Sends a request to a specific client. Optionally specify a user and a reply callback for the response.
```lua
--- Send a request to a client; optionally specify a user and reply callback
---@param data table
---@param user integer|Guid
---@param replyCallback fun(data:table)
function NetChannel:RequestToClient(data, user, replyCallback) end
```
--------------------------------
### Ext.Events Subscription
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Documentation for subscribing to engine and SE events using Ext.Events.:Subscribe(fun).
```APIDOC
## Ext.Events Subscription
### Description
Subscribe to engine and SE events to execute custom logic during specific game lifecycle stages.
### Method
Ext.Events.:Subscribe(fun)
### Events
- **ModuleLoadStarted**: Thrown when the engine has started loading mods. Useful for filesystem-level hooks via Ext.IO.AddPathOverride.
- **StatsLoaded**: Thrown after stats entries are cleared and reloaded. Use for persistent stat modifications.
- **SessionLoading**: Thrown when the engine starts setting up a game session.
- **SessionLoaded**: Thrown when the game session setup is complete.
- **ResetCompleted**: Thrown when Ext.Debug.Reset() or the reset console command completes.
- **GameStateChanged**: Indicates a change in server/client game state.
- **Tick**: Thrown after each game engine tick (~30hz on server). Use Ext.OnNextTick(fun) for one-time execution.
```
--------------------------------
### Templates - Ext.Template
Source: https://context7.com/norbyte/bg3se/llms.txt
Provides access to game object templates, including characters and items.
```APIDOC
## Ext.Template
### Description
Methods to access and retrieve game object definitions.
### Methods
- **Ext.Template.GetTemplate(uuid)**: Retrieves a template by ID.
- **Ext.Template.GetRootTemplate(uuid)**: Retrieves a root template by ID.
- **Ext.Template.GetAllRootTemplates()**: Returns all available root templates.
```
--------------------------------
### Configure Script Extender
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Create a Config.json file in the mod's ScriptExtender directory to enable features like Lua scripting.
```json
{
"RequiredVersion": 29,
"ModTable": "YOUR_MOD_NAME_HERE",
"FeatureFlags": ["Lua"]
}
```
--------------------------------
### Level and Physics API
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Methods for pathfinding, raycasting, and physics overlap tests.
```APIDOC
## Ext.Level Methods
### Description
Handles spatial queries, pathfinding, and physics interactions.
### Methods
- `Ext.Level.BeginPathfinding(entity, targetPos, opts): AiPath`
- `Ext.Level.RaycastAny(from, to, physicsType, collidesWith, ignoredGroups, maxHits): boolean`
- `Ext.Level.GetEntitiesOnTile(position): EntityHandle[]`
- `Ext.Level.GetHeightsAt(x, z): number[]`
```
--------------------------------
### Send Request to Server with Reply Callback
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Sends a request to the server. The reply is handled asynchronously via the provided callback.
```lua
--- Send a request to the server; reply arrives via `replyCallback`
---@param data table
---@param replyCallback fun(data:table)
function NetChannel:RequestToServer(data, replyCallback) end
```
--------------------------------
### Send NetMessage from Server to Client(s)
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Use BroadcastMessage to send to all clients, PostMessageToUser for a specific user ID, or PostMessageToClient for a specific character UUID. Payloads must be stringified if they are tables.
```lua
--Server context
local channel = "MyModChannel_SomethingSpecific"
local payload = {["somedata"] = somevalue, ["supertable"]={1,2,3,4,5}}
--We need to stringify our payload in this case since it is a table and not a string
payload=Ext.Json.Stringify(payload)
--If we want to send the message to ALL the clients
Ext.ServerNet.BroadcastMessage(channel, payload)
--If we wanted to send the message to a specific userId
local somePeer = 9999
Ext.ServerNet.PostMessageToUser(somePeer, channel, payload)
--If we wanted to send the message to the client controlling a specific character
local someUUID = "c774d764-4a17-48dc-b470-32ace9ce447d" -- Wyll's uuid
Ext.ServerNet.PostMessageToClient(characterUUID, channel, payload)
```
--------------------------------
### Modify Game Stats with Ext.Stats
Source: https://context7.com/norbyte/bg3se/llms.txt
Read, modify, or create game stat entries. Runtime modifications require a sync call.
```lua
-- Get all stats of a type
local spells = Ext.Stats.GetStats("SpellData")
local weapons = Ext.Stats.GetStats("Weapon")
local statuses = Ext.Stats.GetStats("StatusData")
-- Get a specific stat entry
local spell = Ext.Stats.Get("Shout_FlameBlade")
print("Cost: " .. spell.UseCosts)
print("Damage: " .. spell.SpellType)
-- Modify stats (during StatsLoaded or with Sync)
Ext.Events.StatsLoaded:Subscribe(function()
-- Modify existing spell
local fireball = Ext.Stats.Get("Projectile_Fireball")
fireball.SpellProperties = "IF(not SavingThrow(Ability.Dexterity, 15)):ApplyStatus(BURNING,100,3)"
-- Disable autocast on all spells
for _, name in pairs(Ext.Stats.GetStats("SpellData")) do
local stat = Ext.Stats.Get(name)
if stat.Autocast == "Yes" then
stat.Autocast = "No"
end
end
end)
-- Create new stat entry
local newSpell = Ext.Stats.Create("MyMod_CustomSpell", "SpellData", "Projectile_Fireball")
newSpell.DisplayName = "Custom Fireball"
newSpell.Description = "A custom fireball spell"
newSpell.SpellSchool = "Evocation"
newSpell:Sync() -- Required for runtime changes
-- Modify stats at runtime (requires sync)
local weapon = Ext.Stats.Get("WPN_Longsword")
weapon.Damage = "2d8"
weapon:Sync()
```
--------------------------------
### Registering User Variables
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
This section explains how to register custom variables for entities, enabling automatic network synchronization and savegame persistence.
```APIDOC
## Ext.Vars.RegisterUserVariable
### Description
Registers a user variable for entities, allowing for custom properties with network synchronization and savegame persistence.
### Method
`Ext.Vars.RegisterUserVariable(variableName, settings)`
### Parameters
#### Path Parameters
- **variableName** (string) - Required - The name of the user variable to register. It's recommended to prefix with your mod name.
- **settings** (table) - Optional - A table of settings to configure the variable's behavior.
- **Server** (boolean) - Default: `true` - Whether the variable is present on server entities.
- **Client** (boolean) - Default: `false` - Whether the variable is present on client entities.
- **WriteableOnServer** (boolean) - Default: `true` - Whether the variable can be modified on the server.
- **WriteableOnClient** (boolean) - Default: `false` - Whether the variable can be modified on the client.
- **Persistent** (boolean) - Default: `true` - Whether the variable is written to/restored from savegames.
- **SyncToClient** (boolean) - Default: `false` - Whether server-side changes are synced to all clients.
- **SyncToServer** (boolean) - Default: `false` - Whether client-side changes are synced to the server.
- **SyncOnTick** (boolean) - Default: `true` - Whether client-server sync is performed once per game loop tick.
- **SyncOnWrite** (boolean) - Default: `false` - Whether client-server sync is performed immediately when the variable is written.
- **DontCache** (boolean) - Default: `false` - Disables Lua caching of variable values.
### Usage Notes
- Variables must be registered before savegame load and Lua context reset, ideally in `BootstrapServer.lua` or `BootstrapClient.lua`.
- Register variables with the same settings on both client and server to avoid synchronization issues.
- Client-only variables cannot be persistent.
### Request Example
```lua
Ext.Vars.RegisterUserVariable("NRD_Whatever", {
Server = true,
Client = true,
SyncToClient = true
})
```
### Usage Example
```lua
_C().Vars.NRD_Whatever = 123
Ext.Print(_C().Vars.NRD_Whatever)
```
```
--------------------------------
### Ext.Entity
Source: https://context7.com/norbyte/bg3se/llms.txt
Provides methods to retrieve and manipulate game entities and their components.
```APIDOC
## Ext.Entity.Get
### Description
Retrieves a game entity by its UUID or handle.
### Parameters
- **id** (string) - Required - The UUID or handle of the entity.
### Response
- **entity** (object) - The entity object containing components and helper methods.
```
--------------------------------
### Server-side Broadcast Global Settings
Source: https://github.com/norbyte/bg3se/blob/main/Docs/API.md
Server pushes current settings to all connected clients using `Broadcast`. This is a one-way message.
```lua
-- Server side: push current data to all connected clients
Channels.SyncSettings:Broadcast({ Settings = MCM.GetCurrentSettings() })
```
--------------------------------
### Localization - Ext.Loca
Source: https://context7.com/norbyte/bg3se/llms.txt
Provides access to game localization strings and allows runtime updates to translated text.
```APIDOC
## Ext.Loca
### Description
Methods to retrieve and modify translated strings using their handles.
### Methods
- **Ext.Loca.GetTranslatedString(handle, [fallback])**: Retrieves a translated string by its handle.
- **Ext.Loca.UpdateTranslatedString(handle, text)**: Updates a translated string at runtime.
```
--------------------------------
### Mod Info - Ext.Mod
Source: https://context7.com/norbyte/bg3se/llms.txt
Provides functionality to query information about loaded mods and the current mod load order.
```APIDOC
## Ext.Mod
### Description
Utilities for checking mod status and retrieving metadata for loaded mods.
### Methods
- **Ext.Mod.IsModLoaded(uuid)**: Returns true if the specified mod is loaded.
- **Ext.Mod.GetLoadOrder()**: Returns an array of mod UUIDs in the current load order.
- **Ext.Mod.GetMod(uuid)**: Retrieves detailed information about a specific mod.
```
--------------------------------
### Schedule Tasks with Ext.Timer
Source: https://context7.com/norbyte/bg3se/llms.txt
Execute code after delays or on the next tick, with support for persistent timers that survive save/load cycles.
```lua
-- Wait using game time (pauses when game pauses)
Ext.Timer.WaitFor(3000, function()
print("3 seconds (game time) have passed")
end)
-- Wait using real time
Ext.Timer.WaitForRealtime(5000, function()
print("5 seconds (real time) have passed")
end)
-- Persistent timer (survives save/load)
Ext.Timer.RegisterPersistentHandler("MyMod_DelayedAction", function(timerName)
print("Persistent timer fired: " .. timerName)
end)
local handle = Ext.Timer.WaitForPersistent(60000, "MyMod_DelayedAction", function()
print("One minute passed (persistent)")
end)
-- Timer control
Ext.Timer.Pause(handle)
Ext.Timer.Resume(handle)
local isPaused = Ext.Timer.IsPaused(handle)
Ext.Timer.Cancel(handle)
-- Execute on next tick
Ext.OnNextTick(function()
print("Runs on the next game tick")
end)
-- Performance measurement
local start = Ext.Timer.MonotonicTime()
-- ... do work ...
local elapsed = Ext.Timer.MonotonicTime() - start
print("Took " .. elapsed .. "ms")
```