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

64 lines
2.7 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local Query = require "lib.spell.target_query"
local targetTest = require "lib.spell.target_test"
--- @alias SpellPreview "default" Подсветка возможных целей
--- | "path" Подсветка пути до цели
--- @class Spell
--- @field tag string
--- @field baseCost integer Базовые затраты маны на каст
--- @field baseCooldown integer Базовый кулдаун в ходах
--- @field targetQuery SpellTargetQuery Селектор возможных целей
--- @field previewType SpellPreview Вид превью во время каста
--- @field distance? integer Сторона квадрата с центром в позиции кастера, в пределах которого должна находиться цель, либо отсутствие ограничения
--- @field update fun(self: Spell, caster: Character, dt: number): nil Изменяет состояние спелла
--- @field draw fun(self: Spell): nil Рисует превью каста, ничего не должна изменять в идеальном мире
--- @field cast fun(self: Spell, caster: Character, target: Vec3): Task<nil> | nil Вызывается в момент каста, изменяет мир.
local spell = {}
spell.__index = spell
spell.tag = "spell_base"
spell.baseCost = 1
spell.baseCooldown = 1
spell.targetQuery = Query(targetTest.any)
spell.previewType = "default"
function spell:update(caster, dt) end
function spell:draw() end
function spell:cast(caster, target) return end
--- Конструктор [Spell]
--- @param data {tag: string, baseCost: integer, baseCooldown: integer, targetQuery: SpellTargetQuery, distance: integer?, onCast: fun(caster: Character, target: Vec3): Task}
--- @return Spell
function spell.new(data)
local newSpell = {
tag = data.tag,
baseCost = data.baseCost,
baseCooldown = data.baseCooldown,
targetQuery = data.targetQuery,
distance = data.distance
}
function newSpell:cast(caster, target)
if not self.targetQuery:intersect(Query(targetTest.distance(self.distance))).test(caster, target) then return end -- проверка корректности цели
-- проверка на достаточное количество маны
if caster:try(Tree.behaviors.stats, function(stats)
return stats.mana < self.baseCost
end) then
return
end
caster:try(Tree.behaviors.stats, function(stats)
stats.mana = stats.mana - self.baseCost
end)
return data.onCast(caster, target)
end
return setmetatable(newSpell, spell)
end
return spell