diff --git a/Moose Development/Moose/AI/AI_Designate.lua b/Moose Development/Moose/AI/AI_Designate.lua new file mode 100644 index 000000000..8c4335b4c --- /dev/null +++ b/Moose Development/Moose/AI/AI_Designate.lua @@ -0,0 +1,230 @@ +--- **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 + + --- + -- + -- @field #AI_DESIGNATE 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()) + local NearestRecceUnit = NearestRecceGroup:GetUnit(1) + self:E( { NearestRecceUnit = NearestRecceUnit } ) + self.Spots[Index] = NearestRecceUnit:LaseUnitOn( SmokeUnit, nil, Duration ) + 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 + + diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index f83a2903a..bac65d9aa 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -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. diff --git a/Moose Development/Moose/Core/Spot.lua b/Moose Development/Moose/Core/Spot.lua new file mode 100644 index 000000000..9b4d9e12c --- /dev/null +++ b/Moose Development/Moose/Core/Spot.lua @@ -0,0 +1,98 @@ +--- **Core** -- 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 + 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 = 1, 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 + 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 + end +end \ No newline at end of file diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index 004d93c59..cfb9c02f4 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -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 diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index e6bd95cd3..0d608432e 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -450,3 +450,47 @@ function POSITIONABLE:GetRadio() self:F2(self) return RADIO:New(self) end + +--- Start Lasing a POSITIONABLE +-- @param #POSITIONABLE self +-- @param #POSITIONABLE Target +-- @param #number LaserCode +-- @param #number Duration +-- @return Spot +function POSITIONABLE:LaseUnitOn( Target, LaserCode, Duration ) + self:F2() + + LaserCode = LaserCode or math.random( 1000, 9999 ) + + local TargetUnitName = Target:GetName() + + self.Spots = self.Spots or {} + self.Spots[TargetUnitName] = self.Spots[TargetUnitName] or {} + + local RecceDcsUnit = self:GetDCSObject() + local TargetVec3 = Target:GetVec3() + + self:E("bulding spot") + self.Spots[TargetUnitName] = SPOT:New( self ):LaseOn( Target:GetPointVec3(), LaserCode, Duration) + + return self.Spots[TargetUnitName] + +end + +--- Stop Lasing a POSITIONABLE +-- @param #POSITIONABLE self +-- @param #POSITIONABLE Target +-- @return #POSITIONABLE +function POSITIONABLE:LaseUnitOff( Target ) + self:F2() + + local TargetUnitName = Target:GetName() + + self.Spots = self.Spots or {} + if self.Spots[TargetUnitName] then + self.Spots[TargetUnitName]:LaseOff() + self.Spots[TargetUnitName] = nil + end + + return self +end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index a8d4e75ca..183bc4d5a 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -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. diff --git a/Moose Mission Setup/Moose.files b/Moose Mission Setup/Moose.files index 57f9bca5a..a244de717 100644 --- a/Moose Mission Setup/Moose.files +++ b/Moose Mission Setup/Moose.files @@ -15,6 +15,7 @@ Core/Fsm.lua Core/Radio.lua Core/SpawnStatic.lua Core/Cargo.lua +Core/Spot.lua Wrapper/Object.lua Wrapper/Identifiable.lua @@ -41,6 +42,7 @@ AI/AI_Balancer.lua AI/AI_Patrol.lua AI/AI_Cap.lua AI/AI_Cas.lua +AI/AI_Designate.lua Actions/Act_Assign.lua Actions/Act_Route.lua diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index 53e72fc3d..e52e6aada 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20170416_0614' ) +env.info( 'Moose Generation Timestamp: 20170419_1613' ) local base = _G @@ -37,6 +37,7 @@ __Moose.Include( 'Core/Fsm.lua' ) __Moose.Include( 'Core/Radio.lua' ) __Moose.Include( 'Core/SpawnStatic.lua' ) __Moose.Include( 'Core/Cargo.lua' ) +__Moose.Include( 'Core/Spot.lua' ) __Moose.Include( 'Wrapper/Object.lua' ) __Moose.Include( 'Wrapper/Identifiable.lua' ) __Moose.Include( 'Wrapper/Positionable.lua' ) @@ -60,6 +61,7 @@ __Moose.Include( 'AI/AI_Balancer.lua' ) __Moose.Include( 'AI/AI_Patrol.lua' ) __Moose.Include( 'AI/AI_Cap.lua' ) __Moose.Include( 'AI/AI_Cas.lua' ) +__Moose.Include( 'AI/AI_Designate.lua' ) __Moose.Include( 'Actions/Act_Assign.lua' ) __Moose.Include( 'Actions/Act_Route.lua' ) __Moose.Include( 'Actions/Act_Account.lua' )