diff --git a/Moose Development/Moose/Controllable.lua b/Moose Development/Moose/Controllable.lua index 8b9869a92..eacc134f1 100644 --- a/Moose Development/Moose/Controllable.lua +++ b/Moose Development/Moose/Controllable.lua @@ -2198,4 +2198,121 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end +-- Message APIs + +--- Returns a message with the callsign embedded (if there is one). +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @return Message#MESSAGE +function CONTROLLABLE:GetMessage( Message, Duration ) + self:E( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) + end + + return nil +end + +--- Send a message to all coalitions. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToAll( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToAll() + end + + return nil +end + +--- Send a message to the red coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTYpes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToRed( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToRed() + end + + return nil +end + +--- Send a message to the blue coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToBlue( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToBlue() + end + + return nil +end + +--- Send a message to a client. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Client#CLIENT Client The client object receiving the message. +function CONTROLLABLE:MessageToClient( Message, Duration, Client ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToClient( Client ) + end + + return nil +end + +--- Send a message to a @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Group#GROUP MessageGroup The GROUP object receiving the message. +function CONTROLLABLE:MessageToGroup( Message, Duration, MessageGroup ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + if DCSObject:isExist() then + self:GetMessage( Message, Duration ):ToGroup( MessageGroup ) + end + end + + return nil +end + +--- Send a message to the players in the @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:Message( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToGroup( self ) + end + + return nil +end diff --git a/Moose Development/Moose/Detection.lua b/Moose Development/Moose/Detection.lua index bff709d9f..1b388a7d8 100644 --- a/Moose Development/Moose/Detection.lua +++ b/Moose Development/Moose/Detection.lua @@ -407,6 +407,7 @@ DETECTION_AREAS = { -- @field #table Changes A list of the changes reported on the detected area. (It is up to the user of the detected area to consume those changes). -- @field #number AreaID -- The identifier of the detected area. -- @field #boolean FriendliesNearBy Indicates if there are friendlies within the detected area. +-- @field Unit#UNIT NearestFAC The nearest FAC near the Area. --- DETECTION_AREAS constructor. @@ -594,6 +595,36 @@ function DETECTION_AREAS:CalculateThreatLevelA2G( DetectedArea ) end +--- Find the nearest FAC of the DetectedArea. +-- @param #DETECTION_AREAS self +-- @param #DETECTION_AREAS.DetectedArea DetectedArea +-- @return Unit#UNIT The nearest FAC unit +function DETECTION_AREAS:NearestFAC( DetectedArea ) + + local NearestFAC = nil + local MinDistance = 1000000000 -- Units are not further than 1000000 km away from an area :-) + + for FACGroupName, FACGroupData in pairs( self.DetectionSetGroup:GetSet() ) do + for FACUnit, FACUnitData in pairs( FACGroupData:GetUnits() ) do + local FACUnit = FACUnitData -- Unit#UNIT + if FACUnit:IsActive() then + local Vec3 = FACUnit:GetPointVec3() + local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) + local Distance = PointVec3:Get2DDistance(POINT_VEC3:NewFromVec3( FACUnit:GetPointVec3() ) ) + self:E( "Distance", Distance ) + if Distance < MinDistance then + MinDistance = Distance + NearestFAC = FACUnit + end + end + end + end + + self:E( { NearestFAC.UnitName, MinDistance } ) + DetectedArea.NearestFAC = NearestFAC + +end + --- Returns the A2G threat level of the units in the DetectedArea -- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS.DetectedArea DetectedArea @@ -919,6 +950,7 @@ function DETECTION_AREAS:CreateDetectionSets() self:ReportFriendliesNearBy( { DetectedArea = DetectedArea, ReportSetGroup = self.DetectionSetGroup } ) -- Fill the Friendlies table self:CalculateThreatLevelA2G( DetectedArea ) -- Calculate A2G threat level + self:NearestFAC( DetectedArea ) if DETECTION_AREAS._SmokeDetectedUnits or self._SmokeDetectedUnits then DetectedZone.ZoneUNIT:SmokeRed() diff --git a/Moose Development/Moose/DetectionManager.lua b/Moose Development/Moose/DetectionManager.lua index ec8a868bf..9c25cb542 100644 --- a/Moose Development/Moose/DetectionManager.lua +++ b/Moose Development/Moose/DetectionManager.lua @@ -434,7 +434,7 @@ do -- DETECTION_DISPATCHER if not CASTask then local TargetSetUnit = self:EvaluateCAS( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - CASTask = Mission:AddTask( TASK_CAS:New( Mission, self.SetGroup, "CAS." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if CASTask and CASTask:IsStatePlanned() then @@ -448,7 +448,7 @@ do -- DETECTION_DISPATCHER if not BAITask then local TargetSetUnit = self:EvaluateBAI( DetectedArea, self.CommandCenter:GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - BAITask = Mission:AddTask( TASK_BAI:New( Mission, self.SetGroup, "BAI." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if BAITask and BAITask:IsStatePlanned() then diff --git a/Moose Development/Moose/Group.lua b/Moose Development/Moose/Group.lua index cc10cf621..280ba0308 100644 --- a/Moose Development/Moose/Group.lua +++ b/Moose Development/Moose/Group.lua @@ -866,120 +866,3 @@ function GROUP:CopyRoute( Begin, End, Randomize, Radius ) end --- Message APIs - ---- Returns a message for a coalition or a client. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @return Message#MESSAGE -function GROUP:GetMessage( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) - end - - return nil -end - ---- Send a message to all coalitions. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToAll( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToAll() - end - - return nil -end - ---- Send a message to the red coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTYpes#Duration Duration The duration of the message. -function GROUP:MessageToRed( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToRed() - end - - return nil -end - ---- Send a message to the blue coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToBlue( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToBlue() - end - - return nil -end - ---- Send a message to a client. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Client#CLIENT Client The client object receiving the message. -function GROUP:MessageToClient( Message, Duration, Client ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToClient( Client ) - end - - return nil -end - ---- Send a message to a @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Group#GROUP MessageGroup The GROUP object receiving the message. -function GROUP:MessageToGroup( Message, Duration, MsgGroup ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - if DCSGroup:isExist() then - self:GetMessage( Message, Duration ):ToGroup( MsgGroup ) - end - end - - return nil -end - ---- Send a message to the players in the @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:Message( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToGroup( self ) - end - - return nil -end diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua index 67d96af87..ba20dc1d0 100644 --- a/Moose Development/Moose/Moose.lua +++ b/Moose Development/Moose/Moose.lua @@ -55,11 +55,11 @@ Include.File( "Process_Assign" ) Include.File( "Process_Route" ) Include.File( "Process_Smoke" ) Include.File( "Process_Destroy" ) +Include.File( "Process_JTAC" ) Include.File( "Task" ) Include.File( "Task_SEAD" ) -Include.File( "Task_CAS" ) -Include.File( "Task_BAI" ) +Include.File( "Task_A2G" ) -- The order of the declarations is important here. Don't touch it. diff --git a/Moose Development/Moose/Point.lua b/Moose Development/Moose/Point.lua index 216933c30..530d0217d 100644 --- a/Moose Development/Moose/Point.lua +++ b/Moose Development/Moose/Point.lua @@ -118,6 +118,18 @@ function POINT_VEC3:New( x, y, z ) return self end +--- Create a new POINT_VEC3 object from Vec3 coordinates. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Vec3 Vec3 The Vec3 point. +-- @return Point#POINT_VEC3 self +function POINT_VEC3:NewFromVec3( Vec3 ) + + local self = BASE:Inherit( self, BASE:New() ) + self.PointVec3 = Vec3 + self:F2( self.PointVec3 ) + return self +end + --- Return the coordinates of the POINT_VEC3 in Vec3 format. -- @param #POINT_VEC3 self diff --git a/Moose Development/Moose/Process.lua b/Moose Development/Moose/Process.lua index bf5f9f122..2f2e46801 100644 --- a/Moose Development/Moose/Process.lua +++ b/Moose Development/Moose/Process.lua @@ -4,7 +4,9 @@ -- @type PROCESS -- @field Scheduler#SCHEDULER ProcessScheduler -- @field Unit#UNIT ProcessUnit --- @field Task#TASK Task +-- @field Group#GROUP ProcessGroup +-- @field Menu#MENU_GROUP MissionMenu +-- @field Task#TASK_BASE Task -- @field StateMachine#STATEMACHINE_TASK Fsm -- @field #string ProcessName -- @extends Base#BASE @@ -26,6 +28,8 @@ function PROCESS:New( ProcessName, Task, ProcessUnit ) self:F() self.ProcessUnit = ProcessUnit + self.ProcessGroup = ProcessUnit:GetGroup() + self.MissionMenu = Task.Mission:GetMissionMenu( self.ProcessGroup ) self.Task = Task self.ProcessName = ProcessName @@ -36,9 +40,8 @@ end --- @param #PROCESS self function PROCESS:NextEvent( NextEvent, ... ) - self:F2( arg ) if self.AllowEvents == true then - self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, { self, self.ProcessUnit, unpack( arg ) }, 1 ) + self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, arg, 1 ) end end @@ -75,7 +78,7 @@ end -- @param #string From -- @param #string To function PROCESS:OnStateChange( Fsm, Event, From, To ) - self:E( { Event, From, To, self.ProcessUnit.UnitName } ) + self:E( { self.ProcessName, Event, From, To, self.ProcessUnit.UnitName } ) if self:IsTrace() then MESSAGE:New( "Process " .. self.ProcessName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll() diff --git a/Moose Development/Moose/Process_BAI.lua b/Moose Development/Moose/Process_BAI.lua deleted file mode 100644 index 0181e6a65..000000000 --- a/Moose Development/Moose/Process_BAI.lua +++ /dev/null @@ -1,143 +0,0 @@ ---- @module Process_BAI - ---- PROCESS_BAI class --- @type PROCESS_BAI --- @field Unit#UNIT ProcessUnit --- @field Set#SET_UNIT TargetSetUnit --- @extends Process#PROCESS -PROCESS_BAI = { - ClassName = "PROCESS_BAI", - Fsm = {}, - TargetSetUnit = nil, -} - - ---- Creates a new BAI task. --- @param #PROCESS_BAI self --- @param Task#TASK Task --- @param Unit#UNIT ProcessUnit --- @param Set#SET_UNIT TargetSetUnit --- @return #PROCESS_BAI self -function PROCESS_BAI:New( Task, ProcessUnit, TargetSetUnit ) - - -- Inherits from BASE - local self = BASE:Inherit( self, PROCESS:New( "BAI", Task, ProcessUnit ) ) -- #PROCESS_BAI - - self.TargetSetUnit = TargetSetUnit - - self.Fsm = STATEMACHINE_PROCESS:New( self, { - initial = 'Assigned', - events = { - { name = 'Start', from = 'Assigned', to = 'Waiting' }, - { name = 'HitTarget', from = 'Waiting', to = 'Destroy' }, - { name = 'MoreTargets', from = 'Destroy', to = 'Waiting' }, - { name = 'Destroyed', from = 'Destroy', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Waiting', to = 'Failed' }, - { name = 'Fail', from = 'Destroy', to = 'Failed' }, - }, - callbacks = { - onStart = self.OnStart, - onHitTarget = self.OnHitTarget, - onMoreTargets = self.OnMoreTargets, - onDestroyed = self.OnDestroyed, - onKilled = self.OnKilled, - }, - endstates = { 'Success', 'Failed' } - } ) - - - _EVENTDISPATCHER:OnDead( self.EventDead, self ) - - return self -end - ---- Process Events - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_BAI:OnStart( Fsm, Event, From, To ) - self:E( { Event, From, To, self.ProcessUnit.UnitName} ) - - self:NextEvent( Fsm.Start ) -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To --- @param Event#EVENTDATA Event -function PROCESS_BAI:OnHitTarget( Fsm, Event, From, To, Event ) - - 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_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_BAI:OnMoreTargets( Fsm, Event, From, To ) - - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To --- @param Event#EVENTDATA DCSEvent -function PROCESS_BAI:OnKilled( Fsm, Event, From, To ) - - self:NextEvent( Fsm.Restart ) - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_BAI:OnRestart( Fsm, Event, From, To ) - - self:NextEvent( Fsm.Menu ) - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_BAI self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_BAI:OnDestroyed( Fsm, Event, From, To ) - -end - ---- DCS Events - ---- @param #PROCESS_BAI self --- @param Event#EVENTDATA Event -function PROCESS_BAI:EventDead( Event ) - - if Event.IniDCSUnit then - self.TargetSetUnit:Remove( Event.IniDCSUnitName ) - self:NextEvent( self.Fsm.HitTarget, Event ) - end -end - - diff --git a/Moose Development/Moose/Process_CAS.lua b/Moose Development/Moose/Process_CAS.lua deleted file mode 100644 index d8b4c4b8b..000000000 --- a/Moose Development/Moose/Process_CAS.lua +++ /dev/null @@ -1,143 +0,0 @@ ---- @module Process_CAS - ---- PROCESS_CAS class --- @type PROCESS_CAS --- @field Unit#UNIT ProcessUnit --- @field Set#SET_UNIT TargetSetUnit --- @extends Process#PROCESS -PROCESS_CAS = { - ClassName = "PROCESS_CAS", - Fsm = {}, - TargetSetUnit = nil, -} - - ---- Creates a new CAS task. --- @param #PROCESS_CAS self --- @param Task#TASK Task --- @param Unit#UNIT ProcessUnit --- @param Set#SET_UNIT TargetSetUnit --- @return #PROCESS_CAS self -function PROCESS_CAS:New( Task, ProcessUnit, TargetSetUnit ) - - -- Inherits from BASE - local self = BASE:Inherit( self, PROCESS:New( "CAS", Task, ProcessUnit ) ) -- #PROCESS_CAS - - self.TargetSetUnit = TargetSetUnit - - self.Fsm = STATEMACHINE_PROCESS:New( self, { - initial = 'Assigned', - events = { - { name = 'Start', from = 'Assigned', to = 'Waiting' }, - { name = 'HitTarget', from = 'Waiting', to = 'Destroy' }, - { name = 'MoreTargets', from = 'Destroy', to = 'Waiting' }, - { name = 'Destroyed', from = 'Destroy', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Waiting', to = 'Failed' }, - { name = 'Fail', from = 'Destroy', to = 'Failed' }, - }, - callbacks = { - onStart = self.OnStart, - onHitTarget = self.OnHitTarget, - onMoreTargets = self.OnMoreTargets, - onDestroyed = self.OnDestroyed, - onKilled = self.OnKilled, - }, - endstates = { 'Success', 'Failed' } - } ) - - - _EVENTDISPATCHER:OnDead( self.EventDead, self ) - - return self -end - ---- Process Events - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_CAS:OnStart( Fsm, Event, From, To ) - self:E( { Event, From, To, self.ProcessUnit.UnitName} ) - - self:NextEvent( Fsm.Start ) -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To --- @param Event#EVENTDATA Event -function PROCESS_CAS:OnHitTarget( Fsm, Event, From, To, Event ) - - 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_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_CAS:OnMoreTargets( Fsm, Event, From, To ) - - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To --- @param Event#EVENTDATA DCSEvent -function PROCESS_CAS:OnKilled( Fsm, Event, From, To ) - - self:NextEvent( Fsm.Restart ) - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_CAS:OnRestart( Fsm, Event, From, To ) - - self:NextEvent( Fsm.Menu ) - -end - ---- StateMachine callback function for a PROCESS --- @param #PROCESS_CAS self --- @param StateMachine#STATEMACHINE_PROCESS Fsm --- @param #string Event --- @param #string From --- @param #string To -function PROCESS_CAS:OnDestroyed( Fsm, Event, From, To ) - -end - ---- DCS Events - ---- @param #PROCESS_CAS self --- @param Event#EVENTDATA Event -function PROCESS_CAS:EventDead( Event ) - - if Event.IniDCSUnit then - self.TargetSetUnit:Remove( Event.IniDCSUnitName ) - self:NextEvent( self.Fsm.HitTarget, Event ) - end -end - - diff --git a/Moose Development/Moose/Process_JTAC.lua b/Moose Development/Moose/Process_JTAC.lua new file mode 100644 index 000000000..7e78f1ad5 --- /dev/null +++ b/Moose Development/Moose/Process_JTAC.lua @@ -0,0 +1,199 @@ +--- @module Process_JTAC + +--- PROCESS_JTAC class +-- @type PROCESS_JTAC +-- @field Unit#UNIT ProcessUnit +-- @field Set#SET_UNIT TargetSetUnit +-- @extends Process#PROCESS +PROCESS_JTAC = { + ClassName = "PROCESS_JTAC", + Fsm = {}, + TargetSetUnit = nil, +} + + +--- Creates a new DESTROY process. +-- @param #PROCESS_JTAC self +-- @param Task#TASK Task +-- @param Unit#UNIT ProcessUnit +-- @param Set#SET_UNIT TargetSetUnit +-- @param 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 = STATEMACHINE_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' } + } ) + + + _EVENTDISPATCHER:OnDead( self.EventDead, self ) + + return self +end + +--- Process Events + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnStart( Fsm, Event, From, To ) + + self:NextEvent( Fsm.JTACMenuUpdate ) +end + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuUpdate( Fsm, Event, From, To ) + + local function JTACMenuSpot( MenuParam ) + self:E( MenuParam.TargetUnit.UnitName ) + local self = MenuParam.self + local TargetUnit = MenuParam.TargetUnit + + self:NextEvent( self.Fsm.JTACMenuSpot, TargetUnit ) + end + + local function JTACMenuCancel( MenuParam ) + self:E( 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:E( {"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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuAwait( Fsm, Event, From, To ) + + if self.DisplayCount >= self.DisplayInterval then + + local TaskJTAC = self.Task -- 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuSpot( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- Task#TASK_JTAC + + TaskJTAC.Spots = TaskJTAC.Spots or {} + TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {} + + local DCSFACObject = self.FACUnit:GetDCSObject() + local TargetVec3 = TargetUnit:GetPointVec3() + + TaskJTAC.Spots[TargetUnitName] = Spot.createInfraRed( self.FACUnit:GetDCSObject(), { x = 0, y = 1, z = 0 }, TargetUnit:GetPointVec3(), 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuCancel( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- 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 + + diff --git a/Moose Development/Moose/Process_Route.lua b/Moose Development/Moose/Process_Route.lua index a3bb9fd66..fd240a700 100644 --- a/Moose Development/Moose/Process_Route.lua +++ b/Moose Development/Moose/Process_Route.lua @@ -65,7 +65,7 @@ function PROCESS_ROUTE:OnLeaveUnArrived( Fsm, Event, From, To ) local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y ) local TaskUnitVec2 = self.ProcessUnit:GetVec2() local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y ) - local RouteText = self.ProcessUnit:GetCallSign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." + local RouteText = self.ProcessUnit:GetCallsign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." MESSAGE:New( RouteText, self.DisplayTime, self.DisplayCategory ):ToGroup( self.ProcessUnit:GetGroup() ) end self.DisplayCount = 1 diff --git a/Moose Development/Moose/Set.lua b/Moose Development/Moose/Set.lua index b4f37cfd7..3a4d9a575 100644 --- a/Moose Development/Moose/Set.lua +++ b/Moose Development/Moose/Set.lua @@ -1365,10 +1365,10 @@ function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... ) return self end ---- Returns a comma separated string of the unit types with a count in the @{Set}. +--- Returns map of unit types. -- @param #SET_UNIT self --- @return #string The unit types string -function SET_UNIT:GetUnitTypesText() +-- @return #map<#string,#number> A map of the unit types found. The key is the UnitTypeName and the value is the amount of unit types found. +function SET_UNIT:GetUnitTypes() self:F2() local MT = {} -- Message Text @@ -1391,9 +1391,49 @@ function SET_UNIT:GetUnitTypesText() MT[#MT+1] = UnitType .. " of " .. UnitTypeID end + return UnitTypes +end + + +--- Returns a comma separated string of the unit types with a count in the @{Set}. +-- @param #SET_UNIT self +-- @return #string The unit types string +function SET_UNIT:GetUnitTypesText() + self:F2() + + local MT = {} -- Message Text + local UnitTypes = self:GetUnitTypes() + + for UnitTypeID, UnitType in pairs( UnitTypes ) do + MT[#MT+1] = UnitType .. " of " .. UnitTypeID + end + return table.concat( MT, ", " ) end +--- Returns map of unit threat levels. +-- @param #SET_UNIT self +-- @return #table. +function SET_UNIT:GetUnitThreatLevels() + self:F2() + + local UnitThreatLevels = {} + + for UnitID, UnitData in pairs( self:GetSet() ) do + local ThreatUnit = UnitData -- Unit#UNIT + if ThreatUnit:IsAlive() then + local UnitThreatLevel, UnitThreatLevelText = ThreatUnit:GetThreatLevel() + local ThreatUnitName = ThreatUnit:GetName() + + UnitThreatLevels[UnitThreatLevel] = UnitThreatLevels[UnitThreatLevel] or {} + UnitThreatLevels[UnitThreatLevel].UnitThreatLevelText = UnitThreatLevelText + UnitThreatLevels[UnitThreatLevel].Units = UnitThreatLevels[UnitThreatLevel].Units or {} + UnitThreatLevels[UnitThreatLevel].Units[ThreatUnitName] = ThreatUnit + end + end + + return UnitThreatLevels +end --- Returns if the @{Set} has targets having a radar (of a given type). -- @param #SET_UNIT self diff --git a/Moose Development/Moose/StateMachine.lua b/Moose Development/Moose/StateMachine.lua index 685ce7e18..23ef36db1 100644 --- a/Moose Development/Moose/StateMachine.lua +++ b/Moose Development/Moose/StateMachine.lua @@ -109,7 +109,7 @@ function STATEMACHINE:_create_transition(name) local subtable = self:_gosub( to, name ) for _, sub in pairs( subtable ) do - self:E( "calling sub: " .. sub.event ) + self:F( "calling sub: " .. sub.event ) sub.fsm.fsmparent = self sub.fsm.returnevents = sub.returnevents sub.fsm[sub.event]( sub.fsm ) @@ -118,7 +118,7 @@ function STATEMACHINE:_create_transition(name) local fsmparent, event = self:_isendstate( to ) if fsmparent and event then - self:E( { "end state: ", fsmparent, event } ) + self:F( { "end state: ", fsmparent, event } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) @@ -127,7 +127,7 @@ function STATEMACHINE:_create_transition(name) end if execute then - self:E( { "execute: " .. to, name } ) + self:F( { "execute: " .. to, name } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) diff --git a/Moose Development/Moose/Task_CAS.lua b/Moose Development/Moose/Task_A2G.lua similarity index 69% rename from Moose Development/Moose/Task_CAS.lua rename to Moose Development/Moose/Task_A2G.lua index 95a9341ab..5e026e057 100644 --- a/Moose Development/Moose/Task_CAS.lua +++ b/Moose Development/Moose/Task_A2G.lua @@ -1,9 +1,9 @@ ---- This module contains the TASK_CAS classes. +--- This module contains the TASK_A2G classes. -- --- 1) @{#TASK_CAS} class, extends @{Task#TASK_BASE} +-- 1) @{#TASK_A2G} class, extends @{Task#TASK_BASE} -- ================================================= --- The @{#TASK_CAS} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_CAS is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: +-- The @{#TASK_A2G} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. +-- The TASK_A2G is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: -- -- * **None**: Start of the process -- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. @@ -18,29 +18,31 @@ -- @module Task_CAS -do -- TASK_CAS +do -- TASK_A2G - --- The TASK_CAS class - -- @type TASK_CAS + --- The TASK_A2G class + -- @type TASK_A2G -- @extends Task#TASK_BASE - TASK_CAS = { - ClassName = "TASK_CAS", + TASK_A2G = { + ClassName = "TASK_A2G", } - --- Instantiates a new TASK_CAS. - -- @param #TASK_CAS self + --- Instantiates a new TASK_A2G. + -- @param #TASK_A2G self -- @param Mission#MISSION Mission -- @param 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 TaskType BAI or CAS -- @param Set#SET_UNIT UnitSetTargets -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_CAS self - function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "CAS", "A2G" ) ) + -- @return #TASK_A2G self + function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit ) + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, "A2G" ) ) self:F() self.TargetSetUnit = TargetSetUnit self.TargetZone = TargetZone + self.FACUnit = FACUnit _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) _EVENTDISPATCHER:OnDead( self._EventDead, self ) @@ -50,10 +52,10 @@ do -- TASK_CAS return self end - --- Removes a TASK_CAS. - -- @param #TASK_CAS self + --- Removes a TASK_A2G. + -- @param #TASK_A2G self -- @return #nil - function TASK_CAS:CleanUp() + function TASK_A2G:CleanUp() self:GetParent( self ):CleanUp() @@ -62,16 +64,17 @@ do -- TASK_CAS --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param Unit#UNIT TaskUnit - -- @return #TASK_CAS self - function TASK_CAS:AssignToUnit( TaskUnit ) + -- @return #TASK_A2G self + function TASK_A2G:AssignToUnit( TaskUnit ) self:F( TaskUnit:GetName() ) local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "CAS", TaskUnit, self.TargetSetUnit ) ) + local ProcessDestroy = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, self.TaskType, TaskUnit, self.TargetSetUnit ) ) local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) + local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { initial = 'None', @@ -88,16 +91,17 @@ do -- TASK_CAS onRemove = self.OnRemove, }, subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, + Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } + Destroy = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } }, + Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', }, + JTAC = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessJTAC.Fsm, event = 'Start', }, } } ) ) ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) + ProcessDestroy:AddScore( "Destroy", "destroyed a ground unit", 25 ) + ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 ) Process:Next() @@ -105,26 +109,26 @@ do -- TASK_CAS end --- StateMachine callback function for a TASK - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param StateMachine#STATEMACHINE_TASK Fsm -- @param #string Event -- @param #string From -- @param #string To -- @param Event#EVENTDATA Event - function TASK_CAS:OnNext( Fsm, Event, From, To, Event ) + function TASK_A2G:OnNext( Fsm, Event, From, To, Event ) self:SetState( self, "State", To ) end - --- @param #TASK_CAS self - function TASK_CAS:GetPlannedMenuText() + --- @param #TASK_A2G self + function TASK_A2G:GetPlannedMenuText() return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" end - --- @param #TASK_CAS self - function TASK_CAS:_Schedule() + --- @param #TASK_A2G self + function TASK_A2G:_Schedule() self:F2() self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) @@ -132,8 +136,8 @@ do -- TASK_CAS end - --- @param #TASK_CAS self - function TASK_CAS._Scheduler() + --- @param #TASK_A2G self + function TASK_A2G._Scheduler() self:F2() return true diff --git a/Moose Development/Moose/Task_BAI.lua b/Moose Development/Moose/Task_BAI.lua deleted file mode 100644 index 213f60518..000000000 --- a/Moose Development/Moose/Task_BAI.lua +++ /dev/null @@ -1,145 +0,0 @@ ---- This module contains the TASK_BAI classes. --- --- 1) @{#TASK_BAI} class, extends @{Task#TASK_BASE} --- ================================================= --- The @{#TASK_BAI} class defines a new BAI task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_BAI is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: --- --- * **None**: Start of the process --- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. --- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone. --- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task. --- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. --- --- === --- --- ### Authors: FlightControl - Design and Programming --- --- @module Task_BAI - - -do -- TASK_BAI - - --- The TASK_BAI class - -- @type TASK_BAI - -- @extends Task#TASK_BASE - TASK_BAI = { - ClassName = "TASK_BAI", - } - - --- Instantiates a new TASK_BAI. - -- @param #TASK_BAI self - -- @param Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. - -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT UnitSetTargets - -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_BAI self - function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "BAI", "A2G" ) ) - self:F() - - self.TargetSetUnit = TargetSetUnit - self.TargetZone = TargetZone - - _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) - _EVENTDISPATCHER:OnDead( self._EventDead, self ) - _EVENTDISPATCHER:OnCrash( self._EventDead, self ) - _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) - - return self - end - - --- Removes a TASK_BAI. - -- @param #TASK_BAI self - -- @return #nil - function TASK_BAI:CleanUp() - - self:GetParent( self ):CleanUp() - - return nil - end - - - --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_BAI self - -- @param Unit#UNIT TaskUnit - -- @return #TASK_BAI self - function TASK_BAI:AssignToUnit( TaskUnit ) - self:F( TaskUnit:GetName() ) - - local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) - local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "BAI", TaskUnit, self.TargetSetUnit ) ) - local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) - - local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { - initial = 'None', - events = { - { name = 'Next', from = 'None', to = 'Planned' }, - { name = 'Next', from = 'Planned', to = 'Assigned' }, - { name = 'Reject', from = 'Planned', to = 'Rejected' }, - { name = 'Next', from = 'Assigned', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Arrived', to = 'Failed' } - }, - callbacks = { - onNext = self.OnNext, - onRemove = self.OnRemove, - }, - subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, - Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } - } - } ) ) - - ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - - Process:Next() - - return self - end - - --- StateMachine callback function for a TASK - -- @param #TASK_BAI self - -- @param StateMachine#STATEMACHINE_TASK Fsm - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Event#EVENTDATA Event - function TASK_BAI:OnNext( Fsm, Event, From, To, Event ) - - self:SetState( self, "State", To ) - - end - - --- @param #TASK_BAI self - function TASK_BAI:GetPlannedMenuText() - return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" - end - - - --- @param #TASK_BAI self - function TASK_BAI:_Schedule() - self:F2() - - self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) - return self - end - - - --- @param #TASK_BAI self - function TASK_BAI._Scheduler() - self:F2() - - return true - end - -end - - - diff --git a/Moose Development/Moose/Unit.lua b/Moose Development/Moose/Unit.lua index 223e8476a..3888939af 100644 --- a/Moose Development/Moose/Unit.lua +++ b/Moose Development/Moose/Unit.lua @@ -209,7 +209,7 @@ end -- @param Unit#UNIT self -- @return #string The Callsign of the Unit. -- @return #nil The DCS Unit is not existing or alive. -function UNIT:GetCallSign() +function UNIT:GetCallsign() self:F2( self.UnitName ) local DCSUnit = self:GetDCSObject() @@ -473,6 +473,20 @@ function UNIT:GetThreatLevel() local Attributes = self:GetDesc().attributes local ThreatLevel = 0 + local ThreatLevels = { + "Unarmed", + "Infantry", + "Old Tanks & APCs", + "Tanks & IFVs without ATGM", + "Tanks & IFV with ATGM", + "Modern Tanks", + "AAA", + "IR Guided SAMs", + "SR SAMs", + "MR SAMs", + "LR SAMs" + } + self:T2( Attributes ) if Attributes["LR SAM"] then ThreatLevel = 10 @@ -492,7 +506,7 @@ function UNIT:GetThreatLevel() end self:T2( ThreatLevel ) - return ThreatLevel + return ThreatLevel, ThreatLevels[ThreatLevel+1] end diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua index dc6fc0a37..aa2ae1997 100644 --- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua +++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20160720_1731' ) +env.info( 'Moose Generation Timestamp: 20160721_1527' ) local base = _G Include = {} @@ -6133,7 +6133,7 @@ end -- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #CONTROLLABLE function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) - self:F( { WayPoint, WayPointIndex, WayPointFunction } ) + self:F( { WayPoint, WaitTime } ) if not WayPoint then WayPoint = 1 @@ -6151,6 +6151,123 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end +-- Message APIs + +--- Returns a message with the callsign embedded (if there is one). +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @return Message#MESSAGE +function CONTROLLABLE:GetMessage( Message, Duration ) + self:E( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) + end + + return nil +end + +--- Send a message to all coalitions. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToAll( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToAll() + end + + return nil +end + +--- Send a message to the red coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTYpes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToRed( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToRed() + end + + return nil +end + +--- Send a message to the blue coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToBlue( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToBlue() + end + + return nil +end + +--- Send a message to a client. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Client#CLIENT Client The client object receiving the message. +function CONTROLLABLE:MessageToClient( Message, Duration, Client ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToClient( Client ) + end + + return nil +end + +--- Send a message to a @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Group#GROUP MessageGroup The GROUP object receiving the message. +function CONTROLLABLE:MessageToGroup( Message, Duration, MessageGroup ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + if DCSObject:isExist() then + self:GetMessage( Message, Duration ):ToGroup( MessageGroup ) + end + end + + return nil +end + +--- Send a message to the players in the @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:Message( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToGroup( self ) + end + + return nil +end --- This module contains the SCHEDULER class. -- @@ -8480,123 +8597,6 @@ function GROUP:CopyRoute( Begin, End, Randomize, Radius ) end --- Message APIs - ---- Returns a message for a coalition or a client. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @return Message#MESSAGE -function GROUP:GetMessage( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) - end - - return nil -end - ---- Send a message to all coalitions. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToAll( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToAll() - end - - return nil -end - ---- Send a message to the red coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTYpes#Duration Duration The duration of the message. -function GROUP:MessageToRed( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToRed() - end - - return nil -end - ---- Send a message to the blue coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToBlue( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToBlue() - end - - return nil -end - ---- Send a message to a client. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Client#CLIENT Client The client object receiving the message. -function GROUP:MessageToClient( Message, Duration, Client ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToClient( Client ) - end - - return nil -end - ---- Send a message to a @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Group#GROUP MessageGroup The GROUP object receiving the message. -function GROUP:MessageToGroup( Message, Duration, MsgGroup ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - if DCSGroup:isExist() then - self:GetMessage( Message, Duration ):ToGroup( MsgGroup ) - end - end - - return nil -end - ---- Send a message to the players in the @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:Message( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToGroup( self ) - end - - return nil -end --- This module contains the UNIT class. -- -- 1) @{Unit#UNIT} class, extends @{Controllable#CONTROLLABLE} @@ -8808,7 +8808,7 @@ end -- @param Unit#UNIT self -- @return #string The Callsign of the Unit. -- @return #nil The DCS Unit is not existing or alive. -function UNIT:GetCallSign() +function UNIT:GetCallsign() self:F2( self.UnitName ) local DCSUnit = self:GetDCSObject() @@ -9072,6 +9072,20 @@ function UNIT:GetThreatLevel() local Attributes = self:GetDesc().attributes local ThreatLevel = 0 + local ThreatLevels = { + "Unarmed", + "Infantry", + "Old Tanks & APCs", + "Tanks & IFVs without ATGM", + "Tanks & IFV with ATGM", + "Modern Tanks", + "AAA", + "IR Guided SAMs", + "SR SAMs", + "MR SAMs", + "LR SAMs" + } + self:T2( Attributes ) if Attributes["LR SAM"] then ThreatLevel = 10 @@ -9091,7 +9105,7 @@ function UNIT:GetThreatLevel() end self:T2( ThreatLevel ) - return ThreatLevel + return ThreatLevel, ThreatLevels[ThreatLevel+1] end @@ -9815,8 +9829,8 @@ ZONE_GROUP = { -- @param DCSTypes#Distance Radius The radius of the zone. -- @return #ZONE_GROUP self function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius ) - local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetPointVec2(), Radius ) ) - self:F( { ZoneName, ZoneGROUP:GetPointVec2(), Radius } ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) ) + self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } ) self.ZoneGROUP = ZoneGROUP @@ -9827,14 +9841,14 @@ end --- Returns the current location of the @{Group}. -- @param #ZONE_GROUP self -- @return DCSTypes#Vec2 The location of the zone based on the @{Group} location. -function ZONE_GROUP:GetPointVec2() +function ZONE_GROUP:GetVec2() self:F( self.ZoneName ) - local ZonePointVec2 = self.ZoneGROUP:GetPointVec2() + local ZoneVec2 = self.ZoneGROUP:GetVec2() - self:T( { ZonePointVec2 } ) + self:T( { ZoneVec2 } ) - return ZonePointVec2 + return ZoneVec2 end --- Returns a random location within the zone of the @{Group}. @@ -9844,11 +9858,11 @@ function ZONE_GROUP:GetRandomVec2() self:F( self.ZoneName ) local Point = {} - local PointVec2 = self.ZoneGROUP:GetPointVec2() + local Vec2 = self.ZoneGROUP:GetVec2() local angle = math.random() * math.pi*2; - Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius(); - Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius(); + Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius(); self:T( { Point } ) @@ -12838,10 +12852,10 @@ function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... ) return self end ---- Returns a comma separated string of the unit types with a count in the @{Set}. +--- Returns map of unit types. -- @param #SET_UNIT self --- @return #string The unit types string -function SET_UNIT:GetUnitTypesText() +-- @return #map<#string,#number> A map of the unit types found. The key is the UnitTypeName and the value is the amount of unit types found. +function SET_UNIT:GetUnitTypes() self:F2() local MT = {} -- Message Text @@ -12864,9 +12878,49 @@ function SET_UNIT:GetUnitTypesText() MT[#MT+1] = UnitType .. " of " .. UnitTypeID end + return UnitTypes +end + + +--- Returns a comma separated string of the unit types with a count in the @{Set}. +-- @param #SET_UNIT self +-- @return #string The unit types string +function SET_UNIT:GetUnitTypesText() + self:F2() + + local MT = {} -- Message Text + local UnitTypes = self:GetUnitTypes() + + for UnitTypeID, UnitType in pairs( UnitTypes ) do + MT[#MT+1] = UnitType .. " of " .. UnitTypeID + end + return table.concat( MT, ", " ) end +--- Returns map of unit threat levels. +-- @param #SET_UNIT self +-- @return #table. +function SET_UNIT:GetUnitThreatLevels() + self:F2() + + local UnitThreatLevels = {} + + for UnitID, UnitData in pairs( self:GetSet() ) do + local ThreatUnit = UnitData -- Unit#UNIT + if ThreatUnit:IsAlive() then + local UnitThreatLevel, UnitThreatLevelText = ThreatUnit:GetThreatLevel() + local ThreatUnitName = ThreatUnit:GetName() + + UnitThreatLevels[UnitThreatLevel] = UnitThreatLevels[UnitThreatLevel] or {} + UnitThreatLevels[UnitThreatLevel].UnitThreatLevelText = UnitThreatLevelText + UnitThreatLevels[UnitThreatLevel].Units = UnitThreatLevels[UnitThreatLevel].Units or {} + UnitThreatLevels[UnitThreatLevel].Units[ThreatUnitName] = ThreatUnit + end + end + + return UnitThreatLevels +end --- Returns if the @{Set} has targets having a radar (of a given type). -- @param #SET_UNIT self @@ -13770,6 +13824,18 @@ function POINT_VEC3:New( x, y, z ) return self end +--- Create a new POINT_VEC3 object from Vec3 coordinates. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Vec3 Vec3 The Vec3 point. +-- @return Point#POINT_VEC3 self +function POINT_VEC3:NewFromVec3( Vec3 ) + + local self = BASE:Inherit( self, BASE:New() ) + self.PointVec3 = Vec3 + self:F2( self.PointVec3 ) + return self +end + --- Return the coordinates of the POINT_VEC3 in Vec3 format. -- @param #POINT_VEC3 self @@ -14174,11 +14240,11 @@ Include.File( "Process_Assign" ) Include.File( "Process_Route" ) Include.File( "Process_Smoke" ) Include.File( "Process_Destroy" ) +Include.File( "Process_JTAC" ) Include.File( "Task" ) Include.File( "Task_SEAD" ) -Include.File( "Task_CAS" ) -Include.File( "Task_BAI" ) +Include.File( "Task_A2G" ) -- The order of the declarations is important here. Don't touch it. @@ -25489,6 +25555,7 @@ DETECTION_AREAS = { -- @field #table Changes A list of the changes reported on the detected area. (It is up to the user of the detected area to consume those changes). -- @field #number AreaID -- The identifier of the detected area. -- @field #boolean FriendliesNearBy Indicates if there are friendlies within the detected area. +-- @field Unit#UNIT NearestFAC The nearest FAC near the Area. --- DETECTION_AREAS constructor. @@ -25676,6 +25743,36 @@ function DETECTION_AREAS:CalculateThreatLevelA2G( DetectedArea ) end +--- Find the nearest FAC of the DetectedArea. +-- @param #DETECTION_AREAS self +-- @param #DETECTION_AREAS.DetectedArea DetectedArea +-- @return Unit#UNIT The nearest FAC unit +function DETECTION_AREAS:NearestFAC( DetectedArea ) + + local NearestFAC = nil + local MinDistance = 1000000000 -- Units are not further than 1000000 km away from an area :-) + + for FACGroupName, FACGroupData in pairs( self.DetectionSetGroup:GetSet() ) do + for FACUnit, FACUnitData in pairs( FACGroupData:GetUnits() ) do + local FACUnit = FACUnitData -- Unit#UNIT + if FACUnit:IsActive() then + local Vec3 = FACUnit:GetPointVec3() + local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) + local Distance = PointVec3:Get2DDistance(POINT_VEC3:NewFromVec3( FACUnit:GetPointVec3() ) ) + self:E( "Distance", Distance ) + if Distance < MinDistance then + MinDistance = Distance + NearestFAC = FACUnit + end + end + end + end + + self:E( { NearestFAC.UnitName, MinDistance } ) + DetectedArea.NearestFAC = NearestFAC + +end + --- Returns the A2G threat level of the units in the DetectedArea -- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS.DetectedArea DetectedArea @@ -26001,6 +26098,7 @@ function DETECTION_AREAS:CreateDetectionSets() self:ReportFriendliesNearBy( { DetectedArea = DetectedArea, ReportSetGroup = self.DetectionSetGroup } ) -- Fill the Friendlies table self:CalculateThreatLevelA2G( DetectedArea ) -- Calculate A2G threat level + self:NearestFAC( DetectedArea ) if DETECTION_AREAS._SmokeDetectedUnits or self._SmokeDetectedUnits then DetectedZone.ZoneUNIT:SmokeRed() @@ -26466,7 +26564,7 @@ do -- DETECTION_DISPATCHER if not CASTask then local TargetSetUnit = self:EvaluateCAS( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - CASTask = Mission:AddTask( TASK_CAS:New( Mission, self.SetGroup, "CAS." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if CASTask and CASTask:IsStatePlanned() then @@ -26480,7 +26578,7 @@ do -- DETECTION_DISPATCHER if not BAITask then local TargetSetUnit = self:EvaluateBAI( DetectedArea, self.CommandCenter:GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - BAITask = Mission:AddTask( TASK_BAI:New( Mission, self.SetGroup, "BAI." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if BAITask and BAITask:IsStatePlanned() then @@ -26644,7 +26742,7 @@ function STATEMACHINE:_create_transition(name) local subtable = self:_gosub( to, name ) for _, sub in pairs( subtable ) do - self:E( "calling sub: " .. sub.event ) + self:F( "calling sub: " .. sub.event ) sub.fsm.fsmparent = self sub.fsm.returnevents = sub.returnevents sub.fsm[sub.event]( sub.fsm ) @@ -26653,7 +26751,7 @@ function STATEMACHINE:_create_transition(name) local fsmparent, event = self:_isendstate( to ) if fsmparent and event then - self:E( { "end state: ", fsmparent, event } ) + self:F( { "end state: ", fsmparent, event } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) @@ -26662,7 +26760,7 @@ function STATEMACHINE:_create_transition(name) end if execute then - self:E( { "execute: " .. to, name } ) + self:F( { "execute: " .. to, name } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) @@ -26822,7 +26920,9 @@ end -- @type PROCESS -- @field Scheduler#SCHEDULER ProcessScheduler -- @field Unit#UNIT ProcessUnit --- @field Task#TASK Task +-- @field Group#GROUP ProcessGroup +-- @field Menu#MENU_GROUP MissionMenu +-- @field Task#TASK_BASE Task -- @field StateMachine#STATEMACHINE_TASK Fsm -- @field #string ProcessName -- @extends Base#BASE @@ -26844,6 +26944,8 @@ function PROCESS:New( ProcessName, Task, ProcessUnit ) self:F() self.ProcessUnit = ProcessUnit + self.ProcessGroup = ProcessUnit:GetGroup() + self.MissionMenu = Task.Mission:GetMissionMenu( self.ProcessGroup ) self.Task = Task self.ProcessName = ProcessName @@ -26854,9 +26956,8 @@ end --- @param #PROCESS self function PROCESS:NextEvent( NextEvent, ... ) - self:F2( arg ) if self.AllowEvents == true then - self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, { self, self.ProcessUnit, unpack( arg ) }, 1 ) + self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, arg, 1 ) end end @@ -26893,7 +26994,7 @@ end -- @param #string From -- @param #string To function PROCESS:OnStateChange( Fsm, Event, From, To ) - self:E( { Event, From, To, self.ProcessUnit.UnitName } ) + self:E( { self.ProcessName, Event, From, To, self.ProcessUnit.UnitName } ) if self:IsTrace() then MESSAGE:New( "Process " .. self.ProcessName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll() @@ -27161,7 +27262,7 @@ function PROCESS_ROUTE:OnLeaveUnArrived( Fsm, Event, From, To ) local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y ) local TaskUnitVec2 = self.ProcessUnit:GetVec2() local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y ) - local RouteText = self.ProcessUnit:GetCallSign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." + local RouteText = self.ProcessUnit:GetCallsign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." MESSAGE:New( RouteText, self.DisplayTime, self.DisplayCategory ):ToGroup( self.ProcessUnit:GetGroup() ) end self.DisplayCount = 1 @@ -27465,6 +27566,205 @@ function PROCESS_DESTROY:EventDead( Event ) end +--- @module Process_JTAC + +--- PROCESS_JTAC class +-- @type PROCESS_JTAC +-- @field Unit#UNIT ProcessUnit +-- @field Set#SET_UNIT TargetSetUnit +-- @extends Process#PROCESS +PROCESS_JTAC = { + ClassName = "PROCESS_JTAC", + Fsm = {}, + TargetSetUnit = nil, +} + + +--- Creates a new DESTROY process. +-- @param #PROCESS_JTAC self +-- @param Task#TASK Task +-- @param Unit#UNIT ProcessUnit +-- @param Set#SET_UNIT TargetSetUnit +-- @param 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 = STATEMACHINE_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' } + } ) + + + _EVENTDISPATCHER:OnDead( self.EventDead, self ) + + return self +end + +--- Process Events + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnStart( Fsm, Event, From, To ) + + self:NextEvent( Fsm.JTACMenuUpdate ) +end + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuUpdate( Fsm, Event, From, To ) + + local function JTACMenuSpot( MenuParam ) + self:E( MenuParam.TargetUnit.UnitName ) + local self = MenuParam.self + local TargetUnit = MenuParam.TargetUnit + + self:NextEvent( self.Fsm.JTACMenuSpot, TargetUnit ) + end + + local function JTACMenuCancel( MenuParam ) + self:E( 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:E( {"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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuAwait( Fsm, Event, From, To ) + + if self.DisplayCount >= self.DisplayInterval then + + local TaskJTAC = self.Task -- 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuSpot( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- Task#TASK_JTAC + + TaskJTAC.Spots = TaskJTAC.Spots or {} + TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {} + + local DCSFACObject = self.FACUnit:GetDCSObject() + local TargetVec3 = TargetUnit:GetPointVec3() + + TaskJTAC.Spots[TargetUnitName] = Spot.createInfraRed( self.FACUnit:GetDCSObject(), { x = 0, y = 1, z = 0 }, TargetUnit:GetPointVec3(), 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuCancel( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- 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 + + --- This module contains the TASK_BASE class. -- -- 1) @{#TASK_BASE} class, extends @{Base#BASE} @@ -28475,12 +28775,12 @@ do -- TASK_SEAD end end ---- This module contains the TASK_CAS classes. +--- This module contains the TASK_A2G classes. -- --- 1) @{#TASK_CAS} class, extends @{Task#TASK_BASE} +-- 1) @{#TASK_A2G} class, extends @{Task#TASK_BASE} -- ================================================= --- The @{#TASK_CAS} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_CAS is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: +-- The @{#TASK_A2G} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. +-- The TASK_A2G is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: -- -- * **None**: Start of the process -- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. @@ -28495,29 +28795,31 @@ end -- @module Task_CAS -do -- TASK_CAS +do -- TASK_A2G - --- The TASK_CAS class - -- @type TASK_CAS + --- The TASK_A2G class + -- @type TASK_A2G -- @extends Task#TASK_BASE - TASK_CAS = { - ClassName = "TASK_CAS", + TASK_A2G = { + ClassName = "TASK_A2G", } - --- Instantiates a new TASK_CAS. - -- @param #TASK_CAS self + --- Instantiates a new TASK_A2G. + -- @param #TASK_A2G self -- @param Mission#MISSION Mission -- @param 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 TaskType BAI or CAS -- @param Set#SET_UNIT UnitSetTargets -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_CAS self - function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "CAS", "A2G" ) ) + -- @return #TASK_A2G self + function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit ) + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, "A2G" ) ) self:F() self.TargetSetUnit = TargetSetUnit self.TargetZone = TargetZone + self.FACUnit = FACUnit _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) _EVENTDISPATCHER:OnDead( self._EventDead, self ) @@ -28527,10 +28829,10 @@ do -- TASK_CAS return self end - --- Removes a TASK_CAS. - -- @param #TASK_CAS self + --- Removes a TASK_A2G. + -- @param #TASK_A2G self -- @return #nil - function TASK_CAS:CleanUp() + function TASK_A2G:CleanUp() self:GetParent( self ):CleanUp() @@ -28539,16 +28841,17 @@ do -- TASK_CAS --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param Unit#UNIT TaskUnit - -- @return #TASK_CAS self - function TASK_CAS:AssignToUnit( TaskUnit ) + -- @return #TASK_A2G self + function TASK_A2G:AssignToUnit( TaskUnit ) self:F( TaskUnit:GetName() ) local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "CAS", TaskUnit, self.TargetSetUnit ) ) + local ProcessDestroy = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, self.TaskType, TaskUnit, self.TargetSetUnit ) ) local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) + local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { initial = 'None', @@ -28565,16 +28868,17 @@ do -- TASK_CAS onRemove = self.OnRemove, }, subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, + Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } + Destroy = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } }, + Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', }, + JTAC = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessJTAC.Fsm, event = 'Start', }, } } ) ) ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) + ProcessDestroy:AddScore( "Destroy", "destroyed a ground unit", 25 ) + ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 ) Process:Next() @@ -28582,26 +28886,26 @@ do -- TASK_CAS end --- StateMachine callback function for a TASK - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param StateMachine#STATEMACHINE_TASK Fsm -- @param #string Event -- @param #string From -- @param #string To -- @param Event#EVENTDATA Event - function TASK_CAS:OnNext( Fsm, Event, From, To, Event ) + function TASK_A2G:OnNext( Fsm, Event, From, To, Event ) self:SetState( self, "State", To ) end - --- @param #TASK_CAS self - function TASK_CAS:GetPlannedMenuText() + --- @param #TASK_A2G self + function TASK_A2G:GetPlannedMenuText() return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" end - --- @param #TASK_CAS self - function TASK_CAS:_Schedule() + --- @param #TASK_A2G self + function TASK_A2G:_Schedule() self:F2() self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) @@ -28609,153 +28913,8 @@ do -- TASK_CAS end - --- @param #TASK_CAS self - function TASK_CAS._Scheduler() - self:F2() - - return true - end - -end - - - ---- This module contains the TASK_BAI classes. --- --- 1) @{#TASK_BAI} class, extends @{Task#TASK_BASE} --- ================================================= --- The @{#TASK_BAI} class defines a new BAI task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_BAI is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: --- --- * **None**: Start of the process --- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. --- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone. --- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task. --- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. --- --- === --- --- ### Authors: FlightControl - Design and Programming --- --- @module Task_BAI - - -do -- TASK_BAI - - --- The TASK_BAI class - -- @type TASK_BAI - -- @extends Task#TASK_BASE - TASK_BAI = { - ClassName = "TASK_BAI", - } - - --- Instantiates a new TASK_BAI. - -- @param #TASK_BAI self - -- @param Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. - -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT UnitSetTargets - -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_BAI self - function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "BAI", "A2G" ) ) - self:F() - - self.TargetSetUnit = TargetSetUnit - self.TargetZone = TargetZone - - _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) - _EVENTDISPATCHER:OnDead( self._EventDead, self ) - _EVENTDISPATCHER:OnCrash( self._EventDead, self ) - _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) - - return self - end - - --- Removes a TASK_BAI. - -- @param #TASK_BAI self - -- @return #nil - function TASK_BAI:CleanUp() - - self:GetParent( self ):CleanUp() - - return nil - end - - - --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_BAI self - -- @param Unit#UNIT TaskUnit - -- @return #TASK_BAI self - function TASK_BAI:AssignToUnit( TaskUnit ) - self:F( TaskUnit:GetName() ) - - local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) - local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "BAI", TaskUnit, self.TargetSetUnit ) ) - local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) - - local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { - initial = 'None', - events = { - { name = 'Next', from = 'None', to = 'Planned' }, - { name = 'Next', from = 'Planned', to = 'Assigned' }, - { name = 'Reject', from = 'Planned', to = 'Rejected' }, - { name = 'Next', from = 'Assigned', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Arrived', to = 'Failed' } - }, - callbacks = { - onNext = self.OnNext, - onRemove = self.OnRemove, - }, - subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, - Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } - } - } ) ) - - ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - - Process:Next() - - return self - end - - --- StateMachine callback function for a TASK - -- @param #TASK_BAI self - -- @param StateMachine#STATEMACHINE_TASK Fsm - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Event#EVENTDATA Event - function TASK_BAI:OnNext( Fsm, Event, From, To, Event ) - - self:SetState( self, "State", To ) - - end - - --- @param #TASK_BAI self - function TASK_BAI:GetPlannedMenuText() - return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" - end - - - --- @param #TASK_BAI self - function TASK_BAI:_Schedule() - self:F2() - - self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) - return self - end - - - --- @param #TASK_BAI self - function TASK_BAI._Scheduler() + --- @param #TASK_A2G self + function TASK_A2G._Scheduler() self:F2() return true diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index dc6fc0a37..aa2ae1997 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20160720_1731' ) +env.info( 'Moose Generation Timestamp: 20160721_1527' ) local base = _G Include = {} @@ -6133,7 +6133,7 @@ end -- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #CONTROLLABLE function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) - self:F( { WayPoint, WayPointIndex, WayPointFunction } ) + self:F( { WayPoint, WaitTime } ) if not WayPoint then WayPoint = 1 @@ -6151,6 +6151,123 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end +-- Message APIs + +--- Returns a message with the callsign embedded (if there is one). +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @return Message#MESSAGE +function CONTROLLABLE:GetMessage( Message, Duration ) + self:E( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) + end + + return nil +end + +--- Send a message to all coalitions. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToAll( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToAll() + end + + return nil +end + +--- Send a message to the red coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTYpes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToRed( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToRed() + end + + return nil +end + +--- Send a message to the blue coalition. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:MessageToBlue( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToBlue() + end + + return nil +end + +--- Send a message to a client. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Client#CLIENT Client The client object receiving the message. +function CONTROLLABLE:MessageToClient( Message, Duration, Client ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToClient( Client ) + end + + return nil +end + +--- Send a message to a @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +-- @param Group#GROUP MessageGroup The GROUP object receiving the message. +function CONTROLLABLE:MessageToGroup( Message, Duration, MessageGroup ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + if DCSObject:isExist() then + self:GetMessage( Message, Duration ):ToGroup( MessageGroup ) + end + end + + return nil +end + +--- Send a message to the players in the @{Group}. +-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. +-- @param #CONTROLLABLE self +-- @param #string Message The message text +-- @param DCSTypes#Duration Duration The duration of the message. +function CONTROLLABLE:Message( Message, Duration ) + self:F2( { Message, Duration } ) + + local DCSObject = self:GetDCSObject() + if DCSObject then + self:GetMessage( Message, Duration ):ToGroup( self ) + end + + return nil +end --- This module contains the SCHEDULER class. -- @@ -8480,123 +8597,6 @@ function GROUP:CopyRoute( Begin, End, Randomize, Radius ) end --- Message APIs - ---- Returns a message for a coalition or a client. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @return Message#MESSAGE -function GROUP:GetMessage( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")" ) - end - - return nil -end - ---- Send a message to all coalitions. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToAll( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToAll() - end - - return nil -end - ---- Send a message to the red coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTYpes#Duration Duration The duration of the message. -function GROUP:MessageToRed( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToRed() - end - - return nil -end - ---- Send a message to the blue coalition. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:MessageToBlue( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToBlue() - end - - return nil -end - ---- Send a message to a client. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Client#CLIENT Client The client object receiving the message. -function GROUP:MessageToClient( Message, Duration, Client ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToClient( Client ) - end - - return nil -end - ---- Send a message to a @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. --- @param Group#GROUP MessageGroup The GROUP object receiving the message. -function GROUP:MessageToGroup( Message, Duration, MsgGroup ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - if DCSGroup:isExist() then - self:GetMessage( Message, Duration ):ToGroup( MsgGroup ) - end - end - - return nil -end - ---- Send a message to the players in the @{Group}. --- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. --- @param #GROUP self --- @param #string Message The message text --- @param DCSTypes#Duration Duration The duration of the message. -function GROUP:Message( Message, Duration ) - self:F2( { Message, Duration } ) - - local DCSGroup = self:GetDCSObject() - if DCSGroup then - self:GetMessage( Message, Duration ):ToGroup( self ) - end - - return nil -end --- This module contains the UNIT class. -- -- 1) @{Unit#UNIT} class, extends @{Controllable#CONTROLLABLE} @@ -8808,7 +8808,7 @@ end -- @param Unit#UNIT self -- @return #string The Callsign of the Unit. -- @return #nil The DCS Unit is not existing or alive. -function UNIT:GetCallSign() +function UNIT:GetCallsign() self:F2( self.UnitName ) local DCSUnit = self:GetDCSObject() @@ -9072,6 +9072,20 @@ function UNIT:GetThreatLevel() local Attributes = self:GetDesc().attributes local ThreatLevel = 0 + local ThreatLevels = { + "Unarmed", + "Infantry", + "Old Tanks & APCs", + "Tanks & IFVs without ATGM", + "Tanks & IFV with ATGM", + "Modern Tanks", + "AAA", + "IR Guided SAMs", + "SR SAMs", + "MR SAMs", + "LR SAMs" + } + self:T2( Attributes ) if Attributes["LR SAM"] then ThreatLevel = 10 @@ -9091,7 +9105,7 @@ function UNIT:GetThreatLevel() end self:T2( ThreatLevel ) - return ThreatLevel + return ThreatLevel, ThreatLevels[ThreatLevel+1] end @@ -9815,8 +9829,8 @@ ZONE_GROUP = { -- @param DCSTypes#Distance Radius The radius of the zone. -- @return #ZONE_GROUP self function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius ) - local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetPointVec2(), Radius ) ) - self:F( { ZoneName, ZoneGROUP:GetPointVec2(), Radius } ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) ) + self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } ) self.ZoneGROUP = ZoneGROUP @@ -9827,14 +9841,14 @@ end --- Returns the current location of the @{Group}. -- @param #ZONE_GROUP self -- @return DCSTypes#Vec2 The location of the zone based on the @{Group} location. -function ZONE_GROUP:GetPointVec2() +function ZONE_GROUP:GetVec2() self:F( self.ZoneName ) - local ZonePointVec2 = self.ZoneGROUP:GetPointVec2() + local ZoneVec2 = self.ZoneGROUP:GetVec2() - self:T( { ZonePointVec2 } ) + self:T( { ZoneVec2 } ) - return ZonePointVec2 + return ZoneVec2 end --- Returns a random location within the zone of the @{Group}. @@ -9844,11 +9858,11 @@ function ZONE_GROUP:GetRandomVec2() self:F( self.ZoneName ) local Point = {} - local PointVec2 = self.ZoneGROUP:GetPointVec2() + local Vec2 = self.ZoneGROUP:GetVec2() local angle = math.random() * math.pi*2; - Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius(); - Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius(); + Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius(); self:T( { Point } ) @@ -12838,10 +12852,10 @@ function SET_UNIT:ForEachUnitNotInZone( ZoneObject, IteratorFunction, ... ) return self end ---- Returns a comma separated string of the unit types with a count in the @{Set}. +--- Returns map of unit types. -- @param #SET_UNIT self --- @return #string The unit types string -function SET_UNIT:GetUnitTypesText() +-- @return #map<#string,#number> A map of the unit types found. The key is the UnitTypeName and the value is the amount of unit types found. +function SET_UNIT:GetUnitTypes() self:F2() local MT = {} -- Message Text @@ -12864,9 +12878,49 @@ function SET_UNIT:GetUnitTypesText() MT[#MT+1] = UnitType .. " of " .. UnitTypeID end + return UnitTypes +end + + +--- Returns a comma separated string of the unit types with a count in the @{Set}. +-- @param #SET_UNIT self +-- @return #string The unit types string +function SET_UNIT:GetUnitTypesText() + self:F2() + + local MT = {} -- Message Text + local UnitTypes = self:GetUnitTypes() + + for UnitTypeID, UnitType in pairs( UnitTypes ) do + MT[#MT+1] = UnitType .. " of " .. UnitTypeID + end + return table.concat( MT, ", " ) end +--- Returns map of unit threat levels. +-- @param #SET_UNIT self +-- @return #table. +function SET_UNIT:GetUnitThreatLevels() + self:F2() + + local UnitThreatLevels = {} + + for UnitID, UnitData in pairs( self:GetSet() ) do + local ThreatUnit = UnitData -- Unit#UNIT + if ThreatUnit:IsAlive() then + local UnitThreatLevel, UnitThreatLevelText = ThreatUnit:GetThreatLevel() + local ThreatUnitName = ThreatUnit:GetName() + + UnitThreatLevels[UnitThreatLevel] = UnitThreatLevels[UnitThreatLevel] or {} + UnitThreatLevels[UnitThreatLevel].UnitThreatLevelText = UnitThreatLevelText + UnitThreatLevels[UnitThreatLevel].Units = UnitThreatLevels[UnitThreatLevel].Units or {} + UnitThreatLevels[UnitThreatLevel].Units[ThreatUnitName] = ThreatUnit + end + end + + return UnitThreatLevels +end --- Returns if the @{Set} has targets having a radar (of a given type). -- @param #SET_UNIT self @@ -13770,6 +13824,18 @@ function POINT_VEC3:New( x, y, z ) return self end +--- Create a new POINT_VEC3 object from Vec3 coordinates. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Vec3 Vec3 The Vec3 point. +-- @return Point#POINT_VEC3 self +function POINT_VEC3:NewFromVec3( Vec3 ) + + local self = BASE:Inherit( self, BASE:New() ) + self.PointVec3 = Vec3 + self:F2( self.PointVec3 ) + return self +end + --- Return the coordinates of the POINT_VEC3 in Vec3 format. -- @param #POINT_VEC3 self @@ -14174,11 +14240,11 @@ Include.File( "Process_Assign" ) Include.File( "Process_Route" ) Include.File( "Process_Smoke" ) Include.File( "Process_Destroy" ) +Include.File( "Process_JTAC" ) Include.File( "Task" ) Include.File( "Task_SEAD" ) -Include.File( "Task_CAS" ) -Include.File( "Task_BAI" ) +Include.File( "Task_A2G" ) -- The order of the declarations is important here. Don't touch it. @@ -25489,6 +25555,7 @@ DETECTION_AREAS = { -- @field #table Changes A list of the changes reported on the detected area. (It is up to the user of the detected area to consume those changes). -- @field #number AreaID -- The identifier of the detected area. -- @field #boolean FriendliesNearBy Indicates if there are friendlies within the detected area. +-- @field Unit#UNIT NearestFAC The nearest FAC near the Area. --- DETECTION_AREAS constructor. @@ -25676,6 +25743,36 @@ function DETECTION_AREAS:CalculateThreatLevelA2G( DetectedArea ) end +--- Find the nearest FAC of the DetectedArea. +-- @param #DETECTION_AREAS self +-- @param #DETECTION_AREAS.DetectedArea DetectedArea +-- @return Unit#UNIT The nearest FAC unit +function DETECTION_AREAS:NearestFAC( DetectedArea ) + + local NearestFAC = nil + local MinDistance = 1000000000 -- Units are not further than 1000000 km away from an area :-) + + for FACGroupName, FACGroupData in pairs( self.DetectionSetGroup:GetSet() ) do + for FACUnit, FACUnitData in pairs( FACGroupData:GetUnits() ) do + local FACUnit = FACUnitData -- Unit#UNIT + if FACUnit:IsActive() then + local Vec3 = FACUnit:GetPointVec3() + local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) + local Distance = PointVec3:Get2DDistance(POINT_VEC3:NewFromVec3( FACUnit:GetPointVec3() ) ) + self:E( "Distance", Distance ) + if Distance < MinDistance then + MinDistance = Distance + NearestFAC = FACUnit + end + end + end + end + + self:E( { NearestFAC.UnitName, MinDistance } ) + DetectedArea.NearestFAC = NearestFAC + +end + --- Returns the A2G threat level of the units in the DetectedArea -- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS.DetectedArea DetectedArea @@ -26001,6 +26098,7 @@ function DETECTION_AREAS:CreateDetectionSets() self:ReportFriendliesNearBy( { DetectedArea = DetectedArea, ReportSetGroup = self.DetectionSetGroup } ) -- Fill the Friendlies table self:CalculateThreatLevelA2G( DetectedArea ) -- Calculate A2G threat level + self:NearestFAC( DetectedArea ) if DETECTION_AREAS._SmokeDetectedUnits or self._SmokeDetectedUnits then DetectedZone.ZoneUNIT:SmokeRed() @@ -26466,7 +26564,7 @@ do -- DETECTION_DISPATCHER if not CASTask then local TargetSetUnit = self:EvaluateCAS( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - CASTask = Mission:AddTask( TASK_CAS:New( Mission, self.SetGroup, "CAS." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + CASTask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if CASTask and CASTask:IsStatePlanned() then @@ -26480,7 +26578,7 @@ do -- DETECTION_DISPATCHER if not BAITask then local TargetSetUnit = self:EvaluateBAI( DetectedArea, self.CommandCenter:GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed... if TargetSetUnit then - BAITask = Mission:AddTask( TASK_BAI:New( Mission, self.SetGroup, "BAI." .. AreaID, TargetSetUnit , DetectedZone ) ):StatePlanned() + BAITask = Mission:AddTask( TASK_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) ):StatePlanned() end end if BAITask and BAITask:IsStatePlanned() then @@ -26644,7 +26742,7 @@ function STATEMACHINE:_create_transition(name) local subtable = self:_gosub( to, name ) for _, sub in pairs( subtable ) do - self:E( "calling sub: " .. sub.event ) + self:F( "calling sub: " .. sub.event ) sub.fsm.fsmparent = self sub.fsm.returnevents = sub.returnevents sub.fsm[sub.event]( sub.fsm ) @@ -26653,7 +26751,7 @@ function STATEMACHINE:_create_transition(name) local fsmparent, event = self:_isendstate( to ) if fsmparent and event then - self:E( { "end state: ", fsmparent, event } ) + self:F( { "end state: ", fsmparent, event } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) @@ -26662,7 +26760,7 @@ function STATEMACHINE:_create_transition(name) end if execute then - self:E( { "execute: " .. to, name } ) + self:F( { "execute: " .. to, name } ) self:_call_handler(self["onenter" .. to] or self["on" .. to], params) self:_call_handler(self["onafter" .. name] or self["on" .. name], params) self:_call_handler(self["onstatechange"], params) @@ -26822,7 +26920,9 @@ end -- @type PROCESS -- @field Scheduler#SCHEDULER ProcessScheduler -- @field Unit#UNIT ProcessUnit --- @field Task#TASK Task +-- @field Group#GROUP ProcessGroup +-- @field Menu#MENU_GROUP MissionMenu +-- @field Task#TASK_BASE Task -- @field StateMachine#STATEMACHINE_TASK Fsm -- @field #string ProcessName -- @extends Base#BASE @@ -26844,6 +26944,8 @@ function PROCESS:New( ProcessName, Task, ProcessUnit ) self:F() self.ProcessUnit = ProcessUnit + self.ProcessGroup = ProcessUnit:GetGroup() + self.MissionMenu = Task.Mission:GetMissionMenu( self.ProcessGroup ) self.Task = Task self.ProcessName = ProcessName @@ -26854,9 +26956,8 @@ end --- @param #PROCESS self function PROCESS:NextEvent( NextEvent, ... ) - self:F2( arg ) if self.AllowEvents == true then - self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, { self, self.ProcessUnit, unpack( arg ) }, 1 ) + self.ProcessScheduler = SCHEDULER:New( self.Fsm, NextEvent, arg, 1 ) end end @@ -26893,7 +26994,7 @@ end -- @param #string From -- @param #string To function PROCESS:OnStateChange( Fsm, Event, From, To ) - self:E( { Event, From, To, self.ProcessUnit.UnitName } ) + self:E( { self.ProcessName, Event, From, To, self.ProcessUnit.UnitName } ) if self:IsTrace() then MESSAGE:New( "Process " .. self.ProcessName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll() @@ -27161,7 +27262,7 @@ function PROCESS_ROUTE:OnLeaveUnArrived( Fsm, Event, From, To ) local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y ) local TaskUnitVec2 = self.ProcessUnit:GetVec2() local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y ) - local RouteText = self.ProcessUnit:GetCallSign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." + local RouteText = self.ProcessUnit:GetCallsign() .. ": Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target." MESSAGE:New( RouteText, self.DisplayTime, self.DisplayCategory ):ToGroup( self.ProcessUnit:GetGroup() ) end self.DisplayCount = 1 @@ -27465,6 +27566,205 @@ function PROCESS_DESTROY:EventDead( Event ) end +--- @module Process_JTAC + +--- PROCESS_JTAC class +-- @type PROCESS_JTAC +-- @field Unit#UNIT ProcessUnit +-- @field Set#SET_UNIT TargetSetUnit +-- @extends Process#PROCESS +PROCESS_JTAC = { + ClassName = "PROCESS_JTAC", + Fsm = {}, + TargetSetUnit = nil, +} + + +--- Creates a new DESTROY process. +-- @param #PROCESS_JTAC self +-- @param Task#TASK Task +-- @param Unit#UNIT ProcessUnit +-- @param Set#SET_UNIT TargetSetUnit +-- @param 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 = STATEMACHINE_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' } + } ) + + + _EVENTDISPATCHER:OnDead( self.EventDead, self ) + + return self +end + +--- Process Events + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnStart( Fsm, Event, From, To ) + + self:NextEvent( Fsm.JTACMenuUpdate ) +end + +--- StateMachine callback function for a PROCESS +-- @param #PROCESS_JTAC self +-- @param StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuUpdate( Fsm, Event, From, To ) + + local function JTACMenuSpot( MenuParam ) + self:E( MenuParam.TargetUnit.UnitName ) + local self = MenuParam.self + local TargetUnit = MenuParam.TargetUnit + + self:NextEvent( self.Fsm.JTACMenuSpot, TargetUnit ) + end + + local function JTACMenuCancel( MenuParam ) + self:E( 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:E( {"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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function PROCESS_JTAC:OnJTACMenuAwait( Fsm, Event, From, To ) + + if self.DisplayCount >= self.DisplayInterval then + + local TaskJTAC = self.Task -- 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuSpot( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- Task#TASK_JTAC + + TaskJTAC.Spots = TaskJTAC.Spots or {} + TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {} + + local DCSFACObject = self.FACUnit:GetDCSObject() + local TargetVec3 = TargetUnit:GetPointVec3() + + TaskJTAC.Spots[TargetUnitName] = Spot.createInfraRed( self.FACUnit:GetDCSObject(), { x = 0, y = 1, z = 0 }, TargetUnit:GetPointVec3(), 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 StateMachine#STATEMACHINE_PROCESS Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT TargetUnit +function PROCESS_JTAC:OnJTACMenuCancel( Fsm, Event, From, To, TargetUnit ) + + local TargetUnitName = TargetUnit:GetName() + + local TaskJTAC = self.Task -- 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 + + --- This module contains the TASK_BASE class. -- -- 1) @{#TASK_BASE} class, extends @{Base#BASE} @@ -28475,12 +28775,12 @@ do -- TASK_SEAD end end ---- This module contains the TASK_CAS classes. +--- This module contains the TASK_A2G classes. -- --- 1) @{#TASK_CAS} class, extends @{Task#TASK_BASE} +-- 1) @{#TASK_A2G} class, extends @{Task#TASK_BASE} -- ================================================= --- The @{#TASK_CAS} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_CAS is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: +-- The @{#TASK_A2G} class defines a new CAS task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. +-- The TASK_A2G is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: -- -- * **None**: Start of the process -- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. @@ -28495,29 +28795,31 @@ end -- @module Task_CAS -do -- TASK_CAS +do -- TASK_A2G - --- The TASK_CAS class - -- @type TASK_CAS + --- The TASK_A2G class + -- @type TASK_A2G -- @extends Task#TASK_BASE - TASK_CAS = { - ClassName = "TASK_CAS", + TASK_A2G = { + ClassName = "TASK_A2G", } - --- Instantiates a new TASK_CAS. - -- @param #TASK_CAS self + --- Instantiates a new TASK_A2G. + -- @param #TASK_A2G self -- @param Mission#MISSION Mission -- @param 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 TaskType BAI or CAS -- @param Set#SET_UNIT UnitSetTargets -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_CAS self - function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "CAS", "A2G" ) ) + -- @return #TASK_A2G self + function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit ) + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, "A2G" ) ) self:F() self.TargetSetUnit = TargetSetUnit self.TargetZone = TargetZone + self.FACUnit = FACUnit _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) _EVENTDISPATCHER:OnDead( self._EventDead, self ) @@ -28527,10 +28829,10 @@ do -- TASK_CAS return self end - --- Removes a TASK_CAS. - -- @param #TASK_CAS self + --- Removes a TASK_A2G. + -- @param #TASK_A2G self -- @return #nil - function TASK_CAS:CleanUp() + function TASK_A2G:CleanUp() self:GetParent( self ):CleanUp() @@ -28539,16 +28841,17 @@ do -- TASK_CAS --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param Unit#UNIT TaskUnit - -- @return #TASK_CAS self - function TASK_CAS:AssignToUnit( TaskUnit ) + -- @return #TASK_A2G self + function TASK_A2G:AssignToUnit( TaskUnit ) self:F( TaskUnit:GetName() ) local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "CAS", TaskUnit, self.TargetSetUnit ) ) + local ProcessDestroy = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, self.TaskType, TaskUnit, self.TargetSetUnit ) ) local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) + local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { initial = 'None', @@ -28565,16 +28868,17 @@ do -- TASK_CAS onRemove = self.OnRemove, }, subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, + Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } + Destroy = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } }, + Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', }, + JTAC = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessJTAC.Fsm, event = 'Start', }, } } ) ) ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) + ProcessDestroy:AddScore( "Destroy", "destroyed a ground unit", 25 ) + ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 ) Process:Next() @@ -28582,26 +28886,26 @@ do -- TASK_CAS end --- StateMachine callback function for a TASK - -- @param #TASK_CAS self + -- @param #TASK_A2G self -- @param StateMachine#STATEMACHINE_TASK Fsm -- @param #string Event -- @param #string From -- @param #string To -- @param Event#EVENTDATA Event - function TASK_CAS:OnNext( Fsm, Event, From, To, Event ) + function TASK_A2G:OnNext( Fsm, Event, From, To, Event ) self:SetState( self, "State", To ) end - --- @param #TASK_CAS self - function TASK_CAS:GetPlannedMenuText() + --- @param #TASK_A2G self + function TASK_A2G:GetPlannedMenuText() return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" end - --- @param #TASK_CAS self - function TASK_CAS:_Schedule() + --- @param #TASK_A2G self + function TASK_A2G:_Schedule() self:F2() self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) @@ -28609,153 +28913,8 @@ do -- TASK_CAS end - --- @param #TASK_CAS self - function TASK_CAS._Scheduler() - self:F2() - - return true - end - -end - - - ---- This module contains the TASK_BAI classes. --- --- 1) @{#TASK_BAI} class, extends @{Task#TASK_BASE} --- ================================================= --- The @{#TASK_BAI} class defines a new BAI task of a @{Set} of Target Units, located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK_BASE}. --- The TASK_BAI is processed through a @{Statemachine#STATEMACHINE_TASK}, and has the following statuses: --- --- * **None**: Start of the process --- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Assign#PROCESS_ASSIGN_ACCEPT} is started to accept the task. --- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Route#PROCESS_ROUTE} is started to route the active Units in the Group to the attack zone. --- * **Success**: The SEAD task is successfully completed. Upon Success, the sub-process @{Process_SEAD#PROCESS_SEAD} is started to follow-up successful SEADing of the targets assigned in the task. --- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ. --- --- === --- --- ### Authors: FlightControl - Design and Programming --- --- @module Task_BAI - - -do -- TASK_BAI - - --- The TASK_BAI class - -- @type TASK_BAI - -- @extends Task#TASK_BASE - TASK_BAI = { - ClassName = "TASK_BAI", - } - - --- Instantiates a new TASK_BAI. - -- @param #TASK_BAI self - -- @param Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. - -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT UnitSetTargets - -- @param Zone#ZONE_BASE TargetZone - -- @return #TASK_BAI self - function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "BAI", "A2G" ) ) - self:F() - - self.TargetSetUnit = TargetSetUnit - self.TargetZone = TargetZone - - _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) - _EVENTDISPATCHER:OnDead( self._EventDead, self ) - _EVENTDISPATCHER:OnCrash( self._EventDead, self ) - _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) - - return self - end - - --- Removes a TASK_BAI. - -- @param #TASK_BAI self - -- @return #nil - function TASK_BAI:CleanUp() - - self:GetParent( self ):CleanUp() - - return nil - end - - - --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_BAI self - -- @param Unit#UNIT TaskUnit - -- @return #TASK_BAI self - function TASK_BAI:AssignToUnit( TaskUnit ) - self:F( TaskUnit:GetName() ) - - local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN_ACCEPT:New( self, TaskUnit, self.TaskBriefing ) ) - local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) ) - local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_DESTROY:New( self, "BAI", TaskUnit, self.TargetSetUnit ) ) - local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) - - local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { - initial = 'None', - events = { - { name = 'Next', from = 'None', to = 'Planned' }, - { name = 'Next', from = 'Planned', to = 'Assigned' }, - { name = 'Reject', from = 'Planned', to = 'Rejected' }, - { name = 'Next', from = 'Assigned', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Arrived', to = 'Failed' } - }, - callbacks = { - onNext = self.OnNext, - onRemove = self.OnRemove, - }, - subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, - Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', } - } - } ) ) - - ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - - Process:Next() - - return self - end - - --- StateMachine callback function for a TASK - -- @param #TASK_BAI self - -- @param StateMachine#STATEMACHINE_TASK Fsm - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Event#EVENTDATA Event - function TASK_BAI:OnNext( Fsm, Event, From, To, Event ) - - self:SetState( self, "State", To ) - - end - - --- @param #TASK_BAI self - function TASK_BAI:GetPlannedMenuText() - return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" - end - - - --- @param #TASK_BAI self - function TASK_BAI:_Schedule() - self:F2() - - self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) - return self - end - - - --- @param #TASK_BAI self - function TASK_BAI._Scheduler() + --- @param #TASK_A2G self + function TASK_A2G._Scheduler() self:F2() return true diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat index 486d22b90..331781f0f 100644 --- a/Moose Mission Setup/Moose_Create.bat +++ b/Moose Mission Setup/Moose_Create.bat @@ -93,11 +93,11 @@ COPY /b Moose.lua + %1\Process_Assign.lua Moose.lua COPY /b Moose.lua + %1\Process_Route.lua Moose.lua COPY /b Moose.lua + %1\Process_Smoke.lua Moose.lua COPY /b Moose.lua + %1\Process_Destroy.lua Moose.lua +COPY /b Moose.lua + %1\Process_JTAC.lua Moose.lua COPY /b Moose.lua + %1\Task.lua Moose.lua COPY /b Moose.lua + %1\Task_SEAD.lua Moose.lua -COPY /b Moose.lua + %1\Task_CAS.lua Moose.lua -COPY /b Moose.lua + %1\Task_BAI.lua Moose.lua +COPY /b Moose.lua + %1\Task_A2G.lua Moose.lua COPY /b Moose.lua + "Moose Create Static\Moose_Trace_Off.lua" Moose.lua diff --git a/Moose Test Missions/MOOSE_Test_Template.miz b/Moose Test Missions/MOOSE_Test_Template.miz index 2b714bd81..f95986165 100644 Binary files a/Moose Test Missions/MOOSE_Test_Template.miz and b/Moose Test Missions/MOOSE_Test_Template.miz differ diff --git a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz index f9e1013b6..3313c229a 100644 Binary files a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz and b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz differ diff --git a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE-DB.miz b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE-DB.miz index 937160e9c..1ec470d7a 100644 Binary files a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE-DB.miz and b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE-DB.miz differ diff --git a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz index e564720cc..12feeb7fc 100644 Binary files a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz and b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz differ diff --git a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_CAUCASUS.miz b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_CAUCASUS.miz index 3c5c28ccb..0683c277c 100644 Binary files a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_CAUCASUS.miz and b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_CAUCASUS.miz differ diff --git a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_NEVADA.miz b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_NEVADA.miz index 78d6c5f40..77ce725c5 100644 Binary files a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_NEVADA.miz and b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE_NEVADA.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz index d279048c4..c72f7abff 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz index 42fa9e0ae..7fcb102e8 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz index c064b7842..42efcf355 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz differ diff --git a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz index 349d07791..2264a5096 100644 Binary files a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz and b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz differ diff --git a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz deleted file mode 100644 index af56838aa..000000000 Binary files a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz and /dev/null differ diff --git a/Moose Test Missions/Moose_Test_DESTROY/Moose_Test_DESTROY.lua b/Moose Test Missions/Moose_Test_DESTROY/Moose_Test_DESTROY.lua deleted file mode 100644 index a6efabd7f..000000000 --- a/Moose Test Missions/Moose_Test_DESTROY/Moose_Test_DESTROY.lua +++ /dev/null @@ -1,31 +0,0 @@ - -do - local Mission = MISSION:New( 'Destroy Gound', 'Ground', 'Briefing', 'CCCP' ) - - Mission:AddClient( CLIENT:FindByName( 'Client Plane', "Just wait and observe the SU-25T destoying targets. Your mission goal should increase..." ) ) - - local DESTROYGROUPSTASK = DESTROYGROUPSTASK:New( 'Ground Vehicle', 'Ground Vehicles', { 'DESTROY Test 1' }, 100 ) -- 75% of a patriot battery needs to be destroyed to achieve mission success... - DESTROYGROUPSTASK:SetGoalTotal( 1 ) - Mission:AddTask( DESTROYGROUPSTASK, 1 ) - - MISSIONSCHEDULER.AddMission( Mission ) -end - - -do - local Mission = MISSION:New( 'Destroy Helicopters', 'Helicopters', 'Briefing', 'CCCP' ) - - Mission:AddClient( CLIENT:FindByName( 'Client Plane', "Just wait and observe the SU-25T destoying the helicopters. The helicopter mission goal should increase once all are destroyed ..." ) ) - - local DESTROYGROUPSTASK = DESTROYGROUPSTASK:New( 'Helicopter', 'Helicopters', { 'DESTROY Test 2' }, 50 ) - DESTROYGROUPSTASK:SetGoalTotal( 2 ) - Mission:AddTask( DESTROYGROUPSTASK, 1 ) - - MISSIONSCHEDULER.AddMission( Mission ) -end - --- MISSION SCHEDULER STARTUP -MISSIONSCHEDULER.Start() -MISSIONSCHEDULER.ReportMenu() -MISSIONSCHEDULER.ReportMissionsFlash( 30 ) -MISSIONSCHEDULER.ReportMissionsHide() \ No newline at end of file diff --git a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz index 037b886c1..56fda125d 100644 Binary files a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz and b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz differ diff --git a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION_Laser.miz b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION_Laser.miz index be2a82e8b..3d52c116b 100644 Binary files a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION_Laser.miz and b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION_Laser.miz differ diff --git a/Moose Test Missions/Moose_Test_DETECTION_DISPATCHER/Moose_Test_DETECTION_DISPATCHER.miz b/Moose Test Missions/Moose_Test_DETECTION_DISPATCHER/Moose_Test_DETECTION_DISPATCHER.miz index 7700b387f..89c59ef23 100644 Binary files a/Moose Test Missions/Moose_Test_DETECTION_DISPATCHER/Moose_Test_DETECTION_DISPATCHER.miz and b/Moose Test Missions/Moose_Test_DETECTION_DISPATCHER/Moose_Test_DETECTION_DISPATCHER.miz differ diff --git a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz index 143bd83f1..20c6c3378 100644 Binary files a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz and b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz differ diff --git a/Moose Test Missions/Moose_Test_FAC/Moose_Test_FAC.miz b/Moose Test Missions/Moose_Test_FAC/Moose_Test_FAC.miz index 3c5225784..d857401ed 100644 Binary files a/Moose Test Missions/Moose_Test_FAC/Moose_Test_FAC.miz and b/Moose Test Missions/Moose_Test_FAC/Moose_Test_FAC.miz differ diff --git a/Moose Test Missions/Moose_Test_GROUP_SwitchWayPoint/MOOSE_Test_GROUP_SwitchWayPoint.miz b/Moose Test Missions/Moose_Test_GROUP_SwitchWayPoint/MOOSE_Test_GROUP_SwitchWayPoint.miz index 7708cce62..187e58b80 100644 Binary files a/Moose Test Missions/Moose_Test_GROUP_SwitchWayPoint/MOOSE_Test_GROUP_SwitchWayPoint.miz and b/Moose Test Missions/Moose_Test_GROUP_SwitchWayPoint/MOOSE_Test_GROUP_SwitchWayPoint.miz differ diff --git a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz index 37c82ed66..4be50b03e 100644 Binary files a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz and b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz differ diff --git a/Moose Test Missions/Moose_Test_PATROLZONE/MOOSE_Test_PATROLZONE.miz b/Moose Test Missions/Moose_Test_PATROLZONE/MOOSE_Test_PATROLZONE.miz index b520ebd77..5ae1789ba 100644 Binary files a/Moose Test Missions/Moose_Test_PATROLZONE/MOOSE_Test_PATROLZONE.miz and b/Moose Test Missions/Moose_Test_PATROLZONE/MOOSE_Test_PATROLZONE.miz differ diff --git a/Moose Test Missions/Moose_Test_SCHEDULER/Moose_Test_SCHEDULER.miz b/Moose Test Missions/Moose_Test_SCHEDULER/Moose_Test_SCHEDULER.miz index 357a9ccf1..4fbad41c5 100644 Binary files a/Moose Test Missions/Moose_Test_SCHEDULER/Moose_Test_SCHEDULER.miz and b/Moose Test Missions/Moose_Test_SCHEDULER/Moose_Test_SCHEDULER.miz differ diff --git a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz index 8387eeee3..627f2704a 100644 Binary files a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz and b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_AIRBASE/Moose_Test_SET_AIRBASE.miz b/Moose Test Missions/Moose_Test_SET_AIRBASE/Moose_Test_SET_AIRBASE.miz index d5cfecd2c..4617ecbda 100644 Binary files a/Moose Test Missions/Moose_Test_SET_AIRBASE/Moose_Test_SET_AIRBASE.miz and b/Moose Test Missions/Moose_Test_SET_AIRBASE/Moose_Test_SET_AIRBASE.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz b/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz index 20ec9b381..b697b2248 100644 Binary files a/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz and b/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz index fe406dc34..1f1c3dd68 100644 Binary files a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz and b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz index 5d9ad377c..c11822433 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz and b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_CleanUp/MOOSE_Test_SPAWN_CleanUp.miz b/Moose Test Missions/Moose_Test_SPAWN_CleanUp/MOOSE_Test_SPAWN_CleanUp.miz index 9ecdd0ac7..665dfb6f6 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_CleanUp/MOOSE_Test_SPAWN_CleanUp.miz and b/Moose Test Missions/Moose_Test_SPAWN_CleanUp/MOOSE_Test_SPAWN_CleanUp.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_Limit_Scheduled/MOOSE_Test_SPAWN_Limit_Scheduled.miz b/Moose Test Missions/Moose_Test_SPAWN_Limit_Scheduled/MOOSE_Test_SPAWN_Limit_Scheduled.miz index 919bcc4f6..e2659e57c 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_Limit_Scheduled/MOOSE_Test_SPAWN_Limit_Scheduled.miz and b/Moose Test Missions/Moose_Test_SPAWN_Limit_Scheduled/MOOSE_Test_SPAWN_Limit_Scheduled.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz index 3a911c41d..c17ca6b6a 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz and b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz differ diff --git a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz index 75d2887e5..a941d528f 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz and b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz differ diff --git a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz index 77832abd7..82a9e7191 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz and b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz differ diff --git a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz index 94298d20e..5bf7c28a7 100644 Binary files a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz and b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz index e99cd7361..8ca1cc1b3 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz and b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_GROUP/Moose_Test_ZONE_GROUP.miz b/Moose Test Missions/Moose_Test_ZONE_GROUP/Moose_Test_ZONE_GROUP.miz index a59d99917..b6eb4a543 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_GROUP/Moose_Test_ZONE_GROUP.miz and b/Moose Test Missions/Moose_Test_ZONE_GROUP/Moose_Test_ZONE_GROUP.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz index e83b766ca..7cdb39913 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz and b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz index 43d7612a4..c837373ef 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz and b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz index 0dfbc5099..1e00dff40 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz and b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz differ