Micro AIs: simplify unit variable handling functions
The main reason for doing this, besides simplifying the code, is to avoid using the WML table dump __cfg, which is slow. This includes a change of the format in which the variables are stored, but since these are internal Micro AI utility functions, that does not matter.
(cherry-picked from commit 133568efe6
)
This commit is contained in:
parent
b5c8c60ad0
commit
695fa69238
1 changed files with 30 additions and 66 deletions
|
@ -1,86 +1,50 @@
|
|||
-- This set of functions provides a consistent way of storing Micro AI
|
||||
-- variables in units. They need to be stored inside a [micro_ai] tag in a
|
||||
-- unit's [variables] tag together with an ai_id= key, so that they can be
|
||||
-- removed when the Micro AI gets deleted. Otherwise subsequent Micro AIs used
|
||||
-- in the same scenario (or using the same units in later scenarios) might work
|
||||
-- incorrectly or not at all.
|
||||
-- Note that, with this method, there can only ever be one of these tags for each
|
||||
-- ai_ca in each unit (but of course several when there are several Micro AIs
|
||||
-- with different ai_CA values affecting the same unit)
|
||||
-- For the time being, we only allow key=value style variables.
|
||||
-- variables in units. Individual variables are stored inside a table with a
|
||||
-- name specific to the MAI ('micro_ai-' .. ai_id). This table is removed when
|
||||
-- the Micro AI is deleted in order to ensure that subsequent Micro AIs used
|
||||
-- in the same scenario (or using the same units in later scenarios) work
|
||||
-- correctly.
|
||||
-- Note that, with this method, there can only ever be one of these tables for each
|
||||
-- ai_id in each unit, but several tables are created for the same unit when there
|
||||
-- are several Micro AIs with different ai_id values.
|
||||
-- For the time being, we do not allow sub-tables. This is done because these
|
||||
-- unit variables are required to be persistent across save-load cycles and
|
||||
-- therefore need to be in WML table format. This could be extended to allow
|
||||
-- sub-tables in WML format, but there is no need for that at this time.
|
||||
|
||||
local micro_ai_unit_variables = {}
|
||||
|
||||
function micro_ai_unit_variables.modify_mai_unit_variables(unit, ai_id, action, vars_table)
|
||||
-- Modify [unit][variables][micro_ai] tags
|
||||
-- @ai_id (string): the id of the Micro AI
|
||||
-- @action (string): "delete", "set" or "insert"
|
||||
-- @vars_table: table of key=value pairs with the variables to be set or inserted (not needed for @action="delete")
|
||||
|
||||
local variables = unit.variables.__cfg
|
||||
|
||||
-- Always delete the respective [variables][micro_ai] tag, if it exists
|
||||
local existing_table
|
||||
for i,mai in ipairs(variables) do
|
||||
if (mai[1] == "micro_ai") and (mai[2].ai_id == ai_id) then
|
||||
existing_table = mai[2]
|
||||
table.remove(variables, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Then replace it, if the "set" action is selected
|
||||
-- or add the new keys to it, overwriting old ones with the same name, if action == "insert"
|
||||
if (action == "set") or (action == "insert") then
|
||||
local tag = { "micro_ai" }
|
||||
|
||||
if (not existing_table) or (action == "set") then
|
||||
tag[2] = vars_table
|
||||
tag[2].ai_id = ai_id
|
||||
else
|
||||
for k,v in pairs(vars_table) do existing_table[k] = v end
|
||||
tag[2] = existing_table
|
||||
end
|
||||
|
||||
table.insert(variables, tag)
|
||||
end
|
||||
|
||||
-- All of this so far was only on the table dump -> apply to unit
|
||||
unit.variables.__cfg = variables
|
||||
end
|
||||
|
||||
function micro_ai_unit_variables.delete_mai_unit_variables(unit, ai_id)
|
||||
micro_ai_unit_variables.modify_mai_unit_variables(unit, ai_id, "delete")
|
||||
unit.variables['micro_ai_' .. ai_id] = nil
|
||||
end
|
||||
|
||||
function micro_ai_unit_variables.insert_mai_unit_variables(unit, ai_id, vars_table)
|
||||
micro_ai_unit_variables.modify_mai_unit_variables(unit, ai_id, "insert", vars_table)
|
||||
local mai_var = unit.variables['micro_ai_' .. ai_id] or {}
|
||||
-- Restrict to top-level named fields
|
||||
for k,v in pairs(vars_table) do mai_var[k] = v end
|
||||
unit.variables['micro_ai_' .. ai_id] = mai_var
|
||||
end
|
||||
|
||||
function micro_ai_unit_variables.set_mai_unit_variables(unit, ai_id, vars_table)
|
||||
micro_ai_unit_variables.modify_mai_unit_variables(unit, ai_id, "set", vars_table)
|
||||
local mai_var = {}
|
||||
-- Restrict to top-level named fields
|
||||
for k,v in pairs(vars_table) do mai_var[k] = v end
|
||||
unit.variables['micro_ai_' .. ai_id] = mai_var
|
||||
end
|
||||
|
||||
function micro_ai_unit_variables.get_mai_unit_variables(unit, ai_id, key)
|
||||
-- Get the content of [unit][variables][micro_ai] tag for the given @ai_id
|
||||
-- Get the content of [unit][variables]['micro_ai_' .. ai_id] tag
|
||||
-- Return value:
|
||||
-- - If tag is found: value of key if @key parameter is given, otherwise
|
||||
-- table of key=value pairs (including the ai_id key)
|
||||
-- - If no such tag is found: nil (if @key is set), otherwise empty table
|
||||
-- - If tag is found: value of key if @key parameter is given, otherwise entire table
|
||||
-- - If no such tag is found: nil if @key is given, otherwise empty table
|
||||
|
||||
for mai in wml.child_range(unit.variables.__cfg, "micro_ai") do
|
||||
if (mai.ai_id == ai_id) then
|
||||
if key then
|
||||
return mai[key]
|
||||
else
|
||||
return mai
|
||||
end
|
||||
end
|
||||
local mai_var = unit.variables['micro_ai_' .. ai_id] or {}
|
||||
|
||||
if key then
|
||||
return mai_var[key]
|
||||
else
|
||||
return mai_var
|
||||
end
|
||||
|
||||
-- If we got here, no corresponding tag was found
|
||||
-- Return empty table; or nil if @key was set
|
||||
if (not key) then return {} end
|
||||
end
|
||||
|
||||
return micro_ai_unit_variables
|
||||
|
|
Loading…
Add table
Reference in a new issue