diff --git a/lua/main.lua b/lua/main.lua index 2cb26c05..4742d2dc 100644 --- a/lua/main.lua +++ b/lua/main.lua @@ -1112,3 +1112,96 @@ function wesnoth.wml_actions.set_wrath_intensity(cfg) end wesnoth.units.to_map(unit) end + +-- [unit_status_semaphore] +-- +-- first call with action=incr will save original value and set status +-- last call with action=decr (count=0) will restore original value +-- +-- unit.variables.statuses.foo.original_value, where foo is a status like 'unhealable' - stores original value to restore when all custom actions are done messing with this status +-- unit.variables.statuses.foo.count - counts the number of custom actions that currently need this status set +function wesnoth.wml_actions.unit_status_semaphore(cfg) + local debug = cfg.debug or false + if debug and not debug then print("shut up luacheck") end + local unit_id = cfg.id or wml.error("[unit_status_semaphore]: missing required id=") + local status = cfg.status or wml.error("[unit_status_semaphore]: missing required status=") + local action = cfg.action or wml.error("[unit_status_semaphore]: missing required action=") + + local unit = wesnoth.units.get(unit_id).__cfg + local vars = wml.get_child(unit, "variables") + local statuses = wml.get_child(vars, "statuses") + local current = {} + local had_current = false + if statuses ~= nil then + current = wml.get_child(statuses, status) + if current == nil then + current = {} + else + had_current = true + end + end + if action == "clear" then -- just clear, do not reset to original value + if statuses ~= nil then + if status == "all" then + wml.remove_child(vars, "statuses") + else + wml.remove_child(statuses, status) + if #statuses == 0 then wml.remove_child(vars, "statuses") end + end + end + elseif action == "reset" then -- clear and reset to original value + if statuses == nil then + wml.error("[unit_status_semaphore]: reset failed to find any original values") + else + if status == "all" then + for s in wml.child_range(vars, "statuses") do + wml.get_child(unit, "status")[s] = current.original_value + wml.remove_child(statuses, s) + end + else + if current == nil then + wml.error(string.format("[unit_status_semaphore]: reset failed to find original value for %s",status)) + else + wml.get_child(unit, "status")[status] = current.original_value + wml.remove_child(statuses, status) + end + end + if #statuses == 0 then wml.remove_child(vars, "statuses") end + end + elseif action == "get_count" then + local variable = cfg.variable or wml.error("[unit_status_semaphore]: get_count requires variable=") + wml.variables[variable] = current.count + elseif action == "get_original" then + local variable = cfg.variable or wml.error("[unit_status_semaphore]: get_original requires variable=") + wml.variables[variable] = current.original_value + elseif action == "incr" then + if current == nil or current.count == nil or current.count == 0 then + current.count = 1 + current.original_value = wml.get_child(unit, "status")[status] + wml.get_child(unit, "status")[status] = true + else + current.count = current.count + 1 + end + if statuses == nil then + statuses = {} + table.insert(statuses, { status, current } ) + table.insert(vars, { "statuses", statuses } ) + else + if not had_current then table.insert(statuses, { status, current } ) end + end + elseif action == "decr" then + if statuses == nil or current == nil or current.count == nil or current.count == 0 then + wml.error("[unit_status_semaphore]: Cannot decrement nil/0 value") + else + current.count = current.count - 1 + if current.count == 0 then + wml.get_child(unit, "status")[status] = current.original_value + wml.remove_child(statuses, status) + if #statuses == 0 then wml.remove_child(vars, "statuses") end + end + end + else + wml.error(string.format("[unit_status_semaphore]: Unknown action: %s", action)) + end + wesnoth.units.to_map(unit) +end