From 3f694ccec9d29fef63b34e10757ad1288b5bfb8c Mon Sep 17 00:00:00 2001 From: neckrat Date: Sat, 24 Jan 2026 01:46:05 +0300 Subject: [PATCH] attempt to save our souls (callback hell my beloved) Co-authored-by: Ivan Yuriev --- lib/character/behaviors/ai.lua | 60 +++++++++++++++++++++++++--------- lib/level/selector.lua | 4 ++- lib/level/turn_order.lua | 5 +++ lib/spellbook.lua | 14 ++++---- main.lua | 2 +- 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/lib/character/behaviors/ai.lua b/lib/character/behaviors/ai.lua index fbd9fcf..20a3a83 100644 --- a/lib/character/behaviors/ai.lua +++ b/lib/character/behaviors/ai.lua @@ -22,6 +22,7 @@ end --- @class AIBehavior : Behavior --- @field animationNode AnimationNode? +--- @field target Vec3? local behavior = {} behavior.__index = behavior behavior.id = "ai" @@ -52,26 +53,53 @@ end function behavior:makeMove() self.owner:try(Tree.behaviors.spellcaster, function(spellB) - -- print('какещке') - self.animationNode = AnimationNode { - function(node) end, - onEnd = function() - -- print('kakeshke') - end, - children = { + 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):chain { + spellB.spellbook[1]:cast(self.owner, Vec3 { 10, 10 }):chain { AnimationNode { - function(node) - local charTarget = closestCharacter(self.owner) - local target - charTarget:try(Tree.behaviors.positioned, function(b) - target = Vec3 { b.position.x, b.position.y + 1 } --- @todo тут захардкожено + 1, но мы должны как-то хитро определять с какой стороны обойти - end) - spellB.spellbook[1]:cast(self.owner, target) + onEnd = function() + Tree.level.turnOrder:next() end } } - } - self.animationNode:run() + }:run() + + + + -- -- print('какещке') + -- self.animationNode = AnimationNode { -- кринж + -- function(node) end, + -- onEnd = function() + -- -- print('kakeshke') + -- end, + -- children = { + -- AnimationNode { + -- function(node) --тяжело + -- 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) + -- end, + -- onEnd = function() --база + -- end, + -- children = { + -- AnimationNode { + -- function(node) + -- -- if not self.target then return end + -- print("пупупупупупупупупупуупупуууууу") + -- print(spellB.spellbook[3]:cast(self.owner, self.target)) + -- end + -- } + -- } + -- } + -- } + -- } + -- self.animationNode:run() end) end diff --git a/lib/level/selector.lua b/lib/level/selector.lua index a5d8f98..fd93bbd 100644 --- a/lib/level/selector.lua +++ b/lib/level/selector.lua @@ -37,7 +37,9 @@ function selector:update(dt) if not selectedId then self:select(nil) end return end - if b.cast:cast(char, mousePosition) then + local task = b.cast:cast(char, mousePosition) + if task then + task:run() self:lock() b.state = "running" end diff --git a/lib/level/turn_order.lua b/lib/level/turn_order.lua index f03c836..97e04d1 100644 --- a/lib/level/turn_order.lua +++ b/lib/level/turn_order.lua @@ -34,6 +34,11 @@ function turnOrder:next() local next = self.pendingQueue:peek() if not next then return self:endRound() end self.current = self.pendingQueue:pop() + + local char = Tree.level.characters[self.current] + char:try(Tree.behaviors.ai, function(ai) + ai:makeMove() + end) end --- Меняем местами очередь сходивших и не сходивших (пустую) diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 2aceae1..1df36f3 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -14,7 +14,7 @@ local easing = require "lib.utils.easing" --- @field tag string --- @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): boolean Вызывается в момент каста, изменяет мир. Возвращает bool в зависимости от того, получилось ли скастовать +--- @field cast fun(self: Spell, caster: Character, target: Vec3): AnimationNode | nil Вызывается в момент каста, изменяет мир. local spell = {} spell.__index = spell spell.tag = "base" @@ -35,12 +35,12 @@ function walk:cast(caster, target) if not caster:try(Tree.behaviors.stats, function(stats) return stats.mana >= 2 end) then - return false + return end local path = require "lib.pathfinder" (caster:has(Tree.behaviors.positioned).position:floor(), target) path:pop_front() - if path:is_empty() then return false end + if path:is_empty() then return end for p in path:values() do print(p) end @@ -50,15 +50,13 @@ function walk:cast(caster, target) end) local sprite = caster:has(Tree.behaviors.sprite) - if not sprite then return true end - AnimationNode { + if not sprite then return end + return AnimationNode { function(node) caster:has(Tree.behaviors.tiled):followPath(path, node) end, onEnd = function() caster:has(Tree.behaviors.spellcaster):endCast() end, - }:run() - - return true + } end function walk:update(caster, dt) diff --git a/main.lua b/main.lua index dff5af9..b2f120c 100644 --- a/main.lua +++ b/main.lua @@ -36,7 +36,7 @@ function love.load() character.spawn("Foodor") :addBehavior { Tree.behaviors.residentsleeper.new(), - Tree.behaviors.stats.new(nil, nil, 1), + Tree.behaviors.stats.new(nil, nil, 3), Tree.behaviors.positioned.new(Vec3 { 5, 3 }), Tree.behaviors.tiled.new(), Tree.behaviors.sprite.new(Tree.assets.files.sprites.character),