Last active
October 27, 2022 01:08
-
-
Save LaughingLeader/f32d91b188c81ca392a5054d1f5676b1 to your computer and use it in GitHub Desktop.
Example of making a system for registering functions to call when flags are set, for Divinity: Original Sin 2 with the Script Extender.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
EventManager = { | |
Register = {}, | |
} | |
---@alias EventManagerObjectFlagSetCallback fun(flag:string, targetGUID:GUID, dialogInstance:integer) | |
local _Callbacks = { | |
ObjectFlagSet = { | |
---@type table<string, EventManagerObjectFlagSetCallback[]> | |
Active = {}, | |
Regions = { | |
__ANY__ = {}, -- Any region, | |
} | |
}, | |
} | |
local function _GetCurrentLevel() | |
local current = Ext.Entity.GetCurrentLevel() | |
if current then | |
return current.LevelDesc.LevelName | |
end | |
return "" | |
end | |
--[[ | |
This is configured to be 1 function per flag (using a key-value type table where the flag is the key), | |
but could be changed to support multiple callbacks for the same flags. | |
]] | |
---Register a function to call when the given flag(s) are set. | |
---@param flag string|string[] Any single flag, or a table of flags. | |
---@param callback EventManagerObjectFlagSetCallback | |
---@param region string|nil | |
function EventManager.Register.ObjectFlagSet(flag, callback, region) | |
if not region then | |
region = "__ANY__" | |
end | |
if _Callbacks.ObjectFlagSet.Regions[region] == nil then | |
_Callbacks.ObjectFlagSet.Regions[region] = {} | |
end | |
local t = type(flag) | |
if t == "table" then | |
for _,v in pairs(flag) do | |
_Callbacks.ObjectFlagSet.Regions[region][v] = callback | |
end | |
elseif t == "string" then | |
_Callbacks.ObjectFlagSet.Regions[region][flag] = callback | |
else | |
error("Wrong flag type: " .. t, 2) | |
end | |
end | |
local function _BuildCallbacks(region) | |
local tbl = {} | |
local regionCallbacks = _Callbacks.ObjectFlagSet.Regions[region] | |
if regionCallbacks then | |
for flag,v in pairs(regionCallbacks) do | |
if tbl[flag] == nil then tbl[flag] = {} end | |
table.insert(tbl[flag], v) | |
end | |
end | |
for flag,v in pairs(_Callbacks.ObjectFlagSet.Regions.__ANY__) do | |
if tbl[flag] == nil then tbl[flag] = {} end | |
table.insert(tbl[flag], v) | |
end | |
_Callbacks.ObjectFlagSet.Active = tbl | |
end | |
Ext.Osiris.RegisterListener("RegionStarted", 1, "after", _BuildCallbacks) | |
Ext.Events.ResetCompleted:Subscribe(function (e) _BuildCallbacks(_GetCurrentLevel()) end) | |
Ext.Osiris.RegisterListener("ObjectFlagSet", 3, "after", function (flag, targetGUID, inst) | |
---@cast flag string | |
local callbacks = _Callbacks.ObjectFlagSet.Active[flag] | |
if callbacks then | |
targetGUID = GetUUID(targetGUID) | |
for _,v in pairs(callbacks) do | |
local b,err = xpcall(v, debug.traceback, flag, targetGUID, inst) | |
if not b then | |
Ext.Utils.PrintError(err) | |
end | |
end | |
end | |
end) | |
--[[ | |
--Usage Example: | |
EventManager.Register.ObjectFlagSet({"QuestUpdate_TUT_ShipMurder_Fled", "QuestUpdate_TUT_ShipMurder_Rescued", "QuestUpdate_TUT_ShipMurder_Failed"}, | |
function (flag, targetGUID, dialogInstance) | |
for key, value in pairs(TUT_Char) do | |
if CharacterIsDead(value) == 0 then | |
Crew[value] = true | |
else | |
Crew[value] = nil | |
end | |
end | |
end, "TUT_Tutorial_A") | |
]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment