
This also tweaks the animator:add() API, replacing the facing key with a target key and requiring it to be an adjacent location.
115 lines
No EOL
3.2 KiB
Lua
115 lines
No EOL
3.2 KiB
Lua
local helper = wesnoth.require "lua/helper.lua"
|
|
local T = helper.set_wml_tag_metatable{}
|
|
|
|
local function get_fake_attack(unit, cfg)
|
|
-- This hacky-looking code is because the only way to create an
|
|
-- attack object in Lua is by adding the attack to a unit.
|
|
-- In this case, it's immediately deleted afterwards.
|
|
local n = #unit.attacks + 1
|
|
unit.attacks[n] = cfg
|
|
local atk = unit.attacks[n]
|
|
unit.attacks[n] = nil
|
|
return atk
|
|
end
|
|
|
|
local function get_real_attack(unit, filter)
|
|
for i, atk in ipairs(unit.attacks) do
|
|
if atk:matches(filter) then return atk end
|
|
end
|
|
end
|
|
|
|
local function add_animation(anim, cfg)
|
|
cfg = helper.shallow_parsed(cfg)
|
|
local filter = helper.get_child(cfg, "filter")
|
|
local unit
|
|
if filter then
|
|
unit = wesnoth.get_units{
|
|
limit = 1,
|
|
T["and"](filter)
|
|
}[1]
|
|
else
|
|
unit = wesnoth.get_unit(
|
|
wesnoth.current.event_context.x1,
|
|
wesnoth.current.event_context.y1
|
|
)
|
|
end
|
|
|
|
if unit and not wesnoth.is_fogged(wesnoth.current.side, unit.x, unit.y) then
|
|
local primary = helper.get_child(cfg, "primary_attack")
|
|
local secondary = helper.get_child(cfg, "secondary_attack")
|
|
local get_attack = get_real_attack
|
|
if cfg.flag == "death" or cfg.flag == "victory" then
|
|
-- death and victory animations need a special case
|
|
-- In order to correctly fire certain animations, a dummy attack
|
|
-- is required. This is especially evident in Wose death animations.
|
|
get_attack = get_fake_attack
|
|
end
|
|
if primary then
|
|
primary = get_attack(unit, primary)
|
|
end
|
|
if secondary then
|
|
secondary = get_attack(unit, secondary)
|
|
end
|
|
|
|
local hits = cfg.hits
|
|
if hits == true or hits == nil then
|
|
hits = 'hit'
|
|
elseif hits == false then
|
|
hits = 'miss'
|
|
end
|
|
|
|
local color = {0xff, 0xff, 0xff}
|
|
if cfg.red or cfg.green or cfg.blue then
|
|
-- This tonumber() or 0 is to ensure they're all definitely numbers
|
|
-- It works because tonumber() returns nil if its argument is not a number
|
|
color = {
|
|
tonumber(cfg.red) or 0,
|
|
tonumber(cfg.green) or 0,
|
|
tonumber(cfg.blue) or 0
|
|
}
|
|
end
|
|
|
|
-- TODO: The last argument is currently unused
|
|
-- (should make the game not scroll if view locked or prefs disables it)
|
|
wesnoth.scroll_to_tile(unit.x, unit.y, true, false, true, false)
|
|
|
|
local facing = helper.get_child(cfg, "facing")
|
|
if facing then
|
|
local facing_loc = wesnoth.get_locations(facing)[1]
|
|
if facing_loc then
|
|
local dir = wesnoth.map_location.get_relative_dir(unit.x, unit.y, facing_loc[1], facing_loc[2])
|
|
unit.facing = dir
|
|
facing = wesnoth.map_location.get_direction(unit.x, unit.y, dir)
|
|
else
|
|
facing = nil
|
|
end
|
|
end
|
|
|
|
local text = cfg.text
|
|
if cfg.female_text and unit.gender == 'female' then
|
|
text = cfg.female_text
|
|
elseif cfg.male_text and unit.gender == 'male' then
|
|
text = cfg.male_text
|
|
end
|
|
|
|
anim:add(unit, cfg.flag, hits, {
|
|
target = facing,
|
|
value = {tonumber(cfg.value) or 0, tonumber(cfg.value_second) or 0},
|
|
with_bars = not not cfg.with_bars,
|
|
text = text,
|
|
color = color,
|
|
primary = primary,
|
|
secondary = secondary
|
|
})
|
|
end
|
|
|
|
for c in helper.child_range(cfg, "animate") do
|
|
add_animation(anim, c)
|
|
end
|
|
end
|
|
|
|
function wesnoth.wml_actions.animate_unit(cfg)
|
|
local anim = wesnoth.create_animator()
|
|
add_animation(anim, cfg)
|
|
anim:run()
|
|
end |