68 lines
3.0 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.

--- @alias SpellTarget "any" Любой тайл
--- | "caster" Сам кастующий
--- | "enemy" Противники
--- | "ally" Союзники
--- | "character" Любой персонаж
--- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell
--- @field tag string
--- @field baseCost integer Базовые затраты маны на каст
--- @field baseCooldown integer Базовый кулдаун в ходах
--- @field possibleTarget SpellTarget Возможная цель
--- @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.possibleTarget = "any"
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, possibleTarget: SpellTarget, 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,
possibleTarget = data.possibleTarget,
distance = data.distance
}
function newSpell:cast(caster, target)
-- проверка корректности цели
--- @TODO имплементировать все варианты SpellTarget
-- проверка на расстояние до цели
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 caster:try(Tree.behaviors.stats, function(stats)
return stats.mana < self.baseCost
end) then
return
end
return data.onCast(caster, target)
end
return setmetatable(newSpell, spell)
end
return spell