local EventSystem = require('Event/EventSystem') local Base = require("Battle/Logic/Level/LevelItemFactory/LevelItem") local ConditionHandle = require('Battle/Logic/Level/LevelItemFunction/LevelConditionHandle') local LevelItem_Mission = class("LevelItem_Mission", Base) local MissionAim = class("MissionAim") local ConditionType = LuaConst.LevelConditionType local ActionType = LuaConst.LevelActionType local FP = FP local LuaConst = LuaConst --不需要更新显示的任务类型 local AimWithoutUpdateShow = { [ConditionType.Global_PlayerReachArea] = true } -- 构造函数 ,使用的时候用new ,如果没有特殊的变量设置,不需要这个函数 function LevelItem_Mission:initialize(data) Base.initialize(self,data) self.AimList = {} self._runTimer = FP.newV1(0) self._curAimIndex = nil --所有玩家的当前任务目标索引 self._curAimIndexDic = nil --不同玩家的当前任务目标索引(会覆盖_curAimIndex) end --region --***************生命周期***************-- function LevelItem_Mission:OnActive() self.IsActive = true for i,v in ipairs(self.ItemData.AimList) do local aim = MissionAim:new(v,i,self) aim:OnActive() table.insert(self.AimList,aim) end if self.ItemData.OrderList then self._curAimIndexDic = {} end LevelItemManager.Global:Notify_MissionStart(self) return not self:UpdateState() end function LevelItem_Mission:GetFakeAimList(container) container = container or {} for i,v in ipairs(self.ItemData.AimList) do local aim = MissionAim:new(v,i,self) aim.IsActive = true aim.Completed = false table.insert(container,aim) end return container end function LevelItem_Mission:OnUpdate() Base.OnUpdate(self) if self._runTimer then self._runTimer:Add(LuaConst.TimeSpan) self:Dispatch(ConditionType.Mission_TimeRun,nil,self._runTimer) end if self._runDelayTimer then self._runDelayTimer:Sub(LuaConst.TimeSpan) if FP.LessEquals(self._runDelayTimer, 0) then self:DoAction(ActionType.Mission_Deactive) end end end function LevelItem_Mission:OnDeactive() if Base.OnDeactive(self) then LevelItemManager.Global:Notify_MissionEnd(self) self:ClearAim() self._curAimIndex = 1 self._runDelayTimer = nil if self._curAimIndexDic then table.clear(self._curAimIndexDic) end end end function LevelItem_Mission:OnDestroy() Base.OnDestroy(self) self.AimList = nil self._runTimer = nil self._runDelayTimer = nil self._curAimIndex = nil self._curAimIndexDic = nil end --region 生命周期 --region --***************事件相关***************-- --这个元素可做的事情 ,执行action [事件执行的不受到自身条件限制] function LevelItem_Mission:DoAction(actionType, match, param1) Base.DoAction(self,actionType) if actionType == ActionType.Mission_Deactive then self:OnDeactive() self:Dispatch(ConditionType.Mission_Complete) EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.LevelLayout,self.LevelItemID,1,"Mission Complete") elseif actionType == ActionType.Mission_Active then self:ClearAim() self:OnActive() self:Dispatch(ConditionType.Mission_Start) EventSystem.Dispatch(EventID.UIBattle_Mission_StartMission,self) EventSystem.Dispatch(EventID.BI_LevelMiddle,BIManager.BIType.LevelLayout,self.LevelItemID,1,"Mission Start") elseif actionType == ActionType.Mission_SetWave then self:Dispatch(ConditionType.Mission_WaveReach,nil,param1) end end --endregion 事件相关 --更新任务的状态(当前的目标索引),返回值代表是否所有目标都达成 function LevelItem_Mission:UpdateMissionState() for i, aim in ipairs(self.AimList) do if not aim.Completed then self._curAimIndex = i return false end end return true end function LevelItem_Mission:UpdateOrderState() if not self._curAimIndexDic then return end for playerID, order in ipairs(self.ItemData.OrderList) do for j, aimIndex in ipairs(order) do if not self.AimList[aimIndex].Completed then self._curAimIndexDic[playerID] = aimIndex break end end end end function LevelItem_Mission:UpdateState() self._runDelayTimer = nil if self:UpdateMissionState() then --进入这个判断代表任务目标都已经完成 if self.ItemData.DelayEndTime then self._runDelayTimer = self.ItemData.DelayEndTime:cloneV1() return false else self:DoAction(ActionType.Mission_Deactive) return true end end self:UpdateOrderState() return false end function LevelItem_Mission:ClearAim() for i = 1,#self.AimList do self.AimList[i]:OnDeactive() self.AimList[i] = nil end end function LevelItem_Mission:GetAimCount() return #self.AimList end function LevelItem_Mission:CheckMainMission() return self.ItemData.Branch == 0 end function LevelItem_Mission:GetMissionAimByPlayerID(playerID) local index = not self._curAimIndexDic and self._curAimIndex or self._curAimIndexDic[playerID] return self.AimList[index] end --region --***************任务目标***************-- local CheckOutShape= { [LuaConst.LevelShapeType.Circle] = function(pos, data) return FP.V2.IsDistanceGreater(pos, data.Position, data.Radius) end, [LuaConst.LevelShapeType.Square] = function(pos, data) return not FP.V2.IsInRectRange(pos, data.Position, data.Direction, data.Length, data.Width) end } local CheckOutGuideShape = { [LuaConst.LevelShapeType.Circle] = function(pos, data) return FP.V2.IsDistanceGreater(pos, data.Position, data.GuideRadius) end, [LuaConst.LevelShapeType.Square] = function(pos, data) return not FP.V2.IsInRectRange(pos, data.Position, data.Direction, data.GuideLength, data.GuideWidth) end } local AimRestateType = { [ConditionType.Trigger_PlayerStayNumber] = true, } function MissionAim:initialize(aimData,aimIndex,mission) self.Data = aimData self.Index = aimIndex self.Mission = mission self.PathIndex = 1 self.IsActive = false self.Completed = false self.IsRestate = AimRestateType[aimData.Type] self.ShowGuideIndex = 1 --exp代码,待整理 end function MissionAim:OnMessage(itemId, context, ...) local preCompleted = self.Completed local handleFunc = ConditionHandle[self.Data.Type] if handleFunc then local checkResult = handleFunc(self, ...) if checkResult ~= nil then self.Completed = checkResult end else self.Completed = true end if self.Completed then if not self.IsRestate then self:OnDeactive() end EventSystem.Dispatch(EventID.UIBattle_Mission_CompleteAim, self, true) self.Mission:UpdateState() else if preCompleted then EventSystem.Dispatch(EventID.UIBattle_Mission_CompleteAim, self, false) self.Mission:UpdateState() end if not AimWithoutUpdateShow[self.Data.Type] then EventSystem.Dispatch(EventID.UIBattle_Mission_UpdateAim,self) end end end function MissionAim:OnActive() if self.IsActive then return end self.IsActive = true ConditionHandle.RegisterEvent(self) self.AimEntity = nil local aimData = self.Data if aimData.Type == ConditionType.Global_GivenMonsterAliveNum then self.value = 0 for _, entity in pairs(LogicUpdateManager._entityDic) do if entity._logicInitData.CharacterID == aimData.ParamID and entity.components.attr:IsAlive() then self.value = self.value + 1 end end self.Completed = self.value >= aimData.Param1 elseif aimData.Type == ConditionType.Global_TimeRemain then self.Completed = LevelItemManager.Global:GetRemainTime() >= aimData.Param1 elseif aimData.Type == ConditionType.Global_LevelWaveReach then local curLevelWave = LevelItemManager.Global:GetLevelWave() self.value = curLevelWave >= 0 and curLevelWave or 0 end end function MissionAim:OnDeactive() if not self.IsActive then return end self.IsActive = false ConditionHandle.UnregisterEvent(self) ConditionHandle.ClearCondition(self) if self.AimEntity then EventSystem.UnRegist(self.AimEntity.Event_EntityDead,self.OnAimEntityDead,self) self.AimEntity = nil end end --region -- for guide path --获取指引箭头位置 function MissionAim:RefreshCurrentGuidePosition(pos) if self.Completed then return CheckOutGuideShape[self.Data.ShapeType](pos,self.Data) and self.Data.Position or nil end local point = self.Data.PathPoints[self.ShowGuideIndex] if not point then return self:GetGuidePositionByAim(pos) end if CheckOutGuideShape[point.ShapeType](pos,point) then return point.Position else self.ShowGuideIndex = self.ShowGuideIndex + 1 point = self.Data.PathPoints[self.ShowGuideIndex] return point and point.Position or self:GetGuidePositionByAim(pos) end end --private方法 没有point点的时候,获取目标点的坐标 function MissionAim:GetGuidePositionByAim(pos) if self.Data.NeedAimEntity then if not self.AimEntity then LevelItemManager.Global:LookForMissionAimEntity(self) end if self.AimEntity then local aimPos = self.AimEntity.components.move.LogicPos return FP.V2.IsDistanceGreater(aimPos, pos, self.Data.GuideRadius) and aimPos or nil end end return CheckOutGuideShape[self.Data.ShapeType](pos,self.Data) and self.Data.Position or nil end --endregion -- for guide path --region -- for auto fight --获取任务目标位置 function MissionAim:GetCurrentPosition(pos) if self.Completed then return CheckOutShape[self.Data.ShapeType](pos,self.Data) and self.Data.Position or nil end local point = self.Data.PathPoints[self.PathIndex] if not point then return self:GetPositionByAim(pos) end if CheckOutShape[point.ShapeType](pos,point) then return point.Position else self.PathIndex = self.PathIndex + 1 point = self.Data.PathPoints[self.PathIndex] return point and point.Position or self:GetPositionByAim(pos) end end function MissionAim:RefreshPathIndex(pos) if not self.Completed then local point = self.Data.PathPoints[self.PathIndex] if point then if not CheckOutShape[point.ShapeType](pos, point) then self.PathIndex = self.PathIndex + 1 end end end end function MissionAim:GetPositionByAim(pos) if self.Data.NeedAimEntity then if not self.AimEntity then LevelItemManager.Global:LookForMissionAimEntity(self) end if self.AimEntity then return self.AimEntity.components.move.LogicPos end end return CheckOutShape[self.Data.ShapeType](pos,self.Data) and self.Data.Position or nil end --endregion --for auto fight function MissionAim:ReceiveAimEntity(entity) self.AimEntity = entity EventSystem.Regist(entity.Event_EntityDead, self.OnAimEntityDead, self) end function MissionAim:OnAimEntityDead(entity) self.AimEntity = nil EventSystem.UnRegist(entity.Event_EntityDead,self.OnAimEntityDead,self) end --endregion 任务目标 return LevelItem_Mission