feature/effects #37

Manually merged
neckrat merged 64 commits from feature/effects into main 2026-05-06 10:19:49 +03:00
4 changed files with 67 additions and 11 deletions
Showing only changes of commit f59f32bd70 - Show all commits

View File

@ -29,6 +29,14 @@ function behavior:addEffect(effect, stacks)
-- if not effect:beforeBirth() then return end -- if not effect:beforeBirth() then return end
-- проверяем эффект на возможности суммирования (aka противоречия) -- проверяем эффект на возможности суммирования (aka противоречия)
for i, ef in ipairs(self.effectsPriority) do for i, ef in ipairs(self.effectsPriority) do
if ef == effect then
self.effectsStacks[ef] = stacks
local task1 = effect:afterBirth(self.owner)
if task1 then
task1(function() end)
end

Всё таки позволяет через наложение сильного короткого эффекта поверх слабого длинного получить и сильный, и длинный эффект одновременно?

Всё таки позволяет через наложение сильного короткого эффекта поверх слабого длинного получить и сильный, и длинный эффект одновременно?

да, мы вроде так и договорились по итогу

да, мы вроде так и договорились по итогу

Так вроде смысл реферата по DOS сводился к тому, что так делать не надо? Мы сделали разные выводы?

Так вроде смысл реферата по DOS сводился к тому, что так делать не надо? Мы сделали разные выводы?

Так вроде смысл реферата по DOS сводился к тому, что так делать не надо? Мы сделали разные выводы?
получается, ты сделал

В этот момент новый, невероятно слабый эффект полностью перезапишет сильный эффект высокоуровневого мага.

Так вроде смысл реферата по DOS сводился к тому, что так делать не надо? Мы сделали разные выводы? получается, ты сделал > В этот момент новый, невероятно слабый эффект полностью перезапишет сильный эффект высокоуровневого мага.

видимо ¯(ツ)/¯, я предположил так сделать из-за всех этих скрытых механик, где ты переопределяешь бесконечный эффект конечным и тд

видимо ¯_(ツ)_/¯, я предположил так сделать из-за всех этих скрытых механик, где ты переопределяешь бесконечный эффект конечным и тд

а поддержка бесконечных эффектов же не присутствует в каком-то дополнительном виде, кроме как не указывать эффекту момент потери стака?

а поддержка бесконечных эффектов же не присутствует в каком-то дополнительном виде, кроме как не указывать эффекту момент потери стака?

да, можно добавить просто какое-то магическое значение по типу -1 ради ui, ну или сделать флаг для этого

