wesnoth/data/lua/diversion.lua
2023-10-14 19:26:36 -04:00

101 lines
3.5 KiB
Lua

local _ = wesnoth.textdomain 'wesnoth-help'
local T = wml.tag
local u_pos_filter = function(u_id)
local output = "initial"
local hex_dirs = {"n", "ne", "se", "s", "sw", "nw"}
local diversion_unit = wesnoth.units.get(u_id)
if not diversion_unit then
return nil
end
for i, dir in ipairs(hex_dirs) do
if diversion_unit:matches {
id = u_id,
T.filter_adjacent {
is_enemy = "yes",
adjacent = dir,
formula = "self.hitpoints > 0",
T.filter_adjacent {
is_enemy = "yes",
adjacent = dir,
formula = "self.hitpoints > 0"
}
}
} then
output = "diverter"
break
end
end
if output ~= "initial" then
return output
else
-- either nothing passed filter, or there was an error
return nil
end
end
local function status_anim_update(is_undo)
local ec = wesnoth.current.event_context
local changed_something = false
if not ec.x1 or not ec.y1 then
return
end
-- find all units on map with ability = diversion but not status.diversion = true
local div_candidates = wesnoth.units.find_on_map({
ability = "diversion",
{"not", { status = "diversion" }}
})
-- for those that pass the filter now, change status and fire animation
for index, ec_unit in ipairs(div_candidates) do
local filter_result = u_pos_filter(ec_unit.id)
if filter_result then
changed_something = true
ec_unit.status.diversion = true
ec_unit:extract()
ec_unit:to_map(false)
wesnoth.wml_actions.animate_unit {
flag = "launching",
with_bars = true,
T.filter { id = ec_unit.id }
}
end
end
-- find all units on map with ability = diversion and status.diversion = true
local stop_candidates = wesnoth.units.find_on_map({
ability = "diversion",
status = "diversion"
})
-- for those that fail the filter now, change status and fire animation
for index, ec_unit in ipairs(stop_candidates) do
local filter_result = u_pos_filter(ec_unit.id)
if not filter_result then
changed_something = true
ec_unit.status.diversion = false
ec_unit:extract()
ec_unit:to_map(false)
wesnoth.wml_actions.animate_unit {
flag = "landing",
with_bars = true,
T.filter { id = ec_unit.id }
}
end
end
if not is_undo then
wesnoth.experimental.game_events.set_undoable(true)
if changed_something then
wesnoth.experimental.game_events.add_undo_actions(function(_)
status_anim_update(true)
end)
end
end
end
wesnoth.game_events.add_repeating("moveto, die, recruit, recall", function(_)
status_anim_update(false)
end)