120 lines
3.9 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.

require 'lib.utils.vec3'
--- @alias CharacterState "idle"|"run"|"attack"|"hurt"
--- @alias Id integer
--- @type Id
local characterId = 1
--- @todo Композиция лучше наследования, но не до такой же степени! Надо отрефакторить и избавиться от сотни полей в таблице
--- @class Character
--- @field id Id
--- @field behaviors Behavior[]
--- @field _behaviorsIdx {string: integer}
--- @field spellbook Spell[] собственный набор спеллов персонажа
--- @field cast Spell | nil ссылка на активный спелл из спеллбука
local character = {}
character.__index = character
--- Создаёт персонажа, которым будет управлять или игрок или компьютер
--- @param name string
--- @param template ClassTemplate
--- @param spriteDir table
--- @param position? Vec3
--- @param size? Vec3
--- @param level? integer
local function spawn(name, template, spriteDir, position, size, level)
local char = {}
char = setmetatable(char, character)
char.id = characterId
characterId = characterId + 1
char.behaviors = {}
char._behaviorsIdx = {}
char:addBehavior {
Tree.behaviors.map.new(position, size),
Tree.behaviors.render.new(spriteDir),
}
char:setState("idle") --- @todo сделать это отдельным модулем
local spb = require "lib.spellbook" --- @todo это тоже
char.spellbook = spb.of { spb.walk }
Tree.level.characters[char.id] = char
return char
end
--- Проверяет, есть ли у персонажа поведение [behavior].
--- @generic T : Behavior
--- @param behavior T
--- @return T | nil
function character:has(behavior)
--- @cast behavior Behavior
local idx = self._behaviorsIdx[behavior.id]
if not idx then return nil end
return self.behaviors[idx] or nil
end
--- usage:
--- addModules( {logic = logic.new(), graphics = graphics.new(), ...} )
---
--- or you may chain this if you are a wannabe haskell kiddo
function character:addBehavior(modules)
for _, module in ipairs(modules) do
if module.dependencies then
for _, dep in ipairs(module.dependencies) do
if not self:has(dep) then
return print("[Character]: cannot add \"" .. module.id ..
"\" for a character (Id = " .. self.id .. "): needs \"" .. dep.id .. "\"!")
end
end
end
module.owner = self
table.insert(self.behaviors, module)
self._behaviorsIdx[module.id] = #self.behaviors
end
return self
end
--- геттеры и сеттеры для "внешних" данных
--- забей, это в поведения
--- @deprecated
--- @return CharacterState
function character:getState()
return self.state or "idle"
end
--- @param state CharacterState
--- @deprecated
function character:setState(state) --- @todo это вообще должно быть отдельное поведение
self.state = state
self:has(Tree.behaviors.render).animation:setState(state, (state ~= "idle" and state ~= "run") and function()
self:setState("idle")
end or nil)
end
--- @param path Deque
function character:followPath(path)
self:has(Tree.behaviors.map):followPath(path)
end
function character:update(dt)
--- @todo ну ты понел
-- for _, b in ipairs(self.behaviors) do
-- if b.update then b:update(dt) end
-- end
self:has(Tree.behaviors.map):update(dt)
if self.cast then self.cast:update(self, dt) end
self:has(Tree.behaviors.render):update(dt)
end
function character:draw()
for _, b in ipairs(self.behaviors) do
if b.draw then b:draw() end
end
if self.cast then self.cast:draw() end --- @todo 🤡
end
return { spawn = spawn }