Buff = {} local floor = math.floor function Buff:New() local o = {} setmetatable(o, self) self.__index = self return o end function Buff.Create(caster, type, duration, ...) local instance = require("Modules/Battle/Logic/Buff/"..type):New() instance.type = type instance.id = BattleLogic.GenerateBuffId() instance.caster = caster instance.disperse = false instance.cover = false instance.duration = duration --持续时间为0时buff永久存在 instance.interval = -1 --间隔帧为0时每帧触发,小于0不触发 默认不触发OnTrigger instance.maxCount = 0 --限定效果最大数量 instance.framePass = 0 instance:SetData(...) return instance end BuffManager = {} BuffManager.__index = BuffManager function BuffManager.New(owner) local instance = {} instance.owner = owner instance.buffQueue = BattleQueue.New() instance.buffList = BattleDictionary.New() setmetatable(instance, BuffManager) return instance 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 > 0 then if v[1].type == type and (not checkFunc or (checkFunc and checkFunc(v[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] local count = #v if count > 0 then local removeCount = 0 local idx = 1 while idx <= count do if func(v[idx]) then table.remove(v, idx) count = count - 1 removeCount = removeCount + 1 else idx = idx + 1 end end if removeCount > 0 then self.owner.Event:DispatchEvent(BattleEventName.BuffCountChange, k, count) end end end end function BuffManager:GetBuffCount(id) if self.buffList[id] then return self.buffList[id]:Count() 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 = {} self.buffList:Add(buff.id, buffList) else buffList = self.buffList.kvList[buff.id] end local count = #buffList if buff.cover and count > 0 then if buffList[1]:OnCover(buff) then --判定该效果能否被覆盖 buffList[1]:OnEnd(self.owner) self.owner.Event:DispatchEvent(BattleEventName.BuffEnd, buffList[1]) buffList[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则不限制 count = count + 1 buffList[count] = 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] local count = #v if count > 0 then local removeCount = 0 local idx = 1 local buff while idx <= count do buff = v[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) table.remove(v, idx) count = count - 1 removeCount = removeCount + 1 else idx = idx + 1 end end if removeCount > 0 then self.owner.Event:DispatchEvent(BattleEventName.BuffCountChange, k, count) end end end end