From 0e21864bbc0aa4edf08809b6da54a559064881ed Mon Sep 17 00:00:00 2001 From: newfrenchy83 Date: Mon, 8 Jul 2024 14:47:16 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20=E2=80=9Cfilter=5Fadjacent=5Flocation?= =?UTF-8?q?=E2=80=9D=20not=20working=20in=20ability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not a stricto sensus repair since in this configuration [filter_adjacent_location] will have to be encoded inside a [filter] filter, but the advantage is to generalize the use of this sub-filter to events and others, in addition to having a functional version for the abilities. I don't know if @stevecotton will succeed in repairing the current filter and I therefore propose an alternative. --- data/schema/filters/unit.cfg | 1 + src/units/filter.cpp | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/data/schema/filters/unit.cfg b/data/schema/filters/unit.cfg index 1893453764088..87d07554f6868 100644 --- a/data/schema/filters/unit.cfg +++ b/data/schema/filters/unit.cfg @@ -45,6 +45,7 @@ {FILTER_TAG "has_attack" weapon ()} {FILTER_TAG "filter_vision" vision ()} {FILTER_TAG "filter_adjacent" adjacent ()} + {FILTER_TAG "filter_adjacent_location" adjacent_location ()} {FILTER_TAG "filter_location" location ()} {FILTER_TAG "filter_side" side ()} {FILTER_TAG "experimental_filter_ability" abilities ()} diff --git a/src/units/filter.cpp b/src/units/filter.cpp index c2dfb3439ad97..0f75402947204 100644 --- a/src/units/filter.cpp +++ b/src/units/filter.cpp @@ -158,6 +158,43 @@ struct unit_filter_adjacent : public unit_filter_base const vconfig cfg_; }; +struct unit_filter_adjacent_location : public unit_filter_base +{ + unit_filter_adjacent_location(const vconfig& cfg) + : child_(cfg) + , cfg_(cfg) + { + } + + virtual bool matches(const unit_filter_args& args) const override + { + terrain_filter adj_filter(cfg_, resources::filter_con, false); + const auto adjacent = get_adjacent_tiles(args.loc); + int match_count=0; + + config::attribute_value i_adjacent = cfg_["adjacent"]; + std::vector dirs; + if (i_adjacent.empty()) { + dirs = map_location::all_directions(); + } else { + dirs = map_location::parse_directions(i_adjacent); + } + for (map_location::direction dir : dirs) { + if(!adj_filter.match(adjacent[static_cast(dir)])) { + continue; + } + ++match_count; + } + + static std::vector> default_counts = utils::parse_ranges_unsigned("1-6"); + config::attribute_value i_count = cfg_["count"]; + return in_ranges(match_count, !i_count.blank() ? utils::parse_ranges_unsigned(i_count) : default_counts); + } + + const unit_filter_compound child_; + const vconfig cfg_; +}; + template struct unit_filter_child_literal : public unit_filter_base @@ -764,6 +801,9 @@ void unit_filter_compound::fill(vconfig cfg) else if (child.first == "filter_adjacent") { children_.emplace_back(new unit_filter_adjacent(child.second)); } + else if (child.first == "filter_adjacent_location") { + children_.emplace_back(new unit_filter_adjacent_location(child.second)); + } else if (child.first == "filter_location") { create_child(child.second, [](const vconfig& c, const unit_filter_args& args) { return terrain_filter(c, args.fc, args.use_flat_tod).match(args.loc);