diff --git a/assets/audio/sounds/meow.ogg b/assets/audio/sounds/meow.ogg new file mode 100644 index 0000000..3a7cc9c --- /dev/null +++ b/assets/audio/sounds/meow.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa52fa051a07aad736458e0f0497eabfdcb66685484fba338209291cd484c83f +size 30606 diff --git a/lib/annotations.lua b/lib/annotations.lua index a6be927..00ae451 100644 --- a/lib/annotations.lua +++ b/lib/annotations.lua @@ -9,5 +9,6 @@ Tree.behaviors.positioned = require "character.behaviors.positioned" Tree.behaviors.tiled = require "character.behaviors.tiled" Tree.behaviors.cursor = require "character.behaviors.cursor" Tree.behaviors.ai = require "lib.character.behaviors.ai" +Tree.behaviors.effects = require "lib.character.behaviors.effects" --- @alias voidCallback fun(): nil diff --git a/lib/character/behaviors/effects.lua b/lib/character/behaviors/effects.lua new file mode 100644 index 0000000..3099652 --- /dev/null +++ b/lib/character/behaviors/effects.lua @@ -0,0 +1,187 @@ +local task = require "lib.utils.task" +local efb = require "lib.effectbook" +local book = efb.book + +--- ===========ЛОГИКА ЭФФЕКТОВ И ЧТО С ЭТИМ ЕДЯТ=========== +--- читать здесь: https://docs.google.com/document/d/1Hxa5dOLaeRpLQOs5H-oIDDuLLhKbDw40lR9d62Zb4Tg/edit?usp=sharing +--- и здесь: https://docs.google.com/document/d/1jvhuM3mxqYSQTEM8m-WL-uUSie9QRsZOCCUEiw9ZqzM/edit?tab=t.0 + +--- behavior thats holds all effects that we applied +--- @class EffectsBehavior : Behavior +--- @field effectsPriority EffectTag[] хранит эффекты в порядке их применения +--- @field effectsProperties table хранит характеристики эффектов +local behavior = {} +behavior.__index = behavior +behavior.id = "effects" + +--- @return EffectsBehavior +function behavior.new() + return setmetatable({ + effectsPriority = {}, + effectsProperties = {}, + }, behavior) +end + +--- проверяет, можно ли наложить эффект и при наложении его применяет +--- @param effect EffectTag +--- @param stacks integer +--- @param intensity integer +function behavior:addEffect(effect, stacks, intensity) + local task1, birthStatement = book[effect]:beforeBirth(self.owner, intensity) + if task1 then + task1(function() end) + end + if not birthStatement then return end + + -- проверка на сумму, и её применение + for i, ef in ipairs(self.effectsPriority) do + if efb.sums[effect] then + if efb.sums[effect][ef] then + if not efb.sums[effect][ef](self.owner, effect, ef) then return end + end + elseif efb.sums[ef] then + if efb.sums[ef][effect] then + if not efb.sums[ef][effect](self.owner, ef, effect) then return end + end + end + end + + book[effect]:onBirth(self.owner, stacks, intensity) + + local task3 = book[effect]:afterBirth(self.owner, intensity) + if task3 then + task3(function() + print("[Effects]: мы применили эффект!!") + end) + end +end + +--- Удаляет один эффект по порядку +--- @param effect EffectTag +function behavior:deleteEffect(effect) + self.effectsProperties[effect] = nil + for i, ef in ipairs(self.effectsPriority) do + if ef == effect then + table.remove(self.effectsPriority, i) + return + end + end +end + +--- О ДААА ЭТА ФУНКЦИЯ МЕНЯЕТ СОСТОЯНИЕ О ДАААААА О ДАААААААААА +--- @param effect EffectTag +--- @param amount integer +function behavior:deleteStacks(effect, amount) + print("[Effects]: удаляем стаки!!") + self.effectsProperties[effect].stacks = self.effectsProperties[effect].stacks - + amount -- !!!!!!!!!!!!!!!! <<<<< 21+ only + if self.effectsProperties[effect].stacks <= 0 then + print("[Effects]:", effect, "ДОЛЖЕН БЫТЬ СТЁРТ") + self:deleteEffect(effect) + print("[Effects]:", effect, "СТЁРТ") + end +end + +--- должна вызываться перед смертью персонажа; +--- +--- возвращает, убивать ли персонажа +--- @return boolean +function behavior:beforeDeath() + for i, ef in ipairs(self.effectsPriority) do + local task1, deathStatement = book[ef]:beforeDeath(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + if deathStatement == false then return false end + end + return true +end + +--- должна вызываться после смерти персонажа (может ли такая ситуация возникнуть вообще?) +function behavior:afterDeath() + for i, ef in ipairs(self.effectsPriority) do + local task1 = book[ef]:afterDeath(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + end +end + +--- должен вызываться в начале хода +--- +--- возвращает, может ли персонаж сделать ход? +--- @return boolean +function behavior:beforeTurn() + for i, ef in ipairs(self.effectsPriority) do + local task1, turnStatement = book[ef]:beforeTurn(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + if turnStatement == false then return false end + end + return true +end + +--- должен вызываться в конце хода +function behavior:afterTurn() + for i, ef in ipairs(self.effectsPriority) do + local task1 = book[ef]:afterTurn(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + end +end + +--- должен вызываться перед кастом спелла +--- +--- возвращает, может ли персонаж скастовать спелл? +--- @return boolean +function behavior:beforeCast() + for i, ef in ipairs(self.effectsPriority) do + local task1, castStatement = book[ef]:beforeCast(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + if castStatement == false then return false end + end + return true +end + +--- должен вызываться после каста спелла +function behavior:afterCast() + for i, ef in ipairs(self.effectsPriority) do + local task1 = book[ef]:afterCast(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + end +end + +--- должен вызываться перед получением урона +--- +--- возвращает получаемый урон +--- @return integer +function behavior:beforeDamage(damage) + local totalDamage = damage + for i, ef in ipairs(self.effectsPriority) do + local task1 + task1, totalDamage = book[ef]:beforeDamage(self.owner, self.effectsProperties[ef].intensity, + totalDamage or damage) + if task1 then + task1(function() end) + end + end + return totalDamage or damage +end + +--- должен вызываться после получения урона +function behavior:afterDamage() + for i, ef in ipairs(self.effectsPriority) do + local task1 = book[ef]:afterDamage(self.owner, self.effectsProperties[ef].intensity) + if task1 then + task1(function() end) + end + end +end + +return behavior diff --git a/lib/character/behaviors/spellcaster.lua b/lib/character/behaviors/spellcaster.lua index aa0ad60..8974c39 100644 --- a/lib/character/behaviors/spellcaster.lua +++ b/lib/character/behaviors/spellcaster.lua @@ -20,6 +20,9 @@ function behavior.new(spellbook) end function behavior:endCast() + self.owner:try(Tree.behaviors.effects, function(effects) + effects:afterCast() + end) self.state = "idle" self.cast = nil Tree.level.turnOrder:reorder() diff --git a/lib/character/behaviors/stats.lua b/lib/character/behaviors/stats.lua index d377882..4b8a075 100644 --- a/lib/character/behaviors/stats.lua +++ b/lib/character/behaviors/stats.lua @@ -6,10 +6,27 @@ --- @field initiative integer --- @field class Class --- @field isInTurnOrder boolean +--- @field amIAlive boolean local behavior = {} behavior.__index = behavior behavior.id = "stats" +--- план прост, если что-то не так, то мы просто убиваем бехавиор (по крайней мере так должно было быть, но пиаш мне запретил :sob:) +function behavior:checkStats() + -- if self.hp <= 0 then behavior:die() end + if self.hp <= 0 then + self.amIAlive = false + end +end + +--- @param damage integer +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:checkStats() +end + --- @param hp? integer --- @param mana? integer --- @param initiative? integer @@ -22,6 +39,7 @@ function behavior.new(hp, mana, initiative, class, isInTurnOrder) initiative = initiative or 10, class = class or "dev_warrior", isInTurnOrder = isInTurnOrder or true, + amIAlive = true }, behavior) end diff --git a/lib/effectbook.lua b/lib/effectbook.lua new file mode 100644 index 0000000..3f6f3f8 --- /dev/null +++ b/lib/effectbook.lua @@ -0,0 +1,123 @@ +local task = require "lib.utils.task" +local effect = require "lib.spell.effect" +local easing = require "lib.utils.easing" + +--- некое уникальное строковое значение +--- @alias EffectTag string + +--- Кровотечение. +--- +--- Наносит `intensity` урона перед началом каждого хода. +local bleeding = effect.new({ + tag = "bleeding" +}) + +function bleeding:afterBirth(owner, intensity) + local light = require "lib/character/character".spawn("Bleeding Light Effect") + light:addBehavior { + 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 }), + } + + return task.wait({ task.chain(task.tween(light:has(Tree.behaviors.light) --[[@as LightBehavior]], + { intensity = 1, color = Vec3 { 0, 0., 0. } }, 800, easing.easeInCubic), function() + light:die() + return task.fromValue() + end) }) +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) + return task.wait({ sprite:animate("hurt") }), true +end + +function bleeding:afterTurn(owner, intensity) + local behavior = owner:has(Tree.behaviors.effects) + if not behavior then + print('[EffectBook]: yo man what the hell wheres your behavior how thats possible please stop thats not normal') + else + behavior:deleteStacks("bleeding", 1) + end + return task.wait {} +end + +--- meow +function bleeding:afterCast(owner, intensity) + Tree.audio:play(Tree.assets.files.audio.sounds.meow) + return task.wait {} +end + +function bleeding:beforeCast(owner, intensity) + Tree.audio:play(Tree.assets.files.audio.sounds.meow) + return task.wait {}, true +end + +--- Отвращение к смерти. +--- +--- Спасает от смертельного урона, оставляя одно очко здоровья. Персонаж не может ходить до тех пор, пока эффект не сработает. +local aversionToDeath = effect.new { + tag = "aversionToDeath" +} + +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 + effects:deleteStacks("aversionToDeath", 1) + -- тут должен быть какой-нибудь классный спецэффект, но я не умею в шейдеры + return task.wait({}), stats.hp - 1 + end + return task.wait {}, damage +end + +function aversionToDeath:beforeTurn(owner, intensity) + local sprite = owner:has(Tree.behaviors.sprite) + if not sprite then + return task.wait {}, false + end + return task.wait { + sprite:animate("hurt") + }, false +end + +----------------- Effectbook & Sum ----------------- + +--- @alias EffectSumFunc fun(owner: Character, effect1: EffectTag, effect2: EffectTag): boolean + +--- Принимает таблицу, в ключах которых тэги эффектов, которые мы хотим просуммировать, и в значениях которых функция, +--- возвращающая булево значение: применять ли эффект после суммирования. +--- @type table> +local sums = {} + +--- Сумма кровотечения и отвращения к смерти, (в целях разработки) удаляет оба эффекта, не позволяя дальше применять эффект +sums.bleeding = { + aversionToDeath = function(owner, effect1, effect2) + print("[EffectBook]: применяем сумму, удаляем оба эффекта") + local behaviorEffect = owner:has(Tree.behaviors.effects) + if not behaviorEffect then + print( + "[EffectBook]: yo man what the hell wheres your behavior how thats possible please stop thats not normal") + return true + end + behaviorEffect:deleteEffect(effect1) + behaviorEffect:deleteEffect(effect2) + return false + end +} + +--- @class EffectBook +--- @field sums table> +--- @field book table +local effectbook = { + sums = sums, + book = { + bleeding = bleeding, + aversionToDeath = aversionToDeath + } +} + +return effectbook diff --git a/lib/level/turn_order.lua b/lib/level/turn_order.lua index 08e9eec..a166e62 100644 --- a/lib/level/turn_order.lua +++ b/lib/level/turn_order.lua @@ -43,6 +43,15 @@ function turnOrder:next() char:try(Tree.behaviors.positioned, function(positioned) Tree.level.camera:animateTo(positioned.position, 1500, easing.easeInOutCubic)( function() + -- проверяем, позволяют ли эффекты нам сходить + if char:try(Tree.behaviors.effects, function(effects) + -- print("[TurnOrder]: ну мы пытаемся применить эффект к", char.id) + return effects:beforeTurn() + end) == false then + self:next() + return + end + if char:has(Tree.behaviors.ai) then char:has(Tree.behaviors.ai):makeTurn()( function() @@ -69,6 +78,9 @@ function turnOrder:endRound() char:try(Tree.behaviors.spellcaster, function(spellcaster) spellcaster:processCooldowns() end) + char:try(Tree.behaviors.effects, function(effects) + effects:afterTurn() + end) end self.actedQueue, self.pendingQueue = self.pendingQueue, self.actedQueue diff --git a/lib/spell/effect.lua b/lib/spell/effect.lua new file mode 100644 index 0000000..863f474 --- /dev/null +++ b/lib/spell/effect.lua @@ -0,0 +1,169 @@ +local utils = require "lib.utils.utils" +local taskUtils = require "lib.utils.task" + +--- Некоторое свойство, что можно наложить на персонажа. Позволяет реализовать такие вещи как DOT'ы +--- и вообще, что душа поживает. +--- +--- У каждого эффекта есть тэг и функции триггеры (например, `beforeTurn`, что срабатывает перед началом хода персонажа и так далее). +--- Каждая функция триггер делится на два типа, `before...` и `after...`. Каждая из них возвращает `task`, для того чтобы +--- проиграть анимацию, например. Функции типа `before...` также возвращают по мимо таска некоторое значение, зависящее от +--- конкретной функции. +--- @class Effect +--- @field tag string +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 EffectData { tag: string } + +--- Срабатывает перед применением эффекта +--- +--- Возвращает, а можно ли применить эффект? +--- @param owner Character +--- @param intensity integer +--- @return Task, boolean +function effect:beforeBirth(owner, intensity) return taskUtils.fromValue(), true end + +--- Срабатывает после применения эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +function effect:afterBirth(owner, intensity) return taskUtils.fromValue() end + +--- Срабатывает перед смертью владельца эффекта +--- +--- Возвращает, умирает ли персонаж? +--- @param owner Character +--- @param intensity integer +--- @return Task, boolean +function effect:beforeDeath(owner, intensity) return taskUtils.fromValue(), true end + +--- Срабатывает после смерти владельца эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +function effect:afterDeath(owner, intensity) return taskUtils.fromValue() end + +--- Срабатывает перед ходом владельца эффекта +--- +--- Возвращает, будет ли персонаж ходить? +--- @param owner Character +--- @param intensity integer +--- @return Task, boolean +function effect:beforeTurn(owner, intensity) return taskUtils.fromValue(), true end + +--- Срабатывает после хода владельца эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +function effect:afterTurn(owner, intensity) return taskUtils.fromValue() end + +--- Срабатывает перед кастом заклинания владельцем эффекта +--- +--- Возвращает, произойдёт ли каст? +--- @param owner Character +--- @param intensity integer +--- @return Task, boolean +function effect:beforeCast(owner, intensity) return taskUtils.fromValue(), true end + +--- Срабатывает после каста заклинания владельцем эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +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 + +--- Срабатывает после нанесения урона владельцем эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +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 + +--- Срабатывает после получения урона владельцем эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +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 + +--- Срабатывает после регенерации здоровья владельцем эффекта +--- @param owner Character +--- @param intensity integer +--- @return Task +function effect:afterRegeneration(owner, intensity) return taskUtils.fromValue() end + +--- Функция, что задаёт правила присвоения эффекта +--- @param owner Character +--- @param stacks integer +--- @param intensity integer +function effect:onBirth(owner, stacks, intensity) + local effects = owner:has(Tree.behaviors.effects) + if not effects then return end + -- проверяем на наличие такого же эффекта + if effects.effectsProperties[self.tag] then + local i = 1 + while i < #effects.effectsPriority and effects.effectsPriority[i] ~= self.tag do + i = i + 1 + end + local ef = table.remove(effects.effectsPriority, i) + effects.effectsPriority[#effects.effectsPriority + 1] = ef + else + effects.effectsPriority[#effects.effectsPriority + 1] = self.tag + end + effects.effectsProperties[self.tag] = { + stacks = stacks, + intensity = intensity + } +end + +function effect:update(dt) end + +function effect:draw() end + +--- дип сравнение эффектов +--- @param other Effect +--- @return boolean +function effect:__eq(other) + return utils.deepComparison(self, other) +end + +--- @param data EffectData +--- @return Effect +local function new(data) + local newEffect = setmetatable({ + tag = data.tag, + }, effect) + + return newEffect +end + +return { new = new } diff --git a/lib/spell/spell.lua b/lib/spell/spell.lua index e57ffba..11e3e45 100644 --- a/lib/spell/spell.lua +++ b/lib/spell/spell.lua @@ -123,6 +123,13 @@ function spell.new(data) return end + -- проверка на возможность каста + if not caster:try(Tree.behaviors.effects, function(effects) + return effects:beforeCast() + end) then + return + end + caster:try(Tree.behaviors.stats, function(stats) stats.mana = stats.mana - self.baseCost end) @@ -130,6 +137,8 @@ function spell.new(data) caster:try(Tree.behaviors.spellcaster, function(spellcaster) spellcaster.cooldowns[self.tag] = self.baseCooldown end) + + return data.onCast(caster, target) end diff --git a/lib/spellbook.lua b/lib/spellbook.lua index d3d4d61..4c13c0a 100644 --- a/lib/spellbook.lua +++ b/lib/spellbook.lua @@ -52,7 +52,8 @@ local regenerateMana = spell.new { end) local sprite = caster:has(Tree.behaviors.sprite) - if not sprite then return end + local effects = caster:has(Tree.behaviors.effects) + if not sprite or not effects then return end -- и тут возможно на эффекты проверять не стоит print(caster.id, "has regenerated mana and gained initiative") local light = require "lib/character/character".spawn("Light Effect") @@ -67,7 +68,8 @@ local regenerateMana = spell.new { light:die() return task.fromValue() end), - sprite:animate("hurt") + sprite:animate("hurt"), + effects:addEffect("aversionToDeath", 1, 1), } end } @@ -86,9 +88,10 @@ local attack = spell.new { stats.hp = stats.hp - 4 end) + local targetEffects = targetCharacter:has(Tree.behaviors.effects) local sprite = caster:has(Tree.behaviors.sprite) local targetSprite = targetCharacter:has(Tree.behaviors.sprite) - if not sprite or not targetSprite then return end + if not sprite or not targetSprite or not targetEffects then return end -- проверять на эффект может и не стоит caster:try(Tree.behaviors.positioned, function(b) b:lookAt(target) end) @@ -111,7 +114,8 @@ local attack = spell.new { light:die() return task.fromValue() end), - targetSprite:animate("hurt") + targetSprite:animate("hurt"), + targetEffects:addEffect("bleeding", 3, 3) } end ), diff --git a/lib/utils/utils.lua b/lib/utils/utils.lua index b5c0362..7920e87 100644 --- a/lib/utils/utils.lua +++ b/lib/utils/utils.lua @@ -74,4 +74,19 @@ function P.lerp(from, to, t) return from + (to - from) * t end +--- Compares two tables by their fields +--- @param t1 table +--- @param t2 table +--- @return boolean +function P.deepComparison(t1, t2) + for k, v in pairs(t1) do + if type(v) == "table" and type(t2[k]) == "table" then + if not P.deepComparison(v, t2[k]) then return false end + elseif t2[k] ~= v then + return false + end + end + return true +end + return P diff --git a/main.lua b/main.lua index 112fc59..76792bc 100644 --- a/main.lua +++ b/main.lua @@ -15,16 +15,17 @@ function love.load() testLayout = require "lib.simple_ui.level.layout" local chars = { - character.spawn("Foodor") - :addBehavior { - Tree.behaviors.residentsleeper.new(), - Tree.behaviors.stats.new(nil, nil, 1), - Tree.behaviors.positioned.new(Vec3 { 1, 1 }), - Tree.behaviors.tiled.new(), - Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), - Tree.behaviors.shadowcaster.new(), - Tree.behaviors.spellcaster.new() - }, + -- character.spawn("Foodor") + -- :addBehavior { + -- Tree.behaviors.residentsleeper.new(), + -- Tree.behaviors.stats.new(nil, nil, 1), + -- Tree.behaviors.positioned.new(Vec3 { 3, 3 }), + -- Tree.behaviors.tiled.new(), + -- Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), + -- Tree.behaviors.shadowcaster.new(), + -- Tree.behaviors.spellcaster.new(), + -- Tree.behaviors.effects.new() + -- }, character.spawn("Foodor") :addBehavior { Tree.behaviors.residentsleeper.new(), @@ -33,7 +34,8 @@ function love.load() Tree.behaviors.tiled.new(), Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), Tree.behaviors.shadowcaster.new(), - Tree.behaviors.spellcaster.new() + Tree.behaviors.spellcaster.new(), + Tree.behaviors.effects.new() }, character.spawn("Foodor") :addBehavior { @@ -43,19 +45,33 @@ function love.load() Tree.behaviors.tiled.new(), Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), Tree.behaviors.shadowcaster.new(), - Tree.behaviors.spellcaster.new() - }, - character.spawn("BOAR") - :addBehavior { - Tree.behaviors.residentsleeper.new(), - Tree.behaviors.stats.new(nil, nil, 2), - Tree.behaviors.positioned.new(Vec3 { 5, 5 }), - Tree.behaviors.tiled.new(), - Tree.behaviors.sprite.new(Tree.assets.files.sprites.boar), - Tree.behaviors.shadowcaster.new(), Tree.behaviors.spellcaster.new(), - Tree.behaviors.ai.new("dev_warrior") + Tree.behaviors.effects.new() }, + -- character.spawn("Baris") + -- :addBehavior { + -- Tree.behaviors.residentsleeper.new(), + -- Tree.behaviors.stats.new(nil, nil, 2), + -- Tree.behaviors.positioned.new(Vec3 { 5, 5 }), + -- Tree.behaviors.tiled.new(), + -- Tree.behaviors.sprite.new(Tree.assets.files.sprites.character), + -- Tree.behaviors.shadowcaster.new(), + -- Tree.behaviors.spellcaster.new(), + -- Tree.behaviors.ai.new(), + -- Tree.behaviors.effects.new() + -- }, + -- character.spawn("BOAR") + -- :addBehavior { + -- Tree.behaviors.residentsleeper.new(), + -- Tree.behaviors.stats.new(nil, nil, 2), + -- Tree.behaviors.positioned.new(Vec3 { 7, 7 }), + -- Tree.behaviors.tiled.new(), + -- Tree.behaviors.sprite.new(Tree.assets.files.sprites.boar), + -- Tree.behaviors.shadowcaster.new(), + -- Tree.behaviors.spellcaster.new(), + -- Tree.behaviors.ai.new(), + -- Tree.behaviors.effects.new() + -- }, } for id, _ in pairs(chars) do