From 40536e20cc13e970842bb6979101a4edfae25168 Mon Sep 17 00:00:00 2001 From: neckrat Date: Thu, 7 May 2026 17:16:12 +0300 Subject: [PATCH 1/5] =?UTF-8?q?rewrite=20eveything=20on=20impact=20?= =?UTF-8?q?=F0=9F=A4=AA=20=F0=9F=8D=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/character/behaviors/effects.lua | 2 +- lib/character/behaviors/stats.lua | 4 +- lib/effectbook.lua | 11 +++-- lib/spell/effect.lua | 72 ++++++++--------------------- lib/utils/impact.lua | 29 ++++++++++++ 5 files changed, 58 insertions(+), 60 deletions(-) create mode 100644 lib/utils/impact.lua diff --git a/lib/character/behaviors/effects.lua b/lib/character/behaviors/effects.lua index 3099652..d644028 100644 --- a/lib/character/behaviors/effects.lua +++ b/lib/character/behaviors/effects.lua @@ -160,7 +160,7 @@ end --- должен вызываться перед получением урона --- --- возвращает получаемый урон ---- @return integer +--- @return Impact function behavior:beforeDamage(damage) local totalDamage = damage for i, ef in ipairs(self.effectsPriority) do diff --git a/lib/character/behaviors/stats.lua b/lib/character/behaviors/stats.lua index 4b8a075..63f59dc 100644 --- a/lib/character/behaviors/stats.lua +++ b/lib/character/behaviors/stats.lua @@ -19,11 +19,11 @@ function behavior:checkStats() end end ---- @param damage integer +--- @param damage Impact function behavior:dealDamage(damage) local effects = self.owner:has(Tree.behaviors.effects) if effects then damage = effects:beforeDamage(damage) end - self.hp = self.hp - damage + self.hp = self.hp - damage.intensity self:checkStats() end diff --git a/lib/effectbook.lua b/lib/effectbook.lua index 3f6f3f8..fb3641d 100644 --- a/lib/effectbook.lua +++ b/lib/effectbook.lua @@ -1,6 +1,7 @@ local task = require "lib.utils.task" local effect = require "lib.spell.effect" local easing = require "lib.utils.easing" +local impact = require "lib.utils.impact" --- некое уникальное строковое значение --- @alias EffectTag string @@ -29,8 +30,8 @@ end function bleeding:beforeTurn(owner, intensity) 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(intensity) + if not stats or not sprite then return task.fromValue(), true end + stats:dealDamage(impact(intensity, "physic")) return task.wait({ sprite:animate("hurt") }), true end @@ -65,11 +66,11 @@ local aversionToDeath = effect.new { function aversionToDeath:beforeDamage(owner, intensity, damage) local stats = owner:has(Tree.behaviors.stats) local effects = owner:has(Tree.behaviors.effects) - if not stats or not effects then return end - if stats.hp <= damage then + if not stats or not effects then return task.fromValue(), damage end + if stats.hp <= damage.intensity then effects:deleteStacks("aversionToDeath", 1) -- тут должен быть какой-нибудь классный спецэффект, но я не умею в шейдеры - return task.wait({}), stats.hp - 1 + return task.wait({}), impact(stats.hp - 1, "magic") end return task.wait {}, damage end diff --git a/lib/spell/effect.lua b/lib/spell/effect.lua index 863f474..d818ac0 100644 --- a/lib/spell/effect.lua +++ b/lib/spell/effect.lua @@ -14,111 +14,79 @@ local effect = {} effect.__index = effect --- Предполагается, что в каждую функцию будет передаваться `Character` (владелец эффекта) и параметр `intensity`, который отвечает за силу эффекта ---- @alias EffectFunc fun(owner: Character, intensity: integer): Task, nil бред конечно, но иначе всё в жёлтом ---- @alias EffectStatementFunc fun(owner: Character, intensity: integer): Task, boolean ---- @alias EffectDamageFunc fun(owner: Character, intensity: integer, damage: integer): Task, integer ---- @alias EffectRegenFunc fun(owner: Character, intensity: integer, amountHp: integer): Task, integer +--- @alias EffectFunc fun(self: Effect, owner: Character, intensity: integer): Task, nil бред конечно, но иначе всё в жёлтом +--- @alias EffectStatementFunc fun(self: Effect, owner: Character, intensity: integer): Task, boolean +--- @alias EffectImpactFunc fun(self: Effect, owner: Character, intensity: integer, impact: Impact): Task, Impact --- @alias EffectData { tag: string } --- Срабатывает перед применением эффекта --- --- Возвращает, а можно ли применить эффект? ---- @param owner Character ---- @param intensity integer ---- @return Task, boolean +--- @type EffectStatementFunc function effect:beforeBirth(owner, intensity) return taskUtils.fromValue(), true end --- Срабатывает после применения эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterBirth(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед смертью владельца эффекта --- --- Возвращает, умирает ли персонаж? ---- @param owner Character ---- @param intensity integer ---- @return Task, boolean +--- @type EffectStatementFunc function effect:beforeDeath(owner, intensity) return taskUtils.fromValue(), true end --- Срабатывает после смерти владельца эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterDeath(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед ходом владельца эффекта --- --- Возвращает, будет ли персонаж ходить? ---- @param owner Character ---- @param intensity integer ---- @return Task, boolean +--- @type EffectStatementFunc function effect:beforeTurn(owner, intensity) return taskUtils.fromValue(), true end --- Срабатывает после хода владельца эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterTurn(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед кастом заклинания владельцем эффекта --- --- Возвращает, произойдёт ли каст? ---- @param owner Character ---- @param intensity integer ---- @return Task, boolean +--- @type EffectStatementFunc function effect:beforeCast(owner, intensity) return taskUtils.fromValue(), true end --- Срабатывает после каста заклинания владельцем эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterCast(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед нанесением урона владельцем эффекта --- --- Возвращает урон, который собираются нанести ---- @param owner Character ---- @param intensity integer ---- @param damage integer ---- @return Task, integer -function effect:beforeAttack(owner, intensity, damage) return taskUtils.fromValue(), damage end +--- @type EffectImpactFunc +function effect:beforeAttack(owner, intensity, impact) return taskUtils.fromValue(), impact end --- Срабатывает после нанесения урона владельцем эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterAttack(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед получением урона владельцем эффекта --- --- Возвращает урон, который должны получить ---- @param owner Character ---- @param intensity integer ---- @param damage integer ---- @return Task, integer -function effect:beforeDamage(owner, intensity, damage) return taskUtils.fromValue(), damage end +--- @type EffectImpactFunc +function effect:beforeDamage(owner, intensity, impact) return taskUtils.fromValue(), impact end --- Срабатывает после получения урона владельцем эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterDamage(owner, intensity) return taskUtils.fromValue() end --- Срабатывает перед регенерацией здоровья владельцем эффекта --- --- Возвращает количество здоровья, которое должно быть восстановлено ---- @param owner Character ---- @param intensity integer ---- @param amountHp integer кол-во хп для регена ---- @return Task, integer -function effect:beforeRegeneration(owner, intensity, amountHp) return taskUtils.fromValue(), amountHp end +--- @type EffectImpactFunc +function effect:beforeRegeneration(owner, intensity, impact) return taskUtils.fromValue(), impact end --- Срабатывает после регенерации здоровья владельцем эффекта ---- @param owner Character ---- @param intensity integer ---- @return Task +--- @type EffectFunc function effect:afterRegeneration(owner, intensity) return taskUtils.fromValue() end --- Функция, что задаёт правила присвоения эффекта diff --git a/lib/utils/impact.lua b/lib/utils/impact.lua new file mode 100644 index 0000000..b2525c0 --- /dev/null +++ b/lib/utils/impact.lua @@ -0,0 +1,29 @@ +--- @alias ImpactType "physic"|"magic" + +--- Представляет из себя некое "взаимодействие", которое мы должны применить к игроку в зависимости от контекста, +--- например, нанести урон. +--- @class Impact +--- @field intensity integer +--- @field impactType ImpactType +local impact = {} +impact.__index = impact + +--- @param other Impact +function impact:__add(other) + self.intensity = self.intensity + other.intensity + return self +end + +--- @param other Impact +function impact:__sub(other) + self.intensity = self.intensity - other.intensity + return self +end + +--- @param intensity integer +--- @param impactType ImpactType +local function new(intensity, impactType) + return setmetatable({ intensity = intensity, impactType = impactType }, impact) +end + +return new -- 2.47.2 From 138502ce3fac1962d6f9f9295f7b24fd215a66a0 Mon Sep 17 00:00:00 2001 From: neckrat Date: Sat, 9 May 2026 22:46:43 +0300 Subject: [PATCH 2/5] =?UTF-8?q?some=20stats=20rewriting=20=F0=9F=A4=AA=20?= =?UTF-8?q?=F0=9F=8D=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/character/behaviors/stats.lua | 44 +++++++++++++++++++++++-------- lib/effectbook.lua | 14 +++++----- lib/utils/impact.lua | 14 +++++----- main.lua | 4 +-- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lib/character/behaviors/stats.lua b/lib/character/behaviors/stats.lua index 63f59dc..a325bac 100644 --- a/lib/character/behaviors/stats.lua +++ b/lib/character/behaviors/stats.lua @@ -1,9 +1,13 @@ +local impact = require "lib.utils.impact" + --- @alias Class "dev_warrior"|"dev_mage" +--- @alias Chars "strength"|"intelligence"|"agility"|"stamina"|"lunacy" --- @class StatsBehavior : Behavior --- @field hp integer --- @field mana integer --- @field initiative integer +--- @field chars table --- @field class Class --- @field isInTurnOrder boolean --- @field amIAlive boolean @@ -19,24 +23,42 @@ function behavior:checkStats() end end ---- @param damage Impact -function behavior:dealDamage(damage) +function behavior:maxHealth() + return self.chars["stamina"] * 2 +end + +--- @param damage integer +--- @param impactType ImpactType +function behavior:dealDamage(damage, impactType) + local damageImpact = impact(damage, impactType) local effects = self.owner:has(Tree.behaviors.effects) - if effects then damage = effects:beforeDamage(damage) end - self.hp = self.hp - damage.intensity + if effects then damageImpact = effects:beforeDamage(damageImpact) end + self.hp = self.hp - damageImpact.intensity self:checkStats() end ---- @param hp? integer ---- @param mana? integer ---- @param initiative? integer --- @param class? Class +--- @param chars? table --- @param isInTurnOrder? boolean -function behavior.new(hp, mana, initiative, class, isInTurnOrder) +function behavior.new(class, chars, isInTurnOrder) + --- @type Chars + local _chars = {} + if not chars then + _chars = { strength = 10, stamina = 10, intelligence = 10, agility = 10, lunacy = 0 } + else + _chars = { + strength = chars.strength or 10, + stamina = chars.stamina or 10, + intelligence = chars.intelligence or 10, + agility = chars.agility or 10, + lunacy = chars.lunacy or 0, + } + end return setmetatable({ - hp = hp or 20, - mana = mana or 10, - initiative = initiative or 10, + hp = _chars["stamina"] * 2, + mana = 10, -- я полагаю, у всех будет одинаковое кол-во маны (оно же кол-во действий) + initiative = _chars.agility, + chars = _chars, class = class or "dev_warrior", isInTurnOrder = isInTurnOrder or true, amIAlive = true diff --git a/lib/effectbook.lua b/lib/effectbook.lua index fb3641d..20bee55 100644 --- a/lib/effectbook.lua +++ b/lib/effectbook.lua @@ -31,7 +31,7 @@ function bleeding:beforeTurn(owner, intensity) local stats = owner:has(Tree.behaviors.stats) local sprite = owner:has(Tree.behaviors.sprite) if not stats or not sprite then return task.fromValue(), true end - stats:dealDamage(impact(intensity, "physic")) + stats:dealDamage(intensity, "physic") return task.wait({ sprite:animate("hurt") }), true end @@ -42,18 +42,18 @@ function bleeding:afterTurn(owner, intensity) else behavior:deleteStacks("bleeding", 1) end - return task.wait {} + return task.fromValue() end --- meow function bleeding:afterCast(owner, intensity) Tree.audio:play(Tree.assets.files.audio.sounds.meow) - return task.wait {} + return task.fromValue() end function bleeding:beforeCast(owner, intensity) Tree.audio:play(Tree.assets.files.audio.sounds.meow) - return task.wait {}, true + return task.fromValue(), true end --- Отвращение к смерти. @@ -70,15 +70,15 @@ function aversionToDeath:beforeDamage(owner, intensity, damage) if stats.hp <= damage.intensity then effects:deleteStacks("aversionToDeath", 1) -- тут должен быть какой-нибудь классный спецэффект, но я не умею в шейдеры - return task.wait({}), impact(stats.hp - 1, "magic") + return task.fromValue(), impact(stats.hp - 1, "magic") end - return task.wait {}, damage + return task.fromValue(), damage end function aversionToDeath:beforeTurn(owner, intensity) local sprite = owner:has(Tree.behaviors.sprite) if not sprite then - return task.wait {}, false + return task.fromValue(), false end return task.wait { sprite:animate("hurt") diff --git a/lib/utils/impact.lua b/lib/utils/impact.lua index b2525c0..dc9f4aa 100644 --- a/lib/utils/impact.lua +++ b/lib/utils/impact.lua @@ -10,20 +10,22 @@ impact.__index = impact --- @param other Impact function impact:__add(other) - self.intensity = self.intensity + other.intensity - return self + assert(self.impactType == other.impactType, "Impact types not equals each other!") + local newImpact = Impact(self.intensity + other.intensity, self.impactType) + return newImpact end --- @param other Impact function impact:__sub(other) - self.intensity = self.intensity - other.intensity - return self + assert(self.impactType == other.impactType, "Impact types not equals each other!") + local newImpact = Impact(self.intensity - other.intensity, self.impactType) + return newImpact end --- @param intensity integer --- @param impactType ImpactType -local function new(intensity, impactType) +function Impact(intensity, impactType) return setmetatable({ intensity = intensity, impactType = impactType }, impact) end -return new +return Impact diff --git a/main.lua b/main.lua index 76792bc..b489a29 100644 --- a/main.lua +++ b/main.lua @@ -29,7 +29,7 @@ function love.load() character.spawn("Foodor") :addBehavior { Tree.behaviors.residentsleeper.new(), - Tree.behaviors.stats.new(nil, nil, 1), + Tree.behaviors.stats.new(nil, { agility = 1 }), Tree.behaviors.positioned.new(Vec3 { 3, 1 }), Tree.behaviors.tiled.new(), Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), @@ -40,7 +40,7 @@ function love.load() character.spawn("Foodor") :addBehavior { Tree.behaviors.residentsleeper.new(), - Tree.behaviors.stats.new(nil, nil, 3), + Tree.behaviors.stats.new(nil, { agility = 3 }), Tree.behaviors.positioned.new(Vec3 { 7, 2 }), Tree.behaviors.tiled.new(), Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), -- 2.47.2 From 5112a42672fa55905a840b378f55101489a1d88d Mon Sep 17 00:00:00 2001 From: neckrat Date: Sun, 10 May 2026 21:15:21 +0300 Subject: [PATCH 3/5] =?UTF-8?q?add=20final=20and=20raw=20chars=20?= =?UTF-8?q?=F0=9F=A4=AA=20=F0=9F=8D=AA=20&=20new=20effect=20rule=20before/?= =?UTF-8?q?afterDelete=20=F0=9F=A4=AA=20=F0=9F=8D=AA=20&=20intensity=20rep?= =?UTF-8?q?laced=20by=20chars.agility=20=F0=9F=A4=AA=20=F0=9F=8D=AA=20&=20?= =?UTF-8?q?rewrite=20some=20regenerateMana=20spell=20logic=20for=20develop?= =?UTF-8?q?ment=20purposes=20=F0=9F=A4=AA=20=F0=9F=8D=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/character/behaviors/effects.lua | 12 ++++-- lib/character/behaviors/stats.lua | 65 +++++++++++++++++++++-------- lib/effectbook.lua | 18 ++++++++ lib/level/turn_order.lua | 2 +- lib/spell/effect.lua | 10 +++++ lib/spellbook.lua | 1 - 6 files changed, 86 insertions(+), 22 deletions(-) diff --git a/lib/character/behaviors/effects.lua b/lib/character/behaviors/effects.lua index d644028..d8b66e0 100644 --- a/lib/character/behaviors/effects.lua +++ b/lib/character/behaviors/effects.lua @@ -59,6 +59,10 @@ end --- Удаляет один эффект по порядку --- @param effect EffectTag function behavior:deleteEffect(effect) + if not self.effectsProperties[effect] then return end + local task1, deleteStatement = book[effect]:beforeDelete(self.owner, self.effectsProperties[effect].intensity) + task1(function() end) + if not deleteStatement then return end self.effectsProperties[effect] = nil for i, ef in ipairs(self.effectsPriority) do if ef == effect then @@ -66,19 +70,21 @@ function behavior:deleteEffect(effect) return end end + local task2 = book[effect]:afterDelete(self.owner, self.effectsProperties[effect].intensity) + task2(function() end) end --- О ДААА ЭТА ФУНКЦИЯ МЕНЯЕТ СОСТОЯНИЕ О ДАААААА О ДАААААААААА --- @param effect EffectTag --- @param amount integer function behavior:deleteStacks(effect, amount) - print("[Effects]: удаляем стаки!!") + -- print("[Effects]: удаляем стаки!!") self.effectsProperties[effect].stacks = self.effectsProperties[effect].stacks - amount -- !!!!!!!!!!!!!!!! <<<<< 21+ only if self.effectsProperties[effect].stacks <= 0 then - print("[Effects]:", effect, "ДОЛЖЕН БЫТЬ СТЁРТ") + -- print("[Effects]:", effect, "ДОЛЖЕН БЫТЬ СТЁРТ") self:deleteEffect(effect) - print("[Effects]:", effect, "СТЁРТ") + -- print("[Effects]:", effect, "СТЁРТ") end end diff --git a/lib/character/behaviors/stats.lua b/lib/character/behaviors/stats.lua index a325bac..9d591b6 100644 --- a/lib/character/behaviors/stats.lua +++ b/lib/character/behaviors/stats.lua @@ -2,12 +2,12 @@ local impact = require "lib.utils.impact" --- @alias Class "dev_warrior"|"dev_mage" --- @alias Chars "strength"|"intelligence"|"agility"|"stamina"|"lunacy" +--- @alias CharsTable table --- @class StatsBehavior : Behavior --- @field hp integer --- @field mana integer ---- @field initiative integer ---- @field chars table +--- @field chars { raw: CharsTable, final: CharsTable } по хорошему, мы не должны менять эту таблицу руками, а делать это только через метод `changeChar` --- @field class Class --- @field isInTurnOrder boolean --- @field amIAlive boolean @@ -24,7 +24,7 @@ function behavior:checkStats() end function behavior:maxHealth() - return self.chars["stamina"] * 2 + return self.chars.final["stamina"] * 2 end --- @param damage integer @@ -37,28 +37,59 @@ function behavior:dealDamage(damage, impactType) self:checkStats() end +--- позволяет изменять значение характеристики персонажа +--- +--- менять характеристики мы должны с помощью функции, которая возвращает значение на сколько мы должны изменить характеристику +--- относительно сырой характеристики, и это значение мы прибавляем к финальным характеристикам +--- +--- такой системой (вроде как) мы гарантируем, что все операции над статами будут обратимыми +--- +--- @TODO: возможно в будущем при появлении эвентов в игре, мы должны регать эвент изменения стата +--- +--- пара примеров: +--- +--- прибавляем 1 к стату: `behavior:changeChar("strength", function (charAmount) return 1 end)` +--- +--- отнимаем от стата 50%: `behavior:changeChar("strength", function (charAmount) return -charAmount / 2 end)` +--- @param char Chars +--- @param func fun(charAmount: integer): integer charAmount здесь это сырое значение характеристики +function behavior:changeChar(char, func) + self.chars.final[char] = func(self.chars.raw[char]) +end + --- @param class? Class ---- @param chars? table +--- @param rawChars? table --- @param isInTurnOrder? boolean -function behavior.new(class, chars, isInTurnOrder) +function behavior.new(class, rawChars, isInTurnOrder) --- @type Chars - local _chars = {} - if not chars then - _chars = { strength = 10, stamina = 10, intelligence = 10, agility = 10, lunacy = 0 } + local chars = { raw = {}, final = {} } + if not rawChars then + chars = { + raw = { strength = 10, stamina = 10, intelligence = 10, agility = 10, lunacy = 0 }, + final = { strength = 10, stamina = 10, intelligence = 10, agility = 10, lunacy = 0 } + } else - _chars = { - strength = chars.strength or 10, - stamina = chars.stamina or 10, - intelligence = chars.intelligence or 10, - agility = chars.agility or 10, - lunacy = chars.lunacy or 0, + chars = { + raw = { + strength = rawChars.strength or 10, + stamina = rawChars.stamina or 10, + intelligence = rawChars.intelligence or 10, + agility = rawChars.agility or 10, + lunacy = rawChars.lunacy or 0, + }, + final = { + strength = rawChars.strength or 10, + stamina = rawChars.stamina or 10, + intelligence = rawChars.intelligence or 10, + agility = rawChars.agility or 10, + lunacy = rawChars.lunacy or 0, + }, } end return setmetatable({ - hp = _chars["stamina"] * 2, + hp = chars.final["stamina"] * 2, mana = 10, -- я полагаю, у всех будет одинаковое кол-во маны (оно же кол-во действий) - initiative = _chars.agility, - chars = _chars, + chars = chars, class = class or "dev_warrior", isInTurnOrder = isInTurnOrder or true, amIAlive = true diff --git a/lib/effectbook.lua b/lib/effectbook.lua index 20bee55..72b0916 100644 --- a/lib/effectbook.lua +++ b/lib/effectbook.lua @@ -63,6 +63,15 @@ local aversionToDeath = effect.new { tag = "aversionToDeath" } +function aversionToDeath:afterCast(owner, intensity) + local stats = owner:has(Tree.behaviors.stats) + if not stats then return task.fromValue() end + stats:changeChar("agility", function(charAmount) + return 10 + end) + return task.fromValue() +end + function aversionToDeath:beforeDamage(owner, intensity, damage) local stats = owner:has(Tree.behaviors.stats) local effects = owner:has(Tree.behaviors.effects) @@ -85,6 +94,15 @@ function aversionToDeath:beforeTurn(owner, intensity) }, false end +function aversionToDeath:afterDelete(owner, intensity) + local stats = owner:has(Tree.behaviors.stats) + if not stats then return task.fromValue() end + stats:changeChar("agility", function(charAmount) + return -10 + end) + return task.fromValue() +end + ----------------- Effectbook & Sum ----------------- --- @alias EffectSumFunc fun(owner: Character, effect1: EffectTag, effect2: EffectTag): boolean diff --git a/lib/level/turn_order.lua b/lib/level/turn_order.lua index a166e62..fd880a8 100644 --- a/lib/level/turn_order.lua +++ b/lib/level/turn_order.lua @@ -4,7 +4,7 @@ local easing = require "lib.utils.easing" 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 + return astats.chars.final["agility"] > bstats.chars.final["agility"] end) return res end) diff --git a/lib/spell/effect.lua b/lib/spell/effect.lua index d818ac0..460854d 100644 --- a/lib/spell/effect.lua +++ b/lib/spell/effect.lua @@ -29,6 +29,16 @@ function effect:beforeBirth(owner, intensity) return taskUtils.fromValue(), true --- @type EffectFunc function effect:afterBirth(owner, intensity) return taskUtils.fromValue() end +--- Срабатывает перед удалением эффекта +--- +--- Возвращает, а можно ли удалить эффект? +--- @type EffectStatementFunc +function effect:beforeDelete(owner, intensity) return taskUtils.fromValue(), true end + +--- Срабатывает после удаления эффекта +--- @type EffectFunc +function effect:afterDelete(owner, intensity) return taskUtils.fromValue() end + --- Срабатывает перед смертью владельца эффекта --- --- Возвращает, умирает ли персонаж? diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 4c13c0a..2fe2c23 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -48,7 +48,6 @@ local regenerateMana = spell.new { onCast = function(caster, target) caster:try(Tree.behaviors.stats, function(stats) stats.mana = 10 - stats.initiative = stats.initiative + 10 end) local sprite = caster:has(Tree.behaviors.sprite) -- 2.47.2 From 3a566f447f93fed1c9b2e12f9d1d73ab20141586 Mon Sep 17 00:00:00 2001 From: neckrat Date: Mon, 11 May 2026 00:17:30 +0300 Subject: [PATCH 4/5] =?UTF-8?q?add=20healHealth=20=F0=9F=A4=AA=20?= =?UTF-8?q?=F0=9F=8D=AA=20&=20add=20before/afterRegeneration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/character/behaviors/effects.lua | 27 +++++++++++++++++++++++++++ lib/character/behaviors/stats.lua | 17 ++++++++++++++--- lib/spellbook.lua | 3 ++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/lib/character/behaviors/effects.lua b/lib/character/behaviors/effects.lua index d8b66e0..55d241a 100644 --- a/lib/character/behaviors/effects.lua +++ b/lib/character/behaviors/effects.lua @@ -190,4 +190,31 @@ function behavior:afterDamage() end end +--- должен вызываться перед регенерацией +--- +--- возвращает кол-во здоровья +--- @return Impact +function behavior:beforeRegeneration(amount) + local totalAmount = amount + for i, ef in ipairs(self.effectsPriority) do + local task1 + task1, totalAmount = book[ef]:beforeRegeneration(self.owner, self.effectsProperties[ef].intensity, + totalAmount or amount) + if task1 then + task1(function() end) + end + end + return totalAmount or amount +end + +--- должен вызываться после регенерации +function behavior:afterRegeneration() + for i, ef in ipairs(self.effectsPriority) do + local task1 = book[ef]:afterRegeneration(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + end +end + return behavior diff --git a/lib/character/behaviors/stats.lua b/lib/character/behaviors/stats.lua index 9d591b6..4f61825 100644 --- a/lib/character/behaviors/stats.lua +++ b/lib/character/behaviors/stats.lua @@ -34,9 +34,20 @@ function behavior:dealDamage(damage, impactType) local effects = self.owner:has(Tree.behaviors.effects) if effects then damageImpact = effects:beforeDamage(damageImpact) end self.hp = self.hp - damageImpact.intensity + if effects then effects:afterDamage() end self:checkStats() end +--- @param amount integer +--- @param impactType ImpactType +function behavior:healHealth(amount, impactType) + local healthImpact = impact(amount, impactType) + local effects = self.owner:has(Tree.behaviors.effects) + if effects then healthImpact = effects:beforeRegeneration(healthImpact) end + self.hp = self.hp + healthImpact.intensity + if effects then effects:afterRegeneration() end +end + --- позволяет изменять значение характеристики персонажа --- --- менять характеристики мы должны с помощью функции, которая возвращает значение на сколько мы должны изменить характеристику @@ -52,9 +63,9 @@ end --- --- отнимаем от стата 50%: `behavior:changeChar("strength", function (charAmount) return -charAmount / 2 end)` --- @param char Chars ---- @param func fun(charAmount: integer): integer charAmount здесь это сырое значение характеристики -function behavior:changeChar(char, func) - self.chars.final[char] = func(self.chars.raw[char]) +--- @param fn fun(charAmount: integer): integer charAmount здесь это сырое значение характеристики +function behavior:changeChar(char, fn) + self.chars.final[char] = fn(self.chars.raw[char]) end --- @param class? Class diff --git a/lib/spellbook.lua b/lib/spellbook.lua index 2fe2c23..07e19fa 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -48,6 +48,7 @@ local regenerateMana = spell.new { onCast = function(caster, target) caster:try(Tree.behaviors.stats, function(stats) stats.mana = 10 + stats:healHealth(10, "magic") end) local sprite = caster:has(Tree.behaviors.sprite) @@ -84,7 +85,7 @@ local attack = spell.new { local targetCharacterId = Tree.level.characterGrid:get(target) local targetCharacter = Tree.level.characters[targetCharacterId] targetCharacter:try(Tree.behaviors.stats, function(stats) - stats.hp = stats.hp - 4 + stats:dealDamage(4, "physic") end) local targetEffects = targetCharacter:has(Tree.behaviors.effects) -- 2.47.2 From dac314f40fce134905a29defb001b3a7491e5dd3 Mon Sep 17 00:00:00 2001 From: neckrat Date: Tue, 12 May 2026 10:37:50 +0300 Subject: [PATCH 5/5] =?UTF-8?q?microrefactor=20for=20development=20purpose?= =?UTF-8?q?=20=F0=9F=A4=AA=20=F0=9F=8D=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/character/behaviors/effects.lua | 2 ++ lib/utils/impact.lua | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/character/behaviors/effects.lua b/lib/character/behaviors/effects.lua index 55d241a..59087bb 100644 --- a/lib/character/behaviors/effects.lua +++ b/lib/character/behaviors/effects.lua @@ -166,6 +166,7 @@ end --- должен вызываться перед получением урона --- --- возвращает получаемый урон +--- @param damage Impact --- @return Impact function behavior:beforeDamage(damage) local totalDamage = damage @@ -193,6 +194,7 @@ end --- должен вызываться перед регенерацией --- --- возвращает кол-во здоровья +--- @param amount Impact --- @return Impact function behavior:beforeRegeneration(amount) local totalAmount = amount diff --git a/lib/utils/impact.lua b/lib/utils/impact.lua index dc9f4aa..02c2432 100644 --- a/lib/utils/impact.lua +++ b/lib/utils/impact.lua @@ -1,6 +1,6 @@ --- @alias ImpactType "physic"|"magic" ---- Представляет из себя некое "взаимодействие", которое мы должны применить к игроку в зависимости от контекста, +--- Представляет из себя некое "взаимодействие", которое мы должны применить к персонажу в зависимости от контекста, --- например, нанести урон. --- @class Impact --- @field intensity integer -- 2.47.2