Refactor spell casts to use task utilities and simplify callbacks

Add task.chain utility for chaining asynchronous tasks
This commit is contained in:
PeaAshMeter 2026-02-01 03:56:18 +03:00
parent 403ba5a03f
commit 1986228670
4 changed files with 48 additions and 29 deletions

View File

@ -70,7 +70,7 @@ function sprite:draw()
end end
--- @return Task<nil> --- @return Task<nil>
function sprite:animate(state, node) function sprite:animate(state)
return function(callback) return function(callback)
if not self.animationGrid[state] then if not self.animationGrid[state] then
print("[SpriteBehavior]: no animation for '" .. state .. "'") print("[SpriteBehavior]: no animation for '" .. state .. "'")

View File

@ -7,7 +7,7 @@
--- --TODO: каждый каст должен возвращать объект, который позволит отследить момент завершения анимации спелла --- --TODO: каждый каст должен возвращать объект, который позволит отследить момент завершения анимации спелла
--- Да, это Future/Promise/await/async --- Да, это Future/Promise/await/async
local Counter = require 'lib.utils.counter' local task = require 'lib.utils.task'
--- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell --- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell
--- @field tag string --- @field tag string
@ -55,11 +55,7 @@ function walk:cast(caster, target)
return return
end end
return function(callback) return caster:has(Tree.behaviors.tiled):followPath(path)
return caster:has(Tree.behaviors.tiled):followPath(path)(
callback
) -- <- callback вызовется после followPath
end
end end
function walk:update(caster, dt) function walk:update(caster, dt)
@ -103,14 +99,10 @@ function regenerateMana:cast(caster, target)
Tree.behaviors.positioned.new(caster:has(Tree.behaviors.positioned).position + Vec3 { 0.5, 0.5 }), Tree.behaviors.positioned.new(caster:has(Tree.behaviors.positioned).position + Vec3 { 0.5, 0.5 }),
} }
return function(callback) return task.wait {
light:has(Tree.behaviors.light):animateColor(Vec3 {})( light:has(Tree.behaviors.light):animateColor(Vec3 {}),
function() sprite:animate("hurt")
light:die() }
end
)
sprite:animate("hurt")(callback)
end
end end
local attack = setmetatable({}, spell) local attack = setmetatable({}, spell)
@ -143,20 +135,16 @@ function attack:cast(caster, target)
caster:try(Tree.behaviors.positioned, function(b) b:lookAt(target) end) caster:try(Tree.behaviors.positioned, function(b) b:lookAt(target) end)
return function(callback) return
local c = Counter(callback) task.wait {
sprite:animate("attack"),
c.push() task.wait {
sprite:animate("attack")(c.pop) task.chain(targetCharacter:has(Tree.behaviors.residentsleeper):sleep(200),
function() return targetSprite:animate("hurt") end
c.push() ),
targetCharacter:has(Tree.behaviors.residentsleeper):sleep(200)(
function()
targetSprite:animate("hurt")(c.pop)
Tree.audio:play(Tree.assets.files.audio.sounds.hurt) Tree.audio:play(Tree.assets.files.audio.sounds.hurt)
end }
) }
end
end end
---------------------------------------- ----------------------------------------

View File

@ -61,6 +61,23 @@ local function wait(tasks)
end end
end end
--- Последовательно объединяет два `Task` в один.
--- @generic T
--- @generic R
--- @param task Task<T> `Task`, который выполнится первым
--- @param onCompleted fun(value: T): Task<R> Конструктор второго `Task`. Принимает результат выполнения первого `Task`
--- @return Task<R>
local function chain(task, onCompleted)
return function(callback)
task(function(value)
local task2 = onCompleted(value)
task2(callback)
end)
end
end
return { return {
wait = wait, wait = wait,
chain = chain
} }

View File

@ -41,7 +41,21 @@ function test:run(complete)
print("task.wait completed in " .. dt .. " sec", "t1 = " .. t1 - t0, "t2 = " .. t2 - t0) print("task.wait completed in " .. dt .. " sec", "t1 = " .. t1 - t0, "t2 = " .. t2 - t0)
t0 = love.timer.getTime()
task.chain(task1(), function(value)
t1 = value
assert(t1 - t0 >= 1)
return task2()
end)(
function(value)
t2 = value
assert(t2 - t0 >= 2)
print("task.chain completed in " .. t2 - t0 .. " sec")
complete() complete()
end
)
end) end)
end end