heroes-of-nerevelon/lib/spell/target_query.lua
PeaAshMeter a6578ec8dd Refactor target distance check using query intersection
Replace manual distance check with combined targetQuery and
distance query intersection for cleaner spell targeting logic

Fix query combinators to correctly reference self in closures
2026-03-18 02:01:59 +03:00

68 lines
1.9 KiB
Lua

--- Тип, отвечающий за выбор и фильтрацию подходящих тайлов как цели спелла
--- теория множеств my beloved?
--- @class SpellTargetQuery
local query = {}
query.__index = query
--- Проверяет координаты на соответствие внутреннему условию
--- @param caster Character
--- @param position Vec3
--- @return boolean
function query.test(caster, position)
return true
end
--- Объединение
--- @param q SpellTargetQuery
function query:join(q)
return setmetatable({
test = function(caster, pos)
return self.test(caster, pos) or q.test(caster, pos)
end
}, query)
end
--- Пересечение
--- @param q SpellTargetQuery
function query:intersect(q)
return setmetatable({
test = function(caster, pos)
return self.test(caster, pos) and q.test(caster, pos)
end
}, query)
end
--- Исключение (не коммутативное, "те, что есть в query, но нет в q")
--- @param q SpellTargetQuery
function query:exclude(q)
return setmetatable({
test = function(caster, pos)
return self.test(caster, pos) and not q.test(caster, pos)
end
}, query)
end
--- Находит все соответствующие условиям координаты тайлов и возвращает их в виде списка
--- @param caster Character
--- @return Vec3[]
function query:asSet(caster)
--- @TODO: оптимизировать и брать не всю карту для выборки
local res = {}
for _, tile in pairs(Tree.level.tileGrid) do
if self.test(caster, tile.position) then
table.insert(res, tile.position)
end
end
return res
end
--- @param test SpellTargetTest
local function new(test)
return setmetatable({
test = test
}, query)
end
return new