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
This commit is contained in:
PeaAshMeter 2026-03-18 02:01:59 +03:00
parent ef5ff5f847
commit a6578ec8dd
3 changed files with 19 additions and 13 deletions

View File

@ -41,16 +41,7 @@ function spell.new(data)
} }
function newSpell:cast(caster, target) function newSpell:cast(caster, target)
-- проверка на расстояние до цели if not self.targetQuery:intersect(Query(targetTest.distance(self.distance))).test(caster, target) then return end -- проверка корректности цели
if self.distance and caster:try(Tree.behaviors.positioned, function(p)
local dist = math.max(math.abs(p.position.x - target.x), math.abs(p.position.y - target.y))
print("dist:", dist)
return dist > self.distance
end) then
return
end
if not self.targetQuery.test(caster, target) then return end -- проверка корректности цели
-- проверка на достаточное количество маны -- проверка на достаточное количество маны
if caster:try(Tree.behaviors.stats, function(stats) if caster:try(Tree.behaviors.stats, function(stats)

View File

@ -19,7 +19,7 @@ function query:join(q)
test = function(caster, pos) test = function(caster, pos)
return self.test(caster, pos) or q.test(caster, pos) return self.test(caster, pos) or q.test(caster, pos)
end end
}, q) }, query)
end end
--- Пересечение --- Пересечение
@ -29,7 +29,7 @@ function query:intersect(q)
test = function(caster, pos) test = function(caster, pos)
return self.test(caster, pos) and q.test(caster, pos) return self.test(caster, pos) and q.test(caster, pos)
end end
}, q) }, query)
end end
--- Исключение (не коммутативное, "те, что есть в query, но нет в q") --- Исключение (не коммутативное, "те, что есть в query, но нет в q")
@ -39,7 +39,7 @@ function query:exclude(q)
test = function(caster, pos) test = function(caster, pos)
return self.test(caster, pos) and not q.test(caster, pos) return self.test(caster, pos) and not q.test(caster, pos)
end end
}, q) }, query)
end end
--- Находит все соответствующие условиям координаты тайлов и возвращает их в виде списка --- Находит все соответствующие условиям координаты тайлов и возвращает их в виде списка

View File

@ -1,13 +1,28 @@
--- @alias SpellTargetTest fun(caster: Character, targetPosition: Vec3) : boolean --- @alias SpellTargetTest fun(caster: Character, targetPosition: Vec3) : boolean
return { return {
-- любой тайл
any = function() return true end, any = function() return true end,
-- тайл, где находится кастующий
caster = function(caster, targetPosition) caster = function(caster, targetPosition)
local targetCharacterId = Tree.level.characterGrid:get(targetPosition) local targetCharacterId = Tree.level.characterGrid:get(targetPosition)
return caster.id == targetCharacterId return caster.id == targetCharacterId
end, end,
-- тайл, где находится любой персонаж
character = function(caster, targetPosition) character = function(caster, targetPosition)
local targetCharacterId = Tree.level.characterGrid:get(targetPosition) local targetCharacterId = Tree.level.characterGrid:get(targetPosition)
return not not targetCharacterId return not not targetCharacterId
end,
-- тайл в пределах окружности в нашей кривой метрике
--- @param radius number
distance = function(radius)
return function(caster, targetPosition)
return caster:try(Tree.behaviors.positioned, function(p)
local dist = math.max(math.abs(p.position.x - targetPosition.x),
math.abs(p.position.y - targetPosition.y))
print("dist:", dist)
return dist <= radius
end)
end
end end
} }