Scenario BlackDeath from last DLC solve how add your custom data into gamecore. Save and load then automatically work with your data. DLC also solve exchange data from UI thread and Script thread.
Simple application in your code on script thread
Code:
-- ===============================================================================================
-- STATE / CACHE from BlackDeathScenario
-- Custom data are kept in cache and set into game as a property on the Game object from script thread
-- Set your custom data = pObject:SetProperty(sPropertyName, value)
-- Get your custom data = pObject:GetProperty(sPropertyName)
-- Object can be Game, pCity, pPlayer, pUnit, pPlot
-- Value are variable, field, structure
-- Name of Value (sPropertyName) are stored in g_PropertyKeys
-- Handle among script thread and UI thread guarantee function in this file
-- This file must be insert on start every file using "include" command (from UI and script)
-- When save, load game system do it with yours custom data
-- ===============================================================================================
g_PropertyKeys = {
Turn = "Turn", -- your custom data
};
-- Every time SetObjectState is called, the script-side cache is updated to prevent unnecessary
-- calls down to gamecore.
local USE_CACHE : boolean = true;
local g_ObjectStateCache = {};
-- ===========================================================================
function SetObjectState(pObject : object, sPropertyName : string, value)
if (sPropertyName == nil) then
return nil;
end
if (pObject == nil) then
print("StateUtils SetObjectState: ERROR: object is nil!");
return nil;
end
if (USE_CACHE == true) then
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
-- update cache
g_ObjectStateCache[pObject][sPropertyName] = value;
end
-- when you call this function from UI thread you must update data on script thread
if UI ~= nil then
-- We are on the UI side of things. We must sent a command to change the game state
local kParameters:table = {};
kParameters.propertyName = sPropertyName;
kParameters.value = value;
kParameters.objectID = pObject:GetComponentID();
-- Send this GameEvent when processing the operation
kParameters.OnStart = "OnPlayerCommandSetObjectState";
UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.EXECUTE_SCRIPT, kParameters);
else
-- when you call this function from script thread you send data into gamecore
if (pObject.SetProperty ~= nil) then
pObject:SetProperty(sPropertyName, value);
end
end
end
-- ====================================================================================
-- This function is called from UI thread using function "UI.RequestPlayerOperation" as event
function OnPlayerCommandSetObjectStateHandler(ePlayer : number, params : table)
local pObject = Game.GetObjectFromComponentID(params.objectID);
if pObject ~= nil then
SetObjectState(pObject, params.propertyName, params.value);
end
end
-- This file gets includes on both the UI and GameCore side, we only want to handle the event on the Game Core side.
if UI == nil then
GameEvents.OnPlayerCommandSetObjectState.Add( OnPlayerCommandSetObjectStateHandler );
end
-- ===================================================================================
function GetObjectState(pObject : object, sPropertyName : string, bCacheCheckOnly : boolean)
if (sPropertyName == nil) then
return nil;
end
if (pObject == nil) then
print("StateUtils GetObjectState: ERROR: object is nil!");
return nil;
end
bCacheCheckOnly = bCacheCheckOnly or false;
if (USE_CACHE == true) then
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
if (g_ObjectStateCache[pObject][sPropertyName] ~= nil) then
return g_ObjectStateCache[pObject][sPropertyName];
else
if (bCacheCheckOnly) then
return nil;
else
return RefreshObjectState(pObject, sPropertyName);
end
end
else
return pObject:GetProperty(sPropertyName);
end
end
-- ===========================================================================
-- Forces a call to gamecore and cache update.
function RefreshObjectState(pObject : object, sPropertyName : string)
if (sPropertyName == nil) then
return nil;
end
if (pObject.GetProperty == nil) then
return nil;
end
local propResult = pObject:GetProperty(sPropertyName);
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
g_ObjectStateCache[pObject][sPropertyName] = propResult;
return propResult;
end
Code:
include "StateUtils"
function Initialize()
print("Test initialize");
GameEvents.OnGameTurnStarted.Add(OnGameTurnStarted);
-- Initialize current turn
local Turn = GetObjectState(Game, g_PropertyKeys.Turn);
if (Turn == nil) then
SetObjectState(Game, g_PropertyKeys.Turn, 0);
print("Initialize turn: ", Turn);
end
end
function OnGameTurnStarted( currentTurn:number )
print("Current turn: ", currentTurn);
local lastTurn = GetObjectState(Game, g_PropertyKeys.Turn);
print("Last turn: ", lastTurn);
SetObjectState(Game, g_PropertyKeys.Turn, currentTurn);
end
Initialize();