Updated Mission, cleaned it up and removed stuff.

This commit is contained in:
FlightControl 2017-03-15 11:49:47 +01:00
parent 9fc3f7a601
commit 520ee6e459
18 changed files with 1679 additions and 3323 deletions

View File

@ -12,22 +12,6 @@ MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
_Clients = {},
TaskMenus = {},
TaskCategoryMenus = {},
TaskTypeMenus = {},
_ActiveTasks = {},
GoalFunction = nil,
MissionReportTrigger = 0,
MissionProgressTrigger = 0,
MissionReportShow = false,
MissionReportFlash = false,
MissionTimeInterval = 0,
MissionCoalition = "",
SUCCESS = 1,
FAILED = 2,
REPEAT = 3,
_GoalTasks = {}
}
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@ -234,6 +218,10 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
self.MissionCoalition = MissionCoalition
self.Tasks = {}
-- Private implementations
return self
end
@ -524,76 +512,44 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n
end
--- old stuff
--- Returns if a Mission has completed.
-- @return bool
--- Is the @{Mission} **Completed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsCompleted()
self:F()
return self.MissionStatus == "ACCOMPLISHED"
return self:Is( "Completed" )
end
--- Set a Mission to completed.
function MISSION:Completed()
self:F()
self.MissionStatus = "ACCOMPLISHED"
self:StatusToClients()
--- Is the @{Mission} **Idle**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsIdle()
return self:Is( "Idle" )
end
--- Returns if a Mission is ongoing.
-- treturn bool
--- Is the @{Mission} **Ongoing**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing()
self:F()
return self.MissionStatus == "ONGOING"
return self:Is( "Ongoing" )
end
--- Set a Mission to ongoing.
function MISSION:Ongoing()
self:F()
self.MissionStatus = "ONGOING"
--self:StatusToClients()
--- Is the @{Mission} **Failed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsFailed()
return self:Is( "Failed" )
end
--- Returns if a Mission is pending.
-- treturn bool
function MISSION:IsPending()
self:F()
return self.MissionStatus == "PENDING"
end
--- Set a Mission to pending.
function MISSION:Pending()
self:F()
self.MissionStatus = "PENDING"
self:StatusToClients()
end
--- Returns if a Mission has failed.
-- treturn bool
function MISSION:IsFailed()
self:F()
return self.MissionStatus == "FAILED"
end
--- Set a Mission to failed.
function MISSION:Failed()
self:F()
self.MissionStatus = "FAILED"
self:StatusToClients()
end
--- Send the status of the MISSION to all Clients.
function MISSION:StatusToClients()
self:F()
if self.MissionReportFlash then
for ClientID, Client in pairs( self._Clients ) do
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, "Mission Command: Mission Status")
end
end
--- Is the @{Mission} **Hold**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsHold()
return self:Is( "Hold" )
end
--- Validates if the Mission has a Group
-- @param #MISSION
-- @return #boolean true if the Mission has a Group.
function MISSION:HasGroup( TaskGroup )
local Has = false
@ -686,107 +642,6 @@ function MISSION:ReportDetails()
return Report:Text()
end
--- Report the status of all MISSIONs to all active Clients.
function MISSION:ReportToAll()
self:F()
local AlivePlayers = ''
for ClientID, Client in pairs( self._Clients ) do
if Client:GetDCSGroup() then
if Client:GetClientGroupDCSUnit() then
if Client:GetClientGroupDCSUnit():getLife() > 0.0 then
if AlivePlayers == '' then
AlivePlayers = ' Players: ' .. Client:GetClientGroupDCSUnit():getPlayerName()
else
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupDCSUnit():getPlayerName()
end
end
end
end
end
local Tasks = self:GetTasks()
local TaskText = ""
for TaskID, TaskData in pairs( Tasks ) do
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
end
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), 10, "Mission Command: Mission Report" ):ToAll()
end
--- Add a goal function to a MISSION. Goal functions are called when a @{TASK} within a mission has been completed.
-- @param function GoalFunction is the function defined by the mission designer to evaluate whether a certain goal has been reached after a @{TASK} finishes within the @{MISSION}. A GoalFunction must accept 2 parameters: Mission, Client, which contains the current MISSION object and the current CLIENT object respectively.
-- @usage
-- PatriotActivation = {
-- { "US SAM Patriot Zerti", false },
-- { "US SAM Patriot Zegduleti", false },
-- { "US SAM Patriot Gvleti", false }
-- }
--
-- function DeployPatriotTroopsGoal( Mission, Client )
--
--
-- -- Check if the cargo is all deployed for mission success.
-- for CargoID, CargoData in pairs( Mission._Cargos ) do
-- if Group.getByName( CargoData.CargoGroupName ) then
-- CargoGroup = Group.getByName( CargoData.CargoGroupName )
-- if CargoGroup then
-- -- Check if the cargo is ready to activate
-- CurrentLandingZoneID = routines.IsUnitInZones( CargoGroup:getUnits()[1], Mission:GetTask( 2 ).LandingZones ) -- The second task is the Deploytask to measure mission success upon
-- if CurrentLandingZoneID then
-- if PatriotActivation[CurrentLandingZoneID][2] == false then
-- -- Now check if this is a new Mission Task to be completed...
-- trigger.action.setGroupAIOn( Group.getByName( PatriotActivation[CurrentLandingZoneID][1] ) )
-- PatriotActivation[CurrentLandingZoneID][2] = true
-- MessageToBlue( "Mission Command: Message to all airborne units! The " .. PatriotActivation[CurrentLandingZoneID][1] .. " is armed. Our air defenses are now stronger.", 60, "BLUE/PatriotDefense" )
-- MessageToRed( "Mission Command: Our satellite systems are detecting additional NATO air defenses. To all airborne units: Take care!!!", 60, "RED/PatriotDefense" )
-- Mission:GetTask( 2 ):AddGoalCompletion( "Patriots activated", PatriotActivation[CurrentLandingZoneID][1], 1 ) -- Register Patriot activation as part of mission goal.
-- end
-- end
-- end
-- end
-- end
-- end
--
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
function MISSION:AddGoalFunction( GoalFunction )
self:F()
self.GoalFunction = GoalFunction
end
--- Register a new @{CLIENT} to participate within the mission.
-- @param CLIENT Client is the @{CLIENT} object. The object must have been instantiated with @{CLIENT:New}.
-- @return CLIENT
-- @usage
-- Add a number of Client objects to the Mission.
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 1', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 3', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
function MISSION:AddClient( Client )
self:F( { Client } )
local Valid = true
if Valid then
self._Clients[Client.ClientName] = Client
end
return Client
end
--- Find a @{CLIENT} object within the @{MISSION} by its ClientName.
-- @param CLIENT ClientName is a string defining the Client Group as defined within the ME.
-- @return CLIENT
-- @usage
-- -- Seach for Client "Bomber" within the Mission.
-- local BomberClient = Mission:FindClient( "Bomber" )
function MISSION:FindClient( ClientName )
self:F( { self._Clients[ClientName] } )
return self._Clients[ClientName]
end
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
-- @usage
@ -800,330 +655,3 @@ function MISSION:GetTasks()
end
--[[
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
- _TransportExecuteStage.EXECUTING
- _TransportExecuteStage.SUCCESS
- _TransportExecuteStage.FAILED
--]]
_TransportExecuteStage = {
NONE = 0,
EXECUTING = 1,
SUCCESS = 2,
FAILED = 3
}
--- The MISSIONSCHEDULER is an OBJECT and is the main scheduler of ALL active MISSIONs registered within this scheduler. It's workings are considered internal and is automatically created when the Mission.lua file is included.
-- @type MISSIONSCHEDULER
-- @field #MISSIONSCHEDULER.MISSIONS Missions
MISSIONSCHEDULER = {
Missions = {},
MissionCount = 0,
TimeIntervalCount = 0,
TimeIntervalShow = 150,
TimeSeconds = 14400,
TimeShow = 5
}
--- @type MISSIONSCHEDULER.MISSIONS
-- @list <#MISSION> Mission
--- This is the main MISSIONSCHEDULER Scheduler function. It is considered internal and is automatically created when the Mission.lua file is included.
function MISSIONSCHEDULER.Scheduler()
-- loop through the missions in the TransportTasks
for MissionName, MissionData in pairs( MISSIONSCHEDULER.Missions ) do
local Mission = MissionData -- #MISSION
if not Mission:IsCompleted() then
-- This flag will monitor if for this mission, there are clients alive. If this flag is still false at the end of the loop, the mission status will be set to Pending (if not Failed or Completed).
local ClientsAlive = false
for ClientID, ClientData in pairs( Mission._Clients ) do
local Client = ClientData -- Wrapper.Client#CLIENT
if Client:IsAlive() then
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
ClientsAlive = true
-- If this Client was not registered as Alive before:
-- 1. We register the Client as Alive.
-- 2. We initialize the Client Tasks and make a link to the original Mission Task.
-- 3. We initialize the Cargos.
-- 4. We flag the Mission as Ongoing.
if not Client.ClientAlive then
Client.ClientAlive = true
Client.ClientBriefingShown = false
for TaskNumber, Task in pairs( Mission._Tasks ) do
-- Note that this a deepCopy. Each client must have their own Tasks with own Stages!!!
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
-- Each MissionTask must point to the original Mission.
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
end
Mission:Ongoing()
end
-- For each Client, check for each Task the state and evolve the mission.
-- This flag will indicate if the Task of the Client is Complete.
local TaskComplete = false
for TaskNumber, Task in pairs( Client._Tasks ) do
if not Task.Stage then
Task:SetStage( 1 )
end
local TransportTime = timer.getTime()
if not Task:IsDone() then
if Task:Goal() then
Task:ShowGoalProgress( Mission, Client )
end
--env.info( 'Scheduler: Mission = ' .. Mission.Name .. ' / Client = ' .. Client.ClientName .. ' / Task = ' .. Task.Name .. ' / Stage = ' .. Task.ActiveStage .. ' - ' .. Task.Stage.Name .. ' - ' .. Task.Stage.StageType )
-- Action
if Task:StageExecute() then
Task.Stage:Execute( Mission, Client, Task )
end
-- Wait until execution is finished
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
Task.Stage:Executing( Mission, Client, Task )
end
-- Validate completion or reverse to earlier stage
if Task.Time + Task.Stage.WaitTime <= TransportTime then
Task:SetStage( Task.Stage:Validate( Mission, Client, Task ) )
end
if Task:IsDone() then
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
else
-- break only if this task is not yet done, so that future task are not yet activated.
TaskComplete = false -- when a task is not yet completed, a mission cannot be completed
--env.info( 'Scheduler: Mission "'.. Mission.Name .. '" Task "' .. Task.Name .. '" Stage "' .. Task.Stage.Name .. '" break. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
break
end
if TaskComplete then
if Mission.GoalFunction ~= nil then
Mission.GoalFunction( Mission, Client )
end
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
end
-- if not Mission:IsCompleted() then
-- end
end
end
end
local MissionComplete = true
for TaskNumber, Task in pairs( Mission._Tasks ) do
if Task:Goal() then
-- Task:ShowGoalProgress( Mission, Client )
if Task:IsGoalReached() then
else
MissionComplete = false
end
else
MissionComplete = false -- If there is no goal, the mission should never be ended. The goal status will be set somewhere else.
end
end
if MissionComplete then
Mission:Completed()
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionScore( Mission.Name, 100 )
end
else
if TaskComplete then
-- Reset for new tasking of active client
Client.ClientAlive = false -- Reset the client tasks.
end
end
else
if Client.ClientAlive then
env.info( 'Scheduler: Client "' .. Client.ClientName .. '" is inactive.' )
Client.ClientAlive = false
-- This is tricky. If we sanitize Client._Tasks before sanitizing Client._Tasks[TaskNumber].MissionTask, then the original MissionTask will be sanitized, and will be lost within the garbage collector.
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
--Client._Tasks[TaskNumber].MissionTask = nil
--Client._Tasks = nil
end
end
end
-- If all Clients of this Mission are not activated, then the Mission status needs to be put back into Pending status.
-- But only if the Mission was Ongoing. In case the Mission is Completed or Failed, the Mission status may not be changed. In these cases, this will be the last run of this Mission in the Scheduler.
if ClientsAlive == false then
if Mission:IsOngoing() then
-- Mission status back to pending...
Mission:Pending()
end
end
end
Mission:StatusToClients()
if Mission:ReportTrigger() then
Mission:ReportToAll()
end
end
return true
end
--- Start the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Start()
if MISSIONSCHEDULER ~= nil then
--MISSIONSCHEDULER.SchedulerId = routines.scheduleFunction( MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
MISSIONSCHEDULER.SchedulerId = SCHEDULER:New( nil, MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
end
end
--- Stop the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Stop()
if MISSIONSCHEDULER.SchedulerId then
routines.removeFunction(MISSIONSCHEDULER.SchedulerId)
MISSIONSCHEDULER.SchedulerId = nil
end
end
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
-- @param Mission is the MISSION object instantiated by @{MISSION:New}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
function MISSIONSCHEDULER.AddMission( Mission )
MISSIONSCHEDULER.Missions[Mission.Name] = Mission
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount + 1
-- Add an overall AI Client for the AI tasks... This AI Client will facilitate the Events in the background for each Task.
--MissionAdd:AddClient( CLIENT:Register( 'AI' ) )
return Mission
end
--- Remove a MISSION from the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now remove the Mission.
-- MISSIONSCHEDULER:RemoveMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.RemoveMission( MissionName )
MISSIONSCHEDULER.Missions[MissionName] = nil
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount - 1
end
--- Find a MISSION within the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now find the Mission.
-- MissionFind = MISSIONSCHEDULER:FindMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.FindMission( MissionName )
return MISSIONSCHEDULER.Missions[MissionName]
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsShow( )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = true
Mission.MissionReportFlash = false
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsFlash( TimeInterval )
local Count = 0
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = true
Mission.MissionReportTrigger = timer.getTime() + Count * TimeInterval
Mission.MissionTimeInterval = MISSIONSCHEDULER.MissionCount * TimeInterval
env.info( "TimeInterval = " .. Mission.MissionTimeInterval )
Count = Count + 1
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsHide( Prm )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = false
end
end
--- Enables a MENU option in the communications menu under F10 to control the status of the active missions.
-- This function should be called only once when starting the MISSIONSCHEDULER.
function MISSIONSCHEDULER.ReportMenu()
local ReportMenu = SUBMENU:New( 'Status' )
local ReportMenuShow = COMMANDMENU:New( 'Show Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsShow, 0 )
local ReportMenuFlash = COMMANDMENU:New('Flash Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsFlash, 120 )
local ReportMenuHide = COMMANDMENU:New( 'Hide Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsHide, 0 )
end
--- Show the remaining mission time.
function MISSIONSCHEDULER:TimeShow()
self.TimeIntervalCount = self.TimeIntervalCount + 1
if self.TimeIntervalCount >= self.TimeTriggerShow then
local TimeMsg = string.format("%00d", ( self.TimeSeconds / 60 ) - ( timer.getTime() / 60 )) .. ' minutes left until mission reload.'
MESSAGE:New( TimeMsg, self.TimeShow, "Mission time" ):ToAll()
self.TimeIntervalCount = 0
end
end
function MISSIONSCHEDULER:Time( TimeSeconds, TimeIntervalShow, TimeShow )
self.TimeIntervalCount = 0
self.TimeSeconds = TimeSeconds
self.TimeIntervalShow = TimeIntervalShow
self.TimeShow = TimeShow
end
--- Adds a mission scoring to the game.
function MISSIONSCHEDULER:Scoring( Scoring )
self.Scoring = Scoring
end

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170315_1007' )
env.info( 'Moose Generation Timestamp: 20170315_1149' )
local base = _G
Include = {}
@ -32319,22 +32319,6 @@ MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
_Clients = {},
TaskMenus = {},
TaskCategoryMenus = {},
TaskTypeMenus = {},
_ActiveTasks = {},
GoalFunction = nil,
MissionReportTrigger = 0,
MissionProgressTrigger = 0,
MissionReportShow = false,
MissionReportFlash = false,
MissionTimeInterval = 0,
MissionCoalition = "",
SUCCESS = 1,
FAILED = 2,
REPEAT = 3,
_GoalTasks = {}
}
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@ -32541,6 +32525,10 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
self.MissionCoalition = MissionCoalition
self.Tasks = {}
-- Private implementations
return self
end
@ -32831,76 +32819,44 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n
end
--- old stuff
--- Returns if a Mission has completed.
-- @return bool
--- Is the @{Mission} **Completed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsCompleted()
self:F()
return self.MissionStatus == "ACCOMPLISHED"
return self:Is( "Completed" )
end
--- Set a Mission to completed.
function MISSION:Completed()
self:F()
self.MissionStatus = "ACCOMPLISHED"
self:StatusToClients()
--- Is the @{Mission} **Idle**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsIdle()
return self:Is( "Idle" )
end
--- Returns if a Mission is ongoing.
-- treturn bool
--- Is the @{Mission} **Ongoing**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing()
self:F()
return self.MissionStatus == "ONGOING"
return self:Is( "Ongoing" )
end
--- Set a Mission to ongoing.
function MISSION:Ongoing()
self:F()
self.MissionStatus = "ONGOING"
--self:StatusToClients()
--- Is the @{Mission} **Failed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsFailed()
return self:Is( "Failed" )
end
--- Returns if a Mission is pending.
-- treturn bool
function MISSION:IsPending()
self:F()
return self.MissionStatus == "PENDING"
end
--- Set a Mission to pending.
function MISSION:Pending()
self:F()
self.MissionStatus = "PENDING"
self:StatusToClients()
end
--- Returns if a Mission has failed.
-- treturn bool
function MISSION:IsFailed()
self:F()
return self.MissionStatus == "FAILED"
end
--- Set a Mission to failed.
function MISSION:Failed()
self:F()
self.MissionStatus = "FAILED"
self:StatusToClients()
end
--- Send the status of the MISSION to all Clients.
function MISSION:StatusToClients()
self:F()
if self.MissionReportFlash then
for ClientID, Client in pairs( self._Clients ) do
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, "Mission Command: Mission Status")
end
end
--- Is the @{Mission} **Hold**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsHold()
return self:Is( "Hold" )
end
--- Validates if the Mission has a Group
-- @param #MISSION
-- @return #boolean true if the Mission has a Group.
function MISSION:HasGroup( TaskGroup )
local Has = false
@ -32993,107 +32949,6 @@ function MISSION:ReportDetails()
return Report:Text()
end
--- Report the status of all MISSIONs to all active Clients.
function MISSION:ReportToAll()
self:F()
local AlivePlayers = ''
for ClientID, Client in pairs( self._Clients ) do
if Client:GetDCSGroup() then
if Client:GetClientGroupDCSUnit() then
if Client:GetClientGroupDCSUnit():getLife() > 0.0 then
if AlivePlayers == '' then
AlivePlayers = ' Players: ' .. Client:GetClientGroupDCSUnit():getPlayerName()
else
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupDCSUnit():getPlayerName()
end
end
end
end
end
local Tasks = self:GetTasks()
local TaskText = ""
for TaskID, TaskData in pairs( Tasks ) do
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
end
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), 10, "Mission Command: Mission Report" ):ToAll()
end
--- Add a goal function to a MISSION. Goal functions are called when a @{TASK} within a mission has been completed.
-- @param function GoalFunction is the function defined by the mission designer to evaluate whether a certain goal has been reached after a @{TASK} finishes within the @{MISSION}. A GoalFunction must accept 2 parameters: Mission, Client, which contains the current MISSION object and the current CLIENT object respectively.
-- @usage
-- PatriotActivation = {
-- { "US SAM Patriot Zerti", false },
-- { "US SAM Patriot Zegduleti", false },
-- { "US SAM Patriot Gvleti", false }
-- }
--
-- function DeployPatriotTroopsGoal( Mission, Client )
--
--
-- -- Check if the cargo is all deployed for mission success.
-- for CargoID, CargoData in pairs( Mission._Cargos ) do
-- if Group.getByName( CargoData.CargoGroupName ) then
-- CargoGroup = Group.getByName( CargoData.CargoGroupName )
-- if CargoGroup then
-- -- Check if the cargo is ready to activate
-- CurrentLandingZoneID = routines.IsUnitInZones( CargoGroup:getUnits()[1], Mission:GetTask( 2 ).LandingZones ) -- The second task is the Deploytask to measure mission success upon
-- if CurrentLandingZoneID then
-- if PatriotActivation[CurrentLandingZoneID][2] == false then
-- -- Now check if this is a new Mission Task to be completed...
-- trigger.action.setGroupAIOn( Group.getByName( PatriotActivation[CurrentLandingZoneID][1] ) )
-- PatriotActivation[CurrentLandingZoneID][2] = true
-- MessageToBlue( "Mission Command: Message to all airborne units! The " .. PatriotActivation[CurrentLandingZoneID][1] .. " is armed. Our air defenses are now stronger.", 60, "BLUE/PatriotDefense" )
-- MessageToRed( "Mission Command: Our satellite systems are detecting additional NATO air defenses. To all airborne units: Take care!!!", 60, "RED/PatriotDefense" )
-- Mission:GetTask( 2 ):AddGoalCompletion( "Patriots activated", PatriotActivation[CurrentLandingZoneID][1], 1 ) -- Register Patriot activation as part of mission goal.
-- end
-- end
-- end
-- end
-- end
-- end
--
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
function MISSION:AddGoalFunction( GoalFunction )
self:F()
self.GoalFunction = GoalFunction
end
--- Register a new @{CLIENT} to participate within the mission.
-- @param CLIENT Client is the @{CLIENT} object. The object must have been instantiated with @{CLIENT:New}.
-- @return CLIENT
-- @usage
-- Add a number of Client objects to the Mission.
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 1', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 3', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
function MISSION:AddClient( Client )
self:F( { Client } )
local Valid = true
if Valid then
self._Clients[Client.ClientName] = Client
end
return Client
end
--- Find a @{CLIENT} object within the @{MISSION} by its ClientName.
-- @param CLIENT ClientName is a string defining the Client Group as defined within the ME.
-- @return CLIENT
-- @usage
-- -- Seach for Client "Bomber" within the Mission.
-- local BomberClient = Mission:FindClient( "Bomber" )
function MISSION:FindClient( ClientName )
self:F( { self._Clients[ClientName] } )
return self._Clients[ClientName]
end
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
-- @usage
@ -33107,333 +32962,6 @@ function MISSION:GetTasks()
end
--[[
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
- _TransportExecuteStage.EXECUTING
- _TransportExecuteStage.SUCCESS
- _TransportExecuteStage.FAILED
--]]
_TransportExecuteStage = {
NONE = 0,
EXECUTING = 1,
SUCCESS = 2,
FAILED = 3
}
--- The MISSIONSCHEDULER is an OBJECT and is the main scheduler of ALL active MISSIONs registered within this scheduler. It's workings are considered internal and is automatically created when the Mission.lua file is included.
-- @type MISSIONSCHEDULER
-- @field #MISSIONSCHEDULER.MISSIONS Missions
MISSIONSCHEDULER = {
Missions = {},
MissionCount = 0,
TimeIntervalCount = 0,
TimeIntervalShow = 150,
TimeSeconds = 14400,
TimeShow = 5
}
--- @type MISSIONSCHEDULER.MISSIONS
-- @list <#MISSION> Mission
--- This is the main MISSIONSCHEDULER Scheduler function. It is considered internal and is automatically created when the Mission.lua file is included.
function MISSIONSCHEDULER.Scheduler()
-- loop through the missions in the TransportTasks
for MissionName, MissionData in pairs( MISSIONSCHEDULER.Missions ) do
local Mission = MissionData -- #MISSION
if not Mission:IsCompleted() then
-- This flag will monitor if for this mission, there are clients alive. If this flag is still false at the end of the loop, the mission status will be set to Pending (if not Failed or Completed).
local ClientsAlive = false
for ClientID, ClientData in pairs( Mission._Clients ) do
local Client = ClientData -- Wrapper.Client#CLIENT
if Client:IsAlive() then
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
ClientsAlive = true
-- If this Client was not registered as Alive before:
-- 1. We register the Client as Alive.
-- 2. We initialize the Client Tasks and make a link to the original Mission Task.
-- 3. We initialize the Cargos.
-- 4. We flag the Mission as Ongoing.
if not Client.ClientAlive then
Client.ClientAlive = true
Client.ClientBriefingShown = false
for TaskNumber, Task in pairs( Mission._Tasks ) do
-- Note that this a deepCopy. Each client must have their own Tasks with own Stages!!!
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
-- Each MissionTask must point to the original Mission.
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
end
Mission:Ongoing()
end
-- For each Client, check for each Task the state and evolve the mission.
-- This flag will indicate if the Task of the Client is Complete.
local TaskComplete = false
for TaskNumber, Task in pairs( Client._Tasks ) do
if not Task.Stage then
Task:SetStage( 1 )
end
local TransportTime = timer.getTime()
if not Task:IsDone() then
if Task:Goal() then
Task:ShowGoalProgress( Mission, Client )
end
--env.info( 'Scheduler: Mission = ' .. Mission.Name .. ' / Client = ' .. Client.ClientName .. ' / Task = ' .. Task.Name .. ' / Stage = ' .. Task.ActiveStage .. ' - ' .. Task.Stage.Name .. ' - ' .. Task.Stage.StageType )
-- Action
if Task:StageExecute() then
Task.Stage:Execute( Mission, Client, Task )
end
-- Wait until execution is finished
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
Task.Stage:Executing( Mission, Client, Task )
end
-- Validate completion or reverse to earlier stage
if Task.Time + Task.Stage.WaitTime <= TransportTime then
Task:SetStage( Task.Stage:Validate( Mission, Client, Task ) )
end
if Task:IsDone() then
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
else
-- break only if this task is not yet done, so that future task are not yet activated.
TaskComplete = false -- when a task is not yet completed, a mission cannot be completed
--env.info( 'Scheduler: Mission "'.. Mission.Name .. '" Task "' .. Task.Name .. '" Stage "' .. Task.Stage.Name .. '" break. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
break
end
if TaskComplete then
if Mission.GoalFunction ~= nil then
Mission.GoalFunction( Mission, Client )
end
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
end
-- if not Mission:IsCompleted() then
-- end
end
end
end
local MissionComplete = true
for TaskNumber, Task in pairs( Mission._Tasks ) do
if Task:Goal() then
-- Task:ShowGoalProgress( Mission, Client )
if Task:IsGoalReached() then
else
MissionComplete = false
end
else
MissionComplete = false -- If there is no goal, the mission should never be ended. The goal status will be set somewhere else.
end
end
if MissionComplete then
Mission:Completed()
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionScore( Mission.Name, 100 )
end
else
if TaskComplete then
-- Reset for new tasking of active client
Client.ClientAlive = false -- Reset the client tasks.
end
end
else
if Client.ClientAlive then
env.info( 'Scheduler: Client "' .. Client.ClientName .. '" is inactive.' )
Client.ClientAlive = false
-- This is tricky. If we sanitize Client._Tasks before sanitizing Client._Tasks[TaskNumber].MissionTask, then the original MissionTask will be sanitized, and will be lost within the garbage collector.
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
--Client._Tasks[TaskNumber].MissionTask = nil
--Client._Tasks = nil
end
end
end
-- If all Clients of this Mission are not activated, then the Mission status needs to be put back into Pending status.
-- But only if the Mission was Ongoing. In case the Mission is Completed or Failed, the Mission status may not be changed. In these cases, this will be the last run of this Mission in the Scheduler.
if ClientsAlive == false then
if Mission:IsOngoing() then
-- Mission status back to pending...
Mission:Pending()
end
end
end
Mission:StatusToClients()
if Mission:ReportTrigger() then
Mission:ReportToAll()
end
end
return true
end
--- Start the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Start()
if MISSIONSCHEDULER ~= nil then
--MISSIONSCHEDULER.SchedulerId = routines.scheduleFunction( MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
MISSIONSCHEDULER.SchedulerId = SCHEDULER:New( nil, MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
end
end
--- Stop the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Stop()
if MISSIONSCHEDULER.SchedulerId then
routines.removeFunction(MISSIONSCHEDULER.SchedulerId)
MISSIONSCHEDULER.SchedulerId = nil
end
end
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
-- @param Mission is the MISSION object instantiated by @{MISSION:New}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
function MISSIONSCHEDULER.AddMission( Mission )
MISSIONSCHEDULER.Missions[Mission.Name] = Mission
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount + 1
-- Add an overall AI Client for the AI tasks... This AI Client will facilitate the Events in the background for each Task.
--MissionAdd:AddClient( CLIENT:Register( 'AI' ) )
return Mission
end
--- Remove a MISSION from the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now remove the Mission.
-- MISSIONSCHEDULER:RemoveMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.RemoveMission( MissionName )
MISSIONSCHEDULER.Missions[MissionName] = nil
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount - 1
end
--- Find a MISSION within the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now find the Mission.
-- MissionFind = MISSIONSCHEDULER:FindMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.FindMission( MissionName )
return MISSIONSCHEDULER.Missions[MissionName]
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsShow( )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = true
Mission.MissionReportFlash = false
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsFlash( TimeInterval )
local Count = 0
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = true
Mission.MissionReportTrigger = timer.getTime() + Count * TimeInterval
Mission.MissionTimeInterval = MISSIONSCHEDULER.MissionCount * TimeInterval
env.info( "TimeInterval = " .. Mission.MissionTimeInterval )
Count = Count + 1
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsHide( Prm )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = false
end
end
--- Enables a MENU option in the communications menu under F10 to control the status of the active missions.
-- This function should be called only once when starting the MISSIONSCHEDULER.
function MISSIONSCHEDULER.ReportMenu()
local ReportMenu = SUBMENU:New( 'Status' )
local ReportMenuShow = COMMANDMENU:New( 'Show Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsShow, 0 )
local ReportMenuFlash = COMMANDMENU:New('Flash Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsFlash, 120 )
local ReportMenuHide = COMMANDMENU:New( 'Hide Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsHide, 0 )
end
--- Show the remaining mission time.
function MISSIONSCHEDULER:TimeShow()
self.TimeIntervalCount = self.TimeIntervalCount + 1
if self.TimeIntervalCount >= self.TimeTriggerShow then
local TimeMsg = string.format("%00d", ( self.TimeSeconds / 60 ) - ( timer.getTime() / 60 )) .. ' minutes left until mission reload.'
MESSAGE:New( TimeMsg, self.TimeShow, "Mission time" ):ToAll()
self.TimeIntervalCount = 0
end
end
function MISSIONSCHEDULER:Time( TimeSeconds, TimeIntervalShow, TimeShow )
self.TimeIntervalCount = 0
self.TimeSeconds = TimeSeconds
self.TimeIntervalShow = TimeIntervalShow
self.TimeShow = TimeShow
end
--- Adds a mission scoring to the game.
function MISSIONSCHEDULER:Scoring( Scoring )
self.Scoring = Scoring
end
--- This module contains the TASK class.
--
-- 1) @{#TASK} class, extends @{Base#BASE}

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170315_1007' )
env.info( 'Moose Generation Timestamp: 20170315_1149' )
local base = _G
Include = {}
@ -32319,22 +32319,6 @@ MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
_Clients = {},
TaskMenus = {},
TaskCategoryMenus = {},
TaskTypeMenus = {},
_ActiveTasks = {},
GoalFunction = nil,
MissionReportTrigger = 0,
MissionProgressTrigger = 0,
MissionReportShow = false,
MissionReportFlash = false,
MissionTimeInterval = 0,
MissionCoalition = "",
SUCCESS = 1,
FAILED = 2,
REPEAT = 3,
_GoalTasks = {}
}
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@ -32541,6 +32525,10 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
self.MissionCoalition = MissionCoalition
self.Tasks = {}
-- Private implementations
return self
end
@ -32831,76 +32819,44 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n
end
--- old stuff
--- Returns if a Mission has completed.
-- @return bool
--- Is the @{Mission} **Completed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsCompleted()
self:F()
return self.MissionStatus == "ACCOMPLISHED"
return self:Is( "Completed" )
end
--- Set a Mission to completed.
function MISSION:Completed()
self:F()
self.MissionStatus = "ACCOMPLISHED"
self:StatusToClients()
--- Is the @{Mission} **Idle**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsIdle()
return self:Is( "Idle" )
end
--- Returns if a Mission is ongoing.
-- treturn bool
--- Is the @{Mission} **Ongoing**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing()
self:F()
return self.MissionStatus == "ONGOING"
return self:Is( "Ongoing" )
end
--- Set a Mission to ongoing.
function MISSION:Ongoing()
self:F()
self.MissionStatus = "ONGOING"
--self:StatusToClients()
--- Is the @{Mission} **Failed**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsFailed()
return self:Is( "Failed" )
end
--- Returns if a Mission is pending.
-- treturn bool
function MISSION:IsPending()
self:F()
return self.MissionStatus == "PENDING"
end
--- Set a Mission to pending.
function MISSION:Pending()
self:F()
self.MissionStatus = "PENDING"
self:StatusToClients()
end
--- Returns if a Mission has failed.
-- treturn bool
function MISSION:IsFailed()
self:F()
return self.MissionStatus == "FAILED"
end
--- Set a Mission to failed.
function MISSION:Failed()
self:F()
self.MissionStatus = "FAILED"
self:StatusToClients()
end
--- Send the status of the MISSION to all Clients.
function MISSION:StatusToClients()
self:F()
if self.MissionReportFlash then
for ClientID, Client in pairs( self._Clients ) do
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, "Mission Command: Mission Status")
end
end
--- Is the @{Mission} **Hold**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsHold()
return self:Is( "Hold" )
end
--- Validates if the Mission has a Group
-- @param #MISSION
-- @return #boolean true if the Mission has a Group.
function MISSION:HasGroup( TaskGroup )
local Has = false
@ -32993,107 +32949,6 @@ function MISSION:ReportDetails()
return Report:Text()
end
--- Report the status of all MISSIONs to all active Clients.
function MISSION:ReportToAll()
self:F()
local AlivePlayers = ''
for ClientID, Client in pairs( self._Clients ) do
if Client:GetDCSGroup() then
if Client:GetClientGroupDCSUnit() then
if Client:GetClientGroupDCSUnit():getLife() > 0.0 then
if AlivePlayers == '' then
AlivePlayers = ' Players: ' .. Client:GetClientGroupDCSUnit():getPlayerName()
else
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupDCSUnit():getPlayerName()
end
end
end
end
end
local Tasks = self:GetTasks()
local TaskText = ""
for TaskID, TaskData in pairs( Tasks ) do
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
end
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), 10, "Mission Command: Mission Report" ):ToAll()
end
--- Add a goal function to a MISSION. Goal functions are called when a @{TASK} within a mission has been completed.
-- @param function GoalFunction is the function defined by the mission designer to evaluate whether a certain goal has been reached after a @{TASK} finishes within the @{MISSION}. A GoalFunction must accept 2 parameters: Mission, Client, which contains the current MISSION object and the current CLIENT object respectively.
-- @usage
-- PatriotActivation = {
-- { "US SAM Patriot Zerti", false },
-- { "US SAM Patriot Zegduleti", false },
-- { "US SAM Patriot Gvleti", false }
-- }
--
-- function DeployPatriotTroopsGoal( Mission, Client )
--
--
-- -- Check if the cargo is all deployed for mission success.
-- for CargoID, CargoData in pairs( Mission._Cargos ) do
-- if Group.getByName( CargoData.CargoGroupName ) then
-- CargoGroup = Group.getByName( CargoData.CargoGroupName )
-- if CargoGroup then
-- -- Check if the cargo is ready to activate
-- CurrentLandingZoneID = routines.IsUnitInZones( CargoGroup:getUnits()[1], Mission:GetTask( 2 ).LandingZones ) -- The second task is the Deploytask to measure mission success upon
-- if CurrentLandingZoneID then
-- if PatriotActivation[CurrentLandingZoneID][2] == false then
-- -- Now check if this is a new Mission Task to be completed...
-- trigger.action.setGroupAIOn( Group.getByName( PatriotActivation[CurrentLandingZoneID][1] ) )
-- PatriotActivation[CurrentLandingZoneID][2] = true
-- MessageToBlue( "Mission Command: Message to all airborne units! The " .. PatriotActivation[CurrentLandingZoneID][1] .. " is armed. Our air defenses are now stronger.", 60, "BLUE/PatriotDefense" )
-- MessageToRed( "Mission Command: Our satellite systems are detecting additional NATO air defenses. To all airborne units: Take care!!!", 60, "RED/PatriotDefense" )
-- Mission:GetTask( 2 ):AddGoalCompletion( "Patriots activated", PatriotActivation[CurrentLandingZoneID][1], 1 ) -- Register Patriot activation as part of mission goal.
-- end
-- end
-- end
-- end
-- end
-- end
--
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
function MISSION:AddGoalFunction( GoalFunction )
self:F()
self.GoalFunction = GoalFunction
end
--- Register a new @{CLIENT} to participate within the mission.
-- @param CLIENT Client is the @{CLIENT} object. The object must have been instantiated with @{CLIENT:New}.
-- @return CLIENT
-- @usage
-- Add a number of Client objects to the Mission.
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 1', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 3', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
function MISSION:AddClient( Client )
self:F( { Client } )
local Valid = true
if Valid then
self._Clients[Client.ClientName] = Client
end
return Client
end
--- Find a @{CLIENT} object within the @{MISSION} by its ClientName.
-- @param CLIENT ClientName is a string defining the Client Group as defined within the ME.
-- @return CLIENT
-- @usage
-- -- Seach for Client "Bomber" within the Mission.
-- local BomberClient = Mission:FindClient( "Bomber" )
function MISSION:FindClient( ClientName )
self:F( { self._Clients[ClientName] } )
return self._Clients[ClientName]
end
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
-- @usage
@ -33107,333 +32962,6 @@ function MISSION:GetTasks()
end
--[[
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
- _TransportExecuteStage.EXECUTING
- _TransportExecuteStage.SUCCESS
- _TransportExecuteStage.FAILED
--]]
_TransportExecuteStage = {
NONE = 0,
EXECUTING = 1,
SUCCESS = 2,
FAILED = 3
}
--- The MISSIONSCHEDULER is an OBJECT and is the main scheduler of ALL active MISSIONs registered within this scheduler. It's workings are considered internal and is automatically created when the Mission.lua file is included.
-- @type MISSIONSCHEDULER
-- @field #MISSIONSCHEDULER.MISSIONS Missions
MISSIONSCHEDULER = {
Missions = {},
MissionCount = 0,
TimeIntervalCount = 0,
TimeIntervalShow = 150,
TimeSeconds = 14400,
TimeShow = 5
}
--- @type MISSIONSCHEDULER.MISSIONS
-- @list <#MISSION> Mission
--- This is the main MISSIONSCHEDULER Scheduler function. It is considered internal and is automatically created when the Mission.lua file is included.
function MISSIONSCHEDULER.Scheduler()
-- loop through the missions in the TransportTasks
for MissionName, MissionData in pairs( MISSIONSCHEDULER.Missions ) do
local Mission = MissionData -- #MISSION
if not Mission:IsCompleted() then
-- This flag will monitor if for this mission, there are clients alive. If this flag is still false at the end of the loop, the mission status will be set to Pending (if not Failed or Completed).
local ClientsAlive = false
for ClientID, ClientData in pairs( Mission._Clients ) do
local Client = ClientData -- Wrapper.Client#CLIENT
if Client:IsAlive() then
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
ClientsAlive = true
-- If this Client was not registered as Alive before:
-- 1. We register the Client as Alive.
-- 2. We initialize the Client Tasks and make a link to the original Mission Task.
-- 3. We initialize the Cargos.
-- 4. We flag the Mission as Ongoing.
if not Client.ClientAlive then
Client.ClientAlive = true
Client.ClientBriefingShown = false
for TaskNumber, Task in pairs( Mission._Tasks ) do
-- Note that this a deepCopy. Each client must have their own Tasks with own Stages!!!
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
-- Each MissionTask must point to the original Mission.
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
end
Mission:Ongoing()
end
-- For each Client, check for each Task the state and evolve the mission.
-- This flag will indicate if the Task of the Client is Complete.
local TaskComplete = false
for TaskNumber, Task in pairs( Client._Tasks ) do
if not Task.Stage then
Task:SetStage( 1 )
end
local TransportTime = timer.getTime()
if not Task:IsDone() then
if Task:Goal() then
Task:ShowGoalProgress( Mission, Client )
end
--env.info( 'Scheduler: Mission = ' .. Mission.Name .. ' / Client = ' .. Client.ClientName .. ' / Task = ' .. Task.Name .. ' / Stage = ' .. Task.ActiveStage .. ' - ' .. Task.Stage.Name .. ' - ' .. Task.Stage.StageType )
-- Action
if Task:StageExecute() then
Task.Stage:Execute( Mission, Client, Task )
end
-- Wait until execution is finished
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
Task.Stage:Executing( Mission, Client, Task )
end
-- Validate completion or reverse to earlier stage
if Task.Time + Task.Stage.WaitTime <= TransportTime then
Task:SetStage( Task.Stage:Validate( Mission, Client, Task ) )
end
if Task:IsDone() then
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
else
-- break only if this task is not yet done, so that future task are not yet activated.
TaskComplete = false -- when a task is not yet completed, a mission cannot be completed
--env.info( 'Scheduler: Mission "'.. Mission.Name .. '" Task "' .. Task.Name .. '" Stage "' .. Task.Stage.Name .. '" break. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
break
end
if TaskComplete then
if Mission.GoalFunction ~= nil then
Mission.GoalFunction( Mission, Client )
end
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
end
-- if not Mission:IsCompleted() then
-- end
end
end
end
local MissionComplete = true
for TaskNumber, Task in pairs( Mission._Tasks ) do
if Task:Goal() then
-- Task:ShowGoalProgress( Mission, Client )
if Task:IsGoalReached() then
else
MissionComplete = false
end
else
MissionComplete = false -- If there is no goal, the mission should never be ended. The goal status will be set somewhere else.
end
end
if MissionComplete then
Mission:Completed()
if MISSIONSCHEDULER.Scoring then
MISSIONSCHEDULER.Scoring:_AddMissionScore( Mission.Name, 100 )
end
else
if TaskComplete then
-- Reset for new tasking of active client
Client.ClientAlive = false -- Reset the client tasks.
end
end
else
if Client.ClientAlive then
env.info( 'Scheduler: Client "' .. Client.ClientName .. '" is inactive.' )
Client.ClientAlive = false
-- This is tricky. If we sanitize Client._Tasks before sanitizing Client._Tasks[TaskNumber].MissionTask, then the original MissionTask will be sanitized, and will be lost within the garbage collector.
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
--Client._Tasks[TaskNumber].MissionTask = nil
--Client._Tasks = nil
end
end
end
-- If all Clients of this Mission are not activated, then the Mission status needs to be put back into Pending status.
-- But only if the Mission was Ongoing. In case the Mission is Completed or Failed, the Mission status may not be changed. In these cases, this will be the last run of this Mission in the Scheduler.
if ClientsAlive == false then
if Mission:IsOngoing() then
-- Mission status back to pending...
Mission:Pending()
end
end
end
Mission:StatusToClients()
if Mission:ReportTrigger() then
Mission:ReportToAll()
end
end
return true
end
--- Start the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Start()
if MISSIONSCHEDULER ~= nil then
--MISSIONSCHEDULER.SchedulerId = routines.scheduleFunction( MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
MISSIONSCHEDULER.SchedulerId = SCHEDULER:New( nil, MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
end
end
--- Stop the MISSIONSCHEDULER.
function MISSIONSCHEDULER.Stop()
if MISSIONSCHEDULER.SchedulerId then
routines.removeFunction(MISSIONSCHEDULER.SchedulerId)
MISSIONSCHEDULER.SchedulerId = nil
end
end
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
-- @param Mission is the MISSION object instantiated by @{MISSION:New}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
function MISSIONSCHEDULER.AddMission( Mission )
MISSIONSCHEDULER.Missions[Mission.Name] = Mission
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount + 1
-- Add an overall AI Client for the AI tasks... This AI Client will facilitate the Events in the background for each Task.
--MissionAdd:AddClient( CLIENT:Register( 'AI' ) )
return Mission
end
--- Remove a MISSION from the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now remove the Mission.
-- MISSIONSCHEDULER:RemoveMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.RemoveMission( MissionName )
MISSIONSCHEDULER.Missions[MissionName] = nil
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount - 1
end
--- Find a MISSION within the MISSIONSCHEDULER.
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
-- @return MISSION
-- @usage
-- -- Declare a mission.
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
-- 'Operational',
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
-- 'Russia' )
-- MISSIONSCHEDULER:AddMission( Mission )
--
-- -- Now find the Mission.
-- MissionFind = MISSIONSCHEDULER:FindMission( 'Russia Transport Troops SA-6' )
function MISSIONSCHEDULER.FindMission( MissionName )
return MISSIONSCHEDULER.Missions[MissionName]
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsShow( )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = true
Mission.MissionReportFlash = false
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsFlash( TimeInterval )
local Count = 0
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = true
Mission.MissionReportTrigger = timer.getTime() + Count * TimeInterval
Mission.MissionTimeInterval = MISSIONSCHEDULER.MissionCount * TimeInterval
env.info( "TimeInterval = " .. Mission.MissionTimeInterval )
Count = Count + 1
end
end
-- Internal function used by the MISSIONSCHEDULER menu.
function MISSIONSCHEDULER.ReportMissionsHide( Prm )
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
Mission.MissionReportShow = false
Mission.MissionReportFlash = false
end
end
--- Enables a MENU option in the communications menu under F10 to control the status of the active missions.
-- This function should be called only once when starting the MISSIONSCHEDULER.
function MISSIONSCHEDULER.ReportMenu()
local ReportMenu = SUBMENU:New( 'Status' )
local ReportMenuShow = COMMANDMENU:New( 'Show Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsShow, 0 )
local ReportMenuFlash = COMMANDMENU:New('Flash Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsFlash, 120 )
local ReportMenuHide = COMMANDMENU:New( 'Hide Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsHide, 0 )
end
--- Show the remaining mission time.
function MISSIONSCHEDULER:TimeShow()
self.TimeIntervalCount = self.TimeIntervalCount + 1
if self.TimeIntervalCount >= self.TimeTriggerShow then
local TimeMsg = string.format("%00d", ( self.TimeSeconds / 60 ) - ( timer.getTime() / 60 )) .. ' minutes left until mission reload.'
MESSAGE:New( TimeMsg, self.TimeShow, "Mission time" ):ToAll()
self.TimeIntervalCount = 0
end
end
function MISSIONSCHEDULER:Time( TimeSeconds, TimeIntervalShow, TimeShow )
self.TimeIntervalCount = 0
self.TimeSeconds = TimeSeconds
self.TimeIntervalShow = TimeIntervalShow
self.TimeShow = TimeShow
end
--- Adds a mission scoring to the game.
function MISSIONSCHEDULER:Scoring( Scoring )
self.Scoring = Scoring
end
--- This module contains the TASK class.
--
-- 1) @{#TASK} class, extends @{Base#BASE}

View File

@ -354,6 +354,12 @@ Use the method <a href="AI_Cap.html##(AI_CAP_ZONE).SetEngageZone">AI<em>Cap#AI</
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).OnEnterEngaging">AI_CAP_ZONE:OnEnterEngaging(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnEnter Transition Handler for State Engaging.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).OnEventDead">AI_CAP_ZONE:OnEventDead(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -1171,6 +1177,27 @@ The To State string.</p>
<dl class="function">
<dt>
<a id="#(AI_CAP_ZONE).OnEventDead" >
<strong>AI_CAP_ZONE:OnEventDead(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_CAP_ZONE).OnLeaveEngaging" >
<strong>AI_CAP_ZONE:OnLeaveEngaging(Controllable, From, Event, To)</strong>
</a>

View File

@ -163,13 +163,16 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<h3>1.2.2) AI<em>CAS</em>ZONE Events</h3>
<ul>
<li><strong>Start</strong> ( Group ): Start the process.</li>
<li><strong>Route</strong> ( Group ): Route the AI to a new random 3D point within the Patrol Zone.</li>
<li><strong>Engage</strong> ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.</li>
<li><strong>RTB</strong> ( Group ): Route the AI to the home base.</li>
<li><strong>Detect</strong> ( Group ): The AI is detecting targets.</li>
<li><strong>Detected</strong> ( Group ): The AI has detected new targets.</li>
<li><strong>Status</strong> ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.</li>
<li>**<a href="AI_Patrol.html##(AI_PATROL_ZONE).Start">AI<em>Patrol#AI</em>PATROL_ZONE.Start</a>**: Start the process.</li>
<li>**<a href="AI_Patrol.html##(AI_PATROL_ZONE).Route">AI<em>Patrol#AI</em>PATROL_ZONE.Route</a>**: Route the AI to a new random 3D point within the Patrol Zone.</li>
<li>**<a href="##(AI_CAS_ZONE).Engage">AI<em>CAS</em>ZONE.Engage</a>**: Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.</li>
<li>**<a href="##(AI_CAS_ZONE).Abort">AI<em>CAS</em>ZONE.Abort</a>**: Aborts the engagement and return patrolling in the patrol zone.</li>
<li>**<a href="AI_Patrol.html##(AI_PATROL_ZONE).RTB">AI<em>Patrol#AI</em>PATROL_ZONE.RTB</a>**: Route the AI to the home base.</li>
<li>**<a href="AI_Patrol.html##(AI_PATROL_ZONE).Detect">AI<em>Patrol#AI</em>PATROL_ZONE.Detect</a>**: The AI is detecting targets.</li>
<li>**<a href="AI_Patrol.html##(AI_PATROL_ZONE).Detected">AI<em>Patrol#AI</em>PATROL_ZONE.Detected</a>**: The AI has detected new targets.</li>
<li>**<a href="##(AI_CAS_ZONE).Destroy">AI<em>CAS</em>ZONE.Destroy</a>**: The AI has destroyed a target <a href="Unit.html">Unit</a>.</li>
<li>**<a href="##(AI_CAS_ZONE).Destroyed">AI<em>CAS</em>ZONE.Destroyed</a>**: The AI has destroyed all target <a href="Unit.html">Unit</a>s assigned in the CAS task.</li>
<li><strong>Status</strong>: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.</li>
</ul>
<hr/>
@ -260,7 +263,7 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).Engage">AI_CAS_ZONE:Engage(EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection)</a></td>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).Engage">AI_CAS_ZONE:Engage(EngageSpeed, EngageWeaponExpend, EngageAltitude, EngageAttackQty, EngageDirection)</a></td>
<td class="summary">
<p>Synchronous Event Trigger for Event Engage.</p>
</td>
@ -371,18 +374,18 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).OnBeforeFired">AI_CAS_ZONE:OnBeforeFired(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnBefore Transition Handler for Event Fired.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).OnDead">AI_CAS_ZONE:OnDead(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).OnEnterEngaging">AI_CAS_ZONE:OnEnterEngaging(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnEnter Transition Handler for State Engaging.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).OnEventDead">AI_CAS_ZONE:OnEventDead(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -422,7 +425,7 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).__Engage">AI_CAS_ZONE:__Engage(Delay, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection)</a></td>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).__Engage">AI_CAS_ZONE:__Engage(Delay, EngageSpeed, EngageWeaponExpend, EngageAltitude, EngageAttackQty, EngageDirection)</a></td>
<td class="summary">
<p>Asynchronous Event Trigger for Event Engage.</p>
</td>
@ -431,6 +434,12 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).__Fired">AI_CAS_ZONE:__Fired(Delay)</a></td>
<td class="summary">
<p>Asynchronous Event Trigger for Event Fired.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).onafterAbort">AI_CAS_ZONE:onafterAbort(Controllable, From, Event, To)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -599,7 +608,7 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<dt>
<a id="#(AI_CAS_ZONE).Engage" >
<strong>AI_CAS_ZONE:Engage(EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection)</strong>
<strong>AI_CAS_ZONE:Engage(EngageSpeed, EngageWeaponExpend, EngageAltitude, EngageAttackQty, EngageDirection)</strong>
</a>
</dt>
<dd>
@ -616,14 +625,14 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
</li>
<li>
<p><code><em><a href="Dcs.DCSTypes.html##(Distance)">Dcs.DCSTypes#Distance</a> EngageAltitude </em></code>:
(optional) Desired altitude to perform the unit engagement.</p>
<p><code><em><a href="Dcs.DCSTypes.html##(AI.Task.WeaponExpend)">Dcs.DCSTypes#AI.Task.WeaponExpend</a> EngageWeaponExpend </em></code>:
(optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.</p>
</li>
<li>
<p><code><em><a href="Dcs.DCSTypes.html##(AI.Task.WeaponExpend)">Dcs.DCSTypes#AI.Task.WeaponExpend</a> EngageWeaponExpend </em></code>:
(optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.</p>
<p><code><em><a href="Dcs.DCSTypes.html##(Distance)">Dcs.DCSTypes#Distance</a> EngageAltitude </em></code>:
(optional) Desired altitude to perform the unit engagement.</p>
</li>
<li>
@ -1222,27 +1231,6 @@ Return false to cancel Transition.</p>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).OnDead" >
<strong>AI_CAS_ZONE:OnDead(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).OnEnterEngaging" >
<strong>AI_CAS_ZONE:OnEnterEngaging(Controllable, From, Event, To)</strong>
</a>
@ -1283,6 +1271,27 @@ The To State string.</p>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).OnEventDead" >
<strong>AI_CAS_ZONE:OnEventDead(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).OnLeaveEngaging" >
<strong>AI_CAS_ZONE:OnLeaveEngaging(Controllable, From, Event, To)</strong>
</a>
@ -1439,7 +1448,7 @@ The delay in seconds.</p>
<dt>
<a id="#(AI_CAS_ZONE).__Engage" >
<strong>AI_CAS_ZONE:__Engage(Delay, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection)</strong>
<strong>AI_CAS_ZONE:__Engage(Delay, EngageSpeed, EngageWeaponExpend, EngageAltitude, EngageAttackQty, EngageDirection)</strong>
</a>
</dt>
<dd>
@ -1462,14 +1471,14 @@ The delay in seconds.</p>
</li>
<li>
<p><code><em><a href="Dcs.DCSTypes.html##(Distance)">Dcs.DCSTypes#Distance</a> EngageAltitude </em></code>:
(optional) Desired altitude to perform the unit engagement.</p>
<p><code><em><a href="Dcs.DCSTypes.html##(AI.Task.WeaponExpend)">Dcs.DCSTypes#AI.Task.WeaponExpend</a> EngageWeaponExpend </em></code>:
(optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.</p>
</li>
<li>
<p><code><em><a href="Dcs.DCSTypes.html##(AI.Task.WeaponExpend)">Dcs.DCSTypes#AI.Task.WeaponExpend</a> EngageWeaponExpend </em></code>:
(optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.</p>
<p><code><em><a href="Dcs.DCSTypes.html##(Distance)">Dcs.DCSTypes#Distance</a> EngageAltitude </em></code>:
(optional) Desired altitude to perform the unit engagement.</p>
</li>
<li>
@ -1512,6 +1521,46 @@ The delay in seconds.</p>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).onafterAbort" >
<strong>AI_CAS_ZONE:onafterAbort(Controllable, From, Event, To)</strong>
</a>
</dt>
<dd>
<h3>Parameters</h3>
<ul>
<li>
<p><code><em><a href="Wrapper.Controllable.html##(CONTROLLABLE)">Wrapper.Controllable#CONTROLLABLE</a> Controllable </em></code>:
The Controllable Object managed by the FSM.</p>
</li>
<li>
<p><code><em>#string From </em></code>:
The From State string.</p>
</li>
<li>
<p><code><em>#string Event </em></code>:
The Event string.</p>
</li>
<li>
<p><code><em>#string To </em></code>:
The To State string.</p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_CAS_ZONE).onafterAccomplish" >
<strong>AI_CAS_ZONE:onafterAccomplish(Controllable, From, Event, To)</strong>
</a>

View File

@ -276,12 +276,6 @@ Each successful dead will trigger an Account state transition that can be scored
<td class="name" nowrap="nowrap"><a href="##(ACT_ACCOUNT_DEADS).TaskName">ACT_ACCOUNT_DEADS.TaskName</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(ACT_ACCOUNT_DEADS)._Destructor">ACT_ACCOUNT_DEADS:_Destructor()</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -683,19 +677,6 @@ Each successful dead will trigger an Account state transition that can be scored
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(ACT_ACCOUNT_DEADS)._Destructor" >
<strong>ACT_ACCOUNT_DEADS:_Destructor()</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">

View File

@ -2216,6 +2216,9 @@ A #table or any field.</p>
<p> THIS IS WHY WE NEED LUA 5.2 ...</p>
</dd>
</dl>
<dl class="function">

View File

@ -2425,6 +2425,7 @@ The UNIT carrying the package.</p>
<dl class="function">
<dt>
<em></em>
<a id="#(AI_CARGO_UNIT).CargoCarrier" >
<strong>AI_CARGO_UNIT.CargoCarrier</strong>
</a>

File diff suppressed because it is too large Load Diff

View File

@ -832,6 +832,12 @@ YYYY-MM-DD: CLASS:<strong>NewFunction( Params )</strong> added</p>
<td class="name" nowrap="nowrap"><a href="##(FSM_PROCESS).New">FSM_PROCESS:New(Controllable, Task)</a></td>
<td class="summary">
<p>Creates a new FSM_PROCESS object.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(FSM_PROCESS).Remove">FSM_PROCESS:Remove()</a></td>
<td class="summary">
<p>Removes an FSM_PROCESS object.</p>
</td>
</tr>
<tr>
@ -2473,6 +2479,24 @@ self</p>
<p><em><a href="##(FSM_PROCESS)">#FSM_PROCESS</a>:</em></p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(FSM_PROCESS).Remove" >
<strong>FSM_PROCESS:Remove()</strong>
</a>
</dt>
<dd>
<p>Removes an FSM_PROCESS object.</p>
<h3>Return value</h3>
<p><em><a href="##(FSM_PROCESS)">#FSM_PROCESS</a>:</em></p>
</dd>
</dl>
<dl class="function">

View File

@ -262,7 +262,7 @@ Use the following Zone validation methods on the group:</p>
<tr>
<td class="name" nowrap="nowrap"><a href="##(GROUP).GetCategoryName">GROUP:GetCategoryName()</a></td>
<td class="summary">
<p>Returns the category name of the DCS Group.</p>
<p>Returns the category name of the #GROUP.</p>
</td>
</tr>
<tr>
@ -748,7 +748,7 @@ The category ID</p>
</dt>
<dd>
<p>Returns the category name of the DCS Group.</p>
<p>Returns the category name of the #GROUP.</p>
<h3>Return value</h3>

View File

@ -190,7 +190,6 @@ on defined intervals (currently every minute).</p>
<dl class="function">
<dt>
<em>#number</em>
<a id="#(MOVEMENT).AliveUnits" >
<strong>MOVEMENT.AliveUnits</strong>
</a>
@ -199,9 +198,6 @@ on defined intervals (currently every minute).</p>
<p> Contains the counter how many units are currently alive</p>
</dd>
</dl>
<dl class="function">

File diff suppressed because it is too large Load Diff

View File

@ -342,7 +342,7 @@ Nothing of this code should be modified without testing it thoroughly.</p>
<p> setmetatable( {}, { __mode = "v" } )</p>
<p> or {}</p>
</dd>
</dl>

View File

@ -1870,6 +1870,9 @@ The group that was spawned. You can use this group for further actions.</p>
<p> Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.</p>
</dd>
</dl>
<dl class="function">
@ -2323,6 +2326,9 @@ when nothing was spawned.</p>
<p> Overwrite unit names by default with group name.</p>
</dd>
</dl>
<dl class="function">
@ -2710,7 +2716,7 @@ Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Schedule( 600, 0.5 )
<dl class="function">
<dt>
<em></em>
<em>#boolean</em>
<a id="#(SPAWN).SpawnUnControlled" >
<strong>SPAWN.SpawnUnControlled</strong>
</a>

View File

@ -297,12 +297,24 @@ Use the method <a href="##(TASK).AddScore">TASK.AddScore</a>() to add scores whe
<td class="name" nowrap="nowrap"><a href="##(TASK).IsAssignedToGroup">TASK:IsAssignedToGroup(TaskGroup)</a></td>
<td class="summary">
<p>Returns if the <a href="Task.html">Task</a> is assigned to the Group.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).IsStateAborted">TASK:IsStateAborted()</a></td>
<td class="summary">
<p>Is the <a href="Task.html">Task</a> status <strong>Aborted</strong>.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).IsStateAssigned">TASK:IsStateAssigned()</a></td>
<td class="summary">
<p>Is the <a href="Task.html">Task</a> status <strong>Assigned</strong>.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).IsStateCancelled">TASK:IsStateCancelled()</a></td>
<td class="summary">
<p>Is the <a href="Task.html">Task</a> status <strong>Cancelled</strong>.</p>
</td>
</tr>
<tr>
@ -354,9 +366,9 @@ Use the method <a href="##(TASK).AddScore">TASK.AddScore</a>() to add scores whe
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).MenuTaskAbort">TASK.MenuTaskAbort(MenuParam)</a></td>
<td class="name" nowrap="nowrap"><a href="##(TASK).MenuTaskAbort">TASK:MenuTaskAbort(TaskGroup)</a></td>
<td class="summary">
<p>Report the task status.</p>
</td>
</tr>
<tr>
@ -537,12 +549,24 @@ Use the method <a href="##(TASK).AddScore">TASK.AddScore</a>() to add scores whe
<td class="name" nowrap="nowrap"><a href="##(TASK).SetUnitProcess">TASK:SetUnitProcess(Core, FsmTemplate)</a></td>
<td class="summary">
<p>Sets the Task FSM Process Template</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).StateAborted">TASK:StateAborted()</a></td>
<td class="summary">
<p>Sets a <a href="Task.html">Task</a> to status <strong>Aborted</strong>.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).StateAssigned">TASK:StateAssigned()</a></td>
<td class="summary">
<p>Sets a <a href="Task.html">Task</a> to status <strong>Assigned</strong>.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK).StateCancelled">TASK:StateCancelled()</a></td>
<td class="summary">
<p>Sets a <a href="Task.html">Task</a> to status <strong>Cancelled</strong>.</p>
</td>
</tr>
<tr>
@ -1299,6 +1323,19 @@ self</p>
<p><em>#boolean:</em></p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(TASK).IsStateAborted" >
<strong>TASK:IsStateAborted()</strong>
</a>
</dt>
<dd>
<p>Is the <a href="Task.html">Task</a> status <strong>Aborted</strong>.</p>
</dd>
</dl>
<dl class="function">
@ -1317,6 +1354,19 @@ self</p>
<dl class="function">
<dt>
<a id="#(TASK).IsStateCancelled" >
<strong>TASK:IsStateCancelled()</strong>
</a>
</dt>
<dd>
<p>Is the <a href="Task.html">Task</a> status <strong>Cancelled</strong>.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(TASK).IsStateFailed" >
<strong>TASK:IsStateFailed()</strong>
</a>
@ -1456,18 +1506,18 @@ true if Unit is part of the Task.</p>
<dt>
<a id="#(TASK).MenuTaskAbort" >
<strong>TASK.MenuTaskAbort(MenuParam)</strong>
<strong>TASK:MenuTaskAbort(TaskGroup)</strong>
</a>
</dt>
<dd>
<p>Report the task status.</p>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em> MenuParam </em></code>: </p>
<p><code><em> TaskGroup </em></code>: </p>
</li>
</ul>
@ -2143,6 +2193,19 @@ Fsm#FSM_PROCESS</p>
<dl class="function">
<dt>
<a id="#(TASK).StateAborted" >
<strong>TASK:StateAborted()</strong>
</a>
</dt>
<dd>
<p>Sets a <a href="Task.html">Task</a> to status <strong>Aborted</strong>.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(TASK).StateAssigned" >
<strong>TASK:StateAssigned()</strong>
</a>
@ -2156,6 +2219,19 @@ Fsm#FSM_PROCESS</p>
<dl class="function">
<dt>
<a id="#(TASK).StateCancelled" >
<strong>TASK:StateCancelled()</strong>
</a>
</dt>
<dd>
<p>Sets a <a href="Task.html">Task</a> to status <strong>Cancelled</strong>.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(TASK).StateFailed" >
<strong>TASK:StateFailed()</strong>
</a>

