Compare commits
No commits in common. "c16870102b4d0a45aac9ce9ba90af1efe9f858f1" and "538bd1df3358847f1c1b52c0bcbdef4fed76db1a" have entirely different histories.
c16870102b
...
538bd1df33
@ -19,7 +19,6 @@ end
|
|||||||
function behavior:endCast()
|
function behavior:endCast()
|
||||||
self.state = "idle"
|
self.state = "idle"
|
||||||
self.cast = nil
|
self.cast = nil
|
||||||
Tree.level.turnOrder:reorder()
|
|
||||||
Tree.level.selector:unlock()
|
Tree.level.selector:unlock()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,17 @@
|
|||||||
--- @class StatsBehavior : Behavior
|
--- @class StatsBehavior : Behavior
|
||||||
--- @field hp integer
|
--- @field hp integer
|
||||||
--- @field mana integer
|
--- @field mana integer
|
||||||
--- @field initiative integer
|
|
||||||
--- @field isInTurnOrder boolean
|
|
||||||
local behavior = {}
|
local behavior = {}
|
||||||
behavior.__index = behavior
|
behavior.__index = behavior
|
||||||
behavior.id = "stats"
|
behavior.id = "stats"
|
||||||
|
|
||||||
--- @param hp? integer
|
--- @param hp? integer
|
||||||
--- @param mana? integer
|
--- @param mana? integer
|
||||||
--- @param initiative? integer
|
function behavior.new(hp, mana)
|
||||||
--- @param isInTurnOrder? boolean
|
return setmetatable({
|
||||||
function behavior.new(hp, mana, initiative, isInTurnOrder)
|
|
||||||
return setmetatable({
|
|
||||||
hp = hp or 20,
|
hp = hp or 20,
|
||||||
mana = mana or 10,
|
mana = mana or 10
|
||||||
initiative = initiative or 10,
|
}, behavior)
|
||||||
isInTurnOrder = isInTurnOrder or true
|
|
||||||
}, behavior)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return behavior
|
return behavior
|
||||||
@ -16,8 +16,8 @@ character.__index = character
|
|||||||
--- @param spriteDir table
|
--- @param spriteDir table
|
||||||
--- @param position? Vec3
|
--- @param position? Vec3
|
||||||
--- @param size? Vec3
|
--- @param size? Vec3
|
||||||
--- @param initiative? integer
|
--- @param level? integer
|
||||||
local function spawn(name, spriteDir, position, size, initiative)
|
local function spawn(name, spriteDir, position, size, level)
|
||||||
local char = {}
|
local char = {}
|
||||||
|
|
||||||
char = setmetatable(char, character)
|
char = setmetatable(char, character)
|
||||||
@ -28,7 +28,7 @@ local function spawn(name, spriteDir, position, size, initiative)
|
|||||||
|
|
||||||
char:addBehavior {
|
char:addBehavior {
|
||||||
Tree.behaviors.residentsleeper.new(),
|
Tree.behaviors.residentsleeper.new(),
|
||||||
Tree.behaviors.stats.new(nil, nil, initiative),
|
Tree.behaviors.stats.new(),
|
||||||
Tree.behaviors.map.new(position, size),
|
Tree.behaviors.map.new(position, size),
|
||||||
Tree.behaviors.sprite.new(spriteDir),
|
Tree.behaviors.sprite.new(spriteDir),
|
||||||
Tree.behaviors.spellcaster.new()
|
Tree.behaviors.spellcaster.new()
|
||||||
|
|||||||
@ -18,9 +18,7 @@ controls.keymap = {
|
|||||||
cameraMoveDown = control("key", "s"),
|
cameraMoveDown = control("key", "s"),
|
||||||
cameraMoveScroll = control("mouse", "3"),
|
cameraMoveScroll = control("mouse", "3"),
|
||||||
fullMana = control("key", "m"),
|
fullMana = control("key", "m"),
|
||||||
select = control("mouse", "1"),
|
select = control("mouse", "1")
|
||||||
endTurnTest = control("key", "e"),
|
|
||||||
toggleTurns = control("key", "r"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local currentKeys = {}
|
local currentKeys = {}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ local utils = require "lib.utils.utils"
|
|||||||
--- @field selector Selector
|
--- @field selector Selector
|
||||||
--- @field camera Camera
|
--- @field camera Camera
|
||||||
--- @field tileGrid TileGrid
|
--- @field tileGrid TileGrid
|
||||||
--- @field turnOrder TurnOrder
|
|
||||||
local level = {}
|
local level = {}
|
||||||
level.__index = level
|
level.__index = level
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ local function new(type, template)
|
|||||||
tileGrid = (require "lib.level.grid.tile_grid").new(type, template, size),
|
tileGrid = (require "lib.level.grid.tile_grid").new(type, template, size),
|
||||||
selector = (require "lib.level.selector").new(),
|
selector = (require "lib.level.selector").new(),
|
||||||
camera = (require "lib.level.camera").new(),
|
camera = (require "lib.level.camera").new(),
|
||||||
turnOrder = (require "lib.level.turn_order").new(),
|
|
||||||
}, level)
|
}, level)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -27,18 +27,14 @@ function selector:update(dt)
|
|||||||
local selectedId = Tree.level.characterGrid:get(Vec3 { mousePosition.x, mousePosition.y })
|
local selectedId = Tree.level.characterGrid:get(Vec3 { mousePosition.x, mousePosition.y })
|
||||||
|
|
||||||
if not self.id then
|
if not self.id then
|
||||||
if selectedId ~= Tree.level.turnOrder.current and Tree.level.turnOrder.isTurnsEnabled then return end
|
|
||||||
return self:select(selectedId)
|
return self:select(selectedId)
|
||||||
else
|
else
|
||||||
local char = Tree.level.characters[self.id]
|
local char = Tree.level.characters[self.id]
|
||||||
|
|
||||||
char:try(Tree.behaviors.spellcaster, function(b)
|
char:try(Tree.behaviors.spellcaster, function(b)
|
||||||
if not b.cast then
|
if not b.cast then
|
||||||
-- тут какая-то страшная дичь, я даже не уверен что оно работает
|
self:select(selectedId)
|
||||||
-- зато я точно уверен, что это надо было писать не так
|
return
|
||||||
if not selectedId then self:select(selectedId) end
|
|
||||||
if selectedId ~= Tree.level.turnOrder.current and Tree.level.turnOrder.isTurnsEnabled then return end
|
|
||||||
return self:select(selectedId)
|
|
||||||
end
|
end
|
||||||
if b.cast:cast(char, mousePosition) then
|
if b.cast:cast(char, mousePosition) then
|
||||||
self:lock()
|
self:lock()
|
||||||
|
|||||||
@ -1,112 +0,0 @@
|
|||||||
local PriorityQueue = require "lib.utils.priority_queue"
|
|
||||||
|
|
||||||
local initiativeComparator = function(id_a, id_b)
|
|
||||||
local res = Tree.level.characters[id_a]:try(Tree.behaviors.stats, function(astats)
|
|
||||||
local res = Tree.level.characters[id_b]:try(Tree.behaviors.stats, function(bstats)
|
|
||||||
return astats.initiative > bstats.initiative
|
|
||||||
end)
|
|
||||||
return res
|
|
||||||
end)
|
|
||||||
return res or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @class TurnOrder
|
|
||||||
--- @field actedQueue PriorityQueue Очередь тех, кто сделал ход в текущем раунде
|
|
||||||
--- @field pendingQueue PriorityQueue Очередь тех, кто ждет своего хода в текущем раунде
|
|
||||||
--- @field current? Id Считаем того, кто сейчас ходит, отдельно, т.к. он ВСЕГДА первый в списке
|
|
||||||
--- @field isTurnsEnabled boolean
|
|
||||||
local turnOrder = {}
|
|
||||||
turnOrder.__index = turnOrder
|
|
||||||
|
|
||||||
local function new()
|
|
||||||
return setmetatable({
|
|
||||||
actedQueue = PriorityQueue.new(initiativeComparator),
|
|
||||||
pendingQueue = PriorityQueue.new(initiativeComparator),
|
|
||||||
isTurnsEnabled = true,
|
|
||||||
}, turnOrder)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Перемещаем активного персонажа в очередь сходивших
|
|
||||||
---
|
|
||||||
--- Если в очереди на ход больше никого нет, заканчиваем раунд
|
|
||||||
function turnOrder:next()
|
|
||||||
Tree.level.selector.id = nil
|
|
||||||
self.actedQueue:insert(self.current)
|
|
||||||
local next = self.pendingQueue:peek()
|
|
||||||
if not next then return self:endRound() end
|
|
||||||
self.current = self.pendingQueue:pop()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Меняем местами очередь сходивших и не сходивших (пустую)
|
|
||||||
function turnOrder:endRound()
|
|
||||||
assert(self.pendingQueue:size() == 0, "[TurnOrder]: tried to end the round before everyone had a turn")
|
|
||||||
print("[TurnOrder]: end of the round")
|
|
||||||
self.actedQueue, self.pendingQueue = self.pendingQueue, self.actedQueue
|
|
||||||
self.current = self.pendingQueue:pop()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Пересчитать очередность хода
|
|
||||||
function turnOrder:reorder()
|
|
||||||
local _acted, _pending = PriorityQueue.new(initiativeComparator), PriorityQueue.new(initiativeComparator)
|
|
||||||
|
|
||||||
--- сортировка отдельно кучи не ходивших и ходивших
|
|
||||||
while self.pendingQueue:peek() do
|
|
||||||
_pending:insert(self.pendingQueue:pop())
|
|
||||||
end
|
|
||||||
|
|
||||||
while self.actedQueue:peek() do
|
|
||||||
_acted:insert(self.actedQueue:pop())
|
|
||||||
end
|
|
||||||
|
|
||||||
self.actedQueue, self.pendingQueue = _acted, _pending
|
|
||||||
|
|
||||||
local t = {}
|
|
||||||
for id in self:getOrder(10) do
|
|
||||||
table.insert(t, id)
|
|
||||||
end
|
|
||||||
print("[TurnOrder]: next 10 turns")
|
|
||||||
print(table.concat(t, ", "))
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Итератор по бесконечной цикличной очереди хода
|
|
||||||
--- @param count integer?
|
|
||||||
function turnOrder:getOrder(count)
|
|
||||||
local order = { self.current }
|
|
||||||
local _acted, _pending = self.actedQueue:copy(), self.pendingQueue:copy()
|
|
||||||
|
|
||||||
local i, j = 0, 0
|
|
||||||
local nextTurn = false -- если вышли за пределы текущего хода, то сортируем список, чтобы поставить активного персонажа на свое место
|
|
||||||
return function()
|
|
||||||
-------------------- Очередь этого хода: активный + не сходившие
|
|
||||||
i = i + 1
|
|
||||||
if count and count < 1 then return nil end
|
|
||||||
if count and i > count then return nil end
|
|
||||||
if i == 1 then return self.current end
|
|
||||||
|
|
||||||
if _pending:peek() then
|
|
||||||
local next = _pending:pop()
|
|
||||||
table.insert(order, next)
|
|
||||||
return next
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------- Очередь следующих ходов: цикл по всем персонажам в порядке инициативы
|
|
||||||
if not nextTurn then
|
|
||||||
while _acted:peek() do
|
|
||||||
table.insert(order, _acted:pop())
|
|
||||||
end
|
|
||||||
table.sort(order, initiativeComparator)
|
|
||||||
nextTurn = true
|
|
||||||
end
|
|
||||||
|
|
||||||
j = j + 1
|
|
||||||
if j % #order == 0 then return order[#order] end
|
|
||||||
return order[j % #order]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @param id Id
|
|
||||||
function turnOrder:add(id)
|
|
||||||
self.actedQueue:insert(id) -- новые персонажи по умолчанию попадают в очередь следующего хода
|
|
||||||
end
|
|
||||||
|
|
||||||
return { new = new }
|
|
||||||
@ -81,9 +81,8 @@ regenerateMana.tag = "dev_mana"
|
|||||||
function regenerateMana:cast(caster, target)
|
function regenerateMana:cast(caster, target)
|
||||||
caster:try(Tree.behaviors.stats, function(stats)
|
caster:try(Tree.behaviors.stats, function(stats)
|
||||||
stats.mana = 10
|
stats.mana = 10
|
||||||
stats.initiative = stats.initiative + 10
|
|
||||||
end)
|
end)
|
||||||
print(caster.id, "has regenerated mana and gained initiative")
|
print(caster.id, "has regenerated mana")
|
||||||
local sprite = caster:has(Tree.behaviors.sprite)
|
local sprite = caster:has(Tree.behaviors.sprite)
|
||||||
if not sprite then return true end
|
if not sprite then return true end
|
||||||
AnimationNode {
|
AnimationNode {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
---@class PriorityQueue
|
---@class PriorityQueue
|
||||||
---@field private data any[] внутренний массив-куча (индексация с 1)
|
---@field private data any[] # внутренний массив-куча (индексация с 1)
|
||||||
---@field private cmp fun(a:any, b:any):boolean компаратор: true, если a выше по приоритету, чем b
|
---@field private cmp fun(a:any, b:any):boolean # компаратор: true, если a выше по приоритету, чем b
|
||||||
local PriorityQueue = {}
|
local PriorityQueue = {}
|
||||||
PriorityQueue.__index = PriorityQueue
|
PriorityQueue.__index = PriorityQueue
|
||||||
|
|
||||||
---Создать очередь с приоритетом.
|
---Создать очередь с приоритетом.
|
||||||
---@param cmp fun(a:any, b:any):boolean|nil если nil, используется a < b (мин-куча)
|
---@param cmp fun(a:any, b:any):boolean|nil # если nil, используется a < b (мин-куча)
|
||||||
---@return PriorityQueue
|
---@return PriorityQueue
|
||||||
function PriorityQueue.new(cmp)
|
function PriorityQueue.new(cmp)
|
||||||
local self = setmetatable({}, PriorityQueue)
|
local self = setmetatable({}, PriorityQueue)
|
||||||
@ -16,8 +16,8 @@ end
|
|||||||
|
|
||||||
-- ===== Внутренние утилиты =====
|
-- ===== Внутренние утилиты =====
|
||||||
|
|
||||||
---@param i integer индекс узла
|
---@param i integer @индекс узла
|
||||||
---@param j integer индекс узла
|
---@param j integer @индекс узла
|
||||||
function PriorityQueue:_swap(i, j)
|
function PriorityQueue:_swap(i, j)
|
||||||
self.data[i], self.data[j] = self.data[j], self.data[i]
|
self.data[i], self.data[j] = self.data[j], self.data[i]
|
||||||
end
|
end
|
||||||
@ -103,16 +103,4 @@ function PriorityQueue:is_empty()
|
|||||||
return #self.data == 0
|
return #self.data == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Shallow-копирование очереди
|
|
||||||
function PriorityQueue:copy()
|
|
||||||
local _data = {}
|
|
||||||
for i, v in ipairs(self.data) do
|
|
||||||
_data[i] = v
|
|
||||||
end
|
|
||||||
return setmetatable({
|
|
||||||
data = _data,
|
|
||||||
cmp = self.cmp
|
|
||||||
}, PriorityQueue)
|
|
||||||
end
|
|
||||||
|
|
||||||
return PriorityQueue
|
return PriorityQueue
|
||||||
|
|||||||
23
main.lua
23
main.lua
@ -9,15 +9,8 @@ function love.conf(t)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
character.spawn("Foodor", Tree.assets.files.sprites.character, nil, nil, 1)
|
character.spawn("Foodor", Tree.assets.files.sprites.character)
|
||||||
character.spawn("Baris", Tree.assets.files.sprites.character, Vec3 { 3, 3 }, nil, 2)
|
character.spawn("Baris", Tree.assets.files.sprites.character, Vec3 { 3, 3 })
|
||||||
character.spawn("Foodor Jr", Tree.assets.files.sprites.character, Vec3 { 0, 3 }, nil, 3)
|
|
||||||
character.spawn("Baris Jr", Tree.assets.files.sprites.character, Vec3 { 0, 6 }, nil, 4)
|
|
||||||
for id, _ in pairs(Tree.level.characters) do
|
|
||||||
Tree.level.turnOrder:add(id)
|
|
||||||
end
|
|
||||||
Tree.level.turnOrder:endRound()
|
|
||||||
print("Now playing:", Tree.level.turnOrder.current)
|
|
||||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -28,18 +21,6 @@ function love.update(dt)
|
|||||||
testLayout:update(dt) -- логика UI-слоя должна отработать раньше всех, потому что нужно перехватить жесты и не пустить их дальше
|
testLayout:update(dt) -- логика UI-слоя должна отработать раньше всех, потому что нужно перехватить жесты и не пустить их дальше
|
||||||
Tree.panning:update(dt)
|
Tree.panning:update(dt)
|
||||||
Tree.level:update(dt)
|
Tree.level:update(dt)
|
||||||
|
|
||||||
-- для тестов очереди ходов
|
|
||||||
-- удалить как только появится ui для людей
|
|
||||||
if Tree.controls:isJustPressed("endTurnTest") then
|
|
||||||
Tree.level.turnOrder:next()
|
|
||||||
print("Now playing:", Tree.level.turnOrder.current)
|
|
||||||
end
|
|
||||||
if Tree.controls:isJustPressed("toggleTurns") then
|
|
||||||
print('toggle turns')
|
|
||||||
Tree.level.turnOrder:toggleTurns()
|
|
||||||
end
|
|
||||||
|
|
||||||
Tree.controls:cache()
|
Tree.controls:cache()
|
||||||
|
|
||||||
local t2 = love.timer.getTime()
|
local t2 = love.timer.getTime()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user