Merge branch 'develop' into feature/zone-unit-offsets

This commit is contained in:
Ewald Zietsman
2018-06-16 15:39:14 +02:00
committed by GitHub
122 changed files with 20237 additions and 6429 deletions

View File

@@ -1,4 +1,4 @@
version: 3.9.1.{build} version: 2.4.a.{build}
shallow_clone: true shallow_clone: true
skip_branch_with_pr: false skip_branch_with_pr: false
skip_commits: skip_commits:
@@ -17,6 +17,7 @@ environment:
platform: platform:
- x64 - x64
init: init:
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
@@ -48,7 +49,7 @@ install:
build_script: build_script:
- ps: | - ps: |
if( $env:appveyor_repo_branch -eq 'master' ) if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{ {
$apiUrl = 'https://ci.appveyor.com/api' $apiUrl = 'https://ci.appveyor.com/api'
$token = 'qts80b5kpq0ooj4x6vvw' $token = 'qts80b5kpq0ooj4x6vvw'
@@ -56,12 +57,12 @@ build_script:
"Authorization" = "Bearer $token" "Authorization" = "Bearer $token"
"Content-type" = "application/json" "Content-type" = "application/json"
} }
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-include'; branch = 'master'; environmentVariables = @{} } | ConvertTo-Json $RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-include'; branch = "$env:appveyor_repo_branch"; environmentVariables = @{} } | ConvertTo-Json
# get project with last build details # Generate the new version ...
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody $project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
} }
- ps: | - ps: |
if( $env:appveyor_repo_branch -eq 'master' ) if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
{ {
$apiUrl = 'https://ci.appveyor.com/api' $apiUrl = 'https://ci.appveyor.com/api'
$token = 'qts80b5kpq0ooj4x6vvw' $token = 'qts80b5kpq0ooj4x6vvw'
@@ -69,13 +70,12 @@ build_script:
"Authorization" = "Bearer $token" "Authorization" = "Bearer $token"
"Content-type" = "application/json" "Content-type" = "application/json"
} }
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-docs'; branch = 'master'; environmentVariables = @{} } | ConvertTo-Json $RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-docs'; branch = "$env:appveyor_repo_branch"; environmentVariables = @{} } | ConvertTo-Json
# get project with last build details # get project with last build details
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody $project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
} }
test: off test: off
# test_script: # test_script:
# - cmd: luacheck "Moose Development\Moose\moose.lua" "Moose Mission Setup\moose.lua" # - cmd: luacheck "Moose Development\Moose\moose.lua" "Moose Mission Setup\moose.lua"

View File

@@ -1,14 +1,13 @@
--- **AI** -- (R2.2) - Models the process of air operations for airplanes. --- **AI** -- (R2.2) - Models the process of air operations for airplanes.
-- --
-- This is a class used in the @{AI_A2A_Dispatcher}.
--
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- === -- ===
-- --
-- @module AI_A2A -- @module AI.AI_A2A
-- @image AI_Air_To_Air_Dispatching.JPG
--BASE:TraceClass("AI_A2A") --BASE:TraceClass("AI_A2A")
@@ -16,9 +15,7 @@
--- @type AI_A2A --- @type AI_A2A
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--- # AI_A2A class, extends @{Fsm#FSM_CONTROLLABLE} --- The AI_A2A class implements the core functions to operate an AI @{Wrapper.Group} A2A tasking.
--
-- The AI_A2A class implements the core functions to operate an AI @{Group} A2A tasking.
-- --
-- --
-- ## AI_A2A constructor -- ## AI_A2A constructor
@@ -295,8 +292,8 @@ end
--- Sets (modifies) the minimum and maximum speed of the patrol. --- Sets (modifies) the minimum and maximum speed of the patrol.
-- @param #AI_A2A self -- @param #AI_A2A self
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @return #AI_A2A self -- @return #AI_A2A self
function AI_A2A:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) function AI_A2A:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
@@ -308,8 +305,8 @@ end
--- Sets the floor and ceiling altitude of the patrol. --- Sets the floor and ceiling altitude of the patrol.
-- @param #AI_A2A self -- @param #AI_A2A self
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @return #AI_A2A self -- @return #AI_A2A self
function AI_A2A:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) function AI_A2A:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )

View File

@@ -1,29 +1,24 @@
--- **AI** -- (R2.2) - Models the process of Combat Air Patrol (CAP) for airplanes. --- **AI** -- (R2.2) - Models the process of Combat Air Patrol (CAP) for airplanes.
-- --
-- This is a class used in the @{AI_A2A_Dispatcher}.
--
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- === -- ===
-- --
-- @module AI_A2A_Cap -- @module AI.AI_A2A_Cap
-- @image AI_Combat_Air_Patrol.JPG
--BASE:TraceClass("AI_A2A_CAP")
--- @type AI_A2A_CAP --- @type AI_A2A_CAP
-- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL -- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL
--- # AI_A2A_CAP class, extends @{AI_CAP#AI_PATROL_ZONE} --- The AI_A2A_CAP class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
--
-- The AI_A2A_CAP class implements the core functions to patrol a @{Zone} by an AI @{Group} or @{Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
-- --
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG) -- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
-- --
-- The AI_A2A_CAP is assigned a @{Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event. -- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.
-- --
-- ![Process](..\Presentations\AI_CAP\Dia4.JPG) -- ![Process](..\Presentations\AI_CAP\Dia4.JPG)
-- --
@@ -66,15 +61,15 @@
-- --
-- ### 2.2 AI_A2A_CAP Events -- ### 2.2 AI_A2A_CAP Events
-- --
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_A2A_CAP.Engage}**: Let the AI engage the bogeys. -- * **@{#AI_A2A_CAP.Engage}**: Let the AI engage the bogeys.
-- * **@{#AI_A2A_CAP.Abort}**: Aborts the engagement and return patrolling in the patrol zone. -- * **@{#AI_A2A_CAP.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_A2A_CAP.Destroy}**: The AI has destroyed a bogey @{Unit}. -- * **@{#AI_A2A_CAP.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
-- * **@{#AI_A2A_CAP.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task. -- * **@{#AI_A2A_CAP.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ## 3. Set the Range of Engagement -- ## 3. Set the Range of Engagement
@@ -85,7 +80,7 @@
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone. -- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI. -- The range is applied at the position of the AI.
-- Use the method @{AI_CAP#AI_A2A_CAP.SetEngageRange}() to define that range. -- Use the method @{AI.AI_CAP#AI_A2A_CAP.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- ## 4. Set the Zone of Engagement
-- --
@@ -93,7 +88,7 @@
-- --
-- An optional @{Zone} can be set, -- An optional @{Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI_Cap#AI_A2A_CAP.SetEngageZone}() to define that Zone. -- Use the method @{AI.AI_Cap#AI_A2A_CAP.SetEngageZone}() to define that Zone.
-- --
-- === -- ===
-- --
@@ -106,13 +101,13 @@ AI_A2A_CAP = {
-- @param #AI_A2A_CAP self -- @param #AI_A2A_CAP self
-- @param Wrapper.Group#GROUP AICap -- @param Wrapper.Group#GROUP AICap
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
-- @param Dcs.DCSTypes#Speed EngageMinSpeed The minimum speed of the @{Group} in km/h when engaging a target. -- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
-- @param Dcs.DCSTypes#Speed EngageMaxSpeed The maximum speed of the @{Group} in km/h when engaging a target. -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_A2A_CAP -- @return #AI_A2A_CAP
function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType ) function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType )

View File

@@ -1,11 +1,24 @@
--- **AI** - (R2.2) - Manages the process of an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI. --- **AI** - (R2.2) - Manages the process of an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI.
-- --
-- ===
-- --
-- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia1.JPG) -- Features:
--
-- * Setup quickly an A2A defense system for a coalition.
-- * Setup (CAP) Control Air Patrols at defined zones to enhance your A2A defenses.
-- * Setup (GCI) Ground Control Intercept at defined airbases to enhance your A2A defenses.
-- * Define and use an EWR (Early Warning Radar) network.
-- * Define squadrons at airbases.
-- * Enable airbases for A2A defenses.
-- * Add different plane types to different squadrons.
-- * Add multiple squadrons to different airbases.
-- * Define different ranges to engage upon intruders.
-- * Establish an automatic in air refuel process for CAP using refuel tankers.
-- * Setup default settings for all squadrons and A2A defenses.
-- * Setup specific settings for specific squadrons.
-- * Quickly setup an A2A defense system using @{#AI_A2A_GCICAP}.
-- * Setup a more advanced defense system using @{#AI_A2A_DISPATCHER}.
--
-- --
-- ===
--
-- # QUICK START GUIDE -- # QUICK START GUIDE
-- --
-- There are basically two classes available to model an A2A defense system. -- There are basically two classes available to model an A2A defense system.
@@ -155,7 +168,8 @@
-- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons). -- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
-- ### Authors: **Stonehouse**, **SNAFU** in terms of the advice, documentation, and the original GCICAP script. -- ### Authors: **Stonehouse**, **SNAFU** in terms of the advice, documentation, and the original GCICAP script.
-- --
-- @module AI_A2A_Dispatcher -- @module AI.AI_A2A_Dispatcher
-- @image AI_Air_To_Air_Dispatching.JPG
@@ -165,11 +179,7 @@ do -- AI_A2A_DISPATCHER
-- @type AI_A2A_DISPATCHER -- @type AI_A2A_DISPATCHER
-- @extends Tasking.DetectionManager#DETECTION_MANAGER -- @extends Tasking.DetectionManager#DETECTION_MANAGER
--- # AI\_A2A\_DISPATCHER class, extends @{Tasking#DETECTION_MANAGER} --- Create an automatic air defence system for a coalition.
--
-- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia1.JPG)
--
-- The @{#AI_A2A_DISPATCHER} class is designed to create an automatic air defence system for a coalition.
-- --
-- === -- ===
-- --
@@ -229,7 +239,7 @@ do -- AI_A2A_DISPATCHER
-- therefore less CAP and GCI flights will spawn and this will tend to make just the border area active rather than a melee over the whole map. -- therefore less CAP and GCI flights will spawn and this will tend to make just the border area active rather than a melee over the whole map.
-- It all depends on what the desired effect is. -- It all depends on what the desired effect is.
-- --
-- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional#DETECTION_BASE} object that is given as the input parameter of the AI\_A2A\_DISPATCHER class. -- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional.Detection#DETECTION_BASE} object that is given as the input parameter of the AI\_A2A\_DISPATCHER class.
-- By defining in a **smart way the names or name prefixes of the groups** with EWR capable units, these groups will be **automatically added or deleted** from the EWR network, -- By defining in a **smart way the names or name prefixes of the groups** with EWR capable units, these groups will be **automatically added or deleted** from the EWR network,
-- increasing or decreasing the radar coverage of the Early Warning System. -- increasing or decreasing the radar coverage of the Early Warning System.
-- --
@@ -346,7 +356,7 @@ do -- AI_A2A_DISPATCHER
-- --
-- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia9.JPG) -- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia9.JPG)
-- --
-- If its a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Zone#ZONE_BASE}. -- If its a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}.
-- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. -- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. -- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
@@ -544,7 +554,7 @@ do -- AI_A2A_DISPATCHER
-- * As the CAP flights wander around within the zone waiting to be tasked, these zones need to be large enough that the aircraft are not constantly turning -- * As the CAP flights wander around within the zone waiting to be tasked, these zones need to be large enough that the aircraft are not constantly turning
-- but do not have to be big and numerous enough to completely cover a border. -- but do not have to be big and numerous enough to completely cover a border.
-- --
-- * CAP zones can be of any type, and are derived from the @{Zone#ZONE_BASE} class. Zones can be @{Zone#ZONE}, @{Zone#ZONE_POLYGON}, @{Zone#ZONE_UNIT}, @{Zone#ZONE_GROUP}, etc. -- * CAP zones can be of any type, and are derived from the @{Core.Zone#ZONE_BASE} class. Zones can be @{Core.Zone#ZONE}, @{Core.Zone#ZONE_POLYGON}, @{Core.Zone#ZONE_UNIT}, @{Core.Zone#ZONE_GROUP}, etc.
-- This allows to setup **static, moving and/or complex zones** wherein aircraft will perform the CAP. -- This allows to setup **static, moving and/or complex zones** wherein aircraft will perform the CAP.
-- --
-- * Typically 20000-50000 metres width is used and they are spaced so that aircraft in the zone waiting for tasks dont have to far to travel to protect their coalitions important targets. -- * Typically 20000-50000 metres width is used and they are spaced so that aircraft in the zone waiting for tasks dont have to far to travel to protect their coalitions important targets.
@@ -740,7 +750,7 @@ do -- AI_A2A_DISPATCHER
-- --
-- In the mission editor, setup a group with task Refuelling. A tanker unit of the correct coalition will be automatically selected. -- In the mission editor, setup a group with task Refuelling. A tanker unit of the correct coalition will be automatically selected.
-- Then, use the method @{#AI_A2A_DISPATCHER.SetDefaultTanker}() to set the tanker for the dispatcher. -- Then, use the method @{#AI_A2A_DISPATCHER.SetDefaultTanker}() to set the tanker for the dispatcher.
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultFuelTreshold}() to set the %-tage left in the defender airplane tanks when a refuel action is needed. -- Use the method @{#AI_A2A_DISPATCHER.SetDefaultFuelThreshold}() to set the %-tage left in the defender airplane tanks when a refuel action is needed.
-- --
-- When the tanker specified is alive and in the air, the tanker will be used for refuelling. -- When the tanker specified is alive and in the air, the tanker will be used for refuelling.
-- --
@@ -830,7 +840,7 @@ do -- AI_A2A_DISPATCHER
--- AI_A2A_DISPATCHER constructor. --- AI_A2A_DISPATCHER constructor.
-- This is defining the A2A DISPATCHER for one coaliton. -- This is defining the A2A DISPATCHER for one coaliton.
-- The Dispatcher works with a @{Functional#Detection} object that is taking of the detection of targets using the EWR units. -- The Dispatcher works with a @{Functional.Detection#DETECTION_BASE} object that is taking of the detection of targets using the EWR units.
-- The Detection object is polymorphic, depending on the type of detection object choosen, the detection will work differently. -- The Detection object is polymorphic, depending on the type of detection object choosen, the detection will work differently.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE Detection The DETECTION object that will detects targets using the the Early Warning Radar network. -- @param Functional.Detection#DETECTION_BASE Detection The DETECTION object that will detects targets using the the Early Warning Radar network.
@@ -1142,7 +1152,7 @@ do -- AI_A2A_DISPATCHER
--- Define a border area to simulate a **cold war** scenario. --- Define a border area to simulate a **cold war** scenario.
-- A **cold war** is one where CAP aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border. -- A **cold war** is one where CAP aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border.
-- A **hot war** is one where CAP aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send CAP and GCI aircraft to attack it. -- A **hot war** is one where CAP aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send CAP and GCI aircraft to attack it.
-- If its a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Zone#ZONE_BASE}. This method needs to be used for this. -- If its a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this.
-- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1 -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE. -- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE.
@@ -1276,7 +1286,7 @@ do -- AI_A2A_DISPATCHER
--- Calculates which AI friendlies are nearby the area --- Calculates which AI friendlies are nearby the area
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param DetectedItem -- @param DetectedItem
-- @return #number, Core.CommandCenter#REPORT -- @return #table A list of the friendlies nearby.
function AI_A2A_DISPATCHER:GetAIFriendliesNearBy( DetectedItem ) function AI_A2A_DISPATCHER:GetAIFriendliesNearBy( DetectedItem )
local FriendliesNearBy = self.Detection:GetFriendliesDistance( DetectedItem ) local FriendliesNearBy = self.Detection:GetFriendliesDistance( DetectedItem )
@@ -1423,11 +1433,11 @@ do -- AI_A2A_DISPATCHER
-- You need to specify here EXACTLY the name of the airbase as you see it in the mission editor. -- You need to specify here EXACTLY the name of the airbase as you see it in the mission editor.
-- Examples are `"Batumi"` or `"Tbilisi-Lochini"`. -- Examples are `"Batumi"` or `"Tbilisi-Lochini"`.
-- EXACTLY the airbase name, between quotes `""`. -- EXACTLY the airbase name, between quotes `""`.
-- To ease the airbase naming when using the LDT editor and IntelliSense, the @{Airbase#AIRBASE} class contains enumerations of the airbases of each map. -- To ease the airbase naming when using the LDT editor and IntelliSense, the @{Wrapper.Airbase#AIRBASE} class contains enumerations of the airbases of each map.
-- --
-- * Caucasus: @{Airbase#AIRBASE.Caucaus} -- * Caucasus: @{Wrapper.Airbase#AIRBASE.Caucaus}
-- * Nevada or NTTR: @{Airbase#AIRBASE.Nevada} -- * Nevada or NTTR: @{Wrapper.Airbase#AIRBASE.Nevada}
-- * Normandy: @{Airbase#AIRBASE.Normandy} -- * Normandy: @{Wrapper.Airbase#AIRBASE.Normandy}
-- --
-- @param #string TemplatePrefixes A string or an array of strings specifying the **prefix names of the templates** (not going to explain what is templates here again). -- @param #string TemplatePrefixes A string or an array of strings specifying the **prefix names of the templates** (not going to explain what is templates here again).
-- Examples are `{ "104th", "105th" }` or `"104th"` or `"Template 1"` or `"BLUE PLANES"`. -- Examples are `{ "104th", "105th" }` or `"104th"` or `"Template 1"` or `"BLUE PLANES"`.
@@ -1512,7 +1522,7 @@ do -- AI_A2A_DISPATCHER
--- Set a CAP for a Squadron. --- Set a CAP for a Squadron.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param #string SquadronName The squadron name. -- @param #string SquadronName The squadron name.
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed. -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
-- @param #number FloorAltitude The minimum altitude at which the cap can be executed. -- @param #number FloorAltitude The minimum altitude at which the cap can be executed.
-- @param #number CeilingAltitude the maximum altitude at which the cap can be executed. -- @param #number CeilingAltitude the maximum altitude at which the cap can be executed.
-- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed.
@@ -2391,7 +2401,7 @@ do -- AI_A2A_DISPATCHER
--- Set the default tanker where defenders will Refuel in the air. --- Set the default tanker where defenders will Refuel in the air.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param #strig TankerName A string defining the group name of the Tanker as defined within the Mission Editor. -- @param #string TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
-- @return #AI_A2A_DISPATCHER -- @return #AI_A2A_DISPATCHER
-- @usage -- @usage
-- --
@@ -2414,7 +2424,7 @@ do -- AI_A2A_DISPATCHER
--- Set the squadron tanker where defenders will Refuel in the air. --- Set the squadron tanker where defenders will Refuel in the air.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param #string SquadronName The name of the squadron. -- @param #string SquadronName The name of the squadron.
-- @param #strig TankerName A string defining the group name of the Tanker as defined within the Mission Editor. -- @param #string TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
-- @return #AI_A2A_DISPATCHER -- @return #AI_A2A_DISPATCHER
-- @usage -- @usage
-- --
@@ -2470,7 +2480,7 @@ do -- AI_A2A_DISPATCHER
--- Creates an SWEEP task when there are targets for it. --- Creates an SWEEP task when there are targets for it.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
-- @return Set#SET_UNIT TargetSetUnit: The target set of units. -- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set. -- @return #nil If there are no targets to be set.
function AI_A2A_DISPATCHER:EvaluateSWEEP( DetectedItem ) function AI_A2A_DISPATCHER:EvaluateSWEEP( DetectedItem )
self:F( { DetectedItem.ItemID } ) self:F( { DetectedItem.ItemID } )
@@ -2890,8 +2900,8 @@ do -- AI_A2A_DISPATCHER
--- Creates an ENGAGE task when there are human friendlies airborne near the targets. --- Creates an ENGAGE task when there are human friendlies airborne near the targets.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem The detected item.
-- @return Set#SET_UNIT TargetSetUnit: The target set of units. -- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set. -- @return #nil If there are no targets to be set.
function AI_A2A_DISPATCHER:EvaluateENGAGE( DetectedItem ) function AI_A2A_DISPATCHER:EvaluateENGAGE( DetectedItem )
self:F( { DetectedItem.ItemID } ) self:F( { DetectedItem.ItemID } )
@@ -2917,8 +2927,8 @@ do -- AI_A2A_DISPATCHER
--- Creates an GCI task when there are targets for it. --- Creates an GCI task when there are targets for it.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem -- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem The detected item.
-- @return Set#SET_UNIT TargetSetUnit: The target set of units. -- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set. -- @return #nil If there are no targets to be set.
function AI_A2A_DISPATCHER:EvaluateGCI( DetectedItem ) function AI_A2A_DISPATCHER:EvaluateGCI( DetectedItem )
self:F( { DetectedItem.ItemID } ) self:F( { DetectedItem.ItemID } )
@@ -2944,7 +2954,7 @@ do -- AI_A2A_DISPATCHER
--- Assigns A2A AI Tasks in relation to the detected items. --- Assigns A2A AI Tasks in relation to the detected items.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object. -- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop. -- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function AI_A2A_DISPATCHER:ProcessDetected( Detection ) function AI_A2A_DISPATCHER:ProcessDetected( Detection )
@@ -3069,10 +3079,10 @@ end
do do
--- Calculates which HUMAN friendlies are nearby the area --- Calculates which HUMAN friendlies are nearby the area.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param DetectedItem -- @param DetectedItem The detected item.
-- @return #number, Core.CommandCenter#REPORT -- @return #number, Core.Report#REPORT The amount of friendlies and a text string explaining which friendlies of which type.
function AI_A2A_DISPATCHER:GetPlayerFriendliesNearBy( DetectedItem ) function AI_A2A_DISPATCHER:GetPlayerFriendliesNearBy( DetectedItem )
local DetectedSet = DetectedItem.Set local DetectedSet = DetectedItem.Set
@@ -3115,14 +3125,14 @@ do
return PlayersCount, PlayerTypesReport return PlayersCount, PlayerTypesReport
end end
--- Calculates which friendlies are nearby the area --- Calculates which friendlies are nearby the area.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param DetectedItem -- @param DetectedItem The detected item.
-- @return #number, Core.CommandCenter#REPORT -- @return #number, Core.Report#REPORT The amount of friendlies and a text string explaining which friendlies of which type.
function AI_A2A_DISPATCHER:GetFriendliesNearBy( Target ) function AI_A2A_DISPATCHER:GetFriendliesNearBy( DetectedItem )
local DetectedSet = Target.Set local DetectedSet = DetectedItem.Set
local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( Target ) local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( DetectedItem )
local FriendlyTypes = {} local FriendlyTypes = {}
local FriendliesCount = 0 local FriendliesCount = 0
@@ -3159,8 +3169,8 @@ do
return FriendliesCount, FriendlyTypesReport return FriendliesCount, FriendlyTypesReport
end end
--- --- Schedules a new CAP for the given SquadronName.
-- @param AI_A2A_DISPATCHER -- @param #AI_A2A_DISPATCHER self
-- @param #string SquadronName The squadron name. -- @param #string SquadronName The squadron name.
function AI_A2A_DISPATCHER:SchedulerCAP( SquadronName ) function AI_A2A_DISPATCHER:SchedulerCAP( SquadronName )
self:CAP( SquadronName ) self:CAP( SquadronName )
@@ -3173,12 +3183,8 @@ do
--- @type AI_A2A_GCICAP --- @type AI_A2A_GCICAP
-- @extends #AI_A2A_DISPATCHER -- @extends #AI_A2A_DISPATCHER
--- # AI\_A2A\_GCICAP class, extends @{AI_A2A_Dispatcher#AI_A2A_DISPATCHER} --- Create an automatic air defence system for a coalition setting up GCI and CAP air defenses.
-- -- The class derives from @{#AI_A2A_DISPATCHER} and thus, all the methods that are defined in the @{#AI_A2A_DISPATCHER} class, can be used also in AI\_A2A\_GCICAP.
-- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia1.JPG)
--
-- The AI_A2A_GCICAP class is designed to create an automatic air defence system for a coalition setting up GCI and CAP air defenses.
-- The class derives from @{AI#AI_A2A_DISPATCHER} and thus, all the methods that are defined in the @{AI#AI_A2A_DISPATCHER} class, can be used also in AI\_A2A\_GCICAP.
-- --
-- === -- ===
-- --
@@ -3281,7 +3287,7 @@ do
-- --
-- **The place of the helicopter is important, as the airbase closest to the helicopter will be the airbase from where the CAP planes will take off for CAP.** -- **The place of the helicopter is important, as the airbase closest to the helicopter will be the airbase from where the CAP planes will take off for CAP.**
-- --
-- ## 2) There are a lot of defaults set, which can be further modified using the methods in @{AI#AI_A2A_DISPATCHER}: -- ## 2) There are a lot of defaults set, which can be further modified using the methods in @{#AI_A2A_DISPATCHER}:
-- --
-- ### 2.1) Planes are taking off in the air from the airbases. -- ### 2.1) Planes are taking off in the air from the airbases.
-- --

View File

@@ -8,7 +8,8 @@
-- --
-- === -- ===
-- --
-- @module AI_A2A_GCI -- @module AI.AI_A2A_GCI
-- @image AI_Ground_Control_Intercept.JPG
@@ -16,13 +17,11 @@
-- @extends AI.AI_A2A#AI_A2A -- @extends AI.AI_A2A#AI_A2A
--- # AI_A2A_GCI class, extends @{AI_A2A#AI_A2A} --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
--
-- The AI_A2A_GCI class implements the core functions to intercept intruders. The Engage function will intercept intruders.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia3.JPG) -- ![Process](..\Presentations\AI_GCI\Dia3.JPG)
-- --
-- The AI_A2A_GCI is assigned a @{Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event. -- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
-- --
-- ![Process](..\Presentations\AI_GCI\Dia4.JPG) -- ![Process](..\Presentations\AI_GCI\Dia4.JPG)
-- --
@@ -65,15 +64,15 @@
-- --
-- ### 2.2 AI_A2A_GCI Events -- ### 2.2 AI_A2A_GCI Events
-- --
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_A2A_GCI.Engage}**: Let the AI engage the bogeys. -- * **@{#AI_A2A_GCI.Engage}**: Let the AI engage the bogeys.
-- * **@{#AI_A2A_GCI.Abort}**: Aborts the engagement and return patrolling in the patrol zone. -- * **@{#AI_A2A_GCI.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_A2A_GCI.Destroy}**: The AI has destroyed a bogey @{Unit}. -- * **@{#AI_A2A_GCI.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
-- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task. -- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ## 3. Set the Range of Engagement -- ## 3. Set the Range of Engagement
@@ -84,7 +83,7 @@
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone. -- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI. -- The range is applied at the position of the AI.
-- Use the method @{AI_GCI#AI_A2A_GCI.SetEngageRange}() to define that range. -- Use the method @{AI.AI_GCI#AI_A2A_GCI.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- ## 4. Set the Zone of Engagement
-- --
@@ -92,7 +91,7 @@
-- --
-- An optional @{Zone} can be set, -- An optional @{Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI_Cap#AI_A2A_GCI.SetEngageZone}() to define that Zone. -- Use the method @{AI.AI_Cap#AI_A2A_GCI.SetEngageZone}() to define that Zone.
-- --
-- === -- ===
-- --

View File

@@ -1,26 +1,23 @@
--- **AI** -- (R2.2) - Models the process of air patrol of airplanes. --- **AI** -- (R2.2) - Models the process of air patrol of airplanes.
-- --
-- This is a class used in the @{AI_A2A_Dispatcher}.
--
-- === -- ===
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- === -- ===
-- --
-- @module AI_A2A_Patrol -- @module AI.AI_A2A_Patrol
-- @image AI_Air_Patrolling.JPG
--- @type AI_A2A_PATROL --- @type AI_A2A_PATROL
-- @extends AI.AI_A2A#AI_A2A -- @extends AI.AI_A2A#AI_A2A
--- # AI_A2A_PATROL class, extends @{Fsm#FSM_CONTROLLABLE} --- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
--
-- The AI_A2A_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Group} or @{Group}.
-- --
-- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG)
-- --
-- The AI_A2A_PATROL is assigned a @{Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event. -- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.
-- --
-- ![Process](..\Presentations\AI_PATROL\Dia4.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia4.JPG)
-- --
@@ -93,7 +90,7 @@
-- * @{#AI_A2A_PATROL.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. -- * @{#AI_A2A_PATROL.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased.
-- --
-- The detection frequency can be set with @{#AI_A2A_PATROL.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. -- The detection frequency can be set with @{#AI_A2A_PATROL.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection.
-- Use the method @{#AI_A2A_PATROL.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI. -- Use the method @{#AI_A2A_PATROL.GetDetectedUnits}() to obtain a list of the @{Wrapper.Unit}s detected by the AI.
-- --
-- The detection can be filtered to potential targets in a specific zone. -- The detection can be filtered to potential targets in a specific zone.
-- Use the method @{#AI_A2A_PATROL.SetDetectionZone}() to set the zone where targets need to be detected. -- Use the method @{#AI_A2A_PATROL.SetDetectionZone}() to set the zone where targets need to be detected.
@@ -126,11 +123,11 @@ AI_A2A_PATROL = {
-- @param #AI_A2A_PATROL self -- @param #AI_A2A_PATROL self
-- @param Wrapper.Group#GROUP AIPatrol -- @param Wrapper.Group#GROUP AIPatrol
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_A2A_PATROL self -- @return #AI_A2A_PATROL self
-- @usage -- @usage
-- -- Define a new AI_A2A_PATROL Object. This PatrolArea will patrol a Group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. -- -- Define a new AI_A2A_PATROL Object. This PatrolArea will patrol a Group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
@@ -236,8 +233,8 @@ end
--- Sets (modifies) the minimum and maximum speed of the patrol. --- Sets (modifies) the minimum and maximum speed of the patrol.
-- @param #AI_A2A_PATROL self -- @param #AI_A2A_PATROL self
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
-- @return #AI_A2A_PATROL self -- @return #AI_A2A_PATROL self
function AI_A2A_PATROL:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) function AI_A2A_PATROL:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
@@ -250,8 +247,8 @@ end
--- Sets the floor and ceiling altitude of the patrol. --- Sets the floor and ceiling altitude of the patrol.
-- @param #AI_A2A_PATROL self -- @param #AI_A2A_PATROL self
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @return #AI_A2A_PATROL self -- @return #AI_A2A_PATROL self
function AI_A2A_PATROL:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) function AI_A2A_PATROL:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
@@ -358,7 +355,7 @@ function AI_A2A_PATROL.Resume( AIPatrol )
AIPatrol:F( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } ) AIPatrol:F( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } )
if AIPatrol:IsAlive() then if AIPatrol:IsAlive() then
local _AI_A2A = AIPatrol:GetState( AIPatrol, "AI_A2A" ) -- #AI_A2A local _AI_A2A = AIPatrol:GetState( AIPatrol, "AI_A2A" ) -- AI.AI_A2A#AI_A2A
_AI_A2A:__Reset( 1 ) _AI_A2A:__Reset( 1 )
_AI_A2A:__Route( 5 ) _AI_A2A:__Route( 5 )
end end

View File

@@ -1,9 +1,14 @@
--- **AI** -- (R2.1) - Manages the independent process of Battlefield Air Interdiction (bombing) for airplanes. --- **AI** -- Peform Battlefield Area Interdiction (BAI) within an engagement zone.
-- --
-- === -- **Features:**
--
-- ![Banner Image](..\Presentations\AI_BAI\Dia1.JPG)
-- --
-- * Hold and standby within a patrol zone.
-- * Engage upon command the assigned targets within an engagement zone.
-- * Loop the zone until all targets are eliminated.
-- * Trigger different events upon the results achieved.
-- * After combat, return to the patrol zone and hold.
-- * RTB when commanded or after out of fuel.
--
-- === -- ===
-- --
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BAI%20-%20Battlefield%20Air%20Interdiction) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BAI%20-%20Battlefield%20Air%20Interdiction)
@@ -21,25 +26,23 @@
-- --
-- === -- ===
-- --
-- @module AI_Bai -- @module AI.AI_Bai
-- @image AI_Battlefield_Air_Interdiction.JPG
--- AI_BAI_ZONE class --- AI_BAI_ZONE class
-- @type AI_BAI_ZONE -- @type AI_BAI_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. -- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE -- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # AI_BAI_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE} --- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
-- --
-- AI_BAI_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
--
-- The AI_BAI_ZONE class implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
-- --
-- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG) -- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG)
-- --
-- The AI_BAI_ZONE is assigned a @{Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event. -- The AI_BAI_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event.
-- --
-- ![Start Event](..\Presentations\AI_BAI\Dia4.JPG) -- ![Start Event](..\Presentations\AI_BAI\Dia4.JPG)
-- --
@@ -105,15 +108,15 @@
-- --
-- ### 2.2. AI_BAI_ZONE Events -- ### 2.2. AI_BAI_ZONE Events
-- --
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_BAI_ZONE.Engage}**: Engage the AI to provide BOMB in the Engage Zone, destroying any target it finds. -- * **@{#AI_BAI_ZONE.Engage}**: Engage the AI to provide BOMB in the Engage Zone, destroying any target it finds.
-- * **@{#AI_BAI_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone. -- * **@{#AI_BAI_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Unit}. -- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
-- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the BOMB task. -- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the BOMB task.
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ## 3. Modify the Engage Zone behaviour to pinpoint a **map object** or **scenery object** -- ## 3. Modify the Engage Zone behaviour to pinpoint a **map object** or **scenery object**
@@ -140,12 +143,12 @@ AI_BAI_ZONE = {
--- Creates a new AI_BAI_ZONE object --- Creates a new AI_BAI_ZONE object
-- @param #AI_BAI_ZONE self -- @param #AI_BAI_ZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen. -- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_BAI_ZONE self -- @return #AI_BAI_ZONE self
function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType ) function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType )
@@ -182,24 +185,24 @@ function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
-- @function [parent=#AI_BAI_ZONE] Engage -- @function [parent=#AI_BAI_ZONE] Engage
-- @param #AI_BAI_ZONE self -- @param #AI_BAI_ZONE self
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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. -- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. -- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- Asynchronous Event Trigger for Event Engage. --- Asynchronous Event Trigger for Event Engage.
-- @function [parent=#AI_BAI_ZONE] __Engage -- @function [parent=#AI_BAI_ZONE] __Engage
-- @param #AI_BAI_ZONE self -- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds. -- @param #number Delay The delay in seconds.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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. -- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. -- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- OnLeave Transition Handler for State Engaging. --- OnLeave Transition Handler for State Engaging.
-- @function [parent=#AI_BAI_ZONE] OnLeaveEngaging -- @function [parent=#AI_BAI_ZONE] OnLeaveEngaging
@@ -486,10 +489,10 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (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. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To, function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
EngageSpeed, EngageSpeed,
EngageAltitude, EngageAltitude,

View File

@@ -1,8 +1,11 @@
--- **AI** -- (2.1) - Balance player slots with AI to create an engaging simulation environment, independent of the amount of players. --- **AI** -- Balance player slots with AI to create an engaging simulation environment, independent of the amount of players.
-- --
-- === -- **Features:**
-- --
-- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG) -- * Automatically spawn AI as a replacement of free player slots for a coalition.
-- * Make the AI to perform tasks.
-- * Define a maximum amount of AI to be active at the same time.
-- * Configure the behaviour of AI when a human joins a slot for which an AI is active.
-- --
-- === -- ===
-- --
@@ -21,7 +24,8 @@
-- --
-- === -- ===
-- --
-- @module AI_Balancer -- @module AI.AI_Balancer
-- @image AI_Balancing.JPG
--- @type AI_BALANCER --- @type AI_BALANCER
-- @field Core.Set#SET_CLIENT SetClient -- @field Core.Set#SET_CLIENT SetClient
@@ -30,13 +34,11 @@
-- @extends Core.Fsm#FSM_SET -- @extends Core.Fsm#FSM_SET
--- # AI_BALANCER class, extends @{Fsm#FSM_SET} --- Monitors and manages as many replacement AI groups as there are
-- -- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
-- The AI_BALANCER class monitors and manages as many replacement AI groups as there are
-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players.
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions. -- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
-- --
-- The parent class @{Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM). -- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. -- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods.
-- An explanation about state and event transition methods can be found in the @{FSM} module documentation. -- An explanation about state and event transition methods can be found in the @{FSM} module documentation.
-- --
@@ -78,8 +80,8 @@
-- However, there are 2 additional options that you can use to customize the destroy behaviour. -- However, there are 2 additional options that you can use to customize the destroy behaviour.
-- When a human player joins a slot, you can configure to let the AI return to: -- When a human player joins a slot, you can configure to let the AI return to:
-- --
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Airbase#AIRBASE}. -- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Wrapper.Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Airbase#AIRBASE}. -- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Wrapper.Airbase#AIRBASE}.
-- --
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return, -- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed. -- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
@@ -141,10 +143,10 @@ function AI_BALANCER:InitSpawnInterval( Earliest, Latest )
return self return self
end end
--- Returns the AI to the nearest friendly @{Airbase#AIRBASE}. --- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self -- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnThresholdRange If there is an enemy @{Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}. -- @param DCS#Distance ReturnThresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
-- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Set#SET_AIRBASE}s to evaluate where to return to. -- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Core.Set#SET_AIRBASE}s to evaluate where to return to.
function AI_BALANCER:ReturnToNearestAirbases( ReturnThresholdRange, ReturnAirbaseSet ) function AI_BALANCER:ReturnToNearestAirbases( ReturnThresholdRange, ReturnAirbaseSet )
self.ToNearestAirbase = true self.ToNearestAirbase = true
@@ -152,9 +154,9 @@ function AI_BALANCER:ReturnToNearestAirbases( ReturnThresholdRange, ReturnAirbas
self.ReturnAirbaseSet = ReturnAirbaseSet self.ReturnAirbaseSet = ReturnAirbaseSet
end end
--- Returns the AI to the home @{Airbase#AIRBASE}. --- Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
-- @param #AI_BALANCER self -- @param #AI_BALANCER self
-- @param Dcs.DCSTypes#Distance ReturnThresholdRange If there is an enemy @{Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}. -- @param DCS#Distance ReturnThresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
function AI_BALANCER:ReturnToHomeAirbase( ReturnThresholdRange ) function AI_BALANCER:ReturnToHomeAirbase( ReturnThresholdRange )
self.ToHomeAirbase = true self.ToHomeAirbase = true

View File

@@ -1,9 +1,13 @@
--- **AI** -- (R2.1) - Manages the independent process of Combat Air Patrol (CAP) for airplanes. --- **AI** -- Perform Combat Air Patrolling (CAP) for airplanes.
-- --
-- === -- **Features:**
--
-- ![Banner Image](..\Presentations\AI_CAP\Dia1.JPG)
-- --
-- * Patrol AI airplanes within a given zone.
-- * Trigger detected events when enemy airplanes are detected.
-- * Manage a fuel treshold to RTB on time.
-- * Engage the enemy when detected.
--
--
-- === -- ===
-- --
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol)
@@ -25,23 +29,22 @@
-- --
-- === -- ===
-- --
-- @module AI_Cap -- @module AI.AI_Cap
-- @image AI_Combat_Air_Patrol.JPG
--- @type AI_CAP_ZONE --- @type AI_CAP_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. -- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE -- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # AI_CAP_ZONE class, extends @{AI_CAP#AI_PATROL_ZONE} --- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
--
-- The AI_CAP_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
-- --
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG) -- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
-- --
-- The AI_CAP_ZONE is assigned a @{Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event. -- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
-- --
-- ![Process](..\Presentations\AI_CAP\Dia4.JPG) -- ![Process](..\Presentations\AI_CAP\Dia4.JPG)
-- --
@@ -84,15 +87,15 @@
-- --
-- ### 2.2 AI_CAP_ZONE Events -- ### 2.2 AI_CAP_ZONE Events
-- --
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_CAP_ZONE.Engage}**: Let the AI engage the bogeys. -- * **@{#AI_CAP_ZONE.Engage}**: Let the AI engage the bogeys.
-- * **@{#AI_CAP_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone. -- * **@{#AI_CAP_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_CAP_ZONE.Destroy}**: The AI has destroyed a bogey @{Unit}. -- * **@{#AI_CAP_ZONE.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
-- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task. -- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- ## 3. Set the Range of Engagement -- ## 3. Set the Range of Engagement
@@ -103,7 +106,7 @@
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- The range can be beyond or smaller than the range of the Patrol Zone. -- The range can be beyond or smaller than the range of the Patrol Zone.
-- The range is applied at the position of the AI. -- The range is applied at the position of the AI.
-- Use the method @{AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range. -- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range.
-- --
-- ## 4. Set the Zone of Engagement -- ## 4. Set the Zone of Engagement
-- --
@@ -111,7 +114,7 @@
-- --
-- An optional @{Zone} can be set, -- An optional @{Zone} can be set,
-- that will define when the AI will engage with the detected airborne enemy targets. -- that will define when the AI will engage with the detected airborne enemy targets.
-- Use the method @{AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
-- --
-- === -- ===
-- --
@@ -125,11 +128,11 @@ AI_CAP_ZONE = {
--- Creates a new AI_CAP_ZONE object --- Creates a new AI_CAP_ZONE object
-- @param #AI_CAP_ZONE self -- @param #AI_CAP_ZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_CAP_ZONE self -- @return #AI_CAP_ZONE self
function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )

View File

@@ -1,9 +1,14 @@
--- **AI** -- (R2.1) - Manages the independent process of Close Air Support for airplanes. --- **AI** -- Perform Close Air Support (CAS) near friendlies.
-- --
-- === -- **Features:**
--
-- ![Banner Image](..\Presentations\AI_CAS\Dia1.JPG)
-- --
-- * Hold and standby within a patrol zone.
-- * Engage upon command the enemies within an engagement zone.
-- * Loop the zone until all enemies are eliminated.
-- * Trigger different events upon the results achieved.
-- * After combat, return to the patrol zone and hold.
-- * RTB when commanded or after fuel.
--
-- === -- ===
-- --
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support)
@@ -23,25 +28,21 @@
-- --
-- === -- ===
-- --
-- @module AI_Cas -- @module AI.AI_Cas
-- @image AI_Close_Air_Support.JPG
--- AI_CAS_ZONE class --- AI_CAS_ZONE class
-- @type AI_CAS_ZONE -- @type AI_CAS_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. -- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE -- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # AI_CAS_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE} --- Implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
--
-- AI_CAS_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
--
-- The AI_CAS_ZONE class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
-- --
-- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG) -- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG)
-- --
-- The AI_CAS_ZONE is assigned a @{Group} and this must be done before the AI_CAS_ZONE process can be started through the **Start** event. -- The AI_CAS_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
-- --
-- ![Start Event](..\Presentations\AI_CAS\Dia4.JPG) -- ![Start Event](..\Presentations\AI_CAS\Dia4.JPG)
-- --
@@ -107,15 +108,15 @@
-- --
-- ### 2.2. AI_CAS_ZONE Events -- ### 2.2. AI_CAS_ZONE Events
-- --
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_CAS_ZONE.Engage}**: Engage the AI to provide CAS in the Engage Zone, destroying any target it finds. -- * **@{#AI_CAS_ZONE.Engage}**: Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
-- * **@{#AI_CAS_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone. -- * **@{#AI_CAS_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. -- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Unit}. -- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the CAS task. -- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the CAS task.
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
-- --
-- === -- ===
@@ -130,12 +131,12 @@ AI_CAS_ZONE = {
--- Creates a new AI_CAS_ZONE object --- Creates a new AI_CAS_ZONE object
-- @param #AI_CAS_ZONE self -- @param #AI_CAS_ZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen. -- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_CAS_ZONE self -- @return #AI_CAS_ZONE self
function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType ) function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType )
@@ -171,24 +172,24 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
-- @function [parent=#AI_CAS_ZONE] Engage -- @function [parent=#AI_CAS_ZONE] Engage
-- @param #AI_CAS_ZONE self -- @param #AI_CAS_ZONE self
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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. -- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. -- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- Asynchronous Event Trigger for Event Engage. --- Asynchronous Event Trigger for Event Engage.
-- @function [parent=#AI_CAS_ZONE] __Engage -- @function [parent=#AI_CAS_ZONE] __Engage
-- @param #AI_CAS_ZONE self -- @param #AI_CAS_ZONE self
-- @param #number Delay The delay in seconds. -- @param #number Delay The delay in seconds.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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. -- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. -- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- OnLeave Transition Handler for State Engaging. --- OnLeave Transition Handler for State Engaging.
-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging -- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
@@ -430,10 +431,10 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. -- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (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. -- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (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.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
EngageSpeed, EngageSpeed,
EngageAltitude, EngageAltitude,

View File

@@ -0,0 +1,673 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry and other cargo.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_APC
-- @image AI_Cargo_Dispatching_For_APC.JPG
--- @type AI_CARGO_APC
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- Brings a dynamic cargo handling capability for AI groups.
--
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\APC module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\APC object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- ## Cargo loading.
--
-- The module will load automatically cargo when the APCs are within boarding or loading range.
-- The boarding or loading range is specified when the cargo is created in the simulation, and therefore, this range depends on the type of cargo
-- and the specified boarding range.
--
-- ## Enemies nearby.
--
-- When the APCs are approaching enemy units, something special is happening.
-- The APCs will stop moving, and the loaded infantry will unboard and follow the APCs and will help to defend the group.
-- The carrier will hold the route once the unboarded infantry is further than 50 meters from the APCs,
-- to ensure that the APCs are not too far away from the following running infantry.
-- Once all enemies are cleared, the infantry will board again automatically into the APCs. Once boarded, the APCs will follow its pre-defined route.
--
-- A combat range needs to be specified in meters at the @{#AI_CARGO_APC.New}() method.
-- This combat range will trigger the unboarding of troops when enemies are within the combat range around the APCs.
-- During my tests, I've noticed that there is a balance between ensuring that the infantry is within sufficient hit range (effectiveness) versus
-- vulnerability of the infantry. It all depends on the kind of enemies that are expected to be encountered.
-- A combat range of 350 meters to 500 meters has been proven to be the most effective and efficient.
--
-- ## Infantry health.
--
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
-- However, infantry that was destroyed when unboarded and following the APCs, won't be respawned again. Destroyed is destroyed.
-- As a result, there is some additional strength that is gained when an unboarding action happens, but in terms of simulation balance this has
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
-- time is not so much of an issue ...
--
-- ## Control the APCs on the map.
--
-- It is possible also as a human ground commander to influence the path of the APCs, by pointing a new path using the DCS user interface on the map.
-- In this case, the APCs will change the direction towards its new indicated route. However, there is a catch!
-- Once the APCs are near the enemy, and infantry is unboarded, the APCs won't be able to hold the route until the infantry could catch up.
-- The APCs will simply drive on and won't stop! This is a limitation in ED that prevents user actions being controlled by the scripting engine.
-- No workaround is possible on this.
--
-- ## Cargo deployment.
--
-- Using the @{#AI_CARGO_APC.Deploy}() method, you are able to direct the APCs towards a point on the battlefield to unboard/unload the cargo at the specific coordinate.
-- The APCs will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment.
--
-- ## Cargo pickup.
--
-- Using the @{#AI_CARGO_APC.Pickup}() method, you are able to direct the APCs towards a point on the battlefield to board/load the cargo at the specific coordinate.
-- The APCs will follow nearby roads as much as possible, to ensure fast and clean cargo transportation between the objects and villages in the simulation environment.
--
--
--
-- @field #AI_CARGO_APC
AI_CARGO_APC = {
ClassName = "AI_CARGO_APC",
Coordinate = nil, -- Core.Point#COORDINATE,
APC_Cargo = {},
}
--- Creates a new AI_CARGO_APC object.
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param Core.Set#SET_CARGO CargoSet
-- @param #number CombatRadius
-- @return #AI_CARGO_APC
function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_APC
self.CargoSet = CargoSet -- Core.Set#SET_CARGO
self.CombatRadius = CombatRadius
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "*", "Load", "Boarding" )
self:AddTransition( "Boarding", "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( { "Unboarding", "Unloaded" }, "Unloaded", "Unloaded" )
self:AddTransition( "*", "Monitor", "*" )
self:AddTransition( "*", "Follow", "Following" )
self:AddTransition( "*", "Guard", "Unloaded" )
self:AddTransition( "*", "Home", "*" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
--- Pickup Handler OnBefore for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnBeforePickup
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean
--- Pickup Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterPickup
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
--- Pickup Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] Pickup
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
--- Pickup Asynchronous Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] __Pickup
-- @param #AI_CARGO_APC self
-- @param #number Delay
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Handler OnBefore for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnBeforeDeploy
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean
--- Deploy Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterDeploy
-- @param #AI_CARGO_APC self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] Deploy
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Asynchronous Trigger for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] __Deploy
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Delay
--- Loaded Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterLoaded
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param #string From
-- @param #string Event
-- @param #string To
--- Unloaded Handler OnAfter for AI_CARGO_APC
-- @function [parent=#AI_CARGO_APC] OnAfterUnloaded
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param #string From
-- @param #string Event
-- @param #string To
self:__Monitor( 1 )
self:SetCarrier( APC )
self.Transporting = false
self.Relocating = false
return self
end
--- Set the Carrier.
-- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP CargoCarrier
-- @return #AI_CARGO_APC
function AI_CARGO_APC:SetCarrier( CargoCarrier )
self.CargoCarrier = CargoCarrier -- Wrapper.Group#GROUP
self.CargoCarrier:SetState( self.CargoCarrier, "AI_CARGO_APC", self )
CargoCarrier:HandleEvent( EVENTS.Dead )
CargoCarrier:HandleEvent( EVENTS.Hit )
function CargoCarrier:OnEventDead( EventData )
self:F({"dead"})
local AICargoTroops = self:GetState( self, "AI_CARGO_APC" )
self:F({AICargoTroops=AICargoTroops})
if AICargoTroops then
self:F({})
if not AICargoTroops:Is( "Loaded" ) then
-- There are enemies within combat range. Unload the CargoCarrier.
AICargoTroops:Destroyed()
end
end
end
function CargoCarrier:OnEventHit( EventData )
self:F({"hit"})
local AICargoTroops = self:GetState( self, "AI_CARGO_APC" )
if AICargoTroops then
self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } )
if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then
-- There are enemies within combat range. Unload the CargoCarrier.
AICargoTroops:Unload( false )
end
end
end
self.Zone = ZONE_UNIT:New( self.CargoCarrier:GetName() .. "-Zone", self.CargoCarrier, self.CombatRadius )
self.Coalition = self.CargoCarrier:GetCoalition()
self:SetControllable( CargoCarrier )
self:Guard()
return self
end
function AI_CARGO_APC:IsTransporting()
return self.Transporting == true
end
function AI_CARGO_APC:IsRelocating()
return self.Relocating == true
end
--- Find a free Carrier within a range.
-- @param #AI_CARGO_APC self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Radius
-- @return Wrapper.Group#GROUP NewCarrier
function AI_CARGO_APC:FindCarrier( Coordinate, Radius )
local CoordinateZone = ZONE_RADIUS:New( "Zone" , Coordinate:GetVec2(), Radius )
CoordinateZone:Scan( { Object.Category.UNIT } )
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
local NearUnit = UNIT:Find( DCSUnit )
self:F({NearUnit=NearUnit})
if not NearUnit:GetState( NearUnit, "AI_CARGO_APC" ) then
local Attributes = NearUnit:GetDesc()
self:F({Desc=Attributes})
if NearUnit:HasAttribute( "Trucks" ) then
return NearUnit:GetGroup()
end
end
end
return nil
end
--- Follow Infantry to the Carrier.
-- @param #AI_CARGO_APC self
-- @param #AI_CARGO_APC Me
-- @param Wrapper.Unit#UNIT APCUnit
-- @param Cargo.CargoGroup#CARGO_GROUP Cargo
-- @return #AI_CARGO_APC
function AI_CARGO_APC:FollowToCarrier( Me, APCUnit, CargoGroup )
local InfantryGroup = CargoGroup:GetGroup()
self:F( { self = self:GetClassNameAndID(), InfantryGroup = InfantryGroup:GetName() } )
--if self:Is( "Following" ) then
if APCUnit:IsAlive() then
-- We check if the Cargo is near to the CargoCarrier.
if InfantryGroup:IsPartlyInZone( ZONE_UNIT:New( "Radius", APCUnit, 25 ) ) then
-- The Cargo does not need to follow the Carrier.
Me:Guard()
else
self:F( { InfantryGroup = InfantryGroup:GetName() } )
if InfantryGroup:IsAlive() then
self:F( { InfantryGroup = InfantryGroup:GetName() } )
local Waypoints = {}
-- Calculate the new Route.
local FromCoord = InfantryGroup:GetCoordinate()
local FromGround = FromCoord:WaypointGround( 10, "Diamond" )
self:F({FromGround=FromGround})
table.insert( Waypoints, FromGround )
local ToCoord = APCUnit:GetCoordinate():GetRandomCoordinateInRadius( 10, 5 )
local ToGround = ToCoord:WaypointGround( 10, "Diamond" )
self:F({ToGround=ToGround})
table.insert( Waypoints, ToGround )
local TaskRoute = InfantryGroup:TaskFunction( "AI_CARGO_APC.FollowToCarrier", Me, APCUnit, CargoGroup )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
InfantryGroup:SetTaskWaypoint( Waypoint, TaskRoute ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
InfantryGroup:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
end
end
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
self:F( { APC, From, Event, To } )
if APC and APC:IsAlive() then
if self.CarrierCoordinate then
if self:IsRelocating() == true then
local Coordinate = APC:GetCoordinate()
self.Zone:Scan( { Object.Category.UNIT } )
if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
if self:Is( "Unloaded" ) or self:Is( "Following" ) then
-- There are no enemies within combat range. Load the CargoCarrier.
self:Load()
end
else
if self:Is( "Loaded" ) then
-- There are enemies within combat range. Unload the CargoCarrier.
self:__Unload( 1, false )
else
if self:Is( "Unloaded" ) then
self:Follow()
end
if self:Is( "Following" ) then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
if Cargo:IsAlive() then
if not Cargo:IsNear( APCUnit, 40 ) then
APCUnit:RouteStop()
self.CarrierStopped = true
else
if self.CarrierStopped then
if Cargo:IsNear( APCUnit, 25 ) then
APCUnit:RouteResume()
self.CarrierStopped = nil
end
end
end
end
end
end
end
end
end
end
self.CarrierCoordinate = APC:GetCoordinate()
end
self:__Monitor( -5 )
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To )
self:F( { APC, From, Event, To } )
local Boarding = false
self.BoardingCount = 0
if APC and APC:IsAlive() then
self.APC_Cargo = {}
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), APC:GetName() } )
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
self:F( { "In radius", APCUnit:GetName() } )
APC:RouteStop()
--Cargo:Ungroup()
Cargo:Board( APCUnit, 25 )
self:__Board( 1, Cargo )
Boarding = true
-- So now this APCUnit has Cargo that is being loaded.
-- This will be used further in the logic to follow and to check cargo status.
self.APC_Cargo[APCUnit] = Cargo
break
end
end
end
end
end
return Boarding
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo )
self:F( { APC, From, Event, To, Cargo } )
if APC and APC:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), APC:GetName() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo )
else
self:__Loaded( 1 )
end
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To )
self:F( { APC, From, Event, To } )
local Loaded = true
if APC and APC:IsAlive() then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), APC:GetName() } )
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
Loaded = false
end
end
end
if Loaded == true then
APC:RouteResume()
end
return Loaded
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed )
self:F( { APC, From, Event, To, Deployed } )
if APC and APC:IsAlive() then
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
APC:RouteStop()
for _, Cargo in pairs( APCUnit:GetCargo() ) do
Cargo:UnBoard()
self:__Unboard( 10, Cargo, Deployed )
end
end
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onafterUnboard( APC, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName() } )
if APC and APC:IsAlive() then
if not Cargo:IsUnLoaded() then
self:__Unboard( 10, Cargo, Deployed )
else
self:__Unloaded( 1, Cargo, Deployed )
end
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
local AllUnloaded = true
--Cargo:Regroup()
if APC and APC:IsAlive() then
for _, APCUnit in pairs( APC:GetUnits() ) do
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
local CargoCheck = self.APC_Cargo[APCUnit]
if CargoCheck then
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
if CargoCheck:IsUnLoaded() == false then
AllUnloaded = false
break
end
end
end
if AllUnloaded == true then
if Deployed == true then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
Cargo:SetDeployed( true )
end
self.APC_Cargo = {}
end
self:Guard()
self.CargoCarrier = APC
end
end
self:F( { AllUnloaded = AllUnloaded } )
return AllUnloaded
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC:onafterFollow( APC, From, Event, To )
self:F( { APC, From, Event, To } )
self:F( "Follow" )
if APC and APC:IsAlive() then
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
if Cargo:IsUnLoaded() then
self:FollowToCarrier( self, APCUnit, Cargo )
APCUnit:RouteResume()
end
end
end
end
--- @param #AI_CARGO_APC
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC._Pickup( APC, self )
APC:F( { "AI_CARGO_APC._Pickup:", APC:GetName() } )
if APC:IsAlive() then
self:Load()
self.Relocating = true
end
end
--- @param #AI_CARGO_APC
-- @param Wrapper.Group#GROUP APC
function AI_CARGO_APC._Deploy( APC, self )
APC:F( { "AI_CARGO_APC._Deploy:", APC } )
if APC:IsAlive() then
self:Unload( true )
self.Transporting = false
self.Relocating = false
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate )
if APC and APC:IsAlive() then
if Coordinate then
self.RoutePickup = true
local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
APC:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
else
AI_CARGO_APC._Pickup( APC, self )
end
self.Transporting = true
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate )
if APC and APC:IsAlive() then
self.RouteDeploy = true
local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" )
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
APC:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
end
end
--- @param #AI_CARGO_APC self
-- @param Wrapper.Group#GROUP APC
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
function AI_CARGO_APC:onafterHome( APC, From, Event, To, Coordinate )
if APC and APC:IsAlive() ~= nil then
self.RouteHome = true
local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" )
self:F({Waypoints = Waypoints})
local Waypoint = Waypoints[#Waypoints]
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
end
end

View File

@@ -0,0 +1,447 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Airplane
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
--- @type AI_CARGO_AIRPLANE
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- Implements the transportation of cargo by airplanes.
--
-- @field #AI_CARGO_AIRPLANE
AI_CARGO_AIRPLANE = {
ClassName = "AI_CARGO_AIRPLANE",
Coordinate = nil -- Core.Point#COORDINATE,
}
--- Creates a new AI_CARGO_AIRPLANE object.
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @param Core.Set#SET_CARGO CargoSet
-- @param #number CombatRadius
-- @return #AI_CARGO_AIRPLANE
function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_AIRPLANE
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "Unloaded", "Load", "Boarding" )
self:AddTransition( "Boarding", "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
self:AddTransition( "*", "Landed", "*" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
--- Pickup Handler OnBefore for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforePickup
-- @param #AI_CARGO_AIRPLANE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @return #boolean
--- Pickup Handler OnAfter for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterPickup
-- @param #AI_CARGO_AIRPLANE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Airbase#AIRBASE Airbase
--- Pickup Trigger for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] Pickup
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Airbase#AIRBASE Airbase
--- Pickup Asynchronous Trigger for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] __Pickup
-- @param #AI_CARGO_AIRPLANE self
-- @param #number Delay
-- @param Wrapper.Airbase#AIRBASE Airbase
--- Deploy Handler OnBefore for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforeDeploy
-- @param #AI_CARGO_AIRPLANE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @return #boolean
--- Deploy Handler OnAfter for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeploy
-- @param #AI_CARGO_AIRPLANE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Airbase#AIRBASE Airbase
--- Deploy Trigger for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] Deploy
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Airbase#AIRBASE Airbase
--- Deploy Asynchronous Trigger for AI_CARGO_AIRPLANE
-- @function [parent=#AI_CARGO_AIRPLANE] __Deploy
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Delay
self:SetCarrier( Airplane )
return self
end
--- Set the Carrier.
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @return #AI_CARGO_AIRPLANE
function AI_CARGO_AIRPLANE:SetCarrier( Airplane )
local AICargo = self
self.Airplane = Airplane -- Wrapper.Group#GROUP
self.Airplane:SetState( self.Airplane, "AI_CARGO_AIRPLANE", self )
self.RoutePickup = false
self.RouteDeploy = false
Airplane:HandleEvent( EVENTS.Dead )
Airplane:HandleEvent( EVENTS.Hit )
Airplane:HandleEvent( EVENTS.EngineShutdown )
function Airplane:OnEventDead( EventData )
local AICargoTroops = self:GetState( self, "AI_CARGO_AIRPLANE" )
self:F({AICargoTroops=AICargoTroops})
if AICargoTroops then
self:F({})
if not AICargoTroops:Is( "Loaded" ) then
-- There are enemies within combat range. Unload the Airplane.
AICargoTroops:Destroyed()
end
end
end
function Airplane:OnEventHit( EventData )
local AICargoTroops = self:GetState( self, "AI_CARGO_AIRPLANE" )
if AICargoTroops then
self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } )
if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then
-- There are enemies within combat range. Unload the Airplane.
AICargoTroops:Unload()
end
end
end
function Airplane:OnEventEngineShutdown( EventData )
AICargo:Landed()
end
self.Coalition = self.Airplane:GetCoalition()
self:SetControllable( Airplane )
return self
end
--- Find a free Carrier within a range.
-- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Radius
-- @return Wrapper.Group#GROUP NewCarrier
function AI_CARGO_AIRPLANE:FindCarrier( Coordinate, Radius )
local CoordinateZone = ZONE_RADIUS:New( "Zone" , Coordinate:GetVec2(), Radius )
CoordinateZone:Scan( { Object.Category.UNIT } )
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
local NearUnit = UNIT:Find( DCSUnit )
self:F({NearUnit=NearUnit})
if not NearUnit:GetState( NearUnit, "AI_CARGO_AIRPLANE" ) then
local Attributes = NearUnit:GetDesc()
self:F({Desc=Attributes})
if NearUnit:HasAttribute( "Trucks" ) then
self:SetCarrier( NearUnit )
break
end
end
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @param From
-- @param Event
-- @param To
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Speed
function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
if self.RoutePickup == true then
self:Load( Airplane:GetPointVec2() )
self.RoutePickup = false
end
if self.RouteDeploy == true then
self:Unload()
self.RouteDeploy = false
end
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @param From
-- @param Event
-- @param To
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Speed
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Speed )
if Airplane and Airplane:IsAlive() then
self:Route( Airplane, Airbase, Speed )
self.RoutePickup = true
self.Airbase = Airbase
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @param From
-- @param Event
-- @param To
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Speed
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Airbase, Speed )
if Airplane and Airplane:IsAlive() then
self:Route( Airplane, Airbase, Speed )
self.RouteDeploy = true
self.Airbase = Airbase
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterLoad( Airplane, From, Event, To, Coordinate )
if Airplane and Airplane:IsAlive() then
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
if Cargo:IsInLoadRadius( Coordinate ) then
self:__Board( 5 )
Cargo:Board( Airplane, 25 )
self.Cargo = Cargo
break
end
end
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterBoard( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
self:F({ IsLoaded = self.Cargo:IsLoaded() } )
if not self.Cargo:IsLoaded() then
self:__Board( 10 )
else
self:__Loaded( 1 )
end
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterLoaded( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
self.Cargo:UnBoard()
self:__Unboard( 10 )
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
if not self.Cargo:IsUnLoaded() then
self:__Unboard( 10 )
else
self:__Unloaded( 1 )
end
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To )
if Airplane and Airplane:IsAlive() then
self.Airplane = Airplane
end
end
--- @param #AI_CARGO_AIRPLANE self
-- @param Wrapper.Group#GROUP Airplane
-- @param Wrapper.Airbase#AIRBASE Airbase
-- @param #number Speed
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed )
if Airplane and Airplane:IsAlive() then
local PointVec3 = Airplane:GetPointVec3()
local Takeoff = SPAWN.Takeoff.Hot
local Template = Airplane:GetTemplate()
if Template then
local Points = {}
if self.Airbase then
local FromWaypoint = Template.route.points[1]
-- These are only for ships.
FromWaypoint.linkUnit = nil
FromWaypoint.helipadId = nil
FromWaypoint.airdromeId = nil
local AirbaseID = self.Airbase:GetID()
local AirbaseCategory = self.Airbase:GetDesc().category
FromWaypoint.airdromeId = AirbaseID
FromWaypoint.alt = 0
FromWaypoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
FromWaypoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
-- Translate the position of the Group Template to the Vec3.
for UnitID = 1, #Template.units do
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. Template.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. Template.units[UnitID].y )
-- These cause a lot of confusion.
local UnitTemplate = Template.units[UnitID]
UnitTemplate.parking = 15
UnitTemplate.parking_id = "1"
UnitTemplate.alt = 0
local SX = UnitTemplate.x
local SY = UnitTemplate.y
local BX = FromWaypoint.x
local BY = FromWaypoint.y
local TX = PointVec3.x + ( SX - BX )
local TY = PointVec3.z + ( SY - BY )
UnitTemplate.x = TX
UnitTemplate.y = TY
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
end
FromWaypoint.x = PointVec3.x
FromWaypoint.y = PointVec3.z
Points[#Points+1] = FromWaypoint
else
local GroupPoint = Airplane:GetVec2()
local GroupVelocity = Airplane:GetUnit(1):GetDesc().speedMax
local FromWaypoint = {}
FromWaypoint.x = GroupPoint.x
FromWaypoint.y = GroupPoint.y
FromWaypoint.type = "Turning Point"
FromWaypoint.action = "Turning Point"
FromWaypoint.speed = GroupVelocity
Points[#Points+1] = FromWaypoint
end
local AirbasePointVec2 = Airbase:GetPointVec2()
local ToWaypoint = AirbasePointVec2:WaypointAir(
POINT_VEC3.RoutePointAltType.BARO,
"Land",
"Landing",
Speed or Airplane:GetUnit(1):GetDesc().speedMax
)
ToWaypoint["airdromeId"] = Airbase:GetID()
ToWaypoint["speed_locked"] = true,
self:F( ToWaypoint )
Points[#Points+1] = ToWaypoint
Template.x = PointVec3.x
Template.y = PointVec3.z
self:T3( Points )
Template.route.points = Points
--self:Respawn( Template )
local GroupSpawned = Airplane:Respawn( Template )
return GroupSpawned
end
end
end

View File

@@ -0,0 +1,477 @@
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Dispatcher
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
--- @type AI_CARGO_DISPATCHER
-- @extends Core.Fsm#FSM
--- A dynamic cargo handling capability for AI groups.
--
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER module uses the @{Cargo} capabilities within the MOOSE framework, to enable Carrier GROUP objects
-- to transport @{Cargo} towards several deploy zones.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- ## 1. AI\_CARGO\_DISPATCHER constructor
--
-- * @{#AI_CARGO_DISPATCHER.New}(): Creates a new AI\_CARGO\_DISPATCHER object.
--
-- ## 2. AI\_CARGO\_DISPATCHER is a FSM
--
-- ![Process](..\Presentations\AI_PATROL\Dia2.JPG)
--
-- ### 2.1. AI\_CARGO\_DISPATCHER States
--
-- * **Monitoring**: The process is dispatching.
-- * **Idle**: The process is idle.
--
-- ### 2.2. AI\_CARGO\_DISPATCHER Events
--
-- * **Monitor**: Monitor and take action.
-- * **Start**: Start the transport process.
-- * **Stop**: Stop the transport process.
-- * **Pickup**: Pickup cargo.
-- * **Load**: Load the cargo.
-- * **Loaded**: Flag that the cargo is loaded.
-- * **Deploy**: Deploy cargo to a location.
-- * **Unload**: Unload the cargo.
-- * **Unloaded**: Flag that the cargo is unloaded.
-- * **Home**: A Carrier is going home.
--
-- ## 3. Set the pickup parameters.
--
-- Several parameters can be set to pickup cargo:
--
-- * @{#AI_CARGO_DISPATCHER.SetPickupRadius}(): Sets or randomizes the pickup location for the carrier around the cargo coordinate in a radius defined an outer and optional inner radius.
-- * @{#AI_CARGO_DISPATCHER.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
--
-- ## 4. Set the deploy parameters.
--
-- Several parameters can be set to deploy cargo:
--
-- * @{#AI_CARGO_DISPATCHER.SetDeployRadius}(): Sets or randomizes the deploy location for the carrier around the cargo coordinate in a radius defined an outer and an optional inner radius.
-- * @{#AI_CARGO_DISPATCHER.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
--
-- ## 5. Set the home zone when there isn't any more cargo to pickup.
--
-- A home zone can be specified to where the Carriers will move when there isn't any cargo left for pickup.
-- Use @{#AI_CARGO_DISPATCHER.SetHomeZone}() to specify the home zone.
--
-- If no home zone is specified, the carriers will wait near the deploy zone for a new pickup command.
--
-- ===
--
-- @field #AI_CARGO_DISPATCHER
AI_CARGO_DISPATCHER = {
ClassName = "AI_CARGO_DISPATCHER",
SetCarrier = nil,
SetDeployZones = nil,
AI_Cargo = {},
PickupCargo = {}
}
--- @field #AI_CARGO_DISPATCHER.AI_Cargo
AI_CARGO_DISPATCHER.AI_Cargo = {}
--- @field #AI_CARGO_DISPATCHER.PickupCargo
AI_CARGO_DISPATCHER.PickupCargo = {}
--- Creates a new AI_CARGO_DISPATCHER object.
-- @param #AI_CARGO_DISPATCHER self
-- @param Core.Set#SET_GROUP SetCarrier
-- @param Core.Set#SET_CARGO SetCargo
-- @param Core.Set#SET_ZONE SetDeployZone
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- SetCarrier = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
function AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZones )
local self = BASE:Inherit( self, FSM:New() ) -- #AI_CARGO_DISPATCHER
self.SetCarrier = SetCarrier -- Core.Set#SET_GROUP
self.SetCargo = SetCargo -- Core.Set#SET_CARGO
self.SetDeployZones = SetDeployZones -- Core.Set#SET_ZONE
self:SetStartState( "Idle" )
self:AddTransition( "Monitoring", "Monitor", "Monitoring" )
self:AddTransition( "Idle", "Start", "Monitoring" )
self:AddTransition( "Monitoring", "Stop", "Idle" )
self:AddTransition( "*", "Pickup", "*" )
self:AddTransition( "*", "Loading", "*" )
self:AddTransition( "*", "Loaded", "*" )
self:AddTransition( "*", "Deploy", "*" )
self:AddTransition( "*", "Unloading", "*" )
self:AddTransition( "*", "Unloaded", "*" )
self:AddTransition( "*", "Home", "*" )
self.MonitorTimeInterval = 30
self.DeployRadiusInner = 200
self.DeployRadiusOuter = 500
self.PickupCargo = {}
self.CarrierHome = {}
-- Put a Dead event handler on SetCarrier, to ensure that when a carrier is destroyed, that all internal parameters are reset.
function SetCarrier.OnAfterRemoved( SetCarrier, From, Event, To, CarrierName, Carrier )
self:F( { Carrier = Carrier:GetName() } )
self.PickupCargo[Carrier] = nil
self.CarrierHome[Carrier] = nil
end
return self
end
--- Set the home zone.
-- When there is nothing anymore to pickup, the carriers will go to a random coordinate in this zone.
-- They will await here new orders.
-- @param #AI_CARGO_DISPATCHER self
-- @param Core.Zone#ZONE_BASE HomeZone
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
-- -- Set the home coordinate
-- local HomeZone = ZONE:New( "Home" )
-- AICargoDispatcher:SetHomeZone( HomeZone )
--
function AI_CARGO_DISPATCHER:SetHomeZone( HomeZone )
self.HomeZone = HomeZone
return self
end
--- Sets or randomizes the pickup location for the carrier around the cargo coordinate in a radius defined an outer and optional inner radius.
-- This radius is influencing the location where the carrier will land to pickup the cargo.
-- There are two aspects that are very important to remember and take into account:
--
-- - Ensure that the outer and inner radius are within reporting radius set by the cargo.
-- For example, if the cargo has a reporting radius of 400 meters, and the outer and inner radius is set to 500 and 450 respectively,
-- then no cargo will be loaded!!!
-- - Also take care of the potential cargo position and possible reasons to crash the carrier. This is especially important
-- for locations which are crowded with other objects, like in the middle of villages or cities.
-- So, for the best operation of cargo operations, always ensure that the cargo is located at open spaces.
--
-- The default radius is 0, so the center. In case of a polygon zone, a random location will be selected as the center in the zone.
-- @param #AI_CARGO_DISPATCHER self
-- @param #number OuterRadius The outer radius in meters around the cargo coordinate.
-- @param #number InnerRadius (optional) The inner radius in meters around the cargo coordinate.
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
-- -- Set the carrier to land within a band around the cargo coordinate between 500 and 300 meters!
-- AICargoDispatcher:SetPickupRadius( 500, 300 )
--
function AI_CARGO_DISPATCHER:SetPickupRadius( OuterRadius, InnerRadius )
OuterRadius = OuterRadius or 0
InnerRadius = InnerRadius or OuterRadius
self.PickupOuterRadius = OuterRadius
self.PickupInnerRadius = InnerRadius
return self
end
--- Set the speed or randomizes the speed in km/h to pickup the cargo.
-- @param #AI_CARGO_DISPATCHER self
-- @param #number MaxSpeed (optional) The maximum speed to move to the cargo pickup location.
-- @param #number MinSpeed The minimum speed to move to the cargo pickup location.
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
-- -- Set the minimum pickup speed to be 100 km/h and the maximum speed to be 200 km/h.
-- AICargoDispatcher:SetPickupSpeed( 200, 100 )
--
function AI_CARGO_DISPATCHER:SetPickupSpeed( MaxSpeed, MinSpeed )
MaxSpeed = MaxSpeed or 999
MinSpeed = MinSpeed or MaxSpeed
self.PickupMinSpeed = MinSpeed
self.PickupMaxSpeed = MaxSpeed
return self
end
--- Sets or randomizes the deploy location for the carrier around the cargo coordinate in a radius defined an outer and an optional inner radius.
-- This radius is influencing the location where the carrier will land to deploy the cargo.
-- There is an aspect that is very important to remember and take into account:
--
-- - Take care of the potential cargo position and possible reasons to crash the carrier. This is especially important
-- for locations which are crowded with other objects, like in the middle of villages or cities.
-- So, for the best operation of cargo operations, always ensure that the cargo is located at open spaces.
--
-- The default radius is 0, so the center. In case of a polygon zone, a random location will be selected as the center in the zone.
-- @param #AI_CARGO_DISPATCHER self
-- @param #number OuterRadius The outer radius in meters around the cargo coordinate.
-- @param #number InnerRadius (optional) The inner radius in meters around the cargo coordinate.
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
-- -- Set the carrier to land within a band around the cargo coordinate between 500 and 300 meters!
-- AICargoDispatcher:SetDeployRadius( 500, 300 )
--
function AI_CARGO_DISPATCHER:SetDeployRadius( OuterRadius, InnerRadius )
OuterRadius = OuterRadius or 0
InnerRadius = InnerRadius or OuterRadius
self.DeployOuterRadius = OuterRadius
self.DeployInnerRadius = InnerRadius
return self
end
--- Sets or randomizes the speed in km/h to deploy the cargo.
-- @param #AI_CARGO_DISPATCHER self
-- @param #number MaxSpeed The maximum speed to move to the cargo deploy location.
-- @param #number MinSpeed (optional) The minimum speed to move to the cargo deploy location.
-- @return #AI_CARGO_DISPATCHER
-- @usage
--
-- -- Create a new cargo dispatcher
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
--
-- -- Set the minimum deploy speed to be 100 km/h and the maximum speed to be 200 km/h.
-- AICargoDispatcher:SetDeploySpeed( 200, 100 )
--
function AI_CARGO_DISPATCHER:SetDeploySpeed( MaxSpeed, MinSpeed )
MaxSpeed = MaxSpeed or 999
MinSpeed = MinSpeed or MaxSpeed
self.DeployMinSpeed = MinSpeed
self.DeployMaxSpeed = MaxSpeed
return self
end
--- The Start trigger event, which actually takes action at the specified time interval.
-- @param #AI_CARGO_DISPATCHER self
function AI_CARGO_DISPATCHER:onafterMonitor()
for CarrierGroupName, Carrier in pairs( self.SetCarrier:GetSet() ) do
local Carrier = Carrier -- Wrapper.Group#GROUP
local AI_Cargo = self.AI_Cargo[Carrier]
if not AI_Cargo then
-- ok, so this Carrier does not have yet an AI_CARGO handling object...
-- let's create one and also declare the Loaded and UnLoaded handlers.
self.AI_Cargo[Carrier] = self:AICargo( Carrier, self.SetCargo, self.CombatRadius )
AI_Cargo = self.AI_Cargo[Carrier]
function AI_Cargo.OnAfterPickup( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Pickup( Carrier, Cargo )
end
function AI_Cargo.OnAfterLoad( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Loading( Carrier )
end
function AI_Cargo.OnAfterLoaded( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Loaded( Carrier, Cargo )
end
function AI_Cargo.OnAfterDeploy( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Deploy( Carrier, Cargo )
end
function AI_Cargo.OnAfterUnload( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Unloading( Carrier, Cargo )
end
function AI_Cargo.OnAfterUnloaded( AI_Cargo, Carrier, From, Event, To, Cargo )
self:Unloaded( Carrier, Cargo )
end
end
-- The Pickup sequence ...
-- Check if this Carrier need to go and Pickup something...
self:I( { IsTransporting = AI_Cargo:IsTransporting() } )
if AI_Cargo:IsTransporting() == false then
-- ok, so there is a free Carrier
-- now find the first cargo that is Unloaded
local PickupCargo = nil
for CargoName, Cargo in pairs( self.SetCargo:GetSet() ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { Cargo = Cargo:GetName(), UnLoaded = Cargo:IsUnLoaded(), Deployed = Cargo:IsDeployed(), PickupCargo = self.PickupCargo[Carrier] ~= nil } )
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
local CargoCoordinate = Cargo:GetCoordinate()
local CoordinateFree = true
for CarrierPickup, Coordinate in pairs( self.PickupCargo ) do
if CarrierPickup:IsAlive() == true then
if CargoCoordinate:Get2DDistance( Coordinate ) <= 25 then
CoordinateFree = false
break
end
else
self.PickupCargo[CarrierPickup] = nil
end
end
if CoordinateFree == true then
self.PickupCargo[Carrier] = CargoCoordinate
PickupCargo = Cargo
break
end
end
end
if PickupCargo then
self.CarrierHome[Carrier] = nil
local PickupCoordinate = PickupCargo:GetCoordinate():GetRandomCoordinateInRadius( self.PickupOuterRadius, self.PickupInnerRadius )
AI_Cargo:Pickup( PickupCoordinate, math.random( self.PickupMinSpeed, self.PickupMaxSpeed ) )
break
else
if self.HomeZone then
if not self.CarrierHome[Carrier] then
self.CarrierHome[Carrier] = true
AI_Cargo:__Home( 60, self.HomeZone:GetRandomPointVec2() )
end
end
end
end
end
self:__Monitor( self.MonitorTimeInterval )
end
--- Start Handler OnBefore for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnBeforeStart
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Start Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterStart
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Start Trigger for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] Start
-- @param #AI_CARGO_DISPATCHER self
--- Start Asynchronous Trigger for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] __Start
-- @param #AI_CARGO_DISPATCHER self
-- @param #number Delay
function AI_CARGO_DISPATCHER:onafterStart( From, Event, To )
self:__Monitor( -1 )
end
--- Stop Handler OnBefore for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnBeforeStop
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Stop Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterStop
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Stop Trigger for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] Stop
-- @param #AI_CARGO_DISPATCHER self
--- Stop Asynchronous Trigger for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] __Stop
-- @param #AI_CARGO_DISPATCHER self
-- @param #number Delay
--- Loaded Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterLoaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Group#GROUP Carrier
-- @param Cargo.Cargo#CARGO Cargo
--- Unloaded Handler OnAfter for AI_CARGO_DISPATCHER
-- @function [parent=#AI_CARGO_DISPATCHER] OnAfterUnloaded
-- @param #AI_CARGO_DISPATCHER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Group#GROUP Carrier
-- @param Cargo.Cargo#CARGO Cargo
--- Make a Carrier run for a cargo deploy action after the cargo has been loaded, by default.
-- @param #AI_CARGO_DISPATCHER self
-- @param From
-- @param Event
-- @param To
-- @param Wrapper.Group#GROUP Carrier
-- @param Cargo.Cargo#CARGO Cargo
-- @return #AI_CARGO_DISPATCHER
function AI_CARGO_DISPATCHER:OnAfterLoaded( From, Event, To, Carrier, Cargo )
local DeployZone = self.SetDeployZones:GetRandomZone()
local DeployCoordinate = DeployZone:GetCoordinate():GetRandomCoordinateInRadius( self.DeployOuterRadius, self.DeployInnerRadius )
self.AI_Cargo[Carrier]:Deploy( DeployCoordinate, math.random( self.DeployMinSpeed, self.DeployMaxSpeed ) )
self.PickupCargo[Carrier] = nil
end

View File

@@ -0,0 +1,122 @@
--- **AI** -- Models the intelligent transportation of infantry and other cargo using APCs.
--
-- **Features:**
--
-- * Quickly transport cargo to various deploy zones using ground vehicles (APCs, trucks ...).
-- * Various @{Cargo.Cargo#CARGO} types can be transported. These are infantry groups and crates.
-- * Define a list of deploy zones of various types to transport the cargo to.
-- * The vehicles follow the roads to ensure the fastest possible cargo transportation over the ground.
-- * Multiple vehicles can transport multiple cargo as one vehicle group.
-- * Multiple vehicle groups can be enabled as one collaborating transportation process.
-- * Infantry loaded as cargo, will unboard in case enemies are nearby and will help defending the vehicles.
-- * Different ranges can be setup for enemy defenses.
-- * Different options can be setup to tweak the cargo transporation behaviour.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Dispatcher_APC
-- @image AI_Cargo_Dispatching_For_APC.JPG
--- @type AI_CARGO_DISPATCHER_APC
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
--- A dynamic cargo transportation capability for AI groups.
--
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER\_APC module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_APC object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- ## 1. AI\_CARGO\_DISPATCHER\_APC constructor
--
-- * @{#AI_CARGO_DISPATCHER\_APC.New}(): Creates a new AI\_CARGO\_DISPATCHER\_APC object.
--
-- ## 2. AI\_CARGO\_DISPATCHER\_APC is a FSM
--
-- ![Process](..\Presentations\AI_CARGO_DISPATCHER_APC\Dia3.JPG)
--
-- ### 2.1. AI\_CARGO\_DISPATCHER\_APC States
--
-- * **Monitoring**: The process is dispatching.
-- * **Idle**: The process is idle.
--
-- ### 2.2. AI\_CARGO\_DISPATCHER\_APC Events
--
-- * **Monitor**: Monitor and take action.
-- * **Start**: Start the transport process.
-- * **Stop**: Stop the transport process.
-- * **Pickup**: Pickup cargo.
-- * **Load**: Load the cargo.
-- * **Loaded**: Flag that the cargo is loaded.
-- * **Deploy**: Deploy cargo to a location.
-- * **Unload**: Unload the cargo.
-- * **Unloaded**: Flag that the cargo is unloaded.
-- * **Home**: A APC is going home.
--
-- ## 3. Set the pickup parameters.
--
-- Several parameters can be set to pickup cargo:
--
-- * @{#AI_CARGO_DISPATCHER\_APC.SetPickupRadius}(): Sets or randomizes the pickup location for the APC around the cargo coordinate in a radius defined an outer and optional inner radius.
-- * @{#AI_CARGO_DISPATCHER\_APC.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
--
-- ## 4. Set the deploy parameters.
--
-- Several parameters can be set to deploy cargo:
--
-- * @{#AI_CARGO_DISPATCHER\_APC.SetDeployRadius}(): Sets or randomizes the deploy location for the APC around the cargo coordinate in a radius defined an outer and an optional inner radius.
-- * @{#AI_CARGO_DISPATCHER\_APC.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
--
-- ## 5. Set the home zone when there isn't any more cargo to pickup.
--
-- A home zone can be specified to where the APCs will move when there isn't any cargo left for pickup.
-- Use @{#AI_CARGO_DISPATCHER\_APC.SetHomeZone}() to specify the home zone.
--
-- If no home zone is specified, the APCs will wait near the deploy zone for a new pickup command.
--
-- ===
--
-- @field #AI_CARGO_DISPATCHER_APC
AI_CARGO_DISPATCHER_APC = {
ClassName = "AI_CARGO_DISPATCHER_APC",
}
--- Creates a new AI_CARGO_DISPATCHER_APC object.
-- @param #AI_CARGO_DISPATCHER_APC self
-- @param Core.Set#SET_GROUP SetAPC The collection of APC @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO SetCargo The collection of @{Cargo} derived objects.
-- @param Core.Set#SET_ZONE SetDeployZone The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the APCs.
-- @param DCS#Distance CombatRadius The cargo will be unloaded from the APC and engage the enemy if the enemy is within CombatRadius range. The radius is in meters, the default value is 500 meters.
-- @return #AI_CARGO_DISPATCHER_APC
-- @usage
--
-- -- Create a new cargo dispatcher for the set of APCs, with a combatradius of 500.
-- SetAPC = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, 500 )
--
function AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZone, CombatRadius )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAPC, SetCargo, SetDeployZone ) ) -- #AI_CARGO_DISPATCHER_APC
self.CombatRadius = CombatRadius or 500
self:SetDeploySpeed( 70, 120 )
self:SetPickupSpeed( 70, 120 )
self:SetPickupRadius( 0, 0 )
self:SetDeployRadius( 0, 0 )
return self
end
function AI_CARGO_DISPATCHER_APC:AICargo( APC, SetCargo )
return AI_CARGO_APC:New( APC, SetCargo, self.CombatRadius )
end

View File

@@ -0,0 +1,51 @@
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using Planes.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Dispatcher_Airplane
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
--
--- @type AI_CARGO_DISPATCHER_AIRPLANE
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
--- Brings a dynamic cargo handling capability for AI groups.
--
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER\_AIRPLANE module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_AIRPLANE object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
--
--
-- @field #AI_CARGO_DISPATCHER_AIRPLANE
AI_CARGO_DISPATCHER_AIRPLANE = {
ClassName = "AI_CARGO_DISPATCHER_AIRPLANE",
}
--- Creates a new AI_CARGO_DISPATCHER_AIRPLANE object.
-- @param #AI_CARGO_DISPATCHER_AIRPLANE self
-- @param Core.Set#SET_GROUP SetAirplane
-- @param Core.Set#SET_CARGO SetCargo
-- @param Core.Set#SET_ZONE SetDeployZone
-- @return #AI_CARGO_DISPATCHER_AIRPLANE
-- @usage
--
-- -- Create a new cargo dispatcher
-- SetAirplane = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo )
--
function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo, SetDeployZones )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAirplane, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
return self
end

View File

@@ -0,0 +1,119 @@
--- **AI** -- Models the intelligent transportation of infantry and other cargo using Helicopters.
--
-- The @{#AI_CARGO_DISPATCHER_HELICOPTER} classes implements the dynamic dispatching of cargo transportation tasks for helicopters.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Dispatcher_Helicopter
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
--- @type AI_CARGO_DISPATCHER_HELICOPTER
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
--- A dynamic cargo handling capability for AI helicopter groups.
--
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
-- The AI\_CARGO\_DISPATCHER\_HELICOPTER module uses the @{Cargo} capabilities within the MOOSE framework.
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_HELICOPTER object recognize the cargo.
-- Please consult the @{Cargo} module for more information.
--
-- ---
--
-- ## 1. AI\_CARGO\_DISPATCHER\_HELICOPTER constructor
--
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.New}(): Creates a new AI\_CARGO\_DISPATCHER\_HELICOPTER object.
--
-- ---
--
-- ## 2. AI\_CARGO\_DISPATCHER\_HELICOPTER is a FSM
--
-- ![Process](..\Presentations\AI_CARGO_DISPATCHER_HELICOPTER\Dia3.JPG)
--
-- ### 2.1. AI\_CARGO\_DISPATCHER\_HELICOPTER States
--
-- * **Monitoring**: The process is dispatching.
-- * **Idle**: The process is idle.
--
-- ### 2.2. AI\_CARGO\_DISPATCHER\_HELICOPTER Events
--
-- * **Monitor**: Monitor and take action.
-- * **Start**: Start the transport process.
-- * **Stop**: Stop the transport process.
-- * **Pickup**: Pickup cargo.
-- * **Load**: Load the cargo.
-- * **Loaded**: Flag that the cargo is loaded.
-- * **Deploy**: Deploy cargo to a location.
-- * **Unload**: Unload the cargo.
-- * **Unloaded**: Flag that the cargo is unloaded.
-- * **Home**: A Helicopter is going home.
--
-- ---
--
-- ## 3. Set the pickup parameters.
--
-- Several parameters can be set to pickup cargo:
--
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.SetPickupRadius}(): Sets or randomizes the pickup location for the helicopter around the cargo coordinate in a radius defined an outer and optional inner radius.
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
--
-- ---
--
-- ## 4. Set the deploy parameters.
--
-- Several parameters can be set to deploy cargo:
--
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.SetDeployRadius}(): Sets or randomizes the deploy location for the helicopter around the cargo coordinate in a radius defined an outer and an optional inner radius.
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
--
-- ---
--
-- ## 5. Set the home zone when there isn't any more cargo to pickup.
--
-- A home zone can be specified to where the Helicopters will move when there isn't any cargo left for pickup.
-- Use @{#AI_CARGO_DISPATCHER\_HELICOPTER.SetHomeZone}() to specify the home zone.
--
-- If no home zone is specified, the helicopters will wait near the deploy zone for a new pickup command.
--
-- ===
--
-- @field #AI_CARGO_DISPATCHER_HELICOPTER
AI_CARGO_DISPATCHER_HELICOPTER = {
ClassName = "AI_CARGO_DISPATCHER_HELICOPTER",
}
--- Creates a new AI_CARGO_DISPATCHER_HELICOPTER object.
-- @param #AI_CARGO_DISPATCHER_HELICOPTER self
-- @param Core.Set#SET_GROUP SetHelicopter The collection of Helicopter @{Wrapper.Group}s.
-- @param Core.Set#SET_CARGO SetCargo The collection of @{Cargo} derived objects.
-- @param Core.Set#SET_ZONE SetDeployZone The collection of deploy @{Zone}s, which are used to where the cargo will be deployed by the Helicopters.
-- @return #AI_CARGO_DISPATCHER_HELICOPTER
-- @usage
--
-- -- Create a new cargo dispatcher
-- SetHelicopter = SET_GROUP:New():FilterPrefixes( "Helicopter" ):FilterStart()
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo )
--
function AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo, SetDeployZones )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetHelicopter, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
self:SetDeploySpeed( 200, 150 )
self:SetPickupSpeed( 200, 150 )
self:SetPickupRadius( 0, 0 )
self:SetDeployRadius( 0, 0 )
return self
end
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, SetCargo )
return AI_CARGO_HELICOPTER:New( Helicopter, SetCargo )
end

View File

@@ -0,0 +1,717 @@
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ===
--
-- @module AI.AI_Cargo_Helicopter
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
--- @type AI_CARGO_HELICOPTER
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- # AI\_CARGO\_TROOPS class, extends @{Core.Fsm#FSM_CONTROLLABLE}
--
-- ===
--
-- @field #AI_CARGO_HELICOPTER
AI_CARGO_HELICOPTER = {
ClassName = "AI_CARGO_HELICOPTER",
Coordinate = nil -- Core.Point#COORDINATE,
}
AI_CARGO_QUEUE = {}
--- Creates a new AI_CARGO_HELICOPTER object.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param Core.Set#SET_CARGO CargoSet
-- @param #number CombatRadius
-- @return #AI_CARGO_HELICOPTER
function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_HELICOPTER
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "Unloaded", "Load", "Boarding" )
self:AddTransition( "Boarding", "Board", "Boarding" )
self:AddTransition( "Boarding", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "Unload", "Unboarding" )
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
self:AddTransition( "*", "Landed", "*" )
self:AddTransition( "*", "Queue", "*" )
self:AddTransition( "*", "Orbit" , "*" )
self:AddTransition( "*", "Home" , "*" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
-- @param #AI_CARGO_HELICOPTER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean
--- Pickup Handler OnAfter for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] OnAfterPickup
-- @param #AI_CARGO_HELICOPTER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
--- Pickup Trigger for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] Pickup
-- @param #AI_CARGO_HELICOPTER self
-- @param Core.Point#COORDINATE Coordinate
--- Pickup Asynchronous Trigger for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] __Pickup
-- @param #AI_CARGO_HELICOPTER self
-- @param #number Delay
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Handler OnBefore for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforeDeploy
-- @param #AI_CARGO_HELICOPTER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean
--- Deploy Handler OnAfter for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] OnAfterDeploy
-- @param #AI_CARGO_HELICOPTER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Trigger for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] Deploy
-- @param #AI_CARGO_HELICOPTER self
-- @param Core.Point#COORDINATE Coordinate
--- Deploy Asynchronous Trigger for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] __Deploy
-- @param #AI_CARGO_HELICOPTER self
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Delay
-- We need to capture the Crash events for the helicopters.
-- The helicopter reference is used in the semaphore AI_CARGO_QUEUE.
-- So, we need to unlock this when the helo is not anymore ...
Helicopter:HandleEvent( EVENTS.Crash,
function( Helicopter, EventData )
AI_CARGO_QUEUE[Helicopter] = nil
end
)
-- We need to capture the Land events for the helicopters.
-- The helicopter reference is used in the semaphore AI_CARGO_QUEUE.
-- So, we need to unlock this when the helo has landed, which can be anywhere ...
-- But only free the landing coordinate after 1 minute, to ensure that all helos have left.
Helicopter:HandleEvent( EVENTS.Land,
function( Helicopter, EventData )
self:ScheduleOnce( 60,
function( Helicopter )
AI_CARGO_QUEUE[Helicopter] = nil
end, Helicopter
)
end
)
self:SetCarrier( Helicopter )
return self
end
function AI_CARGO_HELICOPTER:IsTransporting()
return self.Transporting == true
end
function AI_CARGO_HELICOPTER:IsRelocating()
return self.Relocating == true
end
--- Set the Carrier.
-- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @return #AI_CARGO_HELICOPTER
function AI_CARGO_HELICOPTER:SetCarrier( Helicopter )
local AICargo = self
self.Helicopter = Helicopter -- Wrapper.Group#GROUP
self.Helicopter:SetState( self.Helicopter, "AI_CARGO_HELICOPTER", self )
self.RoutePickup = false
self.RouteDeploy = false
Helicopter:HandleEvent( EVENTS.Dead )
Helicopter:HandleEvent( EVENTS.Hit )
Helicopter:HandleEvent( EVENTS.Land )
function Helicopter:OnEventDead( EventData )
local AICargoTroops = self:GetState( self, "AI_CARGO_HELICOPTER" )
self:F({AICargoTroops=AICargoTroops})
if AICargoTroops then
self:F({})
if not AICargoTroops:Is( "Loaded" ) then
-- There are enemies within combat range. Unload the Helicopter.
AICargoTroops:Destroyed()
end
end
end
function Helicopter:OnEventLand( EventData )
AICargo:Landed()
end
self.Coalition = self.Helicopter:GetCoalition()
self:SetControllable( Helicopter )
return self
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
Helicopter:F( { Name = Helicopter:GetName() } )
if Helicopter and Helicopter:IsAlive() then
-- S_EVENT_LAND is directly called in two situations:
-- 1 - When the helo lands normally on the ground.
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
-- For point 2, this is an issue, the infantry may not unload in this case!
-- So we check if the helo is on the ground, and velocity< 5.
-- Only then the infantry can unload (and load too, for consistency)!
self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
if self.RoutePickup == true then
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
self:Load( Helicopter:GetPointVec2() )
self.RoutePickup = false
self.Relocating = true
end
end
if self.RouteDeploy == true then
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
self:Unload( true )
self.RouteDeploy = false
self.Transporting = false
self.Relocating = false
end
end
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate )
local HelicopterInZone = false
if Helicopter and Helicopter:IsAlive() == true then
local Distance = Coordinate:DistanceFromPointVec2( Helicopter:GetCoordinate() )
if Distance > 2000 then
self:__Queue( -10, Coordinate )
else
local ZoneFree = true
for Helicopter, ZoneQueue in pairs( AI_CARGO_QUEUE ) do
local ZoneQueue = ZoneQueue -- Core.Zone#ZONE_RADIUS
if ZoneQueue:IsCoordinateInZone( Coordinate ) then
ZoneFree = false
end
end
self:F({ZoneFree=ZoneFree})
if ZoneFree == true then
local ZoneQueue = ZONE_RADIUS:New( Helicopter:GetName(), Coordinate:GetVec2(), 100 )
AI_CARGO_QUEUE[Helicopter] = ZoneQueue
local Route = {}
-- local CoordinateFrom = Helicopter:GetCoordinate()
-- local WaypointFrom = CoordinateFrom:WaypointAir(
-- "RADIO",
-- POINT_VEC3.RoutePointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint,
-- Speed,
-- true
-- )
-- Route[#Route+1] = WaypointFrom
local CoordinateTo = Coordinate
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
50,
true
)
Route[#Route+1] = WaypointTo
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
Helicopter:Route( Route, 0 )
else
self:__Queue( -10, Coordinate )
end
end
else
AI_CARGO_QUEUE[Helicopter] = nil
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordinate )
if Helicopter and Helicopter:IsAlive() then
if not self:IsTransporting() then
local Route = {}
-- local CoordinateFrom = Helicopter:GetCoordinate()
-- local WaypointFrom = CoordinateFrom:WaypointAir(
-- "RADIO",
-- POINT_VEC3.RoutePointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint,
-- Speed,
-- true
-- )
-- Route[#Route+1] = WaypointFrom
local CoordinateTo = Coordinate
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
50,
true
)
Route[#Route+1] = WaypointTo
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 80 ), 150, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
Helicopter:Route( Route, 0 )
end
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onbeforeLoad( Helicopter, From, Event, To, Coordinate )
local Boarding = false
if Helicopter and Helicopter:IsAlive() then
self.BoardingCount = 0
if Helicopter and Helicopter:IsAlive() then
self.Helicopter_Cargo = {}
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsUnLoaded = Cargo:IsUnLoaded() } )
if Cargo:IsUnLoaded() then
if Cargo:IsInLoadRadius( HelicopterUnit:GetCoordinate() ) then
self:F( { "In radius", HelicopterUnit:GetName() } )
--Cargo:Ungroup()
Cargo:Board( HelicopterUnit, 25 )
self:__Board( 1, Cargo )
Boarding = true
-- So now this APCUnit has Cargo that is being loaded.
-- This will be used further in the logic to follow and to check cargo status.
self.Helicopter_Cargo[HelicopterUnit] = Cargo
break
end
end
end
end
end
end
return Boarding
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onafterBoard( Helicopter, From, Event, To, Cargo )
self:F( { APC, From, Event, To, Cargo } )
if Helicopter and Helicopter:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded() } )
if not Cargo:IsLoaded() then
self:__Board( 10, Cargo )
else
self:__Loaded( 1, Cargo )
end
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onbeforeLoaded( Helicopter, From, Event, To, Cargo )
self:F( { APC, From, Event, To } )
local Loaded = true
if Helicopter and Helicopter:IsAlive() then
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed() } )
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
Loaded = false
end
end
end
return Loaded
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onafterUnload( Helicopter, From, Event, To, Deployed )
if Helicopter and Helicopter:IsAlive() then
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
for _, Cargo in pairs( HelicopterUnit:GetCargo() ) do
Cargo:UnBoard()
Cargo:SetDeployed( true )
self:__Unboard( 10, Cargo, Deployed )
end
end
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onafterUnboard( Helicopter, From, Event, To, Cargo, Deployed )
if Helicopter and Helicopter:IsAlive() then
if not Cargo:IsUnLoaded() then
self:__Unboard( 10, Cargo, Deployed )
else
self:__Unloaded( 1, Cargo, Deployed )
end
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onbeforeUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
local AllUnloaded = true
--Cargo:Regroup()
if Helicopter and Helicopter:IsAlive() then
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local CargoCheck = self.Helicopter_Cargo[HelicopterUnit] -- Cargo.Cargo#CARGO
if CargoCheck then
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
if CargoCheck:IsUnLoaded() == false then
AllUnloaded = false
break
end
end
end
if AllUnloaded == true then
if Deployed == true then
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
end
self.Helicopter_Cargo = {}
end
self.Helicopter = Helicopter
end
end
self:F( { AllUnloaded = AllUnloaded } )
return AllUnloaded
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
self:Orbit( Helicopter:GetCoordinate(), 50 )
-- Free the coordinate zone after 30 seconds, so that the original helicopter can fly away first.
self:ScheduleOnce( 30,
function( Helicopter )
AI_CARGO_QUEUE[Helicopter] = nil
end, Helicopter
)
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate )
if Helicopter and Helicopter:IsAlive() ~= nil then
Helicopter:Activate()
self.RoutePickup = true
Coordinate.y = math.random( 50, 200 )
local Route = {}
--- Calculate the target route point.
local CoordinateFrom = Helicopter:GetCoordinate()
local CoordinateTo = Coordinate
--- Create a route point of type air.
local WaypointFrom = CoordinateFrom:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
--- Create a route point of type air.
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointTo
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
Helicopter:WayPointInitialize( Route )
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
Helicopter:Route( Route, 1 )
self.Transporting = true
end
end
function AI_CARGO_HELICOPTER:_Deploy( AICargoHelicopter, Coordinate )
AICargoHelicopter:__Queue( -10, Coordinate, 100 )
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate )
if Helicopter and Helicopter:IsAlive() ~= nil then
self.RouteDeploy = true
local Route = {}
--- Calculate the target route point.
Coordinate.y = math.random( 50, 200 )
--- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointFrom
--- Create a route point of type air.
local CoordinateTo = Coordinate
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
Route[#Route+1] = WaypointTo
Route[#Route+1] = WaypointTo
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
Helicopter:WayPointInitialize( Route )
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskFunction( "AI_CARGO_HELICOPTER._Deploy", self, Coordinate )
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 100 ), 150, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
--Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
Helicopter:Route( Route, 0 )
end
end
--- @param #AI_CARGO_HELICOPTER self
-- @param Wrapper.Group#GROUP Helicopter
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#COORDINATE Coordinate
-- @param #number Speed
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate )
if Helicopter and Helicopter:IsAlive() ~= nil then
self.RouteHome = true
local Route = {}
--- Calculate the target route point.
Coordinate.y = math.random( 50, 200 )
--- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
Route[#Route+1] = WaypointFrom
--- Create a route point of type air.
local CoordinateTo = Coordinate
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
150,
true
)
Route[#Route+1] = WaypointTo
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
Helicopter:WayPointInitialize( Route )
local Tasks = {}
Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
Route[#Route].task = Helicopter:TaskCombo( Tasks )
Route[#Route+1] = WaypointTo
-- Now route the helicopter
Helicopter:Route( Route, 0 )
end
end

View File

@@ -1,35 +1,11 @@
--- **AI** -- (R2.2) - Build large airborne formations of aircraft. --- **AI** -- Build large airborne formations of aircraft.
-- --
-- === -- **Features:**
--
-- * Build in-air formations consisting of more than 40 aircraft as one group.
-- * Build different formation types.
-- * Assign a group leader that will guide the large formation path.
-- --
-- ![Banner Image](..\Presentations\AI_FORMATION\Dia1.JPG)
--
-- ===
--
-- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions.
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
-- The purpose of the class is to:
--
-- * Make formation building a process that can be managed while in flight, rather than a task.
-- * Human players can guide formations, consisting of larget planes.
-- * Build large formations (like a large bomber field).
-- * Form formations that DCS does not support off the shelve.
--
-- A few remarks:
--
-- * Depending on the type of plane, the change in direction by the leader may result in the formation getting disentangled while in flight and needs to be rebuild.
-- * Formations are vulnerable to collissions, but is depending on the type of plane, the distance between the planes and the speed and angle executed by the leader.
-- * Formations may take a while to build up.
--
-- As a result, the AI_FORMATION is not perfect, but is very useful to:
--
-- * Model large formations when flying straight line.
-- * Make humans guide a large formation, when the planes are wide from each other.
--
-- There are the following types of classes defined:
--
-- * @{#AI_FORMATION}: Create a formation from several @{GROUP}s.
--
-- === -- ===
-- --
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20Formation) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20Formation)
@@ -45,13 +21,14 @@
-- --
-- === -- ===
-- --
-- @module AI_Formation -- @module AI.AI_Formation
-- @image AI_Large_Formations.JPG
--- AI_FORMATION class --- AI_FORMATION class
-- @type AI_FORMATION -- @type AI_FORMATION
-- @extends Fsm#FSM_SET -- @extends Core.Fsm#FSM_SET
-- @field Unit#UNIT FollowUnit -- @field Wrapper.Unit#UNIT FollowUnit
-- @field Set#SET_GROUP FollowGroupSet -- @field Core.Set#SET_GROUP FollowGroupSet
-- @field #string FollowName -- @field #string FollowName
-- @field #AI_FORMATION.MODE FollowMode The mode the escort is in. -- @field #AI_FORMATION.MODE FollowMode The mode the escort is in.
-- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class. -- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
@@ -61,9 +38,7 @@
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup. -- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
--- # AI_FORMATION class, extends @{Fsm#FSM_SET} --- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
--
-- The #AI_FORMATION class allows you to build large formations, make AI follow a @{Client#CLIENT} (player) leader or a @{Unit#UNIT} (AI) leader.
-- --
-- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions. -- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions.
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!! -- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
@@ -89,25 +64,25 @@
-- --
-- Create a new SPAWN object with the @{#AI_FORMATION.New} method: -- Create a new SPAWN object with the @{#AI_FORMATION.New} method:
-- --
-- * @{Follow#AI_FORMATION.New}(): Creates a new AI_FORMATION object from a @{Group#GROUP} for a @{Client#CLIENT} or a @{Unit#UNIT}, with an optional briefing text. -- * @{#AI_FORMATION.New}(): Creates a new AI_FORMATION object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT} or a @{Wrapper.Unit#UNIT}, with an optional briefing text.
-- --
-- ## Formation methods -- ## Formation methods
-- --
-- The following methods can be used to set or change the formation: -- The following methods can be used to set or change the formation:
-- --
-- * @{AI_Formation#AI_FORMATION.FormationLine}(): Form a line formation (core formation function). -- * @{#AI_FORMATION.FormationLine}(): Form a line formation (core formation function).
-- * @{AI_Formation#AI_FORMATION.FormationTrail}(): Form a trail formation. -- * @{#AI_FORMATION.FormationTrail}(): Form a trail formation.
-- * @{AI_Formation#AI_FORMATION.FormationLeftLine}(): Form a left line formation. -- * @{#AI_FORMATION.FormationLeftLine}(): Form a left line formation.
-- * @{AI_Formation#AI_FORMATION.FormationRightLine}(): Form a right line formation. -- * @{#AI_FORMATION.FormationRightLine}(): Form a right line formation.
-- * @{AI_Formation#AI_FORMATION.FormationRightWing}(): Form a right wing formation. -- * @{#AI_FORMATION.FormationRightWing}(): Form a right wing formation.
-- * @{AI_Formation#AI_FORMATION.FormationLeftWing}(): Form a left wing formation. -- * @{#AI_FORMATION.FormationLeftWing}(): Form a left wing formation.
-- * @{AI_Formation#AI_FORMATION.FormationCenterWing}(): Form a center wing formation. -- * @{#AI_FORMATION.FormationCenterWing}(): Form a center wing formation.
-- * @{AI_Formation#AI_FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing. -- * @{#AI_FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing.
-- * @{AI_Formation#AI_FORMATION.FormationCenterBoxed}(): Form a center boxed formation. -- * @{#AI_FORMATION.FormationCenterBoxed}(): Form a center boxed formation.
-- --
-- ## Randomization -- ## Randomization
-- --
-- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters. -- Use the method @{AI.AI_Formation#AI_FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters.
-- --
-- @usage -- @usage
-- local FollowGroupSet = SET_GROUP:New():FilterCategories("plane"):FilterCoalitions("blue"):FilterPrefixes("Follow"):FilterStart() -- local FollowGroupSet = SET_GROUP:New():FilterCategories("plane"):FilterCoalitions("blue"):FilterPrefixes("Follow"):FilterStart()
@@ -147,7 +122,7 @@ AI_FORMATION = {
--- AI_FORMATION class constructor for an AI group --- AI_FORMATION class constructor for an AI group
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet. -- @param Wrapper.Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet.
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
-- @param #string FollowName Name of the escort. -- @param #string FollowName Name of the escort.
-- @return #AI_FORMATION self -- @return #AI_FORMATION self
@@ -155,8 +130,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
local self = BASE:Inherit( self, FSM_SET:New( FollowGroupSet ) ) local self = BASE:Inherit( self, FSM_SET:New( FollowGroupSet ) )
self:F( { FollowUnit, FollowGroupSet, FollowName } ) self:F( { FollowUnit, FollowGroupSet, FollowName } )
self.FollowUnit = FollowUnit -- Unit#UNIT self.FollowUnit = FollowUnit -- Wrapper.Unit#UNIT
self.FollowGroupSet = FollowGroupSet -- Set#SET_GROUP self.FollowGroupSet = FollowGroupSet -- Core.Set#SET_GROUP
self:SetFlightRandomization( 2 ) self:SetFlightRandomization( 2 )
@@ -906,7 +881,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
end end
--- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation. --- Use the method @{AI.AI_Formation#AI_FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation.
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number FlightRandomization The formation flying errors that pilots can make while in formation. Is a range set in meters. -- @param #number FlightRandomization The formation flying errors that pilots can make while in formation. Is a range set in meters.
-- @return #AI_FORMATION -- @return #AI_FORMATION

View File

@@ -1,8 +1,10 @@
--- **AI** -- (R2.1) - Manages the independent process of Air Patrol for airplanes. --- **AI** -- Perform Air Patrolling for airplanes.
-- --
-- === -- **Features:**
-- --
-- ![Banner Image](..\Presentations\AI_PATROL\Dia1.JPG) -- * Patrol AI airplanes within a given zone.
-- * Trigger detected events when enemy airplanes are detected.
-- * Manage a fuel treshold to RTB on time.
-- --
-- === -- ===
-- --
@@ -30,27 +32,25 @@
-- --
-- === -- ===
-- --
-- @module AI_Patrol -- @module AI.AI_Patrol
-- @image AI_Air_Patrolling.JPG
--- AI_PATROL_ZONE class --- AI_PATROL_ZONE class
-- @type AI_PATROL_ZONE -- @type AI_PATROL_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @field DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @field DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @field DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @field DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @field Core.Spawn#SPAWN CoordTest -- @field Core.Spawn#SPAWN CoordTest
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--- # AI_PATROL_ZONE class, extends @{Fsm#FSM_CONTROLLABLE} --- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
--
-- The AI_PATROL_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
-- --
-- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG)
-- --
-- The AI_PATROL_ZONE is assigned a @{Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event. -- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
-- --
-- ![Process](..\Presentations\AI_PATROL\Dia4.JPG) -- ![Process](..\Presentations\AI_PATROL\Dia4.JPG)
-- --
@@ -123,7 +123,7 @@
-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. -- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased.
-- --
-- The detection frequency can be set with @{#AI_PATROL_ZONE.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. -- The detection frequency can be set with @{#AI_PATROL_ZONE.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection.
-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI. -- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Wrapper.Unit}s detected by the AI.
-- --
-- The detection can be filtered to potential targets in a specific zone. -- The detection can be filtered to potential targets in a specific zone.
-- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected. -- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected.
@@ -155,11 +155,11 @@ AI_PATROL_ZONE = {
--- Creates a new AI_PATROL_ZONE object --- Creates a new AI_PATROL_ZONE object
-- @param #AI_PATROL_ZONE self -- @param #AI_PATROL_ZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_PATROL_ZONE self -- @return #AI_PATROL_ZONE self
-- @usage -- @usage
-- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. -- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
@@ -454,8 +454,8 @@ end
--- Sets (modifies) the minimum and maximum speed of the patrol. --- Sets (modifies) the minimum and maximum speed of the patrol.
-- @param #AI_PATROL_ZONE self -- @param #AI_PATROL_ZONE self
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
-- @return #AI_PATROL_ZONE self -- @return #AI_PATROL_ZONE self
function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
@@ -468,8 +468,8 @@ end
--- Sets the floor and ceiling altitude of the patrol. --- Sets the floor and ceiling altitude of the patrol.
-- @param #AI_PATROL_ZONE self -- @param #AI_PATROL_ZONE self
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @return #AI_PATROL_ZONE self -- @return #AI_PATROL_ZONE self
function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
@@ -562,18 +562,18 @@ function AI_PATROL_ZONE:SetDetectionZone( DetectionZone )
end end
end end
--- Gets a list of @{Unit#UNIT}s that were detected by the AI. --- Gets a list of @{Wrapper.Unit#UNIT}s that were detected by the AI.
-- No filtering is applied, so, ANY detected UNIT can be in this list. -- No filtering is applied, so, ANY detected UNIT can be in this list.
-- It is up to the mission designer to use the @{Unit} class and methods to filter the targets. -- It is up to the mission designer to use the @{Wrapper.Unit} class and methods to filter the targets.
-- @param #AI_PATROL_ZONE self -- @param #AI_PATROL_ZONE self
-- @return #table The list of @{Unit#UNIT}s -- @return #table The list of @{Wrapper.Unit#UNIT}s
function AI_PATROL_ZONE:GetDetectedUnits() function AI_PATROL_ZONE:GetDetectedUnits()
self:F2() self:F2()
return self.DetectedUnits return self.DetectedUnits
end end
--- Clears the list of @{Unit#UNIT}s that were detected by the AI. --- Clears the list of @{Wrapper.Unit#UNIT}s that were detected by the AI.
-- @param #AI_PATROL_ZONE self -- @param #AI_PATROL_ZONE self
function AI_PATROL_ZONE:ClearDetectedUnits() function AI_PATROL_ZONE:ClearDetectedUnits()
self:F2() self:F2()

View File

@@ -1,15 +1,15 @@
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occuring on @{Unit}s. --- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occuring on @{Wrapper.Unit}s.
-- --
-- ![Banner Image](..\Presentations\ACT_ACCOUNT\Dia1.JPG) -- ![Banner Image](..\Presentations\ACT_ACCOUNT\Dia1.JPG)
-- --
-- === -- ===
-- --
-- @module Account -- @module Actions.Account
-- @image MOOSE.JPG
do -- ACT_ACCOUNT do -- ACT_ACCOUNT
--- # @{#ACT_ACCOUNT} FSM class, extends @{Fsm#FSM_PROCESS} --- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ## ACT_ACCOUNT state machine: -- ## ACT_ACCOUNT state machine:
-- --
@@ -55,7 +55,7 @@ do -- ACT_ACCOUNT
-- These state transition methods need to provide a return value, which is specified at the function description. -- These state transition methods need to provide a return value, which is specified at the function description.
-- --
-- @type ACT_ACCOUNT -- @type ACT_ACCOUNT
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS -- @extends Core.Fsm#FSM_PROCESS
ACT_ACCOUNT = { ACT_ACCOUNT = {
ClassName = "ACT_ACCOUNT", ClassName = "ACT_ACCOUNT",
@@ -138,7 +138,7 @@ end -- ACT_ACCOUNT
do -- ACT_ACCOUNT_DEADS do -- ACT_ACCOUNT_DEADS
--- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Fsm.Account#ACT_ACCOUNT} --- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Core.Fsm.Account#ACT_ACCOUNT}
-- --
-- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units. -- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units.
-- The process is given a @{Set} of units that will be tracked upon successful destruction. -- The process is given a @{Set} of units that will be tracked upon successful destruction.
@@ -151,7 +151,7 @@ do -- ACT_ACCOUNT_DEADS
-- * @{#ACT_ACCOUNT_DEADS.New}(): Creates a new ACT_ACCOUNT_DEADS object. -- * @{#ACT_ACCOUNT_DEADS.New}(): Creates a new ACT_ACCOUNT_DEADS object.
-- --
-- @type ACT_ACCOUNT_DEADS -- @type ACT_ACCOUNT_DEADS
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends #ACT_ACCOUNT -- @extends #ACT_ACCOUNT
ACT_ACCOUNT_DEADS = { ACT_ACCOUNT_DEADS = {
ClassName = "ACT_ACCOUNT_DEADS", ClassName = "ACT_ACCOUNT_DEADS",
@@ -160,7 +160,7 @@ do -- ACT_ACCOUNT_DEADS
--- Creates a new DESTROY process. --- Creates a new DESTROY process.
-- @param #ACT_ACCOUNT_DEADS self -- @param #ACT_ACCOUNT_DEADS self
-- @param Set#SET_UNIT TargetSetUnit -- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskName -- @param #string TaskName
function ACT_ACCOUNT_DEADS:New() function ACT_ACCOUNT_DEADS:New()
-- Inherits from BASE -- Inherits from BASE
@@ -285,7 +285,7 @@ do -- ACT_ACCOUNT_DEADS
end end
--- @param #ACT_ACCOUNT_DEADS self --- @param #ACT_ACCOUNT_DEADS self
-- @param Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData ) function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
self:T( { "EventDead", EventData } ) self:T( { "EventDead", EventData } )
@@ -297,7 +297,7 @@ do -- ACT_ACCOUNT_DEADS
--- DCS Events --- DCS Events
--- @param #ACT_ACCOUNT_DEADS self --- @param #ACT_ACCOUNT_DEADS self
-- @param Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData ) function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
self:T( { "EventDead", EventData } ) self:T( { "EventDead", EventData } )

View File

@@ -2,7 +2,7 @@
-- --
-- === -- ===
-- --
-- # @{#ACT_ASSIGN} FSM template class, extends @{Fsm#FSM_PROCESS} -- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ## ACT_ASSIGN state machine: -- ## ACT_ASSIGN state machine:
-- --
@@ -54,7 +54,7 @@
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN} -- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN}
-- --
-- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task. -- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task.
-- --
@@ -64,7 +64,7 @@
-- --
-- === -- ===
-- --
-- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN} -- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN}
-- --
-- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option. -- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option.
-- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task. -- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task.
@@ -77,7 +77,8 @@
-- --
-- === -- ===
-- --
-- @module Assign -- @module Actions.Assign
-- @image MOOSE.JPG
do -- ACT_ASSIGN do -- ACT_ASSIGN
@@ -155,8 +156,7 @@ do -- ACT_ASSIGN_ACCEPT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ASSIGN_ACCEPT:onafterStart( ProcessUnit, From, Event, To ) function ACT_ASSIGN_ACCEPT:onafterStart( ProcessUnit, Task, From, Event, To )
self:F( { ProcessUnit, From, Event, To } )
self:__Assign( 1 ) self:__Assign( 1 )
end end
@@ -167,11 +167,8 @@ do -- ACT_ASSIGN_ACCEPT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ASSIGN_ACCEPT:onenterAssigned( ProcessUnit, From, Event, To ) function ACT_ASSIGN_ACCEPT:onenterAssigned( ProcessUnit, Task, From, Event, To )
self:F( { ProcessUnit, From, Event, To } )
local ProcessGroup = ProcessUnit:GetGroup()
self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() ) self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() )
end end
@@ -192,36 +189,26 @@ do -- ACT_ASSIGN_MENU_ACCEPT
--- Init. --- Init.
-- @param #ACT_ASSIGN_MENU_ACCEPT self -- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param #string TaskName
-- @param #string TaskBriefing -- @param #string TaskBriefing
-- @return #ACT_ASSIGN_MENU_ACCEPT self -- @return #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:New( TaskName, TaskBriefing ) function ACT_ASSIGN_MENU_ACCEPT:New( TaskBriefing )
-- Inherits from BASE -- Inherits from BASE
local self = BASE:Inherit( self, ACT_ASSIGN:New() ) -- #ACT_ASSIGN_MENU_ACCEPT local self = BASE:Inherit( self, ACT_ASSIGN:New() ) -- #ACT_ASSIGN_MENU_ACCEPT
self.TaskName = TaskName
self.TaskBriefing = TaskBriefing self.TaskBriefing = TaskBriefing
return self return self
end end
function ACT_ASSIGN_MENU_ACCEPT:Init( FsmAssign )
self.TaskName = FsmAssign.TaskName
self.TaskBriefing = FsmAssign.TaskBriefing
end
--- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. --- Creates a new task assignment state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIGN_MENU_ACCEPT self -- @param #ACT_ASSIGN_MENU_ACCEPT self
-- @param #string TaskName
-- @param #string TaskBriefing -- @param #string TaskBriefing
-- @return #ACT_ASSIGN_MENU_ACCEPT self -- @return #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:Init( TaskName, TaskBriefing ) function ACT_ASSIGN_MENU_ACCEPT:Init( TaskBriefing )
self.TaskBriefing = TaskBriefing self.TaskBriefing = TaskBriefing
self.TaskName = TaskName
return self return self
end end
@@ -232,30 +219,31 @@ do -- ACT_ASSIGN_MENU_ACCEPT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterStart( ProcessUnit, From, Event, To ) function ACT_ASSIGN_MENU_ACCEPT:onafterStart( ProcessUnit, Task, From, Event, To )
self:F( { ProcessUnit, From, Event, To } )
self:GetCommandCenter():MessageTypeToGroup( "Access the radio menu to accept the task. You have 30 seconds or the assignment will be cancelled.", ProcessUnit:GetGroup(), MESSAGE.Type.Information ) self:GetCommandCenter():MessageToGroup( "Task " .. self.Task:GetName() .. " has been assigned to you and your group!\nRead the briefing and use the Radio Menu (F10) / Task ... CONFIRMATION menu to accept or reject the task.\nYou have 2 minutes to accept, or the task assignment will be cancelled!", ProcessUnit:GetGroup(), 120 )
local ProcessGroup = ProcessUnit:GetGroup() local TaskGroup = ProcessUnit:GetGroup()
self.Menu = MENU_GROUP:New( TaskGroup, "Task " .. self.Task:GetName() .. " CONFIRMATION" )
self.MenuAcceptTask = MENU_GROUP_COMMAND:New( TaskGroup, "Accept task " .. self.Task:GetName(), self.Menu, self.MenuAssign, self, TaskGroup )
self.MenuRejectTask = MENU_GROUP_COMMAND:New( TaskGroup, "Reject task " .. self.Task:GetName(), self.Menu, self.MenuReject, self, TaskGroup )
self.Menu = MENU_GROUP:New( ProcessGroup, "Task " .. self.TaskName .. " acceptance" ) self:__Reject( 120, TaskGroup )
self.MenuAcceptTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Accept task " .. self.TaskName, self.Menu, self.MenuAssign, self )
self.MenuRejectTask = MENU_GROUP_COMMAND:New( ProcessGroup, "Reject task " .. self.TaskName, self.Menu, self.MenuReject, self )
end end
--- Menu function. --- Menu function.
-- @param #ACT_ASSIGN_MENU_ACCEPT self -- @param #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:MenuAssign() function ACT_ASSIGN_MENU_ACCEPT:MenuAssign( TaskGroup )
self:__Assign( 1 ) self:__Assign( -1, TaskGroup )
end end
--- Menu function. --- Menu function.
-- @param #ACT_ASSIGN_MENU_ACCEPT self -- @param #ACT_ASSIGN_MENU_ACCEPT self
function ACT_ASSIGN_MENU_ACCEPT:MenuReject() function ACT_ASSIGN_MENU_ACCEPT:MenuReject( TaskGroup )
self:__Reject( 1 ) self:__Reject( -1, TaskGroup )
end end
--- StateMachine callback function --- StateMachine callback function
@@ -264,8 +252,7 @@ do -- ACT_ASSIGN_MENU_ACCEPT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterAssign( ProcessUnit, From, Event, To ) function ACT_ASSIGN_MENU_ACCEPT:onafterAssign( ProcessUnit, Task, From, Event, To, TaskGroup )
self:F( { ProcessUnit.UnitNameFrom, Event, To } )
self.Menu:Remove() self.Menu:Remove()
end end
@@ -276,13 +263,25 @@ do -- ACT_ASSIGN_MENU_ACCEPT
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onafterReject( ProcessUnit, From, Event, To ) function ACT_ASSIGN_MENU_ACCEPT:onafterReject( ProcessUnit, Task, From, Event, To, TaskGroup )
self:F( { ProcessUnit.UnitName, From, Event, To } ) self:F( { TaskGroup = TaskGroup } )
self.Menu:Remove() self.Menu:Remove()
--TODO: need to resolve this problem ... it has to do with the events ... --TODO: need to resolve this problem ... it has to do with the events ...
--self.Task:UnAssignFromUnit( ProcessUnit )needs to become a callback funtion call upon the event --self.Task:UnAssignFromUnit( ProcessUnit )needs to become a callback funtion call upon the event
ProcessUnit:Destroy() self.Task:RejectGroup( TaskGroup )
end
--- StateMachine callback function
-- @param #ACT_ASSIGN_ACCEPT self
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIGN_MENU_ACCEPT:onenterAssigned( ProcessUnit, Task, From, Event, To, TaskGroup )
--self.Task:AssignToGroup( TaskGroup )
self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() )
end end
end -- ACT_ASSIGN_MENU_ACCEPT end -- ACT_ASSIGN_MENU_ACCEPT

View File

@@ -1,9 +1,5 @@
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones. --- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
-- --
-- ===
--
-- # @{#ACT_ASSIST} FSM class, extends @{Fsm#FSM_PROCESS}
--
-- ## ACT_ASSIST state machine: -- ## ACT_ASSIST state machine:
-- --
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur. -- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
@@ -52,7 +48,7 @@
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Fsm.Route#ACT_ASSIST} -- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Core.Fsm.Route#ACT_ASSIST}
-- --
-- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Zone}. -- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Zone}.
-- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour. -- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour.
@@ -64,7 +60,9 @@
-- --
-- === -- ===
-- --
-- @module Smoke -- @module Actions.Assist
-- @image MOOSE.JPG
do -- ACT_ASSIST do -- ACT_ASSIST
@@ -142,7 +140,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
--- ACT_ASSIST_SMOKE_TARGETS_ZONE class --- ACT_ASSIST_SMOKE_TARGETS_ZONE class
-- @type ACT_ASSIST_SMOKE_TARGETS_ZONE -- @type ACT_ASSIST_SMOKE_TARGETS_ZONE
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @field Core.Zone#ZONE_BASE TargetZone -- @field Core.Zone#ZONE_BASE TargetZone
-- @extends #ACT_ASSIST -- @extends #ACT_ASSIST
ACT_ASSIST_SMOKE_TARGETS_ZONE = { ACT_ASSIST_SMOKE_TARGETS_ZONE = {
@@ -158,7 +156,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. --- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self -- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
-- @param Set#SET_UNIT TargetSetUnit -- @param Core.Set#SET_UNIT TargetSetUnit
-- @param Core.Zone#ZONE_BASE TargetZone -- @param Core.Zone#ZONE_BASE TargetZone
function ACT_ASSIST_SMOKE_TARGETS_ZONE:New( TargetSetUnit, TargetZone ) function ACT_ASSIST_SMOKE_TARGETS_ZONE:New( TargetSetUnit, TargetZone )
local self = BASE:Inherit( self, ACT_ASSIST:New() ) -- #ACT_ASSIST local self = BASE:Inherit( self, ACT_ASSIST:New() ) -- #ACT_ASSIST
@@ -177,7 +175,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. --- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self -- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
-- @param Set#SET_UNIT TargetSetUnit -- @param Core.Set#SET_UNIT TargetSetUnit
-- @param Core.Zone#ZONE_BASE TargetZone -- @param Core.Zone#ZONE_BASE TargetZone
-- @return #ACT_ASSIST_SMOKE_TARGETS_ZONE self -- @return #ACT_ASSIST_SMOKE_TARGETS_ZONE self
function ACT_ASSIST_SMOKE_TARGETS_ZONE:Init( TargetSetUnit, TargetZone ) function ACT_ASSIST_SMOKE_TARGETS_ZONE:Init( TargetSetUnit, TargetZone )

View File

@@ -1,198 +0,0 @@
--- @module Process_JTAC
--- PROCESS_JTAC class
-- @type PROCESS_JTAC
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS
PROCESS_JTAC = {
ClassName = "PROCESS_JTAC",
Fsm = {},
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #PROCESS_JTAC self
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param Wrapper.Unit#UNIT FACUnit
-- @return #PROCESS_JTAC self
function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( "JTAC", Task, ProcessUnit ) ) -- #PROCESS_JTAC
self.TargetSetUnit = TargetSetUnit
self.FACUnit = FACUnit
self.DisplayInterval = 60
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = FSM_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'CreatedMenu' },
{ name = 'JTACMenuUpdate', from = 'CreatedMenu', to = 'AwaitingMenu' },
{ name = 'JTACMenuAwait', from = 'AwaitingMenu', to = 'AwaitingMenu' },
{ name = 'JTACMenuSpot', from = 'AwaitingMenu', to = 'AwaitingMenu' },
{ name = 'JTACMenuCancel', from = 'AwaitingMenu', to = 'AwaitingMenu' },
{ name = 'JTACStatus', from = 'AwaitingMenu', to = 'AwaitingMenu' },
{ name = 'Fail', from = 'AwaitingMenu', to = 'Failed' },
{ name = 'Fail', from = 'CreatedMenu', to = 'Failed' },
},
callbacks = {
onStart = self.OnStart,
onJTACMenuUpdate = self.OnJTACMenuUpdate,
onJTACMenuAwait = self.OnJTACMenuAwait,
onJTACMenuSpot = self.OnJTACMenuSpot,
onJTACMenuCancel = self.OnJTACMenuCancel,
},
endstates = { 'Failed' }
} )
self:HandleEvent( EVENTS.Dead, self.EventDead )
return self
end
--- Process Events
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_JTAC:OnStart( Fsm, From, Event, To )
self:NextEvent( Fsm.JTACMenuUpdate )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_JTAC:OnJTACMenuUpdate( Fsm, From, Event, To )
local function JTACMenuSpot( MenuParam )
self:F( MenuParam.TargetUnit.UnitName )
local self = MenuParam.self
local TargetUnit = MenuParam.TargetUnit
self:NextEvent( self.Fsm.JTACMenuSpot, TargetUnit )
end
local function JTACMenuCancel( MenuParam )
self:F( MenuParam )
local self = MenuParam.self
local TargetUnit = MenuParam.TargetUnit
self:NextEvent( self.Fsm.JTACMenuCancel, TargetUnit )
end
-- Loop each unit in the target set, and determine the threat levels map table.
local UnitThreatLevels = self.TargetSetUnit:GetUnitThreatLevels()
self:F( {"UnitThreadLevels", UnitThreatLevels } )
local JTACMenu = self.ProcessGroup:GetState( self.ProcessGroup, "JTACMenu" )
if not JTACMenu then
JTACMenu = MENU_GROUP:New( self.ProcessGroup, "JTAC", self.MissionMenu )
for ThreatLevel, ThreatLevelTable in pairs( UnitThreatLevels ) do
local JTACMenuThreatLevel = MENU_GROUP:New( self.ProcessGroup, ThreatLevelTable.UnitThreatLevelText, JTACMenu )
for ThreatUnitName, ThreatUnit in pairs( ThreatLevelTable.Units ) do
local JTACMenuUnit = MENU_GROUP:New( self.ProcessGroup, ThreatUnit:GetTypeName(), JTACMenuThreatLevel )
MENU_GROUP_COMMAND:New( self.ProcessGroup, "Lase Target", JTACMenuUnit, JTACMenuSpot, { self = self, TargetUnit = ThreatUnit } )
MENU_GROUP_COMMAND:New( self.ProcessGroup, "Cancel Target", JTACMenuUnit, JTACMenuCancel, { self = self, TargetUnit = ThreatUnit } )
end
end
end
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_JTAC:OnJTACMenuAwait( Fsm, From, Event, To )
if self.DisplayCount >= self.DisplayInterval then
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
for TargetUnitName, SpotData in pairs( TaskJTAC.Spots) do
local TargetUnit = UNIT:FindByName( TargetUnitName )
self.FACUnit:MessageToGroup( "Lasing " .. TargetUnit:GetTypeName() .. " with laser code " .. SpotData:getCode(), 15, self.ProcessGroup )
end
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
self:NextEvent( Fsm.JTACMenuAwait )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT TargetUnit
function PROCESS_JTAC:OnJTACMenuSpot( Fsm, From, Event, To, TargetUnit )
local TargetUnitName = TargetUnit:GetName()
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {}
local DCSFACObject = self.FACUnit:GetDCSObject()
local TargetVec3 = TargetUnit:GetVec3()
TaskJTAC.Spots[TargetUnitName] = Spot.createInfraRed( self.FACUnit:GetDCSObject(), { x = 0, y = 1, z = 0 }, TargetUnit:GetVec3(), math.random( 1000, 9999 ) )
local SpotData = TaskJTAC.Spots[TargetUnitName]
self.FACUnit:MessageToGroup( "Lasing " .. TargetUnit:GetTypeName() .. " with laser code " .. SpotData:getCode(), 15, self.ProcessGroup )
self:NextEvent( Fsm.JTACMenuAwait )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_JTAC self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT TargetUnit
function PROCESS_JTAC:OnJTACMenuCancel( Fsm, From, Event, To, TargetUnit )
local TargetUnitName = TargetUnit:GetName()
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
TaskJTAC.Spots = TaskJTAC.Spots or {}
if TaskJTAC.Spots[TargetUnitName] then
TaskJTAC.Spots[TargetUnitName]:destroy() -- destroys the spot
TaskJTAC.Spots[TargetUnitName] = nil
end
self.FACUnit:MessageToGroup( "Stopped lasing " .. TargetUnit:GetTypeName(), 15, self.ProcessGroup )
self:NextEvent( Fsm.JTACMenuAwait )
end

View File

@@ -1,173 +0,0 @@
--- @module Process_Pickup
--- PROCESS_PICKUP class
-- @type PROCESS_PICKUP
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Core.Fsm#FSM_PROCESS
PROCESS_PICKUP = {
ClassName = "PROCESS_PICKUP",
Fsm = {},
TargetSetUnit = nil,
}
--- Creates a new DESTROY process.
-- @param #PROCESS_PICKUP self
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @return #PROCESS_PICKUP self
function PROCESS_PICKUP:New( Task, ProcessName, ProcessUnit )
-- Inherits from BASE
local self = BASE:Inherit( self, PROCESS:New( ProcessName, Task, ProcessUnit ) ) -- #PROCESS_PICKUP
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self.DisplayCategory = "HQ" -- Targets is the default display category
self.Fsm = FSM_PROCESS:New( self, {
initial = 'Assigned',
events = {
{ name = 'Start', from = 'Assigned', to = 'Navigating' },
{ name = 'Start', from = 'Navigating', to = 'Navigating' },
{ name = 'Nearby', from = 'Navigating', to = 'Preparing' },
{ name = 'Pickup', from = 'Preparing', to = 'Loading' },
{ name = 'Load', from = 'Loading', to = 'Success' },
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
{ name = 'Fail', from = 'Navigating', to = 'Failed' },
{ name = 'Fail', from = 'Preparing', to = 'Failed' },
},
callbacks = {
onStart = self.OnStart,
onNearby = self.OnNearby,
onPickup = self.OnPickup,
onLoad = self.OnLoad,
},
endstates = { 'Success', 'Failed' }
} )
return self
end
--- Process Events
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnStart( Fsm, From, Event, To )
self:NextEvent( Fsm.Start )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnNavigating( Fsm, From, Event, To )
local TaskGroup = self.ProcessUnit:GetGroup()
if self.DisplayCount >= self.DisplayInterval then
MESSAGE:New( "Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed.", 5, "HQ" ):ToGroup( TaskGroup )
self.DisplayCount = 1
else
self.DisplayCount = self.DisplayCount + 1
end
return true -- Process always the event.
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Event#EVENTDATA Event
function PROCESS_PICKUP:OnHitTarget( Fsm, From, Event, To, Event )
self.TargetSetUnit:Flush( self )
if self.TargetSetUnit:FindUnit( Event.IniUnitName ) then
self.TargetSetUnit:RemoveUnitsByName( Event.IniUnitName )
local TaskGroup = self.ProcessUnit:GetGroup()
MESSAGE:New( "You hit a target. Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed.", 15, "HQ" ):ToGroup( TaskGroup )
end
if self.TargetSetUnit:Count() > 0 then
self:NextEvent( Fsm.MoreTargets )
else
self:NextEvent( Fsm.Destroyed )
end
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnMoreTargets( Fsm, From, Event, To )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Event#EVENTDATA DCSEvent
function PROCESS_PICKUP:OnKilled( Fsm, From, Event, To )
self:NextEvent( Fsm.Restart )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnRestart( Fsm, From, Event, To )
self:NextEvent( Fsm.Menu )
end
--- StateMachine callback function for a PROCESS
-- @param #PROCESS_PICKUP self
-- @param Core.Fsm#FSM_PROCESS Fsm
-- @param #string Event
-- @param #string From
-- @param #string To
function PROCESS_PICKUP:OnDestroyed( Fsm, From, Event, To )
end
--- DCS Events
--- @param #PROCESS_PICKUP self
-- @param Core.Event#EVENTDATA Event
function PROCESS_PICKUP:EventDead( Event )
if Event.IniDCSUnit then
self:NextEvent( self.Fsm.HitTarget, Event )
end
end

View File

@@ -2,7 +2,7 @@
-- --
-- === -- ===
-- --
-- # @{#ACT_ROUTE} FSM class, extends @{Fsm#FSM_PROCESS} -- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
-- --
-- ## ACT_ROUTE state machine: -- ## ACT_ROUTE state machine:
-- --
@@ -60,9 +60,9 @@
-- --
-- === -- ===
-- --
-- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Fsm.Route#ACT_ROUTE} -- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Core.Fsm.Route#ACT_ROUTE}
-- --
-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Controllable} player @{Unit} to a @{Zone}. -- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Zone}.
-- The player receives on perioding times messages with the coordinates of the route to follow. -- The player receives on perioding times messages with the coordinates of the route to follow.
-- Upon arrival at the zone, a confirmation of arrival is sent, and the process will be ended. -- Upon arrival at the zone, a confirmation of arrival is sent, and the process will be ended.
-- --
@@ -72,7 +72,8 @@
-- --
-- === -- ===
-- --
-- @module Route -- @module Actions.Route
-- @image MOOSE.JPG
do -- ACT_ROUTE do -- ACT_ROUTE
@@ -123,16 +124,20 @@ do -- ACT_ROUTE
--- Set a Cancel Menu item. --- Set a Cancel Menu item.
-- @param #ACT_ROUTE self -- @param #ACT_ROUTE self
-- @return #ACT_ROUTE -- @return #ACT_ROUTE
function ACT_ROUTE:SetMenuCancel( MenuGroup, MenuText, ParentMenu, MenuTime ) function ACT_ROUTE:SetMenuCancel( MenuGroup, MenuText, ParentMenu, MenuTime, MenuTag )
MENU_GROUP_COMMAND:New( self.CancelMenuGroupCommand = MENU_GROUP_COMMAND:New(
MenuGroup, MenuGroup,
MenuText, MenuText,
ParentMenu, ParentMenu,
self.MenuCancel, self.MenuCancel,
self self
):SetTime(MenuTime) ):SetTime( MenuTime ):SetTag( MenuTag )
ParentMenu:SetTime( MenuTime )
ParentMenu:Remove( MenuTime, MenuTag )
return self return self
end end
@@ -206,7 +211,9 @@ do -- ACT_ROUTE
function ACT_ROUTE:MenuCancel() function ACT_ROUTE:MenuCancel()
self:Cancel() self:F("Cancelled")
self.CancelMenuGroupCommand:Remove()
self:__Cancel( 1 )
end end
--- Task Events --- Task Events
@@ -238,10 +245,8 @@ do -- ACT_ROUTE
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function ACT_ROUTE:onbeforeRoute( ProcessUnit, From, Event, To ) function ACT_ROUTE:onbeforeRoute( ProcessUnit, From, Event, To )
self:F( { "BeforeRoute 1", self.DisplayCount, self.DisplayInterval } )
if ProcessUnit:IsAlive() then if ProcessUnit:IsAlive() then
self:F( "BeforeRoute 2" )
local HasArrived = self:onfuncHasArrived( ProcessUnit ) -- Polymorphic local HasArrived = self:onfuncHasArrived( ProcessUnit ) -- Polymorphic
if self.DisplayCount >= self.DisplayInterval then if self.DisplayCount >= self.DisplayInterval then
self:T( { HasArrived = HasArrived } ) self:T( { HasArrived = HasArrived } )
@@ -253,8 +258,6 @@ do -- ACT_ROUTE
self.DisplayCount = self.DisplayCount + 1 self.DisplayCount = self.DisplayCount + 1
end end
self:T( { DisplayCount = self.DisplayCount } )
if HasArrived then if HasArrived then
self:__Arrive( 1 ) self:__Arrive( 1 )
else else
@@ -337,7 +340,7 @@ do -- ACT_ROUTE_POINT
-- @param #ACT_ROUTE_POINT self -- @param #ACT_ROUTE_POINT self
-- @param #number Range The Range to consider the arrival. Default is 10000 meters. -- @param #number Range The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:SetRange( Range ) function ACT_ROUTE_POINT:SetRange( Range )
self:F2( { self.Range } ) self:F2( { Range } )
self.Range = Range or 10000 self.Range = Range or 10000
end end
@@ -345,6 +348,7 @@ do -- ACT_ROUTE_POINT
-- @param #ACT_ROUTE_POINT self -- @param #ACT_ROUTE_POINT self
-- @return #number The Range to consider the arrival. Default is 10000 meters. -- @return #number The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:GetRange() function ACT_ROUTE_POINT:GetRange()
self:F2( { self.Range } )
return self.Range return self.Range
end end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,311 @@
--- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object.
--
-- ===
--
-- ### [Demo Missions]()
--
-- ### [YouTube Playlist]()
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions:
--
-- ===
--
-- @module Cargo.CargoCrate
-- @image Cargo_Crates.JPG
do -- CARGO_CRATE
--- Models the behaviour of cargo crates, which can be slingloaded and boarded on helicopters.
-- @type CARGO_CRATE
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
--
-- ===
--
-- @field #CARGO_CRATE
CARGO_CRATE = {
ClassName = "CARGO_CRATE"
}
--- CARGO_CRATE Constructor.
-- @param #CARGO_CRATE self
-- @param Wrapper.Static#STATIC CargoStatic
-- @param #string Type
-- @param #string Name
-- @param #number LoadRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_CRATE
function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE
self:F( { Type, Name, NearRadius } )
self.CargoObject = CargoStatic -- Wrapper.Static#STATIC
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
self:SetEventPriority( 4 )
return self
end
--- @param #CARGO_CRATE self
-- @param Core.Event#EVENTDATA EventData
function CARGO_CRATE:OnEventCargoDead( EventData )
local Destroyed = false
if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() then
if self.CargoObject:GetName() == EventData.IniUnitName then
if not self.NoDestroy then
Destroyed = true
end
end
else
if self:IsLoaded() then
local CarrierName = self.CargoCarrier:GetName()
if CarrierName == EventData.IniDCSUnitName then
MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll()
Destroyed = true
self.CargoCarrier:ClearCargo()
end
end
end
if Destroyed then
self:I( { "Cargo crate destroyed: " .. self.CargoObject:GetName() } )
self:Destroyed()
end
end
--- Enter UnLoaded State.
-- @param #CARGO_CRATE self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
--self:F( { ToPointVec2, From, Event, To } )
local Angle = 180
local Speed = 10
local Distance = 10
if From == "Loaded" then
local StartCoordinate = self.CargoCarrier:GetCoordinate()
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoDeployCoord = StartCoordinate:Translate( Distance, CargoDeployHeading )
ToPointVec2 = ToPointVec2 or COORDINATE:NewFromVec2( { x= CargoDeployCoord.x, y = CargoDeployCoord.z } )
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawnAt( ToPointVec2, 0 )
self.CargoCarrier = nil
end
end
if self.OnUnLoadedCallBack then
self.OnUnLoadedCallBack( self, unpack( self.OnUnLoadedParameters ) )
self.OnUnLoadedCallBack = nil
end
end
--- Loaded State.
-- @param #CARGO_CRATE self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier )
--self:F( { From, Event, To, CargoCarrier } )
self.CargoCarrier = CargoCarrier
-- Only destroy the CargoObject is if there is a CargoObject (packages don't have CargoObjects).
if self.CargoObject then
self:T("Destroying")
self.NoDestroy = true
self.CargoObject:Destroy()
--local Coordinate = self.CargoObject:GetCoordinate():GetRandomCoordinateInRadius( 50, 20 )
--self.CargoObject:ReSpawnAt( Coordinate, 0 )
end
end
--- Check if the cargo can be Boarded.
-- @param #CARGO_CRATE self
function CARGO_CRATE:CanBoard()
return false
end
--- Check if the cargo can be Unboarded.
-- @param #CARGO_CRATE self
function CARGO_CRATE:CanUnboard()
return false
end
--- Check if Cargo Crate is in the radius for the Cargo to be reported.
-- @param #CARGO_CRATE self
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean true if the Cargo Crate is within the report radius.
function CARGO_CRATE:IsInReportRadius( Coordinate )
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
local Distance = 0
if self:IsUnLoaded() then
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
--self:T( Distance )
if Distance <= self.LoadRadius then
return true
end
end
return false
end
--- Check if Cargo Crate is in the radius for the Cargo to be Boarded or Loaded.
-- @param #CARGO_CRATE self
-- @param Core.Point#Coordinate Coordinate
-- @return #boolean true if the Cargo Crate is within the loading radius.
function CARGO_CRATE:IsInLoadRadius( Coordinate )
--self:F( { Coordinate, LoadRadius = self.NearRadius } )
local Distance = 0
if self:IsUnLoaded() then
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
--self:T( Distance )
if Distance <= self.NearRadius then
return true
end
end
return false
end
--- Get the current Coordinate of the CargoGroup.
-- @param #CARGO_CRATE self
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
-- @return #nil There is no valid Cargo in the CargoGroup.
function CARGO_CRATE:GetCoordinate()
--self:F()
return self.CargoObject:GetCoordinate()
end
--- Check if the CargoGroup is alive.
-- @param #CARGO_CRATE self
-- @return #boolean true if the CargoGroup is alive.
-- @return #boolean false if the CargoGroup is dead.
function CARGO_CRATE:IsAlive()
local Alive = true
-- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive.
-- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive.
if self:IsLoaded() then
Alive = Alive == true and self.CargoCarrier:IsAlive()
else
Alive = Alive == true and self.CargoObject:IsAlive()
end
return Alive
end
--- Route Cargo to Coordinate and randomize locations.
-- @param #CARGO_CRATE self
-- @param Core.Point#COORDINATE Coordinate
function CARGO_CRATE:RouteTo( Coordinate )
self:F( {Coordinate = Coordinate } )
end
--- Check if Cargo is near to the Carrier.
-- The Cargo is near to the Carrier within NearRadius.
-- @param #CARGO_CRATE self
-- @param Wrapper.Group#GROUP CargoCarrier
-- @param #number NearRadius
-- @return #boolean The Cargo is near to the Carrier.
-- @return #nil The Cargo is not near to the Carrier.
function CARGO_CRATE:IsNear( CargoCarrier, NearRadius )
self:F( {NearRadius = NearRadius } )
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
end
--- Respawn the CargoGroup.
-- @param #CARGO_CRATE self
function CARGO_CRATE:Respawn()
self:F( { "Respawning crate " .. self:GetName() } )
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawn() -- A cargo destroy crates a DEAD event.
self:__Reset( -0.1 )
end
end
--- Respawn the CargoGroup.
-- @param #CARGO_CRATE self
function CARGO_CRATE:onafterReset()
self:F( { "Reset crate " .. self:GetName() } )
-- Respawn the group...
if self.CargoObject then
self:SetDeployed( false )
self:SetStartState( "UnLoaded" )
self.CargoCarrier = nil
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
end
end
--- Get the transportation method of the Cargo.
-- @param #CARGO_CRATE self
-- @return #string The transportation method of the Cargo.
function CARGO_CRATE:GetTransportationMethod()
if self:IsLoaded() then
return "for unloading"
else
if self:IsUnLoaded() then
return "for loading"
else
if self:IsDeployed() then
return "delivered"
end
end
end
return ""
end
end

View File

@@ -0,0 +1,772 @@
--- **Cargo** -- Management of grouped cargo logistics, which are based on a @{Wrapper.Group} object.
--
-- ===
--
-- ![Banner Image](..\Presentations\CARGO\Dia1.JPG)
--
-- ===
--
-- ### [Demo Missions]()
--
-- ### [YouTube Playlist]()
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions:
--
-- ===
--
-- @module Cargo.CargoGroup
-- @image Cargo_Groups.JPG
do -- CARGO_GROUP
--- @type CARGO_GROUP
-- @extends Cargo.Cargo#CARGO_REPORTABLE
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
-- @field #string GroupName The name of the CargoGroup.
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
--
-- The above cargo classes are used by the AI\_CARGO\_ classes to allow AI groups to transport cargo:
--
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class.
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class.
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Plane#AI_CARGO_PLANE} class.
-- * AI Ships is planned.
--
-- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking:
--
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
--
-- The
--
-- @field #CARGO_GROUP CARGO_GROUP
--
CARGO_GROUP = {
ClassName = "CARGO_GROUP",
}
--- CARGO_GROUP constructor.
-- This make a new CARGO_GROUP from a @{Wrapper.Group} object.
-- It will "ungroup" the group object within the sim, and will create a @{Set} of individual Unit objects.
-- @param #CARGO_GROUP self
-- @param Wrapper.Group#GROUP CargoGroup
-- @param #string Type
-- @param #string Name
-- @param #number LoadRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_GROUP
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius )
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius ) ) -- #CARGO_GROUP
self:F( { Type, Name, LoadRadius } )
self.CargoSet = SET_CARGO:New()
self.CargoGroup = CargoGroup
self.Grouped = true
self.CargoUnitTemplate = {}
self:SetDeployed( false )
local WeightGroup = 0
self.CargoGroup:Destroy()
local GroupName = CargoGroup:GetName()
self.CargoName = Name
self.CargoTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) )
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
GroupTemplate.name = self.CargoName .. "#CARGO"
GroupTemplate.groupId = nil
GroupTemplate.units = {}
for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do
UnitTemplate.name = UnitTemplate.name .. "#CARGO"
local CargoUnitName = UnitTemplate.name
self.CargoUnitTemplate[CargoUnitName] = UnitTemplate
GroupTemplate.units[#GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
GroupTemplate.units[#GroupTemplate.units].unitId = nil
-- And we register the spawned unit as part of the CargoSet.
local Unit = UNIT:Register( CargoUnitName )
--local WeightUnit = Unit:GetDesc().massEmpty
--WeightGroup = WeightGroup + WeightUnit
local CargoUnit = CARGO_UNIT:New( Unit, Type, CargoUnitName, 10 )
self.CargoSet:Add( CargoUnitName, CargoUnit )
end
-- Then we register the new group in the database
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
-- Now we spawn the new group based on the template created.
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
self:SetWeight( WeightGroup )
self.CargoLimit = 10
self:T( { "Weight Cargo", WeightGroup } )
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
self:SetEventPriority( 4 )
return self
end
--- Ungroup the cargo group into individual groups with one unit.
-- This is required because by default a group will move in formation and this is really an issue for group control.
-- Therefore this method is made to be able to ungroup a group.
-- This works for ground only groups.
-- @param #CARGO_GROUP self
function CARGO_GROUP:Ungroup()
if self.Grouped == true then
self.Grouped = false
self.CargoGroup:Destroy()
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
if CargoUnit:IsUnLoaded() then
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
--local GroupName = env.getValueDictByKey( GroupTemplate.name )
-- We create a new group object with one unit...
-- First we prepare the template...
GroupTemplate.name = self.CargoName .. "#CARGO#" .. CargoUnitName
GroupTemplate.groupId = nil
if CargoUnit:IsUnLoaded() then
GroupTemplate.units = {}
GroupTemplate.units[1] = self.CargoUnitTemplate[CargoUnitName]
GroupTemplate.units[#GroupTemplate.units].unitId = nil
GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX()
GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY()
GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading()
end
-- Then we register the new group in the database
local CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
-- Now we spawn the new group based on the template created.
_DATABASE:Spawn( GroupTemplate )
end
end
self.CargoObject = nil
end
end
--- Regroup the cargo group into one group with multiple unit.
-- This is required because by default a group will move in formation and this is really an issue for group control.
-- Therefore this method is made to be able to regroup a group.
-- This works for ground only groups.
-- @param #CARGO_GROUP self
function CARGO_GROUP:Regroup()
self:F("Regroup")
if self.Grouped == false then
self.Grouped = true
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
GroupTemplate.name = self.CargoName .. "#CARGO"
GroupTemplate.groupId = nil
GroupTemplate.units = {}
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
self:F( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
if CargoUnit:IsUnLoaded() then
CargoUnit.CargoObject:Destroy()
GroupTemplate.units[#GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
GroupTemplate.units[#GroupTemplate.units].unitId = nil
GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX()
GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY()
GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading()
end
end
-- Then we register the new group in the database
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
self:F( { "Regroup", GroupTemplate } )
-- Now we spawn the new group based on the template created.
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
end
end
--- @param #CARGO_GROUP self
-- @param Core.Event#EVENTDATA EventData
function CARGO_GROUP:OnEventCargoDead( EventData )
self:I( EventData )
local Destroyed = false
if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() or self:IsUnboarding() then
Destroyed = true
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
local Cargo = CargoData -- Cargo.Cargo#CARGO
if Cargo:IsAlive() then
Destroyed = false
else
Cargo:Destroyed()
end
end
else
local CarrierName = self.CargoCarrier:GetName()
if CarrierName == EventData.IniDCSUnitName then
MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll()
Destroyed = true
self.CargoCarrier:ClearCargo()
end
end
if Destroyed then
self:Destroyed()
self:E( { "Cargo group destroyed" } )
end
end
--- Enter Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
--self:F( { CargoCarrier.UnitName, From, Event, To } )
local NearRadius = NearRadius or 25
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo, ... )
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
end, ...
)
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
end
end
--- Enter Loaded State.
-- @param #CARGO_GROUP self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... )
--self:F( { From, Event, To, CargoCarrier, ...} )
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
Cargo:Load( CargoCarrier )
end
end
--self.CargoObject:Destroy()
self.CargoCarrier = CargoCarrier
self.CargoCarrier:AddCargo( self )
end
--- Leave Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
--self:F( { CargoCarrier.UnitName, From, Event, To } )
local NearRadius = NearRadius or 100
local Boarded = true
local Cancelled = false
local Dead = true
self.CargoSet:Flush()
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( { Cargo:GetName(), Cargo.current } )
if not Cargo:is( "Loaded" )
and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function.
Boarded = false
end
if Cargo:is( "UnLoaded" ) then
Cancelled = true
end
if not Cargo:is( "Destroyed" ) then
Dead = false
end
end
if not Dead then
if not Cancelled then
if not Boarded then
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
else
self:F("Group Cargo is loaded")
self:__Load( 1, CargoCarrier, ... )
end
else
self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... )
end
else
self:__Destroyed( 1, CargoCarrier, NearRadius, ... )
end
end
--- Enter UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
--self:F( {From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
local Timer = 1
if From == "Loaded" then
if self.CargoObject then
self.CargoObject:Destroy()
end
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
--- @param Cargo.Cargo#CARGO Cargo
function( Cargo, NearRadius )
if not Cargo:IsDestroyed() then
Cargo:__UnBoard( Timer, ToPointVec2, NearRadius )
Timer = Timer + 3
end
end, { NearRadius }
)
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
end
--- Leave UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
--local NearRadius = NearRadius or 25
local Angle = 180
local Speed = 10
local Distance = 5
if From == "UnBoarding" then
local UnBoarded = true
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( { Cargo:GetName(), Cargo.current } )
if not Cargo:is( "UnLoaded" ) and not Cargo:IsDestroyed() then
UnBoarded = false
end
end
if UnBoarded then
return true
else
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
return false
end
end
--- UnBoard Event.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
--local NearRadius = NearRadius or 25
self:__UnLoad( 1, ToPointVec2, ... )
end
--- Enter UnLoaded State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... )
--self:F( { From, Event, To, ToPointVec2 } )
if From == "Loaded" then
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo )
--Cargo:UnLoad( ToPointVec2 )
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(10)
Cargo:UnLoad( RandomVec2 )
end
)
end
self.CargoCarrier:RemoveCargo( self )
self.CargoCarrier = nil
end
--- Get the current Coordinate of the CargoGroup.
-- @param #CARGO_GROUP self
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
-- @return #nil There is no valid Cargo in the CargoGroup.
function CARGO_GROUP:GetCoordinate()
self:F()
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
if Cargo then
return Cargo.CargoObject:GetCoordinate()
end
return nil
end
--- Get the x position of the cargo.
-- @param #CARGO_GROUP self
-- @return #number
function CARGO:GetX()
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
if Cargo then
return Cargo:GetCoordinate().x
end
return nil
end
--- Get the y position of the cargo.
-- @param #CARGO_GROUP self
-- @return #number
function CARGO:GetY()
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
if Cargo then
return Cargo:GetCoordinate().z
end
return nil
end
--- Check if the CargoGroup is alive.
-- @param #CARGO_GROUP self
-- @return #boolean true if the CargoGroup is alive.
-- @return #boolean false if the CargoGroup is dead.
function CARGO_GROUP:IsAlive()
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
return Cargo ~= nil
end
--- Get the first alive Cargo Unit of the Cargo Group.
-- @param #CARGO_GROUP self
-- @return #CARGO_GROUP
function CARGO_GROUP:GetFirstAlive()
local CargoFirstAlive = nil
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
if not Cargo:IsDestroyed() then
CargoFirstAlive = Cargo
break
end
end
return CargoFirstAlive
end
--- Get the amount of cargo units in the group.
-- @param #CARGO_GROUP self
-- @return #CARGO_GROUP
function CARGO_GROUP:GetCount()
return self.CargoSet:Count()
end
--- Get the amount of cargo units in the group.
-- @param #CARGO_GROUP self
-- @return #CARGO_GROUP
function CARGO_GROUP:GetGroup( Cargo )
local Cargo = Cargo or self:GetFirstAlive() -- Cargo.Cargo#CARGO
return Cargo.CargoObject:GetGroup()
end
--- Route Cargo to Coordinate and randomize locations.
-- @param #CARGO_GROUP self
-- @param Core.Point#COORDINATE Coordinate
function CARGO_GROUP:RouteTo( Coordinate )
--self:F( {Coordinate = Coordinate } )
-- For each Cargo within the CargoSet, route each object to the Coordinate
self.CargoSet:ForEach(
function( Cargo )
Cargo.CargoObject:RouteGroundTo( Coordinate, 10, "vee", 0 )
end
)
end
--- Check if Cargo is near to the Carrier.
-- The Cargo is near to the Carrier if the first unit of the Cargo Group is within NearRadius.
-- @param #CARGO_GROUP self
-- @param Wrapper.Group#GROUP CargoCarrier
-- @param #number NearRadius
-- @return #boolean The Cargo is near to the Carrier.
-- @return #nil The Cargo is not near to the Carrier.
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
self:F( {NearRadius = NearRadius } )
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
local Cargo = Cargo -- Cargo.Cargo#CARGO
if Cargo:IsAlive() then
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
self:F( "Near" )
return true
end
end
end
return nil
end
--- Check if Cargo Group is in the radius for the Cargo to be Boarded.
-- @param #CARGO_GROUP self
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean true if the Cargo Group is within the load radius.
function CARGO_GROUP:IsInLoadRadius( Coordinate )
--self:F( { Coordinate } )
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
if Cargo then
local Distance = 0
if Cargo:IsLoaded() then
Distance = Coordinate:Get2DDistance( Cargo.CargoCarrier:GetCoordinate() )
else
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
end
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
if Distance <= self.LoadRadius then
return true
else
return false
end
end
return nil
end
--- Check if Cargo Group is in the report radius.
-- @param #CARGO_GROUP self
-- @param Core.Point#Coordinate Coordinate
-- @return #boolean true if the Cargo Group is within the report radius.
function CARGO_GROUP:IsInReportRadius( Coordinate )
--self:F( { Coordinate } )
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
if Cargo then
self:F( { Cargo } )
local Distance = 0
if Cargo:IsUnLoaded() then
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
--self:T( Distance )
if Distance <= self.LoadRadius then
return true
end
end
end
return nil
end
--- Respawn the CargoGroup.
-- @param #CARGO_GROUP self
function CARGO_GROUP:Respawn()
self:F( { "Respawning" } )
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
local Cargo = CargoData -- Cargo.Cargo#CARGO
Cargo:Destroy()
Cargo:SetStartState( "UnLoaded" )
end
-- We iterate through the group template and for each unit in the template, we create a new group with one unit.
for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
local GroupName = env.getValueDictByKey( GroupTemplate.name )
-- We create a new group object with one unit...
-- First we prepare the template...
GroupTemplate.name = GroupName .. "#CARGO#" .. UnitID
GroupTemplate.groupId = nil
GroupTemplate.units = {}
GroupTemplate.units[1] = UnitTemplate
local UnitName = UnitTemplate.name .. "#CARGO"
GroupTemplate.units[1].name = UnitTemplate.name .. "#CARGO"
-- Then we register the new group in the database
local CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
-- Now we spawn the new group based on the template created.
_DATABASE:Spawn( GroupTemplate )
-- And we register the spawned unit as part of the CargoSet.
local Unit = UNIT:FindByName( UnitName )
--local WeightUnit = Unit:GetDesc().massEmpty
--WeightGroup = WeightGroup + WeightUnit
local CargoUnit = CARGO_UNIT:New( Unit, Type, UnitName, 10 )
self.CargoSet:Add( UnitName, CargoUnit )
end
self:SetDeployed( false )
self:SetStartState( "UnLoaded" )
end
--- Signal a flare at the position of the CargoGroup.
-- @param #CARGO_GROUP self
-- @param Utilities.Utils#FLARECOLOR FlareColor
function CARGO_GROUP:Flare( FlareColor )
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
if Cargo then
Cargo:Flare( FlareColor )
end
end
--- Smoke the CargoGroup.
-- @param #CARGO_GROUP self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke.
-- @param #number Radius The radius of randomization around the center of the first element of the CargoGroup.
function CARGO_GROUP:Smoke( SmokeColor, Radius )
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
if Cargo then
Cargo:Smoke( SmokeColor, Radius )
end
end
--- Check if the first element of the CargoGroup is the given @{Zone}.
-- @param #CARGO_GROUP self
-- @param Core.Zone#ZONE_BASE Zone
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
function CARGO_GROUP:IsInZone( Zone )
--self:F( { Zone } )
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
if Cargo then
return Cargo:IsInZone( Zone )
end
return nil
end
--- Get the transportation method of the Cargo.
-- @param #CARGO_GROUP self
-- @return #string The transportation method of the Cargo.
function CARGO_GROUP:GetTransportationMethod()
if self:IsLoaded() then
return "for unboarding"
else
if self:IsUnLoaded() then
return "for boarding"
else
if self:IsDeployed() then
return "delivered"
end
end
end
return ""
end
end -- CARGO_GROUP

View File

@@ -0,0 +1,262 @@
--- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object. The cargo can only be slingloaded.
--
-- ===
--
-- ### [Demo Missions]()
--
-- ### [YouTube Playlist]()
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions:
--
-- ===
--
-- @module Cargo.CargoSlingload
-- @image Cargo_Slingload.JPG
do -- CARGO_SLINGLOAD
--- Models the behaviour of cargo crates, which can only be slingloaded.
-- @type CARGO_SLINGLOAD
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
--
-- ===
--
-- @field #CARGO_SLINGLOAD
CARGO_SLINGLOAD = {
ClassName = "CARGO_SLINGLOAD"
}
--- CARGO_SLINGLOAD Constructor.
-- @param #CARGO_SLINGLOAD self
-- @param Wrapper.Static#STATIC CargoStatic
-- @param #string Type
-- @param #string Name
-- @param #number LoadRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_SLINGLOAD
function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD
self:F( { Type, Name, NearRadius } )
self.CargoObject = CargoStatic
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
self:SetEventPriority( 4 )
return self
end
--- @param #CARGO_SLINGLOAD self
-- @param Core.Event#EVENTDATA EventData
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
local Destroyed = false
if self:IsDestroyed() or self:IsUnLoaded() then
if self.CargoObject:GetName() == EventData.IniUnitName then
if not self.NoDestroy then
Destroyed = true
end
end
end
if Destroyed then
self:I( { "Cargo crate destroyed: " .. self.CargoObject:GetName() } )
self:Destroyed()
end
end
--- Check if the cargo can be Slingloaded.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:CanSlingload()
return true
end
--- Check if the cargo can be Boarded.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:CanBoard()
return false
end
--- Check if the cargo can be Unboarded.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:CanUnboard()
return false
end
--- Check if the cargo can be Loaded.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:CanLoad()
return false
end
--- Check if the cargo can be Unloaded.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:CanUnload()
return false
end
--- Check if Cargo Crate is in the radius for the Cargo to be reported.
-- @param #CARGO_SLINGLOAD self
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean true if the Cargo Crate is within the report radius.
function CARGO_SLINGLOAD:IsInReportRadius( Coordinate )
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
local Distance = 0
if self:IsUnLoaded() then
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
if Distance <= self.LoadRadius then
return true
end
end
return false
end
--- Check if Cargo Slingload is in the radius for the Cargo to be Boarded or Loaded.
-- @param #CARGO_SLINGLOAD self
-- @param Core.Point#COORDINATE Coordinate
-- @return #boolean true if the Cargo Slingload is within the loading radius.
function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate )
--self:F( { Coordinate } )
local Distance = 0
if self:IsUnLoaded() then
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
if Distance <= self.NearRadius then
return true
end
end
return false
end
--- Get the current Coordinate of the CargoGroup.
-- @param #CARGO_SLINGLOAD self
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
-- @return #nil There is no valid Cargo in the CargoGroup.
function CARGO_SLINGLOAD:GetCoordinate()
--self:F()
return self.CargoObject:GetCoordinate()
end
--- Check if the CargoGroup is alive.
-- @param #CARGO_SLINGLOAD self
-- @return #boolean true if the CargoGroup is alive.
-- @return #boolean false if the CargoGroup is dead.
function CARGO_SLINGLOAD:IsAlive()
local Alive = true
-- When the Cargo is Loaded, the Cargo is in the CargoCarrier, so we check if the CargoCarrier is alive.
-- When the Cargo is not Loaded, the Cargo is the CargoObject, so we check if the CargoObject is alive.
if self:IsLoaded() then
Alive = Alive == true and self.CargoCarrier:IsAlive()
else
Alive = Alive == true and self.CargoObject:IsAlive()
end
return Alive
end
--- Route Cargo to Coordinate and randomize locations.
-- @param #CARGO_SLINGLOAD self
-- @param Core.Point#COORDINATE Coordinate
function CARGO_SLINGLOAD:RouteTo( Coordinate )
--self:F( {Coordinate = Coordinate } )
end
--- Check if Cargo is near to the Carrier.
-- The Cargo is near to the Carrier within NearRadius.
-- @param #CARGO_SLINGLOAD self
-- @param Wrapper.Group#GROUP CargoCarrier
-- @param #number NearRadius
-- @return #boolean The Cargo is near to the Carrier.
-- @return #nil The Cargo is not near to the Carrier.
function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius )
--self:F( {NearRadius = NearRadius } )
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
end
--- Respawn the CargoGroup.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:Respawn()
--self:F( { "Respawning slingload " .. self:GetName() } )
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawn() -- A cargo destroy crates a DEAD event.
self:__Reset( -0.1 )
end
end
--- Respawn the CargoGroup.
-- @param #CARGO_SLINGLOAD self
function CARGO_SLINGLOAD:onafterReset()
--self:F( { "Reset slingload " .. self:GetName() } )
-- Respawn the group...
if self.CargoObject then
self:SetDeployed( false )
self:SetStartState( "UnLoaded" )
self.CargoCarrier = nil
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
end
end
--- Get the transportation method of the Cargo.
-- @param #CARGO_SLINGLOAD self
-- @return #string The transportation method of the Cargo.
function CARGO_SLINGLOAD:GetTransportationMethod()
if self:IsLoaded() then
return "for sling loading"
else
if self:IsUnLoaded() then
return "for sling loading"
else
if self:IsDeployed() then
return "delivered"
end
end
end
return ""
end
end

View File

@@ -0,0 +1,393 @@
--- **Cargo** -- Management of single cargo logistics, which are based on a @{Wrapper.Unit} object.
--
-- ===
--
-- ### [Demo Missions]()
--
-- ### [YouTube Playlist]()
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions:
--
-- ===
--
-- @module Cargo.CargoUnit
-- @image Cargo_Units.JPG
do -- CARGO_UNIT
--- Models CARGO in the form of units, which can be boarded, unboarded, loaded, unloaded.
-- @type CARGO_UNIT
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_UNIT objects to and from carriers.
--
-- ===
--
-- @field #CARGO_UNIT CARGO_UNIT
--
CARGO_UNIT = {
ClassName = "CARGO_UNIT"
}
--- CARGO_UNIT Constructor.
-- @param #CARGO_UNIT self
-- @param Wrapper.Unit#UNIT CargoUnit
-- @param #string Type
-- @param #string Name
-- @param #number Weight
-- @param #number LoadRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_UNIT
function CARGO_UNIT:New( CargoUnit, Type, Name, Weight, NearRadius )
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, Weight, NearRadius ) ) -- #CARGO_UNIT
self:I( { Type, Name, Weight, NearRadius } )
self:T( CargoUnit )
self.CargoObject = CargoUnit
self:T( self.ClassName )
self:SetEventPriority( 5 )
return self
end
--- Enter UnBoarding State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
local Angle = 180
local Speed = 60
local DeployDistance = 9
local RouteDistance = 60
if From == "Loaded" then
if not self:IsDestroyed() then
local CargoCarrier = self.CargoCarrier -- Wrapper.Controllable#CONTROLLABLE
if CargoCarrier:IsAlive() then
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoRoutePointVec2 = CargoCarrierPointVec2:Translate( RouteDistance, CargoDeployHeading )
-- if there is no ToPointVec2 given, then use the CargoRoutePointVec2
local FromDirectionVec3 = CargoCarrierPointVec2:GetDirectionVec3( ToPointVec2 or CargoRoutePointVec2 )
local FromAngle = CargoCarrierPointVec2:GetAngleDegrees(FromDirectionVec3)
local FromPointVec2 = CargoCarrierPointVec2:Translate( DeployDistance, FromAngle )
--local CargoDeployPointVec2 = CargoCarrierPointVec2:GetRandomCoordinateInRadius( 10, 5 )
ToPointVec2 = ToPointVec2 or CargoCarrierPointVec2:GetRandomCoordinateInRadius( NearRadius, DeployDistance )
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading )
self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
self.CargoCarrier = nil
local Points = {}
-- From
Points[#Points+1] = FromPointVec2:WaypointGround( Speed, "Vee" )
-- To
Points[#Points+1] = ToPointVec2:WaypointGround( Speed, "Vee" )
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 1 )
self:__UnBoarding( 1, ToPointVec2, NearRadius )
end
else
-- the Carrier is dead. This cargo is dead too!
self:Destroyed()
end
end
end
end
--- Leave UnBoarding State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 100
local Angle = 180
local Speed = 10
local Distance = 5
if From == "UnBoarding" then
--if self:IsNear( ToPointVec2, NearRadius ) then
return true
--else
--self:__UnBoarding( 1, ToPointVec2, NearRadius )
--end
--return false
end
end
--- UnBoard Event.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 100
self.CargoInAir = self.CargoObject:InAir()
self:T( self.CargoInAir )
-- Only unboard the cargo when the carrier is not in the air.
-- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea).
if not self.CargoInAir then
end
self:__UnLoad( 1, ToPointVec2, NearRadius )
end
--- Enter UnLoaded State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
self:F( { ToPointVec2, From, Event, To } )
local Angle = 180
local Speed = 10
local Distance = 5
if From == "Loaded" then
local StartPointVec2 = self.CargoCarrier:GetPointVec2()
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoDeployCoord = StartPointVec2:Translate( Distance, CargoDeployHeading )
ToPointVec2 = ToPointVec2 or COORDINATE:New( CargoDeployCoord.x, CargoDeployCoord.z )
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawnAt( ToPointVec2, 0 )
self.CargoCarrier = nil
end
end
if self.OnUnLoadedCallBack then
self.OnUnLoadedCallBack( self, unpack( self.OnUnLoadedParameters ) )
self.OnUnLoadedCallBack = nil
end
end
--- Board Event.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { From, Event, To, CargoCarrier, NearRadius } )
local NearRadius = NearRadius or 25
self.CargoInAir = self.CargoObject:InAir()
local Desc = self.CargoObject:GetDesc()
local MaxSpeed = Desc.speedMaxOffRoad
local TypeName = Desc.typeName
self:T( self.CargoInAir )
-- Only move the group to the carrier when the cargo is not in the air
-- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea).
if not self.CargoInAir then
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:Load( CargoCarrier, NearRadius, ... )
else
if MaxSpeed and MaxSpeed == 0 or TypeName and TypeName == "Stinger comm" then
self:Load( CargoCarrier, NearRadius, ... )
else
local Speed = 90
local Angle = 180
local Distance = 5
NearRadius = NearRadius or 25
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading )
-- Set the CargoObject to state Green to ensure it is boarding!
self.CargoObject:OptionAlarmStateGreen()
local Points = {}
local PointStartVec2 = self.CargoObject:GetPointVec2()
Points[#Points+1] = PointStartVec2:WaypointGround( Speed )
Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed )
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 2 )
self:__Boarding( -1, CargoCarrier, NearRadius )
self.RunCount = 0
end
end
end
end
--- Boarding Event.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Client#CLIENT CargoCarrier
-- @param #number NearRadius
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
if CargoCarrier and CargoCarrier:IsAlive() and self.CargoObject and self.CargoObject:IsAlive() then
if CargoCarrier:InAir() == false then
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:__Load( 1, CargoCarrier, ... )
else
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
self.RunCount = self.RunCount + 1
if self.RunCount >= 40 then
self.RunCount = 0
local Speed = 90
local Angle = 180
local Distance = 5
NearRadius = NearRadius or 25
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading )
-- Set the CargoObject to state Green to ensure it is boarding!
self.CargoObject:OptionAlarmStateGreen()
local Points = {}
local PointStartVec2 = self.CargoObject:GetPointVec2()
Points[#Points+1] = PointStartVec2:WaypointGround( Speed, "Off road" )
Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed, "Off road" )
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 0.2 )
end
end
else
self.CargoObject:MessageToGroup( "Cancelling Boarding... Get back on the ground!", 5, CargoCarrier:GetGroup(), self:GetName() )
self:CancelBoarding( CargoCarrier, NearRadius, ... )
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
end
else
self:E("Something is wrong")
end
end
--- Enter Boarding State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
local Speed = 90
local Angle = 180
local Distance = 5
local NearRadius = NearRadius or 25
if From == "UnLoaded" or From == "Boarding" then
end
end
--- Loaded State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
self:F( { From, Event, To, CargoCarrier } )
self.CargoCarrier = CargoCarrier
-- Only destroy the CargoObject is if there is a CargoObject (packages don't have CargoObjects).
if self.CargoObject then
self:T("Destroying")
self.CargoObject:Destroy()
--self.CargoObject:ReSpawnAt( COORDINATE:NewFromVec2( {x=0,y=0} ), 0 )
end
end
--- Get the transportation method of the Cargo.
-- @param #CARGO_UNIT self
-- @return #string The transportation method of the Cargo.
function CARGO_UNIT:GetTransportationMethod()
if self:IsLoaded() then
return "for unboarding"
else
if self:IsUnLoaded() then
return "for boarding"
else
if self:IsDeployed() then
return "delivered"
end
end
end
return ""
end
end -- CARGO_UNIT

View File

@@ -1,15 +1,12 @@
--- **Core** -- BASE forms **the basis of the MOOSE framework**. Each class within the MOOSE framework derives from BASE. --- **Core** -- BASE forms **the basis of the MOOSE framework**. Each class within the MOOSE framework derives from BASE.
-- --
-- ![Banner Image](..\Presentations\BASE\Dia1.JPG)
--
-- ===
--
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions:
-- --
-- === -- ===
-- --
-- @module Base -- @module Core.Base
-- @image Core_Base.JPG
@@ -26,9 +23,7 @@ local _ClassID = 0
-- @field ClassID The ID number of the class. -- @field ClassID The ID number of the class.
-- @field ClassNameAndID The name of the class concatenated with the ID number of the class. -- @field ClassNameAndID The name of the class concatenated with the ID number of the class.
--- # 1) #BASE class --- All classes within the MOOSE framework are derived from the BASE class.
--
-- All classes within the MOOSE framework are derived from the BASE class.
-- --
-- BASE provides facilities for : -- BASE provides facilities for :
-- --
@@ -42,8 +37,8 @@ local _ClassID = 0
-- --
-- ## 1.1) BASE constructor -- ## 1.1) BASE constructor
-- --
-- Any class derived from BASE, will use the @{Base#BASE.New} constructor embedded in the @{Base#BASE.Inherit} method. -- Any class derived from BASE, will use the @{Core.Base#BASE.New} constructor embedded in the @{Core.Base#BASE.Inherit} method.
-- See an example at the @{Base#BASE.New} method how this is done. -- See an example at the @{Core.Base#BASE.New} method how this is done.
-- --
-- ## 1.2) Trace information for debugging -- ## 1.2) Trace information for debugging
-- --
@@ -127,7 +122,7 @@ local _ClassID = 0
-- ### 1.3.2 Event Handling of DCS Events -- ### 1.3.2 Event Handling of DCS Events
-- --
-- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called -- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called
-- when the DCS event occurs. The Event Handling method receives an @{Event#EVENTDATA} structure, which contains a lot of information -- when the DCS event occurs. The Event Handling method receives an @{Core.Event#EVENTDATA} structure, which contains a lot of information
-- about the event that occurred. -- about the event that occurred.
-- --
-- Find below an example of the prototype how to write an event handling function for two units: -- Find below an example of the prototype how to write an event handling function for two units:
@@ -609,8 +604,8 @@ end
--- Creation of a Birth Event. --- Creation of a Birth Event.
-- @param #BASE self -- @param #BASE self
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event. -- @param DCS#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event. -- @param DCS#Object Initiator The initiating object of the event.
-- @param #string IniUnitName The initiating unit name. -- @param #string IniUnitName The initiating unit name.
-- @param place -- @param place
-- @param subplace -- @param subplace
@@ -631,8 +626,8 @@ end
--- Creation of a Crash Event. --- Creation of a Crash Event.
-- @param #BASE self -- @param #BASE self
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event. -- @param DCS#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event. -- @param DCS#Object Initiator The initiating object of the event.
function BASE:CreateEventCrash( EventTime, Initiator ) function BASE:CreateEventCrash( EventTime, Initiator )
self:F( { EventTime, Initiator } ) self:F( { EventTime, Initiator } )
@@ -645,10 +640,26 @@ function BASE:CreateEventCrash( EventTime, Initiator )
world.onEvent( Event ) world.onEvent( Event )
end end
--- Creation of a Dead Event.
-- @param #BASE self
-- @param DCS#Time EventTime The time stamp of the event.
-- @param DCS#Object Initiator The initiating object of the event.
function BASE:CreateEventDead( EventTime, Initiator )
self:F( { EventTime, Initiator } )
local Event = {
id = world.event.S_EVENT_DEAD,
time = EventTime,
initiator = Initiator,
}
world.onEvent( Event )
end
--- Creation of a Takeoff Event. --- Creation of a Takeoff Event.
-- @param #BASE self -- @param #BASE self
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event. -- @param DCS#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event. -- @param DCS#Object Initiator The initiating object of the event.
function BASE:CreateEventTakeoff( EventTime, Initiator ) function BASE:CreateEventTakeoff( EventTime, Initiator )
self:F( { EventTime, Initiator } ) self:F( { EventTime, Initiator } )
@@ -661,10 +672,10 @@ function BASE:CreateEventTakeoff( EventTime, Initiator )
world.onEvent( Event ) world.onEvent( Event )
end end
-- TODO: Complete Dcs.DCSTypes#Event structure. -- TODO: Complete DCS#Event structure.
--- The main event handling function... This function captures all events generated for the class. --- The main event handling function... This function captures all events generated for the class.
-- @param #BASE self -- @param #BASE self
-- @param Dcs.DCSTypes#Event event -- @param DCS#Event event
function BASE:onEvent(event) function BASE:onEvent(event)
--self:F( { BaseEventCodes[event.id], event } ) --self:F( { BaseEventCodes[event.id], event } )

File diff suppressed because it is too large Load Diff

View File

@@ -7,13 +7,14 @@
-- --
-- === -- ===
-- --
-- @module Database -- @module Core.Database
-- @image Core_Database.JPG
--- @type DATABASE --- @type DATABASE
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # DATABASE class, extends @{Base#BASE} --- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
-- --
-- Mission designers can use the DATABASE class to refer to: -- Mission designers can use the DATABASE class to refer to:
-- --
@@ -58,6 +59,7 @@ DATABASE = {
ZONENAMES = {}, ZONENAMES = {},
HITS = {}, HITS = {},
DESTROYS = {}, DESTROYS = {},
ZONES = {},
} }
local _DATABASECoalition = local _DATABASECoalition =
@@ -95,6 +97,8 @@ function DATABASE:New()
self:HandleEvent( EVENTS.Hit, self.AccountHits ) self:HandleEvent( EVENTS.Hit, self.AccountHits )
self:HandleEvent( EVENTS.NewCargo ) self:HandleEvent( EVENTS.NewCargo )
self:HandleEvent( EVENTS.DeleteCargo ) self:HandleEvent( EVENTS.DeleteCargo )
self:HandleEvent( EVENTS.NewZone )
self:HandleEvent( EVENTS.DeleteZone )
-- Follow alive players and clients -- Follow alive players and clients
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event. --self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event.
@@ -242,35 +246,178 @@ function DATABASE:FindAirbase( AirbaseName )
return AirbaseFound return AirbaseFound
end end
--- Adds a Cargo based on the Cargo Name in the DATABASE.
-- @param #DATABASE self
-- @param #string CargoName The name of the airbase
function DATABASE:AddCargo( Cargo )
if not self.CARGOS[Cargo.Name] then do -- Zones
self.CARGOS[Cargo.Name] = Cargo
--- Finds a @{Zone} based on the zone name.
-- @param #DATABASE self
-- @param #string ZoneName The name of the zone.
-- @return Core.Zone#ZONE_BASE The found ZONE.
function DATABASE:FindZone( ZoneName )
local ZoneFound = self.ZONES[ZoneName]
return ZoneFound
end
--- Adds a @{Zone} based on the zone name in the DATABASE.
-- @param #DATABASE self
-- @param #string ZoneName The name of the zone.
-- @param Core.Zone#ZONE_BASE Zone The zone.
function DATABASE:AddZone( ZoneName, Zone )
if not self.ZONES[ZoneName] then
self.ZONES[ZoneName] = Zone
end
end
--- Deletes a @{Zone} from the DATABASE based on the zone name.
-- @param #DATABASE self
-- @param #string ZoneName The name of the zone.
function DATABASE:DeleteZone( ZoneName )
self.ZONES[ZoneName] = nil
end
--- Finds an @{Zone} based on the zone name in the DATABASE.
-- @param #DATABASE self
-- @param #string ZoneName
-- @return Core.Zone#ZONE_BASE The found @{Zone}.
function DATABASE:FindZone( ZoneName )
local ZoneFound = self.ZONES[ZoneName]
return ZoneFound
end end
end
--- Deletes a Cargo from the DATABASE based on the Cargo Name. --- Private method that registers new ZONE_BASE derived objects within the DATABASE Object.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string CargoName The name of the airbase -- @return #DATABASE self
function DATABASE:DeleteCargo( CargoName ) function DATABASE:_RegisterZones()
self.CARGOS[CargoName] = nil for ZoneID, ZoneData in pairs( env.mission.triggers.zones ) do
end local ZoneName = ZoneData.name
--- Finds an CARGO based on the CargoName. self:I( { "Register ZONE:", Name = ZoneName } )
-- @param #DATABASE self local Zone = ZONE:New( ZoneName )
-- @param #string CargoName self.ZONENAMES[ZoneName] = ZoneName
-- @return Wrapper.Cargo#CARGO The found CARGO. self:AddZone( ZoneName, Zone )
function DATABASE:FindCargo( CargoName ) end
for ZoneGroupName, ZoneGroup in pairs( self.GROUPS ) do
if ZoneGroupName:match("~ZONE_POLYGON") then
local ZoneName1 = ZoneGroupName:match("(.*)~ZONE_POLYGON")
local ZoneName2 = ZoneGroupName:match(".*~ZONE_POLYGON(.*)")
local ZoneName = ZoneName1 .. ( ZoneName2 or "" )
self:I( { "Register ZONE_POLYGON:", Name = ZoneName } )
local Zone_Polygon = ZONE_POLYGON:New( ZoneName, ZoneGroup )
self.ZONENAMES[ZoneName] = ZoneName
self:AddZone( ZoneName, Zone_Polygon )
end
end
end
local CargoFound = self.CARGOS[CargoName]
return CargoFound
end
end -- zone
do -- cargo
--- Adds a Cargo based on the Cargo Name in the DATABASE.
-- @param #DATABASE self
-- @param #string CargoName The name of the airbase
function DATABASE:AddCargo( Cargo )
if not self.CARGOS[Cargo.Name] then
self.CARGOS[Cargo.Name] = Cargo
end
end
--- Deletes a Cargo from the DATABASE based on the Cargo Name.
-- @param #DATABASE self
-- @param #string CargoName The name of the airbase
function DATABASE:DeleteCargo( CargoName )
self.CARGOS[CargoName] = nil
end
--- Finds an CARGO based on the CargoName.
-- @param #DATABASE self
-- @param #string CargoName
-- @return Wrapper.Cargo#CARGO The found CARGO.
function DATABASE:FindCargo( CargoName )
local CargoFound = self.CARGOS[CargoName]
return CargoFound
end
--- Checks if the Template name has a ~CARGO tag.
-- If yes, the group is a cargo.
-- @param #DATABASE self
-- @param #string TemplateName
-- @return #boolean
function DATABASE:IsCargo( TemplateName )
TemplateName = env.getValueDictByKey( TemplateName )
local Cargo = TemplateName:match( "~(CARGO)" )
return Cargo and Cargo == "CARGO"
end
--- Private method that registers new Static Templates within the DATABASE Object.
-- @param #DATABASE self
-- @return #DATABASE self
function DATABASE:_RegisterCargos()
for CargoGroupName, CargoGroup in pairs( self.GROUPS ) do
if self:IsCargo( CargoGroupName ) then
local CargoInfo = CargoGroupName:match("~CARGO(.*)")
local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)")
local CargoName1 = CargoGroupName:match("(.*)~CARGO%(.*%)")
local CargoName2 = CargoGroupName:match(".*~CARGO%(.*%)(.*)")
self:E({CargoName1 = CargoName1, CargoName2 = CargoName2 })
local CargoName = CargoName1 .. ( CargoName2 or "" )
local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?")
local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName
local LoadRadius = CargoParam and tonumber( CargoParam:match( "RR=([%a%d]+),?") )
local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") )
self:I({"Register CargoGroup:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius )
end
end
for CargoStaticName, CargoStatic in pairs( self.STATICS ) do
if self:IsCargo( CargoStaticName ) then
local CargoInfo = CargoStaticName:match("~CARGO(.*)")
local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)")
local CargoName = CargoStaticName:match("(.*)~CARGO")
local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?")
local Category = CargoParam and CargoParam:match( "C=([%a%d ]+),?")
local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName
local LoadRadius = CargoParam and tonumber( CargoParam:match( "RR=([%a%d]+),?") )
local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") )
if Category == "SLING" then
self:I({"Register CargoSlingload:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
else
if Category == "CRATE" then
self:I({"Register CargoCrate:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
end
end
end
end
end
end -- cargo
--- Finds a CLIENT based on the ClientName. --- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self -- @param #DATABASE self
@@ -442,16 +589,14 @@ end
--- Private method that registers new Group Templates within the DATABASE Object. --- Private method that registers new Group Templates within the DATABASE Object.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #table GroupTemplate -- @param #table GroupTemplate
-- @param Dcs.DCScoalition#coalition.side CoalitionSide The coalition.side of the object. -- @param DCS#coalition.side CoalitionSide The coalition.side of the object.
-- @param Dcs.DCSObject#Object.Category CategoryID The Object.category of the object. -- @param DCS#Object.Category CategoryID The Object.category of the object.
-- @param Dcs.DCScountry#country.id CountryID the country.id of the object -- @param DCS#country.id CountryID the country.id of the object
-- @return #DATABASE self -- @return #DATABASE self
function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName ) function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName )
local GroupTemplateName = GroupName or env.getValueDictByKey( GroupTemplate.name ) local GroupTemplateName = GroupName or env.getValueDictByKey( GroupTemplate.name )
local TraceTable = {}
if not self.Templates.Groups[GroupTemplateName] then if not self.Templates.Groups[GroupTemplateName] then
self.Templates.Groups[GroupTemplateName] = {} self.Templates.Groups[GroupTemplateName] = {}
self.Templates.Groups[GroupTemplateName].Status = nil self.Templates.Groups[GroupTemplateName].Status = nil
@@ -475,18 +620,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
self.Templates.Groups[GroupTemplateName].CoalitionID = CoalitionSide self.Templates.Groups[GroupTemplateName].CoalitionID = CoalitionSide
self.Templates.Groups[GroupTemplateName].CountryID = CountryID self.Templates.Groups[GroupTemplateName].CountryID = CountryID
local UnitNames = {}
TraceTable[#TraceTable+1] = "Group"
TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].GroupName
TraceTable[#TraceTable+1] = "Coalition"
TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CoalitionID
TraceTable[#TraceTable+1] = "Category"
TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CategoryID
TraceTable[#TraceTable+1] = "Country"
TraceTable[#TraceTable+1] = self.Templates.Groups[GroupTemplateName].CountryID
TraceTable[#TraceTable+1] = "Units"
for unit_num, UnitTemplate in pairs( GroupTemplate.units ) do for unit_num, UnitTemplate in pairs( GroupTemplate.units ) do
@@ -510,10 +644,16 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate
end end
TraceTable[#TraceTable+1] = self.Templates.Units[UnitTemplate.name].UnitName UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName
end end
self:E( TraceTable ) self:I( { Group = self.Templates.Groups[GroupTemplateName].GroupName,
Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID,
Category = self.Templates.Groups[GroupTemplateName].CategoryID,
Country = self.Templates.Groups[GroupTemplateName].CountryID,
Units = UnitNames
}
)
end end
function DATABASE:GetGroupTemplate( GroupName ) function DATABASE:GetGroupTemplate( GroupName )
@@ -530,8 +670,6 @@ end
-- @return #DATABASE self -- @return #DATABASE self
function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID ) function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
local TraceTable = {}
local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name) local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name)
self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {} self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
@@ -547,28 +685,22 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category
self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID
self.Templates.Statics[StaticTemplateName].CountryID = CountryID self.Templates.Statics[StaticTemplateName].CountryID = CountryID
self:I( { Static = self.Templates.Statics[StaticTemplateName].StaticName,
Coalition = self.Templates.Statics[StaticTemplateName].CoalitionID,
Category = self.Templates.Statics[StaticTemplateName].CategoryID,
Country = self.Templates.Statics[StaticTemplateName].CountryID
}
)
self:AddStatic( StaticTemplateName )
TraceTable[#TraceTable+1] = "Static"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].StaticName
TraceTable[#TraceTable+1] = "Coalition"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CoalitionID
TraceTable[#TraceTable+1] = "Category"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CategoryID
TraceTable[#TraceTable+1] = "Country"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CountryID
self:E( TraceTable )
end end
--- @param #DATABASE self --- @param #DATABASE self
function DATABASE:GetStaticUnitTemplate( StaticName ) function DATABASE:GetStaticUnitTemplate( StaticName )
local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate
StaticTemplate.SpawnCoalitionID = self.Templates.Statics[StaticName].CoalitionID return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID
StaticTemplate.SpawnCategoryID = self.Templates.Statics[StaticName].CategoryID
StaticTemplate.SpawnCountryID = self.Templates.Statics[StaticName].CountryID
return StaticTemplate
end end
@@ -703,7 +835,7 @@ function DATABASE:_RegisterAirbases()
local DCSAirbaseName = DCSAirbase:getName() local DCSAirbaseName = DCSAirbase:getName()
self:E( { "Register Airbase:", DCSAirbaseName } ) self:E( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
self:AddAirbase( DCSAirbaseName ) self:AddAirbase( DCSAirbaseName )
end end
end end
@@ -734,7 +866,7 @@ function DATABASE:_EventOnBirth( Event )
Event.IniGroup = self:FindGroup( Event.IniDCSGroupName ) Event.IniGroup = self:FindGroup( Event.IniDCSGroupName )
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName()
self:E( { "PlayerName:", PlayerName } ) self:E( { "PlayerName:", PlayerName } )
if PlayerName ~= "" then if PlayerName then
self:E( { "Player Joined:", PlayerName } ) self:E( { "Player Joined:", PlayerName } )
if not self.PLAYERS[PlayerName] then if not self.PLAYERS[PlayerName] then
self:AddPlayer( Event.IniUnitName, PlayerName ) self:AddPlayer( Event.IniUnitName, PlayerName )
@@ -803,7 +935,7 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then if Event.IniObjectCategory == 1 then
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName()
if self.PLAYERS[PlayerName] then if PlayerName and self.PLAYERS[PlayerName] then
self:E( { "Player Left:", PlayerName } ) self:E( { "Player Left:", PlayerName } )
local Settings = SETTINGS:Set( PlayerName ) local Settings = SETTINGS:Set( PlayerName )
Settings:RemovePlayerMenu( Event.IniUnit ) Settings:RemovePlayerMenu( Event.IniUnit )
@@ -988,6 +1120,31 @@ function DATABASE:OnEventDeleteCargo( EventData )
end end
--- Handles the OnEventNewZone event.
-- @param #DATABASE self
-- @param Core.Event#EVENTDATA EventData
function DATABASE:OnEventNewZone( EventData )
self:F2( { EventData } )
if EventData.Zone then
self:AddZone( EventData.Zone )
end
end
--- Handles the OnEventDeleteZone.
-- @param #DATABASE self
-- @param Core.Event#EVENTDATA EventData
function DATABASE:OnEventDeleteZone( EventData )
self:F2( { EventData } )
if EventData.Zone then
self:DeleteZone( EventData.Zone.ZoneName )
end
end
--- Gets the player settings --- Gets the player settings
-- @param #DATABASE self -- @param #DATABASE self
-- @param #string PlayerName -- @param #string PlayerName
@@ -1025,7 +1182,6 @@ function DATABASE:_RegisterTemplates()
local CoalitionSide = coalition.side[string.upper(CoalitionName)] local CoalitionSide = coalition.side[string.upper(CoalitionName)]
----------------------------------------------
-- build nav points DB -- build nav points DB
self.Navpoints[CoalitionName] = {} self.Navpoints[CoalitionName] = {}
if coa_data.nav_points then --navpoints if coa_data.nav_points then --navpoints
@@ -1040,8 +1196,9 @@ function DATABASE:_RegisterTemplates()
self.Navpoints[CoalitionName][nav_ind]['point']['y'] = 0 self.Navpoints[CoalitionName][nav_ind]['point']['y'] = 0
self.Navpoints[CoalitionName][nav_ind]['point']['z'] = nav_data.y self.Navpoints[CoalitionName][nav_ind]['point']['z'] = nav_data.y
end end
end
end end
end
------------------------------------------------- -------------------------------------------------
if coa_data.country then --there is a country table if coa_data.country then --there is a country table
for cntry_id, cntry_data in pairs(coa_data.country) do for cntry_id, cntry_data in pairs(coa_data.country) do
@@ -1094,11 +1251,6 @@ function DATABASE:_RegisterTemplates()
end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then
end --for coa_name, coa_data in pairs(mission.coalition) do end --for coa_name, coa_data in pairs(mission.coalition) do
for ZoneID, ZoneData in pairs( env.mission.triggers.zones ) do
local ZoneName = ZoneData.name
self.ZONENAMES[ZoneName] = ZoneName
end
return self return self
end end

View File

@@ -1,7 +1,5 @@
--- **Core** -- EVENT models DCS **event dispatching** using a **publish-subscribe** model. --- **Core** -- EVENT models DCS **event dispatching** using a **publish-subscribe** model.
-- --
-- ![Banner Image](..\Presentations\EVENT\Dia1.JPG)
--
-- === -- ===
-- --
-- # 1) Event Handling Overview -- # 1) Event Handling Overview
@@ -61,8 +59,8 @@
-- So, when the DCS event occurs, the class will be notified of that event. -- So, when the DCS event occurs, the class will be notified of that event.
-- There are two functions which you use to subscribe to or unsubscribe from an event. -- There are two functions which you use to subscribe to or unsubscribe from an event.
-- --
-- * @{Base#BASE.HandleEvent}(): Subscribe to a DCS Event. -- * @{Core.Base#BASE.HandleEvent}(): Subscribe to a DCS Event.
-- * @{Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event. -- * @{Core.Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
-- --
-- Note that for a UNIT, the event will be handled **for that UNIT only**! -- Note that for a UNIT, the event will be handled **for that UNIT only**!
-- Note that for a GROUP, the event will be handled **for all the UNITs in that GROUP only**! -- Note that for a GROUP, the event will be handled **for all the UNITs in that GROUP only**!
@@ -74,7 +72,7 @@
-- ### 1.3.2 Event Handling of DCS Events -- ### 1.3.2 Event Handling of DCS Events
-- --
-- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called -- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called
-- when the DCS event occurs. The Event Handling method receives an @{Event#EVENTDATA} structure, which contains a lot of information -- when the DCS event occurs. The Event Handling method receives an @{Core.Event#EVENTDATA} structure, which contains a lot of information
-- about the event that occurred. -- about the event that occurred.
-- --
-- Find below an example of the prototype how to write an event handling function for two units: -- Find below an example of the prototype how to write an event handling function for two units:
@@ -112,11 +110,11 @@
-- # 2) EVENTS type -- # 2) EVENTS type
-- --
-- The EVENTS structure contains names for all the different DCS events that objects can subscribe to using the -- The EVENTS structure contains names for all the different DCS events that objects can subscribe to using the
-- @{Base#BASE.HandleEvent}() method. -- @{Core.Base#BASE.HandleEvent}() method.
-- --
-- # 3) EVENTDATA type -- # 3) EVENTDATA type
-- --
-- The @{Event#EVENTDATA} structure contains all the fields that are populated with event information before -- The @{Core.Event#EVENTDATA} structure contains all the fields that are populated with event information before
-- an Event Handler method is being called by the event dispatcher. -- an Event Handler method is being called by the event dispatcher.
-- The Event Handler received the EVENTDATA object as a parameter, and can be used to investigate further the different events. -- The Event Handler received the EVENTDATA object as a parameter, and can be used to investigate further the different events.
-- There are basically 4 main categories of information stored in the EVENTDATA structure: -- There are basically 4 main categories of information stored in the EVENTDATA structure:
@@ -164,23 +162,28 @@
-- --
-- === -- ===
-- --
-- @module Event -- @module Core.Event
-- @image Core_Event.JPG
--- The EVENT structure --- The EVENT structure
--
-- @type EVENT -- @type EVENT
-- @field #EVENT.Events Events -- @field #EVENT.Events Events
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
EVENT = { EVENT = {
ClassName = "EVENT", ClassName = "EVENT",
ClassID = 0, ClassID = 0,
MissionEnd = false,
} }
world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000 world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000
world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001 world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001
world.event.S_EVENT_NEW_ZONE = world.event.S_EVENT_MAX + 1002
world.event.S_EVENT_DELETE_ZONE = world.event.S_EVENT_MAX + 1003
--- The different types of events supported by MOOSE. --- The different types of events supported by MOOSE.
-- Use this structure to subscribe to events using the @{Base#BASE.HandleEvent}() method. -- Use this structure to subscribe to events using the @{Core.Base#BASE.HandleEvent}() method.
-- @type EVENTS -- @type EVENTS
EVENTS = { EVENTS = {
Shot = world.event.S_EVENT_SHOT, Shot = world.event.S_EVENT_SHOT,
@@ -209,9 +212,10 @@ EVENTS = {
MarkAdded = world.event.S_EVENT_MARK_ADDED, MarkAdded = world.event.S_EVENT_MARK_ADDED,
MarkChange = world.event.S_EVENT_MARK_CHANGE, MarkChange = world.event.S_EVENT_MARK_CHANGE,
MarkRemoved = world.event.S_EVENT_MARK_REMOVED, MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
NewCargo = world.event.S_EVENT_NEW_CARGO, NewCargo = world.event.S_EVENT_NEW_CARGO,
DeleteCargo = world.event.S_EVENT_DELETE_CARGO, DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
NewZone = world.event.S_EVENT_NEW_ZONE,
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
} }
--- The Event structure --- The Event structure
@@ -223,34 +227,34 @@ EVENTS = {
-- @type EVENTDATA -- @type EVENTDATA
-- @field #number id The identifier of the event. -- @field #number id The identifier of the event.
-- --
-- @field Dcs.DCSUnit#Unit initiator (UNIT/STATIC/SCENERY) The initiating @{Dcs.DCSUnit#Unit} or @{Dcs.DCSStaticObject#StaticObject}. -- @field DCS#Unit initiator (UNIT/STATIC/SCENERY) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
-- @field Dcs.DCSObject#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ). -- @field DCS#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ).
-- @field Dcs.DCSUnit#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCSUnit#Unit} or @{DCSStaticObject#StaticObject}. -- @field DCS#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
-- @field #string IniDCSUnitName (UNIT/STATIC) The initiating Unit name. -- @field #string IniDCSUnitName (UNIT/STATIC) The initiating Unit name.
-- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Unit#UNIT} of the initiator Unit object. -- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Wrapper.Unit#UNIT} of the initiator Unit object.
-- @field #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName). -- @field #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName).
-- @field Dcs.DCSGroup#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}. -- @field DCS#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}.
-- @field #string IniDCSGroupName (UNIT) The initiating Group name. -- @field #string IniDCSGroupName (UNIT) The initiating Group name.
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Group#GROUP} of the initiator Group object. -- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName). -- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot. -- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
-- @field Dcs.DCScoalition#coalition.side IniCoalition (UNIT) The coalition of the initiator. -- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator.
-- @field Dcs.DCSUnit#Unit.Category IniCategory (UNIT) The category of the initiator. -- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
-- @field #string IniTypeName (UNIT) The type name of the initiator. -- @field #string IniTypeName (UNIT) The type name of the initiator.
-- --
-- @field Dcs.DCSUnit#Unit target (UNIT/STATIC) The target @{Dcs.DCSUnit#Unit} or @{DCSStaticObject#StaticObject}. -- @field DCS#Unit target (UNIT/STATIC) The target @{DCS#Unit} or @{DCS#StaticObject}.
-- @field Dcs.DCSObject#Object.Category TgtObjectCategory (UNIT/STATIC) The target object category ( Object.Category.UNIT or Object.Category.STATIC ). -- @field DCS#Object.Category TgtObjectCategory (UNIT/STATIC) The target object category ( Object.Category.UNIT or Object.Category.STATIC ).
-- @field Dcs.DCSUnit#Unit TgtDCSUnit (UNIT/STATIC) The target @{DCSUnit#Unit} or @{DCSStaticObject#StaticObject}. -- @field DCS#Unit TgtDCSUnit (UNIT/STATIC) The target @{DCS#Unit} or @{DCS#StaticObject}.
-- @field #string TgtDCSUnitName (UNIT/STATIC) The target Unit name. -- @field #string TgtDCSUnitName (UNIT/STATIC) The target Unit name.
-- @field Wrapper.Unit#UNIT TgtUnit (UNIT/STATIC) The target MOOSE wrapper @{Unit#UNIT} of the target Unit object. -- @field Wrapper.Unit#UNIT TgtUnit (UNIT/STATIC) The target MOOSE wrapper @{Wrapper.Unit#UNIT} of the target Unit object.
-- @field #string TgtUnitName (UNIT/STATIC) The target UNIT name (same as TgtDCSUnitName). -- @field #string TgtUnitName (UNIT/STATIC) The target UNIT name (same as TgtDCSUnitName).
-- @field Dcs.DCSGroup#Group TgtDCSGroup (UNIT) The target {DCSGroup#Group}. -- @field DCS#Group TgtDCSGroup (UNIT) The target {DCSGroup#Group}.
-- @field #string TgtDCSGroupName (UNIT) The target Group name. -- @field #string TgtDCSGroupName (UNIT) The target Group name.
-- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Group#GROUP} of the target Group object. -- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object.
-- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName). -- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName).
-- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot. -- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot.
-- @field Dcs.DCScoalition#coalition.side TgtCoalition (UNIT) The coalition of the target. -- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target.
-- @field Dcs.DCSUnit#Unit.Category TgtCategory (UNIT) The category of the target. -- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target.
-- @field #string TgtTypeName (UNIT) The type name of the target. -- @field #string TgtTypeName (UNIT) The type name of the target.
-- --
-- @field weapon The weapon used during the event. -- @field weapon The weapon used during the event.
@@ -427,6 +431,16 @@ local _EVENTMETA = {
Event = "OnEventDeleteCargo", Event = "OnEventDeleteCargo",
Text = "S_EVENT_DELETE_CARGO" Text = "S_EVENT_DELETE_CARGO"
}, },
[EVENTS.NewZone] = {
Order = 1,
Event = "OnEventNewZone",
Text = "S_EVENT_NEW_ZONE"
},
[EVENTS.DeleteZone] = {
Order = 1,
Event = "OnEventDeleteZone",
Text = "S_EVENT_DELETE_ZONE"
},
} }
@@ -444,7 +458,7 @@ end
--- Initializes the Events structure for the event --- Initializes the Events structure for the event
-- @param #EVENT self -- @param #EVENT self
-- @param Dcs.DCSWorld#world.event EventID -- @param DCS#world.event EventID
-- @param Core.Base#BASE EventClass -- @param Core.Base#BASE EventClass
-- @return #EVENT.Events -- @return #EVENT.Events
function EVENT:Init( EventID, EventClass ) function EVENT:Init( EventID, EventClass )
@@ -470,7 +484,7 @@ end
--- Removes a subscription --- Removes a subscription
-- @param #EVENT self -- @param #EVENT self
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is. -- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID -- @param DCS#world.event EventID
-- @return #EVENT.Events -- @return #EVENT.Events
function EVENT:RemoveEvent( EventClass, EventID ) function EVENT:RemoveEvent( EventClass, EventID )
@@ -490,7 +504,7 @@ end
--- Resets subscriptions --- Resets subscriptions
-- @param #EVENT self -- @param #EVENT self
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is. -- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID -- @param DCS#world.event EventID
-- @return #EVENT.Events -- @return #EVENT.Events
function EVENT:Reset( EventObject ) --R2.1 function EVENT:Reset( EventObject ) --R2.1
@@ -513,7 +527,7 @@ end
--- Clears all event subscriptions for a @{Base#BASE} derived object. --- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
-- @param #EVENT self -- @param #EVENT self
-- @param Core.Base#BASE EventObject -- @param Core.Base#BASE EventObject
function EVENT:RemoveAll( EventObject ) function EVENT:RemoveAll( EventObject )
@@ -731,6 +745,36 @@ do -- Event Creation
world.onEvent( Event ) world.onEvent( Event )
end end
--- Creation of a New Zone Event.
-- @param #EVENT self
-- @param Core.Zone#ZONE_BASE Zone The Zone created.
function EVENT:CreateEventNewZone( Zone )
self:F( { Zone } )
local Event = {
id = EVENTS.NewZone,
time = timer.getTime(),
zone = Zone,
}
world.onEvent( Event )
end
--- Creation of a Zone Deletion Event.
-- @param #EVENT self
-- @param Core.Zone#ZONE_BASE Zone The Zone created.
function EVENT:CreateEventDeleteZone( Zone )
self:F( { Zone } )
local Event = {
id = EVENTS.DeleteZone,
time = timer.getTime(),
zone = Zone,
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event. --- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
-- @param #EVENT self -- @param #EVENT self
-- @param Wrapper.Unit#UNIT PlayerUnit. -- @param Wrapper.Unit#UNIT PlayerUnit.
@@ -770,8 +814,13 @@ function EVENT:onEvent( Event )
if self and if self and
self.Events and self.Events and
self.Events[Event.id] and self.Events[Event.id] and
self.MissionEnd == false and
( Event.initiator ~= nil or ( Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit ) ) then ( Event.initiator ~= nil or ( Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit ) ) then
if Event.id and Event.id == EVENTS.MissionEnd then
self.MissionEnd = true
end
if Event.initiator then if Event.initiator then
Event.IniObjectCategory = Event.initiator:getCategory() Event.IniObjectCategory = Event.initiator:getCategory()
@@ -810,6 +859,16 @@ function EVENT:onEvent( Event )
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end end
if Event.IniObjectCategory == Object.Category.CARGO then
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end
if Event.IniObjectCategory == Object.Category.SCENERY then if Event.IniObjectCategory == Object.Category.SCENERY then
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
@@ -874,11 +933,28 @@ function EVENT:onEvent( Event )
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName() Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget() --Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end end
-- @FC: something like this should be added.
--[[
if Event.idx then
Event.MarkID=Event.idx
Event.MarkVec3=Event.pos
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
Event.MarkText=Event.text
Event.MarkCoalition=Event.coalition
Event.MarkGroupID = Event.groupID
end
]]
if Event.cargo then if Event.cargo then
Event.Cargo = Event.cargo Event.Cargo = Event.cargo
Event.CargoName = Event.cargo.Name Event.CargoName = Event.cargo.Name
end end
if Event.zone then
Event.Zone = Event.zone
Event.ZoneName = Event.zone.ZoneName
end
local PriorityOrder = EventMeta.Order local PriorityOrder = EventMeta.Order
local PriorityBegin = PriorityOrder == -1 and 5 or 1 local PriorityBegin = PriorityOrder == -1 and 5 or 1
@@ -894,7 +970,7 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called. -- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
--if Event.IniObjectCategory ~= Object.Category.STATIC then --if Event.IniObjectCategory ~= Object.Category.STATIC then
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } ) -- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
--end --end
@@ -1043,6 +1119,16 @@ function EVENT:onEvent( Event )
end end
end end
end end
-- When cargo was deleted, it may probably be because of an S_EVENT_DEAD.
-- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call.
-- And this is a problem because it will remove all entries from the SET_CARGOs.
-- To prevent this from happening, the Cargo object has a flag NoDestroy.
-- When true, the SET_CARGO won't Remove the Cargo object from the set.
-- But we need to switch that flag off after the event handlers have been called.
if Event.id == EVENTS.DeleteCargo then
Event.Cargo.NoDestroy = nil
end
else else
self:T( { EventMeta.Text, Event } ) self:T( { EventMeta.Text, Event } )
end end

View File

@@ -1,8 +1,6 @@
--- **Core** -- The **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes --- **Core** -- The **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes
-- are design patterns allowing efficient (long-lasting) processes and workflows. -- are design patterns allowing efficient (long-lasting) processes and workflows.
-- --
-- ![Banner Image](..\Presentations\FSM\Dia1.JPG)
--
-- === -- ===
-- --
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**. -- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
@@ -52,7 +50,7 @@
-- --
-- * @{#FSM_TASK}: Models Finite State Machines for @{Task}s. -- * @{#FSM_TASK}: Models Finite State Machines for @{Task}s.
-- * @{#FSM_PROCESS}: Models Finite State Machines for @{Task} actions, which control @{Client}s. -- * @{#FSM_PROCESS}: Models Finite State Machines for @{Task} actions, which control @{Client}s.
-- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Controllable}s, which are @{Group}s, @{Unit}s, @{Client}s. -- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s.
-- * @{#FSM_SET}: Models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here -- * @{#FSM_SET}: Models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
-- for multiple objects or the position of the state machine in the process. -- for multiple objects or the position of the state machine in the process.
-- --
@@ -64,7 +62,8 @@
-- --
-- === -- ===
-- --
-- @module Fsm -- @module Core.Fsm
-- @image Core_Finite_State_Machine.JPG
do -- FSM do -- FSM
@@ -72,9 +71,7 @@ do -- FSM
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # FSM class, extends @{Base#BASE} --- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
--
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
-- --
-- A FSM can only be in one of a finite number of states. -- A FSM can only be in one of a finite number of states.
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**. -- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
@@ -337,7 +334,7 @@ do -- FSM
--- Creates a new FSM object. --- Creates a new FSM object.
-- @param #FSM self -- @param #FSM self
-- @return #FSM -- @return #FSM
function FSM:New( FsmT ) function FSM:New()
-- Inherits from BASE -- Inherits from BASE
self = BASE:Inherit( self, BASE:New() ) self = BASE:Inherit( self, BASE:New() )
@@ -410,7 +407,7 @@ do -- FSM
return self._Transitions or {} return self._Transitions or {}
end end
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task. --- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Wrapper.Controllable} by the task.
-- @param #FSM self -- @param #FSM self
-- @param #table From Can contain a string indicating the From state or a table of strings containing multiple From states. -- @param #table From Can contain a string indicating the From state or a table of strings containing multiple From states.
-- @param #string Event The Event name. -- @param #string Event The Event name.
@@ -441,6 +438,8 @@ do -- FSM
-- @return #table -- @return #table
function FSM:GetProcesses() function FSM:GetProcesses()
self:F( { Processes = self._Processes } )
return self._Processes or {} return self._Processes or {}
end end
@@ -455,6 +454,18 @@ do -- FSM
error( "Sub-Process from state " .. From .. " with event " .. Event .. " not found!" ) error( "Sub-Process from state " .. From .. " with event " .. Event .. " not found!" )
end end
function FSM:SetProcess( From, Event, Fsm )
for ProcessID, Process in pairs( self:GetProcesses() ) do
if Process.From == From and Process.Event == Event then
Process.fsm = Fsm
return true
end
end
error( "Sub-Process from state " .. From .. " with event " .. Event .. " not found!" )
end
--- Adds an End state. --- Adds an End state.
function FSM:AddEndState( State ) function FSM:AddEndState( State )
@@ -557,8 +568,9 @@ do -- FSM
end end
function FSM:_call_handler( handler, params, EventName ) function FSM:_call_handler( step, trigger, params, EventName )
local handler = step .. trigger
local ErrorHandler = function( errmsg ) local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg ) env.info( "Error in SCHEDULER function:" .. errmsg )
@@ -569,83 +581,117 @@ do -- FSM
return errmsg return errmsg
end end
if self[handler] then if self[handler] then
self:T2( "Calling " .. handler ) self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] )
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler ) local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
return Value return Value
end end
end end
--- @param #FSM self
function FSM._handler( self, EventName, ... ) function FSM._handler( self, EventName, ... )
local Can, to = self:can( EventName ) local Can, To = self:can( EventName )
if to == "*" then if To == "*" then
to = self.current To = self.current
end end
if Can then if Can then
local from = self.current local From = self.current
local params = { from, EventName, to, ... } local Params = { From, EventName, To, ... }
if self.Controllable then
self:T( "FSM Transition for " .. self.Controllable.ControllableName .. " :" .. self.current .. " --> " .. EventName .. " --> " .. to ) if self["onleave".. From] or
self["OnLeave".. From] or
self["onbefore".. EventName] or
self["OnBefore".. EventName] or
self["onafter".. EventName] or
self["OnAfter".. EventName] or
self["onenter".. To] or
self["OnEnter".. To]
then
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
return false
else
if self:_call_handler( "OnBefore", EventName, Params, EventName ) == false then
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** OnBefore" .. EventName )
return false
else
if self:_call_handler( "onleave", From, Params, EventName ) == false then
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onleave" .. From )
return false
else
if self:_call_handler( "OnLeave", From, Params, EventName ) == false then
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** OnLeave" .. From )
return false
end
end
end
end
else else
self:T( "FSM Transition:" .. self.current .. " --> " .. EventName .. " --> " .. to ) local ClassName = self:GetClassName()
end if ClassName == "FSM" then
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
end
if ( self:_call_handler("onbefore" .. EventName, params, EventName ) == false ) if ClassName == "FSM_TASK" then
or ( self:_call_handler("OnBefore" .. EventName, params, EventName ) == false ) self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** Task: " .. self.TaskName )
or ( self:_call_handler("onleave" .. from, params, EventName ) == false ) end
or ( self:_call_handler("OnLeave" .. from, params, EventName ) == false ) then
self:T( "Cancel Transition" ) if ClassName == "FSM_CONTROLLABLE" then
return false self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** TaskUnit: " .. self.Controllable.ControllableName .. " *** " )
end
if ClassName == "FSM_PROCESS" then
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** Task: " .. self.Task:GetName() .. ", TaskUnit: " .. self.Controllable.ControllableName .. " *** " )
end
end end
self.current = to self.current = To
local execute = true local execute = true
local subtable = self:_gosub( from, EventName ) local subtable = self:_gosub( From, EventName )
for _, sub in pairs( subtable ) do for _, sub in pairs( subtable ) do
--if sub.nextevent then --if sub.nextevent then
-- self:F2( "nextevent = " .. sub.nextevent ) -- self:F2( "nextevent = " .. sub.nextevent )
-- self[sub.nextevent]( self ) -- self[sub.nextevent]( self )
--end --end
self:T( "calling sub start event: " .. sub.StartEvent ) self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
sub.fsm.fsmparent = self sub.fsm.fsmparent = self
sub.fsm.ReturnEvents = sub.ReturnEvents sub.fsm.ReturnEvents = sub.ReturnEvents
sub.fsm[sub.StartEvent]( sub.fsm ) sub.fsm[sub.StartEvent]( sub.fsm )
execute = false execute = false
end end
local fsmparent, Event = self:_isendstate( to ) local fsmparent, Event = self:_isendstate( To )
if fsmparent and Event then if fsmparent and Event then
self:F2( { "end state: ", fsmparent, Event } ) self:T( "*** FSM *** End *** " .. Event )
self:_call_handler("onenter" .. to, params, EventName ) self:_call_handler("onenter", To, Params, EventName )
self:_call_handler("OnEnter" .. to, params, EventName ) self:_call_handler("OnEnter", To, Params, EventName )
self:_call_handler("onafter" .. EventName, params, EventName ) self:_call_handler("onafter", EventName, Params, EventName )
self:_call_handler("OnAfter" .. EventName, params, EventName ) self:_call_handler("OnAfter", EventName, Params, EventName )
self:_call_handler("onstatechange", params, EventName ) self:_call_handler("onstate", "change", Params, EventName )
fsmparent[Event]( fsmparent ) fsmparent[Event]( fsmparent )
execute = false execute = false
end end
if execute then if execute then
self:_call_handler("onafter", EventName, Params, EventName )
self:_call_handler("OnAfter", EventName, Params, EventName )
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute! -- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute!
--if from ~= to then --if from ~= to then
self:_call_handler("onenter" .. to, params, EventName ) self:_call_handler("onenter", To, Params, EventName )
self:_call_handler("OnEnter" .. to, params, EventName ) self:_call_handler("OnEnter", To, Params, EventName )
--end --end
self:_call_handler("onafter" .. EventName, params, EventName ) self:_call_handler("onstate", "change", Params, EventName )
self:_call_handler("OnAfter" .. EventName, params, EventName )
self:_call_handler("onstatechange", params, EventName )
end end
else else
self:T( "Cannot execute transition." ) self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
self:T( { From = self.current, Event = EventName, To = to, Can = Can } )
end end
return nil return nil
@@ -691,17 +737,16 @@ do -- FSM
function FSM:_isendstate( Current ) function FSM:_isendstate( Current )
local FSMParent = self.fsmparent local FSMParent = self.fsmparent
if FSMParent and self.endstates[Current] then if FSMParent and self.endstates[Current] then
self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } ) --self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
FSMParent.current = Current FSMParent.current = Current
local ParentFrom = FSMParent.current local ParentFrom = FSMParent.current
self:T( ParentFrom ) --self:T( { ParentFrom, self.ReturnEvents } )
self:T( self.ReturnEvents )
local Event = self.ReturnEvents[Current] local Event = self.ReturnEvents[Current]
self:T( { ParentFrom, Event, self.ReturnEvents } ) --self:T( { Event } )
if Event then if Event then
return FSMParent, Event return FSMParent, Event
else else
self:T( { "Could not find parent event name for state ", ParentFrom } ) --self:T( { "Could not find parent event name for state ", ParentFrom } )
end end
end end
@@ -724,6 +769,10 @@ do -- FSM
return self.current return self.current
end end
function FSM:GetCurrentState()
return self.current
end
function FSM:Is( State ) function FSM:Is( State )
return self.current == State return self.current == State
@@ -752,9 +801,7 @@ do -- FSM_CONTROLLABLE
-- @field Wrapper.Controllable#CONTROLLABLE Controllable -- @field Wrapper.Controllable#CONTROLLABLE Controllable
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- # FSM_CONTROLLABLE, extends @{#FSM} --- Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s.
--
-- FSM_CONTROLLABLE class models Finite State Machines for @{Controllable}s, which are @{Group}s, @{Unit}s, @{Client}s.
-- --
-- === -- ===
-- --
@@ -769,10 +816,10 @@ do -- FSM_CONTROLLABLE
-- @param #table FSMT Finite State Machine Table -- @param #table FSMT Finite State Machine Table
-- @param Wrapper.Controllable#CONTROLLABLE Controllable (optional) The CONTROLLABLE object that the FSM_CONTROLLABLE governs. -- @param Wrapper.Controllable#CONTROLLABLE Controllable (optional) The CONTROLLABLE object that the FSM_CONTROLLABLE governs.
-- @return #FSM_CONTROLLABLE -- @return #FSM_CONTROLLABLE
function FSM_CONTROLLABLE:New( FSMT, Controllable ) function FSM_CONTROLLABLE:New( Controllable )
-- Inherits from BASE -- Inherits from BASE
local self = BASE:Inherit( self, FSM:New( FSMT ) ) -- Core.Fsm#FSM_CONTROLLABLE local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_CONTROLLABLE
if Controllable then if Controllable then
self:SetControllable( Controllable ) self:SetControllable( Controllable )
@@ -855,7 +902,9 @@ do -- FSM_CONTROLLABLE
return self.Controllable return self.Controllable
end end
function FSM_CONTROLLABLE:_call_handler( handler, params, EventName ) function FSM_CONTROLLABLE:_call_handler( step, trigger, params, EventName )
local handler = step .. trigger
local ErrorHandler = function( errmsg ) local ErrorHandler = function( errmsg )
@@ -868,7 +917,7 @@ do -- FSM_CONTROLLABLE
end end
if self[handler] then if self[handler] then
self:F3( "Calling " .. handler ) self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] .. " *** TaskUnit: " .. self.Controllable:GetName() )
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler ) local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler )
return Value return Value
@@ -885,9 +934,7 @@ do -- FSM_PROCESS
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--- # FSM_PROCESS, extends @{#FSM} --- FSM_PROCESS class models Finite State Machines for @{Task} actions, which control @{Client}s.
--
-- FSM_PROCESS class models Finite State Machines for @{Task} actions, which control @{Client}s.
-- --
-- === -- ===
-- --
@@ -905,9 +952,9 @@ do -- FSM_PROCESS
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_PROCESS local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_PROCESS
--self:F( Controllable ) --self:F( Controllable )
self:Assign( Controllable, Task ) self:Assign( Controllable, Task )
return self return self
end end
@@ -915,7 +962,9 @@ do -- FSM_PROCESS
self:T( "No Initialisation" ) self:T( "No Initialisation" )
end end
function FSM_PROCESS:_call_handler( handler, params, EventName ) function FSM_PROCESS:_call_handler( step, trigger, params, EventName )
local handler = step .. trigger
local ErrorHandler = function( errmsg ) local ErrorHandler = function( errmsg )
@@ -928,9 +977,13 @@ do -- FSM_PROCESS
end end
if self[handler] then if self[handler] then
self:F3( "Calling " .. handler ) if handler ~= "onstatechange" then
self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] .. " *** Task: " .. self.Task:GetName() .. ", TaskUnit: " .. self.Controllable:GetName() )
end
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler ) if self.Controllable and self.Controllable:IsAlive() == true then
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
end
return Value return Value
--return self[handler]( self, self.Controllable, unpack( params ) ) --return self[handler]( self, self.Controllable, unpack( params ) )
end end
@@ -946,7 +999,7 @@ do -- FSM_PROCESS
local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS
NewFsm:Assign( Controllable, Task ) NewFsm:Assign( Controllable, Task )
-- Polymorphic call to initialize the new FSM_PROCESS based on self FSM_PROCESS -- Polymorphic call to initialize the new FSM_PROCESS based on self FSM_PROCESS
NewFsm:Init( self ) NewFsm:Init( self )
@@ -1037,26 +1090,26 @@ do -- FSM_PROCESS
-- TODO: Need to check and fix that an FSM_PROCESS is only for a UNIT. Not for a GROUP. -- TODO: Need to check and fix that an FSM_PROCESS is only for a UNIT. Not for a GROUP.
--- Send a message of the @{Task} to the Group of the Unit. --- Send a message of the @{Task} to the Group of the Unit.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
function FSM_PROCESS:Message( Message ) function FSM_PROCESS:Message( Message )
self:F( { Message = Message } ) self:F( { Message = Message } )
local CC = self:GetCommandCenter()
local TaskGroup = self.Controllable:GetGroup()
local PlayerName = self.Controllable:GetPlayerName() -- Only for a unit local CC = self:GetCommandCenter()
PlayerName = PlayerName and " (" .. PlayerName .. ")" or "" -- If PlayerName is nil, then keep it nil, otherwise add brackets. local TaskGroup = self.Controllable:GetGroup()
local Callsign = self.Controllable:GetCallsign()
local Prefix = Callsign and " @ " .. Callsign .. PlayerName or "" local PlayerName = self.Controllable:GetPlayerName() -- Only for a unit
PlayerName = PlayerName and " (" .. PlayerName .. ")" or "" -- If PlayerName is nil, then keep it nil, otherwise add brackets.
Message = Prefix .. ": " .. Message local Callsign = self.Controllable:GetCallsign()
CC:MessageToGroup( Message, TaskGroup ) local Prefix = Callsign and " @ " .. Callsign .. PlayerName or ""
end
Message = Prefix .. ": " .. Message
CC:MessageToGroup( Message, TaskGroup )
end
--- Assign the process to a @{Unit} and activate the process. --- Assign the process to a @{Wrapper.Unit} and activate the process.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
-- @param Task.Tasking#TASK Task -- @param Task.Tasking#TASK Task
-- @param Wrapper.Unit#UNIT ProcessUnit -- @param Wrapper.Unit#UNIT ProcessUnit
@@ -1072,14 +1125,16 @@ end
return self return self
end end
function FSM_PROCESS:onenterAssigned( ProcessUnit ) -- function FSM_PROCESS:onenterAssigned( ProcessUnit, Task, From, Event, To )
self:T( "Assign" ) --
-- if From( "Planned" ) then
-- self:T( "*** FSM *** Assign *** " .. Task:GetName() .. "/" .. ProcessUnit:GetName() .. " *** " .. From .. " --> " .. Event .. " --> " .. To )
-- self.Task:Assign()
-- end
-- end
self.Task:Assign() function FSM_PROCESS:onenterFailed( ProcessUnit, Task, From, Event, To )
end self:T( "*** FSM *** Failed *** " .. Task:GetName() .. "/" .. ProcessUnit:GetName() .. " *** " .. From .. " --> " .. Event .. " --> " .. To )
function FSM_PROCESS:onenterFailed( ProcessUnit )
self:T( "Failed" )
self.Task:Fail() self.Task:Fail()
end end
@@ -1091,14 +1146,17 @@ end
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
function FSM_PROCESS:onstatechange( ProcessUnit, Task, From, Event, To, Dummy ) function FSM_PROCESS:onstatechange( ProcessUnit, Task, From, Event, To )
self:T( { ProcessUnit:GetName(), From, Event, To, Dummy, self:IsTrace() } )
if self:IsTrace() then if From ~= To then
--MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll() self:T( "*** FSM *** Change *** " .. Task:GetName() .. "/" .. ProcessUnit:GetName() .. " *** " .. From .. " --> " .. Event .. " --> " .. To )
end end
self:T( { Scores = self._Scores, To = To } ) -- if self:IsTrace() then
-- MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
-- self:F2( { Scores = self._Scores, To = To } )
-- end
-- TODO: This needs to be reworked with a callback functions allocated within Task, and set within the mission script from the Task Objects... -- TODO: This needs to be reworked with a callback functions allocated within Task, and set within the mission script from the Task Objects...
if self._Scores[To] then if self._Scores[To] then
@@ -1119,9 +1177,7 @@ do -- FSM_TASK
-- @field Tasking.Task#TASK Task -- @field Tasking.Task#TASK Task
-- @extends #FSM -- @extends #FSM
--- # FSM_TASK, extends @{#FSM} --- Models Finite State Machines for @{Tasking.Task}s.
--
-- FSM_TASK class models Finite State Machines for @{Task}s.
-- --
-- === -- ===
-- --
@@ -1133,22 +1189,23 @@ do -- FSM_TASK
--- Creates a new FSM_TASK object. --- Creates a new FSM_TASK object.
-- @param #FSM_TASK self -- @param #FSM_TASK self
-- @param #table FSMT -- @param #string TaskName The name of the task.
-- @param Tasking.Task#TASK Task
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #FSM_TASK -- @return #FSM_TASK
function FSM_TASK:New( FSMT ) function FSM_TASK:New( TaskName )
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( FSMT ) ) -- Core.Fsm#FSM_TASK local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_TASK
self["onstatechange"] = self.OnStateChange self["onstatechange"] = self.OnStateChange
self.TaskName = TaskName
return self return self
end end
function FSM_TASK:_call_handler( handler, params, EventName ) function FSM_TASK:_call_handler( step, trigger, params, EventName )
local handler = step .. trigger
if self[handler] then if self[handler] then
self:T( "Calling " .. handler ) self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] .. " *** Task: " .. self.TaskName )
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
return self[handler]( self, unpack( params ) ) return self[handler]( self, unpack( params ) )
end end
@@ -1164,9 +1221,7 @@ do -- FSM_SET
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- # FSM_SET, extends @{#FSM} --- FSM_SET class models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
--
-- FSM_SET class models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
-- for multiple objects or the position of the state machine in the process. -- for multiple objects or the position of the state machine in the process.
-- --
-- === -- ===
@@ -1210,9 +1265,10 @@ do -- FSM_SET
return self.Controllable return self.Controllable
end end
function FSM_SET:_call_handler( handler, params, EventName ) function FSM_SET:_call_handler( step, trigger, params, EventName )
local handler = step .. trigger
if self[handler] then if self[handler] then
self:T( "Calling " .. handler ) self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] )
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
return self[handler]( self, self.Set, unpack( params ) ) return self[handler]( self, self.Set, unpack( params ) )
end end

View File

@@ -10,7 +10,8 @@
-- --
-- === -- ===
-- --
-- @module Goal -- @module Core.Goal
-- @image Core_Goal.JPG
do -- Goal do -- Goal
@@ -18,9 +19,7 @@ do -- Goal
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- # GOAL class, extends @{Fsm#FSM} --- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
--
-- GOAL models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
-- --
-- ## 1. GOAL constructor -- ## 1. GOAL constructor
-- --

View File

@@ -13,15 +13,15 @@
-- --
-- ### To manage **main menus**, the classes begin with **MENU_**: -- ### To manage **main menus**, the classes begin with **MENU_**:
-- --
-- * @{Menu#MENU_MISSION}: Manages main menus for whole mission file. -- * @{Core.Menu#MENU_MISSION}: Manages main menus for whole mission file.
-- * @{Menu#MENU_COALITION}: Manages main menus for whole coalition. -- * @{Core.Menu#MENU_COALITION}: Manages main menus for whole coalition.
-- * @{Menu#MENU_GROUP}: Manages main menus for GROUPs. -- * @{Core.Menu#MENU_GROUP}: Manages main menus for GROUPs.
-- --
-- ### To manage **command menus**, which are menus that allow the player to issue **functions**, the classes begin with **MENU_COMMAND_**: -- ### To manage **command menus**, which are menus that allow the player to issue **functions**, the classes begin with **MENU_COMMAND_**:
-- --
-- * @{Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file. -- * @{Core.Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file.
-- * @{Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition. -- * @{Core.Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition.
-- * @{Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs. -- * @{Core.Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
-- --
-- === -- ===
--- ---
@@ -30,7 +30,8 @@
-- --
-- === -- ===
-- --
-- @module Menu -- @module Core.Menu
-- @image Core_Menu.JPG
MENU_INDEX = {} MENU_INDEX = {}
@@ -182,8 +183,7 @@ do -- MENU_BASE
--- @type MENU_BASE --- @type MENU_BASE
-- @extends Base#BASE -- @extends Base#BASE
--- # MENU_BASE class, extends @{Base#BASE} --- Defines the main MENU class where other MENU classes are derived from.
-- The MENU_BASE class defines the main MENU class where other MENU classes are derived from.
-- This is an abstract class, so don't use it. -- This is an abstract class, so don't use it.
-- @field #MENU_BASE -- @field #MENU_BASE
MENU_BASE = { MENU_BASE = {
@@ -213,6 +213,7 @@ do -- MENU_BASE
self.Menus = {} self.Menus = {}
self.MenuCount = 0 self.MenuCount = 0
self.MenuTime = timer.getTime() self.MenuTime = timer.getTime()
self.MenuRemoveParent = false
if self.ParentMenu then if self.ParentMenu then
self.ParentMenu.Menus = self.ParentMenu.Menus or {} self.ParentMenu.Menus = self.ParentMenu.Menus or {}
@@ -226,14 +227,30 @@ do -- MENU_BASE
if self.ParentMenu then if self.ParentMenu then
self.ParentMenu.Menus = self.ParentMenu.Menus or {} self.ParentMenu.Menus = self.ParentMenu.Menus or {}
self.ParentMenu.Menus[MenuText] = Menu self.ParentMenu.Menus[MenuText] = Menu
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
end end
end end
function MENU_BASE:ClearParentMenu( MenuText ) function MENU_BASE:ClearParentMenu( MenuText )
if self.ParentMenu and self.ParentMenu.Menus[MenuText] then if self.ParentMenu and self.ParentMenu.Menus[MenuText] then
self.ParentMenu.Menus[MenuText] = nil self.ParentMenu.Menus[MenuText] = nil
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
--self.ParentMenu:Remove()
end
end end
end end
--- Sets a @{Menu} to remove automatically the parent menu when the menu removed is the last child menu of that parent @{Menu}.
-- @param #MENU_BASE self
-- @param #boolean RemoveParent If true, the parent menu is automatically removed when this menu is the last child menu of that parent @{Menu}.
-- @return #MENU_BASE
function MENU_BASE:SetRemoveParent( RemoveParent )
--self:F( { RemoveParent } )
self.MenuRemoveParent = RemoveParent
return self
end
--- Gets a @{Menu} from a parent @{Menu} --- Gets a @{Menu} from a parent @{Menu}
-- @param #MENU_BASE self -- @param #MENU_BASE self
@@ -269,9 +286,7 @@ do -- MENU_COMMAND_BASE
-- @field #function MenuCallHandler -- @field #function MenuCallHandler
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- # MENU_COMMAND_BASE class, extends @{Base#BASE} --- Defines the main MENU class where other MENU COMMAND_
-- ----------------------------------------------------------
-- The MENU_COMMAND_BASE class defines the main MENU class where other MENU COMMAND_
-- classes are derived from, in order to set commands. -- classes are derived from, in order to set commands.
-- --
-- @field #MENU_COMMAND_BASE -- @field #MENU_COMMAND_BASE
@@ -341,9 +356,8 @@ do -- MENU_MISSION
--- @type MENU_MISSION --- @type MENU_MISSION
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- # MENU_MISSION class, extends @{Menu#MENU_BASE} --- Manages the main menus for a complete mission.
-- --
-- The MENU_MISSION class manages the main menus for a complete mission.
-- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference. -- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}.
-- @field #MENU_MISSION -- @field #MENU_MISSION
@@ -438,9 +452,8 @@ do -- MENU_MISSION_COMMAND
--- @type MENU_MISSION_COMMAND --- @type MENU_MISSION_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_MISSION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE} --- Manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- --
-- The MENU_MISSION_COMMAND class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference. -- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}.
-- --
@@ -452,7 +465,7 @@ do -- MENU_MISSION_COMMAND
--- MENU_MISSION constructor. Creates a new radio command item for a complete mission file, which can invoke a function with parameters. --- MENU_MISSION constructor. Creates a new radio command item for a complete mission file, which can invoke a function with parameters.
-- @param #MENU_MISSION_COMMAND self -- @param #MENU_MISSION_COMMAND self
-- @param #string MenuText The text for the menu. -- @param #string MenuText The text for the menu.
-- @param Menu#MENU_MISSION ParentMenu The parent menu. -- @param Core.Menu#MENU_MISSION ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed. -- @param CommandMenuFunction A function that is called when the menu key is pressed.
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this. -- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
-- @return #MENU_MISSION_COMMAND self -- @return #MENU_MISSION_COMMAND self
@@ -525,9 +538,8 @@ do -- MENU_COALITION
--- @type MENU_COALITION --- @type MENU_COALITION
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- # MENU_COALITION class, extends @{Menu#MENU_BASE} --- Manages the main menus for @{DCS.coalition}s.
-- --
-- The @{Menu#MENU_COALITION} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference. -- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.
-- --
@@ -576,7 +588,7 @@ do -- MENU_COALITION
--- MENU_COALITION constructor. Creates a new MENU_COALITION object and creates the menu for a complete coalition. --- MENU_COALITION constructor. Creates a new MENU_COALITION object and creates the menu for a complete coalition.
-- @param #MENU_COALITION self -- @param #MENU_COALITION self
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu. -- @param DCS#coalition.side Coalition The coalition owning the menu.
-- @param #string MenuText The text for the menu. -- @param #string MenuText The text for the menu.
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other). -- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
-- @return #MENU_COALITION self -- @return #MENU_COALITION self
@@ -663,9 +675,8 @@ do -- MENU_COALITION_COMMAND
--- @type MENU_COALITION_COMMAND --- @type MENU_COALITION_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_COALITION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE} --- Manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- --
-- The MENU_COALITION_COMMAND class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference. -- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}.
-- --
@@ -676,9 +687,9 @@ do -- MENU_COALITION_COMMAND
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters. --- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
-- @param #MENU_COALITION_COMMAND self -- @param #MENU_COALITION_COMMAND self
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu. -- @param DCS#coalition.side Coalition The coalition owning the menu.
-- @param #string MenuText The text for the menu. -- @param #string MenuText The text for the menu.
-- @param Menu#MENU_COALITION ParentMenu The parent menu. -- @param Core.Menu#MENU_COALITION ParentMenu The parent menu.
-- @param CommandMenuFunction A function that is called when the menu key is pressed. -- @param CommandMenuFunction A function that is called when the menu key is pressed.
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this. -- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
-- @return #MENU_COALITION_COMMAND -- @return #MENU_COALITION_COMMAND
@@ -763,9 +774,8 @@ do
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- #MENU_GROUP class, extends @{Menu#MENU_BASE} --- Manages the main menus for @{Wrapper.Group}s.
-- --
-- The MENU_GROUP class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference. -- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
-- --
@@ -900,8 +910,8 @@ do
self:RemoveSubMenus( MenuTime, MenuTag ) self:RemoveSubMenus( MenuTime, MenuTag )
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuTime or self.MenuTime ~= MenuTime then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
missionCommands.removeItemForGroup( self.GroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.GroupID, self.MenuPath )
end end
MENU_INDEX:ClearGroupMenu( self.Group, Path ) MENU_INDEX:ClearGroupMenu( self.Group, Path )
@@ -921,9 +931,7 @@ do
--- @type MENU_GROUP_COMMAND --- @type MENU_GROUP_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_GROUP_COMMAND class, extends @{Menu#MENU_COMMAND_BASE} --- The @{Core.Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
--
-- The @{Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference. -- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}.
-- --
@@ -992,8 +1000,8 @@ do
if GroupMenu == self then if GroupMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuTime or self.MenuTime ~= MenuTime then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
missionCommands.removeItemForGroup( self.GroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.GroupID, self.MenuPath )
end end
MENU_INDEX:ClearGroupMenu( self.Group, Path ) MENU_INDEX:ClearGroupMenu( self.Group, Path )
@@ -1018,9 +1026,7 @@ do
-- @extends Core.Menu#MENU_BASE -- @extends Core.Menu#MENU_BASE
--- #MENU_GROUP_DELAYED class, extends @{Menu#MENU_BASE} --- The MENU_GROUP_DELAYED class manages the main menus for groups.
--
-- The MENU_GROUP_DELAYED class manages the main menus for groups.
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference. -- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
-- The creation of the menu item is delayed however, and must be created using the @{#MENU_GROUP.Set} method. -- The creation of the menu item is delayed however, and must be created using the @{#MENU_GROUP.Set} method.
@@ -1133,8 +1139,8 @@ do
self:RemoveSubMenus( MenuTime, MenuTag ) self:RemoveSubMenus( MenuTime, MenuTag )
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuTime or self.MenuTime ~= MenuTime then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
missionCommands.removeItemForGroup( self.GroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.GroupID, self.MenuPath )
end end
MENU_INDEX:ClearGroupMenu( self.Group, Path ) MENU_INDEX:ClearGroupMenu( self.Group, Path )
@@ -1154,9 +1160,8 @@ do
--- @type MENU_GROUP_COMMAND_DELAYED --- @type MENU_GROUP_COMMAND_DELAYED
-- @extends Core.Menu#MENU_COMMAND_BASE -- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_GROUP_COMMAND_DELAYED class, extends @{Menu#MENU_COMMAND_BASE} --- Manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- --
-- The @{Menu#MENU_GROUP_COMMAND_DELAYED} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_GROUP_COMMAND_DELAYED.New} method, which constructs a MENU_GROUP_COMMAND_DELAYED object and returns you the object reference. -- You can add menus with the @{#MENU_GROUP_COMMAND_DELAYED.New} method, which constructs a MENU_GROUP_COMMAND_DELAYED object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND_DELAYED.Remove}. -- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND_DELAYED.Remove}.
-- --
@@ -1244,8 +1249,8 @@ do
if GroupMenu == self then if GroupMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuTime or self.MenuTime ~= MenuTime then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
missionCommands.removeItemForGroup( self.GroupID, self.MenuPath ) missionCommands.removeItemForGroup( self.GroupID, self.MenuPath )
end end
MENU_INDEX:ClearGroupMenu( self.Group, Path ) MENU_INDEX:ClearGroupMenu( self.Group, Path )

View File

@@ -1,43 +1,40 @@
--- **Core** -- MESSAGE class takes are of the **real-time notifications** and **messages to players** during a simulation. --- **Core** -- MESSAGE class takes are of the **real-time notifications** and **messages to players** during a simulation.
-- --
-- ![Banner Image](..\Presentations\MESSAGE\Dia1.JPG)
--
-- === -- ===
-- --
-- @module Message -- @module Core.Message
-- @image Core_Message.JPG
--- The MESSAGE class --- The MESSAGE class
-- @type MESSAGE -- @type MESSAGE
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # MESSAGE class, extends @{Base#BASE} --- Message System to display Messages to Clients, Coalitions or All.
--
-- Message System to display Messages to Clients, Coalitions or All.
-- Messages are shown on the display panel for an amount of seconds, and will then disappear. -- Messages are shown on the display panel for an amount of seconds, and will then disappear.
-- Messages can contain a category which is indicating the category of the message. -- Messages can contain a category which is indicating the category of the message.
-- --
-- ## MESSAGE construction -- ## MESSAGE construction
-- --
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet. -- Messages are created with @{#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions. -- To send messages, you need to use the To functions.
-- --
-- ## Send messages to an audience -- ## Send messages to an audience
-- --
-- Messages are sent: -- Messages are sent:
-- --
-- * To a @{Client} using @{Message#MESSAGE.ToClient}(). -- * To a @{Client} using @{#MESSAGE.ToClient}().
-- * To a @{Group} using @{Message#MESSAGE.ToGroup}() -- * To a @{Wrapper.Group} using @{#MESSAGE.ToGroup}()
-- * To a coalition using @{Message#MESSAGE.ToCoalition}(). -- * To a coalition using @{#MESSAGE.ToCoalition}().
-- * To the red coalition using @{Message#MESSAGE.ToRed}(). -- * To the red coalition using @{#MESSAGE.ToRed}().
-- * To the blue coalition using @{Message#MESSAGE.ToBlue}(). -- * To the blue coalition using @{#MESSAGE.ToBlue}().
-- * To all Players using @{Message#MESSAGE.ToAll}(). -- * To all Players using @{#MESSAGE.ToAll}().
-- --
-- ## Send conditionally to an audience -- ## Send conditionally to an audience
-- --
-- Messages can be sent conditionally to an audience (when a condition is true): -- Messages can be sent conditionally to an audience (when a condition is true):
-- --
-- * To all players using @{Message#MESSAGE.ToAllIf}(). -- * To all players using @{#MESSAGE.ToAllIf}().
-- * To a coalition using @{Message#MESSAGE.ToCoalitionIf}(). -- * To a coalition using @{#MESSAGE.ToCoalitionIf}().
-- --
-- === -- ===
-- --
@@ -69,6 +66,7 @@ MESSAGE.Type = {
-- @param #string MessageText is the text of the Message. -- @param #string MessageText is the text of the Message.
-- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel. -- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel.
-- @param #string MessageCategory (optional) is a string expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ". -- @param #string MessageCategory (optional) is a string expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
-- @return #MESSAGE -- @return #MESSAGE
-- @usage -- @usage
-- -- Create a series of new Messages. -- -- Create a series of new Messages.
@@ -80,7 +78,7 @@ MESSAGE.Type = {
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" ) -- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" ) -- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score") -- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
function MESSAGE:New( MessageText, MessageDuration, MessageCategory ) function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self:F( { MessageText, MessageDuration, MessageCategory } ) self:F( { MessageText, MessageDuration, MessageCategory } )
@@ -97,6 +95,11 @@ function MESSAGE:New( MessageText, MessageDuration, MessageCategory )
else else
self.MessageCategory = "" self.MessageCategory = ""
end end
self.ClearScreen=false
if ClearScreen~=nil then
self.ClearScreen=ClearScreen
end
self.MessageDuration = MessageDuration or 5 self.MessageDuration = MessageDuration or 5
self.MessageTime = timer.getTime() self.MessageTime = timer.getTime()
@@ -117,18 +120,24 @@ end
-- @param self -- @param self
-- @param #string MessageText is the text of the Message. -- @param #string MessageText is the text of the Message.
-- @param #MESSAGE.Type MessageType The type of the message. -- @param #MESSAGE.Type MessageType The type of the message.
-- @param #boolean ClearScreen (optional) Clear all previous messages.
-- @return #MESSAGE -- @return #MESSAGE
-- @usage -- @usage
-- MessageAll = MESSAGE:NewType( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", MESSAGE.Type.Information ) -- MessageAll = MESSAGE:NewType( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", MESSAGE.Type.Information )
-- MessageRED = MESSAGE:NewType( "To the RED Players: You receive a penalty because you've killed one of your own units", MESSAGE.Type.Information ) -- MessageRED = MESSAGE:NewType( "To the RED Players: You receive a penalty because you've killed one of your own units", MESSAGE.Type.Information )
-- MessageClient1 = MESSAGE:NewType( "Congratulations, you've just hit a target", MESSAGE.Type.Update ) -- MessageClient1 = MESSAGE:NewType( "Congratulations, you've just hit a target", MESSAGE.Type.Update )
-- MessageClient2 = MESSAGE:NewType( "Congratulations, you've just killed a target", MESSAGE.Type.Update ) -- MessageClient2 = MESSAGE:NewType( "Congratulations, you've just killed a target", MESSAGE.Type.Update )
function MESSAGE:NewType( MessageText, MessageType ) function MESSAGE:NewType( MessageText, MessageType, ClearScreen )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
self:F( { MessageText } ) self:F( { MessageText } )
self.MessageType = MessageType self.MessageType = MessageType
self.ClearScreen=false
if ClearScreen~=nil then
self.ClearScreen=ClearScreen
end
self.MessageTime = timer.getTime() self.MessageTime = timer.getTime()
self.MessageText = MessageText:gsub("^\n","",1):gsub("\n$","",1) self.MessageText = MessageText:gsub("^\n","",1):gsub("\n$","",1)
@@ -138,6 +147,15 @@ end
--- Clears all previous messages from the screen before the new message is displayed. Not that this must come before all functions starting with ToX(), e.g. ToAll(), ToGroup() etc.
-- @param #MESSAGE self
-- @return #MESSAGE
function MESSAGE:Clear()
self:F()
self.ClearScreen=true
return self
end
--- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player". --- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player".
@@ -173,7 +191,7 @@ function MESSAGE:ToClient( Client, Settings )
if self.MessageDuration ~= 0 then if self.MessageDuration ~= 0 then
local ClientGroupID = Client:GetClientGroupID() local ClientGroupID = Client:GetClientGroupID()
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration ) self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration ) trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration , self.ClearScreen)
end end
end end
@@ -197,7 +215,7 @@ function MESSAGE:ToGroup( Group, Settings )
if self.MessageDuration ~= 0 then if self.MessageDuration ~= 0 then
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration ) self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
trigger.action.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration ) trigger.action.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
end end
end end
@@ -265,7 +283,7 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
if CoalitionSide then if CoalitionSide then
if self.MessageDuration ~= 0 then if self.MessageDuration ~= 0 then
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration ) self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration ) trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
end end
end end
@@ -308,7 +326,7 @@ function MESSAGE:ToAll()
if self.MessageDuration ~= 0 then if self.MessageDuration ~= 0 then
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration ) self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
trigger.action.outText( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration ) trigger.action.outText( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
end end
return self return self

View File

@@ -1,7 +1,5 @@
--- **Core** -- **POINT\_VEC** classes define an **extensive API** to **manage 3D points** in the simulation space. --- **Core** -- **POINT\_VEC** classes define an **extensive API** to **manage 3D points** in the simulation space.
-- --
-- ![Banner Image](..\Presentations\POINT\Dia1.JPG)
--
-- === -- ===
-- --
-- # Demo Missions -- # Demo Missions
@@ -26,8 +24,8 @@
-- --
-- ### Contributions: -- ### Contributions:
-- --
-- @module Point -- @module Core.Point
-- @image Core_Coordinate.JPG
@@ -38,17 +36,15 @@ do -- COORDINATE
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # COORDINATE class, extends @{Base#BASE} --- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
--
-- COORDINATE defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
-- --
-- ## COORDINATE constructor -- ## COORDINATE constructor
-- --
-- A new COORDINATE object can be created with: -- A new COORDINATE object can be created with:
-- --
-- * @{#COORDINATE.New}(): a 3D point. -- * @{#COORDINATE.New}(): a 3D point.
-- * @{#COORDINATE.NewFromVec2}(): a 2D point created from a @{DCSTypes#Vec2}. -- * @{#COORDINATE.NewFromVec2}(): a 2D point created from a @{DCS#Vec2}.
-- * @{#COORDINATE.NewFromVec3}(): a 3D point created from a @{DCSTypes#Vec3}. -- * @{#COORDINATE.NewFromVec3}(): a 3D point created from a @{DCS#Vec3}.
-- --
-- ## Create waypoints for routes -- ## Create waypoints for routes
-- --
@@ -57,7 +53,7 @@ do -- COORDINATE
-- * @{#COORDINATE.WaypointAir}(): Build an air route point. -- * @{#COORDINATE.WaypointAir}(): Build an air route point.
-- * @{#COORDINATE.WaypointGround}(): Build a ground route point. -- * @{#COORDINATE.WaypointGround}(): Build a ground route point.
-- --
-- Route points can be used in the Route methods of the @{Group#GROUP} class. -- Route points can be used in the Route methods of the @{Wrapper.Group#GROUP} class.
-- --
-- --
-- ## Smoke, flare, explode, illuminate -- ## Smoke, flare, explode, illuminate
@@ -178,9 +174,9 @@ do -- COORDINATE
--- COORDINATE constructor. --- COORDINATE constructor.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. -- @param DCS#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. -- @param DCS#Distance y The y coordinate of the Vec3 point, pointing to the Right.
-- @param Dcs.DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. -- @param DCS#Distance z The z coordinate of the Vec3 point, pointing to the Right.
-- @return #COORDINATE -- @return #COORDINATE
function COORDINATE:New( x, y, z ) function COORDINATE:New( x, y, z )
@@ -192,10 +188,24 @@ do -- COORDINATE
return self return self
end end
--- COORDINATE constructor.
-- @param #COORDINATE self
-- @param #COORDINATE Coordinate.
-- @return #COORDINATE
function COORDINATE:NewFromCoordinate( Coordinate )
local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE
self.x = Coordinate.x
self.y = Coordinate.y
self.z = Coordinate.z
return self
end
--- Create a new COORDINATE object from Vec2 coordinates. --- Create a new COORDINATE object from Vec2 coordinates.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point. -- @param DCS#Vec2 Vec2 The Vec2 point.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height. -- @param DCS#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return #COORDINATE -- @return #COORDINATE
function COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) function COORDINATE:NewFromVec2( Vec2, LandHeightAdd )
@@ -214,7 +224,7 @@ do -- COORDINATE
--- Create a new COORDINATE object from Vec3 coordinates. --- Create a new COORDINATE object from Vec3 coordinates.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point. -- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return #COORDINATE -- @return #COORDINATE
function COORDINATE:NewFromVec3( Vec3 ) function COORDINATE:NewFromVec3( Vec3 )
@@ -228,7 +238,7 @@ do -- COORDINATE
--- Return the coordinates of the COORDINATE in Vec3 format. --- Return the coordinates of the COORDINATE in Vec3 format.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @return Dcs.DCSTypes#Vec3 The Vec3 format coordinate. -- @return DCS#Vec3 The Vec3 format coordinate.
function COORDINATE:GetVec3() function COORDINATE:GetVec3()
return { x = self.x, y = self.y, z = self.z } return { x = self.x, y = self.y, z = self.z }
end end
@@ -236,30 +246,69 @@ do -- COORDINATE
--- Return the coordinates of the COORDINATE in Vec2 format. --- Return the coordinates of the COORDINATE in Vec2 format.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @return Dcs.DCSTypes#Vec2 The Vec2 format coordinate. -- @return DCS#Vec2 The Vec2 format coordinate.
function COORDINATE:GetVec2() function COORDINATE:GetVec2()
return { x = self.x, y = self.z } return { x = self.x, y = self.z }
end end
--TODO: check this to replace --- Returns the coordinate from the latitude and longitude given in decimal degrees.
--- Calculate the distance from a reference @{DCSTypes#Vec2}.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec2 Vec2Reference The reference @{DCSTypes#Vec2}. -- @param #number latitude Latitude in decimal degrees.
-- @return Dcs.DCSTypes#Distance The distance from the reference @{DCSTypes#Vec2} in meters. -- @param #number longitude Longitude in decimal degrees.
function COORDINATE:DistanceFromVec2( Vec2Reference ) -- @param #number altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
self:F2( Vec2Reference ) -- @return #COORDINATE
function COORDINATE:NewFromLLDD( latitude, longitude, altitude)
-- Returns a point from latitude and longitude in the vec3 format.
local vec3=coord.LLtoLO(latitude, longitude)
-- Convert vec3 to coordinate object.
local _coord=self:NewFromVec3(vec3)
-- Adjust height
if altitude==nil then
_coord.y=altitude
end
local Distance = ( ( Vec2Reference.x - self.x ) ^ 2 + ( Vec2Reference.y - self.z ) ^2 ) ^0.5 return _coord
end
--- Returns if the 2 coordinates are at the same 2D position.
-- @param #COORDINATE self
-- @param #COORDINATE Coordinate
-- @param #number Precision
-- @return #boolean true if at the same position.
function COORDINATE:IsAtCoordinate2D( Coordinate, Precision )
self:F( { Coordinate = Coordinate:GetVec2() } )
self:F( { self = self:GetVec2() } )
local x = Coordinate.x
local z = Coordinate.z
return x - Precision <= self.x and x + Precision >= self.x and z - Precision <= self.z and z + Precision >= self.z
end
--- Calculate the distance from a reference @{#COORDINATE}.
-- @param #COORDINATE self
-- @param #COORDINATE PointVec2Reference The reference @{#COORDINATE}.
-- @return DCS#Distance The distance from the reference @{#COORDINATE} in meters.
function COORDINATE:DistanceFromPointVec2( PointVec2Reference )
self:F2( PointVec2Reference )
local Distance = ( ( PointVec2Reference.x - self.x ) ^ 2 + ( PointVec2Reference.z - self.z ) ^2 ) ^ 0.5
self:T2( Distance ) self:T2( Distance )
return Distance return Distance
end end
--- Add a Distance in meters from the COORDINATE orthonormal plane, with the given angle, and calculate the new COORDINATE. --- Add a Distance in meters from the COORDINATE orthonormal plane, with the given angle, and calculate the new COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance Distance The Distance to be added in meters. -- @param DCS#Distance Distance The Distance to be added in meters.
-- @param Dcs.DCSTypes#Angle Angle The Angle in degrees. -- @param DCS#Angle Angle The Angle in degrees.
-- @return #COORDINATE The new calculated COORDINATE. -- @return #COORDINATE The new calculated COORDINATE.
function COORDINATE:Translate( Distance, Angle ) function COORDINATE:Translate( Distance, Angle )
local SX = self.x local SX = self.x
@@ -273,9 +322,9 @@ do -- COORDINATE
--- Return a random Vec2 within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE. --- Return a random Vec2 within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance OuterRadius -- @param DCS#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius -- @param DCS#Distance InnerRadius
-- @return Dcs.DCSTypes#Vec2 Vec2 -- @return DCS#Vec2 Vec2
function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius ) function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } ) self:F2( { OuterRadius, InnerRadius } )
@@ -303,11 +352,23 @@ do -- COORDINATE
end end
--- Return a random Coordinate within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #COORDINATE
function COORDINATE:GetRandomCoordinateInRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
return COORDINATE:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) )
end
--- Return a random Vec3 within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE. --- Return a random Vec3 within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance OuterRadius -- @param DCS#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius -- @param DCS#Distance InnerRadius
-- @return Dcs.DCSTypes#Vec3 Vec3 -- @return DCS#Vec3 Vec3
function COORDINATE:GetRandomVec3InRadius( OuterRadius, InnerRadius ) function COORDINATE:GetRandomVec3InRadius( OuterRadius, InnerRadius )
local RandomVec2 = self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) local RandomVec2 = self:GetRandomVec2InRadius( OuterRadius, InnerRadius )
@@ -370,7 +431,7 @@ do -- COORDINATE
--- Return a direction vector Vec3 from COORDINATE to the COORDINATE. --- Return a direction vector Vec3 from COORDINATE to the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE TargetCoordinate The target COORDINATE. -- @param #COORDINATE TargetCoordinate The target COORDINATE.
-- @return Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format. -- @return DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
function COORDINATE:GetDirectionVec3( TargetCoordinate ) function COORDINATE:GetDirectionVec3( TargetCoordinate )
return { x = TargetCoordinate.x - self.x, y = TargetCoordinate.y - self.y, z = TargetCoordinate.z - self.z } return { x = TargetCoordinate.x - self.x, y = TargetCoordinate.y - self.y, z = TargetCoordinate.z - self.z }
end end
@@ -389,7 +450,7 @@ do -- COORDINATE
--- Return an angle in radians from the COORDINATE using a direction vector in Vec3 format. --- Return an angle in radians from the COORDINATE using a direction vector in Vec3 format.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format. -- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The angle in radians. -- @return #number DirectionRadians The angle in radians.
function COORDINATE:GetAngleRadians( DirectionVec3 ) function COORDINATE:GetAngleRadians( DirectionVec3 )
local DirectionRadians = math.atan2( DirectionVec3.z, DirectionVec3.x ) local DirectionRadians = math.atan2( DirectionVec3.z, DirectionVec3.x )
@@ -402,7 +463,7 @@ do -- COORDINATE
--- Return an angle in degrees from the COORDINATE using a direction vector in Vec3 format. --- Return an angle in degrees from the COORDINATE using a direction vector in Vec3 format.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format. -- @param DCS#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The angle in degrees. -- @return #number DirectionRadians The angle in degrees.
function COORDINATE:GetAngleDegrees( DirectionVec3 ) function COORDINATE:GetAngleDegrees( DirectionVec3 )
local AngleRadians = self:GetAngleRadians( DirectionVec3 ) local AngleRadians = self:GetAngleRadians( DirectionVec3 )
@@ -414,7 +475,7 @@ do -- COORDINATE
--- Return the 2D distance in meters between the target COORDINATE and the COORDINATE. --- Return the 2D distance in meters between the target COORDINATE and the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE TargetCoordinate The target COORDINATE. -- @param #COORDINATE TargetCoordinate The target COORDINATE.
-- @return Dcs.DCSTypes#Distance Distance The distance in meters. -- @return DCS#Distance Distance The distance in meters.
function COORDINATE:Get2DDistance( TargetCoordinate ) function COORDINATE:Get2DDistance( TargetCoordinate )
local TargetVec3 = TargetCoordinate:GetVec3() local TargetVec3 = TargetCoordinate:GetVec3()
local SourceVec3 = self:GetVec3() local SourceVec3 = self:GetVec3()
@@ -426,8 +487,8 @@ do -- COORDINATE
-- @param height (Optional) parameter specifying the height ASL. -- @param height (Optional) parameter specifying the height ASL.
-- @return Temperature in Degrees Celsius. -- @return Temperature in Degrees Celsius.
function COORDINATE:GetTemperature(height) function COORDINATE:GetTemperature(height)
self:F2(height)
local y=height or self.y local y=height or self.y
env.info("FF height = "..y)
local point={x=self.x, y=height or self.y, z=self.z} local point={x=self.x, y=height or self.y, z=self.z}
-- get temperature [K] and pressure [Pa] at point -- get temperature [K] and pressure [Pa] at point
local T,P=atmosphere.getTemperatureAndPressure(point) local T,P=atmosphere.getTemperatureAndPressure(point)
@@ -578,7 +639,7 @@ do -- COORDINATE
--- Return the 3D distance in meters between the target COORDINATE and the COORDINATE. --- Return the 3D distance in meters between the target COORDINATE and the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE TargetCoordinate The target COORDINATE. -- @param #COORDINATE TargetCoordinate The target COORDINATE.
-- @return Dcs.DCSTypes#Distance Distance The distance in meters. -- @return DCS#Distance Distance The distance in meters.
function COORDINATE:Get3DDistance( TargetCoordinate ) function COORDINATE:Get3DDistance( TargetCoordinate )
local TargetVec3 = TargetCoordinate:GetVec3() local TargetVec3 = TargetCoordinate:GetVec3()
local SourceVec3 = self:GetVec3() local SourceVec3 = self:GetVec3()
@@ -714,8 +775,8 @@ do -- COORDINATE
--- Add a Distance in meters from the COORDINATE horizontal plane, with the given angle, and calculate the new COORDINATE. --- Add a Distance in meters from the COORDINATE horizontal plane, with the given angle, and calculate the new COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance Distance The Distance to be added in meters. -- @param DCS#Distance Distance The Distance to be added in meters.
-- @param Dcs.DCSTypes#Angle Angle The Angle in degrees. -- @param DCS#Angle Angle The Angle in degrees.
-- @return #COORDINATE The new calculated COORDINATE. -- @return #COORDINATE The new calculated COORDINATE.
function COORDINATE:Translate( Distance, Angle ) function COORDINATE:Translate( Distance, Angle )
local SX = self.x local SX = self.x
@@ -734,7 +795,7 @@ do -- COORDINATE
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param #COORDINATE.WaypointType Type The route point type. -- @param #COORDINATE.WaypointType Type The route point type.
-- @param #COORDINATE.WaypointAction Action The route point action. -- @param #COORDINATE.WaypointAction Action The route point action.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h. Default is 500 km/h.
-- @param #boolean SpeedLocked true means the speed is locked. -- @param #boolean SpeedLocked true means the speed is locked.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAir( AltType, Type, Action, Speed, SpeedLocked ) function COORDINATE:WaypointAir( AltType, Type, Action, Speed, SpeedLocked )
@@ -777,7 +838,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Turning Point". --- Build a Waypoint Air "Turning Point".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirTurningPoint( AltType, Speed ) function COORDINATE:WaypointAirTurningPoint( AltType, Speed )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed )
@@ -787,7 +848,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Fly Over Point". --- Build a Waypoint Air "Fly Over Point".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirFlyOverPoint( AltType, Speed ) function COORDINATE:WaypointAirFlyOverPoint( AltType, Speed )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.FlyoverPoint, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.FlyoverPoint, Speed )
@@ -797,7 +858,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Take Off Parking Hot". --- Build a Waypoint Air "Take Off Parking Hot".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirTakeOffParkingHot( AltType, Speed ) function COORDINATE:WaypointAirTakeOffParkingHot( AltType, Speed )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOffParkingHot, COORDINATE.WaypointAction.FromParkingAreaHot, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOffParkingHot, COORDINATE.WaypointAction.FromParkingAreaHot, Speed )
@@ -807,7 +868,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Take Off Parking". --- Build a Waypoint Air "Take Off Parking".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirTakeOffParking( AltType, Speed ) function COORDINATE:WaypointAirTakeOffParking( AltType, Speed )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOffParking, COORDINATE.WaypointAction.FromParkingArea, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOffParking, COORDINATE.WaypointAction.FromParkingArea, Speed )
@@ -817,7 +878,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Take Off Runway". --- Build a Waypoint Air "Take Off Runway".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirTakeOffRunway( AltType, Speed ) function COORDINATE:WaypointAirTakeOffRunway( AltType, Speed )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOff, COORDINATE.WaypointAction.FromRunway, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TakeOff, COORDINATE.WaypointAction.FromRunway, Speed )
@@ -826,7 +887,7 @@ do -- COORDINATE
--- Build a Waypoint Air "Landing". --- Build a Waypoint Air "Landing".
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @return #table The route point. -- @return #table The route point.
-- @usage -- @usage
-- --
@@ -844,17 +905,19 @@ do -- COORDINATE
--- Build an ground type route point. --- Build an ground type route point.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number Speed (optional) Speed in km/h. The default speed is 999 km/h. -- @param #number Speed (optional) Speed in km/h. The default speed is 20 km/h.
-- @param #string Formation (optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right". -- @param #string Formation (optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right".
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointGround( Speed, Formation ) function COORDINATE:WaypointGround( Speed, Formation )
self:F2( { Formation, Speed } ) self:F2( { Formation, Speed } )
local RoutePoint = {} local RoutePoint = {}
RoutePoint.x = self.x RoutePoint.x = self.x
RoutePoint.y = self.z RoutePoint.y = self.z
RoutePoint.action = Formation or "" RoutePoint.action = Formation or ""
--RoutePoint.formation_template = Formation and "" or nil
RoutePoint.speed = ( Speed or 20 ) / 3.6 RoutePoint.speed = ( Speed or 20 ) / 3.6
@@ -890,21 +953,41 @@ do -- COORDINATE
return COORDINATE:NewFromVec2(vec2) return COORDINATE:NewFromVec2(vec2)
end end
--- Returns a table of coordinates to a destination. --- Returns a table of coordinates to a destination using only roads.
-- The first point is the closest point on road of the given coordinate. The last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE ToCoord Coordinate of destination. -- @param #COORDINATE ToCoord Coordinate of destination.
-- @return #table Table of coordinates on road. -- @return #table Table of coordinates on road. If no path on road can be found, nil is returned.
function COORDINATE:GetPathOnRoad(ToCoord) function COORDINATE:GetPathOnRoad(ToCoord)
local Path={}
-- DCS API function returning a table of vec2.
local path = land.findPathOnRoads("roads", self.x, self.z, ToCoord.x, ToCoord.z) local path = land.findPathOnRoads("roads", self.x, self.z, ToCoord.x, ToCoord.z)
for i, v in ipairs(path) do
--self:E(v) local Path={}
local coord=COORDINATE:NewFromVec2(v)
Path[#Path+1]=COORDINATE:NewFromVec2(v) if path then
--Path[#Path+1]=self
for i, v in ipairs(path) do
Path[#Path+1]=COORDINATE:NewFromVec2(v)
end
--Path[#Path+1]=ToCoord
else
-- There are cases where no path on road can be found.
return nil
end end
return Path return Path
end end
--- Gets the surface type at the coordinate.
-- @param #COORDINATE self
-- @return DCS#SurfaceType Surface type.
function COORDINATE:GetSurfaceType()
local vec2=self:GetVec2()
local surface=land.getSurfaceType(vec2)
return surface
end
--- Creates an explosion at the point of a certain intensity. --- Creates an explosion at the point of a certain intensity.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number ExplosionIntensity -- @param #number ExplosionIntensity
@@ -964,10 +1047,92 @@ do -- COORDINATE
self:Smoke( SMOKECOLOR.Blue ) self:Smoke( SMOKECOLOR.Blue )
end end
--- Big smoke and fire at the coordinate.
-- @param #COORDINATE self
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (0=small smoke and fire, 1=medium smoke and fire, 2=large smoke and fire, 3=huge smoke and fire, 4=small smoke, 5=medium smoke, 6=large smoke, 7=huge smoke).
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
function COORDINATE:BigSmokeAndFire( preset, density )
self:F2( { preset=preset, density=density } )
density=density or 0.5
trigger.action.effectSmokeBig( self:GetVec3(), preset, density )
end
--- Small smoke and fire at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeAndFireSmall( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, density)
end
--- Medium smoke and fire at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeAndFireMedium( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, density)
end
--- Large smoke and fire at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeAndFireLarge( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, density)
end
--- Huge smoke and fire at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeAndFireHuge( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, density)
end
--- Small smoke at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeSmall( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, density)
end
--- Medium smoke at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeMedium( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, density)
end
--- Large smoke at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeLarge( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, density)
end
--- Huge smoke at the coordinate.
-- @param #COORDINATE self
-- @number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
function COORDINATE:BigSmokeHuge( density )
self:F2( { density=density } )
density=density or 0.5
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, density)
end
--- Flares the point in a color. --- Flares the point in a color.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Utilities.Utils#FLARECOLOR FlareColor -- @param Utilities.Utils#FLARECOLOR FlareColor
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:Flare( FlareColor, Azimuth ) function COORDINATE:Flare( FlareColor, Azimuth )
self:F2( { FlareColor } ) self:F2( { FlareColor } )
trigger.action.signalFlare( self:GetVec3(), FlareColor, Azimuth and Azimuth or 0 ) trigger.action.signalFlare( self:GetVec3(), FlareColor, Azimuth and Azimuth or 0 )
@@ -975,7 +1140,7 @@ do -- COORDINATE
--- Flare the COORDINATE White. --- Flare the COORDINATE White.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareWhite( Azimuth ) function COORDINATE:FlareWhite( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.White, Azimuth ) self:Flare( FLARECOLOR.White, Azimuth )
@@ -983,7 +1148,7 @@ do -- COORDINATE
--- Flare the COORDINATE Yellow. --- Flare the COORDINATE Yellow.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareYellow( Azimuth ) function COORDINATE:FlareYellow( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.Yellow, Azimuth ) self:Flare( FLARECOLOR.Yellow, Azimuth )
@@ -991,7 +1156,7 @@ do -- COORDINATE
--- Flare the COORDINATE Green. --- Flare the COORDINATE Green.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareGreen( Azimuth ) function COORDINATE:FlareGreen( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.Green, Azimuth ) self:Flare( FLARECOLOR.Green, Azimuth )
@@ -1009,13 +1174,19 @@ do -- COORDINATE
--- Mark to All --- Mark to All
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string MarkText Free format text that shows the marking clarification. -- @param #string MarkText Free format text that shows the marking clarification.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number. -- @return #number The resulting Mark ID which is a number.
-- @usage -- @usage
-- local TargetCoord = TargetGroup:GetCoordinate() -- local TargetCoord = TargetGroup:GetCoordinate()
-- local MarkID = TargetCoord:MarkToAll( "This is a target for all players" ) -- local MarkID = TargetCoord:MarkToAll( "This is a target for all players" )
function COORDINATE:MarkToAll( MarkText ) function COORDINATE:MarkToAll( MarkText, ReadOnly, Text )
local MarkID = UTILS.GetMarkID() local MarkID = UTILS.GetMarkID()
trigger.action.markToAll( MarkID, MarkText, self:GetVec3(), false, "" ) if ReadOnly==nil then
ReadOnly=false
end
local text=Text or ""
trigger.action.markToAll( MarkID, MarkText, self:GetVec3(), ReadOnly, text)
return MarkID return MarkID
end end
@@ -1023,50 +1194,66 @@ do -- COORDINATE
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string MarkText Free format text that shows the marking clarification. -- @param #string MarkText Free format text that shows the marking clarification.
-- @param Coalition -- @param Coalition
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number. -- @return #number The resulting Mark ID which is a number.
-- @usage -- @usage
-- local TargetCoord = TargetGroup:GetCoordinate() -- local TargetCoord = TargetGroup:GetCoordinate()
-- local MarkID = TargetCoord:MarkToCoalition( "This is a target for the red coalition", coalition.side.RED ) -- local MarkID = TargetCoord:MarkToCoalition( "This is a target for the red coalition", coalition.side.RED )
function COORDINATE:MarkToCoalition( MarkText, Coalition ) function COORDINATE:MarkToCoalition( MarkText, Coalition, ReadOnly, Text )
local MarkID = UTILS.GetMarkID() local MarkID = UTILS.GetMarkID()
trigger.action.markToCoalition( MarkID, MarkText, self:GetVec3(), Coalition, false, "" ) if ReadOnly==nil then
ReadOnly=false
end
local text=Text or ""
trigger.action.markToCoalition( MarkID, MarkText, self:GetVec3(), Coalition, ReadOnly, text )
return MarkID return MarkID
end end
--- Mark to Red Coalition --- Mark to Red Coalition
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string MarkText Free format text that shows the marking clarification. -- @param #string MarkText Free format text that shows the marking clarification.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number. -- @return #number The resulting Mark ID which is a number.
-- @usage -- @usage
-- local TargetCoord = TargetGroup:GetCoordinate() -- local TargetCoord = TargetGroup:GetCoordinate()
-- local MarkID = TargetCoord:MarkToCoalitionRed( "This is a target for the red coalition" ) -- local MarkID = TargetCoord:MarkToCoalitionRed( "This is a target for the red coalition" )
function COORDINATE:MarkToCoalitionRed( MarkText ) function COORDINATE:MarkToCoalitionRed( MarkText, ReadOnly, Text )
return self:MarkToCoalition( MarkText, coalition.side.RED ) return self:MarkToCoalition( MarkText, coalition.side.RED, ReadOnly, Text )
end end
--- Mark to Blue Coalition --- Mark to Blue Coalition
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string MarkText Free format text that shows the marking clarification. -- @param #string MarkText Free format text that shows the marking clarification.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number. -- @return #number The resulting Mark ID which is a number.
-- @usage -- @usage
-- local TargetCoord = TargetGroup:GetCoordinate() -- local TargetCoord = TargetGroup:GetCoordinate()
-- local MarkID = TargetCoord:MarkToCoalitionBlue( "This is a target for the blue coalition" ) -- local MarkID = TargetCoord:MarkToCoalitionBlue( "This is a target for the blue coalition" )
function COORDINATE:MarkToCoalitionBlue( MarkText ) function COORDINATE:MarkToCoalitionBlue( MarkText, ReadOnly, Text )
return self:MarkToCoalition( MarkText, coalition.side.BLUE ) return self:MarkToCoalition( MarkText, coalition.side.BLUE, ReadOnly, Text )
end end
--- Mark to Group --- Mark to Group
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #string MarkText Free format text that shows the marking clarification. -- @param #string MarkText Free format text that shows the marking clarification.
-- @param Wrapper.Group#GROUP MarkGroup The @{Group} that receives the mark. -- @param Wrapper.Group#GROUP MarkGroup The @{Wrapper.Group} that receives the mark.
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
-- @param #string Text (Optional) Text displayed when mark is added. Default none.
-- @return #number The resulting Mark ID which is a number. -- @return #number The resulting Mark ID which is a number.
-- @usage -- @usage
-- local TargetCoord = TargetGroup:GetCoordinate() -- local TargetCoord = TargetGroup:GetCoordinate()
-- local MarkGroup = GROUP:FindByName( "AttackGroup" ) -- local MarkGroup = GROUP:FindByName( "AttackGroup" )
-- local MarkID = TargetCoord:MarkToGroup( "This is a target for the attack group", AttackGroup ) -- local MarkID = TargetCoord:MarkToGroup( "This is a target for the attack group", AttackGroup )
function COORDINATE:MarkToGroup( MarkText, MarkGroup ) function COORDINATE:MarkToGroup( MarkText, MarkGroup, ReadOnly, Text )
local MarkID = UTILS.GetMarkID() local MarkID = UTILS.GetMarkID()
trigger.action.markToGroup( MarkID, MarkText, self:GetVec3(), MarkGroup:GetID(), false, "" ) if ReadOnly==nil then
ReadOnly=false
end
local text=Text or ""
trigger.action.markToGroup( MarkID, MarkText, self:GetVec3(), MarkGroup:GetID(), ReadOnly, text )
return MarkID return MarkID
end end
@@ -1163,7 +1350,7 @@ do -- COORDINATE
--- Return a BULLS string out of the BULLS of the coalition to the COORDINATE. --- Return a BULLS string out of the BULLS of the coalition to the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition. -- @param DCS#coalition.side Coalition The coalition.
-- @return #string The BR text. -- @return #string The BR text.
function COORDINATE:ToStringBULLS( Coalition, Settings ) function COORDINATE:ToStringBULLS( Coalition, Settings )
local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( Coalition ) ) local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( Coalition ) )
@@ -1244,7 +1431,7 @@ do -- COORDINATE
-- @return #string The coordinate Text in the configured coordinate system. -- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToStringFromRP( ReferenceCoord, ReferenceName, Controllable, Settings ) -- R2.2 function COORDINATE:ToStringFromRP( ReferenceCoord, ReferenceName, Controllable, Settings ) -- R2.2
self:F( { ReferenceCoord = ReferenceCoord, ReferenceName = ReferenceName } ) self:F2( { ReferenceCoord = ReferenceCoord, ReferenceName = ReferenceName } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1273,7 +1460,7 @@ do -- COORDINATE
-- @return #string The coordinate Text in the configured coordinate system. -- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToStringA2G( Controllable, Settings ) -- R2.2 function COORDINATE:ToStringA2G( Controllable, Settings ) -- R2.2
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1308,7 +1495,7 @@ do -- COORDINATE
-- @return #string The coordinate Text in the configured coordinate system. -- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToStringA2A( Controllable, Settings ) -- R2.2 function COORDINATE:ToStringA2A( Controllable, Settings ) -- R2.2
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1348,7 +1535,7 @@ do -- COORDINATE
-- @return #string The coordinate Text in the configured coordinate system. -- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToString( Controllable, Settings, Task ) -- R2.2 function COORDINATE:ToString( Controllable, Settings, Task ) -- R2.2
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1397,7 +1584,7 @@ do -- COORDINATE
-- @return #string The pressure text in the configured measurement system. -- @return #string The pressure text in the configured measurement system.
function COORDINATE:ToStringPressure( Controllable, Settings ) -- R2.3 function COORDINATE:ToStringPressure( Controllable, Settings ) -- R2.3
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1413,7 +1600,7 @@ do -- COORDINATE
-- @return #string The wind text in the configured measurement system. -- @return #string The wind text in the configured measurement system.
function COORDINATE:ToStringWind( Controllable, Settings ) -- R2.3 function COORDINATE:ToStringWind( Controllable, Settings ) -- R2.3
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1429,7 +1616,7 @@ do -- COORDINATE
-- @return #string The temperature text in the configured measurement system. -- @return #string The temperature text in the configured measurement system.
function COORDINATE:ToStringTemperature( Controllable, Settings ) -- R2.3 function COORDINATE:ToStringTemperature( Controllable, Settings ) -- R2.3
self:F( { Controllable = Controllable and Controllable:GetName() } ) self:F2( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
@@ -1453,9 +1640,7 @@ do -- POINT_VEC3
-- @extends Core.Point#COORDINATE -- @extends Core.Point#COORDINATE
--- # POINT_VEC3 class, extends @{Point#COORDINATE} --- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
--
-- POINT_VEC3 defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
-- --
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts. -- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author, -- In order to keep the credibility of the the author,
@@ -1468,7 +1653,7 @@ do -- POINT_VEC3
-- A new POINT_VEC3 object can be created with: -- A new POINT_VEC3 object can be created with:
-- --
-- * @{#POINT_VEC3.New}(): a 3D point. -- * @{#POINT_VEC3.New}(): a 3D point.
-- * @{#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{DCSTypes#Vec3}. -- * @{#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{DCS#Vec3}.
-- --
-- --
-- ## Manupulate the X, Y, Z coordinates of the POINT_VEC3 -- ## Manupulate the X, Y, Z coordinates of the POINT_VEC3
@@ -1532,9 +1717,9 @@ do -- POINT_VEC3
--- Create a new POINT_VEC3 object. --- Create a new POINT_VEC3 object.
-- @param #POINT_VEC3 self -- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. -- @param DCS#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards. -- @param DCS#Distance y The y coordinate of the Vec3 point, pointing Upwards.
-- @param Dcs.DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. -- @param DCS#Distance z The z coordinate of the Vec3 point, pointing to the Right.
-- @return Core.Point#POINT_VEC3 -- @return Core.Point#POINT_VEC3
function POINT_VEC3:New( x, y, z ) function POINT_VEC3:New( x, y, z )
@@ -1546,8 +1731,8 @@ do -- POINT_VEC3
--- Create a new POINT_VEC3 object from Vec2 coordinates. --- Create a new POINT_VEC3 object from Vec2 coordinates.
-- @param #POINT_VEC3 self -- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point. -- @param DCS#Vec2 Vec2 The Vec2 point.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) Add a landheight. -- @param DCS#Distance LandHeightAdd (optional) Add a landheight.
-- @return Core.Point#POINT_VEC3 self -- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd ) function POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd )
@@ -1560,7 +1745,7 @@ do -- POINT_VEC3
--- Create a new POINT_VEC3 object from Vec3 coordinates. --- Create a new POINT_VEC3 object from Vec3 coordinates.
-- @param #POINT_VEC3 self -- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point. -- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC3 self -- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec3( Vec3 ) function POINT_VEC3:NewFromVec3( Vec3 )
@@ -1649,8 +1834,8 @@ do -- POINT_VEC3
--- Return a random POINT_VEC3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3. --- Return a random POINT_VEC3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self -- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Distance OuterRadius -- @param DCS#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius -- @param DCS#Distance InnerRadius
-- @return #POINT_VEC3 -- @return #POINT_VEC3
function POINT_VEC3:GetRandomPointVec3InRadius( OuterRadius, InnerRadius ) function POINT_VEC3:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
@@ -1662,20 +1847,18 @@ end
do -- POINT_VEC2 do -- POINT_VEC2
--- @type POINT_VEC2 --- @type POINT_VEC2
-- @field Dcs.DCSTypes#Distance x The x coordinate in meters. -- @field DCS#Distance x The x coordinate in meters.
-- @field Dcs.DCSTypes#Distance y the y coordinate in meters. -- @field DCS#Distance y the y coordinate in meters.
-- @extends Core.Point#COORDINATE -- @extends Core.Point#COORDINATE
--- # POINT_VEC2 class, extends @{Point#COORDINATE} --- Defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
--
-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
-- --
-- ## POINT_VEC2 constructor -- ## POINT_VEC2 constructor
-- --
-- A new POINT_VEC2 instance can be created with: -- A new POINT_VEC2 instance can be created with:
-- --
-- * @{Point#POINT_VEC2.New}(): a 2D point, taking an additional height parameter. -- * @{Core.Point#POINT_VEC2.New}(): a 2D point, taking an additional height parameter.
-- * @{Point#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{DCSTypes#Vec2}. -- * @{Core.Point#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{DCS#Vec2}.
-- --
-- ## Manupulate the X, Altitude, Y coordinates of the 2D point -- ## Manupulate the X, Altitude, Y coordinates of the 2D point
-- --
@@ -1700,9 +1883,9 @@ do -- POINT_VEC2
--- POINT_VEC2 constructor. --- POINT_VEC2 constructor.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. -- @param DCS#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. -- @param DCS#Distance y The y coordinate of the Vec3 point, pointing to the Right.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height. -- @param DCS#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return Core.Point#POINT_VEC2 -- @return Core.Point#POINT_VEC2
function POINT_VEC2:New( x, y, LandHeightAdd ) function POINT_VEC2:New( x, y, LandHeightAdd )
@@ -1719,7 +1902,7 @@ do -- POINT_VEC2
--- Create a new POINT_VEC2 object from Vec2 coordinates. --- Create a new POINT_VEC2 object from Vec2 coordinates.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point. -- @param DCS#Vec2 Vec2 The Vec2 point.
-- @return Core.Point#POINT_VEC2 self -- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd ) function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd )
@@ -1736,7 +1919,7 @@ do -- POINT_VEC2
--- Create a new POINT_VEC2 object from Vec3 coordinates. --- Create a new POINT_VEC2 object from Vec3 coordinates.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point. -- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC2 self -- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec3( Vec3 ) function POINT_VEC2:NewFromVec3( Vec3 )
@@ -1856,8 +2039,8 @@ do -- POINT_VEC2
--- Return a random POINT_VEC2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC2. --- Return a random POINT_VEC2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC2.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param Dcs.DCSTypes#Distance OuterRadius -- @param DCS#Distance OuterRadius
-- @param Dcs.DCSTypes#Distance InnerRadius -- @param DCS#Distance InnerRadius
-- @return #POINT_VEC2 -- @return #POINT_VEC2
function POINT_VEC2:GetRandomPointVec2InRadius( OuterRadius, InnerRadius ) function POINT_VEC2:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } ) self:F2( { OuterRadius, InnerRadius } )
@@ -1869,7 +2052,7 @@ do -- POINT_VEC2
--- Calculate the distance from a reference @{#POINT_VEC2}. --- Calculate the distance from a reference @{#POINT_VEC2}.
-- @param #POINT_VEC2 self -- @param #POINT_VEC2 self
-- @param #POINT_VEC2 PointVec2Reference The reference @{#POINT_VEC2}. -- @param #POINT_VEC2 PointVec2Reference The reference @{#POINT_VEC2}.
-- @return Dcs.DCSTypes#Distance The distance from the reference @{#POINT_VEC2} in meters. -- @return DCS#Distance The distance from the reference @{#POINT_VEC2} in meters.
function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference ) function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
self:F2( PointVec2Reference ) self:F2( PointVec2Reference )

View File

@@ -1,7 +1,5 @@
--- **Core** -- The RADIO Module is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio transmissions... --- **Core** -- The RADIO Module is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio transmissions...
-- --
-- ![Banner Image](..\Presentations\RADIO\Dia1.JPG)
--
-- === -- ===
-- --
-- The Radio contains 2 classes : RADIO and BEACON -- The Radio contains 2 classes : RADIO and BEACON
@@ -18,10 +16,10 @@
-- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file), -- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file),
-- * For simplicty sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission. -- * For simplicty sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission.
-- --
-- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Unit#UNIT} or a @{Group#GROUP} or by any other @{Positionable#POSITIONABLE} -- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or by any other @{Wrapper.Positionable#POSITIONABLE}
-- --
-- * If the transmitter is a @{Unit#UNIT} or a @{Group#GROUP}, DCS will set the power of the transmission automatically, -- * If the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, DCS will set the power of the transmission automatically,
-- * If the transmitter is any other @{Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped. -- * If the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped.
-- --
-- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft, -- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft,
-- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below). -- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below).
@@ -32,39 +30,40 @@
-- --
-- ### Author: Hugues "Grey_Echo" Bousquet -- ### Author: Hugues "Grey_Echo" Bousquet
-- --
-- @module Radio -- @module Core.Radio
-- @image Core_Radio.JPG
--- # RADIO class, extends @{Base#BASE} --- Models the radio capabilty.
-- --
-- ## RADIO usage -- ## RADIO usage
-- --
-- There are 3 steps to a successful radio transmission. -- There are 3 steps to a successful radio transmission.
-- --
-- * First, you need to **"add a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function, -- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function,
-- * Then, you will **set the relevant parameters** to the transmission (see below), -- * Then, you will **set the relevant parameters** to the transmission (see below),
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function. -- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
-- --
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE} -- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE}
-- --
-- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"), -- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"),
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission. -- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission.
-- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission. -- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission.
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead... -- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead...
-- --
-- Additional Methods to set relevant parameters if the transmiter is a @{Unit#UNIT} or a @{Group#GROUP} -- Additional Methods to set relevant parameters if the transmiter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}
-- --
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration, -- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call -- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
-- --
-- Additional Methods to set relevant parameters if the transmiter is any other @{Positionable#POSITIONABLE} -- Additional Methods to set relevant parameters if the transmiter is any other @{Wrapper.Positionable#POSITIONABLE}
-- --
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts -- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call -- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
-- --
-- What is this power thing ? -- What is this power thing ?
-- --
-- * If your transmission is sent by a @{Positionable#POSITIONABLE} other than a @{Unit#UNIT} or a @{Group#GROUP}, you can set the power of the antenna, -- * If your transmission is sent by a @{Wrapper.Positionable#POSITIONABLE} other than a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, you can set the power of the antenna,
-- * Otherwise, DCS sets it automatically, depending on what's available on your Unit, -- * Otherwise, DCS sets it automatically, depending on what's available on your Unit,
-- * If the player gets **too far** from the transmiter, or if the antenna is **too weak**, the transmission will **fade** and **become noisyer**, -- * If the player gets **too far** from the transmiter, or if the antenna is **too weak**, the transmission will **fade** and **become noisyer**,
-- * This an automated DCS calculation you have no say on, -- * This an automated DCS calculation you have no say on,
@@ -93,7 +92,7 @@ RADIO = {
} }
--- Create a new RADIO Object. This doesn't broadcast a transmission, though, use @{#RADIO.Broadcast} to actually broadcast --- Create a new RADIO Object. This doesn't broadcast a transmission, though, use @{#RADIO.Broadcast} to actually broadcast
-- If you want to create a RADIO, you probably should use @{Positionable#POSITIONABLE.GetRadio}() instead -- If you want to create a RADIO, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetRadio}() instead
-- @param #RADIO self -- @param #RADIO self
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities. -- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
-- @return #RADIO Radio -- @return #RADIO Radio
@@ -262,7 +261,7 @@ end
--- Create a new transmission, that is to say, populate the RADIO with relevant data --- Create a new transmission, that is to say, populate the RADIO with relevant data
-- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP, -- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
-- but it will work for any @{Positionable#POSITIONABLE}. -- but it will work for any @{Wrapper.Positionable#POSITIONABLE}.
-- Only the RADIO and the Filename are mandatory. -- Only the RADIO and the Filename are mandatory.
-- @param #RADIO self -- @param #RADIO self
-- @param #string FileName -- @param #string FileName
@@ -291,7 +290,7 @@ end
--- Actually Broadcast the transmission --- Actually Broadcast the transmission
-- * The Radio has to be populated with the new transmission before broadcasting. -- * The Radio has to be populated with the new transmission before broadcasting.
-- * Please use RADIO setters or either @{Radio#RADIO.NewGenericTransmission} or @{Radio#RADIO.NewUnitTransmission} -- * Please use RADIO setters or either @{#RADIO.NewGenericTransmission} or @{#RADIO.NewUnitTransmission}
-- * This class is in fact pretty smart, it determines the right DCS function to use depending on the type of POSITIONABLE -- * This class is in fact pretty smart, it determines the right DCS function to use depending on the type of POSITIONABLE
-- * If the POSITIONABLE is not a UNIT or a GROUP, we use the generic (but limited) trigger.action.radioTransmission() -- * If the POSITIONABLE is not a UNIT or a GROUP, we use the generic (but limited) trigger.action.radioTransmission()
-- * If the POSITIONABLE is a UNIT or a GROUP, we use the "TransmitMessage" Command -- * If the POSITIONABLE is a UNIT or a GROUP, we use the "TransmitMessage" Command
@@ -343,22 +342,20 @@ function RADIO:StopBroadcast()
end end
--- # BEACON class, extends @{Base#BASE} --- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
--
-- After attaching a @{#BEACON} to your @{Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
-- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon. -- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon.
-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is -- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is
-- attach to a cargo crate, for exemple. -- attach to a cargo crate, for exemple.
-- --
-- ## AA TACAN Beacon usage -- ## AA TACAN Beacon usage
-- --
-- This beacon only works with airborne @{Unit#UNIT} or a @{Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon. -- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
-- Use @#BEACON:StopAATACAN}() to stop it. -- Use @#BEACON:StopAATACAN}() to stop it.
-- --
-- ## General Purpose Radio Beacon usage -- ## General Purpose Radio Beacon usage
-- --
-- This beacon will work with any @{Positionable#POSITIONABLE}, but **it won't follow the @{Positionable#POSITIONABLE}** ! This means that you should only use it with -- This beacon will work with any @{Wrapper.Positionable#POSITIONABLE}, but **it won't follow the @{Wrapper.Positionable#POSITIONABLE}** ! This means that you should only use it with
-- @{Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon. -- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
-- Use @{#BEACON:StopRadioBeacon}() to stop it. -- Use @{#BEACON:StopRadioBeacon}() to stop it.
-- --
-- @type BEACON -- @type BEACON
@@ -368,7 +365,7 @@ BEACON = {
} }
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.AATACAN} or @{#BEACON.Generic} --- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.AATACAN} or @{#BEACON.Generic}
-- If you want to create a BEACON, you probably should use @{Positionable#POSITIONABLE.GetBeacon}() instead. -- If you want to create a BEACON, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetBeacon}() instead.
-- @param #BEACON self -- @param #BEACON self
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities. -- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
-- @return #BEACON Beacon -- @return #BEACON Beacon

View File

@@ -1,3 +1,17 @@
--- **Core** -- **REPORT** class provides a handy means to create messages and reports.
--
-- ===
--
-- ### Authors:
--
-- * FlightControl : Design & Programming
--
-- ### Contributions:
--
-- @module Core.Report
-- @image Core_Report.JPG
--- The REPORT class --- The REPORT class
-- @type REPORT -- @type REPORT
-- @extends Core.Base#BASE -- @extends Core.Base#BASE

View File

@@ -22,7 +22,7 @@
-- --
-- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object. -- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object.
-- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER. -- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER.
-- The SCHEDULER object plans new scheduled functions through the @{Scheduler#SCHEDULER.Schedule}() method. -- The SCHEDULER object plans new scheduled functions through the @{Core.Scheduler#SCHEDULER.Schedule}() method.
-- The Schedule() method returns the CallID that is the reference ID for each planned schedule. -- The Schedule() method returns the CallID that is the reference ID for each planned schedule.
-- --
-- === -- ===
@@ -30,7 +30,8 @@
-- ### Contributions: - -- ### Contributions: -
-- ### Authors: FlightControl : Design & Programming -- ### Authors: FlightControl : Design & Programming
-- --
-- @module ScheduleDispatcher -- @module Core.ScheduleDispatcher
-- @image Core_Schedule_Dispatcher.JPG
--- The SCHEDULEDISPATCHER structure --- The SCHEDULEDISPATCHER structure
-- @type SCHEDULEDISPATCHER -- @type SCHEDULEDISPATCHER

View File

@@ -1,7 +1,5 @@
--- **Core** -- SCHEDULER prepares and handles the **execution of functions over scheduled time (intervals)**. --- **Core** -- SCHEDULER prepares and handles the **execution of functions over scheduled time (intervals)**.
-- --
-- ![Banner Image](..\Presentations\SCHEDULER\Dia1.JPG)
--
-- === -- ===
-- --
-- SCHEDULER manages the **scheduling of functions**: -- SCHEDULER manages the **scheduling of functions**:
@@ -39,8 +37,8 @@
-- --
-- === -- ===
-- --
-- @module Scheduler -- @module Core.Scheduler
-- @image Core_Scheduler.JPG
--- The SCHEDULER class --- The SCHEDULER class
-- @type SCHEDULER -- @type SCHEDULER
@@ -48,9 +46,7 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # SCHEDULER class, extends @{Base#BASE} --- Creates and handles schedules over time, which allow to execute code at specific time intervals with randomization.
--
-- The SCHEDULER class creates schedule.
-- --
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**. -- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called. -- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,5 @@
--- **Core** -- Manages various settings for MOOSE classes. --- **Core** -- Manages various settings for MOOSE classes.
-- --
-- ![Banner Image](..\Presentations\SETTINGS\Dia1.JPG)
--
-- === -- ===
-- --
-- The documentation of the SETTINGS class can be found further in this document. -- The documentation of the SETTINGS class can be found further in this document.
@@ -16,21 +14,17 @@
-- --
-- * **FlightControl**: Design & Programming -- * **FlightControl**: Design & Programming
-- --
-- @module Settings -- @module Core.Settings
-- @image Core_Settings.JPG
--- @type SETTINGS --- @type SETTINGS
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # SETTINGS class, extends @{Base#BASE} --- Takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
-- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\SETTINGS\Dia1.JPG)
--
-- ===
--
-- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework. -- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
-- SETTINGS can work on 2 levels: -- SETTINGS can work on 2 levels:
-- --
@@ -39,29 +33,29 @@
-- --
-- So, when there isn't any **Player setting** defined for a player for a specific setting, or, the player cannot be identified, the **Default setting** will be used instead. -- So, when there isn't any **Player setting** defined for a player for a specific setting, or, the player cannot be identified, the **Default setting** will be used instead.
-- --
-- ## 1. \_SETTINGS object -- # 1) \_SETTINGS object
-- --
-- MOOSE defines by default a singleton object called **\_SETTINGS**. Use this object to modify all the **Default settings** for a running mission. -- MOOSE defines by default a singleton object called **\_SETTINGS**. Use this object to modify all the **Default settings** for a running mission.
-- For each player, MOOSE will automatically allocate also a **player settings** object, and will expose a radio menu to allow the player to adapt the settings to his own preferences. -- For each player, MOOSE will automatically allocate also a **player settings** object, and will expose a radio menu to allow the player to adapt the settings to his own preferences.
-- --
-- ## 2. SETTINGS Menu -- # 2) SETTINGS Menu
-- --
-- Settings can be adapted by the Players and by the Mission Administrator through **radio menus, which are automatically available in the mission**. -- Settings can be adapted by the Players and by the Mission Administrator through **radio menus, which are automatically available in the mission**.
-- These menus can be found **on level F10 under "Settings"**. There are two kinds of menus generated by the system. -- These menus can be found **on level F10 under "Settings"**. There are two kinds of menus generated by the system.
-- --
-- ### 2.1. Default settings menu -- ## 2.1) Default settings menu
-- --
-- A menu is created automatically per Command Center that allows to modify the **Default** settings. -- A menu is created automatically per Command Center that allows to modify the **Default** settings.
-- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**! -- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**!
-- Note that the **Default settings** will only be used when a player has not choosen its own settings. -- Note that the **Default settings** will only be used when a player has not choosen its own settings.
-- --
-- ### 2.2. Player settings menu -- ## 2.2) Player settings menu
-- --
-- A menu is created automatically per Player Slot (group) that allows to modify the **Player** settings. -- A menu is created automatically per Player Slot (group) that allows to modify the **Player** settings.
-- So, when joining a slot, a menu wil be available that allows to change the settings parameters **FOR THE PLAYER ONLY**! -- So, when joining a slot, a menu wil be available that allows to change the settings parameters **FOR THE PLAYER ONLY**!
-- Note that when a player has not chosen a specific setting, the **Default settings** will be used. -- Note that when a player has not chosen a specific setting, the **Default settings** will be used.
-- --
-- ### 2.3. Show or Hide the Player Setting menus -- ## 2.3) Show or Hide the Player Setting menus
-- --
-- Of course, it may be requried not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**. -- Of course, it may be requried not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**.
-- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus. -- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus.
@@ -75,14 +69,14 @@
-- -- But only when a player exits and reenters the slot these settings will have effect! -- -- But only when a player exits and reenters the slot these settings will have effect!
-- --
-- --
-- ## 3. Settings -- # 3) Settings
-- --
-- There are different settings that are managed and applied within the MOOSE framework. -- There are different settings that are managed and applied within the MOOSE framework.
-- See below a comprehensive description of each. -- See below a comprehensive description of each.
-- --
-- ### 3.1. **A2G coordinates** display formatting -- ## 3.1) **A2G coordinates** display formatting
-- --
-- #### 3.1.1. A2G coordinates setting **types** -- ### 3.1.1) A2G coordinates setting **types**
-- --
-- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications. -- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications.
-- --
@@ -91,11 +85,11 @@
-- - A2G LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted. -- - A2G LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
-- - A2G LL DDM: Lattitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. -- - A2G LL DDM: Lattitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
-- --
-- #### 3.1.2. A2G coordinates setting **menu** -- ### 3.1.2) A2G coordinates setting **menu**
-- --
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
-- --
-- #### 3.1.3. A2G coordinates setting **methods** -- ### 3.1.3) A2G coordinates setting **methods**
-- --
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
@@ -104,14 +98,14 @@
-- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- --
-- #### 3.1.4. A2G coordinates setting - additional notes -- ### 3.1.4) A2G coordinates setting - additional notes
-- --
-- One additional note on BR. In a situation when a BR coordinate should be given, -- One additional note on BR. In a situation when a BR coordinate should be given,
-- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied! -- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied!
-- --
-- ### 3.2. **A2A coordinates** formatting -- ## 3.2) **A2A coordinates** formatting
-- --
-- #### 3.2.1. A2A coordinates setting **types** -- ### 3.2.1) A2A coordinates setting **types**
-- --
-- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications. -- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications.
-- --
@@ -121,11 +115,11 @@
-- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. -- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
-- - A2A BULLS: [Bullseye](http://falcon4.wikidot.com/concepts:bullseye). -- - A2A BULLS: [Bullseye](http://falcon4.wikidot.com/concepts:bullseye).
-- --
-- #### 3.2.2. A2A coordinates setting **menu** -- ### 3.2.2) A2A coordinates setting **menu**
-- --
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
-- --
-- #### 3.2.3. A2A coordinates setting **methods** -- ### 3.2.3) A2A coordinates setting **methods**
-- --
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
@@ -135,34 +129,34 @@
-- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
-- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default. -- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default.
-- --
-- #### 3.2.4. A2A coordinates settings - additional notes -- ### 3.2.4) A2A coordinates settings - additional notes
-- --
-- One additional note on BRAA. In a situation when a BRAA coordinate should be given, -- One additional note on BRAA. In a situation when a BRAA coordinate should be given,
-- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied! -- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied!
-- --
-- ### 3.3. **Measurements** formatting -- ## 3.3) **Measurements** formatting
-- --
-- #### 3.3.1. Measurements setting **types** -- ### 3.3.1) Measurements setting **types**
-- --
-- Will customize the measurements system being used as part as part of the Command Center communications. -- Will customize the measurements system being used as part as part of the Command Center communications.
-- --
-- - **Metrics** system: Applies the [Metrics system](https://en.wikipedia.org/wiki/Metric_system) ... -- - **Metrics** system: Applies the [Metrics system](https://en.wikipedia.org/wiki/Metric_system) ...
-- - **Imperial** system: Applies the [Imperial system](https://en.wikipedia.org/wiki/Imperial_units) ... -- - **Imperial** system: Applies the [Imperial system](https://en.wikipedia.org/wiki/Imperial_units) ...
-- --
-- #### 3.3.2. Measurements setting **menu** -- ### 3.3.2) Measurements setting **menu**
-- --
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
-- --
-- #### 3.3.3. Measurements setting **methods** -- ### 3.3.3) Measurements setting **methods**
-- --
-- There are different methods that can be used to change the **Default settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **Default settings** using the \_SETTINGS object.
-- --
-- - @{#SETTINGS.SetMetric}(): Enable the Metric system. -- - @{#SETTINGS.SetMetric}(): Enable the Metric system.
-- - @{#SETTINGS.SetImperial}(): Enable the Imperial system. -- - @{#SETTINGS.SetImperial}(): Enable the Imperial system.
-- --
-- ### 3.4. **Message** display times -- ## 3.4) **Message** display times
-- --
-- #### 3.4.1. Message setting **types** -- ### 3.4.1) Message setting **types**
-- --
-- There are various **Message Types** that will influence the duration how long a message will appear as part of the Command Center communications. -- There are various **Message Types** that will influence the duration how long a message will appear as part of the Command Center communications.
-- --
@@ -172,7 +166,7 @@
-- - **Overview report**: Provides a short report overview, the summary of the report. -- - **Overview report**: Provides a short report overview, the summary of the report.
-- - **Detailed report**: Provides a complete report. -- - **Detailed report**: Provides a complete report.
-- --
-- #### 3.4.2. Message setting **menu** -- ### 3.4.2) Message setting **menu**
-- --
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
-- --
@@ -181,7 +175,7 @@
-- So the player can choose its own amount of seconds how long a message should be displayed of a certain type. -- So the player can choose its own amount of seconds how long a message should be displayed of a certain type.
-- Note that **Update** messages can be chosen not to be displayed at all! -- Note that **Update** messages can be chosen not to be displayed at all!
-- --
-- #### 3.4.3. Message setting **methods** -- ### 3.4.3) Message setting **methods**
-- --
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
-- --
@@ -729,7 +723,7 @@ do -- SETTINGS
end end
--- Removes the player menu from the PlayerUnit. --- Removes the player menu from the PlayerUnit.
--- @param #SETTINGS self -- @param #SETTINGS self
-- @param Wrapper.Client#CLIENT PlayerUnit -- @param Wrapper.Client#CLIENT PlayerUnit
-- @return #SETTINGS self -- @return #SETTINGS self
function SETTINGS:RemovePlayerMenu( PlayerUnit ) function SETTINGS:RemovePlayerMenu( PlayerUnit )

View File

@@ -1,7 +1,5 @@
--- **Core** -- SPAWN class dynamically spawns new groups of units in your missions. --- **Core** -- SPAWN class dynamically spawns new groups of units in your missions.
-- --
-- ![Banner Image](..\Presentations\SPAWN\SPAWN.JPG)
--
-- === -- ===
-- --
-- The documentation of the SPAWN class can be found further in this document. -- The documentation of the SPAWN class can be found further in this document.
@@ -21,7 +19,8 @@
-- --
-- === -- ===
-- --
-- @module Spawn -- @module Core.Spawn
-- @image Core_Spawn.JPG
--- SPAWN Class --- SPAWN Class
@@ -37,13 +36,8 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # SPAWN class, extends @{Base#BASE} --- Allows to spawn dynamically new @{Core.Group}s.
-- --
-- -- ![Banner Image](..\Presentations\SPAWN\SPAWN.JPG)
--
-- ===
--
-- The SPAWN class allows to spawn dynamically new groups.
-- Each SPAWN object needs to be have related **template groups** setup in the Mission Editor (ME), -- Each SPAWN object needs to be have related **template groups** setup in the Mission Editor (ME),
-- which is a normal group with the **Late Activation** flag set. -- which is a normal group with the **Late Activation** flag set.
-- This template group will never be activated in your mission. -- This template group will never be activated in your mission.
@@ -67,8 +61,8 @@
-- **Limits** can be set on how many groups can be spawn in each SPAWN object, -- **Limits** can be set on how many groups can be spawn in each SPAWN object,
-- using the method @{#SPAWN.InitLimit}. SPAWN has 2 kind of limits: -- using the method @{#SPAWN.InitLimit}. SPAWN has 2 kind of limits:
-- --
-- * The maximum amount of @{Unit}s that can be **alive** at the same time... -- * The maximum amount of @{Wrapper.Unit}s that can be **alive** at the same time...
-- * The maximum amount of @{Group}s that can be **spawned**... This is more of a **resource**-type of limit. -- * The maximum amount of @{Wrapper.Group}s that can be **spawned**... This is more of a **resource**-type of limit.
-- --
-- When new groups get spawned using the **Spawn** methods, -- When new groups get spawned using the **Spawn** methods,
-- it will be evaluated whether any limits have been reached. -- it will be evaluated whether any limits have been reached.
@@ -82,7 +76,7 @@
-- with unlimited resources = :InitLimit( 100, 0 ) and 10 groups are alive, but two groups have only one unit alive in the group, -- with unlimited resources = :InitLimit( 100, 0 ) and 10 groups are alive, but two groups have only one unit alive in the group,
-- then a sequent Spawn(Scheduled) will allow a new group to be spawned!!! -- then a sequent Spawn(Scheduled) will allow a new group to be spawned!!!
-- --
-- ### IMPORTANT!! If a limit has been reached, it is possible that a **Spawn** method returns **nil**, meaning, no @{Group} had been spawned!!! -- ### IMPORTANT!! If a limit has been reached, it is possible that a **Spawn** method returns **nil**, meaning, no @{Wrapper.Group} had been spawned!!!
-- --
-- Spawned groups get **the same name** as the name of the template group. -- Spawned groups get **the same name** as the name of the template group.
-- Spawned units in those groups keep _by default_ **the same name** as the name of the template group. -- Spawned units in those groups keep _by default_ **the same name** as the name of the template group.
@@ -117,7 +111,7 @@
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods: -- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
-- --
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition). -- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition).
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition), and gives each spawned @{Group} an different name. -- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition), and gives each spawned @{Wrapper.Group} an different name.
-- --
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned. -- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons. -- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
@@ -149,15 +143,15 @@
-- --
-- ### Position randomization -- ### Position randomization
-- --
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens. -- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Wrapper.Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius. -- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Wrapper.Unit}s in the @{Wrapper.Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor. -- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
-- --
-- ### Enable / Disable AI when spawning a new @{Group} -- ### Enable / Disable AI when spawning a new @{Wrapper.Group}
-- --
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object. -- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Wrapper.Group} object.
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object. -- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Wrapper.Group} object.
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object. -- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Wrapper.Group} object.
-- --
-- ### Limit scheduled spawning -- ### Limit scheduled spawning
-- --
@@ -165,11 +159,11 @@
-- --
-- ### Delay initial scheduled spawn -- ### Delay initial scheduled spawn
-- --
-- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when scheduled spawning the first @{Group} object. -- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when scheduled spawning the first @{Wrapper.Group} object.
-- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when scheduled spawning the first @{Group} object. -- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when scheduled spawning the first @{Wrapper.Group} object.
-- * @{#SPAWN.InitDelayOff}(): Turns the inital delay Off when scheduled spawning the first @{Group} object. -- * @{#SPAWN.InitDelayOff}(): Turns the inital delay Off when scheduled spawning the first @{Wrapper.Group} object.
-- --
-- ### Repeat spawned @{Group}s upon landing -- ### Repeat spawned @{Wrapper.Group}s upon landing
-- --
-- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed. -- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed.
-- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp. -- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp.
@@ -186,11 +180,11 @@
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air). -- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ). -- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}. -- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}. -- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Wrapper.Unit}.
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}. -- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
-- * @{#SPAWN.SpawnAtAirbase}(): Spawn a new group at an @{Airbase}, which can be an airdrome, ship or helipad. -- * @{#SPAWN.SpawnAtAirbase}(): Spawn a new group at an @{Wrapper.Airbase}, which can be an airdrome, ship or helipad.
-- --
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object. -- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{Wrapper.Group#GROUP.New} object, that contains a reference to the DCSGroup object.
-- You can use the @{GROUP} object to do further actions with the DCSGroup. -- You can use the @{GROUP} object to do further actions with the DCSGroup.
-- --
-- ### **Scheduled** spawning methods -- ### **Scheduled** spawning methods
@@ -226,21 +220,21 @@
-- This models AI that has succesfully returned to their airbase, to restart their combat activities. -- This models AI that has succesfully returned to their airbase, to restart their combat activities.
-- Check the @{#SPAWN.InitCleanUp}() for further info. -- Check the @{#SPAWN.InitCleanUp}() for further info.
-- --
-- ## Catch the @{Group} Spawn Event in a callback function! -- ## Catch the @{Wrapper.Group} Spawn Event in a callback function!
-- --
-- When using the @{#SPAWN.SpawnScheduled)() method, new @{Group}s are created following the spawn time interval parameters. -- When using the @{#SPAWN.SpawnScheduled)() method, new @{Wrapper.Group}s are created following the spawn time interval parameters.
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event. -- When a new @{Wrapper.Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
-- The SPAWN class supports this functionality through the method @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ), -- The SPAWN class supports this functionality through the method @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ),
-- which takes a function as a parameter that you can define locally. -- which takes a function as a parameter that you can define locally.
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter. -- Whenever a new @{Wrapper.Group} is spawned, the given function is called, and the @{Wrapper.Group} that was just spawned, is given as a parameter.
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object. -- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Wrapper.Group} object.
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method. -- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
-- --
-- ## Delay the initial spawning -- ## Delay the initial spawning
-- --
-- When using the @{#SPAWN.SpawnScheduled)() method, the default behaviour of this method will be that it will spawn the initial (first) @{Group} -- When using the @{#SPAWN.SpawnScheduled)() method, the default behaviour of this method will be that it will spawn the initial (first) @{Wrapper.Group}
-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to -- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
-- activate a delay before the first @{Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that -- activate a delay before the first @{Wrapper.Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a -- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
-- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used. -- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used.
-- --
@@ -270,7 +264,7 @@ SPAWN.Takeoff = {
-- @list <Core.Zone#ZONE_BASE> SpawnZone -- @list <Core.Zone#ZONE_BASE> SpawnZone
--- Creates the main object to spawn a @{Group} defined in the DCS ME. --- Creates the main object to spawn a @{Wrapper.Group} defined in the DCS ME.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix. -- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
-- @return #SPAWN -- @return #SPAWN
@@ -288,20 +282,20 @@ function SPAWN:New( SpawnTemplatePrefix )
self.SpawnIndex = 0 self.SpawnIndex = 0
self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart. self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart.
self.AliveUnits = 0 -- Contains the counter how many units are currently alive self.AliveUnits = 0 -- Contains the counter how many units are currently alive
self.SpawnIsScheduled = false -- Reflects if the spawning for this SpawnTemplatePrefix is going to be scheduled or not. self.SpawnIsScheduled = false -- Reflects if the spawning for this SpawnTemplatePrefix is going to be scheduled or not.
self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning. self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts. self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
self.SpawnInitLimit = false -- By default, no InitLimit self.SpawnInitLimit = false -- By default, no InitLimit
self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time. self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned. self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false. self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false.
self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned. self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
self.AIOnOff = true -- The AI is on by default when spawning a group. self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil -- No grouping self.Grouping = nil -- No grouping
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@@ -334,19 +328,19 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
self.SpawnIndex = 0 self.SpawnIndex = 0
self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart. self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart.
self.AliveUnits = 0 -- Contains the counter how many units are currently alive self.AliveUnits = 0 -- Contains the counter how many units are currently alive
self.SpawnIsScheduled = false -- Reflects if the spawning for this SpawnTemplatePrefix is going to be scheduled or not. self.SpawnIsScheduled = false -- Reflects if the spawning for this SpawnTemplatePrefix is going to be scheduled or not.
self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! self.SpawnTemplate = self._GetTemplate( self, SpawnTemplatePrefix ) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning. self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts. self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
self.SpawnInitLimit = false -- By default, no InitLimit self.SpawnInitLimit = false -- By default, no InitLimit
self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time. self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned. self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false. self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false.
self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned. self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
self.AIOnOff = true -- The AI is on by default when spawning a group. self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil self.Grouping = nil
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
@@ -361,6 +355,55 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
end end
--- Creates a new SPAWN instance to create new groups based on the provided template.
-- @param #SPAWN self
-- @param #table SpawnTemplate is the Template of the Group. This must be a valid Group Template structure!
-- @param #string SpawnTemplatePrefix is the name of the Group that will be given at each spawn.
-- @param #string SpawnAliasPrefix (optional) is the name that will be given to the Group at runtime.
-- @return #SPAWN
-- @usage
-- -- Create a new SPAWN object based on a Group Template defined from scratch.
-- Spawn_BE_KA50 = SPAWN:NewWithAlias( 'BE KA-50@RAMP-Ground Defense', 'Helicopter Attacking a City' )
-- @usage
-- -- Create a new CSAR_Spawn object based on a normal Group Template to spawn a soldier.
-- local CSAR_Spawn = SPAWN:NewWithFromTemplate( Template, "CSAR", "Pilot" )
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix )
local self = BASE:Inherit( self, BASE:New() )
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
if SpawnTemplate then
self.SpawnTemplate = SpawnTemplate -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
self.SpawnTemplatePrefix = SpawnTemplatePrefix
self.SpawnAliasPrefix = SpawnAliasPrefix
self.SpawnIndex = 0
self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart.
self.AliveUnits = 0 -- Contains the counter how many units are currently alive
self.SpawnIsScheduled = false -- Reflects if the spawning for this SpawnTemplatePrefix is going to be scheduled or not.
self.Repeat = false -- Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
self.UnControlled = false -- When working in UnControlled mode, all planes are Spawned in UnControlled mode before the scheduler starts.
self.SpawnInitLimit = false -- By default, no InitLimit.
self.SpawnMaxUnitsAlive = 0 -- The maximum amount of groups that can be alive of SpawnTemplatePrefix at the same time.
self.SpawnMaxGroups = 0 -- The maximum amount of groups that can be spawned.
self.SpawnRandomize = false -- Sets the randomization flag of new Spawned units to false.
self.SpawnVisible = false -- Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else
error( "There is no template provided for SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
end
self:SetEventPriority( 5 )
self.SpawnHookScheduler = SCHEDULER:New( nil )
return self
end
--- Limits the Maximum amount of Units that can be alive at the same time, and the maximum amount of groups that can be spawned. --- Limits the Maximum amount of Units that can be alive at the same time, and the maximum amount of groups that can be spawned.
-- Note that this method is exceptionally important to balance the performance of the mission. Depending on the machine etc, a mission can only process a maximum amount of units. -- Note that this method is exceptionally important to balance the performance of the mission. Depending on the machine etc, a mission can only process a maximum amount of units.
-- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this method should be used... -- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this method should be used...
@@ -395,16 +438,82 @@ end
-- and any spaces before and after the resulting name are removed. -- and any spaces before and after the resulting name are removed.
-- IMPORTANT! This method MUST be the first used after :New !!! -- IMPORTANT! This method MUST be the first used after :New !!!
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean KeepUnitNames (optional) If true, the unit names are kept, false or not provided to make new unit names.
-- @return #SPAWN self -- @return #SPAWN self
function SPAWN:InitKeepUnitNames() function SPAWN:InitKeepUnitNames( KeepUnitNames )
self:F( ) self:F( )
self.SpawnInitKeepUnitNames = true self.SpawnInitKeepUnitNames = KeepUnitNames or true
return self return self
end end
--- Flags that the spawned groups must be spawned late activated.
-- @param #SPAWN self
-- @param #boolean LateActivated (optional) If true, the spawned groups are late activated.
-- @return #SPAWN self
function SPAWN:InitLateActivated( LateActivated )
self:F( )
self.LateActivated = LateActivated or true
return self
end
--- Defines the Heading for the new spawned units.
-- The heading can be given as one fixed degree, or can be randomized between minimum and maximum degrees.
-- @param #SPAWN self
-- @param #number HeadingMin The minimum or fixed heading in degrees.
-- @param #number HeadingMax (optional) The maximum heading in degrees. This there is no maximum heading, then the heading will be fixed for all units using minimum heading.
-- @return #SPAWN self
-- @usage
--
-- Spawn = SPAWN:New( ... )
--
-- -- Spawn the units pointing to 100 degrees.
-- Spawn:InitHeading( 100 )
--
-- -- Spawn the units pointing between 100 and 150 degrees.
-- Spawn:InitHeading( 100, 150 )
--
function SPAWN:InitHeading( HeadingMin, HeadingMax )
self:F( )
self.SpawnInitHeadingMin = HeadingMin
self.SpawnInitHeadingMax = HeadingMax
return self
end
function SPAWN:InitCoalition( Coalition )
self:F( )
self.SpawnInitCoalition = Coalition
return self
end
function SPAWN:InitCountry( Country )
self:F( )
self.SpawnInitCountry = Country
return self
end
function SPAWN:InitCategory( Category )
self:F( )
self.SpawnInitCategory = Category
return self
end
--- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups. --- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #number SpawnStartPoint is the waypoint where the randomization begins. -- @param #number SpawnStartPoint is the waypoint where the randomization begins.
@@ -436,11 +545,11 @@ function SPAWN:InitRandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius,
return self return self
end end
--- Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens. --- Randomizes the position of @{Wrapper.Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean RandomizePosition If true, SPAWN will perform the randomization of the @{Group}s position between a given outer and inner radius. -- @param #boolean RandomizePosition If true, SPAWN will perform the randomization of the @{Wrapper.Group}s position between a given outer and inner radius.
-- @param Dcs.DCSTypes#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned. -- @param DCS#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned.
-- @param Dcs.DCSTypes#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned. -- @param DCS#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned.
-- @return #SPAWN -- @return #SPAWN
function SPAWN:InitRandomizePosition( RandomizePosition, OuterRadius, InnerRadius ) function SPAWN:InitRandomizePosition( RandomizePosition, OuterRadius, InnerRadius )
self:F( { self.SpawnTemplatePrefix, RandomizePosition, OuterRadius, InnerRadius } ) self:F( { self.SpawnTemplatePrefix, RandomizePosition, OuterRadius, InnerRadius } )
@@ -460,8 +569,8 @@ end
--- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius. --- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius. -- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius.
-- @param Dcs.DCSTypes#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned. -- @param DCS#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned.
-- @param Dcs.DCSTypes#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned. -- @param DCS#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned.
-- @return #SPAWN -- @return #SPAWN
-- @usage -- @usage
-- -- NATO helicopters engaging in the battle field. -- -- NATO helicopters engaging in the battle field.
@@ -789,7 +898,7 @@ function SPAWN:InitArray( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY )
end end
do -- AI methods do -- AI methods
--- Turns the AI On or Off for the @{Group} when spawning. --- Turns the AI On or Off for the @{Wrapper.Group} when spawning.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean AIOnOff A value of true sets the AI On, a value of false sets the AI Off. -- @param #boolean AIOnOff A value of true sets the AI On, a value of false sets the AI Off.
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
@@ -799,7 +908,7 @@ do -- AI methods
return self return self
end end
--- Turns the AI On for the @{Group} when spawning. --- Turns the AI On for the @{Wrapper.Group} when spawning.
-- @param #SPAWN self -- @param #SPAWN self
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
function SPAWN:InitAIOn() function SPAWN:InitAIOn()
@@ -807,7 +916,7 @@ do -- AI methods
return self:InitAIOnOff( true ) return self:InitAIOnOff( true )
end end
--- Turns the AI Off for the @{Group} when spawning. --- Turns the AI Off for the @{Wrapper.Group} when spawning.
-- @param #SPAWN self -- @param #SPAWN self
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
function SPAWN:InitAIOff() function SPAWN:InitAIOff()
@@ -818,8 +927,8 @@ do -- AI methods
end -- AI methods end -- AI methods
do -- Delay methods do -- Delay methods
--- Turns the Delay On or Off for the first @{Group} scheduled spawning. --- Turns the Delay On or Off for the first @{Wrapper.Group} scheduled spawning.
-- The default value is that for scheduled spawning, there is an initial delay when spawning the first @{Group}. -- The default value is that for scheduled spawning, there is an initial delay when spawning the first @{Wrapper.Group}.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #boolean DelayOnOff A value of true sets the Delay On, a value of false sets the Delay Off. -- @param #boolean DelayOnOff A value of true sets the Delay On, a value of false sets the Delay Off.
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
@@ -829,7 +938,7 @@ do -- Delay methods
return self return self
end end
--- Turns the Delay On for the @{Group} when spawning. --- Turns the Delay On for the @{Wrapper.Group} when spawning.
-- @param #SPAWN self -- @param #SPAWN self
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
function SPAWN:InitDelayOn() function SPAWN:InitDelayOn()
@@ -837,7 +946,7 @@ do -- Delay methods
return self:InitDelayOnOff( true ) return self:InitDelayOnOff( true )
end end
--- Turns the Delay Off for the @{Group} when spawning. --- Turns the Delay Off for the @{Wrapper.Group} when spawning.
-- @param #SPAWN self -- @param #SPAWN self
-- @return #SPAWN The SPAWN object -- @return #SPAWN The SPAWN object
function SPAWN:InitDelayOff() function SPAWN:InitDelayOff()
@@ -941,6 +1050,18 @@ function SPAWN:SpawnWithIndex( SpawnIndex )
end end
end end
-- If Heading is given, point all the units towards the given Heading.
if self.SpawnInitHeadingMin then
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].heading = self.SpawnInitHeadingMax and math.random( self.SpawnInitHeadingMin, self.SpawnInitHeadingMax ) or self.SpawnInitHeadingMin
end
end
SpawnTemplate.CategoryID = self.SpawnInitCategory or SpawnTemplate.CategoryID
SpawnTemplate.CountryID = self.SpawnInitCountry or SpawnTemplate.CountryID
SpawnTemplate.CoalitionID = self.SpawnInitCoalition or SpawnTemplate.CoalitionID
if SpawnTemplate.CategoryID == Group.Category.HELICOPTER or SpawnTemplate.CategoryID == Group.Category.AIRPLANE then if SpawnTemplate.CategoryID == Group.Category.HELICOPTER or SpawnTemplate.CategoryID == Group.Category.AIRPLANE then
if SpawnTemplate.route.points[1].type == "TakeOffParking" then if SpawnTemplate.route.points[1].type == "TakeOffParking" then
SpawnTemplate.uncontrolled = self.SpawnUnControlled SpawnTemplate.uncontrolled = self.SpawnUnControlled
@@ -1045,7 +1166,7 @@ end
--- Allows to place a CallFunction hook when a new group spawns. --- Allows to place a CallFunction hook when a new group spawns.
-- The provided method will be called when a new group is spawned, including its given parameters. -- The provided method will be called when a new group is spawned, including its given parameters.
-- The first parameter of the SpawnFunction is the @{Group#GROUP} that was spawned. -- The first parameter of the SpawnFunction is the @{Wrapper.Group#GROUP} that was spawned.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #function SpawnCallBackFunction The function to be called when a group spawns. -- @param #function SpawnCallBackFunction The function to be called when a group spawns.
-- @param SpawnFunctionArguments A random amount of arguments to be provided to the function when the group spawns. -- @param SpawnFunctionArguments A random amount of arguments to be provided to the function when the group spawns.
@@ -1073,28 +1194,28 @@ function SPAWN:OnSpawnGroup( SpawnCallBackFunction, ... )
return self return self
end end
--- Will spawn a group at an @{Airbase}. --- Will spawn a group at an @{Wrapper.Airbase}.
-- This method is mostly advisable to be used if you want to simulate spawning units at an airbase. -- This method is mostly advisable to be used if you want to simulate spawning units at an airbase.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
-- --
-- The @{Airbase#AIRBASE} object must refer to a valid airbase known in the sim. -- The @{Wrapper.Airbase#AIRBASE} object must refer to a valid airbase known in the sim.
-- You can use the following enumerations to search for the pre-defined airbases on the current known maps of DCS: -- You can use the following enumerations to search for the pre-defined airbases on the current known maps of DCS:
-- --
-- * @{Airbase#AIRBASE.Caucasus}: The airbases on the Caucasus map. -- * @{Wrapper.Airbase#AIRBASE.Caucasus}: The airbases on the Caucasus map.
-- * @{Airbase#AIRBASE.Nevada}: The airbases on the Nevada (NTTR) map. -- * @{Wrapper.Airbase#AIRBASE.Nevada}: The airbases on the Nevada (NTTR) map.
-- * @{Airbase#AIRBASE.Normandy}: The airbases on the Normandy map. -- * @{Wrapper.Airbase#AIRBASE.Normandy}: The airbases on the Normandy map.
-- --
-- Use the method @{Airbase#AIRBASE.FindByName}() to retrieve the airbase object. -- Use the method @{Wrapper.Airbase#AIRBASE.FindByName}() to retrieve the airbase object.
-- The known AIRBASE objects are automatically imported at mission start by MOOSE. -- The known AIRBASE objects are automatically imported at mission start by MOOSE.
-- Therefore, there isn't any New() constructor defined for AIRBASE objects. -- Therefore, there isn't any New() constructor defined for AIRBASE objects.
-- --
-- Ships and Farps are added within the mission, and are therefore not known. -- Ships and Farps are added within the mission, and are therefore not known.
-- For these AIRBASE objects, there isn't an @{Airbase#AIRBASE} enumeration defined. -- For these AIRBASE objects, there isn't an @{Wrapper.Airbase#AIRBASE} enumeration defined.
-- You need to provide the **exact name** of the airbase as the parameter to the @{Airbase#AIRBASE.FindByName}() method! -- You need to provide the **exact name** of the airbase as the parameter to the @{Wrapper.Airbase#AIRBASE.FindByName}() method!
-- --
-- @param #SPAWN self -- @param #SPAWN self
-- @param Wrapper.Airbase#AIRBASE SpawnAirbase The @{Airbase} where to spawn the group. -- @param Wrapper.Airbase#AIRBASE SpawnAirbase The @{Wrapper.Airbase} where to spawn the group.
-- @param #SPAWN.Takeoff Takeoff (optional) The location and takeoff method. Default is Hot. -- @param #SPAWN.Takeoff Takeoff (optional) The location and takeoff method. Default is Hot.
-- @param #number TakeoffAltitude (optional) The altitude above the ground. -- @param #number TakeoffAltitude (optional) The altitude above the ground.
-- @return Wrapper.Group#GROUP that was spawned. -- @return Wrapper.Group#GROUP that was spawned.
@@ -1224,7 +1345,7 @@ end
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 coordinates where to spawn the group. -- @param DCS#Vec3 Vec3 The Vec3 coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. -- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned. -- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned. -- @return #nil Nothing was spawned.
@@ -1247,14 +1368,20 @@ function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
self:T( { "Current point of ", self.SpawnTemplatePrefix, Vec3 } ) self:T( { "Current point of ", self.SpawnTemplatePrefix, Vec3 } )
local TemplateHeight = SpawnTemplate.route.points[1].alt local TemplateHeight = SpawnTemplate.route and SpawnTemplate.route.points[1].alt or nil
SpawnTemplate.route = SpawnTemplate.route or {}
SpawnTemplate.route.points = SpawnTemplate.route.points or {}
SpawnTemplate.route.points[1] = SpawnTemplate.route.points[1] or {}
SpawnTemplate.route.points[1].x = SpawnTemplate.route.points[1].x or 0
SpawnTemplate.route.points[1].y = SpawnTemplate.route.points[1].y or 0
-- Translate the position of the Group Template to the Vec3. -- Translate the position of the Group Template to the Vec3.
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, #SpawnTemplate.units do
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y ) --self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
local UnitTemplate = SpawnTemplate.units[UnitID] local UnitTemplate = SpawnTemplate.units[UnitID]
local SX = UnitTemplate.x local SX = UnitTemplate.x or 0
local SY = UnitTemplate.y local SY = UnitTemplate.y or 0
local BX = SpawnTemplate.route.points[1].x local BX = SpawnTemplate.route.points[1].x
local BY = SpawnTemplate.route.points[1].y local BY = SpawnTemplate.route.points[1].y
local TX = Vec3.x + ( SX - BX ) local TX = Vec3.x + ( SX - BX )
@@ -1266,7 +1393,6 @@ function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
end end
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y ) self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y )
end end
SpawnTemplate.route.points[1].x = Vec3.x SpawnTemplate.route.points[1].x = Vec3.x
SpawnTemplate.route.points[1].y = Vec3.z SpawnTemplate.route.points[1].y = Vec3.z
if SpawnTemplate.CategoryID ~= Group.Category.SHIP then if SpawnTemplate.CategoryID ~= Group.Category.SHIP then
@@ -1283,12 +1409,53 @@ function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
return nil return nil
end end
--- Will spawn a group from a Coordinate in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Core.Point#Coordinate Coordinate The Coordinate coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
function SPAWN:SpawnFromCoordinate( Coordinate, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, SpawnIndex } )
return self:SpawnFromVec3( Coordinate:GetVec3(), SpawnIndex )
end
--- Will spawn a group from a PointVec3 in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
-- @usage
--
-- local SpawnPointVec3 = ZONE:New( ZoneName ):GetPointVec3( 2000 ) -- Get the center of the ZONE object at 2000 meters from the ground.
--
-- -- Spawn at the zone center position at 2000 meters from the ground!
-- SpawnAirplanes:SpawnFromPointVec3( SpawnPointVec3 )
--
function SPAWN:SpawnFromPointVec3( PointVec3, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, SpawnIndex } )
return self:SpawnFromVec3( PointVec3:GetVec3(), SpawnIndex )
end
--- Will spawn a group from a Vec2 in 3D space. --- Will spawn a group from a Vec2 in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles. -- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 coordinates where to spawn the group. -- @param DCS#Vec2 Vec2 The Vec2 coordinates where to spawn the group.
-- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone. -- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone.
-- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone. -- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. -- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
@@ -1317,6 +1484,35 @@ function SPAWN:SpawnFromVec2( Vec2, MinHeight, MaxHeight, SpawnIndex )
end end
--- Will spawn a group from a POINT_VEC2 in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 coordinates where to spawn the group.
-- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone.
-- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned.
-- @return #nil Nothing was spawned.
-- @usage
--
-- local SpawnPointVec2 = ZONE:New( ZoneName ):GetPointVec2()
--
-- -- Spawn at the zone center position at the height specified in the ME of the group template!
-- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2 )
--
-- -- Spawn from the static position at the height randomized between 2000 and 4000 meters.
-- SpawnAirplanes:SpawnFromPointVec2( SpawnPointVec2, 2000, 4000 )
--
function SPAWN:SpawnFromPointVec2( PointVec2, MinHeight, MaxHeight, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex } )
return self:SpawnFromVec2( PointVec2:GetVec2(), MinHeight, MaxHeight, SpawnIndex )
end
--- Will spawn a group from a hosting unit. This method is mostly advisable to be used if you want to simulate spawning from air units, like helicopters, which are dropping infantry into a defined Landing Zone. --- Will spawn a group from a hosting unit. This method is mostly advisable to be used if you want to simulate spawning from air units, like helicopters, which are dropping infantry into a defined Landing Zone.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. -- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed. -- You can use the returned group to further define the route to be followed.
@@ -1377,12 +1573,12 @@ function SPAWN:SpawnFromStatic( HostStatic, MinHeight, MaxHeight, SpawnIndex )
end end
--- Will spawn a Group within a given @{Zone}. --- Will spawn a Group within a given @{Zone}.
-- The @{Zone} can be of any type derived from @{Zone#ZONE_BASE}. -- The @{Zone} can be of any type derived from @{Core.Zone#ZONE_BASE}.
-- Once the @{Group} is spawned within the zone, the @{Group} will continue on its route. -- Once the @{Wrapper.Group} is spawned within the zone, the @{Wrapper.Group} will continue on its route.
-- The **first waypoint** (where the group is spawned) is replaced with the zone location coordinates. -- The **first waypoint** (where the group is spawned) is replaced with the zone location coordinates.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Core.Zone#ZONE Zone The zone where the group is to be spawned. -- @param Core.Zone#ZONE Zone The zone where the group is to be spawned.
-- @param #boolean RandomizeGroup (optional) Randomization of the @{Group} position in the zone. -- @param #boolean RandomizeGroup (optional) Randomization of the @{Wrapper.Group} position in the zone.
-- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone. -- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone.
-- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone. -- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. -- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
@@ -1478,12 +1674,12 @@ function SPAWN:SpawnGroupName( SpawnIndex )
end end
--- Will find the first alive @{Group} it has spawned, and return the alive @{Group} object and the first Index where the first alive @{Group} object has been found. --- Will find the first alive @{Wrapper.Group} it has spawned, and return the alive @{Wrapper.Group} object and the first Index where the first alive @{Wrapper.Group} object has been found.
-- @param #SPAWN self -- @param #SPAWN self
-- @return Wrapper.Group#GROUP, #number The @{Group} object found, the new Index where the group was found. -- @return Wrapper.Group#GROUP, #number The @{Wrapper.Group} object found, the new Index where the group was found.
-- @return #nil, #nil When no group is found, #nil is returned. -- @return #nil, #nil When no group is found, #nil is returned.
-- @usage -- @usage
-- -- Find the first alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission. -- -- Find the first alive @{Wrapper.Group} object of the SpawnPlanes SPAWN object @{Wrapper.Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup() -- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup()
-- while GroupPlane ~= nil do -- while GroupPlane ~= nil do
-- -- Do actions with the GroupPlane object. -- -- Do actions with the GroupPlane object.
@@ -1503,13 +1699,13 @@ function SPAWN:GetFirstAliveGroup()
end end
--- Will find the next alive @{Group} object from a given Index, and return a reference to the alive @{Group} object and the next Index where the alive @{Group} has been found. --- Will find the next alive @{Wrapper.Group} object from a given Index, and return a reference to the alive @{Wrapper.Group} object and the next Index where the alive @{Wrapper.Group} has been found.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #number SpawnIndexStart A Index holding the start position to search from. This method can also be used to find the first alive @{Group} object from the given Index. -- @param #number SpawnIndexStart A Index holding the start position to search from. This method can also be used to find the first alive @{Wrapper.Group} object from the given Index.
-- @return Wrapper.Group#GROUP, #number The next alive @{Group} object found, the next Index where the next alive @{Group} object was found. -- @return Wrapper.Group#GROUP, #number The next alive @{Wrapper.Group} object found, the next Index where the next alive @{Wrapper.Group} object was found.
-- @return #nil, #nil When no alive @{Group} object is found from the start Index position, #nil is returned. -- @return #nil, #nil When no alive @{Wrapper.Group} object is found from the start Index position, #nil is returned.
-- @usage -- @usage
-- -- Find the first alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission. -- -- Find the first alive @{Wrapper.Group} object of the SpawnPlanes SPAWN object @{Wrapper.Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup() -- local GroupPlane, Index = SpawnPlanes:GetFirstAliveGroup()
-- while GroupPlane ~= nil do -- while GroupPlane ~= nil do
-- -- Do actions with the GroupPlane object. -- -- Do actions with the GroupPlane object.
@@ -1529,12 +1725,12 @@ function SPAWN:GetNextAliveGroup( SpawnIndexStart )
return nil, nil return nil, nil
end end
--- Will find the last alive @{Group} object, and will return a reference to the last live @{Group} object and the last Index where the last alive @{Group} object has been found. --- Will find the last alive @{Wrapper.Group} object, and will return a reference to the last live @{Wrapper.Group} object and the last Index where the last alive @{Wrapper.Group} object has been found.
-- @param #SPAWN self -- @param #SPAWN self
-- @return Wrapper.Group#GROUP, #number The last alive @{Group} object found, the last Index where the last alive @{Group} object was found. -- @return Wrapper.Group#GROUP, #number The last alive @{Wrapper.Group} object found, the last Index where the last alive @{Wrapper.Group} object was found.
-- @return #nil, #nil When no alive @{Group} object is found, #nil is returned. -- @return #nil, #nil When no alive @{Wrapper.Group} object is found, #nil is returned.
-- @usage -- @usage
-- -- Find the last alive @{Group} object of the SpawnPlanes SPAWN object @{Group} collection that it has spawned during the mission. -- -- Find the last alive @{Wrapper.Group} object of the SpawnPlanes SPAWN object @{Wrapper.Group} collection that it has spawned during the mission.
-- local GroupPlane, Index = SpawnPlanes:GetLastAliveGroup() -- local GroupPlane, Index = SpawnPlanes:GetLastAliveGroup()
-- if GroupPlane then -- GroupPlane can be nil!!! -- if GroupPlane then -- GroupPlane can be nil!!!
-- -- Do actions with the GroupPlane object. -- -- Do actions with the GroupPlane object.
@@ -1583,7 +1779,7 @@ end
-- The method will search for a #-mark, and will return the text before the #-mark. -- The method will search for a #-mark, and will return the text before the #-mark.
-- It will return nil of no prefix was found. -- It will return nil of no prefix was found.
-- @param #SPAWN self -- @param #SPAWN self
-- @param Dcs.DCSWrapper.Unit#UNIT DCSUnit The @{DCSUnit} to be searched. -- @param DCS#UNIT DCSUnit The @{DCSUnit} to be searched.
-- @return #string The prefix -- @return #string The prefix
-- @return #nil Nothing found -- @return #nil Nothing found
function SPAWN:_GetPrefixFromGroup( SpawnGroup ) function SPAWN:_GetPrefixFromGroup( SpawnGroup )
@@ -1693,7 +1889,10 @@ function SPAWN:_GetTemplate( SpawnTemplatePrefix )
local SpawnTemplate = nil local SpawnTemplate = nil
SpawnTemplate = routines.utils.deepCopy( _DATABASE.Templates.Groups[SpawnTemplatePrefix].Template ) local Template = _DATABASE.Templates.Groups[SpawnTemplatePrefix].Template
self:F( { Template = Template } )
SpawnTemplate = UTILS.DeepCopy( _DATABASE.Templates.Groups[SpawnTemplatePrefix].Template )
if SpawnTemplate == nil then if SpawnTemplate == nil then
error( 'No Template returned for SpawnTemplatePrefix = ' .. SpawnTemplatePrefix ) error( 'No Template returned for SpawnTemplatePrefix = ' .. SpawnTemplatePrefix )
@@ -1715,12 +1914,17 @@ end
function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) --R2.2 function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) --R2.2
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } ) self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } )
local SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix ) -- if not self.SpawnTemplate then
-- self.SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
-- end
local SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
--local SpawnTemplate = self.SpawnTemplate
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex ) SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
SpawnTemplate.groupId = nil SpawnTemplate.groupId = nil
--SpawnTemplate.lateActivation = false --SpawnTemplate.lateActivation = false
SpawnTemplate.lateActivation = false SpawnTemplate.lateActivation = self.LateActivated or false
if SpawnTemplate.CategoryID == Group.Category.GROUND then if SpawnTemplate.CategoryID == Group.Category.GROUND then
self:T3( "For ground units, visible needs to be false..." ) self:T3( "For ground units, visible needs to be false..." )
@@ -1808,7 +2012,7 @@ function SPAWN:_RandomizeTemplate( SpawnIndex )
if self.SpawnRandomizeTemplate then if self.SpawnRandomizeTemplate then
self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefixTable[ math.random( 1, #self.SpawnTemplatePrefixTable ) ] self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefixTable[ math.random( 1, #self.SpawnTemplatePrefixTable ) ]
self.SpawnGroups[SpawnIndex].SpawnTemplate = self:_Prepare( self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix, SpawnIndex ) self.SpawnGroups[SpawnIndex].SpawnTemplate = self:_Prepare( self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix, SpawnIndex )
self.SpawnGroups[SpawnIndex].SpawnTemplate.route = routines.utils.deepCopy( self.SpawnTemplate.route ) self.SpawnGroups[SpawnIndex].SpawnTemplate.route = UTILS.DeepCopy( self.SpawnTemplate.route )
self.SpawnGroups[SpawnIndex].SpawnTemplate.x = self.SpawnTemplate.x self.SpawnGroups[SpawnIndex].SpawnTemplate.x = self.SpawnTemplate.x
self.SpawnGroups[SpawnIndex].SpawnTemplate.y = self.SpawnTemplate.y self.SpawnGroups[SpawnIndex].SpawnTemplate.y = self.SpawnTemplate.y
self.SpawnGroups[SpawnIndex].SpawnTemplate.start_time = self.SpawnTemplate.start_time self.SpawnGroups[SpawnIndex].SpawnTemplate.start_time = self.SpawnTemplate.start_time

View File

@@ -1,7 +1,5 @@
--- **Core** -- Spawn dynamically new STATICs in your missions. --- **Core** -- Spawn dynamically new STATICs in your missions.
-- --
-- ![Banner Image](..\Presentations\SPAWNSTATIC\Dia1.JPG)
--
-- === -- ===
-- --
-- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation. -- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation.
@@ -29,7 +27,8 @@
-- --
-- === -- ===
-- --
-- @module SpawnStatic -- @module Core.SpawnStatic
-- @image Core_Spawnstatic.JPG
@@ -37,9 +36,7 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # SPAWNSTATIC class, extends @{Base#BASE} --- Allows to spawn dynamically new @{Static}s.
--
-- The SPAWNSTATIC class allows to spawn dynamically new @{Static}s.
-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME), -- Through creating a copy of an existing static object template as defined in the Mission Editor (ME),
-- SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), and "copy" -- SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), and "copy"
-- these properties to create a new static object and place it at the desired coordinate. -- these properties to create a new static object and place it at the desired coordinate.
@@ -81,14 +78,16 @@ SPAWNSTATIC = {
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix. -- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
-- @return #SPAWNSTATIC -- @return #SPAWNSTATIC
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID ) --R2.1 function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID ) --R2.1
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
self:F( { SpawnTemplatePrefix } ) self:F( { SpawnTemplatePrefix } )
local TemplateStatic = StaticObject.getByName( SpawnTemplatePrefix ) local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticUnitTemplate( SpawnTemplatePrefix )
if TemplateStatic then if TemplateStatic then
self.SpawnTemplatePrefix = SpawnTemplatePrefix self.SpawnTemplatePrefix = SpawnTemplatePrefix
self.CountryID = CountryID self.CountryID = SpawnCountryID or CountryID
self.CategoryID = CategoryID
self.CoalitionID = CoalitionID
self.SpawnIndex = 0 self.SpawnIndex = 0
else else
error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" ) error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
@@ -116,6 +115,7 @@ function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory,
return self return self
end end
--- Creates a new @{Static} at the original position. --- Creates a new @{Static} at the original position.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360. -- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
@@ -124,22 +124,28 @@ end
function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3 function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3
self:F( { Heading, NewName } ) self:F( { Heading, NewName } )
local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID]
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) if StaticTemplate then
StaticTemplate.heading = ( Heading / 180 ) * math.pi
StaticTemplate.CountryID = nil local CountryID = self.CountryID
StaticTemplate.CoalitionID = nil local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( self.CountryID, StaticTemplate ) StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
StaticTemplate.heading = ( Heading / 180 ) * math.pi
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
self.SpawnIndex = self.SpawnIndex + 1
self.SpawnIndex = self.SpawnIndex + 1 return Static
end
return Static
return nil
end end
@@ -153,32 +159,101 @@ end
function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1 function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
self:F( { PointVec2, Heading, NewName } ) self:F( { PointVec2, Heading, NewName } )
local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID] local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
if StaticTemplate then
local CountryID = self.CountryID
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
StaticTemplate.x = PointVec2.x
StaticTemplate.y = PointVec2.z
StaticTemplate.units = nil
StaticTemplate.route = nil
StaticTemplate.groupId = nil
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
StaticTemplate.heading = ( Heading / 180 ) * math.pi
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
self.SpawnIndex = self.SpawnIndex + 1
return Static
end
return nil
end
--- Creates the original @{Static} at a POINT_VEC2.
-- @param #SPAWNSTATIC self
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @param #string (optional) The name of the new static.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:ReSpawn()
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix ) local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
StaticTemplate.x = PointVec2.x if StaticTemplate then
StaticTemplate.y = PointVec2.z
StaticTemplate.units = nil local CountryID = self.CountryID
StaticTemplate.route = nil local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
StaticTemplate.groupId = nil
StaticTemplate.units = nil
StaticTemplate.route = nil
StaticTemplate.groupId = nil
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
return Static
end
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex ) return nil
StaticTemplate.heading = ( Heading / 180 ) * math.pi
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( self.CountryID, StaticTemplate )
self.SpawnIndex = self.SpawnIndex + 1
return Static
end end
--- Creates the original @{Static} at a POINT_VEC2.
-- @param #SPAWNSTATIC self
-- @param Core.Point#COORDINATE Coordinate The 2D coordinate where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:ReSpawnAt( Coordinate, Heading )
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
if StaticTemplate then
local CountryID = self.CountryID
StaticTemplate.x = Coordinate.x
StaticTemplate.y = Coordinate.z
StaticTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
return Static
end
return nil
end
--- Creates a new @{Static} from a @{Zone}. --- Creates a new @{Static} from a @{Zone}.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static. -- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.

View File

@@ -1,14 +1,12 @@
--- **Core** -- Management of SPOT logistics, that can be transported from and to transportation carriers. --- **Core** -- Management of SPOT logistics, that can be transported from and to transportation carriers.
-- --
-- ![Banner Image](..\Presentations\SPOT\Dia1.JPG)
--
-- === -- ===
-- --
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to: -- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
-- --
-- * Spot for a defined duration. -- * Spot for a defined duration.
-- * wiggle the spot at the target. -- * wiggle the spot at the target.
-- * Provide a @{Unit} as a target, instead of a point. -- * Provide a @{Wrapper.Unit} as a target, instead of a point.
-- * Implement a status machine, LaseOn, LaseOff. -- * Implement a status machine, LaseOn, LaseOff.
-- --
-- === -- ===
@@ -38,7 +36,8 @@
-- --
-- === -- ===
-- --
-- @module Spot -- @module Core.Spot
-- @image Core_Spot.JPG
do do
@@ -47,13 +46,11 @@ do
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- # SPOT class, extends @{Fsm#FSM} --- Implements the target spotting or marking functionality, but adds additional luxury to be able to:
--
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
-- --
-- * Mark targets for a defined duration. -- * Mark targets for a defined duration.
-- * wiggle the spot at the target. -- * wiggle the spot at the target.
-- * Provide a @{Unit} as a target, instead of a point. -- * Provide a @{Wrapper.Unit} as a target, instead of a point.
-- * Implement a status machine, LaseOn, LaseOff. -- * Implement a status machine, LaseOn, LaseOff.
-- --
-- ## 1. SPOT constructor -- ## 1. SPOT constructor

View File

@@ -10,7 +10,9 @@
-- --
-- === -- ===
-- --
-- @module UserFlag -- @module Core.UserFlag
-- @image Core_Userflag.JPG
--
do -- UserFlag do -- UserFlag
@@ -18,11 +20,9 @@ do -- UserFlag
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # USERFLAG class, extends @{Base#BASE} --- Management of DCS User Flags.
-- --
-- Management of DCS User Flags. -- ## USERFLAG constructor
--
-- ## 1. USERFLAG constructor
-- --
-- * @{#USERFLAG.New}(): Creates a new USERFLAG object. -- * @{#USERFLAG.New}(): Creates a new USERFLAG object.
-- --

View File

@@ -10,7 +10,8 @@
-- --
-- === -- ===
-- --
-- @module UserSound -- @module Core.UserSound
-- @image Core_Usersound.JPG
do -- UserSound do -- UserSound
@@ -18,11 +19,9 @@ do -- UserSound
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # USERSOUND class, extends @{Base#BASE} --- Management of DCS User Sound.
-- --
-- Management of DCS User Sound. -- ## USERSOUND constructor
--
-- ## 1. USERSOUND constructor
-- --
-- * @{#USERSOUND.New}(): Creates a new USERSOUND object. -- * @{#USERSOUND.New}(): Creates a new USERSOUND object.
-- --
@@ -80,7 +79,7 @@ do -- UserSound
--- Play the usersound to the given coalition. --- Play the usersound to the given coalition.
-- @param #USERSOUND self -- @param #USERSOUND self
-- @param Dcs.DCScoalition#coalition Coalition The coalition to play the usersound to. -- @param DCS#coalition Coalition The coalition to play the usersound to.
-- @return #USERSOUND The usersound instance. -- @return #USERSOUND The usersound instance.
-- @usage -- @usage
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" ) -- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
@@ -96,7 +95,7 @@ do -- UserSound
--- Play the usersound to the given country. --- Play the usersound to the given country.
-- @param #USERSOUND self -- @param #USERSOUND self
-- @param Dcs.DCScountry#country Country The country to play the usersound to. -- @param DCS#country Country The country to play the usersound to.
-- @return #USERSOUND The usersound instance. -- @return #USERSOUND The usersound instance.
-- @usage -- @usage
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" ) -- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
@@ -110,9 +109,9 @@ do -- UserSound
end end
--- Play the usersound to the given @{Group}. --- Play the usersound to the given @{Wrapper.Group}.
-- @param #USERSOUND self -- @param #USERSOUND self
-- @param Wrapper.Group#GROUP Group The @{Group} to play the usersound to. -- @param Wrapper.Group#GROUP Group The @{Wrapper.Group} to play the usersound to.
-- @return #USERSOUND The usersound instance. -- @return #USERSOUND The usersound instance.
-- @usage -- @usage
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" ) -- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )

View File

@@ -7,7 +7,8 @@
-- --
-- === -- ===
-- --
-- @module Velocity -- @module Core.Velocity
-- @image MOOSE.JPG
do -- Velocity do -- Velocity
@@ -15,11 +16,9 @@ do -- Velocity
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # VELOCITY class, extends @{Base#BASE} --- VELOCITY models a speed, which can be expressed in various formats according the Settings.
-- --
-- VELOCITY models a speed, which can be expressed in various formats according the Settings. -- ## VELOCITY constructor
--
-- ## 1. VELOCITY constructor
-- --
-- * @{#VELOCITY.New}(): Creates a new VELOCITY object. -- * @{#VELOCITY.New}(): Creates a new VELOCITY object.
-- --
@@ -125,7 +124,7 @@ do -- VELOCITY_POSITIONABLE
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # VELOCITY_POSITIONABLE class, extends @{Base#BASE} --- # VELOCITY_POSITIONABLE class, extends @{Core.Base#BASE}
-- --
-- VELOCITY_POSITIONABLE monitors the speed of an @{Positionable} in the simulation, which can be expressed in various formats according the Settings. -- VELOCITY_POSITIONABLE monitors the speed of an @{Positionable} in the simulation, which can be expressed in various formats according the Settings.
-- --

View File

@@ -1,7 +1,5 @@
--- **Core** -- ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**. --- **Core** -- ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**.
-- --
-- ![Banner Image](..\Presentations\ZONE\Dia1.JPG)
--
-- === -- ===
-- --
-- There are essentially two core functions that zones accomodate: -- There are essentially two core functions that zones accomodate:
@@ -12,7 +10,7 @@
-- The object classes are using the zone classes to test the zone boundaries, which can take various forms: -- The object classes are using the zone classes to test the zone boundaries, which can take various forms:
-- --
-- * Test if completely within the zone. -- * Test if completely within the zone.
-- * Test if partly within the zone (for @{Group#GROUP} objects). -- * Test if partly within the zone (for @{Wrapper.Group#GROUP} objects).
-- * Test if not in the zone. -- * Test if not in the zone.
-- * Distance to the nearest intersecting point of the zone. -- * Distance to the nearest intersecting point of the zone.
-- * Distance to the center of the zone. -- * Distance to the center of the zone.
@@ -23,9 +21,9 @@
-- * @{#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes. -- * @{#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes.
-- * @{#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius. -- * @{#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- * @{#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor. -- * @{#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor.
-- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Unit#UNIT} with a radius. -- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Wrapper.Unit#UNIT} with a radius.
-- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. -- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius.
-- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. -- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- --
-- === -- ===
-- --
@@ -34,7 +32,8 @@
-- --
-- === -- ===
-- --
-- @module Zone -- @module Core.Zone
-- @image Core_Zones.JPG
--- @type ZONE_BASE --- @type ZONE_BASE
@@ -43,9 +42,7 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # ZONE_BASE class, extends @{Base#BASE} --- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
-- --
-- ## Each zone has a name: -- ## Each zone has a name:
-- --
@@ -53,7 +50,7 @@
-- * @{#ZONE_BASE.SetName}(): Sets the name of the zone. -- * @{#ZONE_BASE.SetName}(): Sets the name of the zone.
-- --
-- --
-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: -- ## Each zone implements two polymorphic functions defined in @{Core.Zone#ZONE_BASE}:
-- --
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone. -- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone.
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone. -- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone.
@@ -95,10 +92,10 @@ ZONE_BASE = {
--- The ZONE_BASE.BoundingSquare --- The ZONE_BASE.BoundingSquare
-- @type ZONE_BASE.BoundingSquare -- @type ZONE_BASE.BoundingSquare
-- @field Dcs.DCSTypes#Distance x1 The lower x coordinate (left down) -- @field DCS#Distance x1 The lower x coordinate (left down)
-- @field Dcs.DCSTypes#Distance y1 The lower y coordinate (left down) -- @field DCS#Distance y1 The lower y coordinate (left down)
-- @field Dcs.DCSTypes#Distance x2 The higher x coordinate (right up) -- @field DCS#Distance x2 The higher x coordinate (right up)
-- @field Dcs.DCSTypes#Distance y2 The higher y coordinate (right up) -- @field DCS#Distance y2 The higher y coordinate (right up)
--- ZONE_BASE constructor --- ZONE_BASE constructor
@@ -114,6 +111,8 @@ function ZONE_BASE:New( ZoneName )
return self return self
end end
--- Returns the name of the zone. --- Returns the name of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #string The name of the zone. -- @return #string The name of the zone.
@@ -136,7 +135,7 @@ end
--- Returns if a Vec2 is within the zone. --- Returns if a Vec2 is within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 to test. -- @param DCS#Vec2 Vec2 The Vec2 to test.
-- @return #boolean true if the Vec2 is within the zone. -- @return #boolean true if the Vec2 is within the zone.
function ZONE_BASE:IsVec2InZone( Vec2 ) function ZONE_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 ) self:F2( Vec2 )
@@ -146,13 +145,19 @@ end
--- Returns if a Vec3 is within the zone. --- Returns if a Vec3 is within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test. -- @param DCS#Vec3 Vec3 The point to test.
-- @return #boolean true if the Vec3 is within the zone. -- @return #boolean true if the Vec3 is within the zone.
function ZONE_BASE:IsVec3InZone( Vec3 ) function ZONE_BASE:IsVec3InZone( Vec3 )
self:F2( Vec3 )
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } ) local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
return InZone
end
--- Returns if a Coordinate is within the zone.
-- @param #ZONE_BASE self
-- @param Core.Point#COORDINATE Coordinate The coordinate to test.
-- @return #boolean true if the coordinate is within the zone.
function ZONE_BASE:IsCoordinateInZone( Coordinate )
local InZone = self:IsVec2InZone( Coordinate:GetVec2() )
return InZone return InZone
end end
@@ -161,10 +166,7 @@ end
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test. -- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test.
-- @return #boolean true if the PointVec2 is within the zone. -- @return #boolean true if the PointVec2 is within the zone.
function ZONE_BASE:IsPointVec2InZone( PointVec2 ) function ZONE_BASE:IsPointVec2InZone( PointVec2 )
self:F2( PointVec2 )
local InZone = self:IsVec2InZone( PointVec2:GetVec2() ) local InZone = self:IsVec2InZone( PointVec2:GetVec2() )
return InZone return InZone
end end
@@ -173,26 +175,21 @@ end
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test. -- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test.
-- @return #boolean true if the PointVec3 is within the zone. -- @return #boolean true if the PointVec3 is within the zone.
function ZONE_BASE:IsPointVec3InZone( PointVec3 ) function ZONE_BASE:IsPointVec3InZone( PointVec3 )
self:F2( PointVec3 )
local InZone = self:IsPointVec2InZone( PointVec3 ) local InZone = self:IsPointVec2InZone( PointVec3 )
return InZone return InZone
end end
--- Returns the @{DCSTypes#Vec2} coordinate of the zone. --- Returns the @{DCS#Vec2} coordinate of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #nil. -- @return #nil.
function ZONE_BASE:GetVec2() function ZONE_BASE:GetVec2()
self:F2( self.ZoneName )
return nil return nil
end end
--- Returns a @{Point#POINT_VEC2} of the zone. --- Returns a @{Core.Point#POINT_VEC2} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone. -- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
function ZONE_BASE:GetPointVec2() function ZONE_BASE:GetPointVec2()
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -207,7 +204,7 @@ function ZONE_BASE:GetPointVec2()
end end
--- Returns a @{Point#COORDINATE} of the zone. --- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Core.Point#COORDINATE The Coordinate of the zone. -- @return Core.Point#COORDINATE The Coordinate of the zone.
function ZONE_BASE:GetCoordinate() function ZONE_BASE:GetCoordinate()
@@ -223,10 +220,10 @@ function ZONE_BASE:GetCoordinate()
end end
--- Returns the @{DCSTypes#Vec3} of the zone. --- Returns the @{DCS#Vec3} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The Vec3 of the zone. -- @return DCS#Vec3 The Vec3 of the zone.
function ZONE_BASE:GetVec3( Height ) function ZONE_BASE:GetVec3( Height )
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -241,9 +238,9 @@ function ZONE_BASE:GetVec3( Height )
return Vec3 return Vec3
end end
--- Returns a @{Point#POINT_VEC3} of the zone. --- Returns a @{Core.Point#POINT_VEC3} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone. -- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
function ZONE_BASE:GetPointVec3( Height ) function ZONE_BASE:GetPointVec3( Height )
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -257,9 +254,9 @@ function ZONE_BASE:GetPointVec3( Height )
return PointVec3 return PointVec3
end end
--- Returns a @{Point#COORDINATE} of the zone. --- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#COORDINATE The Coordinate of the zone. -- @return Core.Point#COORDINATE The Coordinate of the zone.
function ZONE_BASE:GetCoordinate( Height ) --R2.1 function ZONE_BASE:GetCoordinate( Height ) --R2.1
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -274,21 +271,21 @@ function ZONE_BASE:GetCoordinate( Height ) --R2.1
end end
--- Define a random @{DCSTypes#Vec2} within the zone. --- Define a random @{DCS#Vec2} within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates. -- @return DCS#Vec2 The Vec2 coordinates.
function ZONE_BASE:GetRandomVec2() function ZONE_BASE:GetRandomVec2()
return nil return nil
end end
--- Define a random @{Point#POINT_VEC2} within the zone. --- Define a random @{Core.Point#POINT_VEC2} within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. -- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
function ZONE_BASE:GetRandomPointVec2() function ZONE_BASE:GetRandomPointVec2()
return nil return nil
end end
--- Define a random @{Point#POINT_VEC3} within the zone. --- Define a random @{Core.Point#POINT_VEC3} within the zone.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates. -- @return Core.Point#POINT_VEC3 The PointVec3 coordinates.
function ZONE_BASE:GetRandomPointVec3() function ZONE_BASE:GetRandomPointVec3()
@@ -322,7 +319,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. -- @param ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
function ZONE_BASE:SetZoneProbability( ZoneProbability ) function ZONE_BASE:SetZoneProbability( ZoneProbability )
self:F2( ZoneProbability ) self:F( { self:GetName(), ZoneProbability = ZoneProbability } )
self.ZoneProbability = ZoneProbability or 1 self.ZoneProbability = ZoneProbability or 1
return self return self
@@ -341,6 +338,27 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor. -- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
-- @return #nil The zone is not selected taking into account the randomization probability factor. -- @return #nil The zone is not selected taking into account the randomization probability factor.
-- @usage
--
-- local ZoneArray = { ZONE:New( "Zone1" ), ZONE:New( "Zone2" ) }
--
-- -- We set a zone probability of 70% to the first zone and 30% to the second zone.
-- ZoneArray[1]:SetZoneProbability( 0.5 )
-- ZoneArray[2]:SetZoneProbability( 0.5 )
--
-- local ZoneSelected = nil
--
-- while ZoneSelected == nil do
-- for _, Zone in pairs( ZoneArray ) do
-- ZoneSelected = Zone:GetZoneMaybe()
-- if ZoneSelected ~= nil then
-- break
-- end
-- end
-- end
--
-- -- The result should be that Zone1 would be more probable selected than Zone2.
--
function ZONE_BASE:GetZoneMaybe() function ZONE_BASE:GetZoneMaybe()
self:F2() self:F2()
@@ -355,13 +373,11 @@ end
--- The ZONE_RADIUS class, defined by a zone name, a location and a radius. --- The ZONE_RADIUS class, defined by a zone name, a location and a radius.
-- @type ZONE_RADIUS -- @type ZONE_RADIUS
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone. -- @field DCS#Vec2 Vec2 The current location of the zone.
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone. -- @field DCS#Distance Radius The radius of the zone.
-- @extends #ZONE_BASE -- @extends #ZONE_BASE
--- # ZONE_RADIUS class, extends @{Zone#ZONE_BASE} --- The ZONE_RADIUS class defined by a zone name, a location and a radius.
--
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties. -- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties.
-- --
-- ## ZONE_RADIUS constructor -- ## ZONE_RADIUS constructor
@@ -375,17 +391,17 @@ end
-- --
-- ## Manage the location of the zone -- ## Manage the location of the zone
-- --
-- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCSTypes#Vec2} of the zone. -- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCS#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCSTypes#Vec2} of the zone. -- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCS#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCSTypes#Vec3} of the zone, taking an additional height parameter. -- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCS#Vec3} of the zone, taking an additional height parameter.
-- --
-- ## Zone point randomization -- ## Zone point randomization
-- --
-- Various functions exist to find random points within the zone. -- Various functions exist to find random points within the zone.
-- --
-- * @{#ZONE_RADIUS.GetRandomVec2}(): Gets a random 2D point in the zone. -- * @{#ZONE_RADIUS.GetRandomVec2}(): Gets a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone. -- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Core.Point#POINT_VEC2} object representing a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight. -- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Core.Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
-- --
-- @field #ZONE_RADIUS -- @field #ZONE_RADIUS
ZONE_RADIUS = { ZONE_RADIUS = {
@@ -395,8 +411,8 @@ ZONE_RADIUS = {
--- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius. --- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #string ZoneName Name of the zone. -- @param #string ZoneName Name of the zone.
-- @param Dcs.DCSTypes#Vec2 Vec2 The location of the zone. -- @param DCS#Vec2 Vec2 The location of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone. -- @param DCS#Distance Radius The radius of the zone.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:New( ZoneName, Vec2, Radius ) function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
@@ -410,8 +426,9 @@ end
--- Bounds the zone with tires. --- Bounds the zone with tires.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number Points (optional) The amount of points in the circle. -- @param #number Points (optional) The amount of points in the circle. Default 360.
-- @param #boolean UnBound If true the tyres will be destroyed. -- @param DCS#country.id CountryID The country id of the tire objects, e.g. country.id.USA for blue or country.id.RUSSIA for red.
-- @param #boolean UnBound (Optional) If true the tyres will be destroyed.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound )
@@ -490,7 +507,7 @@ end
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Utilities.Utils#FLARECOLOR FlareColor The flare color. -- @param Utilities.Utils#FLARECOLOR FlareColor The flare color.
-- @param #number Points (optional) The amount of points in the circle. -- @param #number Points (optional) The amount of points in the circle.
-- @param Dcs.DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare. -- @param DCS#Azimuth Azimuth (optional) Azimuth The azimuth of the flare.
-- @param #number AddHeight (optional) The height to be added for the smoke. -- @param #number AddHeight (optional) The height to be added for the smoke.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight ) function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight )
@@ -518,7 +535,7 @@ end
--- Returns the radius of the zone. --- Returns the radius of the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @return Dcs.DCSTypes#Distance The radius of the zone. -- @return DCS#Distance The radius of the zone.
function ZONE_RADIUS:GetRadius() function ZONE_RADIUS:GetRadius()
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -529,8 +546,8 @@ end
--- Sets the radius of the zone. --- Sets the radius of the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone. -- @param DCS#Distance Radius The radius of the zone.
-- @return Dcs.DCSTypes#Distance The radius of the zone. -- @return DCS#Distance The radius of the zone.
function ZONE_RADIUS:SetRadius( Radius ) function ZONE_RADIUS:SetRadius( Radius )
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -540,9 +557,9 @@ function ZONE_RADIUS:SetRadius( Radius )
return self.Radius return self.Radius
end end
--- Returns the @{DCSTypes#Vec2} of the zone. --- Returns the @{DCS#Vec2} of the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @return Dcs.DCSTypes#Vec2 The location of the zone. -- @return DCS#Vec2 The location of the zone.
function ZONE_RADIUS:GetVec2() function ZONE_RADIUS:GetVec2()
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -551,10 +568,10 @@ function ZONE_RADIUS:GetVec2()
return self.Vec2 return self.Vec2
end end
--- Sets the @{DCSTypes#Vec2} of the zone. --- Sets the @{DCS#Vec2} of the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Dcs.DCSTypes#Vec2 Vec2 The new location of the zone. -- @param DCS#Vec2 Vec2 The new location of the zone.
-- @return Dcs.DCSTypes#Vec2 The new location of the zone. -- @return DCS#Vec2 The new location of the zone.
function ZONE_RADIUS:SetVec2( Vec2 ) function ZONE_RADIUS:SetVec2( Vec2 )
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -565,10 +582,10 @@ function ZONE_RADIUS:SetVec2( Vec2 )
return self.Vec2 return self.Vec2
end end
--- Returns the @{DCSTypes#Vec3} of the ZONE_RADIUS. --- Returns the @{DCS#Vec3} of the ZONE_RADIUS.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The point of the zone. -- @return DCS#Vec3 The point of the zone.
function ZONE_RADIUS:GetVec3( Height ) function ZONE_RADIUS:GetVec3( Height )
self:F2( { self.ZoneName, Height } ) self:F2( { self.ZoneName, Height } )
@@ -603,6 +620,7 @@ function ZONE_RADIUS:Scan( ObjectCategories )
self.ScanData = {} self.ScanData = {}
self.ScanData.Coalitions = {} self.ScanData.Coalitions = {}
self.ScanData.Scenery = {} self.ScanData.Scenery = {}
self.ScanData.Units = {}
local ZoneCoord = self:GetCoordinate() local ZoneCoord = self:GetCoordinate()
local ZoneRadius = self:GetRadius() local ZoneRadius = self:GetRadius()
@@ -625,6 +643,7 @@ function ZONE_RADIUS:Scan( ObjectCategories )
(ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
local CoalitionDCSUnit = ZoneObject:getCoalition() local CoalitionDCSUnit = ZoneObject:getCoalition()
self.ScanData.Coalitions[CoalitionDCSUnit] = true self.ScanData.Coalitions[CoalitionDCSUnit] = true
self.ScanData.Units[ZoneObject] = ZoneObject
self:F( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } ) self:F( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
end end
if ObjectCategory == Object.Category.SCENERY then if ObjectCategory == Object.Category.SCENERY then
@@ -643,6 +662,12 @@ function ZONE_RADIUS:Scan( ObjectCategories )
end end
function ZONE_RADIUS:GetScannedUnits()
return self.ScanData.Units
end
function ZONE_RADIUS:CountScannedCoalitions() function ZONE_RADIUS:CountScannedCoalitions()
local Count = 0 local Count = 0
@@ -804,7 +829,7 @@ end
--- Returns if a location is within the zone. --- Returns if a location is within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test. -- @param DCS#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone. -- @return #boolean true if the location is within the zone.
function ZONE_RADIUS:IsVec2InZone( Vec2 ) function ZONE_RADIUS:IsVec2InZone( Vec2 )
self:F2( Vec2 ) self:F2( Vec2 )
@@ -822,7 +847,7 @@ end
--- Returns if a point is within the zone. --- Returns if a point is within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test. -- @param DCS#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone. -- @return #boolean true if the point is within the zone.
function ZONE_RADIUS:IsVec3InZone( Vec3 ) function ZONE_RADIUS:IsVec3InZone( Vec3 )
self:F2( Vec3 ) self:F2( Vec3 )
@@ -836,7 +861,7 @@ end
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Dcs.DCSTypes#Vec2 The random location within the zone. -- @return DCS#Vec2 The random location within the zone.
function ZONE_RADIUS:GetRandomVec2( inner, outer ) function ZONE_RADIUS:GetRandomVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
@@ -854,11 +879,11 @@ function ZONE_RADIUS:GetRandomVec2( inner, outer )
return Point return Point
end end
--- Returns a @{Point#POINT_VEC2} object reflecting a random 2D location within the zone. --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec2( inner, outer ) function ZONE_RADIUS:GetRandomPointVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
@@ -873,7 +898,7 @@ end
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Dcs.DCSTypes#Vec3 The random location within the zone. -- @return DCS#Vec3 The random location within the zone.
function ZONE_RADIUS:GetRandomVec3( inner, outer ) function ZONE_RADIUS:GetRandomVec3( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
@@ -885,11 +910,11 @@ function ZONE_RADIUS:GetRandomVec3( inner, outer )
end end
--- Returns a @{Point#POINT_VEC3} object reflecting a random 3D location within the zone. --- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC3 The @{Point#POINT_VEC3} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC3 The @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec3( inner, outer ) function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
@@ -901,7 +926,7 @@ function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
end end
--- Returns a @{Point#COORDINATE} object reflecting a random 3D location within the zone. --- Returns a @{Core.Point#COORDINATE} object reflecting a random 3D location within the zone.
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
@@ -922,11 +947,33 @@ end
-- @extends #ZONE_RADIUS -- @extends #ZONE_RADIUS
--- # ZONE class, extends @{Zone#ZONE_RADIUS} --- The ZONE class, defined by the zone name as defined within the Mission Editor.
--
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
-- --
-- ## ZONE constructor
--
-- * @{#ZONE.New}(): Constructor. This will search for a trigger zone with the name given, and will return for you a ZONE object.
--
-- ## Declare a ZONE directly in the DCS mission editor!
--
-- You can declare a ZONE using the DCS mission editor by adding a trigger zone in the mission editor.
--
-- Then during mission startup, when loading Moose.lua, this trigger zone will be detected as a ZONE declaration.
-- Within the background, a ZONE object will be created within the @{Core.Database}.
-- The ZONE name will be the trigger zone name.
--
-- So, you can search yourself for the ZONE object by using the @{#ZONE.FindByName}() method.
-- In this example, `local TriggerZone = ZONE:FindByName( "DefenseZone" )` would return the ZONE object
-- that was created at mission startup, and reference it into the `TriggerZone` local object.
--
-- Refer to mission `ZON-110` for a demonstration.
--
-- This is especially handy if you want to quickly setup a SET_ZONE...
-- So when you would declare `local SetZone = SET_ZONE:New():FilterPrefixes( "Defense" ):FilterStart()`,
-- then SetZone would contain the ZONE object `DefenseZone` as part of the zone collection,
-- without much scripting overhead!!!
--
--
-- @field #ZONE -- @field #ZONE
ZONE = { ZONE = {
ClassName="ZONE", ClassName="ZONE",
@@ -954,14 +1001,26 @@ function ZONE:New( ZoneName )
return self return self
end end
--- Find a zone in the _DATABASE using the name of the zone.
-- @param #ZONE_BASE self
-- @param #string ZoneName The name of the zone.
-- @return #ZONE_BASE self
function ZONE:FindByName( ZoneName )
local ZoneFound = _DATABASE:FindZone( ZoneName )
return ZoneFound
end
--- @type ZONE_UNIT --- @type ZONE_UNIT
-- @field Wrapper.Unit#UNIT ZoneUNIT -- @field Wrapper.Unit#UNIT ZoneUNIT
-- @extends Core.Zone#ZONE_RADIUS -- @extends Core.Zone#ZONE_RADIUS
--- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS} --- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
-- --
-- The ZONE_UNIT class defined by a zone attached to a @{Unit#UNIT} with a radius and optional x and y offsets. -- The ZONE_UNIT class defined by a zone attached to a @{Wrapper.Unit#UNIT} with a radius and optional offsets.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
-- --
-- @field #ZONE_UNIT -- @field #ZONE_UNIT
@@ -981,6 +1040,7 @@ ZONE_UNIT = {
-- theta The azimuth of the zone relative to unit -- theta The azimuth of the zone relative to unit
-- relative_to_unit If true, theta is measured clockwise from unit's direction else clockwise from north. If using dx, dy setting this to true makes +x parallel to unit heading. -- relative_to_unit If true, theta is measured clockwise from unit's direction else clockwise from north. If using dx, dy setting this to true makes +x parallel to unit heading.
-- dx, dy OR rho, theta may be used, not both. -- dx, dy OR rho, theta may be used, not both.
-- @return #ZONE_UNIT self -- @return #ZONE_UNIT self
function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset) function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
@@ -1002,13 +1062,16 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
self.ZoneUNIT = ZoneUNIT self.ZoneUNIT = ZoneUNIT
self.LastVec2 = ZoneUNIT:GetVec2() self.LastVec2 = ZoneUNIT:GetVec2()
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self )
return self return self
end end
--- Returns the current location of the @{Unit#UNIT}. --- Returns the current location of the @{Wrapper.Unit#UNIT}.
-- @param #ZONE_UNIT self -- @param #ZONE_UNIT self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location and the offset, if any. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Unit#UNIT}location and the offset, if any.
function ZONE_UNIT:GetVec2() function ZONE_UNIT:GetVec2()
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -1049,7 +1112,7 @@ end
--- Returns a random location within the zone. --- Returns a random location within the zone.
-- @param #ZONE_UNIT self -- @param #ZONE_UNIT self
-- @return Dcs.DCSTypes#Vec2 The random location within the zone. -- @return DCS#Vec2 The random location within the zone.
function ZONE_UNIT:GetRandomVec2() function ZONE_UNIT:GetRandomVec2()
self:F( self.ZoneName ) self:F( self.ZoneName )
@@ -1069,10 +1132,10 @@ function ZONE_UNIT:GetRandomVec2()
return RandomVec2 return RandomVec2
end end
--- Returns the @{DCSTypes#Vec3} of the ZONE_UNIT. --- Returns the @{DCS#Vec3} of the ZONE_UNIT.
-- @param #ZONE_UNIT self -- @param #ZONE_UNIT self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Dcs.DCSTypes#Vec3 The point of the zone. -- @return DCS#Vec3 The point of the zone.
function ZONE_UNIT:GetVec3( Height ) function ZONE_UNIT:GetVec3( Height )
self:F2( self.ZoneName ) self:F2( self.ZoneName )
@@ -1091,35 +1154,36 @@ end
-- @extends #ZONE_RADIUS -- @extends #ZONE_RADIUS
--- # ZONE_GROUP class, extends @{Zone#ZONE_RADIUS} --- The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
-- -- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- --
-- @field #ZONE_GROUP -- @field #ZONE_GROUP
ZONE_GROUP = { ZONE_GROUP = {
ClassName="ZONE_GROUP", ClassName="ZONE_GROUP",
} }
--- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Group#GROUP} and a radius. --- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Wrapper.Group#GROUP} and a radius.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @param #string ZoneName Name of the zone. -- @param #string ZoneName Name of the zone.
-- @param Wrapper.Group#GROUP ZoneGROUP The @{Group} as the center of the zone. -- @param Wrapper.Group#GROUP ZoneGROUP The @{Wrapper.Group} as the center of the zone.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone. -- @param DCS#Distance Radius The radius of the zone.
-- @return #ZONE_GROUP self -- @return #ZONE_GROUP self
function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius ) function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) ) local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) )
self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } ) self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } )
self._.ZoneGROUP = ZoneGROUP self._.ZoneGROUP = ZoneGROUP
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self )
return self return self
end end
--- Returns the current location of the @{Group}. --- Returns the current location of the @{Wrapper.Group}.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
function ZONE_GROUP:GetVec2() function ZONE_GROUP:GetVec2()
self:F( self.ZoneName ) self:F( self.ZoneName )
@@ -1130,9 +1194,9 @@ function ZONE_GROUP:GetVec2()
return ZoneVec2 return ZoneVec2
end end
--- Returns a random location within the zone of the @{Group}. --- Returns a random location within the zone of the @{Wrapper.Group}.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @return Dcs.DCSTypes#Vec2 The random location of the zone based on the @{Group} location. -- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
function ZONE_GROUP:GetRandomVec2() function ZONE_GROUP:GetRandomVec2()
self:F( self.ZoneName ) self:F( self.ZoneName )
@@ -1148,11 +1212,11 @@ function ZONE_GROUP:GetRandomVec2()
return Point return Point
end end
--- Returns a @{Point#POINT_VEC2} object reflecting a random 2D location within the zone. --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
function ZONE_GROUP:GetRandomPointVec2( inner, outer ) function ZONE_GROUP:GetRandomPointVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
@@ -1165,14 +1229,12 @@ end
--- @type ZONE_POLYGON_BASE --- @type ZONE_POLYGON_BASE
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}. -- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
-- @extends #ZONE_BASE -- @extends #ZONE_BASE
--- # ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE} --- The ZONE_POLYGON_BASE class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- -- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- The ZONE_POLYGON_BASE class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated. -- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
-- --
-- ## Zone point randomization -- ## Zone point randomization
@@ -1180,8 +1242,8 @@ end
-- Various functions exist to find random points within the zone. -- Various functions exist to find random points within the zone.
-- --
-- * @{#ZONE_POLYGON_BASE.GetRandomVec2}(): Gets a random 2D point in the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomVec2}(): Gets a random 2D point in the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Core.Point#POINT_VEC2} object representing a random 2D point within the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
-- --
-- @field #ZONE_POLYGON_BASE -- @field #ZONE_POLYGON_BASE
ZONE_POLYGON_BASE = { ZONE_POLYGON_BASE = {
@@ -1190,13 +1252,13 @@ ZONE_POLYGON_BASE = {
--- A points array. --- A points array.
-- @type ZONE_POLYGON_BASE.ListVec2 -- @type ZONE_POLYGON_BASE.ListVec2
-- @list <Dcs.DCSTypes#Vec2> -- @list <DCS#Vec2>
--- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCSTypes#Vec2}, forming a polygon. --- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCS#Vec2}, forming a polygon.
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected. -- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @param #string ZoneName Name of the zone. -- @param #string ZoneName Name of the zone.
-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCSTypes#Vec2}, forming a polygon.. -- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCS#Vec2}, forming a polygon..
-- @return #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) )
@@ -1217,7 +1279,7 @@ end
--- Returns the center location of the polygon. --- Returns the center location of the polygon.
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
function ZONE_POLYGON_BASE:GetVec2() function ZONE_POLYGON_BASE:GetVec2()
self:F( self.ZoneName ) self:F( self.ZoneName )
@@ -1324,7 +1386,7 @@ end
--- Returns if a location is within the zone. --- Returns if a location is within the zone.
-- Source learned and taken from: https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html -- Source learned and taken from: https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test. -- @param DCS#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone. -- @return #boolean true if the location is within the zone.
function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 ) function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 ) self:F2( Vec2 )
@@ -1352,9 +1414,9 @@ function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
return InPolygon return InPolygon
end end
--- Define a random @{DCSTypes#Vec2} within the zone. --- Define a random @{DCS#Vec2} within the zone.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinate. -- @return DCS#Vec2 The Vec2 coordinate.
function ZONE_POLYGON_BASE:GetRandomVec2() function ZONE_POLYGON_BASE:GetRandomVec2()
self:F2() self:F2()
@@ -1378,9 +1440,9 @@ function ZONE_POLYGON_BASE:GetRandomVec2()
return Vec2 return Vec2
end end
--- Return a @{Point#POINT_VEC2} object representing a random 2D point at landheight within the zone. --- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Point#POINT_VEC2} -- @return @{Core.Point#POINT_VEC2}
function ZONE_POLYGON_BASE:GetRandomPointVec2() function ZONE_POLYGON_BASE:GetRandomPointVec2()
self:F2() self:F2()
@@ -1391,9 +1453,9 @@ function ZONE_POLYGON_BASE:GetRandomPointVec2()
return PointVec2 return PointVec2
end end
--- Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. --- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Point#POINT_VEC3} -- @return @{Core.Point#POINT_VEC3}
function ZONE_POLYGON_BASE:GetRandomPointVec3() function ZONE_POLYGON_BASE:GetRandomPointVec3()
self:F2() self:F2()
@@ -1405,7 +1467,7 @@ function ZONE_POLYGON_BASE:GetRandomPointVec3()
end end
--- Return a @{Point#COORDINATE} object representing a random 3D point at landheight within the zone. --- Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone.
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return Core.Point#COORDINATE -- @return Core.Point#COORDINATE
function ZONE_POLYGON_BASE:GetRandomCoordinate() function ZONE_POLYGON_BASE:GetRandomCoordinate()
@@ -1446,18 +1508,36 @@ end
-- @extends #ZONE_POLYGON_BASE -- @extends #ZONE_POLYGON_BASE
--- # ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE} --- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- --
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. -- ## Declare a ZONE_POLYGON directly in the DCS mission editor!
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties. --
-- You can declare a ZONE_POLYGON using the DCS mission editor by adding the ~ZONE_POLYGON tag in the group name.
--
-- So, imagine you have a group declared in the mission editor, with group name `DefenseZone~ZONE_POLYGON`.
-- Then during mission startup, when loading Moose.lua, this group will be detected as a ZONE_POLYGON declaration.
-- Within the background, a ZONE_POLYGON object will be created within the @{Core.Database} using the properties of the group.
-- The ZONE_POLYGON name will be the group name without the ~ZONE_POLYGON tag.
--
-- So, you can search yourself for the ZONE_POLYGON by using the @{#ZONE_POLYGON.FindByName}() method.
-- In this example, `local PolygonZone = ZONE_POLYGON:FindByName( "DefenseZone" )` would return the ZONE_POLYGON object
-- that was created at mission startup, and reference it into the `PolygonZone` local object.
--
-- Mission `ZON-510` shows a demonstration of this feature or method.
--
-- This is especially handy if you want to quickly setup a SET_ZONE...
-- So when you would declare `local SetZone = SET_ZONE:New():FilterPrefixes( "Defense" ):FilterStart()`,
-- then SetZone would contain the ZONE_POLYGON object `DefenseZone` as part of the zone collection,
-- without much scripting overhead!!!
-- --
-- @field #ZONE_POLYGON -- @field #ZONE_POLYGON
ZONE_POLYGON = { ZONE_POLYGON = {
ClassName="ZONE_POLYGON", ClassName="ZONE_POLYGON",
} }
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the @{Group#GROUP} defined within the Mission Editor. --- Constructor to create a ZONE_POLYGON instance, taking the zone name and the @{Wrapper.Group#GROUP} defined within the Mission Editor.
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. -- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
-- @param #ZONE_POLYGON self -- @param #ZONE_POLYGON self
-- @param #string ZoneName Name of the zone. -- @param #string ZoneName Name of the zone.
-- @param Wrapper.Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape. -- @param Wrapper.Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape.
@@ -1473,8 +1553,8 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup )
end end
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the **name** of the @{Group#GROUP} defined within the Mission Editor. --- Constructor to create a ZONE_POLYGON instance, taking the zone name and the **name** of the @{Wrapper.Group#GROUP} defined within the Mission Editor.
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. -- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
-- @param #ZONE_POLYGON self -- @param #ZONE_POLYGON self
-- @param #string ZoneName Name of the zone. -- @param #string ZoneName Name of the zone.
-- @param #string GroupName The group name of the GROUP defining the waypoints within the Mission Editor to define the polygon shape. -- @param #string GroupName The group name of the GROUP defining the waypoints within the Mission Editor to define the polygon shape.
@@ -1491,3 +1571,15 @@ function ZONE_POLYGON:NewFromGroupName( GroupName )
return self return self
end end
--- Find a polygon zone in the _DATABASE using the name of the polygon zone.
-- @param #ZONE_POLYGON self
-- @param #string ZoneName The name of the polygon zone.
-- @return #ZONE_POLYGON self
function ZONE_POLYGON:FindByName( ZoneName )
local ZoneFound = _DATABASE:FindZone( ZoneName )
return ZoneFound
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSAirbase
--- Represents airbases: airdromes, helipads and ships with flying decks or landing pads.
-- @type Airbase
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
-- @field #Airbase.ID ID Identifier of an airbase. It assigned to an airbase by the Mission Editor automatically. This identifier is used in AI tasks to refer an airbase that exists (spawned and not dead) or not.
-- @field #Airbase.Category Category enum contains identifiers of airbase categories.
-- @field #Airbase.Desc Desc Airbase descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
--- Enum contains identifiers of airbase categories.
-- @type Airbase.Category
-- @field AIRDROME
-- @field HELIPAD
-- @field SHIP
--- Airbase descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
-- @type Airbase.Desc
-- @extends #Desc
-- @field #Airbase.Category category Category of the airbase type.
--- Returns airbase by its name. If no airbase found the function will return nil.
-- @function [parent=#Airbase] getByName
-- @param #string name
-- @return #Airbase
--- Returns airbase descriptor by type name. If no descriptor is found the function will return nil.
-- @function [parent=#Airbase] getDescByName
-- @param #TypeName typeName Airbase type name.
-- @return #Airbase.Desc
--- Returns Unit that is corresponded to the airbase. Works only for ships.
-- @function [parent=#Airbase] getUnit
-- @param self
-- @return Wrapper.Unit#Unit
--- Returns identifier of the airbase.
-- @function [parent=#Airbase] getID
-- @param self
-- @return #Airbase.ID
--- Returns the airbase's callsign - the localized string.
-- @function [parent=#Airbase] getCallsign
-- @param self
-- @return #string
--- Returns descriptor of the airbase.
-- @function [parent=#Airbase] getDesc
-- @param self
-- @return #Airbase.Desc
Airbase = {} --#Airbase

View File

@@ -1,20 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSCoalitionObject
--- @type CoalitionObject
-- @extends Dcs.DCSWrapper.Object#Object
coalition = {} --#coalition
--- Returns coalition of the object.
-- @function [parent=#CoalitionObject] getCoalition
-- @param #CoalitionObject self
-- @return Dcs.DCSTypes#coalition.side
--- Returns object country.
-- @function [parent=#CoalitionObject] getCountry
-- @param #CoalitionObject self
-- @return #country.id
CoalitionObject = {} --#CoalitionObject

View File

@@ -1,10 +0,0 @@
--- @module DCSCommand
--- @type Command
-- @field #string id
-- @field #Command.params params
--- @type Command.params
env.info( "Command defined" )

View File

@@ -1,115 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSController
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
--
-- This class has 2 types of functions:
--
-- * Tasks
-- * Commands: Commands are instant actions those required zero time to perform. Commands may be used both for control unit/group behavior and control game mechanics.
-- @type Controller
-- @field #Controller.Detection Detection Enum contains identifiers of surface types.
--- Enables and disables the controller.
-- Note: Now it works only for ground / naval groups!
-- @function [parent=#Controller] setOnOff
-- @param self
-- @param #boolean value Enable / Disable.
-- Tasks
--- Resets current task and then sets the task to the controller. Task is a table that contains task identifier and task parameters.
-- @function [parent=#Controller] setTask
-- @param self
-- @param #Task task
--- Resets current task of the controller.
-- @function [parent=#Controller] resetTask
-- @param self
--- Pushes the task to the front of the queue and makes the task active. Further call of function Controller.setTask() function will stop current task, clear the queue and set the new task active. If the task queue is empty the function will work like function Controller.setTask() function.
-- @function [parent=#Controller] pushTask
-- @param self
-- @param #Task task
--- Pops current (front) task from the queue and makes active next task in the queue (if exists). If no more tasks in the queue the function works like function Controller.resetTask() function. Does nothing if the queue is empty.
-- @function [parent=#Controller] popTask
-- @param self
--- Returns true if the controller has a task.
-- @function [parent=#Controller] hasTask
-- @param self
-- @return #boolean
-- Commands
--TODO: describe #Command structure
--- Sets the command to perform by controller.
-- @function [parent=#Controller] setCommand
-- @param self
-- @param #Command command Table that contains command identifier and command parameters.
-- Behaviours
--- Sets the option to the controller.
-- Option is a pair of identifier and value. Behavior options are global parameters those affect controller behavior in all tasks it performs.
-- Option identifiers and values are stored in table AI.Option in subtables Air, Ground and Naval.
--
-- OptionId = @{#AI.Option.Air.id} or @{#AI.Option.Ground.id} or @{#AI.Option.Naval.id}
-- OptionValue = AI.Option.Air.val[optionName] or AI.Option.Ground.val[optionName] or AI.Option.Naval.val[optionName]
--
-- @function [parent=#Controller] setOption
-- @param self
-- @param #OptionId optionId Option identifier.
-- @param #OptionValue optionValue Value of the option.
-- Detection
--- Enum contains identifiers of surface types.
-- @type Controller.Detection
-- @field VISUAL
-- @field OPTIC
-- @field RADAR
-- @field IRST
-- @field RWR
-- @field DLINK
--- Detected target.
-- @type DetectedTarget
-- @field Wrapper.Object#Object object The target
-- @field #boolean visible The target is visible
-- @field #boolean type The target type is known
-- @field #boolean distance Distance to the target is known
--- Checks if the target is detected or not. If one or more detection method is specified the function will return true if the target is detected by at least one of these methods. If no detection methods are specified the function will return true if the target is detected by any method.
-- @function [parent=#Controller] isTargetDetected
-- @param self
-- @param Wrapper.Object#Object target Target to check
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
-- @return #boolean detected True if the target is detected.
-- @return #boolean visible Has effect only if detected is true. True if the target is visible now.
-- @return #ModelTime lastTime Has effect only if visible is false. Last time when target was seen.
-- @return #boolean type Has effect only if detected is true. True if the target type is known.
-- @return #boolean distance Has effect only if detected is true. True if the distance to the target is known.
-- @return #Vec3 lastPos Has effect only if visible is false. Last position of the target when it was seen.
-- @return #Vec3 lastVel Has effect only if visible is false. Last velocity of the target when it was seen.
--- Returns list of detected targets. If one or more detection method is specified the function will return targets which were detected by at least one of these methods. If no detection methods are specified the function will return targets which were detected by any method.
-- @function [parent=#Controller] getDetectedTargets
-- @param self
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
-- @return #list<#DetectedTarget> array of DetectedTarget
--- Know a target.
-- @function [parent=#Controller] knowTarget
-- @param self
-- @param Wrapper.Object#Object object The target.
-- @param #boolean type Target type is known.
-- @param #boolean distance Distance to target is known.
Controller = {} --#Controller

View File

@@ -1,83 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSGroup
--- Represents group of Units.
-- @type Group
-- @field #ID ID Identifier of a group. It is assigned to a group by Mission Editor automatically.
-- @field #Group.Category Category Enum contains identifiers of group types.
--- Enum contains identifiers of group types.
-- @type Group.Category
-- @field AIRPLANE
-- @field HELICOPTER
-- @field GROUND
-- @field SHIP
-- Static Functions
--- Returns group by the name assigned to the group in Mission Editor.
-- @function [parent=#Group] getByName
-- @param #string name
-- @return #Group
-- Member Functions
--- returns true if the group exist or false otherwise.
-- @function [parent=#Group] isExist
-- @param #Group self
-- @return #boolean
--- Destroys the group and all of its units.
-- @function [parent=#Group] destroy
-- @param #Group self
--- Returns category of the group.
-- @function [parent=#Group] getCategory
-- @param #Group self
-- @return #Group.Category
--TODO check coalition.side
--- Returns the coalition of the group.
-- @function [parent=#Group] getCoalition
-- @param #Group self
-- @return Dcs.DCSCoalitionWrapper.Object#coalition.side
--- Returns the group's name. This is the same name assigned to the group in Mission Editor.
-- @function [parent=#Group] getName
-- @param #Group self
-- @return #string
--- Returns the group identifier.
-- @function [parent=#Group] getID
-- @param #Group self
-- @return #ID
--- Returns the unit with number unitNumber. If the unit is not exists the function will return nil.
-- @function [parent=#Group] getUnit
-- @param #Group self
-- @param #number unitNumber
-- @return Dcs.DCSWrapper.Unit#Unit
--- Returns current size of the group. If some of the units will be destroyed, As units are destroyed the size of the group will be changed.
-- @function [parent=#Group] getSize
-- @param #Group self
-- @return #number
--- Returns initial size of the group. If some of the units will be destroyed, initial size of the group will not be changed. Initial size limits the unitNumber parameter for Group.getUnit() function.
-- @function [parent=#Group] getInitialSize
-- @param #Group self
-- @return #number
--- Returns array of the units present in the group now. Destroyed units will not be enlisted at all.
-- @function [parent=#Group] getUnits
-- @param #Group self
-- @return #list<Dcs.DCSWrapper.Unit#Unit> array of Units
--- Returns controller of the group.
-- @function [parent=#Group] getController
-- @param #Group self
-- @return Controller#Controller
Group = {} --#Group

View File

@@ -1,73 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSObject
--- @type Object
-- @field #Object.Category Category
-- @field #Object.Desc Desc
--- @type Object.Category
-- @field UNIT
-- @field WEAPON
-- @field STATIC
-- @field SCENERY
-- @field BASE
--- @type Object.Desc
-- @extends #Desc
-- @field #number life initial life level
-- @field #Box3 box bounding box of collision geometry
--- @function [parent=#Object] isExist
-- @param #Object self
-- @return #boolean
--- @function [parent=#Object] destroy
-- @param #Object self
--- @function [parent=#Object] getCategory
-- @param #Object self
-- @return #Object.Category
--- Returns type name of the Object.
-- @function [parent=#Object] getTypeName
-- @param #Object self
-- @return #string
--- Returns object descriptor.
-- @function [parent=#Object] getDesc
-- @param #Object self
-- @return #Object.Desc
--- Returns true if the object belongs to the category.
-- @function [parent=#Object] hasAttribute
-- @param #Object self
-- @param #AttributeName attributeName Attribute name to check.
-- @return #boolean
--- Returns name of the object. This is the name that is assigned to the object in the Mission Editor.
-- @function [parent=#Object] getName
-- @param #Object self
-- @return #string
--- Returns object coordinates for current time.
-- @function [parent=#Object] getPoint
-- @param #Object self
-- @return #Vec3
--- Returns object position for current time.
-- @function [parent=#Object] getPosition
-- @param #Object self
-- @return #Position3
--- Returns the unit's velocity vector.
-- @function [parent=#Object] getVelocity
-- @param #Object self
-- @return #Vec3
--- Returns true if the unit is in air.
-- @function [parent=#Object] inAir
-- @param #Object self
-- @return #boolean
Object = {} --#Object

View File

@@ -1,34 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSStaticObject
-------------------------------------------------------------------------------
-- @module StaticObject
-- @extends CoalitionWrapper.Object#CoalitionObject
--- Represents static object added in the Mission Editor.
-- @type StaticObject
-- @field #StaticObject.ID ID Identifier of a StaticObject. It assigned to an StaticObject by the Mission Editor automatically.
-- @field #StaticObject.Desc Desc Descriptor of StaticObject and Unit are equal. StaticObject is just a passive variant of Unit.
--- StaticObject descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
-- @type StaticObject.Desc
-- @extends Wrapper.Unit#Unit.Desc
--- Returns static object by its name. If no static object found nil will be returned.
-- @function [parent=#StaticObject] getByName
-- @param #string name Name of static object to find.
-- @return #StaticObject
--- returns identifier of the static object.
-- @function [parent=#StaticObject] getID
-- @param #StaticObject self
-- @return #StaticObject.ID
--- Returns descriptor of the StaticObject.
-- @function [parent=#StaticObject] getDesc
-- @param #StaticObject self
-- @return #StaticObject.Desc
StaticObject = {} --#StaticObject

View File

@@ -1,15 +0,0 @@
--- @module DCSTask
--- A task descriptor (internal structure for DCS World)
-- @type Task
-- @field #string id
-- @field #Task.param param
--- @type Task.param
--- List of @{#Task}
-- @type TaskArray
-- @list <#Task>
env.info( "Task defined" )

View File

@@ -1,8 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSTime
--- @type ModelTime
-- @extends #number
--- @type Time
-- @extends #number

View File

@@ -1,246 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSTypes
--- Time is given in seconds.
-- @type Time
-- @extends #number
--- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time.
-- @type ModelTime
-- @extends #number
--- Mission time is a model time plus time of the mission start.
-- @type MissionTime
-- @extends #number
--- Distance is given in meters.
-- @type Distance
-- @extends #number
--- Angle is given in radians.
-- @type Angle
-- @extends #number
--- Azimuth is an angle of rotation around world axis y counter-clockwise.
-- @type Azimuth
-- @extends #number
--- Mass is given in kilograms.
-- @type Mass
-- @extends #number
--- Vec3 type is a 3D-vector.
-- DCS world has 3-dimensional coordinate system. DCS ground is an infinite plain.
-- @type Vec3
-- @field #Distance x is directed to the north
-- @field #Distance z is directed to the east
-- @field #Distance y is directed up
--- Vec2 is a 2D-vector for the ground plane as a reference plane.
-- @type Vec2
-- @field #Distance x Vec2.x = Vec3.x
-- @field #Distance y Vec2.y = Vec3.z
--- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format:
-- @type Position3
-- @field #Vec3 p
-- @field #Vec3 x
-- @field #Vec3 y
-- @field #Vec3 z
--- 3-dimensional box.
-- @type Box3
-- @field #Vec3 min
-- @field #Vec3 max
--- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley".
-- @type TypeName
-- @extends #string
--- AttributeName = string
-- Each object type may have attributes.
-- Attributes are enlisted in ./Scripts/Database/db_attributes.Lua.
-- To know what attributes the object type has, look for the unit type script in sub-directories planes/, helicopter/s, vehicles, navy/ of ./Scripts/Database/ directory.
-- @type AttributeName
-- @extends #string
--- List of @{#AttributeName}
-- @type AttributeNameArray
-- @list <#AttributeName>
--- @type AI
-- @field #AI.Skill Skill
-- @field #AI.Task Task
-- @field #AI.Option Option
--- @type AI.Skill
-- @field AVERAGE
-- @field GOOD
-- @field HIGH
-- @field EXCELLENT
-- @field PLAYER
-- @field CLIENT
--- @type AI.Task
-- @field #AI.Task.WeaponExpend WeaponExpend
-- @field #AI.Task.OrbitPattern OrbitPattern
-- @field #AI.Task.Designation Designation
-- @field #AI.Task.WaypointType WaypointType
-- @field #AI.Task.TurnMethod TurnMethod
-- @field #AI.Task.AltitudeType AltitudeType
-- @field #AI.Task.VehicleFormation VehicleFormation
--- @type AI.Task.WeaponExpend
-- @field ONE
-- @field TWO
-- @field FOUR
-- @field QUARTER
-- @field HALF
-- @field ALL
--- @type AI.Task.OrbitPattern
-- @field CIRCLE
-- @field RACE_TRACK
--- @type AI.Task.Designation
-- @field NO
-- @field AUTO
-- @field WP
-- @field IR_POINTER
-- @field LASER
--- @type AI.Task.WaypointType
-- @field TAKEOFF
-- @field TAKEOFF_PARKING
-- @field TURNING_POINT
-- @field LAND
--- @type AI.Task.TurnMethod
-- @field FLY_OVER_POINT
-- @field FIN_POINT
--- @type AI.Task.AltitudeType
-- @field BARO
-- @field RADIO
--- @type AI.Task.VehicleFormation
-- @field OFF_ROAD
-- @field ON_ROAD
-- @field RANK
-- @field CONE
-- @field DIAMOND
-- @field VEE
-- @field ECHELON_LEFT
-- @field ECHELON_RIGHT
--- @type AI.Option
-- @field #AI.Option.Air Air
-- @field #AI.Option.Ground Ground
-- @field #AI.Option.Naval Naval
--- @type AI.Option.Air
-- @field #AI.Option.Air.id id
-- @field #AI.Option.Air.val val
--- @type AI.Option.Ground
-- @field #AI.Option.Ground.id id
-- @field #AI.Option.Ground.val val
--- @type AI.Option.Naval
-- @field #AI.Option.Naval.id id
-- @field #AI.Option.Naval.val val
--TODO: work on formation
--- @type AI.Option.Air.id
-- @field NO_OPTION
-- @field ROE
-- @field REACTION_ON_THREAT
-- @field RADAR_USING
-- @field FLARE_USING
-- @field FORMATION
-- @field RTB_ON_BINGO
-- @field SILENCE
--- @type AI.Option.Air.val
-- @field #AI.Option.Air.val.ROE ROE
-- @field #AI.Option.Air.val.REACTION_ON_THREAT REACTION_ON_THREAT
-- @field #AI.Option.Air.val.RADAR_USING RADAR_USING
-- @field #AI.Option.Air.val.FLARE_USING FLARE_USING
--- @type AI.Option.Air.val.ROE
-- @field WEAPON_FREE
-- @field OPEN_FIRE_WEAPON_FREE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
--- @type AI.Option.Air.val.REACTION_ON_THREAT
-- @field NO_REACTION
-- @field PASSIVE_DEFENCE
-- @field EVADE_FIRE
-- @field BYPASS_AND_ESCAPE
-- @field ALLOW_ABORT_MISSION
--- @type AI.Option.Air.val.RADAR_USING
-- @field NEVER
-- @field FOR_ATTACK_ONLY
-- @field FOR_SEARCH_IF_REQUIRED
-- @field FOR_CONTINUOUS_SEARCH
--- @type AI.Option.Air.val.FLARE_USING
-- @field NEVER
-- @field AGAINST_FIRED_MISSILE
-- @field WHEN_FLYING_IN_SAM_WEZ
-- @field WHEN_FLYING_NEAR_ENEMIES
--- @type AI.Option.Ground.id
-- @field NO_OPTION
-- @field ROE @{#AI.Option.Ground.val.ROE}
-- @field DISPERSE_ON_ATTACK true or false
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
--- @type AI.Option.Ground.val
-- @field #AI.Option.Ground.val.ROE ROE
-- @field #AI.Option.Ground.val.ALARM_STATE ALARM_STATE
--- @type AI.Option.Ground.val.ROE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
--- @type AI.Option.Ground.val.ALARM_STATE
-- @field AUTO
-- @field GREEN
-- @field RED
--- @type AI.Option.Naval.id
-- @field NO_OPTION
-- @field ROE
--- @type AI.Option.Naval.val
-- @field #AI.Option.Naval.val.ROE ROE
--- @type AI.Option.Naval.val.ROE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
AI = {} --#AI
--- @type Desc
-- @field #TypeName typeName type name
-- @field #string displayName localized display name
-- @field #table attributes object type attributes
--- A distance type
-- @type Distance
--- An angle type
-- @type Angle
env.info( 'AI types created' )

View File

@@ -1,241 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSUnit
--- @type Unit
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
-- @field #Unit.Category Category
-- @field #Unit.RefuelingSystem RefuelingSystem
-- @field #Unit.SensorType SensorType
-- @field #Unit.OpticType OpticType
-- @field #Unit.RadarType RadarType
-- @field #Unit.Desc Desc
-- @field #Unit.DescAircraft DescAircraft
-- @field #Unit.DescAirplane DescAirplane
-- @field #Unit.DescHelicopter DescHelicopter
-- @field #Unit.DescVehicle DescVehicle
-- @field #Unit.DescShip DescShip
-- @field #Unit.AmmoItem AmmoItem
-- @field #list<#Unit.AmmoItem> Ammo
-- @field #Unit.Sensor Sensor
-- @field #Unit.Optic Optic
-- @field #Unit.Radar Radar
-- @field #Unit.IRST IRST
--- Enum that stores unit categories.
-- @type Unit.Category
-- @field AIRPLANE
-- @field HELICOPTER
-- @field GROUND_UNIT
-- @field SHIP
-- @field STRUCTURE
--- Enum that stores aircraft refueling system types.
-- @type Unit.RefuelingSystem
-- @field BOOM_AND_RECEPTACLE
-- @field PROBE_AND_DROGUE
--- Enum that stores sensor types.
-- @type Unit.SensorType
-- @field OPTIC
-- @field RADAR
-- @field IRST
-- @field RWR
--- Enum that stores types of optic sensors.
-- @type Unit.OpticType
-- @field TV TV-sensor
-- @field LLTV Low-level TV-sensor
-- @field IR Infra-Red optic sensor
--- Enum that stores radar types.
-- @type Unit.RadarType
-- @field AS air search radar
-- @field SS surface/land search radar
--- A unit descriptor.
-- @type Unit.Desc
-- @extends Wrapper.Object#Object.Desc
-- @field #Unit.Category category Unit Category
-- @field #Mass massEmpty mass of empty unit
-- @field #number speedMax istance / Time, --maximal velocity
--- An aircraft descriptor.
-- @type Unit.DescAircraft
-- @extends Wrapper.Unit#Unit.Desc
-- @field #Mass fuelMassMax maximal inner fuel mass
-- @field #Distance range Operational range
-- @field #Distance Hmax Ceiling
-- @field #number VyMax #Distance / #Time, --maximal climb rate
-- @field #number NyMin minimal safe acceleration
-- @field #number NyMax maximal safe acceleration
-- @field #Unit.RefuelingSystem tankerType refueling system type
--- An airplane descriptor.
-- @type Unit.DescAirplane
-- @extends Wrapper.Unit#Unit.DescAircraft
-- @field #number speedMax0 Distance / Time maximal TAS at ground level
-- @field #number speedMax10K Distance / Time maximal TAS at altitude of 10 km
--- A helicopter descriptor.
-- @type Unit.DescHelicopter
-- @extends Wrapper.Unit#Unit.DescAircraft
-- @field #Distance HmaxStat static ceiling
--- A vehicle descriptor.
-- @type Unit.DescVehicle
-- @extends Wrapper.Unit#Unit.Desc
-- @field #Angle maxSlopeAngle maximal slope angle
-- @field #boolean riverCrossing can the vehicle cross a rivers
--- A ship descriptor.
-- @type Unit.DescShip
-- @extends #Unit.Desc
--- ammunition item: "type-count" pair.
-- @type Unit.AmmoItem
-- @field #Weapon.Desc desc ammunition descriptor
-- @field #number count ammunition count
--- A unit sensor.
-- @type Unit.Sensor
-- @field #TypeName typeName
-- @field #Unit.SensorType type
--- An optic sensor.
-- @type Unit.Optic
-- @extends Wrapper.Unit#Unit.Sensor
-- @field #Unit.OpticType opticType
--- A radar.
-- @type Unit.Radar
-- @extends Wrapper.Unit#Unit.Sensor
-- @field #Distance detectionDistanceRBM detection distance for RCS=1m^2 in real-beam mapping mode, nil if radar doesn't support surface/land search
-- @field #Distance detectionDistanceHRM detection distance for RCS=1m^2 in high-resolution mapping mode, nil if radar has no HRM
-- @field #Unit.Radar.detectionDistanceAir detectionDistanceAir detection distance for RCS=1m^2 airborne target, nil if radar doesn't support air search
--- @type Unit.Radar.detectionDistanceAir
-- @field #Unit.Radar.detectionDistanceAir.upperHemisphere upperHemisphere
-- @field #Unit.Radar.detectionDistanceAir.lowerHemisphere lowerHemisphere
--- @type Unit.Radar.detectionDistanceAir.upperHemisphere
-- @field #Distance headOn
-- @field #Distance tailOn
--- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
-- @field #Distance headOn
-- @field #Distance tailOn
--- An IRST.
-- @type Wrapper.Unit#Unit.IRST
-- @extends Unit.Sensor
-- @field #Distance detectionDistanceIdle detection of tail-on target with heat signature = 1 in upper hemisphere, engines are in idle
-- @field #Distance detectionDistanceMaximal ..., engines are in maximal mode
-- @field #Distance detectionDistanceAfterburner ..., engines are in afterburner mode
--- An RWR.
-- @type Unit.RWR
-- @extends Wrapper.Unit#Unit.Sensor
--- table that stores all unit sensors.
-- TODO @type Sensors
--
--- Returns unit object by the name assigned to the unit in Mission Editor. If there is unit with such name or the unit is destroyed the function will return nil. The function provides access to non-activated units too.
-- @function [parent=#Unit] getByName
-- @param #string name
-- @return #Unit
--- Returns if the unit is activated.
-- @function [parent=#Unit] isActive
-- @param #Unit self
-- @return #boolean
--- Returns name of the player that control the unit or nil if the unit is controlled by A.I.
-- @function [parent=#Unit] getPlayerName
-- @param #Unit self
-- @return #string
--- returns the unit's unique identifier.
-- @function [parent=#Unit] getID
-- @param #Unit self
-- @return #Unit.ID
--- Returns the unit's number in the group. The number is the same number the unit has in ME. It may not be changed during the mission. If any unit in the group is destroyed, the numbers of another units will not be changed.
-- @function [parent=#Unit] getNumber
-- @param #Unit self
-- @return #number
--- Returns controller of the unit if it exist and nil otherwise
-- @function [parent=#Unit] getController
-- @param #Unit self
-- @return #Controller
--- Returns the unit's group if it exist and nil otherwise
-- @function [parent=#Unit] getGroup
-- @param #Unit self
-- @return Dcs.DCSWrapper.Group#Group
--- Returns the unit's callsign - the localized string.
-- @function [parent=#Unit] getCallsign
-- @param #Unit self
-- @return #string
--- Returns the unit's health. Dead units has health <= 1.0
-- @function [parent=#Unit] getLife
-- @param #Unit self
-- @return #number
--- returns the unit's initial health.
-- @function [parent=#Unit] getLife0
-- @param #Unit self
-- @return #number
--- Returns relative amount of fuel (from 0.0 to 1.0) the unit has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
-- @function [parent=#Unit] getFuel
-- @param #Unit self
-- @return #number
--- Returns the unit ammunition.
-- @function [parent=#Unit] getAmmo
-- @param #Unit self
-- @return #Unit.Ammo
--- Returns the unit sensors.
-- @function [parent=#Unit] getSensors
-- @param #Unit self
-- @return #Unit.Sensors
--- Returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
-- @function [parent=#Unit] hasSensors
-- @param #Unit self
-- @param #Unit.SensorType sensorType (= nil) Sensor type.
-- @param ... Additional parameters.
-- @return #boolean
-- @usage
-- If sensorType is Unit.SensorType.OPTIC, additional parameters are optic sensor types. Following example checks if the unit has LLTV or IR optics:
-- unit:hasSensors(Unit.SensorType.OPTIC, Unit.OpticType.LLTV, Unit.OpticType.IR)
-- If sensorType is Unit.SensorType.RADAR, additional parameters are radar types. Following example checks if the unit has air search radars:
-- unit:hasSensors(Unit.SensorType.RADAR, Unit.RadarType.AS)
-- If no additional parameters are specified the function returns true if the unit has at least one sensor of specified type.
-- If sensor type is not specified the function returns true if the unit has at least one sensor of any type.
--
--- returns two values:
-- First value indicates if at least one of the unit's radar(s) is on.
-- Second value is the object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @function [parent=#Unit] getRadar
-- @param #Unit self
-- @return #boolean, Wrapper.Object#Object
--- Returns unit descriptor. Descriptor type depends on unit category.
-- @function [parent=#Unit] getDesc
-- @param #Unit self
-- @return #Unit.Desc
Unit = {} --#Unit

View File

@@ -1,11 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSVec3
---
-- @type Vec3
-- @field #number x
-- @field #number y
-- @field #number z
Vec3 = {}

View File

@@ -1,10 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSZone
---
-- @type Zone
-- @field DCSVec3#Vec3 point
-- @field #number radius
Zone = {}

View File

@@ -1,14 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCScoalition
--- @type coalition
-- @field #coalition.side side
--- @type coalition.side
-- @field NEUTRAL
-- @field RED
-- @field BLUE
--- @function [parent=#coalition] getCountryCoalition
-- @param #number countryId
-- @return #number coalitionId

View File

@@ -1,27 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCScountry
--- @type country
-- @field #country.id id
country = country -- #country
--- @type country.id
-- @field RUSSIA
-- @field UKRAINE
-- @field USA
-- @field TURKEY
-- @field UK
-- @field FRANCE
-- @field GERMANY
-- @field CANADA
-- @field SPAIN
-- @field THE_NETHERLANDS
-- @field BELGIUM
-- @field NORWAY
-- @field DENMARK
-- @field ISRAEL
-- @field GEORGIA
-- @field INSURGENTS
-- @field ABKHAZIA
-- @field SOUTH_OSETIA
-- @field ITALY

View File

@@ -1,27 +0,0 @@
-------------------------------------------------------------------------------
-- @module env
--- @type env
--- Add message to simulator log with caption "INFO". Message box is optional.
-- @function [parent=#env] info
-- @field #string message message string to add to log.
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
--- Add message to simulator log with caption "WARNING". Message box is optional.
-- @function [parent=#env] warning
-- @field #string message message string to add to log.
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
--- Add message to simulator log with caption "ERROR". Message box is optional.
-- @function [parent=#env] error
-- @field #string message message string to add to log.
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
--- Enables/disables appearance of message box each time lua error occurs.
-- @function [parent=#env] setErrorMessageBoxEnabled
-- @field #boolean on if true message box appearance is enabled.
env = {} --#env

View File

@@ -1,26 +0,0 @@
-------------------------------------------------------------------------------
-- @module land
--- @type land
-- @field #land.SurfaceType SurfaceType
--- @type land.SurfaceType
-- @field LAND
-- @field SHALLOW_WATER
-- @field WATER
-- @field ROAD
-- @field RUNWAY
--- Returns altitude MSL of the point.
-- @function [parent=#land] getHeight
-- @param #Vec2 point point on the ground.
-- @return Dcs.DCSTypes#Distance
--- returns surface type at the given point.
-- @function [parent=#land] getSurfaceType
-- @param #Vec2 point Point on the land.
-- @return #land.SurfaceType
land = {} --#land

View File

@@ -1,45 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCStimer
--- @type timer
--- Returns model time in seconds.
-- @function [parent=#timer] getTime
-- @return #Time
--- Returns mission time in seconds.
-- @function [parent=#timer] getAbsTime
-- @return #Time
--- Returns mission start time in seconds.
-- @function [parent=#timer] getTime0
-- @return #Time
--- Schedules function to call at desired model time.
-- Time function FunctionToCall(any argument, Time time)
--
-- ...
--
-- return ...
--
-- end
--
-- Must return model time of next call or nil. Note that the DCS scheduler calls the function in protected mode and any Lua errors in the called function will be trapped and not reported. If the function triggers a Lua error then it will be terminated and not scheduled to run again.
-- @function [parent=#timer] scheduleFunction
-- @param #FunctionToCall functionToCall Lua-function to call. Must have prototype of FunctionToCall.
-- @param functionArgument Function argument of any type to pass to functionToCall.
-- @param #Time time Model time of the function call.
-- @return functionId
--- Re-schedules function to call at another model time.
-- @function [parent=#timer] setFunctionTime
-- @param functionId Lua-function to call. Must have prototype of FunctionToCall.
-- @param #Time time Model time of the function call.
--- Removes the function from schedule.
-- @function [parent=#timer] removeFunction
-- @param functionId Function identifier to remove from schedule
timer = {} --#timer

View File

@@ -1,8 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCStrigger
trigger = {} --#timer

View File

@@ -1,35 +0,0 @@
-------------------------------------------------------------------------------
-- @module DCSWorld
--- @type world
-- @field #world.event event
--- @type world.event
-- @field S_EVENT_INVALID
-- @field S_EVENT_SHOT
-- @field S_EVENT_HIT
-- @field S_EVENT_TAKEOFF
-- @field S_EVENT_LAND
-- @field S_EVENT_CRASH
-- @field S_EVENT_EJECTION
-- @field S_EVENT_REFUELING
-- @field S_EVENT_DEAD
-- @field S_EVENT_PILOT_DEAD
-- @field S_EVENT_BASE_CAPTURED
-- @field S_EVENT_MISSION_START
-- @field S_EVENT_MISSION_END
-- @field S_EVENT_TOOK_CONTROL
-- @field S_EVENT_REFUELING_STOP
-- @field S_EVENT_BIRTH
-- @field S_EVENT_HUMAN_FAILURE
-- @field S_EVENT_ENGINE_STARTUP
-- @field S_EVENT_ENGINE_SHUTDOWN
-- @field S_EVENT_PLAYER_ENTER_UNIT
-- @field S_EVENT_PLAYER_LEAVE_UNIT
-- @field S_EVENT_PLAYER_COMMENT
-- @field S_EVENT_SHOOTING_START
-- @field S_EVENT_SHOOTING_END
-- @field S_EVENT_MAX
world = {} --#world

View File

@@ -11,8 +11,8 @@
-- --
-- === -- ===
-- --
-- @module ATC_Ground -- @module Functional.ATC_Ground
-- @image Air_Traffic_Control_Ground_Operations.JPG
--- @type ATC_GROUND --- @type ATC_GROUND
-- @field Core.Set#SET_CLIENT SetClient -- @field Core.Set#SET_CLIENT SetClient
@@ -417,7 +417,7 @@ end
-- # Airbases monitored -- # Airbases monitored
-- --
-- The following airbases are monitored at the Caucasus region. -- The following airbases are monitored at the Caucasus region.
-- Use the @{Airbase#AIRBASE.Caucasus} enumeration to select the airbases to be monitored. -- Use the @{Wrapper.Airbase#AIRBASE.Caucasus} enumeration to select the airbases to be monitored.
-- --
-- * `AIRBASE.Caucasus.Anapa_Vityazevo` -- * `AIRBASE.Caucasus.Anapa_Vityazevo`
-- * `AIRBASE.Caucasus.Batumi` -- * `AIRBASE.Caucasus.Batumi`
@@ -1021,7 +1021,7 @@ end
-- # Airbases monitored -- # Airbases monitored
-- --
-- The following airbases are monitored at the Nevada region. -- The following airbases are monitored at the Nevada region.
-- Use the @{Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored. -- Use the @{Wrapper.Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
-- --
-- * `AIRBASE.Nevada.Beatty_Airport` -- * `AIRBASE.Nevada.Beatty_Airport`
-- * `AIRBASE.Nevada.Boulder_City_Airport` -- * `AIRBASE.Nevada.Boulder_City_Airport`
@@ -1561,7 +1561,7 @@ end
-- # Airbases monitored -- # Airbases monitored
-- --
-- The following airbases are monitored at the Normandy region. -- The following airbases are monitored at the Normandy region.
-- Use the @{Airbase#AIRBASE.Normandy} enumeration to select the airbases to be monitored. -- Use the @{Wrapper.Airbase#AIRBASE.Normandy} enumeration to select the airbases to be monitored.
-- --
-- * `AIRBASE.Normandy.Azeville` -- * `AIRBASE.Normandy.Azeville`
-- * `AIRBASE.Normandy.Bazenville` -- * `AIRBASE.Normandy.Bazenville`

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,8 @@
-- --
-- === -- ===
-- --
-- @module CleanUp -- @module Functional.CleanUp
-- @image CleanUp_Airbases.JPG
--- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-) --- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases. -- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
@@ -16,11 +17,8 @@
--- @type CLEANUP_AIRBASE --- @type CLEANUP_AIRBASE
-- @extends #CLEANUP_AIRBASE.__ -- @extends #CLEANUP_AIRBASE.__
--- # CLEANUP_AIRBASE, extends @{Base#BASE} --- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
-- --
-- ![Banner Image](..\Presentations\CLEANUP_AIRBASE\Dia1.JPG)
--
-- The CLEANUP_AIRBASE class keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
-- Specific airbases need to be provided that need to be guarded. Each airbase registered, will be guarded within a zone of 8 km around the airbase. -- Specific airbases need to be provided that need to be guarded. Each airbase registered, will be guarded within a zone of 8 km around the airbase.
-- Any unit that fires a missile, or shoots within the zone of an airbase, will be monitored by CLEANUP_AIRBASE. -- Any unit that fires a missile, or shoots within the zone of an airbase, will be monitored by CLEANUP_AIRBASE.
-- Within the 8km zone, units cannot fire any missile, which prevents the airbase runway to receive missile or bomb hits. -- Within the 8km zone, units cannot fire any missile, which prevents the airbase runway to receive missile or bomb hits.
@@ -173,7 +171,7 @@ end
--- Destroys a @{Unit} from the simulator, but checks first if it is still existing! --- Destroys a @{Wrapper.Unit} from the simulator, but checks first if it is still existing!
-- @param #CLEANUP_AIRBASE self -- @param #CLEANUP_AIRBASE self
-- @param Wrapper.Unit#UNIT CleanUpUnit The object to be destroyed. -- @param Wrapper.Unit#UNIT CleanUpUnit The object to be destroyed.
function CLEANUP_AIRBASE.__:DestroyUnit( CleanUpUnit ) function CLEANUP_AIRBASE.__:DestroyUnit( CleanUpUnit )
@@ -200,7 +198,7 @@ end
--- Destroys a missile from the simulator, but checks first if it is still existing! --- Destroys a missile from the simulator, but checks first if it is still existing!
-- @param #CLEANUP_AIRBASE self -- @param #CLEANUP_AIRBASE self
-- @param Dcs.DCSTypes#Weapon MissileObject -- @param DCS#Weapon MissileObject
function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject ) function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject )
self:F( { MissileObject } ) self:F( { MissileObject } )
@@ -290,9 +288,9 @@ function CLEANUP_AIRBASE.__:OnEventHit( Event )
end end
end end
--- Add the @{DCSWrapper.Unit#Unit} to the CleanUpList for CleanUp. --- Add the @{DCS#Unit} to the CleanUpList for CleanUp.
-- @param #CLEANUP_AIRBASE self -- @param #CLEANUP_AIRBASE self
-- @param Wrapper.Unit#UNIT CleanUpUnit -- @param DCS#UNIT CleanUpUnit
-- @oaram #string CleanUpUnitName -- @oaram #string CleanUpUnitName
function CLEANUP_AIRBASE.__:AddForCleanUp( CleanUpUnit, CleanUpUnitName ) function CLEANUP_AIRBASE.__:AddForCleanUp( CleanUpUnit, CleanUpUnitName )
self:F( { CleanUpUnit, CleanUpUnitName } ) self:F( { CleanUpUnit, CleanUpUnitName } )

View File

@@ -2,7 +2,7 @@
-- --
-- === -- ===
-- --
-- DESIGNATE is orchestrating the designation of potential targets executed by a Recce group, -- Orchestrate the designation of potential targets executed by a Recce group,
-- and communicates these to a dedicated attacking group of players, -- and communicates these to a dedicated attacking group of players,
-- so that following a dynamically generated menu system, -- so that following a dynamically generated menu system,
-- each detected set of potential targets can be lased or smoked... -- each detected set of potential targets can be lased or smoked...
@@ -28,17 +28,16 @@
-- --
-- * **FlightControl**: Design & Programming -- * **FlightControl**: Design & Programming
-- --
-- @module Designate -- @module Functional.Designate
-- @image Designation.JPG
do -- DESIGNATE do -- DESIGNATE
--- @type DESIGNATE --- @type DESIGNATE
-- @extends Core.Fsm#FSM_PROCESS -- @extends Core.Fsm#FSM_PROCESS
--- # DESIGNATE class, extends @{Fsm#FSM} --- Manage the designation of detected targets.
-- --
-- DESIGNATE is managing the designation of detected targets.
-- Targets detected by recce will be communicated to a group of attacking players. -- Targets detected by recce will be communicated to a group of attacking players.
-- A menu system is made available that allows to: -- A menu system is made available that allows to:
-- --
@@ -268,7 +267,7 @@ do -- DESIGNATE
-- --
-- ## 6. Designate Menu Location for a Mission -- ## 6. Designate Menu Location for a Mission
-- --
-- You can make DESIGNATE work for a @{Mission#MISSION} object. In this way, the designate menu will not appear in the root of the radio menu, but in the menu of the Mission. -- You can make DESIGNATE work for a @{Tasking.Mission#MISSION} object. In this way, the designate menu will not appear in the root of the radio menu, but in the menu of the Mission.
-- Use the method @{#DESIGNATE.SetMission}() to set the @{Mission} object for the designate function. -- Use the method @{#DESIGNATE.SetMission}() to set the @{Mission} object for the designate function.
-- --
-- ## 7. Status Report -- ## 7. Status Report

View File

@@ -2,11 +2,7 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\DETECTION\Dia1.JPG) -- Facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
--
-- ===
--
-- DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
-- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities. -- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
-- --
-- Find the DETECTION classes documentation further in this document in the globals section. -- Find the DETECTION classes documentation further in this document in the globals section.
@@ -29,7 +25,8 @@
-- --
-- * FlightControl : Analysis, Design, Programming, Testing -- * FlightControl : Analysis, Design, Programming, Testing
-- --
-- @module Detection -- @module Functional.Detection
-- @image Detection.JPG
----BASE:TraceClass("DETECTION_BASE") ----BASE:TraceClass("DETECTION_BASE")
----BASE:TraceClass("DETECTION_AREAS") ----BASE:TraceClass("DETECTION_AREAS")
@@ -40,16 +37,14 @@ do -- DETECTION_BASE
--- @type DETECTION_BASE --- @type DETECTION_BASE
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role. -- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected. -- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects. -- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified. -- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
-- @field #number DetectionRun -- @field #number DetectionRun
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- DETECTION_BASE class, extends @{Fsm#FSM} --- Defines the core functions to administer detected objects.
-- -- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s).
-- The DETECTION_BASE class defines the core functions to administer detected objects.
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
-- --
-- ## DETECTION_BASE constructor -- ## DETECTION_BASE constructor
-- --
@@ -105,11 +100,11 @@ do -- DETECTION_BASE
-- --
-- Various methods exist how to retrieve the grouped items from a DETECTION_BASE derived class: -- Various methods exist how to retrieve the grouped items from a DETECTION_BASE derived class:
-- --
-- * The method @{Detection#DETECTION_BASE.GetDetectedItems}() retrieves the DetectedItems[] list. -- * The method @{Functional.Detection#DETECTION_BASE.GetDetectedItems}() retrieves the DetectedItems[] list.
-- * A DetectedItem from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedItem}( DetectedItemIndex ). -- * A DetectedItem from the DetectedItems[] list can be retrieved using the method @{Functional.Detection#DETECTION_BASE.GetDetectedItem}( DetectedItemIndex ).
-- Note that this method returns a DetectedItem element from the list, that contains a Set variable and further information -- Note that this method returns a DetectedItem element from the list, that contains a Set variable and further information
-- about the DetectedItem that is set by the DETECTION_BASE derived classes, used to group the DetectedItem. -- about the DetectedItem that is set by the DETECTION_BASE derived classes, used to group the DetectedItem.
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ). -- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
-- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ). -- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
-- --
-- ## **Visual filters** to fine-tune the probability of the detected objects -- ## **Visual filters** to fine-tune the probability of the detected objects
@@ -146,7 +141,7 @@ do -- DETECTION_BASE
-- --
-- Note that based on this probability factor, not only the detection but also the **type** of the unit will be applied! -- Note that based on this probability factor, not only the detection but also the **type** of the unit will be applied!
-- --
-- Use the method @{Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance. -- Use the method @{Functional.Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
-- --
-- ### Alpha Angle visual detection probability -- ### Alpha Angle visual detection probability
-- --
@@ -158,7 +153,7 @@ do -- DETECTION_BASE
-- For example, if a alpha angle probability factor of 0.7 is given, the extrapolated probabilities of the different angles would look like: -- For example, if a alpha angle probability factor of 0.7 is given, the extrapolated probabilities of the different angles would look like:
-- 0°: 70%, 10°: 75,21%, 20°: 80,26%, 30°: 85%, 40°: 89,28%, 50°: 92,98%, 60°: 95,98%, 70°: 98,19%, 80°: 99,54%, 90°: 100% -- 0°: 70%, 10°: 75,21%, 20°: 80,26%, 30°: 85%, 40°: 89,28%, 50°: 92,98%, 60°: 95,98%, 70°: 98,19%, 80°: 99,54%, 90°: 100%
-- --
-- Use the method @{Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°. -- Use the method @{Functional.Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
-- --
-- ### Cloudy Zones detection probability -- ### Cloudy Zones detection probability
-- --
@@ -166,7 +161,7 @@ do -- DETECTION_BASE
-- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission -- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
-- zones that reflect cloudy areas where detected units may not be so easily visually detected. -- zones that reflect cloudy areas where detected units may not be so easily visually detected.
-- --
-- Use the method @{Detection#DETECTION_BASE.SetZoneProbability}() to set for a defined number of zones, the probability factors. -- Use the method @{Functional.Detection#DETECTION_BASE.SetZoneProbability}() to set for a defined number of zones, the probability factors.
-- --
-- Note however, that the more zones are defined to be "cloudy" within a detection, the more performance it will take -- Note however, that the more zones are defined to be "cloudy" within a detection, the more performance it will take
-- from the DETECTION_BASE to calculate the presence of the detected unit within each zone. -- from the DETECTION_BASE to calculate the presence of the detected unit within each zone.
@@ -183,7 +178,7 @@ do -- DETECTION_BASE
-- ### Detection acceptance of within range limit -- ### Detection acceptance of within range limit
-- --
-- A range can be set that will limit a successful detection for a unit. -- A range can be set that will limit a successful detection for a unit.
-- Use the method @{Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted. -- Use the method @{Functional.Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
-- --
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers. -- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
-- --
@@ -200,7 +195,7 @@ do -- DETECTION_BASE
-- ### Detection acceptance if within zone(s). -- ### Detection acceptance if within zone(s).
-- --
-- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s). -- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones. -- Use the method @{Functional.Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
-- --
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers. -- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
-- --
@@ -220,7 +215,7 @@ do -- DETECTION_BASE
-- ### Detection rejectance if within zone(s). -- ### Detection rejectance if within zone(s).
-- --
-- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s). -- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones. -- Use the method @{Functional.Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
-- An example of how to use the method is shown below. -- An example of how to use the method is shown below.
-- --
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers. -- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
@@ -240,7 +235,7 @@ do -- DETECTION_BASE
-- --
-- ## Detection of Friendlies Nearby -- ## Detection of Friendlies Nearby
-- --
-- Use the method @{Detection#DETECTION_BASE.SetFriendliesRange}() to set the range what will indicate when friendlies are nearby -- Use the method @{Functional.Detection#DETECTION_BASE.SetFriendliesRange}() to set the range what will indicate when friendlies are nearby
-- a DetectedItem. The default range is 6000 meters. For air detections, it is advisory to use about 30.000 meters. -- a DetectedItem. The default range is 6000 meters. For air detections, it is advisory to use about 30.000 meters.
-- --
-- ## DETECTION_BASE is a Finite State Machine -- ## DETECTION_BASE is a Finite State Machine
@@ -510,7 +505,6 @@ do -- DETECTION_BASE
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function DETECTION_BASE:onafterDetect(From,Event,To) function DETECTION_BASE:onafterDetect(From,Event,To)
self:F( { From, Event, To } )
local DetectDelay = 0.1 local DetectDelay = 0.1
self.DetectionCount = 0 self.DetectionCount = 0
@@ -533,7 +527,6 @@ do -- DETECTION_BASE
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param Wrapper.Group#GROUP DetectionGroup The Group detecting. -- @param Wrapper.Group#GROUP DetectionGroup The Group detecting.
function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup, DetectionTimeStamp ) function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup, DetectionTimeStamp )
self:F( { From, Event, To } )
self.DetectionRun = self.DetectionRun + 1 self.DetectionRun = self.DetectionRun + 1
@@ -541,7 +534,7 @@ do -- DETECTION_BASE
if DetectionGroup:IsAlive() then if DetectionGroup:IsAlive() then
self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } ) --self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
local DetectionGroupName = DetectionGroup:GetName() local DetectionGroupName = DetectionGroup:GetName()
local DetectionUnit = DetectionGroup:GetUnit(1) local DetectionUnit = DetectionGroup:GetUnit(1)
@@ -557,10 +550,10 @@ do -- DETECTION_BASE
self.DetectDLINK self.DetectDLINK
) )
self:F( DetectedTargets ) --self:F( DetectedTargets )
for DetectionObjectID, Detection in pairs( DetectedTargets ) do for DetectionObjectID, Detection in pairs( DetectedTargets ) do
local DetectedObject = Detection.object -- Dcs.DCSWrapper.Object#Object local DetectedObject = Detection.object -- DCS#Object
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
@@ -574,7 +567,7 @@ do -- DETECTION_BASE
self.DetectDLINK self.DetectDLINK
) )
self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } ) --self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } )
-- Only process if the target is visible. Detection also returns invisible units. -- Only process if the target is visible. Detection also returns invisible units.
--if Detection.visible == true then --if Detection.visible == true then
@@ -596,7 +589,7 @@ do -- DETECTION_BASE
local DetectedUnitCategory = DetectedObject:getDesc().category local DetectedUnitCategory = DetectedObject:getDesc().category
self:F( { "Detected Target:", DetectionGroupName, DetectedObjectName, DetectedObjectType, Distance, DetectedUnitCategory } ) --self:F( { "Detected Target:", DetectionGroupName, DetectedObjectName, DetectedObjectType, Distance, DetectedUnitCategory } )
-- Calculate Acceptance -- Calculate Acceptance
@@ -644,7 +637,7 @@ do -- DETECTION_BASE
local DistanceProbability = 1 - DistanceProbabilityReversed local DistanceProbability = 1 - DistanceProbabilityReversed
DistanceProbability = DistanceProbability * 30 / 300 DistanceProbability = DistanceProbability * 30 / 300
local Probability = math.random() -- Selects a number between 0 and 1 local Probability = math.random() -- Selects a number between 0 and 1
self:T( { Probability, DistanceProbability } ) --self:T( { Probability, DistanceProbability } )
if Probability > DistanceProbability then if Probability > DistanceProbability then
DetectionAccepted = false DetectionAccepted = false
end end
@@ -660,7 +653,7 @@ do -- DETECTION_BASE
AlphaAngleProbability = AlphaAngleProbability * 30 / 300 AlphaAngleProbability = AlphaAngleProbability * 30 / 300
local Probability = math.random() -- Selects a number between 0 and 1 local Probability = math.random() -- Selects a number between 0 and 1
self:T( { Probability, AlphaAngleProbability } ) --self:T( { Probability, AlphaAngleProbability } )
if Probability > AlphaAngleProbability then if Probability > AlphaAngleProbability then
DetectionAccepted = false DetectionAccepted = false
end end
@@ -677,7 +670,7 @@ do -- DETECTION_BASE
if ZoneObject:IsPointVec2InZone( DetectedObjectVec2 ) == true then if ZoneObject:IsPointVec2InZone( DetectedObjectVec2 ) == true then
local Probability = math.random() -- Selects a number between 0 and 1 local Probability = math.random() -- Selects a number between 0 and 1
self:T( { Probability, ZoneProbability } ) --self:T( { Probability, ZoneProbability } )
if Probability > ZoneProbability then if Probability > ZoneProbability then
DetectionAccepted = false DetectionAccepted = false
break break
@@ -702,7 +695,7 @@ do -- DETECTION_BASE
self.DetectedObjects[DetectedObjectName].Distance = Distance self.DetectedObjects[DetectedObjectName].Distance = Distance
self.DetectedObjects[DetectedObjectName].DetectionTimeStamp = DetectionTimeStamp self.DetectedObjects[DetectedObjectName].DetectionTimeStamp = DetectionTimeStamp
self:F( { DetectedObject = self.DetectedObjects[DetectedObjectName] } ) --self:F( { DetectedObject = self.DetectedObjects[DetectedObjectName] } )
local DetectedUnit = UNIT:FindByName( DetectedObjectName ) local DetectedUnit = UNIT:FindByName( DetectedObjectName )
@@ -716,7 +709,7 @@ do -- DETECTION_BASE
--end --end
end end
self:T2( self.DetectedObjects ) --self:T2( self.DetectedObjects )
end end
if HasDetectedObjects then if HasDetectedObjects then
@@ -726,7 +719,6 @@ do -- DETECTION_BASE
end end
if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
self:T( "--> Create Detection Sets" )
-- First check if all DetectedObjects were detected. -- First check if all DetectedObjects were detected.
-- This is important. When there are DetectedObjects in the list, but were not detected, -- This is important. When there are DetectedObjects in the list, but were not detected,
@@ -766,7 +758,6 @@ do -- DETECTION_BASE
local DetectedSet = DetectedItem.Set local DetectedSet = DetectedItem.Set
if DetectedSet:Count() == 0 then if DetectedSet:Count() == 0 then
self:F3( { DetectedItemID = DetectedItemID } )
self:RemoveDetectedItem( DetectedItemID ) self:RemoveDetectedItem( DetectedItemID )
end end
@@ -778,8 +769,7 @@ do -- DETECTION_BASE
-- @param #string UnitName The UnitName that needs to be forgotten from the DetectionItem Sets. -- @param #string UnitName The UnitName that needs to be forgotten from the DetectionItem Sets.
-- @return #DETECTION_BASE -- @return #DETECTION_BASE
function DETECTION_BASE:ForgetDetectedUnit( UnitName ) function DETECTION_BASE:ForgetDetectedUnit( UnitName )
self:F2()
local DetectedItems = self:GetDetectedItems() local DetectedItems = self:GetDetectedItems()
for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do
@@ -796,7 +786,6 @@ do -- DETECTION_BASE
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @return #DETECTION_BASE -- @return #DETECTION_BASE
function DETECTION_BASE:CreateDetectionItems() function DETECTION_BASE:CreateDetectionItems()
self:F2()
self:F( "Error, in DETECTION_BASE class..." ) self:F( "Error, in DETECTION_BASE class..." )
return self return self
@@ -902,7 +891,7 @@ do -- DETECTION_BASE
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } ) -- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
-- --
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param #list<Dcs.DCSUnit#Unit> FilterCategories The Categories entries -- @param #list<DCS#Unit> FilterCategories The Categories entries
-- @return #DETECTION_BASE self -- @return #DETECTION_BASE self
function DETECTION_BASE:FilterCategories( FilterCategories ) function DETECTION_BASE:FilterCategories( FilterCategories )
self:F2() self:F2()
@@ -1176,18 +1165,17 @@ do -- DETECTION_BASE
--- Returns if there are friendlies nearby the FAC units ... --- Returns if there are friendlies nearby the FAC units ...
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param DetectedItem -- @param DetectedItem
-- @param Dcs.DCSUnit#Unit.Category Category The category of the unit. -- @param DCS#Unit.Category Category The category of the unit.
-- @return #boolean true if there are friendlies nearby -- @return #boolean true if there are friendlies nearby
function DETECTION_BASE:IsFriendliesNearBy( DetectedItem, Category ) function DETECTION_BASE:IsFriendliesNearBy( DetectedItem, Category )
--self:F( { "FriendliesNearBy Test", DetectedItem.FriendliesNearBy } )
self:F( { "FriendliesNearBy Test", DetectedItem.FriendliesNearBy } )
return ( DetectedItem.FriendliesNearBy and DetectedItem.FriendliesNearBy[Category] ~= nil ) or false return ( DetectedItem.FriendliesNearBy and DetectedItem.FriendliesNearBy[Category] ~= nil ) or false
end end
--- Returns friendly units nearby the FAC units ... --- Returns friendly units nearby the FAC units ...
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param DetectedItem -- @param DetectedItem
-- @param Dcs.DCSUnit#Unit.Category Category The category of the unit. -- @param DCS#Unit.Category Category The category of the unit.
-- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs. -- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs.
function DETECTION_BASE:GetFriendliesNearBy( DetectedItem, Category ) function DETECTION_BASE:GetFriendliesNearBy( DetectedItem, Category )
@@ -1237,7 +1225,7 @@ do -- DETECTION_BASE
--- Background worker function to determine if there are friendlies nearby ... --- Background worker function to determine if there are friendlies nearby ...
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
function DETECTION_BASE:ReportFriendliesNearBy( TargetData ) function DETECTION_BASE:ReportFriendliesNearBy( TargetData )
self:F( { "Search Friendlies", DetectedItem = TargetData.DetectedItem } ) --self:F( { "Search Friendlies", DetectedItem = TargetData.DetectedItem } )
local DetectedItem = TargetData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem local DetectedItem = TargetData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = TargetData.DetectedItem.Set local DetectedSet = TargetData.DetectedItem.Set
@@ -1260,9 +1248,9 @@ do -- DETECTION_BASE
} }
--- @param Dcs.DCSWrapper.Unit#Unit FoundDCSUnit --- @param DCS#Unit FoundDCSUnit
-- @param Wrapper.Group#GROUP ReportGroup -- @param Wrapper.Group#GROUP ReportGroup
-- @param Set#SET_GROUP ReportSetGroup -- @param Core.Set#SET_GROUP ReportSetGroup
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData ) local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
@@ -1286,7 +1274,7 @@ do -- DETECTION_BASE
if FoundUnitInReportSetGroup == true then if FoundUnitInReportSetGroup == true then
-- If the recce was part of the friendlies found, then check if the recce is part of the allowed friendly unit prefixes. -- If the recce was part of the friendlies found, then check if the recce is part of the allowed friendly unit prefixes.
for PrefixID, Prefix in pairs( self.FriendlyPrefixes or {} ) do for PrefixID, Prefix in pairs( self.FriendlyPrefixes or {} ) do
self:F( { "Friendly Prefix:", Prefix = Prefix } ) --self:F( { "Friendly Prefix:", Prefix = Prefix } )
-- In case a match is found (so a recce unit name is part of the friendly prefixes), then report that recce to be part of the friendlies. -- In case a match is found (so a recce unit name is part of the friendly prefixes), then report that recce to be part of the friendlies.
-- This is important if CAP planes (so planes using their own radar) to be scanning for targets as part of the EWR network. -- This is important if CAP planes (so planes using their own radar) to be scanning for targets as part of the EWR network.
-- But CAP planes are also attackers, so they need to be considered friendlies too! -- But CAP planes are also attackers, so they need to be considered friendlies too!
@@ -1298,7 +1286,7 @@ do -- DETECTION_BASE
end end
end end
self:F( { "Friendlies near Target:", FoundUnitName, FoundUnitCoalition, EnemyUnitName, EnemyCoalition, FoundUnitInReportSetGroup } ) --self:F( { "Friendlies near Target:", FoundUnitName, FoundUnitCoalition, EnemyUnitName, EnemyCoalition, FoundUnitInReportSetGroup } )
if FoundUnitCoalition ~= EnemyCoalition and FoundUnitInReportSetGroup == false then if FoundUnitCoalition ~= EnemyCoalition and FoundUnitInReportSetGroup == false then
local FriendlyUnit = UNIT:Find( FoundDCSUnit ) local FriendlyUnit = UNIT:Find( FoundDCSUnit )
@@ -1313,7 +1301,7 @@ do -- DETECTION_BASE
local Distance = DetectedUnitCoord:Get2DDistance( FriendlyUnit:GetCoordinate() ) local Distance = DetectedUnitCoord:Get2DDistance( FriendlyUnit:GetCoordinate() )
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {} DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
DetectedItem.FriendliesDistance[Distance] = FriendlyUnit DetectedItem.FriendliesDistance[Distance] = FriendlyUnit
self:T( { "Friendlies Found:", FriendlyUnitName = FriendlyUnitName, Distance = Distance, FriendlyUnitCategory = FriendlyUnitCategory, FriendliesCategory = self.FriendliesCategory } ) --self:F( { "Friendlies Found:", FriendlyUnitName = FriendlyUnitName, Distance = Distance, FriendlyUnitCategory = FriendlyUnitCategory, FriendliesCategory = self.FriendliesCategory } )
return true return true
end end
@@ -1355,6 +1343,9 @@ do -- DETECTION_BASE
end end
) )
end end
self:F( { Friendlies = DetectedItem.FriendliesNearBy, Players = DetectedItem.PlayersNearBy } )
end end
end end
@@ -1599,7 +1590,7 @@ do -- DETECTION_BASE
return "" return ""
end end
--- Get the @{Set#SET_UNIT} of a detecttion area using a given numeric index. --- Get the @{Core.Set#SET_UNIT} of a detecttion area using a given numeric index.
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param #DETECTION_BASE.DetectedItem DetectedItem -- @param #DETECTION_BASE.DetectedItem DetectedItem
-- @return Core.Set#SET_UNIT DetectedSet -- @return Core.Set#SET_UNIT DetectedSet
@@ -1648,7 +1639,7 @@ do -- DETECTION_BASE
do -- Zones do -- Zones
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index. --- Get the @{Core.Zone#ZONE_UNIT} of a detection area using a given numeric index.
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem. -- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem.
-- @return Core.Zone#ZONE_UNIT DetectedZone -- @return Core.Zone#ZONE_UNIT DetectedZone
@@ -1811,14 +1802,13 @@ end
do -- DETECTION_UNITS do -- DETECTION_UNITS
--- # DETECTION_UNITS class, extends @{Detection#DETECTION_BASE} --- Will detect units within the battle zone.
-- --
-- The DETECTION_UNITS class will detect units within the battle zone. -- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference.
-- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Set#SET_UNIT} containing ONE @{UNIT} object reference.
-- Beware that when the amount of units detected is large, the DetectedItems list will be large also. -- Beware that when the amount of units detected is large, the DetectedItems list will be large also.
-- --
-- @type DETECTION_UNITS -- @type DETECTION_UNITS
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are detected. -- @field DCS#Distance DetectionRange The range till which targets are detected.
-- @extends #DETECTION_BASE -- @extends #DETECTION_BASE
DETECTION_UNITS = { DETECTION_UNITS = {
ClassName = "DETECTION_UNITS", ClassName = "DETECTION_UNITS",
@@ -1886,7 +1876,6 @@ do -- DETECTION_UNITS
-- @param #DETECTION_UNITS self -- @param #DETECTION_UNITS self
-- @return #DETECTION_UNITS self -- @return #DETECTION_UNITS self
function DETECTION_UNITS:CreateDetectionItems() function DETECTION_UNITS:CreateDetectionItems()
self:F2( #self.DetectedObjects )
-- Loop the current detected items, and check if each object still exists and is detected. -- Loop the current detected items, and check if each object still exists and is detected.
@@ -2062,11 +2051,9 @@ end
do -- DETECTION_TYPES do -- DETECTION_TYPES
--- # 3) DETECTION_TYPES class, extends @{Detection#DETECTION_BASE} --- Will detect units within the battle zone.
--
-- The DETECTION_TYPES class will detect units within the battle zone.
-- It will build a DetectedItems[] list filled with DetectedItems, grouped by the type of units detected. -- It will build a DetectedItems[] list filled with DetectedItems, grouped by the type of units detected.
-- Each DetectedItem will contain a field Set, which contains a @{Set#SET_UNIT} containing ONE @{UNIT} object reference. -- Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference.
-- Beware that when the amount of different types detected is large, the DetectedItems[] list will be large also. -- Beware that when the amount of different types detected is large, the DetectedItems[] list will be large also.
-- --
-- @type DETECTION_TYPES -- @type DETECTION_TYPES
@@ -2137,7 +2124,6 @@ do -- DETECTION_TYPES
-- @param #DETECTION_TYPES self -- @param #DETECTION_TYPES self
-- @return #DETECTION_TYPES self -- @return #DETECTION_TYPES self
function DETECTION_TYPES:CreateDetectionItems() function DETECTION_TYPES:CreateDetectionItems()
self:F2( #self.DetectedObjects )
-- Loop the current detected items, and check if each object still exists and is detected. -- Loop the current detected items, and check if each object still exists and is detected.
@@ -2272,41 +2258,39 @@ end
do -- DETECTION_AREAS do -- DETECTION_AREAS
--- # 4) DETECTION_AREAS class, extends @{Detection#DETECTION_BASE} --- Detect units within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s),
-- -- and will build a list (table) of @{Core.Set#SET_UNIT}s containing the @{Wrapper.Unit#UNIT}s detected.
-- The DETECTION_AREAS class will detect units within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s),
-- and will build a list (table) of @{Set#SET_UNIT}s containing the @{Unit#UNIT}s detected.
-- The class is group the detected units within zones given a DetectedZoneRange parameter. -- The class is group the detected units within zones given a DetectedZoneRange parameter.
-- A set with multiple detected zones will be created as there are groups of units detected. -- A set with multiple detected zones will be created as there are groups of units detected.
-- --
-- ## 4.1) Retrieve the Detected Unit Sets and Detected Zones -- ## 4.1) Retrieve the Detected Unit Sets and Detected Zones
-- --
-- The methods to manage the DetectedItems[].Set(s) are implemented in @{Detection#DECTECTION_BASE} and -- The methods to manage the DetectedItems[].Set(s) are implemented in @{Functional.Detection#DECTECTION_BASE} and
-- the methods to manage the DetectedItems[].Zone(s) is implemented in @{Detection#DETECTION_AREAS}. -- the methods to manage the DetectedItems[].Zone(s) is implemented in @{Functional.Detection#DETECTION_AREAS}.
-- --
-- Retrieve the DetectedItems[].Set with the method @{Detection#DETECTION_BASE.GetDetectedSet}(). A @{Set#SET_UNIT} object will be returned. -- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned.
-- --
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Detection#DETECTION_BASE.GetDetectionZones}(). -- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Detection#DETECTION_BASE.GetDetectionZoneCount}(). -- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Detection#DETECTION_BASE.GetDetectionZone}() with a given index. -- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
-- --
-- ## 4.4) Flare or Smoke detected units -- ## 4.4) Flare or Smoke detected units
-- --
-- Use the methods @{Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place. -- Use the methods @{Functional.Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Functional.Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
-- --
-- ## 4.5) Flare or Smoke or Bound detected zones -- ## 4.5) Flare or Smoke or Bound detected zones
-- --
-- Use the methods: -- Use the methods:
-- --
-- * @{Detection#DETECTION_AREAS.FlareDetectedZones}() to flare in a color -- * @{Functional.Detection#DETECTION_AREAS.FlareDetectedZones}() to flare in a color
-- * @{Detection#DETECTION_AREAS.SmokeDetectedZones}() to smoke in a color -- * @{Functional.Detection#DETECTION_AREAS.SmokeDetectedZones}() to smoke in a color
-- * @{Detection#DETECTION_AREAS.SmokeDetectedZones}() to bound with a tire with a white flag -- * @{Functional.Detection#DETECTION_AREAS.SmokeDetectedZones}() to bound with a tire with a white flag
-- --
-- the detected zones when a new detection has taken place. -- the detected zones when a new detection has taken place.
-- --
-- @type DETECTION_AREAS -- @type DETECTION_AREAS
-- @field Dcs.DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. -- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Unit}s, @{Zone}s, the center @{Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange. -- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
-- @extends #DETECTION_BASE -- @extends #DETECTION_BASE
DETECTION_AREAS = { DETECTION_AREAS = {
ClassName = "DETECTION_AREAS", ClassName = "DETECTION_AREAS",
@@ -2317,7 +2301,7 @@ do -- DETECTION_AREAS
--- DETECTION_AREAS constructor. --- DETECTION_AREAS constructor.
-- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS self
-- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role. -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param Dcs.DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. -- @param DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @return #DETECTION_AREAS -- @return #DETECTION_AREAS
function DETECTION_AREAS:New( DetectionSetGroup, DetectionZoneRange ) function DETECTION_AREAS:New( DetectionSetGroup, DetectionZoneRange )
@@ -2525,10 +2509,9 @@ do -- DETECTION_AREAS
-- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS self
-- @return #DETECTION_AREAS self -- @return #DETECTION_AREAS self
function DETECTION_AREAS:CreateDetectionItems() function DETECTION_AREAS:CreateDetectionItems()
self:F2()
self:T( "Checking Detected Items for new Detected Units ..." ) self:T2( "Checking Detected Items for new Detected Units ..." )
-- First go through all detected sets, and check if there are new detected units, match all existing detected units and identify undetected units. -- First go through all detected sets, and check if there are new detected units, match all existing detected units and identify undetected units.
-- Regroup when needed, split groups when needed. -- Regroup when needed, split groups when needed.
for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
@@ -2537,8 +2520,7 @@ do -- DETECTION_AREAS
if DetectedItem then if DetectedItem then
self:T( { "Detected Item ID:", DetectedItemID } ) self:T2( { "Detected Item ID: ", DetectedItemID } )
local DetectedSet = DetectedItem.Set local DetectedSet = DetectedItem.Set
@@ -2667,7 +2649,6 @@ do -- DETECTION_AREAS
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
if DetectedItem then if DetectedItem then
self:T( "Detection Area #" .. DetectedItem.ID )
local DetectedSet = DetectedItem.Set local DetectedSet = DetectedItem.Set
if not self:IsDetectedObjectIdentified( DetectedObject ) and DetectedUnit:IsInZone( DetectedItem.Zone ) then if not self:IsDetectedObjectIdentified( DetectedObject ) and DetectedUnit:IsInZone( DetectedItem.Zone ) then
self:IdentifyDetectedObject( DetectedObject ) self:IdentifyDetectedObject( DetectedObject )

View File

@@ -2,61 +2,60 @@
-- --
-- === -- ===
-- --
-- @{#ESCORT} class -- Allows you to interact with escorting AI on your flight and take the lead.
-- === --
-- The @{#ESCORT} class allows you to interact with escorting AI on your flight and take the lead.
-- Each escorting group can be commanded with a whole set of radio commands (radio menu in your flight, and then F10). -- Each escorting group can be commanded with a whole set of radio commands (radio menu in your flight, and then F10).
-- --
-- The radio commands will vary according the category of the group. The richest set of commands are with Helicopters and AirPlanes. -- The radio commands will vary according the category of the group. The richest set of commands are with Helicopters and AirPlanes.
-- Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts. -- Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts.
-- --
-- RADIO MENUs that can be created: -- # RADIO MENUs that can be created:
-- === --
-- Find a summary below of the current available commands: -- Find a summary below of the current available commands:
-- --
-- Navigation ...: -- ## Navigation ...:
-- --------------- --
-- Escort group navigation functions: -- Escort group navigation functions:
-- --
-- * **"Join-Up and Follow at x meters":** The escort group fill follow you at about x meters, and they will follow you. -- * **"Join-Up and Follow at x meters":** The escort group fill follow you at about x meters, and they will follow you.
-- * **"Flare":** Provides menu commands to let the escort group shoot a flare in the air in a color. -- * **"Flare":** Provides menu commands to let the escort group shoot a flare in the air in a color.
-- * **"Smoke":** Provides menu commands to let the escort group smoke the air in a color. Note that smoking is only available for ground and naval troops. -- * **"Smoke":** Provides menu commands to let the escort group smoke the air in a color. Note that smoking is only available for ground and naval troops.
-- --
-- Hold position ...: -- ## Hold position ...:
-- ------------------ --
-- Escort group navigation functions: -- Escort group navigation functions:
-- --
-- * **"At current location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. -- * **"At current location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped.
-- * **"At client location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. -- * **"At client location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped.
-- --
-- Report targets ...: -- ## Report targets ...:
-- ------------------- --
-- Report targets will make the escort group to report any target that it identifies within a 8km range. Any detected target can be attacked using the 4. Attack nearby targets function. (see below). -- Report targets will make the escort group to report any target that it identifies within a 8km range. Any detected target can be attacked using the 4. Attack nearby targets function. (see below).
-- --
-- * **"Report now":** Will report the current detected targets. -- * **"Report now":** Will report the current detected targets.
-- * **"Report targets on":** Will make the escort group to report detected targets and will fill the "Attack nearby targets" menu list. -- * **"Report targets on":** Will make the escort group to report detected targets and will fill the "Attack nearby targets" menu list.
-- * **"Report targets off":** Will stop detecting targets. -- * **"Report targets off":** Will stop detecting targets.
-- --
-- Scan targets ...: -- ## Scan targets ...:
-- ----------------- --
-- Menu items to pop-up the escort group for target scanning. After scanning, the escort group will resume with the mission or defined task. -- Menu items to pop-up the escort group for target scanning. After scanning, the escort group will resume with the mission or defined task.
-- --
-- * **"Scan targets 30 seconds":** Scan 30 seconds for targets. -- * **"Scan targets 30 seconds":** Scan 30 seconds for targets.
-- * **"Scan targets 60 seconds":** Scan 60 seconds for targets. -- * **"Scan targets 60 seconds":** Scan 60 seconds for targets.
-- --
-- Attack targets ...: -- ## Attack targets ...:
-- ------------------- --
-- This menu item will list all detected targets within a 15km range. Depending on the level of detection (known/unknown) and visuality, the targets type will also be listed. -- This menu item will list all detected targets within a 15km range. Depending on the level of detection (known/unknown) and visuality, the targets type will also be listed.
-- --
-- Request assistance from ...: -- ## Request assistance from ...:
-- ---------------------------- --
-- This menu item will list all detected targets within a 15km range, as with the menu item **Attack Targets**. -- This menu item will list all detected targets within a 15km range, as with the menu item **Attack Targets**.
-- This menu item allows to request attack support from other escorts supporting the current client group. -- This menu item allows to request attack support from other escorts supporting the current client group.
-- eg. the function allows a player to request support from the Ship escort to attack a target identified by the Plane escort with its Tomahawk missiles. -- eg. the function allows a player to request support from the Ship escort to attack a target identified by the Plane escort with its Tomahawk missiles.
-- eg. the function allows a player to request support from other Planes escorting to bomb the unit with illumination missiles or bombs, so that the main plane escort can attack the area. -- eg. the function allows a player to request support from other Planes escorting to bomb the unit with illumination missiles or bombs, so that the main plane escort can attack the area.
-- --
-- ROE ...: -- ## ROE ...:
-- -------- --
-- Sets the Rules of Engagement (ROE) of the escort group when in flight. -- Sets the Rules of Engagement (ROE) of the escort group when in flight.
-- --
-- * **"Hold Fire":** The escort group will hold fire. -- * **"Hold Fire":** The escort group will hold fire.
@@ -64,8 +63,8 @@
-- * **"Open Fire":** The escort group will open fire on designated targets. -- * **"Open Fire":** The escort group will open fire on designated targets.
-- * **"Weapon Free":** The escort group will engage with any target. -- * **"Weapon Free":** The escort group will engage with any target.
-- --
-- Evasion ...: -- ## Evasion ...:
-- ------------ --
-- Will define the evasion techniques that the escort group will perform during flight or combat. -- Will define the evasion techniques that the escort group will perform during flight or combat.
-- --
-- * **"Fight until death":** The escort group will have no reaction to threats. -- * **"Fight until death":** The escort group will have no reaction to threats.
@@ -73,19 +72,19 @@
-- * **"Evade enemy fire":** The rescort group will evade enemy fire before firing. -- * **"Evade enemy fire":** The rescort group will evade enemy fire before firing.
-- * **"Go below radar and evade fire":** The escort group will perform evasive vertical manoeuvres. -- * **"Go below radar and evade fire":** The escort group will perform evasive vertical manoeuvres.
-- --
-- Resume Mission ...: -- ## Resume Mission ...:
-- ------------------- --
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint. -- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission. -- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
-- --
-- ESCORT construction methods. -- # ESCORT construction methods.
-- === --
-- Create a new SPAWN object with the @{#ESCORT.New} method: -- Create a new SPAWN object with the @{#ESCORT.New} method:
-- --
-- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Group#GROUP} for a @{Client#CLIENT}, with an optional briefing text. -- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT}, with an optional briefing text.
-- --
-- ESCORT initialization methods. -- # ESCORT initialization methods.
-- === --
-- The following menus are created within the RADIO MENU (F10) of an active unit hosted by a player: -- The following menus are created within the RADIO MENU (F10) of an active unit hosted by a player:
-- --
-- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client. -- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client.
@@ -114,8 +113,8 @@
-- --
-- --
-- --
-- @module Escort -- @module Functional.Escort
-- @author FlightControl -- @image Escorting.JPG
--- ESCORT class --- ESCORT class
-- @type ESCORT -- @type ESCORT
@@ -127,8 +126,8 @@
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class. -- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
-- @field #number FollowDistance The current follow distance. -- @field #number FollowDistance The current follow distance.
-- @field #boolean ReportTargets If true, nearby targets are reported. -- @field #boolean ReportTargets If true, nearby targets are reported.
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup. -- @Field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup. -- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
-- @field FunctionalMENU_GROUPDETECTION_BASE Detection -- @field FunctionalMENU_GROUPDETECTION_BASE Detection
ESCORT = { ESCORT = {
ClassName = "ESCORT", ClassName = "ESCORT",
@@ -295,7 +294,7 @@ end
--- Defines a menu slot to let the escort Join and Follow you at a certain distance. --- Defines a menu slot to let the escort Join and Follow you at a certain distance.
-- This menu will appear under **Navigation**. -- This menu will appear under **Navigation**.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Dcs.DCSTypes#Distance Distance The distance in meters that the escort needs to follow the client. -- @param DCS#Distance Distance The distance in meters that the escort needs to follow the client.
-- @return #ESCORT -- @return #ESCORT
function ESCORT:MenuFollowAt( Distance ) function ESCORT:MenuFollowAt( Distance )
self:F(Distance) self:F(Distance)
@@ -320,8 +319,8 @@ end
--- Defines a menu slot to let the escort hold at their current position and stay low with a specified height during a specified time in seconds. --- Defines a menu slot to let the escort hold at their current position and stay low with a specified height during a specified time in seconds.
-- This menu will appear under **Hold position**. -- This menu will appear under **Hold position**.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters. -- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given. -- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed. -- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT -- @return #ESCORT
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function. -- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
@@ -381,8 +380,8 @@ end
--- Defines a menu slot to let the escort hold at the client position and stay low with a specified height during a specified time in seconds. --- Defines a menu slot to let the escort hold at the client position and stay low with a specified height during a specified time in seconds.
-- This menu will appear under **Navigation**. -- This menu will appear under **Navigation**.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters. -- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given. -- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed. -- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT -- @return #ESCORT
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function. -- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
@@ -442,8 +441,8 @@ end
--- Defines a menu slot to let the escort scan for targets at a certain height for a certain time in seconds. --- Defines a menu slot to let the escort scan for targets at a certain height for a certain time in seconds.
-- This menu will appear under **Scan targets**. -- This menu will appear under **Scan targets**.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters. -- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given. -- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed. -- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
-- @return #ESCORT -- @return #ESCORT
function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat ) function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat )
@@ -567,7 +566,7 @@ end
-- This menu will appear under **Report targets**. -- This menu will appear under **Report targets**.
-- Note that if a report targets menu is not specified, no targets will be detected by the escort, and the attack and assisted attack menus will not be displayed. -- Note that if a report targets menu is not specified, no targets will be detected by the escort, and the attack and assisted attack menus will not be displayed.
-- @param #ESCORT self -- @param #ESCORT self
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds. -- @param DCS#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds.
-- @return #ESCORT -- @return #ESCORT
function ESCORT:MenuReportTargets( Seconds ) function ESCORT:MenuReportTargets( Seconds )
self:F( { Seconds } ) self:F( { Seconds } )
@@ -737,7 +736,7 @@ end
-- @param Functional.Escort#ESCORT self -- @param Functional.Escort#ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
-- @param Wrapper.Client#CLIENT EscortClient -- @param Wrapper.Client#CLIENT EscortClient
-- @param Dcs.DCSTypes#Distance Distance -- @param DCS#Distance Distance
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance ) function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
self:F( { EscortGroup, EscortClient, Distance } ) self:F( { EscortGroup, EscortClient, Distance } )

View File

@@ -2,8 +2,6 @@
-- --
-- === -- ===
-- --
-- 1) @{MissileTrainer#MISSILETRAINER} class, extends @{Base#BASE}
-- ===
-- The @{#MISSILETRAINER} class uses the DCS world messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft, -- The @{#MISSILETRAINER} class uses the DCS world messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft,
-- the class will destroy the missile within a certain range, to avoid damage to your aircraft. -- the class will destroy the missile within a certain range, to avoid damage to your aircraft.
-- It suports the following functionality: -- It suports the following functionality:
@@ -77,8 +75,8 @@
-- Danny has shared his ideas and together we made a design. -- Danny has shared his ideas and together we made a design.
-- Together with the **476 virtual team**, we tested the MISSILETRAINER class, and got much positive feedback! -- Together with the **476 virtual team**, we tested the MISSILETRAINER class, and got much positive feedback!
-- --
-- @module MissileTrainer -- @module Functional.MissileTrainer
-- @author FlightControl -- @image Missile_Trainer.JPG
--- The MISSILETRAINER class --- The MISSILETRAINER class

View File

@@ -7,7 +7,8 @@
-- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if -- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if
-- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units -- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units
-- on defined intervals (currently every minute). -- on defined intervals (currently every minute).
-- @module Movement -- @module Functional.Movement
-- @image MOOSE.JPG
--- the MOVEMENT class --- the MOVEMENT class
-- @type MOVEMENT -- @type MOVEMENT

View File

@@ -1,305 +0,0 @@
--- **Functional** -- The PROTECT class handles the protection of objects, which can be zones, units, scenery.
--
-- ===
--
-- ### Author: **FlightControl**
-- ### Contributions: **MillerTime**
--
-- ===
--
-- @module Protect
--- @type PROTECT.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
-- @extends Core.Fsm#FSM
--- @type PROTECT
-- @extends #PROTECT.__
--- # PROTECT, extends @{Base#BASE}
--
-- @field #PROTECT
PROTECT = {
ClassName = "PROTECT",
}
--- Get the ProtectZone
-- @param #PROTECT self
-- @return Core.Zone#ZONE_BASE
function PROTECT:GetProtectZone()
return self.ProtectZone
end
--- Get the name of the ProtectZone
-- @param #PROTECT self
-- @return #string
function PROTECT:GetProtectZoneName()
return self.ProtectZone:GetName()
end
--- Set the owning coalition of the zone.
-- @param #PROTECT self
-- @param DCSCoalition.DCSCoalition#coalition Coalition
function PROTECT:SetCoalition( Coalition )
self.Coalition = Coalition
end
--- Get the owning coalition of the zone.
-- @param #PROTECT self
-- @return DCSCoalition.DCSCoalition#coalition Coalition.
function PROTECT:GetCoalition()
return self.Coalition
end
--- Get the owning coalition name of the zone.
-- @param #PROTECT self
-- @return #string Coalition name.
function PROTECT:GetCoalitionName()
if self.Coalition == coalition.side.BLUE then
return "Blue"
end
if self.Coalition == coalition.side.RED then
return "Red"
end
if self.Coalition == coalition.side.NEUTRAL then
return "Neutral"
end
return ""
end
function PROTECT:IsGuarded()
local IsGuarded = self.ProtectZone:IsAllInZoneOfCoalition( self.Coalition )
self:F( { IsGuarded = IsGuarded } )
return IsGuarded
end
function PROTECT:IsCaptured()
local IsCaptured = self.ProtectZone:IsAllInZoneOfOtherCoalition( self.Coalition )
self:F( { IsCaptured = IsCaptured } )
return IsCaptured
end
function PROTECT:IsAttacked()
local IsAttacked = self.ProtectZone:IsSomeInZoneOfCoalition( self.Coalition )
self:F( { IsAttacked = IsAttacked } )
return IsAttacked
end
function PROTECT:IsEmpty()
local IsEmpty = self.ProtectZone:IsNoneInZone()
self:F( { IsEmpty = IsEmpty } )
return IsEmpty
end
--- Check if the units are still alive.
-- @param #PROTECT self
function PROTECT:AreProtectUnitsAlive()
local IsAlive = false
local UnitSet = self.ProtectUnitSet
UnitSet:Flush( self )
local UnitList = UnitSet:GetSet()
for UnitID, ProtectUnit in pairs( UnitList ) do
local IsUnitAlive = ProtectUnit:IsAlive()
if IsUnitAlive == true then
IsAlive = true
break
end
end
return IsAlive
end
--- Check if the statics are still alive.
-- @param #PROTECT self
function PROTECT:AreProtectStaticsAlive()
local IsAlive = false
local StaticSet = self.ProtectStaticSet
StaticSet:Flush( self )
local StaticList = StaticSet:GetSet()
for UnitID, ProtectStatic in pairs( StaticList ) do
local IsStaticAlive = ProtectStatic:IsAlive()
if IsStaticAlive == true then
IsAlive = true
break
end
end
return IsAlive
end
--- Check if there is a capture unit in the zone.
-- @param #PROTECT self
function PROTECT:IsCaptureUnitInZone()
local CaptureUnitSet = self.CaptureUnitSet
CaptureUnitSet:Flush( self )
local IsInZone = self.CaptureUnitSet:IsPartiallyInZone( self.ProtectZone )
self:F({IsInZone = IsInZone})
return IsInZone
end
--- Smoke.
-- @param #PROTECT self
-- @param #SMOKECOLOR.Color SmokeColor
function PROTECT:Smoke( SmokeColor )
self.SmokeColor = SmokeColor
end
--- Flare.
-- @param #PROTECT self
-- @param #SMOKECOLOR.Color FlareColor
function PROTECT:Flare( FlareColor )
self.ProtectZone:FlareZone( FlareColor, math.random( 1, 360 ) )
end
--- Mark.
-- @param #PROTECT self
function PROTECT:Mark()
local Coord = self.ProtectZone:GetCoordinate()
local ZoneName = self:GetProtectZoneName()
local State = self:GetState()
if self.MarkRed and self.MarkBlue then
self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } )
Coord:RemoveMark( self.MarkRed )
Coord:RemoveMark( self.MarkBlue )
end
if self.Coalition == coalition.side.BLUE then
self.MarkBlue = Coord:MarkToCoalitionBlue( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkRed = Coord:MarkToCoalitionRed( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State )
else
self.MarkRed = Coord:MarkToCoalitionRed( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State )
self.MarkBlue = Coord:MarkToCoalitionBlue( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State )
end
end
--- Bound.
-- @param #PROTECT self
function PROTECT:onafterStart()
self:ScheduleRepeat( 5, 15, 0.1, nil, self.StatusCoalition, self )
self:ScheduleRepeat( 5, 15, 0.1, nil, self.StatusZone, self )
self:ScheduleRepeat( 10, 15, 0, nil, self.StatusSmoke, self )
end
--- Bound.
-- @param #PROTECT self
function PROTECT:onenterGuarded()
if self.Coalition == coalition.side.BLUE then
--elf.ProtectZone:BoundZone( 12, country.id.USA )
else
--self.ProtectZone:BoundZone( 12, country.id.RUSSIA )
end
self:Mark()
end
function PROTECT:onenterCaptured()
local NewCoalition = self.ProtectZone:GetCoalition()
self:F( { NewCoalition = NewCoalition } )
self:SetCoalition( NewCoalition )
self:Mark()
end
function PROTECT:onenterEmpty()
self:Mark()
end
function PROTECT:onenterAttacked()
self:Mark()
end
--- Check status Coalition ownership.
-- @param #PROTECT self
function PROTECT:StatusCoalition()
self:F( { State = self:GetState() } )
self.ProtectZone:Scan()
if self:IsGuarded() then
self:Guard()
else
if self:IsCaptured() then
self:Capture()
end
end
end
--- Check status Zone.
-- @param #PROTECT self
function PROTECT:StatusZone()
self:F( { State = self:GetState() } )
self.ProtectZone:Scan()
if self:IsAttacked() then
self:Attack()
else
if self:IsEmpty() then
self:Empty()
end
end
end
--- Check status Smoke.
-- @param #PROTECT self
function PROTECT:StatusSmoke()
local CurrentTime = timer.getTime()
if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then
if self.SmokeColor then
self.ProtectZone:GetCoordinate():Smoke( self.SmokeColor )
--self.SmokeColor = nil
self.SmokeTime = CurrentTime
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,7 @@
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- **Functional** - (R2.2) - Create random airtraffic in your missions. --- **Functional** - (R2.2) - Create random airtraffic in your missions.
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\RAT\RAT.png)
--
-- ===
--
-- The aim of the RAT class is to fill the empty DCS world with randomized air traffic and bring more life to your airports. -- The aim of the RAT class is to fill the empty DCS world with randomized air traffic and bring more life to your airports.
-- --
-- In particular, it is designed to spawn AI air units at random airports. These units will be assigned a random flight path to another random airport on the map. -- In particular, it is designed to spawn AI air units at random airports. These units will be assigned a random flight path to another random airport on the map.
@@ -42,23 +37,25 @@
-- --
-- # Demo Missions -- # Demo Missions
-- --
-- ### [RAT Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/Release/RAT%20-%20Random%20Air%20Traffic) -- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- ### [MOOSE - RAT Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/RAT%20-%20Random%20Air%20Traffic)
-- --
-- === -- ===
-- --
-- # YouTube Channel -- # YouTube Channel
-- --
-- ### [DCS WORLD - MOOSE - RAT - Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO) -- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
-- ### [MOOSE - RAT - Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO)
-- --
-- === -- ===
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)**
-- --
-- ### Contributions: **Sven van de Velde ([FlightControl](https://forums.eagle.ru/member.php?u=89536))** -- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)
-- --
-- === -- ===
-- @module Rat -- @module Functional.Rat
-- @image RAT.JPG
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- RAT class --- RAT class
@@ -116,7 +113,7 @@
-- @field #boolean continuejourney Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination. -- @field #boolean continuejourney Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination.
-- @field #number ngroups Number of groups to be spawned in total. -- @field #number ngroups Number of groups to be spawned in total.
-- @field #number alive Number of groups which are alive. -- @field #number alive Number of groups which are alive.
-- @field #boolean f10menu Add an F10 menu for RAT. -- @field #boolean f10menu If true, add an F10 radiomenu for RAT. Default is false.
-- @field #table Menu F10 menu items for this RAT object. -- @field #table Menu F10 menu items for this RAT object.
-- @field #string SubMenuName Submenu name for RAT object. -- @field #string SubMenuName Submenu name for RAT object.
-- @field #boolean respawn_at_landing Respawn aircraft the moment they land rather than at engine shutdown. -- @field #boolean respawn_at_landing Respawn aircraft the moment they land rather than at engine shutdown.
@@ -151,9 +148,7 @@
-- @field #boolean useparkingdb Parking spots are added to data base once an aircraft has used it. These spots can later be used by other aircraft. Default is true. -- @field #boolean useparkingdb Parking spots are added to data base once an aircraft has used it. These spots can later be used by other aircraft. Default is true.
-- @extends Core.Spawn#SPAWN -- @extends Core.Spawn#SPAWN
---# RAT class, extends @{Spawn#SPAWN} --- Implements an easy to use way to randomly fill your map with AI aircraft.
-- The RAT class implements an easy to use way to randomly fill your map with AI aircraft.
--
-- --
-- ## Airport Selection -- ## Airport Selection
-- --
@@ -350,7 +345,7 @@ RAT={
continuejourney=false, -- Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination. continuejourney=false, -- Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination.
alive=0, -- Number of groups which are alive. alive=0, -- Number of groups which are alive.
ngroups=nil, -- Number of groups to be spawned in total. ngroups=nil, -- Number of groups to be spawned in total.
f10menu=true, -- Add an F10 menu for RAT. f10menu=false, -- Add an F10 menu for RAT.
Menu={}, -- F10 menu items for this RAT object. Menu={}, -- F10 menu items for this RAT object.
SubMenuName=nil, -- Submenu name for RAT object. SubMenuName=nil, -- Submenu name for RAT object.
respawn_at_landing=false, -- Respawn aircraft the moment they land rather than at engine shutdown. respawn_at_landing=false, -- Respawn aircraft the moment they land rather than at engine shutdown.
@@ -506,7 +501,7 @@ RAT.id="RAT | "
--- RAT version. --- RAT version.
-- @list version -- @list version
RAT.version={ RAT.version={
version = "2.2.1", version = "2.2.2",
print = true, print = true,
} }
@@ -1280,7 +1275,7 @@ end
--- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediatly. --- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediatly.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, check is performed. If false, this check is omitted. -- @param #boolean switch If true, check is performed. If false, this check is omitted.
function RAT:CheckOnRunway(switch) function RAT:CheckOnRunway(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then
@@ -1291,7 +1286,7 @@ end
--- Check if aircraft have accidentally been spawned on top of each other. If yes, they will be removed immediately. --- Check if aircraft have accidentally been spawned on top of each other. If yes, they will be removed immediately.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, check is performed. If false, this check is omitted. -- @param #boolean switch If true, check is performed. If false, this check is omitted.
function RAT:CheckOnTop(switch) function RAT:CheckOnTop(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then
@@ -1302,7 +1297,7 @@ end
--- Put parking spot coordinates in a data base for future use of aircraft. --- Put parking spot coordinates in a data base for future use of aircraft.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, parking spots are memorized. This is also the default setting. -- @param #boolean switch If true, parking spots are memorized. This is also the default setting.
function RAT:ParkingSpotDB(switch) function RAT:ParkingSpotDB(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then
@@ -1363,6 +1358,21 @@ function RAT:Immortal()
self.immortal=true self.immortal=true
end end
--- Radio menu On. Default is off.
-- @param #RAT self
function RAT:RadioMenuON()
self:F2()
self.f10menu=true
end
--- Radio menu Off. This is the default setting.
-- @param #RAT self
function RAT:RadioMenuOFF()
self:F2()
self.f10menu=false
end
--- Activate uncontrolled aircraft. --- Activate uncontrolled aircraft.
-- @param #RAT self -- @param #RAT self
-- @param #number maxactivated Maximal numnber of activated aircraft. Absolute maximum will be the number of spawned groups. Default is 1. -- @param #number maxactivated Maximal numnber of activated aircraft. Absolute maximum will be the number of spawned groups. Default is 1.
@@ -1652,7 +1662,7 @@ end
--- Initialize basic parameters of the aircraft based on its (template) group in the mission editor. --- Initialize basic parameters of the aircraft based on its (template) group in the mission editor.
-- @param #RAT self -- @param #RAT self
-- @param Dcs.DCSWrapper.Group#Group DCSgroup Group of the aircraft in the mission editor. -- @param DCS#Group DCSgroup Group of the aircraft in the mission editor.
function RAT:_InitAircraft(DCSgroup) function RAT:_InitAircraft(DCSgroup)
self:F2(DCSgroup) self:F2(DCSgroup)
@@ -3751,11 +3761,11 @@ end
function RAT:_Destroy(group) function RAT:_Destroy(group)
self:F2(group) self:F2(group)
local DCSGroup = group:GetDCSObject() -- Dcs.DCSGroup#Group local DCSGroup = group:GetDCSObject() -- DCS#Group
if DCSGroup and DCSGroup:isExist() then if DCSGroup and DCSGroup:isExist() then
--local DCSUnit = DCSGroup:getUnit(1) -- Dcs.DCSUnit#Unit --local DCSUnit = DCSGroup:getUnit(1) -- DCS#Unit
--if DCSUnit then --if DCSUnit then
-- self:_CreateEventDead(timer.getTime(), DCSUnit) -- self:_CreateEventDead(timer.getTime(), DCSUnit)
--end --end
@@ -3786,8 +3796,8 @@ end
--- Create a Dead event. --- Create a Dead event.
-- @param #RAT self -- @param #RAT self
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event. -- @param DCS#Time EventTime The time stamp of the event.
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event. -- @param DCS#Object Initiator The initiating object of the event.
function RAT:_CreateEventDead(EventTime, Initiator) function RAT:_CreateEventDead(EventTime, Initiator)
self:F( { EventTime, Initiator } ) self:F( { EventTime, Initiator } )
@@ -4019,11 +4029,11 @@ end
--- Orbit at a specified position at a specified alititude with a specified speed. --- Orbit at a specified position at a specified alititude with a specified speed.
-- @param #RAT self -- @param #RAT self
-- @param Dcs.DCSTypes#Vec2 P1 The point to hold the position. -- @param DCS#Vec2 P1 The point to hold the position.
-- @param #number Altitude The altitude ASL at which to hold the position. -- @param #number Altitude The altitude ASL at which to hold the position.
-- @param #number Speed The speed flying when holding the position in m/s. -- @param #number Speed The speed flying when holding the position in m/s.
-- @param #number Duration Duration of holding pattern in seconds. -- @param #number Duration Duration of holding pattern in seconds.
-- @return Dcs.DCSTasking.Task#Task DCSTask -- @return DCS#Task DCSTask
function RAT:_TaskHolding(P1, Altitude, Speed, Duration) function RAT:_TaskHolding(P1, Altitude, Speed, Duration)
--local LandHeight = land.getHeight(P1) --local LandHeight = land.getHeight(P1)
@@ -4265,10 +4275,10 @@ end
function RAT:_CommandImmortal(group, switch) function RAT:_CommandImmortal(group, switch)
-- Command structure for setting groups to invisible. -- Command structure for setting groups to invisible.
local SetInvisible = {id = 'SetImmortal', params = {value = switch}} local SetImmortal = {id = 'SetImmortal', params = {value = switch}}
-- Execute command. -- Execute command.
group:SetCommand(SetInvisible) group:SetCommand(SetImmortal)
end end
--- Adds a parking spot at an airport when it has been used by a spawned RAT aircraft to the RAT parking data base. --- Adds a parking spot at an airport when it has been used by a spawned RAT aircraft to the RAT parking data base.
@@ -5222,7 +5232,7 @@ end
-- @field #number managerid Managing scheduler id. -- @field #number managerid Managing scheduler id.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
---# RATMANAGER class, extends @{Base#BASE} ---# RATMANAGER class, extends @{Core.Base#BASE}
-- The RATMANAGER class manages spawning of multiple RAT objects in a very simple way. It is created by the @{#RATMANAGER.New}() contructor. -- The RATMANAGER class manages spawning of multiple RAT objects in a very simple way. It is created by the @{#RATMANAGER.New}() contructor.
-- RAT objects with different "tasks" can be defined as usual. However, they **must not** be spawned via the @{#RAT.Spawn}() function. -- RAT objects with different "tasks" can be defined as usual. However, they **must not** be spawned via the @{#RAT.Spawn}() function.
-- --

View File

@@ -1,12 +1,7 @@
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- **Functional** - (R2.3) - Range Practice. --- **Functional** - (R2.3) - Range Practice.
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\RANGE\RANGE_Main.png)
--
-- ===
--
-- The RANGE class enables easy set up of bombing and strafing ranges within DCS World. -- The RANGE class enables easy set up of bombing and strafing ranges within DCS World.
-- --
-- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by [Ciribob](https://forums.eagle.ru/member.php?u=112175), which itself was motivated -- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by [Ciribob](https://forums.eagle.ru/member.php?u=112175), which itself was motivated
@@ -32,12 +27,13 @@
-- --
-- # Demo Missions -- # Demo Missions
-- --
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
-- --
-- === -- ===
-- --
-- # YouTube Channel -- # YouTube Channel
-- --
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
-- ### [MOOSE - On the Range - Demonstration Video](https://www.youtube.com/watch?v=kIXcxNB9_3M) -- ### [MOOSE - On the Range - Demonstration Video](https://www.youtube.com/watch?v=kIXcxNB9_3M)
-- --
-- === -- ===
@@ -47,7 +43,8 @@
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536), [Ciribob](https://forums.eagle.ru/member.php?u=112175) -- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536), [Ciribob](https://forums.eagle.ru/member.php?u=112175)
-- --
-- === -- ===
-- @module Range -- @module Functional.Range
-- @image Range.JPG
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- RANGE class --- RANGE class
@@ -69,6 +66,7 @@
-- @field #table bombPlayerResults Table containing the bombing results of each player. -- @field #table bombPlayerResults Table containing the bombing results of each player.
-- @field #table PlayerSettings Indiviual player settings. -- @field #table PlayerSettings Indiviual player settings.
-- @field #number dtBombtrack Time step [sec] used for tracking released bomb/rocket positions. Default 0.005 seconds. -- @field #number dtBombtrack Time step [sec] used for tracking released bomb/rocket positions. Default 0.005 seconds.
-- @field #number BombtrackThreshold Bombs/rockets/missiles are only tracked if player-range distance is smaller than this threashold [m]. Default 25000 m.
-- @field #number Tmsg Time [sec] messages to players are displayed. Default 30 sec. -- @field #number Tmsg Time [sec] messages to players are displayed. Default 30 sec.
-- @field #number strafemaxalt Maximum altitude above ground for registering for a strafe run. Default is 914 m = 3000 ft. -- @field #number strafemaxalt Maximum altitude above ground for registering for a strafe run. Default is 914 m = 3000 ft.
-- @field #number ndisplayresult Number of (player) results that a displayed. Default is 10. -- @field #number ndisplayresult Number of (player) results that a displayed. Default is 10.
@@ -85,8 +83,7 @@
-- @field #boolean trackmissiles If true (default), all missile types are tracked and impact point to closest bombing target is evaluated. -- @field #boolean trackmissiles If true (default), all missile types are tracked and impact point to closest bombing target is evaluated.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
---# RANGE class, extends @{Base#BASE} --- Enables a mission designer to easily set up practice ranges in DCS. A new RANGE object can be created with the @{#RANGE.New}(rangename) contructor.
-- The RANGE class enables a mission designer to easily set up practice ranges in DCS. A new RANGE object can be created with the @{#RANGE.New}(rangename) contructor.
-- The parameter "rangename" defindes the name of the range. It has to be unique since this is also the name displayed in the radio menu. -- The parameter "rangename" defindes the name of the range. It has to be unique since this is also the name displayed in the radio menu.
-- --
-- Generally, a range consists of strafe pits and bombing targets. For strafe pits the number of hits for each pass is counted and tabulated. -- Generally, a range consists of strafe pits and bombing targets. For strafe pits the number of hits for each pass is counted and tabulated.
@@ -107,7 +104,7 @@
-- --
-- A strafe pit can be added to the range by the @{#RANGE.AddStrafepit}(*targetnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*) function. -- A strafe pit can be added to the range by the @{#RANGE.AddStrafepit}(*targetnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*) function.
-- --
-- * The first parameter *targetnames* defines the target or targets. This has to be given as a lua table which contains the names of @{Unit} or @{Static} objects defined in the mission editor. -- * The first parameter *targetnames* defines the target or targets. This has to be given as a lua table which contains the names of @{Wrapper.Unit} or @{Static} objects defined in the mission editor.
-- * In order to perform a valid pass on the strafe pit, the pilot has to begin his run from the correct direction. Therefore, an "approach box" is defined in front -- * In order to perform a valid pass on the strafe pit, the pilot has to begin his run from the correct direction. Therefore, an "approach box" is defined in front
-- of the strafe targets. The parameters *boxlength* and *boxwidth* define the size of the box while the parameter *heading* defines its direction. -- of the strafe targets. The parameters *boxlength* and *boxwidth* define the size of the box while the parameter *heading* defines its direction.
-- If the parameter *heading* is passed as **nil**, the heading is automatically taken from the heading of the first target unit as defined in the ME. -- If the parameter *heading* is passed as **nil**, the heading is automatically taken from the heading of the first target unit as defined in the ME.
@@ -117,7 +114,7 @@
-- * The last parameter *foulline* sets the distance from the pit targets to the foul line. Hit from closer than this line are not counted! -- * The last parameter *foulline* sets the distance from the pit targets to the foul line. Hit from closer than this line are not counted!
-- --
-- Another function to add a strafe pit is @{#RANGE.AddStrafePitGroup}(*group, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*). Here, -- Another function to add a strafe pit is @{#RANGE.AddStrafePitGroup}(*group, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*). Here,
-- the first parameter *group* is a MOOSE @{Group} object and **all** units in this group define **one** strafe pit. -- the first parameter *group* is a MOOSE @{Wrapper.Group} object and **all** units in this group define **one** strafe pit.
-- --
-- Finally, a valid approach has to be performed below a certain maximum altitude. The default is 914 meters (3000 ft) AGL. This is a parameter valid for all -- Finally, a valid approach has to be performed below a certain maximum altitude. The default is 914 meters (3000 ft) AGL. This is a parameter valid for all
-- strafing pits of the range and can be adjusted by the @{#RANGE.SetMaxStrafeAlt}(maxalt) function. -- strafing pits of the range and can be adjusted by the @{#RANGE.SetMaxStrafeAlt}(maxalt) function.
@@ -125,13 +122,13 @@
-- ## Bombing targets -- ## Bombing targets
-- One ore multiple bombing targets can be added to the range by the @{#RANGE.AddBombingTargets}(targetnames, goodhitrange, randommove) function. -- One ore multiple bombing targets can be added to the range by the @{#RANGE.AddBombingTargets}(targetnames, goodhitrange, randommove) function.
-- --
-- * The first parameter *targetnames* has to be a lua table, which contains the names of @{Unit} and/or @{Static} objects defined in the mission editor. -- * The first parameter *targetnames* has to be a lua table, which contains the names of @{Wrapper.Unit} and/or @{Static} objects defined in the mission editor.
-- Note that the @{Range} logic **automatically** determines, if a name belongs to a @{Unit} or @{Static} object now. -- Note that the @{Range} logic **automatically** determines, if a name belongs to a @{Wrapper.Unit} or @{Static} object now.
-- * The (optional) parameter *goodhitrange* specifies the radius around the target. If a bomb or rocket falls at a distance smaller than this number, the hit is considered to be "good". -- * The (optional) parameter *goodhitrange* specifies the radius around the target. If a bomb or rocket falls at a distance smaller than this number, the hit is considered to be "good".
-- * If final (optional) parameter "*randommove*" can be enabled to create moving targets. If this parameter is set to true, the units of this bombing target will randomly move within the range zone. -- * If final (optional) parameter "*randommove*" can be enabled to create moving targets. If this parameter is set to true, the units of this bombing target will randomly move within the range zone.
-- Note that there might be quirks since DCS units can get stuck in buildings etc. So it might be safer to manually define a route for the units in the mission editor if moving targets are desired. -- Note that there might be quirks since DCS units can get stuck in buildings etc. So it might be safer to manually define a route for the units in the mission editor if moving targets are desired.
-- --
-- Another possibility to add bombing targets is the @{#RANGE.AddBombingTargetGroup}(*group, goodhitrange, randommove*) function. Here the parameter *group* is a MOOSE @{Group} object -- Another possibility to add bombing targets is the @{#RANGE.AddBombingTargetGroup}(*group, goodhitrange, randommove*) function. Here the parameter *group* is a MOOSE @{Wrapper.Group} object
-- and **all** units in this group are defined as bombing targets. -- and **all** units in this group are defined as bombing targets.
-- --
-- ## Fine Tuning -- ## Fine Tuning
@@ -211,6 +208,9 @@
-- --
-- The function @{#RANGE.DebugON}() can be used to send messages on screen. It also smokes all defined strafe and bombing targets, the strafe pit approach boxes and the range zone. -- The function @{#RANGE.DebugON}() can be used to send messages on screen. It also smokes all defined strafe and bombing targets, the strafe pit approach boxes and the range zone.
-- --
-- Note that it can happen that the RANGE radio menu is not shown. Check that the range object is defined as a **global** variable rather than a local one.
-- The could avoid the lua garbage collection to accidentally/falsely deallocate the RANGE objects.
--
-- --
-- --
-- @field #RANGE -- @field #RANGE
@@ -232,6 +232,7 @@ RANGE={
bombPlayerResults = {}, bombPlayerResults = {},
PlayerSettings = {}, PlayerSettings = {},
dtBombtrack=0.005, dtBombtrack=0.005,
BombtrackThreshold=25000,
Tmsg=30, Tmsg=30,
strafemaxalt=914, strafemaxalt=914,
ndisplayresult=10, ndisplayresult=10,
@@ -279,7 +280,7 @@ RANGE.id="RANGE | "
--- Range script version. --- Range script version.
-- @field #number version -- @field #number version
RANGE.version="1.1.0" RANGE.version="1.2.0"
--TODO list: --TODO list:
--TODO: Add custom weapons, which can be specified by the user. --TODO: Add custom weapons, which can be specified by the user.
@@ -310,7 +311,7 @@ function RANGE:New(rangename)
self.rangename=rangename or "Practice Range" self.rangename=rangename or "Practice Range"
-- Debug info. -- Debug info.
local text=string.format("RANGE script version %s. Creating new RANGE object. Range name: %s.", RANGE.version, self.rangename) local text=string.format("RANGE script version %s - creating new RANGE object of name: %s.", RANGE.version, self.rangename)
self:E(RANGE.id..text) self:E(RANGE.id..text)
MESSAGE:New(text, 10):ToAllIf(self.Debug) MESSAGE:New(text, 10):ToAllIf(self.Debug)
@@ -447,6 +448,13 @@ function RANGE:SetRangeRadius(radius)
self.rangeradius=radius*1000 or RANGE.Defaults.rangeradius self.rangeradius=radius*1000 or RANGE.Defaults.rangeradius
end end
--- Set bomb track threshold distance. Bombs/rockets/missiles are only tracked if player-range distance is less than this distance. Default 25 km.
-- @param #RANGE self
-- @param #number distance Threshold distance in km. Default 25 km.
function RANGE:SetBombtrackThreshold(distance)
self.BombtrackThreshold=distance*1000 or 25*1000
end
--- Set range location. If this is not done, one (random) unit position of the range is used to determine the center of the range. --- Set range location. If this is not done, one (random) unit position of the range is used to determine the center of the range.
-- @param #RANGE self -- @param #RANGE self
-- @param Core.Point#COORDINATE coordinate Coordinate of the center of the range. -- @param Core.Point#COORDINATE coordinate Coordinate of the center of the range.
@@ -1077,6 +1085,7 @@ function RANGE:OnEventShot(EventData)
local _weaponName = _weaponStrArray[#_weaponStrArray] local _weaponName = _weaponStrArray[#_weaponStrArray]
-- Debug info. -- Debug info.
self:T(RANGE.id.."EVENT SHOT: Range "..self.rangename)
self:T(RANGE.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName) self:T(RANGE.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName)
self:T(RANGE.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName) self:T(RANGE.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName)
self:T(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon) self:T(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon)
@@ -1093,129 +1102,141 @@ function RANGE:OnEventShot(EventData)
-- Check if any condition applies here. -- Check if any condition applies here.
local _track = (_bombs and self.trackbombs) or (_rockets and self.trackrockets) or (_missiles and self.trackmissiles) local _track = (_bombs and self.trackbombs) or (_rockets and self.trackrockets) or (_missiles and self.trackmissiles)
if _track then -- Get unit name.
local _unitName = EventData.IniUnitName
-- Get player unit and name.
local _unit, _playername = self:_GetPlayerUnitAndName(_unitName)
-- Weapon -- Set this to larger value than the threshold.
local _ordnance = EventData.weapon local dPR=self.BombtrackThreshold*2
-- Distance player to range.
if _unit and _playername then
dPR=_unit:GetCoordinate():Get2DDistance(self.location)
self:T(RANGE.id..string.format("Range %s, player %s, player-range distance = %d km.", self.rangename, _playername, dPR/1000))
end
-- Only track if distance player to range is < 25 km.
if _track and dPR<=self.BombtrackThreshold then
-- Tracking info and init of last bomb position. -- Tracking info and init of last bomb position.
self:T(RANGE.id..string.format("Tracking %s - %s.", _weapon, _ordnance:getName())) self:T(RANGE.id..string.format("RANGE %s: Tracking %s - %s.", self.rangename, _weapon, EventData.weapon:getName()))
-- Init bomb position. -- Init bomb position.
local _lastBombPos = {x=0,y=0,z=0} local _lastBombPos = {x=0,y=0,z=0}
-- Get unit name.
local _unitName = EventData.IniUnitName
-- Function monitoring the position of a bomb until impact. -- Function monitoring the position of a bomb until impact.
local function trackBomb(_previousPos) local function trackBomb(_ordnance)
-- When the pcall returns a failure the weapon has hit.
local _status,_bombPos = pcall(
function()
return _ordnance:getPoint()
end)
self:T3(RANGE.id..string.format("Range %s: Bomb still in air: %s", self.rangename, tostring(_status)))
if _status then
-- Get player unit and name. -- Still in the air. Remember this position.
local _unit, _playername = self:_GetPlayerUnitAndName(_unitName) _lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z }
local _callsign=self:_myname(_unitName)
if _unit and _playername then -- Check again in 0.005 seconds.
return timer.getTime() + self.dtBombtrack
-- When the pcall returns a failure the weapon has hit.
local _status,_bombPos = pcall(
function()
return _ordnance:getPoint()
end)
if _status then
-- Still in the air. Remember this position. else
_lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z }
-- Bomb did hit the ground.
-- Check again in 0.005 seconds. -- Get closet target to last position.
return timer.getTime() + self.dtBombtrack local _closetTarget = nil
local _distance = nil
else local _hitquality = "POOR"
-- Bomb did hit the ground. -- Get callsign.
-- Get closet target to last position. local _callsign=self:_myname(_unitName)
local _closetTarget = nil
local _distance = nil -- Coordinate of impact point.
local _hitquality = "POOR" local impactcoord=COORDINATE:NewFromVec3(_lastBombPos)
-- Coordinate of impact point. -- Distance from range. We dont want to smoke targets outside of the range.
local impactcoord=COORDINATE:NewFromVec3(_lastBombPos) local impactdist=impactcoord:Get2DDistance(self.location)
-- Distance from range. We dont want to smoke targets outside of the range. -- Smoke impact point of bomb.
local impactdist=impactcoord:Get2DDistance(self.location) if self.PlayerSettings[_playername].smokebombimpact and impactdist<self.rangeradius then
if self.PlayerSettings[_playername].delaysmoke then
-- Smoke impact point of bomb. timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
if self.PlayerSettings[_playername].smokebombimpact and impactdist<self.rangeradius then else
if self.PlayerSettings[_playername].delaysmoke then impactcoord:Smoke(self.PlayerSettings[_playername].smokecolor)
timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
else
impactcoord:Smoke(self.PlayerSettings[_playername].smokecolor)
end
end end
end
-- Loop over defined bombing targets.
for _,_bombtarget in pairs(self.bombingTargets) do -- Loop over defined bombing targets.
for _,_bombtarget in pairs(self.bombingTargets) do
local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE
if _target and _target:IsAlive() then
-- Distance between bomb and target.
local _temp = impactcoord:Get2DDistance(_target:GetCoordinate())
local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE -- Find closest target to last known position of the bomb.
if _distance == nil or _temp < _distance then
if _target and _target:IsAlive() then _distance = _temp
_closetTarget = _bombtarget
-- Distance between bomb and target. if _distance <= 0.5*_bombtarget.goodhitrange then
local _temp = impactcoord:Get2DDistance(_target:GetCoordinate()) _hitquality = "EXCELLENT"
elseif _distance <= _bombtarget.goodhitrange then
-- Find closest target to last known position of the bomb. _hitquality = "GOOD"
if _distance == nil or _temp < _distance then elseif _distance <= 2*_bombtarget.goodhitrange then
_distance = _temp _hitquality = "INEFFECTIVE"
_closetTarget = _bombtarget else
if _distance <= 0.5*_bombtarget.goodhitrange then _hitquality = "POOR"
_hitquality = "EXCELLENT"
elseif _distance <= _bombtarget.goodhitrange then
_hitquality = "GOOD"
elseif _distance <= 2*_bombtarget.goodhitrange then
_hitquality = "INEFFECTIVE"
else
_hitquality = "POOR"
end
end end
end end
end end
end
-- Count if bomb fell less than 1 km away from the target. -- Count if bomb fell less than 1 km away from the target.
if _distance <= self.scorebombdistance then if _distance <= self.scorebombdistance then
-- Init bomb player results.
if not self.bombPlayerResults[_playername] then
self.bombPlayerResults[_playername] = {}
end
-- Local results.
local _results = self.bombPlayerResults[_playername]
-- Add to table.
table.insert(_results, {name=_closetTarget.name, distance =_distance, weapon = _weaponName, quality=_hitquality })
-- Send message to player. -- Init bomb player results.
local _message = string.format("%s, impact %d m from bullseye of target %s. %s hit.", _callsign, _distance, _closetTarget.name, _hitquality) if not self.bombPlayerResults[_playername] then
self.bombPlayerResults[_playername] = {}
-- Send message.
self:_DisplayMessageToGroup(_unit, _message, nil, true)
elseif _distance <= self.rangeradius then
-- Send message
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
self:_DisplayMessageToGroup(_unit, _message, nil, true)
end end
end -- _status -- Local results.
local _results = self.bombPlayerResults[_playername]
end -- end unit ~= nil -- Add to table.
table.insert(_results, {name=_closetTarget.name, distance =_distance, weapon = _weaponName, quality=_hitquality })
return nil --Terminate the timer
end -- end function bombtrack
timer.scheduleFunction(trackBomb, nil, timer.getTime() + 1) -- Send message to player.
local _message = string.format("%s, impact %d m from bullseye of target %s. %s hit.", _callsign, _distance, _closetTarget.name, _hitquality)
-- Send message.
self:_DisplayMessageToGroup(_unit, _message, nil, true)
elseif _distance <= self.rangeradius then
-- Send message
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
self:_DisplayMessageToGroup(_unit, _message, nil, true)
end
--Terminate the timer
self:T(RANGE.id..string.format("Range %s, player %s: Terminating bomb track timer.", self.rangename, _playername))
return nil
end -- _status check
end -- end function trackBomb
-- Weapon is not yet "alife" just yet. Start timer in one second.
self:T(RANGE.id..string.format("Range %s, player %s: Tracking of weapon starts in one second.", self.rangename, _playername))
timer.scheduleFunction(trackBomb, EventData.weapon, timer.getTime() + 1.0)
end --if string.match end --if _track (string.match) and player-range distance < threshold.
end end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -1537,6 +1558,80 @@ function RANGE:_DisplayRangeInfo(_unitname)
end end
end end
--- Display bombing target locations to player.
-- @param #RANGE self
-- @param #string _unitname Name of the player unit.
function RANGE:_DisplayBombTargets(_unitname)
self:F(_unitname)
-- Get player unit and player name.
local _unit, _playername = self:_GetPlayerUnitAndName(_unitname)
-- Check if we have a player.
if _unit and _playername then
-- Player settings.
local _settings=_DATABASE:GetPlayerSettings(_playername) or _SETTINGS --Core.Settings#SETTINGS
-- Message text.
local _text="Bomb Target Locations:"
for _,_bombtarget in pairs(self.bombingTargets) do
local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE
if _target and _target:IsAlive() then
-- Core.Point#COORDINATE
local coord=_target:GetCoordinate() --Core.Point#COORDINATE
local mycoord=coord:ToStringA2G(_unit, _settings)
_text=_text..string.format("\n- %s: %s",_bombtarget.name, mycoord)
end
end
self:_DisplayMessageToGroup(_unit,_text, nil, true)
end
end
--- Display pit location and heading to player.
-- @param #RANGE self
-- @param #string _unitname Name of the player unit.
function RANGE:_DisplayStrafePits(_unitname)
self:F(_unitname)
-- Get player unit and player name.
local _unit, _playername = self:_GetPlayerUnitAndName(_unitname)
-- Check if we have a player.
if _unit and _playername then
-- Player settings.
local _settings=_DATABASE:GetPlayerSettings(_playername) or _SETTINGS --Core.Settings#SETTINGS
-- Message text.
local _text="Strafe Target Locations:"
for _,_strafepit in pairs(self.strafeTargets) do
local _target=_strafepit --Wrapper.Positionable#POSITIONABLE
-- Pit parameters.
local coord=_strafepit.coordinate --Core.Point#COORDINATE
local heading=_strafepit.heading
-- Turn heading around ==> approach heading.
if heading>180 then
heading=heading-180
else
heading=heading+180
end
local mycoord=coord:ToStringA2G(_unit, _settings)
_text=_text..string.format("\n- %s: %s - heading %03d",_strafepit.name, mycoord, heading)
end
self:_DisplayMessageToGroup(_unit,_text, nil, true)
end
end
--- Report weather conditions at range. Temperature, QFE pressure and wind data. --- Report weather conditions at range. Temperature, QFE pressure and wind data.
-- @param #RANGE self -- @param #RANGE self
-- @param #string _unitname Name of the player unit. -- @param #string _unitname Name of the player unit.
@@ -1792,11 +1887,11 @@ function RANGE:_AddF10Commands(_unitName)
local _statsPath = missionCommands.addSubMenuForGroup(_gid, "Statistics", _rangePath) local _statsPath = missionCommands.addSubMenuForGroup(_gid, "Statistics", _rangePath)
local _markPath = missionCommands.addSubMenuForGroup(_gid, "Mark Targets", _rangePath) local _markPath = missionCommands.addSubMenuForGroup(_gid, "Mark Targets", _rangePath)
local _settingsPath = missionCommands.addSubMenuForGroup(_gid, "My Settings", _rangePath) local _settingsPath = missionCommands.addSubMenuForGroup(_gid, "My Settings", _rangePath)
local _infoPath = missionCommands.addSubMenuForGroup(_gid, "Range Info", _rangePath)
-- F10/On the Range/<Range Name>/My Settings/ -- F10/On the Range/<Range Name>/My Settings/
local _mysmokePath = missionCommands.addSubMenuForGroup(_gid, "Smoke Color", _settingsPath) local _mysmokePath = missionCommands.addSubMenuForGroup(_gid, "Smoke Color", _settingsPath)
local _myflarePath = missionCommands.addSubMenuForGroup(_gid, "Flare Color", _settingsPath) local _myflarePath = missionCommands.addSubMenuForGroup(_gid, "Flare Color", _settingsPath)
--TODO: Convert to MOOSE menu.
-- F10/On the Range/<Range Name>/Mark Targets/ -- F10/On the Range/<Range Name>/Mark Targets/
missionCommands.addCommandForGroup(_gid, "Mark On Map", _markPath, self._MarkTargetsOnMap, self, _unitName) missionCommands.addCommandForGroup(_gid, "Mark On Map", _markPath, self._MarkTargetsOnMap, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Illuminate Range", _markPath, self._IlluminateBombTargets, self, _unitName) missionCommands.addCommandForGroup(_gid, "Illuminate Range", _markPath, self._IlluminateBombTargets, self, _unitName)
@@ -1824,9 +1919,11 @@ function RANGE:_AddF10Commands(_unitName)
missionCommands.addCommandForGroup(_gid, "Smoke Delay On/Off", _settingsPath, self._SmokeBombDelayOnOff, self, _unitName) missionCommands.addCommandForGroup(_gid, "Smoke Delay On/Off", _settingsPath, self._SmokeBombDelayOnOff, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Smoke Impact On/Off", _settingsPath, self._SmokeBombImpactOnOff, self, _unitName) missionCommands.addCommandForGroup(_gid, "Smoke Impact On/Off", _settingsPath, self._SmokeBombImpactOnOff, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Flare Hits On/Off", _settingsPath, self._FlareDirectHitsOnOff, self, _unitName) missionCommands.addCommandForGroup(_gid, "Flare Hits On/Off", _settingsPath, self._FlareDirectHitsOnOff, self, _unitName)
-- F10/On the Range/<Range Name>/ -- F10/On the Range/<Range Name>/Range Information
missionCommands.addCommandForGroup(_gid, "Range Information", _rangePath, self._DisplayRangeInfo, self, _unitName) missionCommands.addCommandForGroup(_gid, "General Info", _infoPath, self._DisplayRangeInfo, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Weather Report", _rangePath, self._DisplayRangeWeather, self, _unitName) missionCommands.addCommandForGroup(_gid, "Weather Report", _infoPath, self._DisplayRangeWeather, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Bombing Targets", _infoPath, self._DisplayBombTargets, self, _unitName)
missionCommands.addCommandForGroup(_gid, "Strafe Pits", _infoPath, self._DisplayStrafePits, self, _unitName)
end end
else else
self:T(RANGE.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName) self:T(RANGE.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName)

View File

@@ -2,15 +2,11 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\SCORING\Dia1.JPG) -- Administers the scoring of player achievements,
--
-- ===
--
-- The @{#SCORING} class administers the scoring of player achievements,
-- and creates a CSV file logging the scoring events and results for use at team or squadron websites. -- and creates a CSV file logging the scoring events and results for use at team or squadron websites.
-- --
-- SCORING automatically calculates the threat level of the objects hit and destroyed by players, -- SCORING automatically calculates the threat level of the objects hit and destroyed by players,
-- which can be @{Unit}, @{Static) and @{Scenery} objects. -- which can be @{Wrapper.Unit}, @{Static) and @{Scenery} objects.
-- --
-- Positive score points are granted when enemy or neutral targets are destroyed. -- Positive score points are granted when enemy or neutral targets are destroyed.
-- Negative score points or penalties are given when a friendly target is hit or destroyed. -- Negative score points or penalties are given when a friendly target is hit or destroyed.
@@ -56,7 +52,7 @@
-- Use the radio menu F10 to consult the scores while running the mission. -- Use the radio menu F10 to consult the scores while running the mission.
-- Scores can be reported for your user, or an overall score can be reported of all players currently active in the mission. -- Scores can be reported for your user, or an overall score can be reported of all players currently active in the mission.
-- --
-- # 1) @{Scoring#SCORING} class, extends @{Base#BASE} -- # 1) @{Functional.Scoring#SCORING} class, extends @{Core.Base#BASE}
-- --
-- ## 1.1) Set the destroy score or penalty scale -- ## 1.1) Set the destroy score or penalty scale
-- --
@@ -74,9 +70,9 @@
-- ## 1.2) Define special targets that will give extra scores. -- ## 1.2) Define special targets that will give extra scores.
-- --
-- Special targets can be set that will give extra scores to the players when these are destroyed. -- Special targets can be set that will give extra scores to the players when these are destroyed.
-- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Unit}s. -- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Wrapper.Unit}s.
-- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Static}s. -- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Static}s.
-- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Group}s. -- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Wrapper.Group}s.
-- --
-- local Scoring = SCORING:New( "Scoring File" ) -- local Scoring = SCORING:New( "Scoring File" )
-- Scoring:AddUnitScore( UNIT:FindByName( "Unit #001" ), 200 ) -- Scoring:AddUnitScore( UNIT:FindByName( "Unit #001" ), 200 )
@@ -93,7 +89,7 @@
-- Define zones of destruction. Any object destroyed within the zone of the given category will give extra points. -- Define zones of destruction. Any object destroyed within the zone of the given category will give extra points.
-- Use the method @{#SCORING.AddZoneScore}() to add a @{Zone} for additional scoring. -- Use the method @{#SCORING.AddZoneScore}() to add a @{Zone} for additional scoring.
-- Use the method @{#SCORING.RemoveZoneScore}() to remove a @{Zone} for additional scoring. -- Use the method @{#SCORING.RemoveZoneScore}() to remove a @{Zone} for additional scoring.
-- There are interesting variations that can be achieved with this functionality. For example, if the @{Zone} is a @{Zone#ZONE_UNIT}, -- There are interesting variations that can be achieved with this functionality. For example, if the @{Zone} is a @{Core.Zone#ZONE_UNIT},
-- then the zone is a moving zone, and anything destroyed within that @{Zone} will generate points. -- then the zone is a moving zone, and anything destroyed within that @{Zone} will generate points.
-- The other implementation could be to designate a scenery target (a building) in the mission editor surrounded by a @{Zone}, -- The other implementation could be to designate a scenery target (a building) in the mission editor surrounded by a @{Zone},
-- just large enough around that building. -- just large enough around that building.
@@ -206,7 +202,8 @@
-- --
-- * **FlightControl**: Concept, Design & Programming. -- * **FlightControl**: Concept, Design & Programming.
-- --
-- @module Scoring -- @module Functional.Scoring
-- @image Scoring.JPG
--- The Scoring class --- The Scoring class
@@ -339,11 +336,11 @@ function SCORING:SetScaleDestroyPenalty( Scale )
return self return self
end end
--- Add a @{Unit} for additional scoring when the @{Unit} is destroyed. --- Add a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
-- Note that if there was already a @{Unit} declared within the scoring with the same name, -- Note that if there was already a @{Wrapper.Unit} declared within the scoring with the same name,
-- then the old @{Unit} will be replaced with the new @{Unit}. -- then the old @{Wrapper.Unit} will be replaced with the new @{Wrapper.Unit}.
-- @param #SCORING self -- @param #SCORING self
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Unit} for which the Score needs to be given. -- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
-- @param #number Score The Score value. -- @param #number Score The Score value.
-- @return #SCORING -- @return #SCORING
function SCORING:AddUnitScore( ScoreUnit, Score ) function SCORING:AddUnitScore( ScoreUnit, Score )
@@ -355,9 +352,9 @@ function SCORING:AddUnitScore( ScoreUnit, Score )
return self return self
end end
--- Removes a @{Unit} for additional scoring when the @{Unit} is destroyed. --- Removes a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
-- @param #SCORING self -- @param #SCORING self
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Unit} for which the Score needs to be given. -- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
-- @return #SCORING -- @return #SCORING
function SCORING:RemoveUnitScore( ScoreUnit ) function SCORING:RemoveUnitScore( ScoreUnit )
@@ -398,9 +395,9 @@ function SCORING:RemoveStaticScore( ScoreStatic )
end end
--- Specify a special additional score for a @{Group}. --- Specify a special additional score for a @{Wrapper.Group}.
-- @param #SCORING self -- @param #SCORING self
-- @param Wrapper.Group#GROUP ScoreGroup The @{Group} for which each @{Unit} a Score is given. -- @param Wrapper.Group#GROUP ScoreGroup The @{Wrapper.Group} for which each @{Wrapper.Unit} a Score is given.
-- @param #number Score The Score value. -- @param #number Score The Score value.
-- @return #SCORING -- @return #SCORING
function SCORING:AddScoreGroup( ScoreGroup, Score ) function SCORING:AddScoreGroup( ScoreGroup, Score )
@@ -714,7 +711,7 @@ end
-- A free text can be given that is shown to the players. -- A free text can be given that is shown to the players.
-- The Score can be both positive and negative. -- The Score can be both positive and negative.
-- @param #SCORING self -- @param #SCORING self
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the Player. Other Properties for the scoring are taken from this PlayerUnit, like coalition, type etc. -- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the Player. Other Properties for the scoring are taken from this PlayerUnit, like coalition, type etc.
-- @param #string GoalTag The string or identifier that is used in the CSV file to identify the goal (sort or group later in Excel). -- @param #string GoalTag The string or identifier that is used in the CSV file to identify the goal (sort or group later in Excel).
-- @param #string Text A free text that is shown to the players. -- @param #string Text A free text that is shown to the players.
-- @param #number Score The score can be both positive or negative ( Penalty ). -- @param #number Score The score can be both positive or negative ( Penalty ).
@@ -858,7 +855,7 @@ function SCORING:OnEventBirth( Event )
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then if Event.IniObjectCategory == 1 then
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName()
if PlayerName ~= "" then if PlayerName then
self:_AddPlayerFromUnit( Event.IniUnit ) self:_AddPlayerFromUnit( Event.IniUnit )
self:SetScoringMenu( Event.IniGroup ) self:SetScoringMenu( Event.IniGroup )
end end

View File

@@ -2,7 +2,8 @@
-- --
-- === -- ===
-- --
-- @module Sead -- @module Functional.Sead
-- @image SEAD.JPG
--- The SEAD class --- The SEAD class
-- @type SEAD -- @type SEAD

File diff suppressed because it is too large Load Diff

View File

@@ -2,10 +2,6 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\ZONE_CAPTURE_COALITION\Dia1.JPG)
--
-- ===
--
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAZ - Capture Zones) -- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAZ - Capture Zones)
-- --
-- - CAZ-000 - Capture Zone: Demonstrates the basic concept of capturing a zone. -- - CAZ-000 - Capture Zone: Demonstrates the basic concept of capturing a zone.
@@ -21,7 +17,8 @@
-- --
-- === -- ===
-- --
-- @module ZoneCaptureCoalition -- @module Functional.ZoneCaptureCoalition
-- @image Capture_Zones.JPG
do -- ZONE_CAPTURE_COALITION do -- ZONE_CAPTURE_COALITION
@@ -29,9 +26,7 @@ do -- ZONE_CAPTURE_COALITION
-- @extends Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION -- @extends Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION
--- # ZONE\_CAPTURE\_COALITION class, extends @{ZoneGoalCoalition#ZONE_GOAL_COALITION} --- Models the process to capture a Zone for a Coalition, which is guarded by another Coalition.
--
-- Models the process to capture a Zone for a Coalition, which is guarded by another Coalition.
-- This is a powerful concept that allows to create very dynamic missions based on the different state transitions of various zones. -- This is a powerful concept that allows to create very dynamic missions based on the different state transitions of various zones.
-- --
-- --- -- ---

View File

@@ -11,7 +11,8 @@
-- --
-- === -- ===
-- --
-- @module ZoneGoal -- @module Functional.ZoneGoal
-- @image MOOSE.JPG
do -- Zone do -- Zone
@@ -19,9 +20,7 @@ do -- Zone
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- # ZONE_GOAL class, extends @{Fsm#FSM} -- Models processes that have a Goal with a defined achievement involving a Zone.
--
-- ZONE_GOAL models processes that have a Goal with a defined achievement involving a Zone.
-- Derived classes implement the ways how the achievements can be realized. -- Derived classes implement the ways how the achievements can be realized.
-- --
-- ## 1. ZONE_GOAL constructor -- ## 1. ZONE_GOAL constructor
@@ -36,7 +35,7 @@ do -- Zone
-- --
-- ### 2.2 ZONE_GOAL Events -- ### 2.2 ZONE_GOAL Events
-- --
-- * DestroyedUnit: A @{Unit} is destroyed in the Zone. The event will only get triggered if the method @{#ZONE_GOAL.MonitorDestroyedUnits}() is used. -- * DestroyedUnit: A @{Wrapper.Unit} is destroyed in the Zone. The event will only get triggered if the method @{#ZONE_GOAL.MonitorDestroyedUnits}() is used.
-- --
-- @field #ZONE_GOAL -- @field #ZONE_GOAL
ZONE_GOAL = { ZONE_GOAL = {

View File

@@ -11,7 +11,8 @@
-- --
-- === -- ===
-- --
-- @module ZoneGoalCargo -- @module Functional.ZoneGoalCargo
-- @image MOOSE.JPG
do -- ZoneGoal do -- ZoneGoal
@@ -19,9 +20,7 @@ do -- ZoneGoal
-- @extends Functional.ZoneGoal#ZONE_GOAL -- @extends Functional.ZoneGoal#ZONE_GOAL
--- # ZONE_GOAL_CARGO class, extends @{ZoneGoal#ZONE_GOAL} --- Models processes that have a Goal with a defined achievement involving a Zone and Cargo.
--
-- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo.
-- Derived classes implement the ways how the achievements can be realized. -- Derived classes implement the ways how the achievements can be realized.
-- --
-- ## 1. ZONE_GOAL_CARGO constructor -- ## 1. ZONE_GOAL_CARGO constructor

View File

@@ -11,7 +11,8 @@
-- --
-- === -- ===
-- --
-- @module ZoneGoalCoalition -- @module Functional.ZoneGoalCoalition
-- @image MOOSE.JPG
do -- ZoneGoal do -- ZoneGoal
@@ -19,9 +20,7 @@ do -- ZoneGoal
-- @extends Functional.ZoneGoal#ZONE_GOAL -- @extends Functional.ZoneGoal#ZONE_GOAL
--- # ZONE_GOAL_COALITION class, extends @{ZoneGoal#ZONE_GOAL} --- ZONE_GOAL_COALITION models processes that have a Goal with a defined achievement involving a Zone for a Coalition.
--
-- ZONE_GOAL_COALITION models processes that have a Goal with a defined achievement involving a Zone for a Coalition.
-- Derived classes implement the ways how the achievements can be realized. -- Derived classes implement the ways how the achievements can be realized.
-- --
-- ## 1. ZONE_GOAL_COALITION constructor -- ## 1. ZONE_GOAL_COALITION constructor

View File

@@ -13,3 +13,6 @@ _DATABASE = DATABASE:New() -- Core.Database#DATABASE
_SETTINGS = SETTINGS:Set() _SETTINGS = SETTINGS:Set()
_SETTINGS:SetPlayerMenuOn() _SETTINGS:SetPlayerMenuOn()
_DATABASE:_RegisterCargos()
_DATABASE:_RegisterZones()

View File

@@ -1,5 +1,12 @@
--- **Tasking** -- A COMMANDCENTER is the owner of multiple missions within MOOSE. --- **Tasking** -- A command center governs multiple missions, and takes care of the reporting and communications.
-- A COMMANDCENTER governs multiple missions, the tasking and the reporting. --
-- **Features:**
--
-- * Govern multiple missions.
-- * Communicate to coalitions, groups.
-- * Assign tasks.
-- * Manage the menus.
-- * Manage reference zones.
-- --
-- === -- ===
-- --
@@ -9,23 +16,19 @@
-- --
-- === -- ===
-- --
-- @module CommandCenter -- @module Tasking.CommandCenter
-- @image Task_Command_Center.JPG
--- The COMMANDCENTER class --- The COMMANDCENTER class
-- @type COMMANDCENTER -- @type COMMANDCENTER
-- @field Wrapper.Group#GROUP HQ -- @field Wrapper.Group#GROUP HQ
-- @field Dcs.DCSCoalitionWrapper.Object#coalition CommandCenterCoalition -- @field DCS#coalition CommandCenterCoalition
-- @list<Tasking.Mission#MISSION> Missions -- @list<Tasking.Mission#MISSION> Missions
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- # COMMANDCENTER class, extends @{Base#BASE} --- Governs multiple missions, the tasking and the reporting.
--
-- The COMMANDCENTER class governs multiple missions, the tasking and the reporting.
-- --
-- The commandcenter communicates important messages between the various groups of human players executing tasks in missions. -- The commandcenter communicates important messages between the various groups of human players executing tasks in missions.
-- --
@@ -86,11 +89,13 @@ COMMANDCENTER = {
-- @return #COMMANDCENTER -- @return #COMMANDCENTER
function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName ) function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() ) -- #COMMANDCENTER
self.CommandCenterPositionable = CommandCenterPositionable self.CommandCenterPositionable = CommandCenterPositionable
self.CommandCenterName = CommandCenterName or CommandCenterPositionable:GetName() self.CommandCenterName = CommandCenterName or CommandCenterPositionable:GetName()
self.CommandCenterCoalition = CommandCenterPositionable:GetCoalition() self.CommandCenterCoalition = CommandCenterPositionable:GetCoalition()
self.AutoAssignTasks = false
self.Missions = {} self.Missions = {}
@@ -171,7 +176,7 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
end end
) )
-- Handle when a player leaves a slot and goes back to spectators ... -- Handle when a player crashes ...
-- The PlayerUnit will be UnAssigned from the Task. -- The PlayerUnit will be UnAssigned from the Task.
-- When there is no Unit left running the Task, the Task goes into Abort... -- When there is no Unit left running the Task, the Task goes into Abort...
self:HandleEvent( EVENTS.Crash, self:HandleEvent( EVENTS.Crash,
@@ -220,6 +225,14 @@ function COMMANDCENTER:GetShortText()
end end
--- Gets the coalition of the command center.
-- @param #COMMANDCENTER self
-- @return DCScoalition#coalition
function COMMANDCENTER:GetCoalition()
return self.CommandCenterCoalition
end
--- Gets the POSITIONABLE of the HQ command center. --- Gets the POSITIONABLE of the HQ command center.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
@@ -233,7 +246,7 @@ end
-- @return #list<Tasking.Mission#MISSION> -- @return #list<Tasking.Mission#MISSION>
function COMMANDCENTER:GetMissions() function COMMANDCENTER:GetMissions()
return self.Missions return self.Missions or {}
end end
--- Add a MISSION to be governed by the HQ command center. --- Add a MISSION to be governed by the HQ command center.
@@ -322,7 +335,7 @@ end
--- Sets the menu structure of the Missions governed by the HQ command center. --- Sets the menu structure of the Missions governed by the HQ command center.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
function COMMANDCENTER:SetMenu() function COMMANDCENTER:SetMenu()
self:F() self:F2()
local MenuTime = timer.getTime() local MenuTime = timer.getTime()
for MissionID, Mission in pairs( self:GetMissions() or {} ) do for MissionID, Mission in pairs( self:GetMissions() or {} ) do
@@ -331,7 +344,7 @@ function COMMANDCENTER:SetMenu()
end end
for MissionID, Mission in pairs( self:GetMissions() or {} ) do for MissionID, Mission in pairs( self:GetMissions() or {} ) do
local Mission = Mission -- Tasking.Mission#MISSION Mission = Mission -- Tasking.Mission#MISSION
Mission:RemoveMenu( MenuTime ) Mission:RemoveMenu( MenuTime )
end end
@@ -340,10 +353,133 @@ end
--- Gets the commandcenter menu structure governed by the HQ command center. --- Gets the commandcenter menu structure governed by the HQ command center.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
-- @return Core.Menu#MENU_COALITION -- @return Core.Menu#MENU_COALITION
function COMMANDCENTER:GetMenu() function COMMANDCENTER:GetMenu( TaskGroup )
return self.CommandCenterMenu
local MenuTime = timer.getTime()
self.CommandCenterMenus = self.CommandCenterMenus or {}
local CommandCenterMenu
local CommandCenterText = self:GetText()
CommandCenterMenu = MENU_GROUP:New( TaskGroup, CommandCenterText ):SetTime(MenuTime)
self.CommandCenterMenus[TaskGroup] = CommandCenterMenu
if self.AutoAssignTasks == false then
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task On", CommandCenterMenu, self.SetAutoAssignTasks, self, true ):SetTime(MenuTime):SetTag("AutoTask")
local AssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task", CommandCenterMenu, self.AssignRandomTask, self, TaskGroup ):SetTime(MenuTime):SetTag("AutoTask")
else
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task Off", CommandCenterMenu, self.SetAutoAssignTasks, self, false ):SetTime(MenuTime):SetTag("AutoTask")
end
CommandCenterMenu:Remove( MenuTime, "AutoTask" )
return self.CommandCenterMenus[TaskGroup]
end end
--- Assigns a random task to a TaskGroup.
-- @param #COMMANDCENTER self
-- @return #COMMANDCENTER
function COMMANDCENTER:AssignRandomTask( TaskGroup )
local Tasks = {}
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
local MissionTasks = Mission:GetGroupTasks( TaskGroup )
for MissionTaskName, MissionTask in pairs( MissionTasks or {} ) do
Tasks[#Tasks+1] = MissionTask
end
end
local Task = Tasks[ math.random( 1, #Tasks ) ] -- Tasking.Task#TASK
Task:SetAssignMethod( ACT_ASSIGN_MENU_ACCEPT:New( Task.TaskBriefing ) )
Task:AssignToGroup( TaskGroup )
end
--- Automatically assigns tasks to all TaskGroups.
-- @param #COMMANDCENTER self
-- @param #boolean AutoAssign true for ON and false or nil for OFF.
-- @return #COMMANDCENTER
function COMMANDCENTER:SetAutoAssignTasks( AutoAssign )
self.AutoAssignTasks = AutoAssign or false
local GroupSet = self:AddGroups()
for GroupID, TaskGroup in pairs( GroupSet:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
self:GetMenu( TaskGroup )
end
if self.AutoAssignTasks == true then
self:ScheduleRepeat( 10, 30, 0, nil, self.AssignTasks, self )
else
self:ScheduleStop( self.AssignTasks )
end
end
--- Automatically assigns tasks to all TaskGroups.
-- @param #COMMANDCENTER self
function COMMANDCENTER:AssignTasks()
local GroupSet = self:AddGroups()
for GroupID, TaskGroup in pairs( GroupSet:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( TaskGroup ) then
else
-- Only groups with planes or helicopters will receive automatic tasks.
-- TODO Workaround DCS-BUG-3 - https://github.com/FlightControl-Master/MOOSE/issues/696
if TaskGroup:IsAir() then
self:AssignRandomTask( TaskGroup )
end
end
end
end
--- Get all the Groups active within the command center.
-- @param #COMMANDCENTER self
-- @return Core.Set#SET_GROUP
function COMMANDCENTER:AddGroups()
local GroupSet = SET_GROUP:New()
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
GroupSet = Mission:AddGroups( GroupSet )
end
return GroupSet
end
--- Checks of the TaskGroup has a Task.
-- @param #COMMANDCENTER self
-- @return #boolean
function COMMANDCENTER:IsGroupAssigned( TaskGroup )
local Assigned = false
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
if Mission:IsGroupAssigned( TaskGroup ) then
Assigned = true
break
end
end
return Assigned
end
--- Checks of the COMMANDCENTER has a GROUP. --- Checks of the COMMANDCENTER has a GROUP.
-- @param #COMMANDCENTER self -- @param #COMMANDCENTER self
-- @param Wrapper.Group#GROUP -- @param Wrapper.Group#GROUP
@@ -399,7 +535,7 @@ function COMMANDCENTER:MessageToCoalition( Message )
local CCCoalition = self:GetPositionable():GetCoalition() local CCCoalition = self:GetPositionable():GetCoalition()
--TODO: Fix coalition bug! --TODO: Fix coalition bug!
self:GetPositionable():MessageToCoalition( Message, 15, CCCoalition ) self:GetPositionable():MessageToCoalition( Message, 15, CCCoalition, self:GetShortText() )
end end
@@ -413,7 +549,7 @@ function COMMANDCENTER:MessageTypeToCoalition( Message, MessageType )
local CCCoalition = self:GetPositionable():GetCoalition() local CCCoalition = self:GetPositionable():GetCoalition()
--TODO: Fix coalition bug! --TODO: Fix coalition bug!
self:GetPositionable():MessageTypeToCoalition( Message, MessageType, CCCoalition ) self:GetPositionable():MessageTypeToCoalition( Message, MessageType, CCCoalition, self:GetShortText() )
end end

View File

@@ -1,38 +1,36 @@
--- This module contains the DETECTION_MANAGER class and derived classes. --- **Tasking** - This module contains the DETECTION_MANAGER class and derived classes.
-- --
-- === -- ===
-- --
-- 1) @{DetectionManager#DETECTION_MANAGER} class, extends @{Fsm#FSM} -- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
-- ===
-- The @{DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour. -- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
-- --
-- 1.1) DETECTION_MANAGER constructor: -- 1.1) DETECTION_MANAGER constructor:
-- ----------------------------------- -- -----------------------------------
-- * @{DetectionManager#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance. -- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
-- --
-- 1.2) DETECTION_MANAGER reporting: -- 1.2) DETECTION_MANAGER reporting:
-- --------------------------------- -- ---------------------------------
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{DetectionManager#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour. -- Derived DETECTION_MANAGER classes will reports detected units using the method @{#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
-- --
-- The time interval in seconds of the reporting can be changed using the methods @{DetectionManager#DETECTION_MANAGER.SetRefreshTimeInterval}(). -- The time interval in seconds of the reporting can be changed using the methods @{#DETECTION_MANAGER.SetRefreshTimeInterval}().
-- To control how long a reporting message is displayed, use @{DetectionManager#DETECTION_MANAGER.SetReportDisplayTime}(). -- To control how long a reporting message is displayed, use @{#DETECTION_MANAGER.SetReportDisplayTime}().
-- Derived classes need to implement the method @{DetectionManager#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report. -- Derived classes need to implement the method @{#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
-- --
-- Reporting can be started and stopped using the methods @{DetectionManager#DETECTION_MANAGER.StartReporting}() and @{DetectionManager#DETECTION_MANAGER.StopReporting}() respectively. -- Reporting can be started and stopped using the methods @{#DETECTION_MANAGER.StartReporting}() and @{#DETECTION_MANAGER.StopReporting}() respectively.
-- If an ad-hoc report is requested, use the method @{DetectionManager#DETECTION_MANAGER#ReportNow}(). -- If an ad-hoc report is requested, use the method @{#DETECTION_MANAGER#ReportNow}().
-- --
-- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds. -- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds.
-- --
-- === -- ===
-- --
-- 2) @{DetectionManager#DETECTION_REPORTING} class, extends @{DetectionManager#DETECTION_MANAGER} -- 2) @{#DETECTION_REPORTING} class, extends @{#DETECTION_MANAGER}
-- === -- ===
-- The @{DetectionManager#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{DetectionManager#DETECTION_MANAGER} class. -- The @{#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{Tasking.DetectionManager#DETECTION_MANAGER} class.
-- --
-- 2.1) DETECTION_REPORTING constructor: -- 2.1) DETECTION_REPORTING constructor:
-- ------------------------------- -- -------------------------------
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance. -- The @{#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
-- --
-- --
-- === -- ===
@@ -40,13 +38,14 @@
-- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing -- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing
-- ### Author: FlightControl - Framework Design & Programming -- ### Author: FlightControl - Framework Design & Programming
-- --
-- @module DetectionManager -- @module Tasking.DetectionManager
-- @image Task_Detection_Manager.JPG
do -- DETECTION MANAGER do -- DETECTION MANAGER
--- DETECTION_MANAGER class. --- DETECTION_MANAGER class.
-- @type DETECTION_MANAGER -- @type DETECTION_MANAGER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to. -- @field Core.Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects. -- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
DETECTION_MANAGER = { DETECTION_MANAGER = {
@@ -57,7 +56,7 @@ do -- DETECTION MANAGER
--- FAC constructor. --- FAC constructor.
-- @param #DETECTION_MANAGER self -- @param #DETECTION_MANAGER self
-- @param Set#SET_GROUP SetGroup -- @param Core.Set#SET_GROUP SetGroup
-- @param Functional.Detection#DETECTION_BASE Detection -- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_MANAGER self -- @return #DETECTION_MANAGER self
function DETECTION_MANAGER:New( SetGroup, Detection ) function DETECTION_MANAGER:New( SetGroup, Detection )
@@ -122,6 +121,48 @@ do -- DETECTION MANAGER
-- @function [parent=#DETECTION_MANAGER] __Stop -- @function [parent=#DETECTION_MANAGER] __Stop
-- @param #DETECTION_MANAGER self -- @param #DETECTION_MANAGER self
-- @param #number Delay -- @param #number Delay
self:AddTransition( "Started", "Success", "Started" )
--- Success Handler OnAfter for DETECTION_MANAGER
-- @function [parent=#DETECTION_MANAGER] OnAfterSuccess
-- @param #DETECTION_MANAGER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Tasking.Task#TASK Task
self:AddTransition( "Started", "Failed", "Started" )
--- Failed Handler OnAfter for DETECTION_MANAGER
-- @function [parent=#DETECTION_MANAGER] OnAfterFailed
-- @param #DETECTION_MANAGER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Tasking.Task#TASK Task
self:AddTransition( "Started", "Aborted", "Started" )
--- Aborted Handler OnAfter for DETECTION_MANAGER
-- @function [parent=#DETECTION_MANAGER] OnAfterAborted
-- @param #DETECTION_MANAGER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Tasking.Task#TASK Task
self:AddTransition( "Started", "Cancelled", "Started" )
--- Cancelled Handler OnAfter for DETECTION_MANAGER
-- @function [parent=#DETECTION_MANAGER] OnAfterCancelled
-- @param #DETECTION_MANAGER self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Tasking.Task#TASK Task
self:AddTransition( "Started", "Report", "Started" ) self:AddTransition( "Started", "Report", "Started" )
@@ -175,7 +216,7 @@ do -- DETECTION MANAGER
return self._ReportDisplayTime return self._ReportDisplayTime
end end
--- Reports the detected items to the @{Set#SET_GROUP}. --- Reports the detected items to the @{Core.Set#SET_GROUP}.
-- @param #DETECTION_MANAGER self -- @param #DETECTION_MANAGER self
-- @param Functional.Detection#DETECTION_BASE Detection -- @param Functional.Detection#DETECTION_BASE Detection
-- @return #DETECTION_MANAGER self -- @return #DETECTION_MANAGER self
@@ -191,7 +232,7 @@ do -- DETECTION_REPORTING
--- DETECTION_REPORTING class. --- DETECTION_REPORTING class.
-- @type DETECTION_REPORTING -- @type DETECTION_REPORTING
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to. -- @field Core.Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects. -- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
-- @extends #DETECTION_MANAGER -- @extends #DETECTION_MANAGER
DETECTION_REPORTING = { DETECTION_REPORTING = {
@@ -201,7 +242,7 @@ do -- DETECTION_REPORTING
--- DETECTION_REPORTING constructor. --- DETECTION_REPORTING constructor.
-- @param #DETECTION_REPORTING self -- @param #DETECTION_REPORTING self
-- @param Set#SET_GROUP SetGroup -- @param Core.Set#SET_GROUP SetGroup
-- @param Functional.Detection#DETECTION_AREAS Detection -- @param Functional.Detection#DETECTION_AREAS Detection
-- @return #DETECTION_REPORTING self -- @return #DETECTION_REPORTING self
function DETECTION_REPORTING:New( SetGroup, Detection ) function DETECTION_REPORTING:New( SetGroup, Detection )
@@ -215,7 +256,7 @@ do -- DETECTION_REPORTING
--- Creates a string of the detected items in a @{Detection}. --- Creates a string of the detected items in a @{Detection}.
-- @param #DETECTION_MANAGER self -- @param #DETECTION_MANAGER self
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Detection#DETECTION_BASE} object. -- @param Core.Set#SET_UNIT DetectedSet The detected Set created by the @{Functional.Detection#DETECTION_BASE} object.
-- @return #DETECTION_MANAGER self -- @return #DETECTION_MANAGER self
function DETECTION_REPORTING:GetDetectedItemsText( DetectedSet ) function DETECTION_REPORTING:GetDetectedItemsText( DetectedSet )
self:F2() self:F2()
@@ -245,10 +286,10 @@ do -- DETECTION_REPORTING
--- Reports the detected items to the @{Set#SET_GROUP}. --- Reports the detected items to the @{Core.Set#SET_GROUP}.
-- @param #DETECTION_REPORTING self -- @param #DETECTION_REPORTING self
-- @param Wrapper.Group#GROUP Group The @{Group} object to where the report needs to go. -- @param Wrapper.Group#GROUP Group The @{Wrapper.Group} object to where the report needs to go.
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_BASE} object. -- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Functional.Detection#DETECTION_BASE} object.
-- @return #boolean Return true if you want the reporting to continue... false will cancel the reporting loop. -- @return #boolean Return true if you want the reporting to continue... false will cancel the reporting loop.
function DETECTION_REPORTING:ProcessDetected( Group, Detection ) function DETECTION_REPORTING:ProcessDetected( Group, Detection )
self:F2( Group ) self:F2( Group )

View File

@@ -1,4 +1,12 @@
--- **Tasking** -- A MISSION is the main owner of a Mission orchestration within MOOSE. --- **Tasking** -- A mission models a goal to be achieved through the execution and completion of tasks by human players.
--
-- **Features:**
--
-- * A mission has a goal to be achieved, through the execution and completion of tasks of different categories by human players.
-- * A mission manages these tasks.
-- * A mission has a state, that indicates the fase of the mission.
-- * A mission has a menu structure, that facilitates mission reports and tasking menus.
-- * A mission can assign a task to a player.
-- --
-- === -- ===
-- --
@@ -8,7 +16,8 @@
-- --
-- === -- ===
-- --
-- @module Mission -- @module Tasking.Mission
-- @image Task_Mission.JPG
--- The MISSION class --- The MISSION class
-- @type MISSION -- @type MISSION
@@ -29,7 +38,7 @@ MISSION = {
-- @param #string MissionName is the name of the mission. This name will be used to reference the status of each mission by the players. -- @param #string MissionName is the name of the mission. This name will be used to reference the status of each mission by the players.
-- @param #string MissionPriority is a string indicating the "priority" of the Mission. f.e. "Primary", "Secondary" or "First", "Second". It is free format and up to the Mission designer to choose. There are no rules behind this field. -- @param #string MissionPriority is a string indicating the "priority" of the Mission. f.e. "Primary", "Secondary" or "First", "Second". It is free format and up to the Mission designer to choose. There are no rules behind this field.
-- @param #string MissionBriefing is a string indicating the mission briefing to be shown when a player joins a @{CLIENT}. -- @param #string MissionBriefing is a string indicating the mission briefing to be shown when a player joins a @{CLIENT}.
-- @param Dcs.DCSCoalitionWrapper.Object#coalition MissionCoalition is a string indicating the coalition or party to which this mission belongs to. It is free format and can be chosen freely by the mission designer. Note that this field is not to be confused with the coalition concept of the ME. Examples of a Mission Coalition could be "NATO", "CCCP", "Intruders", "Terrorists"... -- @param #string MissionCoalition is a string indicating the coalition or party to which this mission belongs to. It is free format and can be chosen freely by the mission designer. Note that this field is not to be confused with the coalition concept of the ME. Examples of a Mission Coalition could be "NATO", "CCCP", "Intruders", "Terrorists"...
-- @return #MISSION self -- @return #MISSION self
function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefing, MissionCoalition ) function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefing, MissionCoalition )
@@ -265,6 +274,8 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
end end
--- FSM function for a MISSION --- FSM function for a MISSION
-- @param #MISSION self -- @param #MISSION self
-- @param #string From -- @param #string From
@@ -375,24 +386,30 @@ function MISSION:GetScoring()
return self.Scoring return self.Scoring
end end
--- Get the groups for which TASKS are given in the mission --- Gets the groups for which TASKS are given in the mission
-- @param #MISSION self -- @param #MISSION self
-- @param Core.Set#SET_GROUP GroupSet
-- @return Core.Set#SET_GROUP -- @return Core.Set#SET_GROUP
function MISSION:GetGroups() function MISSION:GetGroups()
local SetGroup = SET_GROUP:New() return self:AddGroups()
end
--- Adds the groups for which TASKS are given in the mission
-- @param #MISSION self
-- @param Core.Set#SET_GROUP GroupSet
-- @return Core.Set#SET_GROUP
function MISSION:AddGroups( GroupSet )
GroupSet = GroupSet or SET_GROUP:New()
for TaskID, Task in pairs( self:GetTasks() ) do for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK local Task = Task -- Tasking.Task#TASK
local GroupSet = Task:GetGroups() GroupSet = Task:AddGroups( GroupSet )
GroupSet:ForEachGroup(
function( TaskGroup )
SetGroup:Add( TaskGroup, TaskGroup )
end
)
end end
return SetGroup return GroupSet
end end
@@ -441,16 +458,16 @@ do -- Group Assignment
local MissionGroupName = MissionGroup:GetName() local MissionGroupName = MissionGroup:GetName()
if self.AssignedGroups[MissionGroupName] == MissionGroup then if self.AssignedGroups[MissionGroupName] == MissionGroup then
self:T( { "Mission is assigned to:", MissionGroup:GetName() } ) self:T2( { "Mission is assigned to:", MissionGroup:GetName() } )
return true return true
end end
self:T( { "Mission is not assigned to:", MissionGroup:GetName() } ) self:T2( { "Mission is not assigned to:", MissionGroup:GetName() } )
return false return false
end end
--- Set @{Group} assigned to the @{Mission}. --- Set @{Wrapper.Group} assigned to the @{Mission}.
-- @param #MISSION self -- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup -- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION -- @return #MISSION
@@ -465,7 +482,7 @@ do -- Group Assignment
return self return self
end end
--- Clear the @{Group} assignment from the @{Mission}. --- Clear the @{Wrapper.Group} assignment from the @{Mission}.
-- @param #MISSION self -- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup -- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION -- @return #MISSION
@@ -522,18 +539,13 @@ end
function MISSION:GetMenu( TaskGroup ) -- R2.1 -- Changed Menu Structure function MISSION:GetMenu( TaskGroup ) -- R2.1 -- Changed Menu Structure
local CommandCenter = self:GetCommandCenter() local CommandCenter = self:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu() local CommandCenterMenu = CommandCenter:GetMenu( TaskGroup )
--local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
self.MissionGroupMenu = self.MissionGroupMenu or {} self.MissionGroupMenu = self.MissionGroupMenu or {}
self.MissionGroupMenu[TaskGroup] = self.MissionGroupMenu[TaskGroup] or {} self.MissionGroupMenu[TaskGroup] = self.MissionGroupMenu[TaskGroup] or {}
local GroupMenu = self.MissionGroupMenu[TaskGroup] local GroupMenu = self.MissionGroupMenu[TaskGroup]
local CommandCenterText = CommandCenter:GetText()
CommandCenterMenu = MENU_GROUP:New( TaskGroup, CommandCenterText )
local MissionText = self:GetText() local MissionText = self:GetText()
self.MissionMenu = MENU_GROUP:New( TaskGroup, MissionText, CommandCenterMenu ) self.MissionMenu = MENU_GROUP:New( TaskGroup, MissionText, CommandCenterMenu )
@@ -562,7 +574,7 @@ end
-- @param #string TaskName The Name of the @{Task} within the @{Mission}. -- @param #string TaskName The Name of the @{Task} within the @{Mission}.
-- @return Tasking.Task#TASK The Task -- @return Tasking.Task#TASK The Task
-- @return #nil Returns nil if no task was found. -- @return #nil Returns nil if no task was found.
function MISSION:GetTask( TaskName ) function MISSION:GetTask( TaskName )
self:F( { TaskName } ) self:F( { TaskName } )
return self.Tasks[TaskName] return self.Tasks[TaskName]
@@ -1003,9 +1015,28 @@ end
-- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" ) -- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" )
function MISSION:GetTasks() function MISSION:GetTasks()
return self.Tasks return self.Tasks or {}
end end
--- Get the relevant tasks of a TaskGroup.
-- @param #MISSION
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #list<Tasking.Task#TASK>
function MISSION:GetGroupTasks( TaskGroup )
local Tasks = {}
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:HasGroup( TaskGroup ) then
Tasks[#Tasks+1] = Task
end
end
return Tasks
end
--- Reports the briefing. --- Reports the briefing.
-- @param #MISSION self -- @param #MISSION self
-- @param Wrapper.Group#GROUP ReportGroup The group to which the report needs to be sent. -- @param Wrapper.Group#GROUP ReportGroup The group to which the report needs to be sent.

View File

@@ -8,7 +8,8 @@
-- --
-- === -- ===
-- --
-- @module Task -- @module Tasking.Task
-- @image MOOSE.JPG
--- @type TASK --- @type TASK
-- @field Core.Scheduler#SCHEDULER TaskScheduler -- @field Core.Scheduler#SCHEDULER TaskScheduler
@@ -21,7 +22,7 @@
-- @extends Core.Fsm#FSM_TASK -- @extends Core.Fsm#FSM_TASK
--- ---
-- # TASK class, extends @{Base#BASE} -- # TASK class, extends @{Core.Base#BASE}
-- --
-- ## The TASK class implements the methods for task orchestration within MOOSE. -- ## The TASK class implements the methods for task orchestration within MOOSE.
-- --
@@ -30,9 +31,9 @@
-- * @{#TASK.AssignToGroup}():Assign a task to a group (of players). -- * @{#TASK.AssignToGroup}():Assign a task to a group (of players).
-- * @{#TASK.AddProcess}():Add a @{Process} to a task. -- * @{#TASK.AddProcess}():Add a @{Process} to a task.
-- * @{#TASK.RemoveProcesses}():Remove a running @{Process} from a running task. -- * @{#TASK.RemoveProcesses}():Remove a running @{Process} from a running task.
-- * @{#TASK.SetStateMachine}():Set a @{Fsm} to a task. -- * @{#TASK.SetStateMachine}():Set a @{Core.Fsm} to a task.
-- * @{#TASK.RemoveStateMachine}():Remove @{Fsm} from a task. -- * @{#TASK.RemoveStateMachine}():Remove @{Core.Fsm} from a task.
-- * @{#TASK.HasStateMachine}():Enquire if the task has a @{Fsm} -- * @{#TASK.HasStateMachine}():Enquire if the task has a @{Core.Fsm}
-- * @{#TASK.AssignToUnit}(): Assign a task to a unit. (Needs to be implemented in the derived classes from @{#TASK}. -- * @{#TASK.AssignToUnit}(): Assign a task to a unit. (Needs to be implemented in the derived classes from @{#TASK}.
-- * @{#TASK.UnAssignFromUnit}(): Unassign the task from a unit. -- * @{#TASK.UnAssignFromUnit}(): Unassign the task from a unit.
-- * @{#TASK.SetTimeOut}(): Set timer in seconds before task gets cancelled if not assigned. -- * @{#TASK.SetTimeOut}(): Set timer in seconds before task gets cancelled if not assigned.
@@ -161,7 +162,7 @@ TASK = {
-- @return #TASK self -- @return #TASK self
function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing ) function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
local self = BASE:Inherit( self, FSM_TASK:New() ) -- Tasking.Task#TASK local self = BASE:Inherit( self, FSM_TASK:New( TaskName ) ) -- Tasking.Task#TASK
self:SetStartState( "Planned" ) self:SetStartState( "Planned" )
self:AddTransition( "Planned", "Assign", "Assigned" ) self:AddTransition( "Planned", "Assign", "Assigned" )
@@ -169,17 +170,24 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
self:AddTransition( "Assigned", "Success", "Success" ) self:AddTransition( "Assigned", "Success", "Success" )
self:AddTransition( "Assigned", "Hold", "Hold" ) self:AddTransition( "Assigned", "Hold", "Hold" )
self:AddTransition( "Assigned", "Fail", "Failed" ) self:AddTransition( "Assigned", "Fail", "Failed" )
self:AddTransition( "Assigned", "Abort", "Aborted" ) self:AddTransition( { "Planned", "Assigned" }, "Abort", "Aborted" )
self:AddTransition( "Assigned", "Cancel", "Cancelled" ) self:AddTransition( "Assigned", "Cancel", "Cancelled" )
self:AddTransition( "Assigned", "Goal", "*" ) self:AddTransition( "Assigned", "Goal", "*" )
self.Fsm = {}
local Fsm = self:GetUnitProcess()
Fsm:SetStartState( "Planned" )
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Assigned", Rejected = "Reject" } )
Fsm:AddTransition( "Assigned", "Assigned", "*" )
--- Goal Handler OnBefore for TASK --- Goal Handler OnBefore for TASK
-- @function [parent=#TASK] OnBeforeGoal -- @function [parent=#TASK] OnBeforeGoal
-- @param #TASK self -- @param #TASK self
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player. -- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
-- @param #string PlayerName The name of the player. -- @param #string PlayerName The name of the player.
-- @return #boolean -- @return #boolean
@@ -189,26 +197,27 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player. -- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
-- @param #string PlayerName The name of the player. -- @param #string PlayerName The name of the player.
--- Goal Trigger for TASK --- Goal Trigger for TASK
-- @function [parent=#TASK] Goal -- @function [parent=#TASK] Goal
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player. -- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
-- @param #string PlayerName The name of the player. -- @param #string PlayerName The name of the player.
--- Goal Asynchronous Trigger for TASK --- Goal Asynchronous Trigger for TASK
-- @function [parent=#TASK] __Goal -- @function [parent=#TASK] __Goal
-- @param #TASK self -- @param #TASK self
-- @param #number Delay -- @param #number Delay
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player. -- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
-- @param #string PlayerName The name of the player. -- @param #string PlayerName The name of the player.
self:AddTransition( "*", "PlayerCrashed", "*" ) self:AddTransition( "*", "PlayerCrashed", "*" )
self:AddTransition( "*", "PlayerAborted", "*" ) self:AddTransition( "*", "PlayerAborted", "*" )
self:AddTransition( "*", "PlayerRejected", "*" )
self:AddTransition( "*", "PlayerDead", "*" ) self:AddTransition( "*", "PlayerDead", "*" )
self:AddTransition( { "Failed", "Aborted", "Cancelled" }, "Replan", "Planned" ) self:AddTransition( { "Failed", "Aborted", "Cancelled" }, "Replan", "Planned" )
self:AddTransition( "*", "TimeOut", "Cancelled" ) self:AddTransition( "*", "TimeOut", "Cancelled" )
@@ -216,7 +225,6 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
self:F( "New TASK " .. TaskName ) self:F( "New TASK " .. TaskName )
self.Processes = {} self.Processes = {}
self.Fsm = {}
self.Mission = Mission self.Mission = Mission
self.CommandCenter = Mission:GetCommandCenter() self.CommandCenter = Mission:GetCommandCenter()
@@ -229,7 +237,6 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
self:SetBriefing( TaskBriefing ) self:SetBriefing( TaskBriefing )
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
self.TaskInfo = TASKINFO:New( self ) self.TaskInfo = TASKINFO:New( self )
@@ -246,7 +253,8 @@ function TASK:GetUnitProcess( TaskUnit )
if TaskUnit then if TaskUnit then
return self:GetStateMachine( TaskUnit ) return self:GetStateMachine( TaskUnit )
else else
return self.FsmTemplate self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
return self.FsmTemplate
end end
end end
@@ -295,34 +303,61 @@ function TASK:JoinUnit( PlayerUnit, PlayerGroup )
return PlayerUnitAdded return PlayerUnitAdded
end end
--- Abort a PlayerUnit from a Task. --- A group rejecting a planned 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 self -- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task. -- @param Wrapper.Group#GROUP PlayerGroup The group rejecting the task.
-- @return #TASK -- @return #TASK
function TASK:AbortGroup( PlayerGroup ) function TASK:RejectGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } )
local PlayerGroups = self:GetGroups() local PlayerGroups = self:GetGroups()
-- Is the PlayerGroup part of the PlayerGroups? -- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then if PlayerGroups:IsIncludeObject( PlayerGroup ) then
-- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task. -- Check if the PlayerGroup is already assigned or is planned to be 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 the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group.
if self:IsStateAssigned() then if self:IsStatePlanned() then
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
self:GetMission():GetCommandCenter():MessageToGroup( "Task " .. self:GetName() .. " has been rejected! We will select another task.", PlayerGroup )
self:UnAssignFromGroup( PlayerGroup )
self:PlayerRejected( PlayerGroup:GetUnit(1) )
end
end
end
return self
end
--- A group aborting the task.
-- @param #TASK self
-- @param Wrapper.Group#GROUP PlayerGroup The group aborting the task.
-- @return #TASK
function TASK:AbortGroup( PlayerGroup )
local PlayerGroups = self:GetGroups()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
-- Check if the PlayerGroup is already assigned or is planned to be 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 IsGroupAssigned = self:IsGroupAssigned( PlayerGroup ) local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:F( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName() local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
--self:MessageToGroups( PlayerName .. " aborted Task " .. self:GetName() )
self:UnAssignFromGroup( PlayerGroup ) self:UnAssignFromGroup( PlayerGroup )
--self:Abort()
-- Now check if the task needs to go to hold... -- Now check if the task needs to go to hold...
-- It will go to hold, if there are no players in the mission... -- It will go to hold, if there are no players in the mission...
PlayerGroups:Flush( self ) PlayerGroups:Flush( self )
local IsRemaining = false local IsRemaining = false
for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do
@@ -347,11 +382,10 @@ function TASK:AbortGroup( PlayerGroup )
return self return self
end end
--- A PlayerUnit crashed in a Task. Abort the Player.
-- If the Unit was not part of the Task, false is returned. --- A group crashing and thus aborting from the task.
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task. -- @param Wrapper.Group#GROUP PlayerGroup The group aborting the task.
-- @return #TASK -- @return #TASK
function TASK:CrashGroup( PlayerGroup ) function TASK:CrashGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } ) self:F( { PlayerGroup = PlayerGroup } )
@@ -413,9 +447,29 @@ end
-- @param #TASK self -- @param #TASK self
-- @return Core.Set#SET_GROUP -- @return Core.Set#SET_GROUP
function TASK:GetGroups() function TASK:GetGroups()
return self.SetGroup return self.SetGroup
end end
--- Gets the SET_GROUP assigned to the TASK.
-- @param #TASK self
-- @param Core.Set#SET_GROUP GroupSet
-- @return Core.Set#SET_GROUP
function TASK:AddGroups( GroupSet )
GroupSet = GroupSet or SET_GROUP:New()
self.SetGroup:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupSet
function( GroupItem )
GroupSet:Add( GroupItem:GetName(), GroupItem)
end
)
return GroupSet
end
do -- Group Assignment do -- Group Assignment
--- Returns if the @{Task} is assigned to the Group. --- Returns if the @{Task} is assigned to the Group.
@@ -436,7 +490,7 @@ do -- Group Assignment
end end
--- Set @{Group} assigned to the @{Task}. --- Set @{Wrapper.Group} assigned to the @{Task}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK -- @return #TASK
@@ -466,7 +520,7 @@ do -- Group Assignment
return self return self
end end
--- Clear the @{Group} assignment from the @{Task}. --- Clear the @{Wrapper.Group} assignment from the @{Task}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK -- @return #TASK
@@ -500,7 +554,17 @@ end
do -- Group Assignment do -- Group Assignment
--- Assign the @{Task} to a @{Group}. --- @param #TASK self
-- @param Actions.Act_Assign#ACT_ASSIGN AcceptClass
function TASK:SetAssignMethod( AcceptClass )
local ProcessTemplate = self:GetUnitProcess()
ProcessTemplate:SetProcess( "Planned", "Accept", AcceptClass ) -- Actions.Act_Assign#ACT_ASSIGN
end
--- Assign the @{Task} to a @{Wrapper.Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK -- @return #TASK
@@ -535,7 +599,7 @@ do -- Group Assignment
return self return self
end end
--- UnAssign the @{Task} from a @{Group}. --- UnAssign the @{Task} from a @{Wrapper.Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
function TASK:UnAssignFromGroup( TaskGroup ) function TASK:UnAssignFromGroup( TaskGroup )
@@ -570,7 +634,7 @@ function TASK:HasGroup( FindGroup )
end end
--- Assign the @{Task} to an alive @{Unit}. --- Assign the @{Task} to an alive @{Wrapper.Unit}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK self -- @return #TASK self
@@ -589,7 +653,7 @@ function TASK:AssignToUnit( TaskUnit )
return self return self
end end
--- UnAssign the @{Task} from an alive @{Unit}. --- UnAssign the @{Task} from an alive @{Wrapper.Unit}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK self -- @return #TASK self
@@ -597,7 +661,9 @@ function TASK:UnAssignFromUnit( TaskUnit )
self:F( TaskUnit:GetName() ) self:F( TaskUnit:GetName() )
self:RemoveStateMachine( TaskUnit ) self:RemoveStateMachine( TaskUnit )
-- If a Task Control Menu had been set, then this will be removed.
self:RemoveTaskControlMenu( TaskUnit )
return self return self
end end
@@ -612,7 +678,7 @@ function TASK:SetTimeOut ( Timer )
return self return self
end end
--- Send a message of the @{Task} to the assigned @{Group}s. --- Send a message of the @{Task} to the assigned @{Wrapper.Group}s.
-- @param #TASK self -- @param #TASK self
function TASK:MessageToGroups( Message ) function TASK:MessageToGroups( Message )
self:F( { Message = Message } ) self:F( { Message = Message } )
@@ -620,35 +686,40 @@ function TASK:MessageToGroups( Message )
local Mission = self:GetMission() local Mission = self:GetMission()
local CC = Mission:GetCommandCenter() local CC = Mission:GetCommandCenter()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetAliveSet() ) do for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP TaskGroup = TaskGroup -- Wrapper.Group#GROUP
CC:MessageToGroup( Message, TaskGroup, TaskGroup:GetName() ) if TaskGroup:IsAlive() == true then
end CC:MessageToGroup( Message, TaskGroup, TaskGroup:GetName() )
end
--- Send the briefng message of the @{Task} to the assigned @{Group}s.
-- @param #TASK self
function TASK:SendBriefingToAssignedGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetAliveSet() ) do
if self:IsGroupAssigned( TaskGroup ) then
TaskGroup:Message( self.TaskBriefing, 60 )
end end
end end
end end
--- UnAssign the @{Task} from the @{Group}s. --- Send the briefng message of the @{Task} to the assigned @{Wrapper.Group}s.
-- @param #TASK self
function TASK:SendBriefingToAssignedGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if TaskGroup:IsAlive() then
if self:IsGroupAssigned( TaskGroup ) then
TaskGroup:Message( self.TaskBriefing, 60 )
end
end
end
end
--- UnAssign the @{Task} from the @{Wrapper.Group}s.
-- @param #TASK self -- @param #TASK self
function TASK:UnAssignFromGroups() function TASK:UnAssignFromGroups()
self:F2() self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetAliveSet() ) do for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsGroupAssigned(TaskGroup) then if TaskGroup:IsAlive() == true then
self:UnAssignFromGroup( TaskGroup ) if self:IsGroupAssigned(TaskGroup) then
self:UnAssignFromGroup( TaskGroup )
end
end end
end end
end end
@@ -661,13 +732,15 @@ end
function TASK:HasAliveUnits() function TASK:HasAliveUnits()
self:F() self:F()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetAliveSet() ) do for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsStateAssigned() then if TaskGroup:IsAlive() == true then
if self:IsGroupAssigned( TaskGroup ) then if self:IsStateAssigned() then
for TaskUnitID, TaskUnit in pairs( TaskGroup:GetUnits() ) do if self:IsGroupAssigned( TaskGroup ) then
if TaskUnit:IsAlive() then for TaskUnitID, TaskUnit in pairs( TaskGroup:GetUnits() ) do
self:T( { HasAliveUnits = true } ) if TaskUnit:IsAlive() then
return true self:T( { HasAliveUnits = true } )
return true
end
end end
end end
end end
@@ -686,7 +759,8 @@ function TASK:SetMenu( MenuTime ) --R2.1 Mission Reports and Task Reports added.
self:F( { self:GetName(), MenuTime } ) self:F( { self:GetName(), MenuTime } )
--self.SetGroup:Flush() --self.SetGroup:Flush()
for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetAliveSet() ) do --for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetAliveSet() ) do
for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() == true and TaskGroup:GetPlayerNames() then if TaskGroup:IsAlive() == true and TaskGroup:GetPlayerNames() then
@@ -729,21 +803,14 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime )
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionName = Mission:GetName() local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter() local MissionMenu = Mission:GetMenu( TaskGroup )
local CommandCenterMenu = CommandCenter:GetMenu()
local TaskType = self:GetType() local TaskType = self:GetType()
local TaskPlayerCount = self:GetPlayerCount() local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount ) local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
-- local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskText = string.format( "%s", self:GetName() ) local TaskText = string.format( "%s", self:GetName() )
local TaskName = string.format( "%s", self:GetName() ) local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = Mission:GetMenu( TaskGroup )
--local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
--local MissionMenu = Mission:GetMenu( TaskGroup )
self.MenuPlanned = self.MenuPlanned or {} self.MenuPlanned = self.MenuPlanned or {}
self.MenuPlanned[TaskGroup] = MENU_GROUP_DELAYED:New( TaskGroup, "Join Planned Task", MissionMenu, Mission.MenuReportTasksPerStatus, Mission, TaskGroup, "Planned" ):SetTime( MenuTime ):SetTag( "Tasking" ) self.MenuPlanned[TaskGroup] = MENU_GROUP_DELAYED:New( TaskGroup, "Join Planned Task", MissionMenu, Mission.MenuReportTasksPerStatus, Mission, TaskGroup, "Planned" ):SetTime( MenuTime ):SetTag( "Tasking" )
local TaskTypeMenu = MENU_GROUP_DELAYED:New( TaskGroup, TaskType, self.MenuPlanned[TaskGroup] ):SetTime( MenuTime ):SetTag( "Tasking" ) local TaskTypeMenu = MENU_GROUP_DELAYED:New( TaskGroup, TaskType, self.MenuPlanned[TaskGroup] ):SetTime( MenuTime ):SetTag( "Tasking" )
@@ -768,26 +835,24 @@ end
function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime ) function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime )
self:F( { TaskGroup:GetName(), MenuTime } ) self:F( { TaskGroup:GetName(), MenuTime } )
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local TaskType = self:GetType() local TaskType = self:GetType()
local TaskPlayerCount = self:GetPlayerCount() local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount ) local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString ) local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskName = string.format( "%s", self:GetName() ) local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = Mission:GetMenu( TaskGroup ) for UnitName, TaskUnit in pairs( TaskGroup:GetPlayerUnits() ) do
-- local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime ) local TaskUnit = TaskUnit -- Wrapper.Unit#UNIT
-- local MissionMenu = Mission:GetMenu( TaskGroup ) if TaskUnit then
local MenuControl = self:GetTaskControlMenu( TaskUnit )
self.MenuAssigned = self.MenuAssigned or {} local TaskControl = MENU_GROUP:New( TaskGroup, "Control Task", MenuControl ):SetTime( MenuTime ):SetTag( "Tasking" )
self.MenuAssigned[TaskGroup] = MENU_GROUP_DELAYED:New( TaskGroup, string.format( "Assigned Task %s", TaskName ), MissionMenu ):SetTime( MenuTime ):SetTag( "Tasking" ) if self:IsStateAssigned() then
local TaskMenu = MENU_GROUP_COMMAND_DELAYED:New( TaskGroup, string.format( "Abort Task" ), self.MenuAssigned[TaskGroup], self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" ) local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Abort Task" ), TaskControl, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" )
local MarkMenu = MENU_GROUP_COMMAND_DELAYED:New( TaskGroup, string.format( "Mark Task Location on Map" ), self.MenuAssigned[TaskGroup], self.MenuMarkToGroup, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" ) end
local TaskTypeMenu = MENU_GROUP_COMMAND_DELAYED:New( TaskGroup, string.format( "Report Task Details" ), self.MenuAssigned[TaskGroup], self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" ) local MarkMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Mark Task Location on Map" ), TaskControl, self.MenuMarkToGroup, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Details" ), TaskControl, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetTag( "Tasking" )
end
end
return self return self
end end
@@ -799,16 +864,18 @@ end
function TASK:RemoveMenu( MenuTime ) function TASK:RemoveMenu( MenuTime )
self:F( { self:GetName(), MenuTime } ) self:F( { self:GetName(), MenuTime } )
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetAliveSet() ) do for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP if TaskGroup:IsAlive() == true then
if TaskGroup:IsAlive() == true and TaskGroup:GetPlayerNames() then local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
self:RefreshMenus( TaskGroup, MenuTime ) if TaskGroup:IsAlive() == true and TaskGroup:GetPlayerNames() then
self:RefreshMenus( TaskGroup, MenuTime )
end
end end
end end
end end
--- Remove the menu option of the @{Task} for a @{Group}. --- Remove the menu option of the @{Task} for a @{Wrapper.Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime -- @param #number MenuTime
@@ -818,9 +885,6 @@ function TASK:RefreshMenus( TaskGroup, MenuTime )
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionName = Mission:GetName() local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionMenu = Mission:GetMenu( TaskGroup ) local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskName = self:GetName() local TaskName = self:GetName()
@@ -842,7 +906,7 @@ function TASK:RefreshMenus( TaskGroup, MenuTime )
end end
--- Remove the assigned menu option of the @{Task} for a @{Group}. --- Remove the assigned menu option of the @{Task} for a @{Wrapper.Group}.
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup -- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime -- @param #number MenuTime
@@ -852,7 +916,6 @@ function TASK:RemoveAssignedMenuForGroup( TaskGroup )
local Mission = self:GetMission() local Mission = self:GetMission()
local MissionName = Mission:GetName() local MissionName = Mission:GetName()
local MissionMenu = Mission:GetMenu( TaskGroup ) local MissionMenu = Mission:GetMenu( TaskGroup )
if MissionMenu then if MissionMenu then
@@ -939,7 +1002,7 @@ end
-- TODO: Obscolete? -- TODO: Obscolete?
--- Fail processes from @{Task} with key @{Unit} --- Fail processes from @{Task} with key @{Wrapper.Unit}
-- @param #TASK self -- @param #TASK self
-- @param #string TaskUnitName -- @param #string TaskUnitName
-- @return #TASK self -- @return #TASK self
@@ -951,7 +1014,7 @@ function TASK:FailProcesses( TaskUnitName )
end end
end end
--- Add a FiniteStateMachine to @{Task} with key Task@{Unit} --- Add a FiniteStateMachine to @{Task} with key Task@{Wrapper.Unit}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @param Core.Fsm#FSM_PROCESS Fsm -- @param Core.Fsm#FSM_PROCESS Fsm
@@ -964,7 +1027,7 @@ function TASK:SetStateMachine( TaskUnit, Fsm )
return Fsm return Fsm
end end
--- Gets the FiniteStateMachine of @{Task} with key Task@{Unit} --- Gets the FiniteStateMachine of @{Task} with key Task@{Wrapper.Unit}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Fsm#FSM_PROCESS -- @return Core.Fsm#FSM_PROCESS
@@ -974,7 +1037,7 @@ function TASK:GetStateMachine( TaskUnit )
return self.Fsm[TaskUnit] return self.Fsm[TaskUnit]
end end
--- Remove FiniteStateMachines from @{Task} with key Task@{Unit} --- Remove FiniteStateMachines from @{Task} with key Task@{Wrapper.Unit}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK self -- @return #TASK self
@@ -998,7 +1061,7 @@ function TASK:RemoveStateMachine( TaskUnit )
end end
--- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task} --- Checks if there is a FiniteStateMachine assigned to Task@{Wrapper.Unit} for @{Task}
-- @param #TASK self -- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK self -- @return #TASK self
@@ -1210,12 +1273,16 @@ function TASK:onenterAssigned( From, Event, To, PlayerUnit, PlayerName )
--- This test is required, because the state transition will be fired also when the state does not change in case of an event. --- This test is required, because the state transition will be fired also when the state does not change in case of an event.
if From ~= "Assigned" then if From ~= "Assigned" then
self:F( { From, Event, To, PlayerUnit:GetName(), PlayerName } )
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is assigned." ) local PlayerNames = self:GetPlayerNames()
local PlayerText = REPORT:New()
for PlayerName, TaskName in pairs( PlayerNames ) do
PlayerText:Add( PlayerName )
end
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is assigned to players " .. PlayerText:Text(",") .. ". Good Luck!" )
-- Set the total Progress to be achieved. -- Set the total Progress to be achieved.
self:SetGoalTotal() -- Polymorphic to set the initial goal total! self:SetGoalTotal() -- Polymorphic to set the initial goal total!
if self.Dispatcher then if self.Dispatcher then
@@ -1231,7 +1298,7 @@ function TASK:onenterAssigned( From, Event, To, PlayerUnit, PlayerName )
self:SetMenu() self:SetMenu()
self:F( { "--> Task Assigned", TaskName = self:GetName(), Mission = self:GetMission():GetName() } ) self:F( { "--> Task Assigned", TaskName = self:GetName(), Mission = self:GetMission():GetName() } )
self:F( { "--> Task Player Names", PlayerNames = self:GetPlayerNames() } ) self:F( { "--> Task Player Names", PlayerNames = PlayerNames } )
end end
end end
@@ -1273,6 +1340,7 @@ function TASK:onenterAborted( From, Event, To )
end end
--- FSM function for a TASK --- FSM function for a TASK
-- @param #TASK self -- @param #TASK self
-- @param #string From -- @param #string From
@@ -1441,11 +1509,13 @@ function TASK:GetPlayerCount() --R2.1 Get a count of the players.
local PlayerCount = 0 local PlayerCount = 0
-- Loop each Unit active in the Task, and find Player Names. -- Loop each Unit active in the Task, and find Player Names.
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetAliveSet() ) do for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then if PlayerGroup:IsAlive() == true then
local PlayerNames = PlayerGroup:GetPlayerNames() if self:IsGroupAssigned( PlayerGroup ) then
PlayerCount = PlayerCount + #PlayerNames local PlayerNames = PlayerGroup:GetPlayerNames()
PlayerCount = PlayerCount + #PlayerNames
end
end end
end end
@@ -1461,12 +1531,14 @@ function TASK:GetPlayerNames() --R2.1 Get a map of the players.
local PlayerNameMap = {} local PlayerNameMap = {}
-- Loop each Unit active in the Task, and find Player Names. -- Loop each Unit active in the Task, and find Player Names.
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetAliveSet() ) do for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then if PlayerGroup:IsAlive() == true then
local PlayerNames = PlayerGroup:GetPlayerNames() if self:IsGroupAssigned( PlayerGroup ) then
for PlayerNameID, PlayerName in pairs( PlayerNames ) do local PlayerNames = PlayerGroup:GetPlayerNames()
PlayerNameMap[PlayerName] = PlayerGroup for PlayerNameID, PlayerName in pairs( PlayerNames ) do
PlayerNameMap[PlayerName] = PlayerGroup
end
end end
end end
end end
@@ -1499,7 +1571,7 @@ function TASK:ReportDetails( ReportGroup )
local PlayerReport = REPORT:New() local PlayerReport = REPORT:New()
for PlayerName, PlayerGroup in pairs( PlayerNames ) do for PlayerName, PlayerGroup in pairs( PlayerNames ) do
PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. PlayerName ) PlayerReport:Add( "Players group " .. PlayerGroup:GetCallsign() .. ": " .. PlayerName )
end end
local Players = PlayerReport:Text() local Players = PlayerReport:Text()
@@ -1595,3 +1667,65 @@ do -- Additional Task Scoring and Task Progress
end end
end end
do -- Task Control Menu
-- The Task Control Menu is a menu attached to the task at the main menu to quickly be able to do actions in the task.
-- The Task Control Menu can only be shown when the task is assigned to the player.
-- The Task Control Menu is linked to the process executing the task, so no task menu can be set to the main static task definition.
--- Init Task Control Menu
-- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
-- @return Task Control Menu Refresh ID
function TASK:InitTaskControlMenu( TaskUnit )
self.TaskControlMenuTime = timer.getTime()
return self.TaskControlMenuTime
end
--- Get Task Control Menu
-- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
-- @return Core.Menu#MENU_GROUP TaskControlMenu The Task Control Menu
function TASK:GetTaskControlMenu( TaskUnit, TaskName )
TaskName = TaskName or ""
local TaskGroup = TaskUnit:GetGroup()
local TaskPlayerCount = TaskGroup:GetPlayerCount()
if TaskPlayerCount <= 1 then
self.TaskControlMenu = MENU_GROUP:New( TaskUnit:GetGroup(), "Task " .. self:GetName() .. " control" ):SetTime( self.TaskControlMenuTime )
else
self.TaskControlMenu = MENU_GROUP:New( TaskUnit:GetGroup(), "Task " .. self:GetName() .. " control for " .. TaskUnit:GetPlayerName() ):SetTime( self.TaskControlMenuTime )
end
return self.TaskControlMenu
end
--- Remove Task Control Menu
-- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
function TASK:RemoveTaskControlMenu( TaskUnit )
if self.TaskControlMenu then
self.TaskControlMenu:Remove()
self.TaskControlMenu = nil
end
end
--- Refresh Task Control Menu
-- @param #TASK self
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
-- @param MenuTime The refresh time that was used to refresh the Task Control Menu items.
-- @param MenuTag The tag.
function TASK:RefreshTaskControlMenu( TaskUnit, MenuTime, MenuTag )
if self.TaskControlMenu then
self.TaskControlMenu:Remove( MenuTime, MenuTag )
end
end
end

View File

@@ -8,13 +8,14 @@
-- --
-- === -- ===
-- --
-- @module TaskInfo -- @module Tasking.TaskInfo
-- @image MOOSE.JPG
--- @type TASKINFO --- @type TASKINFO
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- ---
-- # TASKINFO class, extends @{Base#BASE} -- # TASKINFO class, extends @{Core.Base#BASE}
-- --
-- ## The TASKINFO class implements the methods to contain information and display information of a task. -- ## The TASKINFO class implements the methods to contain information and display information of a task.
-- --
@@ -249,17 +250,15 @@ end
function TASKINFO:AddCargoSet( SetCargo, Order, Detail, Keep ) function TASKINFO:AddCargoSet( SetCargo, Order, Detail, Keep )
local CargoReport = REPORT:New() local CargoReport = REPORT:New()
CargoReport:Add( "" )
SetCargo:ForEachCargo( SetCargo:ForEachCargo(
--- @param Core.Cargo#CARGO Cargo --- @param Cargo.Cargo#CARGO Cargo
function( Cargo ) function( Cargo )
local CargoType = Cargo:GetType() CargoReport:Add( string.format( ' - %s (%s) %s - status %s ', Cargo:GetName(), Cargo:GetType(), Cargo:GetTransportationMethod(), Cargo:GetCurrentState() ) )
local CargoName = Cargo:GetName()
local CargoCoordinate = Cargo:GetCoordinate()
CargoReport:Add( string.format( '"%s" (%s) at %s', CargoName, CargoType, CargoCoordinate:ToStringMGRS() ) )
end end
) )
self:AddInfo( "CargoSet", CargoReport:Text(), Order, Detail, Keep ) self:AddInfo( "Cargo", CargoReport:Text(), Order, Detail, Keep )
return self return self
end end
@@ -319,7 +318,7 @@ function TASKINFO:Report( Report, Detail, ReportGroup )
local Coordinate = Data.Data -- Core.Point#COORDINATE local Coordinate = Data.Data -- Core.Point#COORDINATE
Text = Coordinate:ToStringWind( ReportGroup:GetUnit(1), nil, self ) Text = Coordinate:ToStringWind( ReportGroup:GetUnit(1), nil, self )
end end
if Key == "CargoSet" then if Key == "Cargo" then
local DataText = Data.Data -- #string local DataText = Data.Data -- #string
Text = DataText Text = DataText
end end

View File

@@ -8,7 +8,8 @@
-- --
-- === -- ===
-- --
-- @module TaskZoneCapture -- @module Tasking.TaskZoneCapture
-- @image MOOSE.JPG
do -- TASK_ZONE_GOAL do -- TASK_ZONE_GOAL
@@ -17,14 +18,14 @@ do -- TASK_ZONE_GOAL
-- @field Core.ZoneGoal#ZONE_GOAL ZoneGoal -- @field Core.ZoneGoal#ZONE_GOAL ZoneGoal
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
--- # TASK_ZONE_GOAL class, extends @{Task#TASK} --- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK}
-- --
-- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone. -- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone.
-- The TASK_ZONE_GOAL is implemented using a @{Fsm#FSM_TASK}, and has the following statuses: -- The TASK_ZONE_GOAL is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
-- --
-- * **None**: Start of the process -- * **None**: Start of the process
-- * **Planned**: The A2G task is planned. -- * **Planned**: The A2G task is planned.
-- * **Assigned**: The A2G task is assigned to a @{Group#GROUP}. -- * **Assigned**: The A2G task is assigned to a @{Wrapper.Group#GROUP}.
-- * **Success**: The A2G task is successfully completed. -- * **Success**: The A2G task is successfully completed.
-- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. -- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
-- --
@@ -44,7 +45,7 @@ do -- TASK_ZONE_GOAL
--- Instantiates a new TASK_ZONE_GOAL. --- Instantiates a new TASK_ZONE_GOAL.
-- @param #TASK_ZONE_GOAL self -- @param #TASK_ZONE_GOAL self
-- @param Tasking.Mission#MISSION Mission -- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task. -- @param #string TaskName The name of the Task.
-- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal -- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal
-- @return #TASK_ZONE_GOAL self -- @return #TASK_ZONE_GOAL self
@@ -166,12 +167,12 @@ do -- TASK_ZONE_CAPTURE
-- @field Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal -- @field Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal
-- @extends #TASK_ZONE_GOAL -- @extends #TASK_ZONE_GOAL
--- # TASK_ZONE_CAPTURE class, extends @{TaskZoneGoal#TASK_ZONE_GOAL} --- # TASK_ZONE_CAPTURE class, extends @{Tasking.TaskZoneGoal#TASK_ZONE_GOAL}
-- --
-- The TASK_ZONE_CAPTURE class defines an Suppression or Extermination of Air Defenses task for a human player to be executed. -- The TASK_ZONE_CAPTURE class defines an Suppression or Extermination of Air Defenses task for a human player to be executed.
-- These tasks are important to be executed as they will help to achieve air superiority at the vicinity. -- These tasks are important to be executed as they will help to achieve air superiority at the vicinity.
-- --
-- The TASK_ZONE_CAPTURE is used by the @{Task_A2G_Dispatcher#TASK_A2G_DISPATCHER} to automatically create SEAD tasks -- The TASK_ZONE_CAPTURE is used by the @{Tasking.Task_A2G_Dispatcher#TASK_A2G_DISPATCHER} to automatically create SEAD tasks
-- based on detected enemy ground targets. -- based on detected enemy ground targets.
-- --
-- @field #TASK_ZONE_CAPTURE -- @field #TASK_ZONE_CAPTURE

View File

@@ -8,24 +8,23 @@
-- --
-- === -- ===
-- --
-- @module Task_A2A -- @module Tasking.Tasking.Task_A2A
-- @image MOOSE.JPG
do -- TASK_A2A do -- TASK_A2A
--- The TASK_A2A class --- The TASK_A2A class
-- @type TASK_A2A -- @type TASK_A2A
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
--- # TASK_A2A class, extends @{Task#TASK} --- Defines Air To Air tasks for a @{Set} of Target Units,
-- -- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
-- The TASK_A2A class defines Air To Air tasks for a @{Set} of Target Units, -- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
-- based on the tasking capabilities defined in @{Task#TASK}.
-- The TASK_A2A is implemented using a @{Fsm#FSM_TASK}, and has the following statuses:
-- --
-- * **None**: Start of the process -- * **None**: Start of the process
-- * **Planned**: The A2A task is planned. -- * **Planned**: The A2A task is planned.
-- * **Assigned**: The A2A task is assigned to a @{Group#GROUP}. -- * **Assigned**: The A2A task is assigned to a @{Wrapper.Group#GROUP}.
-- * **Success**: The A2A task is successfully completed. -- * **Success**: The A2A task is successfully completed.
-- * **Failed**: The A2A task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. -- * **Failed**: The A2A task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
-- --
@@ -45,9 +44,9 @@ do -- TASK_A2A
--- Instantiates a new TASK_A2A. --- Instantiates a new TASK_A2A.
-- @param #TASK_A2A self -- @param #TASK_A2A self
-- @param Tasking.Mission#MISSION Mission -- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetAttack The set of groups for which the Task can be assigned. -- @param Core.Set#SET_GROUP SetAttack The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task. -- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets -- @param Core.Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range. -- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known. -- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be. -- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
@@ -62,8 +61,6 @@ do -- TASK_A2A
local Fsm = self:GetUnitProcess() local Fsm = self:GetUnitProcess()
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "RouteToRendezVous", Rejected = "Reject" } )
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" ) Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } ) Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } ) Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
@@ -84,6 +81,15 @@ do -- TASK_A2A
Fsm:AddTransition( "Rejected", "Reject", "Aborted" ) Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Failed", "Fail", "Failed" ) Fsm:AddTransition( "Failed", "Fail", "Failed" )
---- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param #TASK_CARGO Task
function Fsm:OnLeaveAssigned( TaskUnit, Task )
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self:SelectAction()
end
--- Test --- Test
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
@@ -352,18 +358,16 @@ do -- TASK_A2A_INTERCEPT
--- The TASK_A2A_INTERCEPT class --- The TASK_A2A_INTERCEPT class
-- @type TASK_A2A_INTERCEPT -- @type TASK_A2A_INTERCEPT
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
--- # TASK_A2A_INTERCEPT class, extends @{Task_A2A#TASK_A2A} --- Defines an intercept task for a human player to be executed.
--
-- The TASK_A2A_INTERCEPT class defines an intercept task for a human player to be executed.
-- When enemy planes need to be intercepted by human players, use this task type to urgen the players to get out there! -- When enemy planes need to be intercepted by human players, use this task type to urgen the players to get out there!
-- --
-- The TASK_A2A_INTERCEPT is used by the @{Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create intercept tasks -- The TASK_A2A_INTERCEPT is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create intercept tasks
-- based on detected airborne enemy targets intruding friendly airspace. -- based on detected airborne enemy targets intruding friendly airspace.
-- --
-- The task is defined for a @{Mission#MISSION}, where a friendly @{Set#SET_GROUP} consisting of GROUPs with one human players each, is intercepting the targets. -- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is intercepting the targets.
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting. -- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
-- --
-- @field #TASK_A2A_INTERCEPT -- @field #TASK_A2A_INTERCEPT
@@ -451,20 +455,18 @@ do -- TASK_A2A_SWEEP
--- The TASK_A2A_SWEEP class --- The TASK_A2A_SWEEP class
-- @type TASK_A2A_SWEEP -- @type TASK_A2A_SWEEP
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
--- # TASK_A2A_SWEEP class, extends @{Task_A2A#TASK_A2A} --- Defines a sweep task for a human player to be executed.
--
-- The TASK_A2A_SWEEP class defines a sweep task for a human player to be executed.
-- A sweep task needs to be given when targets were detected but somehow the detection was lost. -- A sweep task needs to be given when targets were detected but somehow the detection was lost.
-- Most likely, these enemy planes are hidden in the mountains or are flying under radar. -- Most likely, these enemy planes are hidden in the mountains or are flying under radar.
-- These enemy planes need to be sweeped by human players, and use this task type to urge the players to get out there and find those enemy fighters. -- These enemy planes need to be sweeped by human players, and use this task type to urge the players to get out there and find those enemy fighters.
-- --
-- The TASK_A2A_SWEEP is used by the @{Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create sweep tasks -- The TASK_A2A_SWEEP is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create sweep tasks
-- based on detected airborne enemy targets intruding friendly airspace, for which the detection has been lost for more than 60 seconds. -- based on detected airborne enemy targets intruding friendly airspace, for which the detection has been lost for more than 60 seconds.
-- --
-- The task is defined for a @{Mission#MISSION}, where a friendly @{Set#SET_GROUP} consisting of GROUPs with one human players each, is sweeping the targets. -- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is sweeping the targets.
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting. -- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
-- --
-- @field #TASK_A2A_SWEEP -- @field #TASK_A2A_SWEEP
@@ -562,18 +564,16 @@ do -- TASK_A2A_ENGAGE
--- The TASK_A2A_ENGAGE class --- The TASK_A2A_ENGAGE class
-- @type TASK_A2A_ENGAGE -- @type TASK_A2A_ENGAGE
-- @field Set#SET_UNIT TargetSetUnit -- @field Core.Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK -- @extends Tasking.Task#TASK
--- # TASK_A2A_ENGAGE class, extends @{Task_A2A#TASK_A2A} --- Defines an engage task for a human player to be executed.
--
-- The TASK_A2A_ENGAGE class defines an engage task for a human player to be executed.
-- When enemy planes are close to human players, use this task type is used urge the players to get out there! -- When enemy planes are close to human players, use this task type is used urge the players to get out there!
-- --
-- The TASK_A2A_ENGAGE is used by the @{Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create engage tasks -- The TASK_A2A_ENGAGE is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create engage tasks
-- based on detected airborne enemy targets intruding friendly airspace. -- based on detected airborne enemy targets intruding friendly airspace.
-- --
-- The task is defined for a @{Mission#MISSION}, where a friendly @{Set#SET_GROUP} consisting of GROUPs with one human players each, is engaging the targets. -- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is engaging the targets.
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting. -- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
-- --
-- @field #TASK_A2A_ENGAGE -- @field #TASK_A2A_ENGAGE

Some files were not shown because too many files have changed in this diff Show More