diff --git a/data/ai/micro_ais/micro_ai_unit_variables.lua b/data/ai/micro_ais/micro_ai_unit_variables.lua index 583b20c6bcdf..0892a4d9f4c1 100644 --- a/data/ai/micro_ais/micro_ai_unit_variables.lua +++ b/data/ai/micro_ais/micro_ai_unit_variables.lua @@ -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 - end + local mai_var = unit.variables['micro_ai_' .. ai_id] or {} - -- If we got here, no corresponding tag was found - -- Return empty table; or nil if @key was set - if (not key) then return {} end + if key then + return mai_var[key] + else + return mai_var + end end return micro_ai_unit_variables