Buff = {} local floor = math.floor local buffPoolList = {} local getBuff = function(type) if not buffPoolList[type] then buffPoolList[type] = BattleObjectPool.New(function (type) return require("Modules/Battle/Logic/Buff/"..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 = BattleLogic.GenerateBuffId() buff.caster = caster buff.disperse = false buff.cover = false buff.duration = duration --持续时间为0时buff永久存在 buff.interval = -1 --间隔帧为0时每帧触发,小于0不触发 默认不触发OnTrigger buff.framePass = 0 buff:SetData(...) return buff end BuffManager = {} BuffManager.__index = BuffManager function BuffManager.New() local instance = {owner=0, buffQueue = BattleQueue.New(), buffList = BattleDictionary.New()} setmetatable(instance, BuffManager) return instance end function BuffManager:Init() while self.buffQueue.size > 0 do putBuff:Put(self.buffQueue:Dequeue()) end for i = 1, self.buffList.size do local list = self.buffList.vList[i] for j=1, list.size do list.buffer[j]:OnEnd() putBuff(list.buffer[j]) end list:Clear() buffListPool:Put(list) end self.buffList:Clear() end function BuffManager:AddBuff(target, buff) buff.target = target self.buffQueue:Enqueue(buff) if not buff.exCtrlTime then buff.exCtrlTime = 0 end buff.frameDuration = floor(buff.duration * (1 + buff.exCtrlTime) * 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.caster.Event:DispatchEvent(BattleEventName.BuffCaster, buff) end function BuffManager:HasBuff(target, type, checkFunc) if self.buffList.kvList[type] then local buffList = self.buffList.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 function BuffManager:ClearBuff(target, func) for i = 1, self.buffList.size do local list = self.buffList.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 func(buff))) then buff:OnEnd() buff.target.Event:DispatchEvent(BattleEventName.BuffEnd, buff) putBuff(buff) list:Remove(idx) else idx = idx + 1 end end end end end function BuffManager:GetBuffCount(type) if self.buffList[type] then return self.buffList[type].size end return 0 end function BuffManager:Update() while self.buffQueue.size > 0 do local buff = self.buffQueue:Dequeue() local buffList if not self.buffList.kvList[buff.type] then buffList = buffListPool:Get() self.buffList:Add(buff.type, buffList) else buffList = self.buffList.kvList[buff.type] end 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:OnCover(buff) then --判定该效果能否被覆盖 oldBuff:OnEnd() oldBuff.target.Event:DispatchEvent(BattleEventName.BuffEnd, oldBuff) putBuff(oldBuff) 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 if not isCovered then buffList:Add(buff) buff:OnStart() buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff) end else buffList:Add(buff) buff:OnStart() buff.target.Event:DispatchEvent(BattleEventName.BuffStart, buff) end end for i=1, self.buffList.size do local buffList = self.buffList.vList[i] if buffList.size > 0 then local index = 1 while index <= buffList.size do local buff = buffList.buffer[index] --印记类型的buff不处理更新逻辑 if buff.frameDuration == 0 and buff.frameInterval < 0 then else buff.framePass = buff.framePass + 1 if buff.frameDuration == 0 then if buff.frameInterval == 0 or buff.framePass % buff.frameInterval == 0 then if not buff:OnTrigger() then buff.disperse = true end buff.target.Event:DispatchEvent(BattleEventName.BuffTrigger, buff) end elseif buff.frameInterval < 0 then if buff.framePass > buff.frameDuration then buff.disperse = true end else if buff.frameInterval == 0 or buff.framePass % buff.frameInterval == 0 then if not buff:OnTrigger() then buff.disperse = true end buff.target.Event:DispatchEvent(BattleEventName.BuffTrigger, buff) end if buff.framePass > buff.frameDuration then buff.disperse = true end end end if buff.disperse then buff:OnEnd() buff.target.Event:DispatchEvent(BattleEventName.BuffEnd, buff) putBuff(buff) buffList:Remove(index) else index = index + 1 end end end end end