local EventSystem = require('Event/EventSystem') local Evaluation = class("Evaluation") local EvaluationCondition = class("EvaluationCondition") local LevelEvaluationManager = { EvaluationList = {} } local LuaConst = LuaConst local EventID = EventID local FP = FP local GlobalItemID = LuaConst.GlobalItemID local ConditionType = LuaConst.LevelConditionType local EvaluationType = LuaConst.EvaluationType local SortByOrder = function(a,b) return a.Data.Order < b.Data.Order end local EvaluationEventID = { ["LevelEnd"] = GlobalItemID..'_'..ConditionType.Global_LevelEnd, ["LevelTimeRemain"] = GlobalItemID..'_'..ConditionType.Global_TimeRemain, ["TimeRun"] = GlobalItemID..'_'..ConditionType.Global_TimeRun, ["PlayerDeadTimes"] = GlobalItemID..'_'..ConditionType.Global_PlayerDeadTimes, ["UpdateKillNum"] = EventID.Level_UpdateKillNum, ["UpdateComboNum"] = EventID.Level_UpdateComboNum, ["GivenMonsterAliveNum"] = GlobalItemID..'_'..ConditionType.Global_GivenMonsterAliveNum, ["ItemMonsterAliveNum"] = '_'..ConditionType.Monster_AliveNum, ["DeadNumber"] = GlobalItemID..'_'..ConditionType.DeadNumber, ["ItemDeadNumber"] = '_'..ConditionType.DeadNumber, ["InteractNumber"] = GlobalItemID..'_'..ConditionType.InteractNumber, ["ItemInteractNumber"] = '_'..ConditionType.InteractNumber, ["Score"] = EventID.Level_Score, } --region ***************** distinguish ***************** local ConditionFactory = { [EvaluationType.LevelSuccess] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.LevelEnd)) end, [EvaluationType.LevelRemainTime] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.LevelTimeRemain)) end, [EvaluationType.PlayerDeadTimes] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.PlayerDeadTimes)) end, [EvaluationType.KillMonsterNumber] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.UpdateKillNum)) end, [EvaluationType.ComboNumber] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.UpdateComboNum)) end, [EvaluationType.MonsterAliveNum_Item] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.ItemMonsterAliveNum, true, true)) end, [EvaluationType.MonsterAliveNum_ID] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.GivenMonsterAliveNum, nil, true)) end, [EvaluationType.MonsterDeadNum] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.DeadNumber)) end, [EvaluationType.MonsterDeadNum_Item] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.ItemDeadNumber, true)) end, [EvaluationType.MonsterDeadNum_ID] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.DeadNumber)) end, [EvaluationType.TimeMonsterDeadNum] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.DeadNumber)) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.TimeRun)) end, [EvaluationType.TimeMonsterDeadNum_Item] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.ItemDeadNumber, true)) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.TimeRun)) end, [EvaluationType.TimeMonsterDeadNum_ID] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.DeadNumber)) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.TimeRun)) end, [EvaluationType.CollectNum] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.InteractNumber)) end, [EvaluationType.CollectNum_Item] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.ItemInteractNumber, true)) end, [EvaluationType.CollectNum_ID] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.InteractNumber)) end, [EvaluationType.Score] = function(evaluation, list) table.insert(list, EvaluationCondition:new(evaluation,EvaluationEventID.Score)) end, } local ConditionInitializer = { ["Default"] = function(data) return 0 >= data.Param1, 0 end, [EvaluationEventID.LevelEnd] = function() return false end, [EvaluationEventID.LevelTimeRemain] = function(data) return FP.tonumberV1(LevelItemManager.Global:GetRemainTime()) >= data.Param1 end, [EvaluationEventID.TimeRun] = function(data) return 0 <= data.Param2, 0 end, [EvaluationEventID.PlayerDeadTimes] = function(data) return 0 <= data.Param1, 0 end, } local ConditionAnalyzer = { [EvaluationEventID.LevelEnd] = function(selfValue, data, itemID, cxt, val) return val end, [EvaluationEventID.LevelTimeRemain] = function(selfValue, data, itemID, cxt, val) return FP.tonumberV1(val) >= data.Param1 end, [EvaluationEventID.TimeRun] = function(selfValue, data, itemID, cxt, val) selfValue = selfValue + LuaConst.TimeSpan return selfValue <= data.Param2, selfValue end, [EvaluationEventID.PlayerDeadTimes] = function(selfValue, data, itemID, cxt, val) selfValue = math.min(selfValue + 1, val) return selfValue <= data.Param1, selfValue end, [EvaluationEventID.UpdateKillNum] = function(selfValue, data, val) selfValue = math.min(selfValue + 1, val) return selfValue >= data.Param1, selfValue end, [EvaluationEventID.UpdateComboNum] = function(selfValue, data, val) selfValue = math.min(selfValue + 1, val) return selfValue >= data.Param1, selfValue end, [EvaluationEventID.ItemMonsterAliveNum] = function(selfValue, data, itemID, cxt, val) selfValue = selfValue + val return selfValue >= data.Param1, selfValue end, [EvaluationEventID.GivenMonsterAliveNum] = function(selfValue, data, itemID, cxt, monsterID, val) for i, checkID in ipairs(data.Param3) do if checkID == monsterID then selfValue = selfValue + val break end end return selfValue >= data.Param1, selfValue end, [EvaluationEventID.DeadNumber] = function(selfValue, data, itemID, cxt, monsterID, val) if #data.Param3 == 0 then selfValue = selfValue + val return selfValue >= data.Param1, selfValue else for i, checkID in ipairs(data.Param3) do if checkID == monsterID then selfValue = selfValue + val break end end return selfValue >= data.Param1, selfValue end end, [EvaluationEventID.ItemDeadNumber] = function(selfValue, data, itemID, cxt, monsterID, val) selfValue = selfValue + val return selfValue >= data.Param1, selfValue end, [EvaluationEventID.InteractNumber] = function(selfValue, data, itemID, cxt, paramID, val) if #data.Param3 == 0 then selfValue = selfValue + val return selfValue >= data.Param1, selfValue else for i, checkID in ipairs(data.Param3) do if checkID == paramID then selfValue = selfValue + val break end end return selfValue >= data.Param1, selfValue end end, [EvaluationEventID.ItemInteractNumber] = function(selfValue, data, itemID, cxt, paramID, val) selfValue = selfValue + val return selfValue >= data.Param1, selfValue end, [EvaluationEventID.Score] = function(selfValue, data) selfValue = BattleDataGetter.GetLevelScore() return selfValue >= data.Param1, selfValue end } --endregion distinguish function LevelEvaluationManager.InitLevel(levelID) local isSuccess, __ = DataSheetManager.LevelEvaluationData:TryGetDataByLevelID_Order(levelID) if not isSuccess then return end for i, data in DataSheetManager.LevelEvaluationData:GetDataByLevelID_Order(levelID) do local evaluation = Evaluation:new(data) table.insert(LevelEvaluationManager.EvaluationList,evaluation) end table.sort(LevelEvaluationManager.EvaluationList, SortByOrder) end function LevelEvaluationManager.ExitLevel() for i, evaluation in ipairs(LevelEvaluationManager.EvaluationList) do evaluation:Dispose() LevelEvaluationManager.EvaluationList[i] = nil end end function LevelEvaluationManager.StartEvaluations() for i, evaluation in ipairs(LevelEvaluationManager.EvaluationList) do if not evaluation.Data.NotActive then evaluation:Active() end end end function LevelEvaluationManager.StopEvaluations() for i, evaluation in ipairs(LevelEvaluationManager.EvaluationList) do evaluation:Deactive() end end function LevelEvaluationManager.ActiveEvaluation(order) for i, evaluation in ipairs(LevelEvaluationManager.EvaluationList) do if evaluation.Data.Order == order then evaluation:Active() break end end end function LevelEvaluationManager.DeactiveEvaluation(order) for i, evaluation in ipairs(LevelEvaluationManager.EvaluationList) do if evaluation.Data.Order == order then evaluation:Deactive() break end end end --region ***************** evaluation类 ***************** function Evaluation:initialize(data) local type = data.EvaluationType --public self.Data = data self.Completed = nil --private self._isActive = false self._conditionList = {} local factory = ConditionFactory[type] factory(self, self._conditionList) end function Evaluation:Dispose() self:Deactive() self.Data = nil self.Completed = nil self._isActive = nil for i = 1, #self._conditionList do self._conditionList[i]:OnDispose() end self._conditionList = nil end function Evaluation:Active() if self._isActive then return end self._isActive = true for i, condition in ipairs(self._conditionList) do condition:OnActive() end self:UpdateCompleteState() end function Evaluation:Deactive() if not self._isActive then return end self._isActive = false for i, condition in ipairs(self._conditionList) do condition:OnDeactive() end end function Evaluation:UpdateCompleteState() for i, condition in ipairs(self._conditionList) do local complete = condition:CheckComplete() self.Completed = self.Completed and complete or complete end end --endregion evaluation类 --region ***************** evaluation condition类 ***************** --[[ eventID: 事件ID isItem: 是否是监听元素的事件 isRestate: 达成状态改变后是否会再次改变 ]]-- function EvaluationCondition:initialize(evaluation, eventID, isItem, isRestate) self._evaluation = evaluation self._eventID = eventID self._isItem = isItem self._isRestate = isRestate self._isCompleted = nil self._value = nil end function EvaluationCondition:OnDispose() self._evaluation = nil self._eventID = nil self._isItem = nil self._isCompleted = nil self._isRestate = nil self._value = nil end function EvaluationCondition:OnActive() local initializer = ConditionInitializer[self._eventID] or ConditionInitializer.Default self._isCompleted, self._value = initializer(self._evaluation.Data) if self._isItem then for i, itemID in ipairs(self._evaluation.Data.Param3) do EventSystem.Regist(itemID..self._eventID, self.OnMessage, self) end else EventSystem.Regist(self._eventID, self.OnMessage, self) end end function EvaluationCondition:OnDeactive() if self._isItem then for i, itemID in ipairs(self._evaluation.Data.Param3) do EventSystem.UnRegist(itemID..self._eventID, self.OnMessage, self) end else EventSystem.UnRegist(self._eventID, self.OnMessage, self) end end function EvaluationCondition:OnMessage(...) local preComplete = self._isCompleted local analyzer = ConditionAnalyzer[self._eventID] self._isCompleted, self._value = analyzer(self._value, self._evaluation.Data, ...) if self._isCompleted ~= preComplete then self._evaluation:UpdateCompleteState() if not self._isRestate then self:OnDeactive() end end end function EvaluationCondition:CheckComplete() return self._isCompleted end --endregion evaluation condition类 return LevelEvaluationManager