- implement selector locking when processing a spell (players gonna hate
that) - implement spellcaster state handling
This commit is contained in:
parent
83115e82f8
commit
8bcae25a2e
@ -7,6 +7,7 @@ local utils = require "lib.utils.utils"
|
||||
--- @field displayedPosition Vec3 точка, в которой персонаж отображается
|
||||
--- @field t0 number время начала движения для анимациии
|
||||
--- @field path Deque путь, по которому сейчас бежит персонаж
|
||||
--- @field onWalkEnd nil | fun() : nil Функция, которая будет вызвана по завершению [followPath]
|
||||
--- @field size Vec3
|
||||
local mapBehavior = {}
|
||||
mapBehavior.__index = mapBehavior
|
||||
@ -24,8 +25,9 @@ function mapBehavior.new(position, size)
|
||||
end
|
||||
|
||||
--- @param path Deque
|
||||
function mapBehavior:followPath(path)
|
||||
if path:is_empty() then return end
|
||||
function mapBehavior:followPath(path, onEnd)
|
||||
if path:is_empty() then return onEnd() end
|
||||
self.onWalkEnd = onEnd
|
||||
self.position = self.displayedPosition
|
||||
self.owner:try(Tree.behaviors.sprite, function(sprite)
|
||||
sprite:play("run", true)
|
||||
@ -67,6 +69,10 @@ function mapBehavior:update(dt)
|
||||
sprite:play("idle", true)
|
||||
end)
|
||||
self.runTarget = nil
|
||||
if self.onWalkEnd then
|
||||
self.onWalkEnd()
|
||||
self.onWalkEnd = nil
|
||||
end
|
||||
end
|
||||
else -- анимация перемещения не завершена
|
||||
self.displayedPosition = utils.lerp(self.position, self.runTarget, fraction) -- линейный интерполятор
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
--- @class SpellcasterBehavior : Behavior
|
||||
--- @field spellbook Spell[] собственный набор спеллов персонажа
|
||||
--- @field cast Spell | nil ссылка на активный спелл из спеллбука
|
||||
--- @field state "idle" | "casting" | "running"
|
||||
local behavior = {}
|
||||
behavior.__index = behavior
|
||||
behavior.id = "spellcaster"
|
||||
behavior.state = "idle"
|
||||
|
||||
---@param spellbook Spell[] | nil
|
||||
---@return SpellcasterBehavior
|
||||
@ -14,12 +16,18 @@ function behavior.new(spellbook)
|
||||
return setmetatable(t, behavior)
|
||||
end
|
||||
|
||||
function behavior:endCast()
|
||||
self.state = "idle"
|
||||
self.cast = nil
|
||||
Tree.level.selector:unlock()
|
||||
end
|
||||
|
||||
function behavior:update(dt)
|
||||
if self.cast then self.cast:update(self.owner, dt) end
|
||||
if self.cast and self.state == "casting" then self.cast:update(self.owner, dt) end
|
||||
end
|
||||
|
||||
function behavior:draw()
|
||||
if self.cast then self.cast:draw() end
|
||||
if self.cast and self.state == "casting" then self.cast:draw() end
|
||||
end
|
||||
|
||||
return behavior
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
--- @class Selector
|
||||
--- @field id Id | nil
|
||||
--- @field locked boolean
|
||||
local selector = {}
|
||||
selector.__index = selector
|
||||
|
||||
@ -14,7 +15,7 @@ function selector:select(characterId)
|
||||
end
|
||||
|
||||
function selector:update(dt)
|
||||
if not Tree.controls:isJustPressed("select") then return end
|
||||
if self.locked or not Tree.controls:isJustPressed("select") then return end
|
||||
|
||||
local mousePosition = Tree.level.camera:toWorldPosition(Vec3 { love.mouse.getX(), love.mouse.getY() }):floor()
|
||||
|
||||
@ -32,12 +33,25 @@ function selector:update(dt)
|
||||
self:select(selectedId)
|
||||
return
|
||||
end
|
||||
b.cast:cast(char, mousePosition)
|
||||
b.cast = nil
|
||||
if b.cast:cast(char, mousePosition) then
|
||||
self:lock()
|
||||
b.state = "running"
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Disables the selector until [unlock] is called
|
||||
function selector:lock()
|
||||
self.id = nil
|
||||
self.locked = true
|
||||
end
|
||||
|
||||
--- Cancels the effect of [lock]
|
||||
function selector:unlock()
|
||||
self.locked = false
|
||||
end
|
||||
|
||||
return {
|
||||
new = new
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
--- @class Spell
|
||||
--- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell
|
||||
--- @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): nil Вызывается в момент каста, изменяет мир
|
||||
--- @field cast fun(self: Spell, caster: Character, target: Vec3): boolean Вызывается в момент каста, изменяет мир. Возвращает bool в зависимости от того, получилось ли скастовать
|
||||
local spell = {}
|
||||
spell.__index = spell
|
||||
|
||||
@ -9,7 +9,7 @@ function spell:update(caster, dt) end
|
||||
|
||||
function spell:draw() end
|
||||
|
||||
function spell:cast(caster, target) end
|
||||
function spell:cast(caster, target) return true end
|
||||
|
||||
local walk = setmetatable({
|
||||
--- @type Deque
|
||||
@ -18,13 +18,15 @@ local walk = setmetatable({
|
||||
|
||||
function walk:cast(caster, target)
|
||||
local path = self.path
|
||||
if path:is_empty() then return end
|
||||
if path:is_empty() then return false end
|
||||
path:pop_front()
|
||||
print("Following path: ")
|
||||
for p in path:values() do print(p) end
|
||||
caster:has(Tree.behaviors.map):followPath(path)
|
||||
caster:has(Tree.behaviors.map):followPath(path, function()
|
||||
caster:has(Tree.behaviors.spellcaster):endCast()
|
||||
end)
|
||||
-- TODO: списать деньги за каст (антиутопия какая-то)
|
||||
-- TODO: привязка тинькоффа
|
||||
return true
|
||||
end
|
||||
|
||||
function walk:update(caster, dt)
|
||||
|
||||
@ -12,9 +12,16 @@ local SkillButton = ui.Rectangle {
|
||||
function SkillButton:update(dt)
|
||||
ui.Rectangle.update(self, dt)
|
||||
self.owner:try(Tree.behaviors.spellcaster, function(spellcaster)
|
||||
self.color = spellcaster.cast and { 0, 1, 0 } or { 1, 0, 0 }
|
||||
self.color = spellcaster.state == "casting" and { 0, 1, 0 } or { 1, 0, 0 }
|
||||
self:onTap(function()
|
||||
spellcaster.cast = spellcaster.cast and nil or spellcaster.spellbook[self.spellId]
|
||||
if not spellcaster.cast then
|
||||
spellcaster.cast = spellcaster.spellbook
|
||||
[self.spellId]
|
||||
spellcaster.state = "casting"
|
||||
else
|
||||
spellcaster.state = "idle"
|
||||
spellcaster.cast = nil
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user