diff --git a/Moose Development/Moose/Tasking/CommandCenter.lua b/Moose Development/Moose/Tasking/CommandCenter.lua index 7157dddff..f14a49dd5 100644 --- a/Moose Development/Moose/Tasking/CommandCenter.lua +++ b/Moose Development/Moose/Tasking/CommandCenter.lua @@ -79,6 +79,37 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName ) end end ) + + -- When a player enters a client or a unit, the CommandCenter will check for each Mission and each Task in the Mission if the player has things to do. + -- For these elements, it will= + -- - Set the correct menu. + -- - Assign the PlayerUnit to the Task if required. + -- - Send a message to the other players in the group that this player has joined. + self:EventOnPlayerEnterUnit( + --- @param #COMMANDCENTER self + -- @param Core.Event#EVENTDATA EventData + function( self, EventData ) + local PlayerUnit = EventData.IniUnit + for MissionID, Mission in pairs( self:GetMissions() ) do + Mission:AddUnit( PlayerUnit ) + end + end + ) + + -- Handle when a player leaves a slot and goes back to spectators ... + -- The PlayerUnit will be UnAssigned from the Task. + -- When there is no Unit left running the Task, the Task goes into Abort... + self:EventOnPlayerLeaveUnit( + --- @param #TASK_BASE self + -- @param Core.Event#EVENTDATA EventData + function( self, EventData ) + local PlayerUnit = EventData.IniUnit + for MissionID, Mission in pairs( self:GetMissions() ) do + Mission:AbortUnit( PlayerUnit ) + end + end + ) + return self end @@ -98,6 +129,13 @@ function COMMANDCENTER:GetPositionable() return self.CommandCenterPositionable end +--- Get the Missions governed by the HQ command center. +-- @param #COMMANDCENTER self +-- @return #list +function COMMANDCENTER:GetMissions() + + return self.Missions +end --- Add a MISSION to be governed by the HQ command center. -- @param #COMMANDCENTER self diff --git a/Moose Development/Moose/Tasking/Mission.lua b/Moose Development/Moose/Tasking/Mission.lua index 0c0390402..64a31d41e 100644 --- a/Moose Development/Moose/Tasking/Mission.lua +++ b/Moose Development/Moose/Tasking/Mission.lua @@ -73,6 +73,47 @@ function MISSION:GetName() return self.Name end +--- Add a Unit to join the Mission. +-- For each Task within the Mission, the Unit is joined with the Task. +-- If the Unit was not part of a Task in the Mission, false is returned. +-- If the Unit is part of a Task in the Mission, true is returned. +-- @param #MISSION self +-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission. +-- @return #boolean true if Unit is part of a Task in the Mission. +function MISSION:AddUnit( PlayerUnit ) + self:F( { PlayerUnit = PlayerUnit } ) + + local PlayerUnitAdded = false + + for TaskID, Task in pairs( self:GetTasks() ) do + if Task:AddUnit( PlayerUnit ) then + PlayerUnitAdded = true + end + end + + return PlayerUnitAdded +end + +--- Aborts a PlayerUnit from the Mission. +-- For each Task within the Mission, the PlayerUnit is removed from Task where it is assigned. +-- If the Unit was not part of a Task in the Mission, false is returned. +-- If the Unit is part of a Task in the Mission, true is returned. +-- @param #MISSION self +-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission. +-- @return #boolean true if Unit is part of a Task in the Mission. +function MISSION:AbortUnit( PlayerUnit ) + self:F( { PlayerUnit = PlayerUnit } ) + + local PlayerUnitRemoved = false + + for TaskID, Task in pairs( self:GetTasks() ) do + if Task:AbortUnit( PlayerUnit ) then + PlayerUnitRemoved = true + end + end + + return PlayerUnitRemoved +end --- Add a scoring to the mission. -- @param #MISSION self -- @return #MISSION self diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index f599dd00b..8e9365ef8 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -112,68 +112,28 @@ function TASK_BASE:New( Mission, SetGroupAssign, TaskName, TaskType ) -- Handle the birth of new planes within the assigned set. - self:EventOnPlayerEnterUnit( - --- @param #TASK_BASE self - -- @param Core.Event#EVENTDATA EventData - function( self, EventData ) - self:E( EventData ) - self:E( { "State", self:GetState() } ) - local TaskUnit = EventData.IniUnit - local TaskGroup = EventData.IniUnit:GetGroup() - self:SetMenuForGroup(TaskGroup) - if self:IsStateAssigned() then - self:E( self:IsAssignedToGroup( TaskGroup ) ) - if self:IsAssignedToGroup( TaskGroup ) then - self:AssignToUnit( TaskUnit ) - end - end - self:MessageToGroups( TaskUnit:GetPlayerName() .. " joined Task " .. self:GetName() ) - end - ) - - -- Handle when a player leaves a slot and goes back to spectators ... - -- The Task is UnAssigned from the Unit. - -- When there is no Unit left running the Task, the Task goes into Abort... - self:EventOnPlayerLeaveUnit( - --- @param #TASK_BASE self - -- @param Core.Event#EVENTDATA EventData - function( self, EventData ) - self:E( "In LeaveUnit" ) - self:E( { "State", self:GetState() } ) - if self:IsStateAssigned() then - local TaskUnit = EventData.IniUnit - local TaskGroup = EventData.IniUnit:GetGroup() - self:E( self:IsAssignedToGroup( TaskGroup ) ) - if self:IsAssignedToGroup( TaskGroup ) then - self:UnAssignFromUnit( TaskUnit ) - self:MessageToGroups( TaskUnit:GetPlayerName() .. " aborted Task " .. self:GetName() ) - end - self:__Abort( 1 ) - end - end - ) -- Handle when a player crashes ... -- The Task is UnAssigned from the Unit. -- When there is no Unit left running the Task, and all of the Players crashed, the Task goes into Failed ... - self:EventOnCrash( - --- @param #TASK_BASE self - -- @param Core.Event#EVENTDATA EventData - function( self, EventData ) - self:E( "In LeaveUnit" ) - self:E( { "State", self:GetState() } ) - if self:IsStateAssigned() then - local TaskUnit = EventData.IniUnit - local TaskGroup = EventData.IniUnit:GetGroup() - self:E( self.SetGroup:IsIncludeObject( TaskGroup ) ) - if self.SetGroup:IsIncludeObject( TaskGroup ) then - self:UnAssignFromUnit( TaskUnit ) - end - self:MessageToGroups( TaskUnit:GetPlayerName() .. " crashed!, and has aborted Task " .. self:GetName() ) - end - end - ) - +-- self:EventOnCrash( +-- --- @param #TASK_BASE self +-- -- @param Core.Event#EVENTDATA EventData +-- function( self, EventData ) +-- self:E( "In LeaveUnit" ) +-- self:E( { "State", self:GetState() } ) +-- if self:IsStateAssigned() then +-- local TaskUnit = EventData.IniUnit +-- local TaskGroup = EventData.IniUnit:GetGroup() +-- self:E( self.SetGroup:IsIncludeObject( TaskGroup ) ) +-- if self.SetGroup:IsIncludeObject( TaskGroup ) then +-- self:UnAssignFromUnit( TaskUnit ) +-- end +-- self:MessageToGroups( TaskUnit:GetPlayerName() .. " crashed!, and has aborted Task " .. self:GetName() ) +-- end +-- end +-- ) +-- Mission:AddTask( self ) @@ -196,6 +156,80 @@ function TASK_BASE:SetFsmTemplate( FsmTemplate ) self.FsmTemplate = FsmTemplate end +--- Add a PlayerUnit to join the Task. +-- For each Group within the Task, the Unit is check if it can join the Task. +-- If the Unit was not part of the Task, false is returned. +-- If the Unit is part of the Task, true is returned. +-- @param #TASK_BASE self +-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission. +-- @return #boolean true if Unit is part of the Task. +function TASK_BASE:AddUnit( PlayerUnit ) + self:F( { PlayerUnit = PlayerUnit } ) + + local PlayerUnitAdded = false + + local PlayerGroups = self:GetGroups() + local PlayerGroup = PlayerUnit:GetGroup() + + -- Is the PlayerGroup part of the PlayerGroups? + if PlayerGroups:IsIncludeObject( PlayerGroup ) then + + -- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is added to the Task. + -- If the PlayerGroup is not assigned to the Task, the menu needs to be set. In that case, the PlayerUnit will become the GroupPlayer leader. + if self:IsStatePlanned() or self:IsStateReplanned() then + self:SetMenuForGroup( PlayerGroup ) + self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() ) + end + if self:IsStateAssigned() then + local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup ) + self:E( { IsAssignedToGroup = IsAssignedToGroup } ) + if IsAssignedToGroup then + self:AssignToUnit( PlayerUnit ) + self:MessageToGroups( PlayerUnit:GetPlayerName() .. " joined Task " .. self:GetName() ) + end + end + end + + return PlayerUnitAdded +end + +--- Abort a PlayerUnit from a Task. +-- If the Unit was not part of the Task, false is returned. +-- If the Unit is part of the Task, true is returned. +-- @param #TASK_BASE self +-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task. +-- @return #boolean true if Unit is part of the Task. +function TASK_BASE:AbortUnit( PlayerUnit ) + self:F( { PlayerUnit = PlayerUnit } ) + + local PlayerUnitAdded = false + + local PlayerGroups = self:GetGroups() + local PlayerGroup = PlayerUnit:GetGroup() + + -- Is the PlayerGroup part of the PlayerGroups? + if PlayerGroups:IsIncludeObject( PlayerGroup ) then + + -- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task. + -- If the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group. + if self:IsStateAssigned() then + local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup ) + self:E( { IsAssignedToGroup = IsAssignedToGroup } ) + if IsAssignedToGroup then + self:UnAssignFromUnit( PlayerUnit ) + self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() ) + self:E( { TaskGroup = PlayerGroup:GetName(), HasAliveUnits = self:HasAliveUnits() } ) + if self:HasAliveUnits() == false then + PlayerGroup:SetState( PlayerGroup, "Assigned", nil ) + self:RemoveMenuForGroup( PlayerGroup ) + self:__Abort( 1 ) + end + end + end + end + + return PlayerUnitAdded +end --- Gets the Mission to where the TASK belongs. -- @param #TASK_BASE self -- @return Tasking.Mission#MISSION @@ -204,6 +238,7 @@ function TASK_BASE:GetMission() return self.Mission end + --- Gets the SET_GROUP assigned to the TASK. -- @param #TASK_BASE self -- @return Core.Set#SET_GROUP @@ -366,7 +401,7 @@ function TASK_BASE:HasAliveUnits() end end - self:T( { HasAliveUnits = true } ) + self:T( { HasAliveUnits = false } ) return false end @@ -798,19 +833,11 @@ end -- @param #string From -- @param #string To -- @param Core.Event#EVENTDATA Event -function TASK_BASE:onbeforeAbort( Event, From, To ) +function TASK_BASE:onenterAborted( Event, From, To ) - self:E("Abort") - - for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do - if self:HasAliveUnits() then - return false - end - end + self:E("Aborted") self:MessageToGroups( "Task " .. self:GetName() .. " has been aborted! Task will be replanned." ) - - return true end diff --git a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz index 0f935fa24..952828e46 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz and b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz differ diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua index be30215a1..472dde913 100644 --- a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua +++ b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua @@ -30,7 +30,7 @@ local Scoring = SCORING:New( "SEAD" ) Mission:AddScoring( Scoring ) -- Define the set of group of planes that can be assigned to the Mission object. -local SEADSet = SET_GROUP:New():FilterPrefixes( "Test SEAD"):FilterStart() +local SEADSet = SET_GROUP:New():FilterPrefixes( "Test SEAD"):FilterOnce() SEADSet:Flush() -- Define the set of units that are the targets. diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz index 15ec24d93..84f2a2644 100644 Binary files a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz and b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz differ