feat: manapool (kind of bad manapool)
Co-authored-by: Ivan Yuriev <peaashmeter@users.noreply.github.com>
This commit is contained in:
parent
8bcae25a2e
commit
d2caa40a0a
@ -10,9 +10,9 @@ behavior.state = "idle"
|
|||||||
---@param spellbook Spell[] | nil
|
---@param spellbook Spell[] | nil
|
||||||
---@return SpellcasterBehavior
|
---@return SpellcasterBehavior
|
||||||
function behavior.new(spellbook)
|
function behavior.new(spellbook)
|
||||||
local spb = require "lib.spellbook" --- @todo временное добавление ходьбы всем персонажам
|
local spb = require "lib.spellbook" --- @todo временное добавление ходьбы (и читов) всем персонажам
|
||||||
local t = {}
|
local t = {}
|
||||||
t.spellbook = spellbook or spb.of { spb.walk }
|
t.spellbook = spellbook or spb.of { spb.walk, spb.regenerateMana }
|
||||||
return setmetatable(t, behavior)
|
return setmetatable(t, behavior)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -56,12 +56,14 @@ function sprite:draw()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param state string
|
--- @param state string
|
||||||
--- @param loop boolean | nil
|
--- @param loop nil | boolean | fun(): nil
|
||||||
function sprite:play(state, loop)
|
function sprite:play(state, loop)
|
||||||
if not self.animationGrid[state] then
|
if not self.animationGrid[state] then
|
||||||
return print("[SpriteBehavior]: no animation for '" .. state .. "'")
|
return print("[SpriteBehavior]: no animation for '" .. state .. "'")
|
||||||
end
|
end
|
||||||
self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED, function()
|
self.animationTable[state] = anim8.newAnimation(self.animationGrid[state], self.ANIMATION_SPEED,
|
||||||
|
type(loop) == "function" and loop or
|
||||||
|
function()
|
||||||
if not loop then self:play("idle", true) end
|
if not loop then self:play("idle", true) end
|
||||||
end)
|
end)
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
require 'lib.utils.vec3'
|
require 'lib.utils.vec3'
|
||||||
|
|
||||||
|
|
||||||
--- @alias Id integer
|
--- @alias Id integer
|
||||||
--- @type Id
|
--- @type Id
|
||||||
local characterId = 1
|
local characterId = 1
|
||||||
|
|
||||||
--- @class Character
|
--- @class Character
|
||||||
--- @field id Id
|
--- @field id Id
|
||||||
|
--- @field stats Stats
|
||||||
--- @field behaviors Behavior[]
|
--- @field behaviors Behavior[]
|
||||||
--- @field _behaviorsIdx {string: integer}
|
--- @field _behaviorsIdx {string: integer}
|
||||||
local character = {}
|
local character = {}
|
||||||
@ -25,6 +25,7 @@ local function spawn(name, template, spriteDir, position, size, level)
|
|||||||
char = setmetatable(char, character)
|
char = setmetatable(char, character)
|
||||||
char.id = characterId
|
char.id = characterId
|
||||||
characterId = characterId + 1
|
characterId = characterId + 1
|
||||||
|
char.stats = require('lib.character.stats').new()
|
||||||
char.behaviors = {}
|
char.behaviors = {}
|
||||||
char._behaviorsIdx = {}
|
char._behaviorsIdx = {}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
--- @class Stats
|
--- @class Stats
|
||||||
--- @field level integer
|
|
||||||
--- @field initiative integer
|
|
||||||
--- @field hp integer
|
--- @field hp integer
|
||||||
--- @field damage integer
|
--- @field mana integer
|
||||||
--- @field defence integer
|
|
||||||
local stats = {}
|
local stats = {}
|
||||||
|
stats.__index = stats
|
||||||
|
|
||||||
--- @param level? integer
|
--- @param level? integer
|
||||||
local function new(level)
|
local function new(level)
|
||||||
|
return {
|
||||||
|
hp = 20,
|
||||||
|
mana = 10
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- creates stats from character template (like warrior etc etc)
|
--- creates stats from character template (like warrior etc etc)
|
||||||
|
|||||||
@ -17,6 +17,7 @@ controls.keymap = {
|
|||||||
cameraMoveRight = control("key", "d"),
|
cameraMoveRight = control("key", "d"),
|
||||||
cameraMoveDown = control("key", "s"),
|
cameraMoveDown = control("key", "s"),
|
||||||
cameraMoveScroll = control("mouse", "3"),
|
cameraMoveScroll = control("mouse", "3"),
|
||||||
|
fullMana = control("key", "m"),
|
||||||
select = control("mouse", "1")
|
select = control("mouse", "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,12 @@
|
|||||||
|
--- Алгоритм обработки заклинания (for dummies):
|
||||||
|
--- 1) ПОКА выделен персонаж И он находится в режиме каста, вызывать spell:update() и spell:draw() каждый кадр (это отвечает за обработку и отрисовку превьюшки каста, например, превью пути или зоны поражения; реализуется через установку spellcaster.cast, см. код в кнопке)
|
||||||
|
--- ЕСЛИ выбран тайл, ТО вызвать spell:cast() (это запрос на обработку последствий применения заклинания, например, старт анимации ходьбы, выпуск снаряда и т.д.; реализовано в selector)
|
||||||
|
--- ЕСЛИ spell:cast() ИСТИНА, ТО вызвать selector:lock() (отключить обработку выделения всего на уровне; реализовано в selector)
|
||||||
|
---
|
||||||
|
--- 2) ПОКА анимация каста НЕ завершена, ничего не делать, ИНАЧЕ вызвать behaviors.spellcaster:endCast() (вот это сейчас нужно вызывать самостоятельно, т.к. нет возможности обобщенно отследить завершение анимаций)
|
||||||
|
--- --TODO: каждый каст должен возвращать объект, который позволит отследить момент завершения анимации спелла
|
||||||
|
--- Да, это Future/Promise/await/async
|
||||||
|
|
||||||
--- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell
|
--- @class Spell Здесь будет много бойлерплейта, поэтому тоже понадобится спеллмейкерский фреймворк, который просто вернет готовый Spell
|
||||||
--- @field update fun(self: Spell, caster: Character, dt: number): nil Изменяет состояние спелла
|
--- @field update fun(self: Spell, caster: Character, dt: number): nil Изменяет состояние спелла
|
||||||
--- @field draw fun(self: Spell): nil Рисует превью каста, ничего не должна изменять в идеальном мире
|
--- @field draw fun(self: Spell): nil Рисует превью каста, ничего не должна изменять в идеальном мире
|
||||||
@ -17,6 +26,11 @@ local walk = setmetatable({
|
|||||||
}, spell)
|
}, spell)
|
||||||
|
|
||||||
function walk:cast(caster, target)
|
function walk:cast(caster, target)
|
||||||
|
if caster.stats.mana < 2 then
|
||||||
|
print("not enough mana!")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local path = self.path
|
local path = self.path
|
||||||
if path:is_empty() then return false end
|
if path:is_empty() then return false end
|
||||||
path:pop_front()
|
path:pop_front()
|
||||||
@ -26,6 +40,8 @@ function walk:cast(caster, target)
|
|||||||
end)
|
end)
|
||||||
-- TODO: списать деньги за каст (антиутопия какая-то)
|
-- TODO: списать деньги за каст (антиутопия какая-то)
|
||||||
-- TODO: привязка тинькоффа
|
-- TODO: привязка тинькоффа
|
||||||
|
caster.stats.mana = caster.stats.mana - 2
|
||||||
|
print(caster.stats.mana)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -46,9 +62,26 @@ function walk:draw()
|
|||||||
love.graphics.setColor(1, 1, 1)
|
love.graphics.setColor(1, 1, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local regenerateMana = setmetatable({}, spell)
|
||||||
|
|
||||||
|
function regenerateMana:cast(caster, target)
|
||||||
|
caster.stats.mana = 10
|
||||||
|
print(caster.id, "has regenerated mana")
|
||||||
|
caster:try(Tree.behaviors.sprite, function (sprite) -- бойлерплейт (временный)
|
||||||
|
-- В данный момент заклинание не позволяет отслеживать состояние последствий своего применения, так что надо повесить хоть какую-то анимашку просто для того, чтобы отложить завершение каста куда-то в будущее
|
||||||
|
-- См. также https://learn.javascript.ru/settimeout-setinterval
|
||||||
|
sprite:play("hurt", function ()
|
||||||
|
sprite:play("idle")
|
||||||
|
caster:has(Tree.behaviors.spellcaster):endCast()
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
local spellbook = {
|
local spellbook = {
|
||||||
walk = walk
|
walk = walk,
|
||||||
|
regenerateMana = regenerateMana
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Создает новый спеллбук с уникальными спеллами (а не ссылками на шаблоны)
|
--- Создает новый спеллбук с уникальными спеллами (а не ссылками на шаблоны)
|
||||||
|
|||||||
@ -43,7 +43,8 @@ function layout:build()
|
|||||||
local r =
|
local r =
|
||||||
ui.Row {
|
ui.Row {
|
||||||
children = {
|
children = {
|
||||||
setmetatable({ owner = Tree.level.characters[id], spellId = 1 }, { __index = SkillButton })
|
setmetatable({ owner = Tree.level.characters[id], spellId = 1 }, { __index = SkillButton }),
|
||||||
|
setmetatable({ owner = Tree.level.characters[id], spellId = 2 }, { __index = SkillButton })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skillRows[id] = r
|
skillRows[id] = r
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user