Merge branch 'master' into beacons

This commit is contained in:
Grey-Echo
2017-04-20 12:52:09 +02:00
83 changed files with 1849 additions and 41 deletions

View File

@@ -0,0 +1,259 @@
--- **AI (Release 2.1)** -- Management of target designation.
--
-- --![Banner Image](..\Presentations\AI_DESIGNATE\CARGO.JPG)
--
-- ===
--
-- @module AI_Designate
do -- AI_DESIGNATE
--- @type AI_DESIGNATE
-- @extends Core.Fsm#FSM_PROCESS
--- # AI_DESIGNATE class, extends @{Fsm#FSM}
--
-- AI_DESIGNATE is orchestrating the designation of potential targets, and communicate these to a dedicated attacking group
-- of players, so that following a dynamically generated menu system, each detected set of potential targets can be lased or smoked...
--
-- ## 1. AI_DESIGNATE constructor
--
-- * @{#AI_DESIGNATE.New}(): Creates a new AI_DESIGNATE object.
--
-- ## 2. AI_DESIGNATE is a FSM
--
-- ![Process](µ)
--
-- ### 2.1 AI_DESIGNATE States
--
-- * **Designating** ( Group ): The process is not started yet.
--
-- ### 2.2 AI_DESIGNATE Events
--
-- * **@{#AI_DESIGNATE.Detect}**: Detect targets.
-- * **@{#AI_DESIGNATE.LaseOn}**: Lase the targets with the specified Index.
-- * **@{#AI_DESIGNATE.LaseOff}**: Stop lasing the targets with the specified Index.
-- * **@{#AI_DESIGNATE.Smoke}**: Smoke the targets with the specified Index.
-- * **@{#AI_DESIGNATE.}Status**: Report designation status.
--
-- @field #AI_DESIGNATE
--
AI_DESIGNATE = {
ClassName = "AI_DESIGNATE",
}
--- AI_DESIGNATE Constructor. This class is an abstract class and should not be instantiated.
-- @param #AI_DESIGNATE self
-- @param Functional.Detection#DETECTION_BASE Detection
-- @param Core.Set#SET_GROUP GroupSet The set of groups to designate for.
-- @return #AI_DESIGNATE
function AI_DESIGNATE:New( Detection, GroupSet )
local self = BASE:Inherit( self, FSM:New() ) -- #AI_DESIGNATE
self:F( { Detection } )
self:SetStartState( "Designating" )
self:AddTransition( "*", "Detect", "*" )
self:AddTransition( "*", "LaseOn", "*" )
self:AddTransition( "*", "LaseOff", "*" )
self:AddTransition( "*", "Smoke", "*" )
self:AddTransition( "*", "Status", "*" )
self.Detection = Detection
self.GroupSet = GroupSet
self.RecceSet = Detection:GetDetectionSetGroup()
self.Spots = {}
self.Detection:__Start( 2 )
return self
end
---
-- @param #AI_DESIGNATE self
-- @return #AI_DESIGNATE
function AI_DESIGNATE:onafterDetect()
self:__Detect( -60 )
self.GroupSet:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupReport
function( GroupReport )
self:E(GroupReport:GetName())
local DesignateMenu = GroupReport:GetState( GroupReport, "DesignateMenu" ) -- Core.Menu#MENU_GROUP
if DesignateMenu then
DesignateMenu:Remove()
DesignateMenu = nil
self:E("Remove Menu")
end
DesignateMenu = MENU_GROUP:New( GroupReport, "Designate Targets" )
self:E(DesignateMenu)
GroupReport:SetState( GroupReport, "DesignateMenu", DesignateMenu )
local DetectedItems = self.Detection:GetDetectedItems()
for Index, DetectedItemData in pairs( DetectedItems ) do
local DetectedReport = self.Detection:DetectedItemReportSummary( Index )
GroupReport:MessageToAll( DetectedReport, 15, "Detected" )
local DetectedMenu = MENU_GROUP:New(
GroupReport,
DetectedReport,
DesignateMenu
)
if self.Spots[Index] then
MENU_GROUP_COMMAND:New(
GroupReport,
"Switch laser Off",
DetectedMenu,
self.MenuLaseOff,
self,
Index
)
else
MENU_GROUP_COMMAND:New(
GroupReport,
"Lase target 60 secs",
DetectedMenu,
self.MenuLaseOn,
self,
Index,
60
)
MENU_GROUP_COMMAND:New(
GroupReport,
"Lase target 120 secs",
DetectedMenu,
self.MenuLaseOn,
self,
Index,
120
)
end
MENU_GROUP_COMMAND:New(
GroupReport,
"Smoke",
DetectedMenu,
self.MenuSmoke,
self,
Index
)
end
end
)
return self
end
---
-- @param #AI_DESIGNATE self
function AI_DESIGNATE:MenuSmoke( Index )
self:E("Designate through Smoke")
self:__Smoke( 1, Index )
end
---
-- @param #AI_DESIGNATE self
function AI_DESIGNATE:MenuLaseOn( Index, Duration )
self:E("Designate through Lase")
self:__LaseOn( 1, Index, Duration )
end
---
-- @param #AI_DESIGNATE self
function AI_DESIGNATE:MenuLaseOff( Index, Duration )
self:E("Lasing off")
self:__LaseOff( 1, Index )
end
---
-- @param #AI_DESIGNATE self
-- @return #AI_DESIGNATE
function AI_DESIGNATE:onafterLaseOn( From, Event, To, Index, Duration )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
TargetSetUnit:ForEachUnit(
--- @param Wrapper.Unit#UNIT SmokeUnit
function( SmokeUnit )
self:E("In procedure")
--if math.random( 1, ( 100 * TargetSetUnit:Count() ) / 100 ) <= 100 then
if SmokeUnit:IsAlive() then
local NearestRecceGroup = self.RecceSet:FindNearestGroupFromPointVec2(SmokeUnit:GetPointVec2())
if NearestRecceGroup then
for UnitID, UnitData in pairs( NearestRecceGroup:GetUnits() or {} ) do
local RecceUnit = UnitData -- Wrapper.Unit#UNIT
if RecceUnit:IsLasing() == false then
self.Spots[Index] = RecceUnit:LaseUnit( SmokeUnit, nil, Duration )
break
end
end
end
end
--end
end
)
end
---
-- @param #AI_DESIGNATE self
-- @return #AI_DESIGNATE
function AI_DESIGNATE:onafterLaseOff( From, Event, To, Index )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
self.Spots[Index]:LaseOff()
self.Spots[Index] = nil
end
---
-- @param #AI_DESIGNATE self
-- @return #AI_DESIGNATE
function AI_DESIGNATE:onafterSmoke( From, Event, To, Index )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
TargetSetUnit:ForEachUnit(
--- @param Wrapper.Unit#UNIT SmokeUnit
function( SmokeUnit )
self:E("In procedure")
--if math.random( 1, ( 100 * TargetSetUnit:Count() ) / 100 ) <= 100 then
SCHEDULER:New( self,
function()
if SmokeUnit:IsAlive() then
SmokeUnit:Smoke( SMOKECOLOR.Red, 150 )
end
end, {}, math.random( 10, 60 )
)
--end
end
)
end
end

View File

@@ -736,6 +736,31 @@ function SET_GROUP:FindGroup( GroupName )
return GroupFound
end
--- Iterate the SET_GROUP while identifying the nearest object from a @{Point#POINT_VEC2}.
-- @param #SET_GROUP self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @return Wrapper.Group#GROUP The closest group.
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 )
self:F2( PointVec2 )
local NearestGroup = nil
local ClosestDistance = nil
for ObjectID, ObjectData in pairs( self.Set ) do
if NearestGroup == nil then
NearestGroup = ObjectData
ClosestDistance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
else
local Distance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
if Distance < ClosestDistance then
NearestGroup = ObjectData
ClosestDistance = Distance
end
end
end
return NearestGroup
end
--- Builds a set of groups of coalitions.

View File

@@ -0,0 +1,118 @@
--- **Core (Release 2.1)** -- Management of SPOT logistics, that can be transported from and to transportation carriers.
--
-- ![Banner Image](..\Presentations\SPOT\Dia1.JPG)
--
-- ===
--
-- Spot lases points endlessly or for a duration.
--
-- ====
--
-- # Demo Missions
--
-- ### [SPOT Demo Missions source code]()
--
-- ### [SPOT Demo Missions, only for beta testers]()
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [SPOT YouTube Channel]()
--
-- ====
--
-- This module is still under construction, but is described above works already, and will keep working ...
--
-- @module Spot
do
--- @type SPOT
SPOT = {
ClassName = "SPOT",
}
--- SPOT Constructor.
-- @param #SPOT self
-- @param Wrapper.Unit#UNIT Recce
-- @param #number LaserCode
-- @param #number Duration
-- @return #SPOT
function SPOT:New( Recce )
local self = BASE:Inherit( self, FSM:New() ) -- #SPOT
self:F( { Type, Name, Weight } )
self:SetStartState( "Off" )
self:AddTransition( "Off", "LaseOn", "On" )
self:AddTransition( "On" , "LaseOff", "Off" )
self.Recce = Recce
self.LaseScheduler = SCHEDULER:New( self )
self:SetEventPriority( 5 )
return self
end
--- @param #SPOT self
-- @param From
-- @param Event
-- @param To
-- @param Core.Point#POINT_VEC3 PointVec3
-- @param #number LaserCode
-- @param #number Duration
-- @return #SPOT
function SPOT:onafterLaseOn( From, Event, To, PointVec3, LaserCode, Duration )
local function StopLase( self )
self:LaseOff()
end
local RecceDcsUnit = self.Recce:GetDCSObject()
local TargetVec3 = PointVec3:GetVec3()
self:E("lasing")
self.Spot = Spot.createInfraRed( RecceDcsUnit, { x = 0, y = 2, z = 0 }, TargetVec3, LaserCode )
if Duration then
self.ScheduleID = self.LaseScheduler:Schedule( self, StopLase, {self}, Duration )
end
end
--- @param #SPOT self
-- @param From
-- @param Event
-- @param To
-- @return #SPOT
function SPOT:onafterLaseOff( From, Event, To )
self.Spot:destroy()
self.Spot = nil
if self.ScheduleID then
self.LaseScheduler:Stop(self.ScheduleID)
end
self.ScheduleID = nil
return self
end
--- Check if the SPOT is lasing
-- @param #SPOT self
-- @return #boolean true if it is lasing
function SPOT:IsLasing()
self:F2()
local Lasing = false
if self.Spot then
Lasing = true
end
return Lasing
end
end

View File

@@ -309,12 +309,12 @@ do -- DETECTION_BASE
self.DetectionInterval = 30
self:InitDetectVisual( true )
self:InitDetectOptical( true )
self:InitDetectRadar( true )
self:InitDetectRWR( true )
self:InitDetectIRST( true )
self:InitDetectDLINK( true )
self:InitDetectVisual( false )
self:InitDetectOptical( false )
self:InitDetectRadar( false )
self:InitDetectRWR( false )
self:InitDetectIRST( false )
self:InitDetectDLINK( false )
self:FilterCategories( {
Unit.Category.AIRPLANE,
@@ -1250,7 +1250,7 @@ do -- DETECTION_BASE
--- Get the detection Groups.
-- @param #DETECTION_BASE self
-- @return Wrapper.Group#GROUP
-- @return Core.Set#SET_GROUP
function DETECTION_BASE:GetDetectionSetGroup()
local DetectionSetGroup = self.DetectionSetGroup

View File

@@ -1774,6 +1774,7 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad
local DetectionRWR = ( DetectRWR and DetectRWR == true ) and Controller.Detection.RWR or nil
local DetectionDLINK = ( DetectDLINK and DetectDLINK == true ) and Controller.Detection.DLINK or nil
self:T( { DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK } )
return self:_GetController():getDetectedTargets( DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK )
end

View File

@@ -457,4 +457,58 @@ end
function POSITIONABLE:GetBeacon()
self:F2(self)
return BEACON:New(self)
--- Start Lasing a POSITIONABLE
-- @param #POSITIONABLE self
-- @param #POSITIONABLE Target
-- @param #number LaserCode
-- @param #number Duration
-- @return Spot
function POSITIONABLE:LaseUnit( Target, LaserCode, Duration )
self:F2()
LaserCode = LaserCode or math.random( 1000, 9999 )
local RecceDcsUnit = self:GetDCSObject()
local TargetVec3 = Target:GetVec3()
self:E("bulding spot")
self.Spot = SPOT:New( self )
self.Spot:LaseOn( Target:GetPointVec3(), LaserCode, Duration)
return self.Spot
end
--- Stop Lasing a POSITIONABLE
-- @param #POSITIONABLE self
-- @param #POSITIONABLE Target
-- @return #POSITIONABLE
function POSITIONABLE:LaseOff( Target )
self:F2()
local TargetUnitName = Target:GetName()
if self.Spot then
self.Spot:LaseOff()
self.Spot = nil
end
return self
end
--- Check if the POSITIONABLE is lasing a target
-- @param #POSITIONABLE self
-- @return #boolean true if it is lasing a target
function POSITIONABLE:IsLasing()
self:F2()
local Lasing = false
if self.Spot then
Lasing = self.Spot:IsLasing()
end
return Lasing
end

View File

@@ -859,6 +859,8 @@ function UNIT:SmokeBlue()
trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Blue )
end
-- Is methods
--- Returns if the unit is of an air category.