miduo_client/Assets/ManagedResources/~Lua/Modules/Battle/Logic/Base/Buff.lua

510 lines
18 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

Buff = {}
local floor = math.floor
local buffPoolList = {}
local BuffRegister = {
[BuffName.PropertyChange] = "PropertyChange",
[BuffName.Control] = "Control",
[BuffName.DOT] = "DOT",
[BuffName.HOT] = "HOT",
[BuffName.Shield] = "Shield",
[BuffName.Immune] = "Immune",
[BuffName.Curse] = "Curse",
[BuffName.KylinMark] = "KylinMark",
[BuffName.Exile] = "Exile",
[BuffName.NoDead] = "NoDead",
[BuffName.Aura] = "Aura",
[BuffName.Brand] = "Brand",
[BuffName.Blood] = "Blood",
[BuffName.BanBlood] = "BanBlood",
[BuffName.SigilSign] = "SigilSign",
[BuffName.CommonSign] = "CommonSign",
[BuffName.BreakArmor] = "BreakArmor",
[BuffName.AddAttack] = "AddAttack",
[BuffName.Suppress] = "Suppress",
[BuffName.BuDongSign] = "BuDongSign",
[BuffName.FalseNoDead] = "FalseNoDead",
[BuffName.SuckBlood] = "SuckBlood",
}
local getBuff = function(type)
if not buffPoolList[type] then
buffPoolList[type] = BattleObjectPool.New(function (type)
return require("Modules/Battle/Logic/Buff/"..BuffRegister[type]):New()
end)
end
return buffPoolList[type]:Get(type)
end
local putBuff = function(buff)
if buffPoolList[buff.type] then
buffPoolList[buff.type]:Put(buff)
end
end
local buffListPool = BattleObjectPool.New(function ()
return BattleList.New()
end)
function Buff:New()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function Buff.Create(caster, type, duration, ...)
local buff = getBuff(type)
buff.type = type
buff.id = BuffManager.GenerateBuffId()
buff.caster = caster
buff.disperse = false --该值为true时buff在下一帧被清除
buff.cover = false --该值为true时同类型新buff会覆盖旧buff
buff.clear = true --该值为false时,buff不可被驱散除非无条件驱散
buff.duration = duration or 0 --持续时间为0时buff永久存在
buff.interval = -1 --间隔帧为0时每回合触发小于0不触发 默认不触发OnTrigger
-- buff.framePass = 0
buff.roundPass = 0
buff.startRound = BattleLogic.GetCurRound()
-- 重置buff状态
buff.isBuff = nil
buff.isDeBuff = nil
buff:SetData(...)
return buff
end
-- 设置触发间隔
function Buff:SetInterval(interval)
self.interval = interval
return self
end
-- 改变buff的轮次
function Buff:ChangeBuffDuration(type, value)
-- 永久存在改变无效
if self.duration <= 0 then
return
end
-- 计算
local finalDuration = BattleUtil.ErrorCorrection(BattleUtil.CountValue(self.duration, value, type))
self.duration = floor(finalDuration)
if self.roundDuration then
self.roundDuration = finalDuration
end
-- 发送事件
self.caster.Event:DispatchEvent(BattleEventName.BuffDurationChange, self)
end
function Buff:CompareWith(buff)
if self.type == buff.type then
if self.OnCompare then
return self:OnCompare(buff)
else
return true
end
else
return false
end
end
BuffManager = {}
BuffManager.__index = BuffManager
local curBuffId
function BuffManager.New()
local instance = {owner=0, buffQueue = BattleQueue.New(), buffDic = BattleDictionary.New()}
setmetatable(instance, BuffManager)
return instance
end
-- 根据类型获取buff的刷新级别
-- local _TypeToLevel = {
-- [] = ,
-- }
function BuffManager.GetLevelByType(type)
end
function BuffManager:Init()
while self.buffQueue.size > 0 do
putBuff(self.buffQueue:Dequeue())
end
for i = 1, self.buffDic.size do
local list = self.buffDic.vList[i]
for j=1, list.size do
putBuff(list.buffer[j])
end
list:Clear()
buffListPool:Put(list)
end
self.buffDic:Clear()
curBuffId = 0
end
function BuffManager.GenerateBuffId()
if not curBuffId then
curBuffId = 0
end
curBuffId = curBuffId + 1
return curBuffId
end
function BuffManager:AddBuff(target, buff)
-- 灵兽无效
if target.type == BattleUnitType.Monster then
return
end
buff.target = target
self.buffQueue:Enqueue(buff)
-- buff.frameDuration = floor(buff.duration * BattleLogic.GameFrameRate)
--if buff.isBuff then --TODO:增益buff持续时间加成
-- local buffBocus = buff.caster:GetRoleData(RoleDataName.BuffBocus)
-- buff.frameDuration = floor(buff.duration * (1 + buffBocus + buff.exCtrlTime) * BattleLogic.GameFrameRate)
--end
--
--if buff.isDeBuff then --TODO:减益buff持续时间减免
-- local debuffReduce = self.owner:GetRoleData(RoleDataName.DebuffReduce)
-- buff.frameDuration = floor(buff.duration * (1 - debuffReduce - buff.exCtrlTime) * BattleLogic.GameFrameRate)
--end
-- buff.frameInterval = floor(buff.interval * BattleLogic.GameFrameRate)
buff.roundDuration = buff.duration
buff.roundInterval = buff.interval
buff.caster.Event:DispatchEvent(BattleEventName.BuffCaster, buff)
buff.caster.Event:DispatchEvent(BattleEventName.BuffCaster2, buff)
buff.target.Event:DispatchEvent(BattleEventName.BuffBeAdd, buff)
BattleLogManager.Log(
"Role add Buff",
"buff.type", tostring(buff.type),
"target.camp==", tostring(target.camp),
"target.position", tostring(target.position),
"caster.camp==", tostring(buff.caster.camp),
"caster.position", tostring(buff.caster.position)
)
-- 用于记录统计
BattleLogic.Event:DispatchEvent(BattleEventName.RecordBuff, buff.caster, buff.target, buff)
end
function BuffManager:QueryBuff(target, checkFunc)
for i=1, self.buffDic.size do
local list = self.buffDic.vList[i]
for j=1, list.size do
local buff = list.buffer[j]
if buff.target == target then
if checkFunc then
checkFunc(buff)
end
end
end
end
end
function BuffManager:GetBuff(target, checkFunc)
local blist = {}
for i=1, self.buffDic.size do
local list = self.buffDic.vList[i]
for j=1, list.size do
local buff = list.buffer[j]
if buff.target == target then
if not checkFunc or checkFunc(buff)then
table.insert(blist, buff)
end
end
end
end
return blist
end
--根据条件获取所有的buff
function BuffManager:GetAllBuffByFunc(checkFunc)
local blist = {}
for i=1, self.buffDic.size do
local list = self.buffDic.vList[i]
for j=1, list.size do
local buff = list.buffer[j]
if not checkFunc or checkFunc(buff)then
table.insert(blist, buff)
end
end
end
return blist
end
function BuffManager:HasBuff(target, type, checkFunc,caster,dotType)
--如果当前是判断燃烧buff and 当前目标是攻击的主目标则直接返回true
if type== BuffName.DOT and caster and dotType and dotType==1 and (caster.curMainTarget==target or caster.isAllBurn) then
return true
end
if self.buffDic.kvList[type] then
local buffList = self.buffDic.kvList[type]
for i=1, buffList.size do
local v = buffList.buffer[i]
if v.target == target then
if (not checkFunc or (checkFunc and checkFunc(v))) then
return true
end
end
end
end
return false
end
--func为nil时无条件清除否则判定clear值执行func
function BuffManager:ClearBuff(target, func)
for i = 1, self.buffDic.size do
local list = self.buffDic.vList[i]
if list.size > 0 then
local idx = 1
while idx <= list.size do
local buff = list.buffer[idx]
if buff.target == target and (not func or (func and buff.clear and func(buff))) then
if not buff.target:IsRealDead() then
if buff.type== BuffName.Shield then
buff.target.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Shield)
elseif buff.type== BuffName.DOT or buff.type==BuffName.Control or buff.type==BuffName.BanBlood or buff.type==BuffName.Curse then
buff.target.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.clear)
elseif buff.type==BuffName.PropertyChange and buff.changeType and (buff.changeType==3 or buff.changeType==4 )then
buff.target.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.clear)
end
end
buff:OnEnd()
buff.target.Event:DispatchEvent(BattleEventName.BuffEnd, buff)
BattleLogic.Event:DispatchEvent(BattleEventName.BuffEnd, buff)
putBuff(buff)
list:Remove(idx)
else
idx = idx + 1
end
end
end
end
end
function BuffManager:PutBuff(buff)
putBuff(buff)
end
function BuffManager:GetBuffCount(type)
if self.buffDic[type] then
return self.buffDic[type].size
end
return 0
end
-- 每帧刷新
function BuffManager:Update()
-- 检测上一帧生成的buff加入管理
while self.buffQueue.size > 0 do
local buff = self.buffQueue:Dequeue()
local buffList
if not self.buffDic.kvList[buff.type] then
buffList = buffListPool:Get()
self.buffDic:Add(buff.type, buffList)
else
buffList = self.buffDic.kvList[buff.type]
end
-- 是覆盖类型的buff且有老buff buff表现层修改所有cover 字段没用了 注释 by:王振兴 2021/03/11 20:40
-- if buff.cover and buffList.size > 0 then
-- local isCovered = false
-- for i=1, buffList.size do
-- local oldBuff = buffList.buffer[i]
-- if oldBuff.cover and oldBuff.target == buff.target and oldBuff.clear == buff.clear and oldBuff:OnCover(buff) then --判定该效果能否被覆盖
-- -- 结束并回收老buff
-- oldBuff:OnEnd()
-- oldBuff.target.Event:DispatchEvent(BattleEventName.BuffEnd, oldBuff)
-- putBuff(oldBuff)
-- -- 覆盖老buff
-- buffList.buffer[i] = buff
-- buff:OnStart()
-- buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff)
-- buff.target.Event:DispatchEvent(BattleEventName.BuffCover, buff)
-- isCovered = true
-- break
-- end
-- end
-- -- 没有覆盖新buff
-- if not isCovered then
-- buffList:Add(buff)
-- buff:OnStart()
-- buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff)
-- end
-- else
-- -- 新buff
-- buffList:Add(buff)
-- buff:OnStart()
-- buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff)
-- end
buffList:Add(buff)
buff:OnStart()
BattleLogManager.Log(
"Add Buff",
"camp", buff.caster.camp,
"position", buff.caster.position,
"id", buff.id,
"type", buff.type)
buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff)
BattleLogic.Event:DispatchEvent(BattleEventName.BuffStart, buff)
end
-- 清除过期buff
for i=1, self.buffDic.size do
local buffList = self.buffDic.vList[i]
if buffList.size > 0 then
local index = 1
while index <= buffList.size do
local buff = buffList.buffer[index]
if buff.disperse then
buff:OnEnd()
buff.target.Event:DispatchEvent(BattleEventName.BuffEnd, buff)
BattleLogic.Event:DispatchEvent(BattleEventName.BuffEnd, buff)
BattleLogic.Event:DispatchEvent(BattleEventName.BuffBeClear, buff)
putBuff(buff)
buffList:Remove(index)
else
index = index + 1
end
end
end
end
end
-- 计算buff 剩余步数(根据当前回合人刷新其造成的所有buff回合数)
function BuffManager:PassUpdate()
local curCamp, curPos = BattleLogic.GetCurTurn()
for i=1, self.buffDic.size do
local buffList = self.buffDic.vList[i]
if buffList.size > 0 then
for index = 1, buffList.size do
local buff = buffList.buffer[index]
if not buff.disperse -- 没过期
and buff.caster.camp == curCamp -- 释放者是当前轮到的人
and buff.caster.position == curPos
and buff.roundDuration > 0 -- 不是无限存在的buff
and buff.caster.type~=BattleUnitType.Monster --灵兽的buff在这里处理
and buff.type~=BuffName.NoDead
and not buff.target.isExile --放逐单位buff不会更新
then
-- 当前轮释放的buff不结算
if buff.startRound ~= BattleLogic.GetCurRound() then
buff.roundPass = buff.roundPass + 1
--如果是Dot类的buff 判断触发次数;其他的还按照之前的逻辑判断 by:wangzhenxing 2021/08/27
if buff.triggerTime then
--现在按照 每回合都会触发来处理的如果存在4回合触发2次的还需处理 by:wangzhenxing 2021/08/27
if buff.triggerTime==buff.roundDuration then
buff.disperse = true
end
else
if buff.roundPass >= buff.roundDuration then
buff.disperse = true
end
end
buff.target.Event:DispatchEvent(BattleEventName.BuffRoundChange, buff)
end
end
end
end
end
end
--只更新不灭buff
function BuffManager:PassUpdateNoDead()
local curCamp, curPos = BattleLogic.GetCurTurn()
for i=1, self.buffDic.size do
local buffList = self.buffDic.vList[i]
if buffList.size > 0 then
for index = 1, buffList.size do
local buff = buffList.buffer[index]
if not buff.disperse -- 没过期
and buff.caster.camp == curCamp -- 释放者是当前轮到的人
and buff.caster.position == curPos
and buff.roundDuration > 0 -- 不是无限存在的buff
and buff.caster.type~=BattleUnitType.Monster --灵兽的buff在这里处理
and buff.type==BuffName.NoDead --不灭在这里处理
and not buff.target.isExile --放逐单位buff不会更新
then
-- 当前轮释放的buff不结算
buff.roundPass = buff.roundPass + 1
if buff.roundPass >= buff.roundDuration then
buff.disperse = true
end
buff.target.Event:DispatchEvent(BattleEventName.BuffRoundChange, buff)
end
end
end
end
end
--计算灵兽buff更新
function BuffManager:PassMonsterUpdate()
local curCamp, curPos = BattleLogic.GetCurTurn()
for i=1, self.buffDic.size do
local buffList = self.buffDic.vList[i]
if buffList.size > 0 then
for index = 1, buffList.size do
local buff = buffList.buffer[index]
if (not buff.disperse -- 没过期
and buff.roundDuration > 0 -- 不是无限存在的buff
and buff.caster.type==BattleUnitType.Monster --灵兽的buff在这里处理
and not buff.target.isExile) --放逐单位buff不会更新
or (not buff.disperse -- 没过期
and buff.roundDuration > 0 -- 不是无限存在的buff
and buff.caster.type==BattleUnitType.Monster --灵兽的buff在这里处理
and buff.target.isExile
and buff.type==BuffName.Exile)
-- and buff.type~=BuffName.Exile --buff名称不是放逐
then
-- 当前轮释放的buff不结算
if buff.startRound ~= BattleLogic.GetCurRound() then
buff.roundPass = buff.roundPass + 1
if buff.roundPass >= buff.roundDuration then
buff.disperse = true
end
buff.target.Event:DispatchEvent(BattleEventName.BuffRoundChange, buff)
end
end
end
end
end
end
-- 每一个人的轮次都刷新
function BuffManager:TurnUpdate(sort)
local curCamp, curPos = BattleLogic.GetCurTurn()
for i=1, self.buffDic.size do
local buffList = self.buffDic.vList[i]
if buffList.size > 0 then
for index = 1, buffList.size do
local buff = buffList.buffer[index]
if not buff.disperse -- 没有过期
and buff.sort == sort -- 当前buff刷新等级
and buff.target.camp == curCamp -- 当前阵营
and not buff.target.isExile --放逐单位buff不会更新
and buff.target.position == curPos then -- 当前位置
--触发buff
if buff.roundInterval >= 0 then
if buff.roundInterval == 0 or buff.roundPass % buff.roundInterval == 0 then
if not buff:OnTrigger() then
buff.disperse = true
end
buff.target.Event:DispatchEvent(BattleEventName.BuffTrigger, buff)
end
end
end
end
end
end
end