wesnoth/data/lua/wml/role.lua
2019-12-04 08:46:04 -05:00

112 lines
2.8 KiB
Lua

local utils = wesnoth.require "wml-utils"
function wesnoth.wml_actions.role(cfg)
-- role= and type= are handled differently than in other tags,
-- so we need to remove them from the filter
local role = cfg.role
local filter = wml.shallow_literal(cfg)
if role == nil then
wml.error("missing role= in [role]")
end
local types = {}
if cfg.type then
for _,value in ipairs(cfg.type:split()) do
table.insert(types, value:trim())
end
end
filter.role, filter.type = nil, nil
local search_map, search_recall, reassign = true, true, true
if cfg.search_recall_list == "only" then
search_map = false
elseif cfg.search_recall_list ~= nil then
search_recall = not not cfg.search_recall_list
end
if cfg.reassign ~= nil then
reassign = not not cfg.reassign
end
-- pre-build a new [recall] from the [auto_recall]
-- copy only recall-specific attributes, no SUF at all
-- the SUF will be id= which we will add in a moment
-- keep this in sync with the C++ recall function!!!
local recall = nil
local child = wml.get_child(cfg, "auto_recall")
if child ~= nil then
if wml.get_nth_child(cfg, "auto_recall", 2) ~= nil then
wesnoth.log("debug", "More than one [auto_recall] found within [role]", true)
end
local original = wml.shallow_literal(child)
recall = {}
recall.x = original.x
recall.y = original.y
recall.location_id = original.location_id
recall.show = original.show
recall.fire_event = original.fire_event
recall.check_passability = original.check_passability
recall.facing = original.facing
end
if not reassign then
if search_map then
local unit = wesnoth.units.find_on_map{role=role}[1]
if unit then
return
end
end
if recall and search_recall then
local unit = wesnoth.units.find_on_recall{role=role}[1]
if unit then
recall.id = unit.id
wesnoth.wml_actions.recall(recall)
return
end
end
end
if search_map then
-- first attempt to match units on the map
local i = 1
repeat
-- give precedence based on the order specified in type=
if #types > 0 then
filter.type = types[i]
end
local unit = wesnoth.units.find_on_map(filter)[1]
if unit then
unit.role = role
return
end
i = i + 1
until #types == 0 or i > #types
end
if search_recall then
-- then try to match units on the recall lists
local i = 1
repeat
if #types > 0 then
filter.type = types[i]
end
local unit = wesnoth.units.find_on_recall(filter)[1]
if unit then
unit.role = role
if recall then
recall.id = unit.id
wesnoth.wml_actions.recall(recall)
end
return
end
i = i + 1
until #types == 0 or i > #types
end
-- no matching unit found, try the [else] tags
for else_child in wml.child_range(cfg, "else") do
local action = utils.handle_event_commands(else_child, "conditional")
if action ~= "none" then return end
end
end