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)
-- проверка на расстояние до цели
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 not self.targetQuery:intersect(Query(targetTest.distance(self.distance))).test(caster, target) then return end -- проверка корректности цели
-- проверка на достаточное количество маны
if caster:try(Tree.behaviors.stats, function(stats)

View File

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

View File

@ -1,13 +1,28 @@
--- @alias SpellTargetTest fun(caster: Character, targetPosition: Vec3) : boolean
return {
-- любой тайл
any = function() return true end,
-- тайл, где находится кастующий
caster = function(caster, targetPosition)
local targetCharacterId = Tree.level.characterGrid:get(targetPosition)
return caster.id == targetCharacterId
end,
-- тайл, где находится любой персонаж
character = function(caster, targetPosition)
local targetCharacterId = Tree.level.characterGrid:get(targetPosition)
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
}