diff --git a/Moose Development/Moose/AI/AI_Designate.lua b/Moose Development/Moose/AI/AI_Designate.lua index 5df5ee6cd..49244c83e 100644 --- a/Moose Development/Moose/AI/AI_Designate.lua +++ b/Moose Development/Moose/AI/AI_Designate.lua @@ -1,6 +1,6 @@ --- **AI (Release 2.1)** -- Management of target designation. -- --- -- +-- -- -- -- === -- @@ -14,8 +14,27 @@ do -- AI_DESIGNATE --- # 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... + -- AI_DESIGNATE is orchestrating the designation of potential targets executed by a Recce group, + -- and communicates 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... + -- + -- The Recce group is detecting as part of the DETECTION_ class continuously targets. + -- Once targets have been detected, they will be reported. The AI_DESIGNATE object will fire the **Detect** event in this case! + -- As part of the reporting, the following happens: + -- + -- * A message is sent to each GROUP of the Attack SET_GROUP, containing the threat level and the target composition. + -- * A menu is created and updated for each GROUP of the Attack SET_GROUP, containing the the treat level and the target composition. + -- + -- One of the players in one of the Attack GROUPs, can then select a Target Set by selecting one of the menu options. + -- Each menu option has two modes: + -- + -- * If the Target Set is not being designated, then the Designate menu for the target Set will provide options to Lase or Smoke the targets. + -- * If the Target Set is being designated, then the Designate menu will provide an option to cancel the designation. + -- + -- In this way, the AI can assist players to designate ground targets for a coordinated attack! + -- + -- Have FUN! -- -- ## 1. AI_DESIGNATE constructor -- @@ -35,7 +54,27 @@ do -- AI_DESIGNATE -- * **@{#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. + -- * **@{#AI_DESIGNATE.Status}**: Report designation status. + -- + -- ## 3. Set laser codes + -- + -- An array of laser codes can be provided, that will be used by the AI_DESIGNATE when lasing. + -- The laser code is communicated by the Recce when it is lasing a larget. + -- Note that the default laser code is 1113. + -- Working known laser codes are: 1113,1462,1483,1537,1362,1214,1131,1182,1644,1614,1515,1411,1621,1138,1542,1678,1573,1314,1643,1257,1467,1375,1341,1275,1237 + -- + -- Use the method @{#AI_DESIGNATE.SetLaserCodes}() to set the possible laser codes to be selected from. + -- One laser code can be given or an sequence of laser codes through an table... + -- + -- AIDesignate:SetLaserCodes( 1214 ) + -- + -- The above sets one laser code with the value 1214. + -- + -- AIDesignate:SetLaserCodes( { 1214, 1131, 1614, 1138 } ) + -- + -- The above sets a collection of possible laser codes that can be assigned. **Note the { } notation!** + -- + -- -- -- @field #AI_DESIGNATE -- @@ -55,21 +94,168 @@ do -- AI_DESIGNATE self:SetStartState( "Designating" ) self:AddTransition( "*", "Detect", "*" ) + + --- Detect Handler OnBefore for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE] OnBeforeDetect + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @return #boolean + + --- Detect Handler OnAfter for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE] OnAfterDetect + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + + --- Detect Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE] Detect + -- @param #AI_DESIGNATE self + + --- Detect Asynchronous Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE] __Detect + -- @param #AI_DESIGNATE self + -- @param #number Delay + self:AddTransition( "*", "LaseOn", "*" ) + + --- LaseOn Handler OnBefore for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnBeforeLaseOn + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @return #boolean + + --- LaseOn Handler OnAfter for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnAfterLaseOn + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + + --- LaseOn Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] LaseOn + -- @param #AI_DESIGNATE self + + --- LaseOn Asynchronous Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] __LaseOn + -- @param #AI_DESIGNATE self + -- @param #number Delay + + + self:AddTransition( "*", "LaseOff", "*" ) + + --- LaseOff Handler OnBefore for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnBeforeLaseOff + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @return #boolean + + --- LaseOff Handler OnAfter for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnAfterLaseOff + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + + --- LaseOff Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] LaseOff + -- @param #AI_DESIGNATE self + + --- LaseOff Asynchronous Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] __LaseOff + -- @param #AI_DESIGNATE self + -- @param #number Delay + + + self:AddTransition( "*", "Smoke", "*" ) + + --- Smoke Handler OnBefore for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnBeforeSmoke + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @return #boolean + + --- Smoke Handler OnAfter for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnAfterSmoke + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + + --- Smoke Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] Smoke + -- @param #AI_DESIGNATE self + + --- Smoke Asynchronous Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] __Smoke + -- @param #AI_DESIGNATE self + -- @param #number Delay + + + self:AddTransition( "*", "Status", "*" ) - + + --- Status Handler OnBefore for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnBeforeStatus + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @return #boolean + + --- Status Handler OnAfter for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] OnAfterStatus + -- @param #AI_DESIGNATE self + -- @param #string From + -- @param #string Event + -- @param #string To + + --- Status Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] Status + -- @param #AI_DESIGNATE self + + --- Status Asynchronous Trigger for AI_DESIGNATE + -- @function [parent=#AI_DESIGNATE ] __Status + -- @param #AI_DESIGNATE self + -- @param #number Delay + self.Detection = Detection self.GroupSet = GroupSet self.RecceSet = Detection:GetDetectionSetGroup() self.Spots = {} + self:SetLaserCodes( 1113 ) + self.Detection:__Start( 2 ) return self end + + + --- Set an array of possible laser codes. + -- Each new lase will select a code from this table. + -- @param #AI_DESIGNATE self + -- @param #list<#number> LaserCodes + -- @return #AI_DESIGNATE + function AI_DESIGNATE:SetLaserCodes( LaserCodes ) + + self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes } + self:E(self.LaserCodes) + + return self + end + --- -- @param #AI_DESIGNATE self @@ -78,75 +264,112 @@ do -- AI_DESIGNATE self:__Detect( -60 ) + self:SendStatus() + self:SetDesignateMenu() + + return self + end + + --- Sends the status to the Attack Groups. + -- @param #AI_DESIGNATE self + -- @return #AI_DESIGNATE + function AI_DESIGNATE:SendStatus() + + local DetectedReport = REPORT:New( "Targets ready to be designated:" ) + local DetectedItems = self.Detection:GetDetectedItems() + + for Index, DetectedItemData in pairs( DetectedItems ) do + + local Report = self.Detection:DetectedItemReportSummary( Index ) + DetectedReport:Add(" - " .. Report) + end + + local RecceLeader = self.RecceSet:GetFirst() -- Wrapper.Group#GROUP + self.GroupSet:ForEachGroup( --- @param Wrapper.Group#GROUP GroupReport - function( GroupReport ) - - self:E(GroupReport:GetName()) - - local DesignateMenu = GroupReport:GetState( GroupReport, "DesignateMenu" ) -- Core.Menu#MENU_GROUP + function( AttackGroup ) + RecceLeader:MessageToGroup( DetectedReport:Text( "\n" ), 15, AttackGroup ) + end + ) + + return self + end + + --- Sets the Designate Menu. + -- @param #AI_DESIGNATE self + -- @return #AI_DESIGNATE + function AI_DESIGNATE:SetDesignateMenu() + + self.GroupSet:ForEachGroup( + + --- @param Wrapper.Group#GROUP GroupReport + function( AttackGroup ) + local DesignateMenu = AttackGroup:GetState( AttackGroup, "DesignateMenu" ) -- Core.Menu#MENU_GROUP if DesignateMenu then DesignateMenu:Remove() DesignateMenu = nil self:E("Remove Menu") end - DesignateMenu = MENU_GROUP:New( GroupReport, "Designate Targets" ) + DesignateMenu = MENU_GROUP:New( AttackGroup, "Designate Targets" ) self:E(DesignateMenu) - GroupReport:SetState( GroupReport, "DesignateMenu", DesignateMenu ) + AttackGroup:SetState( AttackGroup, "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 Report = self.Detection:DetectedItemReportSummary( Index ) local DetectedMenu = MENU_GROUP:New( - GroupReport, - DetectedReport, + AttackGroup, + Report, DesignateMenu ) if self.Spots[Index] then MENU_GROUP_COMMAND:New( - GroupReport, + AttackGroup, "Switch laser Off", DetectedMenu, self.MenuLaseOff, self, + AttackGroup, Index ) else MENU_GROUP_COMMAND:New( - GroupReport, + AttackGroup, "Lase target 60 secs", DetectedMenu, self.MenuLaseOn, self, + AttackGroup, Index, 60 ) MENU_GROUP_COMMAND:New( - GroupReport, + AttackGroup, "Lase target 120 secs", DetectedMenu, self.MenuLaseOn, self, + AttackGroup, Index, 120 ) end MENU_GROUP_COMMAND:New( - GroupReport, + AttackGroup, "Smoke", DetectedMenu, self.MenuSmoke, self, + AttackGroup, Index ) @@ -154,41 +377,41 @@ do -- AI_DESIGNATE end end ) - + return self end --- -- @param #AI_DESIGNATE self - function AI_DESIGNATE:MenuSmoke( Index ) + function AI_DESIGNATE:MenuSmoke( AttackGroup, Index ) self:E("Designate through Smoke") - self:__Smoke( 1, Index ) + self:__Smoke( 1, AttackGroup, Index ) end --- -- @param #AI_DESIGNATE self - function AI_DESIGNATE:MenuLaseOn( Index, Duration ) + function AI_DESIGNATE:MenuLaseOn( AttackGroup, Index, Duration ) self:E("Designate through Lase") - self:__LaseOn( 1, Index, Duration ) + self:__LaseOn( 1, AttackGroup, Index, Duration ) end --- -- @param #AI_DESIGNATE self - function AI_DESIGNATE:MenuLaseOff( Index, Duration ) + function AI_DESIGNATE:MenuLaseOff( AttackGroup, Index, Duration ) self:E("Lasing off") - self:__LaseOff( 1, Index ) + self:__LaseOff( 1, AttackGroup, Index ) end --- -- @param #AI_DESIGNATE self -- @return #AI_DESIGNATE - function AI_DESIGNATE:onafterLaseOn( From, Event, To, Index, Duration ) + function AI_DESIGNATE:onafterLaseOn( From, Event, To, AttackGroup, Index, Duration ) local TargetSetUnit = self.Detection:GetDetectedSet( Index ) @@ -203,7 +426,12 @@ do -- AI_DESIGNATE 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 ) + self.Spots[Index] = self.Spots[Index] or {} + local Spots = self.Spots[Index] + local LaserCode = self.LaserCodes[math.random(1, #self.LaserCodes)] + local Spot = RecceUnit:LaseUnit( SmokeUnit, LaserCode, Duration ) + Spots[#Spots+1] = Spot + RecceUnit:MessageToGroup( "Lasing " .. SmokeUnit:GetTypeName() .. " for " .. Duration .. " seconds. Laser Code: " .. Spot.LaserCode, 15, AttackGroup ) break end end @@ -212,25 +440,37 @@ do -- AI_DESIGNATE --end end ) + + self:SetDesignateMenu() end - + + --- -- @param #AI_DESIGNATE self -- @return #AI_DESIGNATE - function AI_DESIGNATE:onafterLaseOff( From, Event, To, Index ) + function AI_DESIGNATE:onafterLaseOff( From, Event, To, AttackGroup, Index ) local TargetSetUnit = self.Detection:GetDetectedSet( Index ) - self.Spots[Index]:LaseOff() + local Spots = self.Spots[Index] + + for SpotID, SpotData in pairs( Spots ) do + local Spot = SpotData -- Core.Spot#SPOT + Spot.Recce:MessageToGroup( "Stopped lasing " .. Spot.Target:GetTypeName() .. ".", 15, AttackGroup ) + Spot:LaseOff() + end + + Spots = nil self.Spots[Index] = nil + self:SetDesignateMenu() end --- -- @param #AI_DESIGNATE self -- @return #AI_DESIGNATE - function AI_DESIGNATE:onafterSmoke( From, Event, To, Index ) + function AI_DESIGNATE:onafterSmoke( From, Event, To, AttackGroup, Index ) local TargetSetUnit = self.Detection:GetDetectedSet( Index ) diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index 4469a640e..307cd31bb 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -568,7 +568,7 @@ do -- DETECTION_BASE local DetectedUnitCategory = DetectedObject:getDesc().category - self:T( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory, DetectedCategory } ) + self:T( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory } ) -- Calculate Acceptance diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 7b76f04d9..270677ddb 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -311,7 +311,8 @@ function POSITIONABLE:GetMessage( Message, Duration, Name ) local DCSObject = self:GetDCSObject() if DCSObject then Name = Name or self:GetTypeName() - return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. Name .. ")" ) + local Callsign = self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName() + return MESSAGE:New( Message, Duration, Callsign .. " (" .. Name .. ")" ) end return nil @@ -456,7 +457,7 @@ end -- @param #POSITIONABLE Target -- @param #number LaserCode -- @param #number Duration --- @return Spot +-- @return Core.Spot#SPOT function POSITIONABLE:LaseUnit( Target, LaserCode, Duration ) self:F2() @@ -467,7 +468,7 @@ function POSITIONABLE:LaseUnit( Target, LaserCode, Duration ) self:E("bulding spot") self.Spot = SPOT:New( self ) - self.Spot:LaseOn( Target:GetPointVec3(), LaserCode, Duration) + self.Spot:LaseOn( Target, LaserCode, Duration) return self.Spot diff --git a/docs/Documentation/AI_Designate.html b/docs/Documentation/AI_Designate.html index 924ecdb43..df1b0359e 100644 --- a/docs/Documentation/AI_Designate.html +++ b/docs/Documentation/AI_Designate.html @@ -99,7 +99,7 @@ -
--
--
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...
+AI_DESIGNATE is orchestrating the designation of potential targets executed by a Recce group, +and communicates 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...
Sends the status to the Attack Groups.
+Sets the Designate Menu.
+Set an array of possible laser codes.
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...
+AI_DESIGNATE is orchestrating the designation of potential targets executed by a Recce group, +and communicates 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...
+The Recce group is detecting as part of the DETECTION_ class continuously targets. +Once targets have been detected, they will be reported. The AI_DESIGNATE object will fire the Detect event in this case! +As part of the reporting, the following happens:
+ +One of the players in one of the Attack GROUPs, can then select a Target Set by selecting one of the menu options. +Each menu option has two modes:
+ +In this way, the AI can assist players to designate ground targets for a coordinated attack!
+ +Have FUN!
+An array of laser codes can be provided, that will be used by the AI_DESIGNATE when lasing. +The laser code is communicated by the Recce when it is lasing a larget. +Note that the default laser code is 1113. +Working known laser codes are: 1113,1462,1483,1537,1362,1214,1131,1182,1644,1614,1515,1411,1621,1138,1542,1678,1573,1314,1643,1257,1467,1375,1341,1275,1237
+ +Use the method AI_DESIGNATE.SetLaserCodes() to set the possible laser codes to be selected from. +One laser code can be given or an sequence of laser codes through an table...
+ +AIDesignate:SetLaserCodes( 1214 )
+
+
+The above sets one laser code with the value 1214.
+ +AIDesignate:SetLaserCodes( { 1214, 1131, 1614, 1138 } )
+
+
+The above sets a collection of possible laser codes that can be assigned. Note the { } notation!
+ + + @@ -269,13 +340,26 @@ of players, so that following a dynamically generated menu system, each detected + + + AttackGroup :
Index :
AttackGroup :
Index :
AttackGroup :
Index :
Sends the status to the Attack Groups.
+ +Sets the Designate Menu.
+ +Set an array of possible laser codes.
+ + +Each new lase will select a code from this table.
+ +#list < :
+number> LaserCodes
LaserCodes :
AttackGroup :
Index :
AttackGroup :
Index :
AttackGroup :
Index :
listThis table contains the targets detected during patrol.
-Contains the counter how many units are currently alive
-Don't repeat the group from Take-Off till Landing and back Take-Off by ReSpawning.
+Overwrite unit names by default with group name.
+By default, no InitLimit
+When the first Spawn executes, all the Groups need to be made visible before start.
+Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.
Core.Point#POINT_VEC3 PointVec3 :
Wrapper.Positionable#POSITIONABLE Target :
From :
Event :
To :