local BattleEffect = require("Battle/Logic/BattleEffect/BattleEffect") local BuffObject = class("BuffObject") --BuffUpdateData:记录了层数 local ipairs=ipairs local table_insert=table.insert local pairs=pairs local stringEmpty = string.isNilOrEmpty local CheckBuffHasImmune = DataSheetUtil.CheckBuffHasImmune local CheckBuffHasExclusive = DataSheetUtil.CheckBuffHasExclusive function BuffObject:initialize(buffData) self.BuffInfoData = buffData --这玩意就是BuffData表的数据 self.BuffID = self.BuffInfoData and self.BuffInfoData.BuffID or -1 self.UseStratagemCD = DataSheetManager.StratagemBuff:TryGetDataByBuffID(self.BuffID) self.BuffUpdateData = nil -- 不记录来源时的存贮 self.BuffUpdateList = nil --不同来源的buff会放在这里面,当BuffData的IsRecordSource为true时,不同来源的同ID的buff不能叠加,BuffUpdateData会存在这个list里。 self.LastTriggerTimeStampDic = {} --key是triggerData的index,value是触发时间戳 self.TriggerCountRecordDic = {} --key是triggerData的index,value是触发次数 self.EventID2LastTriggerConditionValue = {} --key为BattleEventID,value为 上一次由该事件引发的对 EventConditionStr 进行条件判定的值(true 或者 false,如果之前没有过该事件引发的条件判定,则为nil) self:InitBattleEventListeners() --免疫和互斥的优化(收集是否参与免疫和互斥) self.NeedCheckImmune = CheckBuffHasImmune(buffData.BuffID) -- 需要校测免疫 self.NeedCheckExclusive = CheckBuffHasExclusive(buffData.BuffID, buffData.BuffGroup) -- 需要校测互斥 --表现层数据 self._buffEffectPlayID = nil -- buff特效播放的句柄ID end function BuffObject:InitBattleEventListeners() self.index2ListenerDic = {} --key是TriggerBuffData_Table的index,value是BattleEventListener if self.BuffInfoData then local isSuccess, buffTriggerData = DataSheetManager.BuffTriggerData:TryGetDataByBuffID(self.BuffInfoData.BuffID) if isSuccess then self.TriggerBuffData_Table = buffTriggerData.TriggerBuffData_Table for i,triggerData in ipairs(self.TriggerBuffData_Table) do self.LastTriggerTimeStampDic[i] = -99999 --上次触发的时间戳,初始设为负很大的值 self.TriggerCountRecordDic[i] = 0 --触发过的次数 self:TryAddBattleEventListenerByTriggerData(triggerData, i) end end end end function BuffObject:CreateListenerParamsByTriggerData(triggerData) local params = {} params.filterSubjectType = triggerData.TriggerSubjectType params.conditionStr = triggerData.EventConditionStr params.conditionAimType = triggerData.EventConditionAimType params.conditionAimStrParam = triggerData.EventConditionAimStrParam params.intParam1 = triggerData.TriggerParam params.buffObject = self return params end function BuffObject:TryAddBattleEventListenerByTriggerData(triggerData, index) if self:NeedAddListener(triggerData) then local callback = function(listener, subject, eventParams) self:OnEvent(listener, subject, eventParams, triggerData, index) end local params = self:CreateListenerParamsByTriggerData(triggerData) --※每个triggerData都会生成一个Listener,不考虑多个triggerData共用同一个Listener,因为即便eventId相同,filterSubjectType、conditionStr、conditionAimType这些参数也可能不同,所以大多数情况下不能共用 -- host 传nil ,因为 :此时buffobject也没有host 。host是buff宿主 self.index2ListenerDic[index] = BattleEventSystem.AddEventListener(triggerData.TriggerType, callback, params, nil) end end function BuffObject:NeedAddListener(triggerData) return triggerData.TriggerType > LuaConst.EBattleEventId.START end --添加第一层buff的时间点 function BuffObject:SetData(updateData, index) --添加一层buff if not self.BuffInfoData.IsRecordSource then self.BuffUpdateData = updateData --如果BuffData的IsRecordSource为false,则不同来源的Buff会叠加,则只需要1个BuffUpdateData,记录在这里 else if not self.BuffUpdateList then self.BuffUpdateList = {} end if index and index > 0 then self.BuffUpdateList[index] = updateData else table_insert(self.BuffUpdateList, updateData) end end self:CastStartEffect(updateData) local hostEntity = self:GetHost() self:PlayEffect(hostEntity, hostEntity.components.replace:GetCurModelBuffResource(self.BuffInfoData)) self:PlayQueueEffect(self.BuffInfoData.QueueResource) end function BuffObject:SetAllDeleteCallback(callback) self.allDeleteCallback = callback end function BuffObject:OnListenerConditionCheck(eventId, result) self.EventID2LastTriggerConditionValue[eventId] = result end function BuffObject:GetLastTriggerCondValue(eventId) return self.EventID2LastTriggerConditionValue[eventId] end --已经有至少1层buff时,再添加buff的时间点(不论是否可以叠层);将最新刷新的buff放在updatelist最后 function BuffObject:OnRefresh(updateData, index) if self.BuffUpdateList then -- 让最新的update放在最后 local count = #self.BuffUpdateList for i = index ,count-1 do self.BuffUpdateList[i] = self.BuffUpdateList[i + 1] end self.BuffUpdateList[count] = updateData end self:CastStartEffect(updateData) end function BuffObject:ReplayBuffEffect() local hostEntity = self:GetHost() self:StopEffect(hostEntity, false) self:PlayEffect(hostEntity, hostEntity.components.replace:GetCurModelBuffResource(self.BuffInfoData)) end function BuffObject:CastEffect(effectID,updateData) if effectID and effectID > 0 then local effectParams = {} effectParams.buff = self effectParams.buffUpdateData = updateData BattleEffect.ExecuteByEffectId(effectID, effectParams, effectParams.buffUpdateData.SourceEntity, self:GetHost()) end end function BuffObject:CastEffects(effectIdList,updateData) for i,effectID in ipairs(effectIdList) do self:CastEffect(effectID, updateData) end end function BuffObject:CastStartEffect(updateData) self:CastEffects(self.BuffInfoData.StartEffects, updateData) end function BuffObject:GetData() return self.BuffInfoData --这玩意就是BuffData表的数据 end --BuffID是BuffData数据表的ID,不是instanceId --这个方法一帧要调几千次,所以必须得做到性能最优 --目前这个方法调用都去掉了,改为直接裸访问BuffID function BuffObject:GetBuffID() -- Check代码,消耗很大,没事别开,有bug了再开↓ -- if not self.BuffInfoData then -- if self:GetHost() then -- logging.error(LTAG.ERROR, "HYW : (程序临时调试代码,可忽略)Buff的BuffInfoData为空! Entity: " , -- self:GetHost().EntityID, " CharacterType : " , self:GetHost():GetCharacterType(), -- " CharacterID : " , self:GetHost():GetCharacterID()) -- else -- logging.error(LTAG.ERROR, "HYW : Buff的BuffInfoData为空 , No Host") -- end -- end -- ↑↑↑↑↑↑↑↑↑↑↑ return self.BuffID end --是否需要显示 function BuffObject:IsShowingBuff() return self.BuffInfoData.BuffIcon ~= nil and self.BuffInfoData.BuffIcon ~= "" end function BuffObject:SetHost(hostEntity) self.hostEntity = hostEntity for k,listener in pairs(self.index2ListenerDic) do --pairs Save BattleEventSystem.SetHostOfListener(listener, hostEntity) end end --可能返回空,瞬时buff没有host function BuffObject:GetHost() return self.hostEntity end function BuffObject:GetUpdateData(index) if self.BuffUpdateData then return self.BuffUpdateData else return self.BuffUpdateList[index] end end --如果是记录来源的,返回最大的那个层数 function BuffObject:GetBuffLayer(sourceEntity) if sourceEntity then for i,v in ipairs(self.BuffUpdateList) do if v.SourceEntity == sourceEntity then return v.BuffLayer end end return -1 else if self.BuffUpdateData then return self.BuffUpdateData.BuffLayer else local biggestBuffLayer = -1 for i,v in ipairs(self.BuffUpdateList) do if v.BuffLayer > biggestBuffLayer then biggestBuffLayer = v.BuffLayer end end return biggestBuffLayer end end end function BuffObject:Dispose() self:DisposeListener() self:StopEffect(self:GetHost(),false) self:ClearData() end function BuffObject:ClearData() self.BuffInfoData = nil self.BuffUpdateData = nil self.BuffUpdateList = nil self.hostEntity = nil end --清空触发的记录数据,包括触发时间戳和触发次数 function BuffObject:ResetTriggerRecord() if self.TriggerBuffData_Table then for i,triggerData in ipairs(self.TriggerBuffData_Table) do self.LastTriggerTimeStampDic[i] = -99999 --上次触发的时间戳,初始设为负很大的值 self.TriggerCountRecordDic[i] = 0 --触发过的次数 end end end function BuffObject:Reset(buffObject) self.BuffInfoData = buffObject.BuffInfoData self.BuffID = self.BuffInfoData and self.BuffInfoData.BuffID or -1 self.BuffUpdateData = buffObject.BuffUpdateData if buffObject.BuffUpdateList then self.BuffUpdateList = {} for _,v in ipairs(buffObject.BuffUpdateList) do local updateData = RuntimeDataManager.New_BuffUpdate() RuntimeDataManager.Set_BuffUpdate(updateData,v) table_insert(self.BuffUpdateList, updateData) end end end function BuffObject:ResumeListener() if self:GetBuffLayer() > 0 then for k,listener in pairs(self.index2ListenerDic) do --pairs Save --logging.error(LTAG.ERROR, "HYW : ResumeListener : ", self:GetData().BuffID) listener:Resume() end end end function BuffObject:PauseListener() for k,listener in pairs(self.index2ListenerDic) do --pairs Save --logging.error(LTAG.ERROR, "HYW : PauseListener : ", self:GetData().BuffID) listener:Pause() end end function BuffObject:DisposeListener() for k,listener in pairs(self.index2ListenerDic) do --pairs Save --logging.error(LTAG.ERROR, "HYW : PauseListener : ", self:GetData().BuffID) BattleEventSystem.RemoveEventListener(listener) end table.clear(self.index2ListenerDic) end function BuffObject:CreateTriggerParams(eventParams) local params = {} params.buff = self if eventParams then for k,v in pairs(eventParams) do --pairs Save params[k] = v end end return params end function BuffObject:IsTriggerInCd(triggerData,index) local cdFrame = 0 if self.UseStratagemCD then return self:GetHost().components.stratagem:GetStratagemCurCD() > 0 else cdFrame = triggerData.CdFrame return cdFrame > 0 and cdFrame > (LogicUpdateManager._clientHandleFrame - self.LastTriggerTimeStampDic[index]) end end function BuffObject:IsReachMaxTriggerCount(triggerData,index) return triggerData.MaxTriggerCount > 0 and triggerData.MaxTriggerCount <= self.TriggerCountRecordDic[index] end function BuffObject:CanTrigger(triggerData,index) return not self:IsTriggerInCd(triggerData,index) and not self:IsReachMaxTriggerCount(triggerData, index) end function BuffObject:OnEvent(listener,eventSubject,eventParams,triggerData,index) --logging.error(LTAG.ERROR, "HYW : BuffObject:OnEvent : ", listener:GetEventName()) if self:CanTrigger(triggerData,index) then self:Trigger(eventSubject, eventParams, triggerData, index) end end function BuffObject:Trigger(eventSubject,eventParams,triggerData,index) self.LastTriggerTimeStampDic[index] = LogicUpdateManager._clientHandleFrame self.TriggerCountRecordDic[index] = self.TriggerCountRecordDic[index] + 1 if self.BuffUpdateList then for i,updateData in ipairs(self.BuffUpdateList) do if updateData.BuffLayer > 0 then local params = self:CreateTriggerParams(eventParams) if params.buffUpdateData then logging.error(LTAG.ERROR, "HYW : 111 事件参数名称撞了,需要修改! buffUpdateData是保留名称!") end params.buffUpdateData = updateData SystemManager.OnEventTriggeredBuff(self,params.buffUpdateData, triggerData, eventSubject, params) end end elseif self.BuffUpdateData then if self.BuffUpdateData.BuffLayer > 0 then local params = self:CreateTriggerParams(eventParams) if params.buffUpdateData then logging.error(LTAG.ERROR, "HYW : 222 事件参数名称撞了,需要修改! buffUpdateData是保留名称!") end params.buffUpdateData = self.BuffUpdateData SystemManager.OnEventTriggeredBuff(self,params.buffUpdateData,triggerData,eventSubject,params) end else logging.error(LTAG.ERROR, "HYW : BuffUpdateData nil 警告! BuffID : " , tostring(self.BuffID), " CharacterID : ", tostring(self:GetHost() and self:GetHost():GetCharacterID() or "host nil") , " CharacterType : ", tostring(self:GetHost() and self:GetHost():GetCharacterType() or "host nil")) end end function BuffObject:OnDeleteBuff(updateData) if #self.BuffInfoData.RemoveEffects > 0 then self:CastEffects(self.BuffInfoData.RemoveEffects, updateData) end local allDeleted = true if self.BuffUpdateList then for i,updateDataTemp in ipairs(self.BuffUpdateList) do if updateDataTemp.BuffLayer > 0 then allDeleted = false break end end end local host = self.hostEntity if allDeleted then self:OnAllDeleted() self:StopEffect(host, true) end if host then SystemManager.DeleteBuffUpdateAttr(host, self.BuffID,updateData.SourceEntity and updateData.SourceEntity.EntityID or 0) end end function BuffObject:OnAllDeleted() self:PauseListener() self:ResetTriggerRecord() if self.allDeleteCallback then self.allDeleteCallback(self) end end function BuffObject:PlayEffect(host, effect) --和策划对过,一次性buff不会产生特效 if not self._buffEffectPlayID and not stringEmpty(effect) then if host:IsMinion() then self._buffEffectPlayID = SystemManager.PlayBuffEffect(host, effect, self.BuffInfoData.MinionShowEffChance) else self._buffEffectPlayID = SystemManager.PlayBuffEffect(host, effect, 1) end end end function BuffObject:StopEffect(host, breakEffect) if self._buffEffectPlayID then SystemManager.StopBuffEffect(host, self._buffEffectPlayID, breakEffect) self._buffEffectPlayID = nil end end function BuffObject:PlayQueueEffect(effect) if self.hostEntity then if not stringEmpty(effect) then SystemManager.AddQueueEffect(self.hostEntity, effect) end end end -- 获取最新的update function BuffObject:GetLastUpdateData() local buffUpdateData = self.BuffUpdateData if buffUpdateData and buffUpdateData.BuffLayer > 0 then return buffUpdateData end local buffUpdateList = self.BuffUpdateList local count = #buffUpdateList for i = count, 1 , -1 do -- 可以不用判空,上面的self.BuffUpdateData为nil,这个就一定不为nil local updateData = buffUpdateList[i] if updateData.BuffLayer > 0 then return updateData end end return nil end return BuffObject