View File

@ -153,13 +153,13 @@ Find a summary below describing for which situation a task type is created:</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK_A2G_DISPATCHER).EvaluateBAI">TASK_A2G_DISPATCHER:EvaluateBAI(DetectedArea, FriendlyCoalition)</a></td>
<td class="name" nowrap="nowrap"><a href="##(TASK_A2G_DISPATCHER).EvaluateBAI">TASK_A2G_DISPATCHER:EvaluateBAI(DetectedItem, FriendlyCoalition)</a></td>
<td class="summary">
<p>Creates a BAI task when there are targets for it.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(TASK_A2G_DISPATCHER).EvaluateCAS">TASK_A2G_DISPATCHER:EvaluateCAS(DetectedArea)</a></td>
<td class="name" nowrap="nowrap"><a href="##(TASK_A2G_DISPATCHER).EvaluateCAS">TASK_A2G_DISPATCHER:EvaluateCAS(DetectedItem)</a></td>
<td class="summary">
<p>Creates a CAS task when there are targets for it.</p>
</td>
@ -270,7 +270,7 @@ Find a summary below describing for which situation a task type is created:</p>
<dt>
<a id="#(TASK_A2G_DISPATCHER).EvaluateBAI" >
<strong>TASK_A2G_DISPATCHER:EvaluateBAI(DetectedArea, FriendlyCoalition)</strong>
<strong>TASK_A2G_DISPATCHER:EvaluateBAI(DetectedItem, FriendlyCoalition)</strong>
</a>
</dt>
<dd>
@ -281,7 +281,7 @@ Find a summary below describing for which situation a task type is created:</p>
<ul>
<li>
<p><code><em><a href="Functional.Detection.html##(DETECTION_AREAS.DetectedArea)">Functional.Detection#DETECTION_AREAS.DetectedArea</a> DetectedArea </em></code>: </p>
<p><code><em><a href="Functional.Detection.html##(DETECTION_AREAS.DetectedItem)">Functional.Detection#DETECTION_AREAS.DetectedItem</a> DetectedItem </em></code>: </p>
</li>
<li>
@ -301,7 +301,7 @@ Find a summary below describing for which situation a task type is created:</p>
<dt>
<a id="#(TASK_A2G_DISPATCHER).EvaluateCAS" >
<strong>TASK_A2G_DISPATCHER:EvaluateCAS(DetectedArea)</strong>
<strong>TASK_A2G_DISPATCHER:EvaluateCAS(DetectedItem)</strong>
</a>
</dt>
<dd>
@ -312,7 +312,7 @@ Find a summary below describing for which situation a task type is created:</p>
<ul>
<li>
<p><code><em><a href="Functional.Detection.html##(DETECTION_AREAS.DetectedArea)">Functional.Detection#DETECTION_AREAS.DetectedArea</a> DetectedArea </em></code>: </p>
<p><code><em><a href="Functional.Detection.html##(DETECTION_AREAS.DetectedItem)">Functional.Detection#DETECTION_AREAS.DetectedItem</a> DetectedItem </em></code>: </p>
</li>
</ul>
@ -335,7 +335,7 @@ Find a summary below describing for which situation a task type is created:</p>
<p>Evaluates the removal of the Task from the Mission.</p>
<p>Can only occur when the DetectedArea is Changed AND the state of the Task is "Planned".</p>
<p>Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".</p>
<h3>Parameters</h3>
<ul>

View File

@ -214,6 +214,12 @@ If you want to obtain the complete <strong>3D position</strong> including ori<72>
<td class="name" nowrap="nowrap"><a href="##(UNIT).GetCallsign">UNIT:GetCallsign()</a></td>
<td class="summary">
<p>Returns the Unit's callsign - the localized string.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(UNIT).GetCategoryName">UNIT:GetCategoryName()</a></td>
<td class="summary">
<p>Returns the category name of the #UNIT.</p>
</td>
</tr>
<tr>
@ -693,6 +699,24 @@ The DCS Unit is not existing or alive. </p>
<dl class="function">
<dt>
<a id="#(UNIT).GetCategoryName" >
<strong>UNIT:GetCategoryName()</strong>
</a>
</dt>
<dd>
<p>Returns the category name of the #UNIT.</p>
<h3>Return value</h3>
<p><em>#string:</em>
Category name = Helicopter, Airplane, Ground Unit, Ship</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(UNIT).GetDCSObject" >
<strong>UNIT:GetDCSObject()</strong>
</a>