local BattleEventListener = class("BattleEventListener") local EBattleEventId = LuaConst.EBattleEventId local EBattleEventSubjectType = LuaConst.EBattleEventSubjectType local EConditionAimType = LuaConst.EConditionAimType --标记哪些 templateEventId 是会抛出单位专属事件的 local EntityExclusiveEventDic = LuaConst.EntityExclusiveEventDic local pcall = pcall local ipairs = ipairs local pairs = pairs local assert = assert --只用于Debug打印,不要随便用,性能差 function BattleEventListener:GetEventName() for k,v in pairs(EBattleEventId) do if v == self:GetEventId() then return k end end return "" end --[[ params = { filterSubjectType, --事件主语类型过滤 conditionStr, --条件字串 conditionAimType, --条件判定目标 intParam1, --整形参数1 } ]] local SubjectCheckByDefault = 1 local SubjectCheckByMaster = 2 local SubjectCheckByBuff = 3 function BattleEventListener:Init(id,eventId,callback,params,host) self.id = id --模板eventId指的是eventId的前缀。 --大多数情况下 self.templateEventId == self.eventId。 --但在一些特殊事件上,当这些事件的 filterSubjectType 为 DEFAULT(即限定仅响应host的事件)时,会基于 self.templateEventId 和 host 拼一个host专属的事件 --以这样的做法增加BattleEventListener:OnEvent的命中率,减少不必要的OnEvent响应,减少性能消耗 self.templateEventId = eventId self.eventId = eventId self.params = params self.callback = callback self.isPaused = true --这段要先调↓ self.isEntityEvent = self:GetEventId() > EBattleEventId.____ENTITY_EVENT_START___ and self:GetEventId() < EBattleEventId.____ENTITY_EVENT_END____ self.isBuffEvent = self:GetEventId() > EBattleEventId.____BUFF_EVENT_START____ and self:GetEventId() < EBattleEventId.____BUFF_EVENT_END____ self.isLevelEvent = self.eventId > EBattleEventId.____LEVEL_NOTIFY_START____ and self.eventId < EBattleEventId.____LEVEL_NOTIFY_END____ self.subjectCheckType = nil if self.params then local filterSubjectType = self.params.filterSubjectType if self.isEntityEvent then if filterSubjectType == EBattleEventSubjectType.HOST or filterSubjectType == EBattleEventSubjectType.DEFAULT then self.subjectCheckType = SubjectCheckByDefault elseif filterSubjectType == EBattleEventSubjectType.MASTER then self.subjectCheckType = SubjectCheckByMaster end elseif self.isBuffEvent then if filterSubjectType > 0 then self.subjectCheckType = SubjectCheckByBuff end end end --这段要先调↑ if host then self:SetHost(host) end if self.isEntityEvent or self.isBuffEvent then if self.params.conditionStr then self.conditionTree = ConditionManager.GetConditionDataTree(self.params.conditionStr) end end --logging.error(LTAG.ERROR, "HYW : Init Listener : ", self:GetEventName()) end function BattleEventListener:SetHost(host) if self.host == nil then self.host = host if self:IsEntityExclusiveEventListener() then self.eventId = host.exclusiveBattleEventDic[self.templateEventId] assert(self.eventId ~= nil, " EntityExclusiveEventListener eventId nil after SetHost Error!") end if self.host and self.host:IsActive() then self:Resume() end else if self.host ~= host then logging.error(LTAG.ERROR, "HYW : 警告!试图改变BuffEventListener的Host!!") end end end function BattleEventListener:GetId() return self.id end function BattleEventListener:GetEventId() return self.eventId end function BattleEventListener:Pause() self.isPaused = true end function BattleEventListener:Resume() self.isPaused = false end --subject:事件主语 function BattleEventListener:OnEvent(subject,eventParams) --检测主语是否满足条件,这一步执行的次数特别多,通过提前判断展开逻辑分支以获得最好的性能 local subjectCheckType = self.subjectCheckType if subjectCheckType == SubjectCheckByDefault then if subject ~= self.host then return end elseif subjectCheckType == SubjectCheckByMaster then if subject ~= self.host._logicInitData.RootMasterEntity then return end elseif subjectCheckType == SubjectCheckByBuff then if subject then if subject.BuffID ~= self.params.filterSubjectType then return end else --正常情况,瞬时Buff不会有主语, 尝试用事件参数来过滤 if eventParams.buffId ~= self.params.filterSubjectType then return end end end if not self:ConditionCheck(subject,eventParams) then return end --logging.error(LTAG.ERROR, "HYW : OnEvent : ", self:GetEventName(), " entityID : ", subject.EntityID, " buffID : ", self.params.buffObject:GetBuffID()) --self:Dispatch(subject,eventParams) --old 新代码内联以节省性能 --new↓ 内联以节省性能 if self.callback then --new↓ 使用pcall,防止打断堆栈,主要是怕打断 BattleEventSystem的private.OnEvent里面的Dispatch计数,所以这里改为pcall local suc, r1 = pcall(self.callback, self, subject, eventParams) if not suc then logging.error(LTAG.ERROR, "HYW : OnEvent : ", r1) end --new↑ end --new↑ end function BattleEventListener:Dispatch(subject,eventParams) if self.callback then --new↓ 使用pcall,防止打断堆栈,主要是怕打断 BattleEventSystem的private.OnEvent里面的Dispatch计数,所以这里改为pcall local suc, r1 = pcall(self.callback, self, subject, eventParams) if not suc then logging.error(LTAG.ERROR, "HYW : OnEvent : ", r1) end --new↑ --self.callback(self,subject,eventParams) --old 没有pcall end end --※ 注意eventParams可能为空,是正常情况 function BattleEventListener:ConditionCheck(subject,eventParams) local result = true if self.isEntityEvent or self.isBuffEvent or self.isLevelEvent then if self.conditionTree then local aim = self.host local params = self.params local conditionAimType = params.conditionAimType if conditionAimType == EConditionAimType.HOST then aim = self.host elseif conditionAimType == EConditionAimType.SUBJECT then aim = subject elseif conditionAimType == EConditionAimType.CASTER then aim = eventParams and eventParams.caster elseif conditionAimType == EConditionAimType.TARGET then aim = eventParams and eventParams.target elseif conditionAimType == EConditionAimType.BY_PARAM then aim = eventParams and eventParams[params.conditionAimStrParam] end if aim then result = ConditionManager.MeetCondition(aim,self.conditionTree,eventParams and (eventParams.missile or eventParams.missileData) or nil ,params.buffObject, eventParams) --ugly 这个代码增加了 BuffObject 跟 BattleEventListener 的耦合, 但是为了代码干净就这么写了↓ if params.buffObject then params.buffObject:OnListenerConditionCheck(self.eventId, result) end --ugly↑ else logging.error(LTAG.ERROR, "HYW : aim nil Error! ", self:GetEventName(), " conditionAimType : ", params.conditionAimType) end end end return result end function BattleEventListener:IsEntityEvent() return self.isEntityEvent --return self:GetEventId() > EBattleEventId.____ENTITY_EVENT_START___ and self:GetEventId() < EBattleEventId.____ENTITY_EVENT_END____ end --是否是单目标的Listener --单目标的Listener可以只监听单个单位的事件,增加BattleEventListener:OnEvent的命中率,减少性能损耗 function BattleEventListener:IsEntityExclusiveEventListener() return EntityExclusiveEventDic[self.templateEventId] and self.subjectCheckType == SubjectCheckByDefault end function BattleEventListener:IsBuffEvent() return self.isBuffEvent end function BattleEventListener:Dispose() self:Pause() end return BattleEventListener