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 Вызывается в момент каста, изменяет мир. 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 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) 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