да, можно добавить просто какое-то магическое значение по типу -1 ради ui, ну или сделать флаг для этого
return
end
local effectSum = effect:sum(ef) local effectSum = effect:sum(ef)
if effectSum then if effectSum then
-- применяем результат суммы и удаляем эффект -- применяем результат суммы и удаляем эффект
@ -39,7 +47,10 @@ function behavior:addEffect(effect, stacks)
self.effectsPriority[#self.effectsPriority + 1] = effect self.effectsPriority[#self.effectsPriority + 1] = effect
self.effectsStacks[effect] = stacks self.effectsStacks[effect] = stacks
print("[Effects]: мы применили эффект!!") print("[Effects]: мы применили эффект!!")
effect:afterBirth(self.owner) local task1 = effect:afterBirth(self.owner)
if task1 then
task1(function() end)
end
end end
--- должен вызываться в начале хода --- должен вызываться в начале хода
@ -52,6 +63,24 @@ function behavior:beforeTurn()
end end
end end
--- О ДААА ЭТА ФУНКЦИЯ МЕНЯЕТ СОСТОЯНИЕ О ДАААААА О ДАААААААААА
--- @param effect Effect
--- @param amount integer
function behavior:deleteStacks(effect, amount)
print("[Effects]: удаляем стаки!!")
self.effectsStacks[effect] = self.effectsStacks[effect] - amount -- !!!!!!!!!!!!!!!! <<<<< 21+ only
if self.effectsStacks[effect] <= 0 then
print("[Effects]:", effect.tag, "ДОЛЖЕН БЫТЬ СТЁРТ")
self.effectsStacks[effect] = nil
for i, ef in ipairs(self.effectsPriority) do

ладно, это ужас, но не ужас-ужас

ладно, это ужас, но не ужас-ужас

по академически я должен был написать линейный поиск через цикл while, но я необучаемое быдло 🤡

по академически я должен был написать линейный поиск через цикл while, но я необучаемое быдло 🤡

академически у тебя не должно быть линейных поисков вообще, в этом-то и суть

академически у тебя не должно быть линейных поисков вообще, в этом-то и суть

а у тебя получается внутри линейного for i, ef in ipairs линейный table.remove. Это не ужас-ужас, потому что ты гарантируешь срабатывание table.remove не более одного раза

а у тебя получается внутри линейного `for i, ef in ipairs` линейный `table.remove`. Это не ужас-ужас, потому что ты гарантируешь срабатывание `table.remove` не более одного раза

этот моментик я бы тоже переписал

этот моментик я бы тоже переписал

типа красиво-алгоритмически - это все на тегах и все за O(1), кроме последовательного срабатывания всех эффектов (очевидно)

типа красиво-алгоритмически - это все на тегах и все за O(1), **кроме** последовательного срабатывания всех эффектов (очевидно)

думаю, хотя бы для этого система тэгов не пригодится (надеюсь)

думаю, хотя бы для этого система тэгов не пригодится (надеюсь)

ну если я правильно собираю в голове ход мыслей, то нужны адекватные теги (уникальные; один тег к одному эффекту), и отдельно группы тегов (один ко многим). Например, чтобы объединить 15 версий невидимости в одну группу "невидимость" и не давать выбрать таких персонажей в таргет

ну если я правильно собираю в голове ход мыслей, то нужны адекватные теги (уникальные; один тег к одному эффекту), и отдельно группы тегов (один ко многим). Например, чтобы объединить 15 версий невидимости в одну группу "невидимость" и не давать выбрать таких персонажей в таргет

это переусложнение, которое уже ближе к реальному геймдизайну, где, как обычно, боссы могут иметь немного другие версии тех же самых эффектов

это переусложнение, которое уже ближе к реальному геймдизайну, где, как обычно, боссы могут иметь немного другие версии тех же самых эффектов

нам же эти же тэги пригодятся для спеллов в конце концов, для их систематизации

нам же эти же тэги пригодятся для спеллов в конце концов, для их систематизации

не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов

не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов

не думаю, что это такое уж переусложнение, мы же не только ради эффектов это делаем в конце концов

не думаю, что это такое уж переусложнение, мы же не только ради эффектов это делаем в конце концов

не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов

типа можно, но пока не знаю, зачем

> не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов типа можно, но пока не знаю, зачем

вай нот? dry и всё такое

не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов

вай нот? dry и всё такое > не вижу необходимости иметь одну общую систему тегов для спеллов и для эффектов

тогда будет нейминг "spell_myspell" и "effect_myeffect"

тогда будет нейминг "spell_myspell" и "effect_myeffect"

так-то у нас не стоит задача по тегу понимать еще и тип объекта, у нас для этого инструменты языка есть, не на бейсике пишем

так-то у нас не стоит задача по тегу понимать еще и тип объекта, у нас для этого инструменты языка есть, не на бейсике пишем

справедливо

справедливо

фактически у нас как будто есть таблицы в реляционной СУБД Microsoft Access: spells и effects.
мы и так понимаем, что это разные таблицы. В рамках разных таблиц айдишники не обязаны быть уникальными

фактически у нас как будто есть таблицы в реляционной СУБД Microsoft Access: spells и effects. мы и так понимаем, что это разные таблицы. В рамках разных таблиц айдишники не обязаны быть уникальными

типа другое дело что у нас у characters айдишники номерные, а у статических данных - строковые. Но это по историческим причинам и потому что, как бы, статические данные типа спеллов и эффектов мы как раз хотим находить по удобному идентификатору, а динамические типа персонажей - не хотим

типа другое дело что у нас у characters айдишники номерные, а у статических данных - строковые. Но это по историческим причинам и потому что, как бы, статические данные типа спеллов и эффектов мы как раз хотим находить по удобному идентификатору, а динамические типа персонажей - не хотим

ну да, да, очевидно

ну да, да, очевидно

у нас персонажи вообще в роли энтити, там со строковыми тэгами не выйдет

у нас персонажи вообще в роли энтити, там со строковыми тэгами не выйдет

короче нормальная архитектура вроде

короче нормальная архитектура вроде
if ef == effect then
table.remove(self.effectsPriority, i)
print("[Effects]:", effect.tag, "СТЁРТ")
end
end
end
end
--- должен вызываться в конце хода --- должен вызываться в конце хода
function behavior:afterTurn() function behavior:afterTurn()
for i, ef in pairs(self.effectsPriority) do for i, ef in pairs(self.effectsPriority) do

View File

@ -4,29 +4,37 @@ local easing = require "lib.utils.easing"
local bleeding = effect.new({ local bleeding = effect.new({
tag = "bleeding", tag = "bleeding",
beforeTurn = function(owner)
print("мы начали применять блидинг!!", owner)
local stats = owner:has(Tree.behaviors.stats)
local sprite = owner:has(Tree.behaviors.sprite)
if not stats or not sprite then return end
stats:dealDamage(2)
return task.wait({ sprite:animate("hurt") })
end,
afterBirth = function(owner) afterBirth = function(owner)
local light = require "lib/character/character".spawn("Light Effect") local light = require "lib/character/character".spawn("Bleeding Light Effect")
light:addBehavior { light:addBehavior {
Tree.behaviors.light.new { color = Vec3 { 1, 0., 0. }, intensity = 4 }, Tree.behaviors.light.new { color = Vec3 { 1, 0., 0. }, intensity = 4 },
Tree.behaviors.positioned.new(owner:has(Tree.behaviors.positioned).position + Vec3 { 0.5, 0.5 }), Tree.behaviors.positioned.new(owner:has(Tree.behaviors.positioned).position + Vec3 { 0.5, 0.5 }),
} }
return task.wait({ task.chain(task.tween(light:has(Tree.behaviors.light) --[[@as LightBehavior]], return task.wait({ task.chain(task.tween(light:has(Tree.behaviors.light) --[[@as LightBehavior]],
{ intensity = 1, color = Vec3 { 1, 0., 0. } }, 800, easing.easeInCubic), function() { intensity = 1, color = Vec3 { 0, 0., 0. } }, 800, easing.easeInCubic), function()
light:die() light:die()
return task.fromValue() return task.fromValue()
end) }) end) })
end end
}) })
function bleeding:beforeTurn(owner)
local stats = owner:has(Tree.behaviors.stats)
local sprite = owner:has(Tree.behaviors.sprite)
if not stats or not sprite then return end
stats:dealDamage(2)
return task.wait({ sprite:animate("hurt") })
end
function bleeding:afterTurn(owner)
local behavior = owner:has(Tree.behaviors.effects)
if not behavior then
print('[Effect]: yo man what the hell wheres your behavior how thats possible please stop thats not normal')
return
end
behavior:deleteStacks(self, 1)
end
local effectbook = { local effectbook = {
bleeding = bleeding bleeding = bleeding

View File

@ -73,6 +73,9 @@ function turnOrder:endRound()
char:try(Tree.behaviors.spellcaster, function(spellcaster) char:try(Tree.behaviors.spellcaster, function(spellcaster)
spellcaster:processCooldowns() spellcaster:processCooldowns()
end) end)
char:try(Tree.behaviors.effects, function(effects)
effects:afterTurn()
end)
end end
self.actedQueue, self.pendingQueue = self.pendingQueue, self.actedQueue self.actedQueue, self.pendingQueue = self.pendingQueue, self.actedQueue

View File

@ -1,3 +1,5 @@
local utils = require "lib.utils.utils"
--- @class Effect --- @class Effect
Review

Почему это вообще в папке со спеллами?

Почему это вообще в папке со спеллами?
Review

я не придумал куда в другое место это запихать, не в либ же кидать 🥵

я не придумал куда в другое место это запихать, не в либ же кидать 🥵
--- @field tag string --- @field tag string
local effect = {} local effect = {}
@ -76,6 +78,13 @@ function effect:update(dt) end
function effect:draw() end function effect:draw() end
--- дип сравнение эффектов
--- @param other Effect
--- @return boolean
function effect:__eq(other)
return utils.deepComprasion(self, other)
end
--- @todo переделать дату и прочее --- @todo переделать дату и прочее
-- --- @param data {tag: string, beforeBirth: fun(owner: Character)?, beforeDeath: fun(owner: Character)?, beforeTurn: (fun(owner: Character): Task<nil>|nil), afterTurn: (fun(owner: Character): Task<nil>|nil), sum: fun(owner: Character)?} -- --- @param data {tag: string, beforeBirth: fun(owner: Character)?, beforeDeath: fun(owner: Character)?, beforeTurn: (fun(owner: Character): Task<nil>|nil), afterTurn: (fun(owner: Character): Task<nil>|nil), sum: fun(owner: Character)?}
--- @param data EffectData --- @param data EffectData
@ -155,6 +164,13 @@ local function new(data)
return data.afterRegeneration(owner) return data.afterRegeneration(owner)
end end
--- дип сравнение эффектов
--- @param other Effect
--- @return boolean
function newEffect:__eq(other)
return utils.deepComprasion(self, other)
end
return newEffect return newEffect
end end