116 lines
4 KiB
Lua
116 lines
4 KiB
Lua
local location_set = wesnoth.require "location_set"
|
|
|
|
local kill_recursion_preventer = location_set.create()
|
|
|
|
function wesnoth.wml_actions.kill(cfg)
|
|
if wml.get_child(cfg, "filter") then
|
|
wml.error "Tag [filter] may not be used in [kill]"
|
|
end
|
|
|
|
local number_killed = 0
|
|
local secondary_unit = wml.get_child(cfg, "secondary_unit")
|
|
local killer_loc = {0, 0}
|
|
if secondary_unit then
|
|
secondary_unit = wesnoth.units.find_on_map(secondary_unit)[1]
|
|
if cfg.fire_event then
|
|
if secondary_unit then
|
|
killer_loc = { x = tonumber(secondary_unit.x) or 0, y = tonumber(secondary_unit.y) or 0 }
|
|
else
|
|
wesnoth.log("warn", "failed to match [secondary_unit] in [kill] with a single on-board unit")
|
|
end
|
|
end
|
|
end
|
|
local dead_men_walking = wesnoth.units.find_on_map(cfg)
|
|
for i,unit in ipairs(dead_men_walking) do
|
|
unit.hitpoints = 0
|
|
local death_loc = {x = tonumber(unit.x) or 0, y = tonumber(unit.y) or 0}
|
|
if not secondary_unit then killer_loc = death_loc end
|
|
local can_fire = false
|
|
|
|
local recursion = (kill_recursion_preventer:get(death_loc.x, death_loc.y) or 0) + 1
|
|
if cfg.fire_event then
|
|
kill_recursion_preventer:insert(death_loc.x, death_loc.y, recursion)
|
|
can_fire = true
|
|
if death_loc.x == wesnoth.current.event_context.x1 and death_loc.y == wesnoth.current.event_context.y1 then
|
|
if wesnoth.current.event_context.name == "die" or wesnoth.current.event_context.name == "last breath" then
|
|
if recursion >= 10 then
|
|
can_fire = false;
|
|
wesnoth.log("error", "tried to fire 'die' or 'last breath' event "
|
|
.. "on unit from the unit's 'die' or 'last breath' event "
|
|
.. "with first_time_only=no!")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if can_fire then
|
|
wesnoth.game_events.fire("last breath", death_loc, killer_loc)
|
|
end
|
|
if cfg.animate and unit.valid == "map" then
|
|
wesnoth.interface.scroll_to_hex(death_loc, true)
|
|
local anim = wesnoth.units.create_animator()
|
|
local primary = wml.get_child(cfg, "primary_attack")
|
|
local secondary = wml.get_child(cfg, "secondary_attack")
|
|
-- Yes, we get the primary attack from the secondary unit and vice versa
|
|
-- The primary attack in a death animation is the weapon that caused the death
|
|
-- In other words, the attacker's weapon. The attacker is the secondary unit.
|
|
-- In the victory animation, this is simply swapped.
|
|
if primary then
|
|
local found_attack = nil
|
|
if secondary_unit then
|
|
found_attack = secondary_unit:find_attack(primary)
|
|
end
|
|
if found_attack then
|
|
primary = found_attack
|
|
else
|
|
primary = wesnoth.units.create_weapon(primary)
|
|
end
|
|
wesnoth.log('info', "Primary weapon:\n" .. wml.tostring(primary.__cfg))
|
|
end
|
|
if secondary then
|
|
local found_weapon = nil
|
|
if primary then
|
|
found_weapon = unit:find_attack(secondary)
|
|
end
|
|
if found_weapon then
|
|
secondary = found_weapon
|
|
else
|
|
secondary = wesnoth.units.create_weapon(secondary)
|
|
end
|
|
wesnoth.log('info', "Secondary weapon:\n" .. wml.tostring(secondary.__cfg))
|
|
end
|
|
anim:add(unit, "death", "kill", {primary = primary, secondary = secondary})
|
|
if secondary_unit then
|
|
anim:add(secondary_unit, "victory", "kill", {primary = secondary, secondary = primary})
|
|
end
|
|
anim:run()
|
|
end
|
|
-- wesnoth.wml_actions.redraw{}
|
|
|
|
if can_fire then
|
|
wesnoth.game_events.fire("die", death_loc, killer_loc)
|
|
end
|
|
if cfg.fire_event then
|
|
if recursion <= 1 then
|
|
kill_recursion_preventer:remove(death_loc.x, death_loc.y)
|
|
else
|
|
kill_recursion_preventer:insert(death_loc.x, death_loc.y, recursion)
|
|
end
|
|
end
|
|
-- Test that it's valid (and still on the map) first, in case the event erased (or extracted) it.
|
|
if unit.valid == "map" then unit:erase() end
|
|
|
|
-- wesnoth.wml_actions.redraw{}
|
|
|
|
number_killed = number_killed + 1
|
|
end
|
|
|
|
if (cfg.x == "recall" or cfg.x == nil) and (cfg.y == "recall" or cfg.y == nil) then
|
|
local dead_men_sleeping = wesnoth.units.find_on_recall(cfg)
|
|
for i,unit in ipairs(dead_men_sleeping) do
|
|
unit:erase()
|
|
end
|
|
number_killed = number_killed + #dead_men_sleeping
|
|
end
|
|
|
|
return number_killed
|
|
end
|