diff --git a/changelog b/changelog index f2a7884a0e636..5eb1ad133f913 100644 --- a/changelog +++ b/changelog @@ -29,6 +29,8 @@ Version 1.13.6+dev: * WML Engine: * Removed LOW_MEM option when building. * Add color= attribute to [floating_text] + * New ability_type key in standard unit filters matches if the unit has any + ability of the specified type (tag name). Version 1.13.6: * AI: diff --git a/data/lua/wml-tags.lua b/data/lua/wml-tags.lua index 57ab588c3a766..19934418c4b50 100644 --- a/data/lua/wml-tags.lua +++ b/data/lua/wml-tags.lua @@ -632,7 +632,67 @@ function wml_actions.unpetrify(cfg) end function wml_actions.heal_unit(cfg) - wesnoth.heal_unit(cfg) + local healers = helper.get_child("filter_second") + if healers then + healers = wesnoth.get_units{ + ability_type = "heals", + T["and"](healers) + } + else + healers = {} + end + + local who = helper.get_child("filter") + if who then + who = wesnoth.get_units(who) + else + who = wesnoth.get_units{ + x = wesnoth.current.event_context.x1, + y = wesnoth.current.event_context.y1 + } + end + + local heal_full = cfg.amount == "full" + local moves_full = cfg.moves == "full" + local heal_amount_set = false + for i,u in ipairs(who) do + local heal_amount = u.max_hitpoints - u.hitpoints + if heal_full then + u.hitpoints = u.max_hitpoints + else + heal_amount = math.min(math.max(1, cfg.amount), heal_amount) + u.hitpoints = u.hitpoints + heal_amount + end + + if moves_full then + u.moves = u.max_moves + else + u.moves = math.min(u.max_moves, u.moves + (cfg.moves or 0)) + end + + if cfg.restore_attacks then + u.attacks_left = u.max_attacks + end + + if cfg.restore_statuses then + u.status.poisoned = false + u.status.petrified = false + u.status.slowed = false + u.status.unhealable = false + end + + if ~heal_amount_set then + heal_amount_set = true + wesnoth.set_variable("heal_amount", heal_amount) + end + + if cfg.animate then + wesnoth.animate_unit{ + T.filter(healers), + flag = "healing" + } + end + end end function wml_actions.transform_unit(cfg) diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index e2d65eabee4ca..5c0b97dd2e1fc 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -1790,88 +1790,6 @@ int game_lua_kernel::intf_find_cost_map(lua_State *L) return 1; } -int game_lua_kernel::intf_heal_unit(lua_State *L) -{ - vconfig cfg(luaW_checkvconfig(L, 1)); - - const game_events::queued_event &event_info = get_event_info(); - - unit_map & temp = units(); - unit_map* units = & temp; - - const vconfig & healers_filter = cfg.child("filter_second"); - std::vector healers; - if (!healers_filter.null()) { - const unit_filter ufilt(healers_filter, &game_state_); - for (unit& u : *units) { - if ( ufilt(u) && u.has_ability_type("heals") ) { - healers.push_back(&u); - } - } - } - - const config::attribute_value amount = cfg["amount"]; - const config::attribute_value moves = cfg["moves"]; - const bool restore_attacks = cfg["restore_attacks"].to_bool(false); - const bool restore_statuses = cfg["restore_statuses"].to_bool(true); - const bool animate = cfg["animate"].to_bool(false); - - const vconfig & healed_filter = cfg.child("filter"); - bool only_unit_at_loc1 = healed_filter.null(); - bool heal_amount_to_set = true; - - const unit_filter ufilt(healed_filter, &game_state_); - for(unit_map::unit_iterator u = units->begin(); u != units->end(); ++u) { - if (only_unit_at_loc1) - { - u = units->find(event_info.loc1); - if(!u.valid()) return 0; - } - else if ( !ufilt(*u) ) continue; - - int heal_amount = u->max_hitpoints() - u->hitpoints(); - if(amount.blank() || amount == "full") u->set_hitpoints(u->max_hitpoints()); - else { - heal_amount = lexical_cast_default (amount, heal_amount); - const int new_hitpoints = std::max(1, std::min(u->max_hitpoints(), u->hitpoints() + heal_amount)); - heal_amount = new_hitpoints - u->hitpoints(); - u->set_hitpoints(new_hitpoints); - } - - if(!moves.blank()) { - if(moves == "full") u->set_movement(u->total_movement()); - else { - // set_movement doesn't set below 0 - u->set_movement(std::min( - u->total_movement(), - u->movement_left() + lexical_cast_default (moves, 0) - )); - } - } - - if(restore_attacks) u->set_attacks(u->max_attacks()); - - if(restore_statuses) - { - u->set_state(unit::STATE_POISONED, false); - u->set_state(unit::STATE_SLOWED, false); - u->set_state(unit::STATE_PETRIFIED, false); - u->set_state(unit::STATE_UNHEALABLE, false); - u->anim_comp().set_standing(); - } - - if (heal_amount_to_set) - { - heal_amount_to_set = false; - gamedata().get_variable("heal_amount") = heal_amount; - } - - if(animate) unit_display::unit_healing(*u, healers, heal_amount); - if(only_unit_at_loc1) return 0; - } - return 0; -} - int game_lua_kernel::intf_print(lua_State *L) { vconfig cfg(luaW_checkvconfig(L, 1)); @@ -4025,7 +3943,6 @@ game_lua_kernel::game_lua_kernel(game_state & gs, play_controller & pc, reports { "get_villages", &dispatch<&game_lua_kernel::intf_get_villages > }, { "get_village_owner", &dispatch<&game_lua_kernel::intf_get_village_owner > }, { "get_displayed_unit", &dispatch<&game_lua_kernel::intf_get_displayed_unit > }, - { "heal_unit", &dispatch<&game_lua_kernel::intf_heal_unit > }, { "highlight_hex", &dispatch<&game_lua_kernel::intf_highlight_hex > }, { "is_enemy", &dispatch<&game_lua_kernel::intf_is_enemy > }, { "kill", &dispatch<&game_lua_kernel::intf_kill > }, diff --git a/src/units/filter.cpp b/src/units/filter.cpp index 99bca5c6d244c..698d0622cc8fb 100644 --- a/src/units/filter.cpp +++ b/src/units/filter.cpp @@ -377,6 +377,19 @@ bool basic_unit_filter_impl::internal_matches_filter(const unit & u, const map_l if (!match) return false; } + if (!vcfg["ability_type"].empty()) + { + bool match = false; + + for (const std::string& ability : utils::split(vcfg["ability_type"])) { + if (u.has_ability_type(ability)) { + match = true; + break; + } + } + if (!match) return false; + } + if (!vcfg["race"].empty()) { std::vector races = utils::split(vcfg["race"]); if (std::find(races.begin(), races.end(), u.race()->id()) == races.end()) {