231 lines
9.8 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>, nil -- бред конечно, но иначе всё в жёлтом
--- @alias EffectStatementFunc fun(owner: Character, intensity: integer): Task<nil>, boolean
--- @alias EffectDamageFunc fun(owner: Character, intensity: integer, damage: integer): Task<nil>, integer
--- @alias EffectRegenFunc fun(owner: Character, intensity: integer, amountHp: integer): Task<nil>, integer
--- @alias EffectData { tag: string, [string]: EffectFunc|EffectStatementFunc|EffectDamageFunc|EffectRegenFunc }
--- Срабатывает перед применением эффекта
---
--- Возвращает, а можно ли применить эффект?
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>, boolean
function effect:beforeBirth(owner, intensity) return taskUtils.wait {}, true end
--- Срабатывает после применения эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterBirth(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед смертью владельца эффекта
---
--- Возвращает, умирает ли персонаж?
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>, boolean
function effect:beforeDeath(owner, intensity) return taskUtils.wait {}, true end
--- Срабатывает после смерти владельца эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterDeath(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед ходом владельца эффекта
---
--- Возвращает, будет ли персонаж ходить?
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>, boolean
function effect:beforeTurn(owner, intensity) return taskUtils.wait {}, true end
--- Срабатывает после хода владельца эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterTurn(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед кастом заклинания владельцем эффекта
---
--- Возвращает, произойдёт ли каст?
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>, boolean
function effect:beforeCast(owner, intensity) return taskUtils.wait {}, true end
--- Срабатывает после каста заклинания владельцем эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterCast(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед нанесением урона владельцем эффекта
---
--- Возвращает урон, который собираются нанести
--- @param owner Character
--- @param intensity integer
--- @param damage integer
--- @return Task<nil>, integer
function effect:beforeAttack(owner, intensity, damage) return taskUtils.wait {}, damage end
--- Срабатывает после нанесения урона владельцем эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterAttack(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед получением урона владельцем эффекта
---
--- Возвращает урон, который должны получить
--- @param owner Character
--- @param intensity integer
--- @param damage integer
--- @return Task<nil>, integer
function effect:beforeDamage(owner, intensity, damage) return taskUtils.wait {}, damage end
--- Срабатывает после получения урона владельцем эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterDamage(owner, intensity) return taskUtils.wait {} end
--- Срабатывает перед регенерацией здоровья владельцем эффекта
---
--- Возвращает количество здоровья, которое должно быть восстановлено
--- @param owner Character
--- @param intensity integer
--- @param amountHp integer кол-во хп для регена
--- @return Task<nil>, integer
function effect:beforeRegeneration(owner, intensity, amountHp) return taskUtils.wait {}, amountHp end
--- Срабатывает после регенерации здоровья владельцем эффекта
--- @param owner Character
--- @param intensity integer
--- @return Task<nil>
function effect:afterRegeneration(owner, intensity) return taskUtils.wait {} end
function effect:update(dt) end
function effect:draw() end
--- дип сравнение эффектов
--- @param other Effect
--- @return boolean
function effect:__eq(other)
return utils.deepComprasion(self, other)
end
--- @param data EffectData
--- @return Effect
local function new(data)
local newEffect = setmetatable({
tag = data.tag
}, effect)
function newEffect:beforeBirth(owner, intensity)
if not data.beforeBirth then return taskUtils.wait {}, true end
local task, statement = data.beforeBirth(owner, intensity)
return task, statement
end
function newEffect:afterBirth(owner, intensity)
if not data.afterBirth then return taskUtils.wait {} end
return data.afterBirth(owner, intensity)
end
function newEffect:beforeDeath(owner, intensity)
if not data.beforeDeath then return taskUtils.wait {}, true end
local task, statement = data.beforeBirth(owner, intensity)
return task, statement
end
function newEffect:afterDeath(owner, intensity)
if not data.afterDeath then return taskUtils.wait {} end
return data.afterDeath(owner, intensity)
end
function newEffect:beforeTurn(owner, intensity)
if not data.beforeTurn then return taskUtils.wait {}, true end
local task, statement = data.beforeBirth(owner, intensity)
return task, statement
end
function newEffect:afterTurn(owner, intensity)
if not data.afterTurn then return taskUtils.wait {} end
return data.afterTurn(owner, intensity)
end
function newEffect:beforeCast(owner, intensity)
if not data.beforeCast then return taskUtils.wait {}, true end
local task, statement = data.beforeBirth(owner, intensity)
return task, statement
end
function newEffect:afterCast(owner, intensity)
if not data.afterCast then return taskUtils.wait {} end
return data.afterCast(owner, intensity)
end
function newEffect:beforeAttack(owner, intensity, damage)
if not data.beforeAttack then return taskUtils.wait {}, damage end
local task, newDamage = data.beforeDamage(owner, intensity, damage)
return task, newDamage
end
function newEffect:afterAttack(owner, intensity)
if not data.afterAttack then return taskUtils.wait {} end
return data.afterAttack(owner, intensity)
end
function newEffect:beforeDamage(owner, intensity, damage)
if not data.beforeDamage then return taskUtils.wait {}, damage end
local task, newDamage = data.beforeDamage(owner, intensity, damage)
return task, newDamage
end
function newEffect:afterDamage(owner, intensity)
if not data.afterDamage then return taskUtils.wait {} end
return data.afterDamage(owner, intensity)
end
function newEffect:beforeRegeneration(owner, intensity, amountHp)
if not data.beforeRegeneration then return taskUtils.wait {}, amountHp end
local task, newAmountHp = data.beforeRegeneration(owner, intensity, amountHp)
return task, newAmountHp
end
function newEffect:afterRegeneration(owner, intensity)
if not data.afterRegeneration then return taskUtils.wait {} end
return data.afterRegeneration(owner, intensity)
end
--- дип сравнение эффектов
--- @param other Effect
--- @return boolean
function newEffect:__eq(other)
return utils.deepComparison(self, other)
end
return newEffect
end
return { new = new }