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 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.maxCount = 0 --限定效果最大数量 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(owner) self.buffQueue:Clear() self.buffList:Clear() self.owner = owner end function BuffManager:AddBuff(buff) 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) end function BuffManager:HasBuff(type, checkFunc) local v for i=1, self.buffList:Count() do v = self.buffList.vList[i] if v.size > 0 then if v.buffer[1].type == type and (not checkFunc or (checkFunc and checkFunc(v.buffer[1]))) then return true end end end return false end function BuffManager:ClearBuff(func) for i = 1, self.buffList.size do local k = self.buffList.kList[i] local v = self.buffList.vList[i] if v.size > 0 then local removeCount = 0 local idx = 1 while idx <= v.size do if func(v.buffer[idx]) then putBuff:Put(v.buffer[idx]) v:Remove(idx) removeCount = removeCount + 1 else idx = idx + 1 end end if removeCount > 0 then self.owner.Event:DispatchEvent(BattleEventName.BuffCountChange, k, v.size) end end end end function BuffManager:GetBuffCount(id) if self.buffList[id] then return self.buffList[id].size end return 0 end function BuffManager:Update() for i=1, self.buffQueue.size do local buff = self.buffQueue:Dequeue() if not buff.caster then --logErrorTrace("buff's caster can't be nil!") return end local buffList if not self.buffList.kvList[buff.id] then buffList = BattleList.New() self.buffList:Add(buff.id, buffList) else buffList = self.buffList.kvList[buff.id] end local count = buffList.size if buff.cover and count > 0 then if buffList.buffer[1]:OnCover(buff) then --判定该效果能否被覆盖 buffList.buffer[1]:OnEnd(self.owner) self.owner.Event:DispatchEvent(BattleEventName.BuffEnd, buffList.buffer[1]) buffList.buffer[1] = buff buff.target = self.owner buff:OnStart() self.owner.Event:DispatchEvent(BattleEventName.BuffStart, buff) self.owner.Event:DispatchEvent(BattleEventName.BuffCover, buff) end else if buff.maxCount == 0 or count < buff.maxCount then --限制相同效果的数量,为0则不限制 buffList:Add(buff) buff.target = self.owner buff:OnStart() self.owner.Event:DispatchEvent(BattleEventName.BuffStart, buff) self.owner.Event:DispatchEvent(BattleEventName.BuffCountChange, buff.id, count) end end end for i = 1, self.buffList.size do local k = self.buffList.kList[i] local v = self.buffList.vList[i] if v.size > 0 then local removeCount = 0 local idx = 1 local buff while idx <= v.size do buff = v.buffer[idx] --印记类型的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(v.buffer[idx]) v:Remove(idx) removeCount = removeCount + 1 else idx = idx + 1 end end if removeCount > 0 then self.owner.Event:DispatchEvent(BattleEventName.BuffCountChange, k, v.size) end end end end