local AnimationNode = require "lib.animation_node" local easing = require "lib.utils.easing" local function closestCharacter(char) local caster = Vec3 {} char:try(Tree.behaviors.positioned, function(b) caster = b.position end) local charTarget local minDist = 88005553535 -- spooky magic number for k, v in pairs(Tree.level.characters) do v:try(Tree.behaviors.positioned, function(b) local dist = ((caster.x - b.position.x) ^ 2 + (caster.y - b.position.y) ^ 2) ^ 0.5 if dist < minDist and dist ~= 0 then minDist = dist charTarget = v end -- print(k, b.position) end) end return charTarget end ---@type {[Class]: fun(self): Task} возможно где-то здесь на объявлении типа сломается типизация local aiNature = { ["dev_warrior"] = function(self) return function(callback) -- почему так, описано в Task self.owner:try(Tree.behaviors.spellcaster, function(spellB) local charTarget = closestCharacter(self.owner) charTarget:try(Tree.behaviors.positioned, function(b) self.target = Vec3 { b.position.x, b.position.y + 1 } --- @todo тут захардкожено + 1, но мы должны как-то хитро определять с какой стороны обойти end) spellB.spellbook[1]:cast(self.owner, self.target)(function() -- здесь мы оказываемся после того, как сходили в первый раз print("[AI]: finished move 1") local newTarget = Vec3 { 1, 1 } -- поэтому позиция персонажа для нового каста пересчитается динамически spellB.spellbook[1]:cast(self.owner, newTarget)(function() print("[AI]: finished move 2") -- дергаем функцию после завершения хода callback() end) end) end) end end, ["dev_mage"] = function(self) return function(callback) print("etoh... bleh") callback() end end } --- @class AIBehavior : Behavior --- @field animationNode AnimationNode? --- @field target Vec3? local behavior = {} behavior.__index = behavior behavior.id = "ai" --- @param class Class function behavior.new(class) return setmetatable({ makeTurn = aiNature[class] }, behavior) end return behavior