require 'lib.utils.vec3' --- @alias Id integer --- @type Id local characterId = 1 --- @class Character --- @field id Id --- @field behaviors Behavior[] --- @field _behaviorsIdx {string: integer} 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.animated.new(spriteDir), Tree.behaviors.spellcaster.new() } 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 --- Если у персонажа есть поведение [behavior], применяет к нему [fn] --- --- Дальше meme для интеллектуалов --- --- *Я: мам купи мне >>=* --- --- *Мама: у нас дома есть >>=* --- --- *Дома:* --- @generic T : Behavior --- @generic V --- @param behavior T --- @param fn fun(behavior: T) : V | nil --- @return V | nil function character:try(behavior, fn) local b = self:has(behavior) if not b then return end return fn(b) end --- usage: --- addBehavior( {logic.new(), graphics.new(), ...} ) --- --- or you may chain this if you are a wannabe haskell kiddo --- @param behaviors Behavior[] --- @return Character | nil function character:addBehavior(behaviors) for _, b in ipairs(behaviors) do if b.dependencies then for _, dep in ipairs(b.dependencies) do if not self:has(dep) then return print("[Character]: cannot add \"" .. b.id .. "\" for a character (Id = " .. self.id .. "): needs \"" .. dep.id .. "\"!") end end end b.owner = self table.insert(self.behaviors, b) self._behaviorsIdx[b.id] = #self.behaviors end return self end function character:update(dt) for _, b in ipairs(self.behaviors) do if b.update then b:update(dt) end end end function character:draw() for _, b in ipairs(self.behaviors) do if b.draw then b:draw() end end end return { spawn = spawn }