mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #315 from FlightControl-Master/FlightControl
New tasking system
This commit is contained in:
commit
46e8f30c4a
1
.gitignore
vendored
1
.gitignore
vendored
@ -222,3 +222,4 @@ _gsdata_/
|
|||||||
#GITHUB
|
#GITHUB
|
||||||
.gitattributes
|
.gitattributes
|
||||||
.gitignore
|
.gitignore
|
||||||
|
Moose Test Missions/MOOSE_Test_Template.miz
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup/Moose Mission Update\Moose_Update_Missions.bat"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc:}/Moose Mission Setup/Moose Mission Update\Moose_Update_Missions.bat"/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""${project_loc:}"/Moose Test Missions"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value=""${project_loc:}/Moose Test Missions""/>
|
||||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup/Moose Mission Update"/>
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${project_loc:}/Moose Mission Setup/Moose Mission Update"/>
|
||||||
</launchConfiguration>
|
</launchConfiguration>
|
||||||
|
|||||||
Binary file not shown.
BIN
Moose Development/Maths/Task Templates.xlsx
Normal file
BIN
Moose Development/Maths/Task Templates.xlsx
Normal file
Binary file not shown.
@ -161,11 +161,6 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
|||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
|
||||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
|
||||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
|
||||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
|
||||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
|
||||||
|
|
||||||
-- @return #boolean Return false to cancel Transition.
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
@ -176,11 +171,6 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
|||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
|
||||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
|
||||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
|
||||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
|
||||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
|
||||||
|
|
||||||
--- Synchronous Event Trigger for Event Engage.
|
--- Synchronous Event Trigger for Event Engage.
|
||||||
-- @function [parent=#AI_CAS_ZONE] Engage
|
-- @function [parent=#AI_CAS_ZONE] Engage
|
||||||
@ -408,7 +398,7 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
|
|||||||
if Detected == true then
|
if Detected == true then
|
||||||
self:E( {"Target: ", DetectedUnit } )
|
self:E( {"Target: ", DetectedUnit } )
|
||||||
self.DetectedUnits[DetectedUnit] = false
|
self.DetectedUnits[DetectedUnit] = false
|
||||||
local AttackTask = Controllable:EnRouteTaskEngageUnit( DetectedUnit, 1, true, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil )
|
local AttackTask = Controllable:TaskAttackUnit( DetectedUnit, false, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil )
|
||||||
self.Controllable:PushTask( AttackTask, 1 )
|
self.Controllable:PushTask( AttackTask, 1 )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -439,8 +429,8 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
|
||||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||||
|
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||||
function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||||
@ -480,28 +470,28 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
EngageRoute[#EngageRoute+1] = CurrentRoutePoint
|
EngageRoute[#EngageRoute+1] = CurrentRoutePoint
|
||||||
|
|
||||||
|
|
||||||
if self.Controllable:IsNotInZone( self.EngageZone ) then
|
-- if self.Controllable:IsNotInZone( self.EngageZone ) then
|
||||||
|
--
|
||||||
-- Find a random 2D point in EngageZone.
|
-- -- Find a random 2D point in EngageZone.
|
||||||
local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
|
-- local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
|
||||||
self:T2( ToEngageZoneVec2 )
|
-- self:T2( ToEngageZoneVec2 )
|
||||||
|
--
|
||||||
-- Obtain a 3D @{Point} from the 2D point + altitude.
|
-- -- Obtain a 3D @{Point} from the 2D point + altitude.
|
||||||
local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, self.EngageAltitude, ToEngageZoneVec2.y )
|
-- local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, self.EngageAltitude, ToEngageZoneVec2.y )
|
||||||
|
--
|
||||||
-- Create a route point of type air.
|
-- -- Create a route point of type air.
|
||||||
local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
|
-- local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
|
||||||
self.PatrolAltType,
|
-- self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
-- POINT_VEC3.RoutePointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
-- POINT_VEC3.RoutePointAction.TurningPoint,
|
||||||
self.EngageSpeed,
|
-- self.EngageSpeed,
|
||||||
true
|
-- true
|
||||||
)
|
-- )
|
||||||
|
--
|
||||||
EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
|
-- EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
|
||||||
|
--
|
||||||
end
|
-- end
|
||||||
|
--
|
||||||
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
|
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
|
||||||
|
|
||||||
--- Find a random 2D point in EngageZone.
|
--- Find a random 2D point in EngageZone.
|
||||||
@ -556,9 +546,9 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
--- NOW ROUTE THE GROUP!
|
--- NOW ROUTE THE GROUP!
|
||||||
self.Controllable:WayPointExecute( 1 )
|
self.Controllable:WayPointExecute( 1 )
|
||||||
|
|
||||||
self:SetDetectionInterval( 10 )
|
self:SetDetectionInterval( 2 )
|
||||||
self:SetDetectionActivated()
|
self:SetDetectionActivated()
|
||||||
self:__Target( -10 ) -- Start Targetting
|
self:__Target( -2 ) -- Start Targetting
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -192,15 +192,6 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
self.TaskName = FsmAccount.TaskName
|
self.TaskName = FsmAccount.TaskName
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ACT_ACCOUNT_DEADS:_Destructor()
|
|
||||||
self:E("_Destructor")
|
|
||||||
|
|
||||||
self:EventRemoveAll()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Process Events
|
--- Process Events
|
||||||
|
|
||||||
--- StateMachine callback function
|
--- StateMachine callback function
|
||||||
@ -231,7 +222,6 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
|
|
||||||
if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then
|
if self.TargetSetUnit:FindUnit( EventData.IniUnitName ) then
|
||||||
local TaskGroup = ProcessUnit:GetGroup()
|
local TaskGroup = ProcessUnit:GetGroup()
|
||||||
self.TargetSetUnit:RemoveUnitsByName( EventData.IniUnitName )
|
|
||||||
self:Message( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed." )
|
self:Message( "You hit a target. Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed." )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -244,7 +234,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
function ACT_ACCOUNT_DEADS:onafterEvent( ProcessUnit, From, Event, To, EventData )
|
function ACT_ACCOUNT_DEADS:onafterEvent( ProcessUnit, From, Event, To, EventData )
|
||||||
|
|
||||||
if self.TargetSetUnit:Count() > 0 then
|
if self.TargetSetUnit:Count() > 1 then
|
||||||
self:__More( 1 )
|
self:__More( 1 )
|
||||||
else
|
else
|
||||||
self:__NoMore( 1 )
|
self:__NoMore( 1 )
|
||||||
@ -259,7 +249,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
|
|
||||||
if EventData.IniDCSUnit then
|
if EventData.IniDCSUnit then
|
||||||
self:__Event( 1, EventData )
|
self:Event( EventData )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -175,7 +175,7 @@ do -- ACT_ASSIGN_ACCEPT
|
|||||||
|
|
||||||
self:Message( "You are assigned to the task " .. self.Task:GetName() )
|
self:Message( "You are assigned to the task " .. self.Task:GetName() )
|
||||||
|
|
||||||
self.Task:Assign()
|
self.Task:Assign( ProcessUnit, self.Task )
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- ACT_ASSIGN_ACCEPT
|
end -- ACT_ASSIGN_ACCEPT
|
||||||
|
|||||||
@ -108,7 +108,7 @@ do -- ACT_ASSIST
|
|||||||
function ACT_ASSIST:onafterStart( ProcessUnit, From, Event, To )
|
function ACT_ASSIST:onafterStart( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
local ProcessGroup = ProcessUnit:GetGroup()
|
local ProcessGroup = ProcessUnit:GetGroup()
|
||||||
local MissionMenu = self:GetMission():GetMissionMenu( ProcessGroup )
|
local MissionMenu = self:GetMission():GetMenu( ProcessGroup )
|
||||||
|
|
||||||
local function MenuSmoke( MenuParam )
|
local function MenuSmoke( MenuParam )
|
||||||
self:E( MenuParam )
|
self:E( MenuParam )
|
||||||
@ -125,6 +125,17 @@ do -- ACT_ASSIST
|
|||||||
self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } )
|
self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } )
|
||||||
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
|
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- StateMachine callback function
|
||||||
|
-- @param #ACT_ASSIST self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string To
|
||||||
|
function ACT_ASSIST:onafterStop( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
|
self.Menu:Remove() -- When stopped, remove the menus
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -56,8 +56,7 @@ function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
|
|||||||
endstates = { 'Failed' }
|
endstates = { 'Failed' }
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
self:HandleEvent( EVENTS.Dead, self.EventDead )
|
||||||
_EVENTDISPATCHER:OnDead( self.EventDead, self )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@ -81,7 +81,7 @@ do -- ACT_ROUTE
|
|||||||
-- @type ACT_ROUTE
|
-- @type ACT_ROUTE
|
||||||
-- @field Tasking.Task#TASK TASK
|
-- @field Tasking.Task#TASK TASK
|
||||||
-- @field Wrapper.Unit#UNIT ProcessUnit
|
-- @field Wrapper.Unit#UNIT ProcessUnit
|
||||||
-- @field Core.Zone#ZONE_BASE TargetZone
|
-- @field Core.Zone#ZONE_BASE Zone
|
||||||
-- @extends Core.Fsm#FSM_PROCESS
|
-- @extends Core.Fsm#FSM_PROCESS
|
||||||
ACT_ROUTE = {
|
ACT_ROUTE = {
|
||||||
ClassName = "ACT_ROUTE",
|
ClassName = "ACT_ROUTE",
|
||||||
@ -177,6 +177,115 @@ do -- ACT_ROUTE
|
|||||||
end -- ACT_ROUTE
|
end -- ACT_ROUTE
|
||||||
|
|
||||||
|
|
||||||
|
do -- ACT_ROUTE_POINT
|
||||||
|
|
||||||
|
--- ACT_ROUTE_POINT class
|
||||||
|
-- @type ACT_ROUTE_POINT
|
||||||
|
-- @field Tasking.Task#TASK TASK
|
||||||
|
-- @extends #ACT_ROUTE
|
||||||
|
ACT_ROUTE_POINT = {
|
||||||
|
ClassName = "ACT_ROUTE_POINT",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a new routing state machine.
|
||||||
|
-- The task will route a controllable to a PointVec2 until the controllable is within the Range.
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @param Core.Point#POINT_VEC2 The PointVec2 to Target.
|
||||||
|
-- @param #number Range The Distance to Target.
|
||||||
|
-- @param Core.Zone#ZONE_BASE Zone
|
||||||
|
function ACT_ROUTE_POINT:New( PointVec2, Range )
|
||||||
|
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_POINT
|
||||||
|
|
||||||
|
self.PointVec2 = PointVec2
|
||||||
|
self.Range = Range or 0
|
||||||
|
|
||||||
|
self.DisplayInterval = 30
|
||||||
|
self.DisplayCount = 30
|
||||||
|
self.DisplayMessage = true
|
||||||
|
self.DisplayTime = 10 -- 10 seconds is the default
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function ACT_ROUTE_POINT:Init( FsmRoute )
|
||||||
|
|
||||||
|
self.PointVec2 = FsmRoute.PointVec2
|
||||||
|
self.Range = FsmRoute.Range or 0
|
||||||
|
|
||||||
|
self.DisplayInterval = 30
|
||||||
|
self.DisplayCount = 30
|
||||||
|
self.DisplayMessage = true
|
||||||
|
self.DisplayTime = 10 -- 10 seconds is the default
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set PointVec2
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
|
||||||
|
function ACT_ROUTE_POINT:SetPointVec2( PointVec2 )
|
||||||
|
self:F2( { PointVec2 } )
|
||||||
|
self.PointVec2 = PointVec2
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get PointVec2
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @return Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
|
||||||
|
function ACT_ROUTE_POINT:GetPointVec2()
|
||||||
|
self:F2( { self.PointVec2 } )
|
||||||
|
return self.PointVec2
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set Range around PointVec2
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @param #number Range The Range to consider the arrival. Default is 10000 meters.
|
||||||
|
function ACT_ROUTE_POINT:SetRange( Range )
|
||||||
|
self:F2( { self.Range } )
|
||||||
|
self.Range = Range or 10000
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get Range around PointVec2
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @return #number The Range to consider the arrival. Default is 10000 meters.
|
||||||
|
function ACT_ROUTE_POINT:GetRange()
|
||||||
|
return self.Range
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Method override to check if the controllable has arrived.
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
||||||
|
-- @return #boolean
|
||||||
|
function ACT_ROUTE_POINT:onfuncHasArrived( ProcessUnit )
|
||||||
|
|
||||||
|
if ProcessUnit:IsAlive() then
|
||||||
|
local Distance = self.PointVec2:Get2DDistance( ProcessUnit:GetPointVec2() )
|
||||||
|
|
||||||
|
if Distance <= self.Range then
|
||||||
|
local RouteText = "You have arrived."
|
||||||
|
self:Message( RouteText )
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Task Events
|
||||||
|
|
||||||
|
--- StateMachine callback function
|
||||||
|
-- @param #ACT_ROUTE_POINT self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string To
|
||||||
|
function ACT_ROUTE_POINT:onenterReporting( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
|
local TaskUnitPointVec2 = ProcessUnit:GetPointVec2()
|
||||||
|
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( self.PointVec2 ) .. " km."
|
||||||
|
self:Message( RouteText )
|
||||||
|
end
|
||||||
|
|
||||||
|
end -- ACT_ROUTE_POINT
|
||||||
|
|
||||||
|
|
||||||
do -- ACT_ROUTE_ZONE
|
do -- ACT_ROUTE_ZONE
|
||||||
|
|
||||||
@ -184,7 +293,7 @@ do -- ACT_ROUTE_ZONE
|
|||||||
-- @type ACT_ROUTE_ZONE
|
-- @type ACT_ROUTE_ZONE
|
||||||
-- @field Tasking.Task#TASK TASK
|
-- @field Tasking.Task#TASK TASK
|
||||||
-- @field Wrapper.Unit#UNIT ProcessUnit
|
-- @field Wrapper.Unit#UNIT ProcessUnit
|
||||||
-- @field Core.Zone#ZONE_BASE TargetZone
|
-- @field Core.Zone#ZONE_BASE Zone
|
||||||
-- @extends #ACT_ROUTE
|
-- @extends #ACT_ROUTE
|
||||||
ACT_ROUTE_ZONE = {
|
ACT_ROUTE_ZONE = {
|
||||||
ClassName = "ACT_ROUTE_ZONE",
|
ClassName = "ACT_ROUTE_ZONE",
|
||||||
@ -193,11 +302,11 @@ do -- ACT_ROUTE_ZONE
|
|||||||
|
|
||||||
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
|
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
|
||||||
-- @param #ACT_ROUTE_ZONE self
|
-- @param #ACT_ROUTE_ZONE self
|
||||||
-- @param Core.Zone#ZONE_BASE TargetZone
|
-- @param Core.Zone#ZONE_BASE Zone
|
||||||
function ACT_ROUTE_ZONE:New( TargetZone )
|
function ACT_ROUTE_ZONE:New( Zone )
|
||||||
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_ZONE
|
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_ZONE
|
||||||
|
|
||||||
self.TargetZone = TargetZone
|
self.Zone = Zone
|
||||||
|
|
||||||
self.DisplayInterval = 30
|
self.DisplayInterval = 30
|
||||||
self.DisplayCount = 30
|
self.DisplayCount = 30
|
||||||
@ -209,7 +318,7 @@ do -- ACT_ROUTE_ZONE
|
|||||||
|
|
||||||
function ACT_ROUTE_ZONE:Init( FsmRoute )
|
function ACT_ROUTE_ZONE:Init( FsmRoute )
|
||||||
|
|
||||||
self.TargetZone = FsmRoute.TargetZone
|
self.Zone = FsmRoute.Zone
|
||||||
|
|
||||||
self.DisplayInterval = 30
|
self.DisplayInterval = 30
|
||||||
self.DisplayCount = 30
|
self.DisplayCount = 30
|
||||||
@ -217,18 +326,32 @@ do -- ACT_ROUTE_ZONE
|
|||||||
self.DisplayTime = 10 -- 10 seconds is the default
|
self.DisplayTime = 10 -- 10 seconds is the default
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set Zone
|
||||||
|
-- @param #ACT_ROUTE_ZONE self
|
||||||
|
-- @param Core.Zone#ZONE_BASE Zone The Zone object where to route to.
|
||||||
|
function ACT_ROUTE_ZONE:SetZone( Zone )
|
||||||
|
self.Zone = Zone
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get Zone
|
||||||
|
-- @param #ACT_ROUTE_ZONE self
|
||||||
|
-- @return Core.Zone#ZONE_BASE Zone The Zone object where to route to.
|
||||||
|
function ACT_ROUTE_ZONE:GetZone()
|
||||||
|
return self.Zone
|
||||||
|
end
|
||||||
|
|
||||||
--- Method override to check if the controllable has arrived.
|
--- Method override to check if the controllable has arrived.
|
||||||
-- @param #ACT_ROUTE self
|
-- @param #ACT_ROUTE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit )
|
function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit )
|
||||||
|
|
||||||
if ProcessUnit:IsInZone( self.TargetZone ) then
|
if ProcessUnit:IsInZone( self.Zone ) then
|
||||||
local RouteText = "You have arrived within the zone."
|
local RouteText = "You have arrived within the zone."
|
||||||
self:Message( RouteText )
|
self:Message( RouteText )
|
||||||
end
|
end
|
||||||
|
|
||||||
return ProcessUnit:IsInZone( self.TargetZone )
|
return ProcessUnit:IsInZone( self.Zone )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Task Events
|
--- Task Events
|
||||||
@ -241,11 +364,11 @@ do -- ACT_ROUTE_ZONE
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, From, Event, To )
|
function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
local ZoneVec2 = self.TargetZone:GetVec2()
|
local ZoneVec2 = self.Zone:GetVec2()
|
||||||
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
|
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
|
||||||
local TaskUnitVec2 = ProcessUnit:GetVec2()
|
local TaskUnitVec2 = ProcessUnit:GetVec2()
|
||||||
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
|
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
|
||||||
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km to target."
|
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km."
|
||||||
self:Message( RouteText )
|
self:Message( RouteText )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -256,12 +256,14 @@ function BASE:_Destructor()
|
|||||||
--self:EventRemoveAll()
|
--self:EventRemoveAll()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- THIS IS WHY WE NEED LUA 5.2 ...
|
||||||
function BASE:_SetDestructor()
|
function BASE:_SetDestructor()
|
||||||
|
|
||||||
-- TODO: Okay, this is really technical...
|
-- TODO: Okay, this is really technical...
|
||||||
-- When you set a proxy to a table to catch __gc, weak tables don't behave like weak...
|
-- When you set a proxy to a table to catch __gc, weak tables don't behave like weak...
|
||||||
-- Therefore, I am parking this logic until I've properly discussed all this with the community.
|
-- Therefore, I am parking this logic until I've properly discussed all this with the community.
|
||||||
--[[
|
|
||||||
local proxy = newproxy(true)
|
local proxy = newproxy(true)
|
||||||
local proxyMeta = getmetatable(proxy)
|
local proxyMeta = getmetatable(proxy)
|
||||||
|
|
||||||
@ -276,7 +278,7 @@ function BASE:_SetDestructor()
|
|||||||
-- table is about to be garbage-collected - then the __gc hook
|
-- table is about to be garbage-collected - then the __gc hook
|
||||||
-- will be invoked and the destructor called
|
-- will be invoked and the destructor called
|
||||||
rawset( self, '__proxy', proxy )
|
rawset( self, '__proxy', proxy )
|
||||||
--]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- This is the worker method to inherit from a parent class.
|
--- This is the worker method to inherit from a parent class.
|
||||||
@ -292,7 +294,7 @@ function BASE:Inherit( Child, Parent )
|
|||||||
setmetatable( Child, Parent )
|
setmetatable( Child, Parent )
|
||||||
Child.__index = Child
|
Child.__index = Child
|
||||||
|
|
||||||
Child:_SetDestructor()
|
--Child:_SetDestructor()
|
||||||
end
|
end
|
||||||
--self:T( 'Inherited from ' .. Parent.ClassName )
|
--self:T( 'Inherited from ' .. Parent.ClassName )
|
||||||
return Child
|
return Child
|
||||||
|
|||||||
@ -54,6 +54,8 @@ DATABASE = {
|
|||||||
PLAYERSJOINED = {},
|
PLAYERSJOINED = {},
|
||||||
CLIENTS = {},
|
CLIENTS = {},
|
||||||
AIRBASES = {},
|
AIRBASES = {},
|
||||||
|
COUNTRY_ID = {},
|
||||||
|
COUNTRY_NAME = {},
|
||||||
NavPoints = {},
|
NavPoints = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,6 +763,9 @@ function DATABASE:_RegisterTemplates()
|
|||||||
local CountryName = string.upper(cntry_data.name)
|
local CountryName = string.upper(cntry_data.name)
|
||||||
local CountryID = cntry_data.id
|
local CountryID = cntry_data.id
|
||||||
|
|
||||||
|
self.COUNTRY_ID[CountryName] = CountryID
|
||||||
|
self.COUNTRY_NAME[CountryID] = CountryName
|
||||||
|
|
||||||
--self.Units[coa_name][countryName] = {}
|
--self.Units[coa_name][countryName] = {}
|
||||||
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id
|
--self.Units[coa_name][countryName]["countryId"] = cntry_data.id
|
||||||
|
|
||||||
|
|||||||
@ -284,7 +284,7 @@ local _EVENTMETA = {
|
|||||||
},
|
},
|
||||||
[world.event.S_EVENT_TAKEOFF] = {
|
[world.event.S_EVENT_TAKEOFF] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
Event = "OnEventTakeOff",
|
Event = "OnEventTakeoff",
|
||||||
Text = "S_EVENT_TAKEOFF"
|
Text = "S_EVENT_TAKEOFF"
|
||||||
},
|
},
|
||||||
[world.event.S_EVENT_LAND] = {
|
[world.event.S_EVENT_LAND] = {
|
||||||
@ -425,11 +425,11 @@ function EVENT:Init( EventID, EventClass )
|
|||||||
-- Each event has a subtable of EventClasses, ordered by EventPriority.
|
-- Each event has a subtable of EventClasses, ordered by EventPriority.
|
||||||
local EventPriority = EventClass:GetEventPriority()
|
local EventPriority = EventClass:GetEventPriority()
|
||||||
if not self.Events[EventID][EventPriority] then
|
if not self.Events[EventID][EventPriority] then
|
||||||
self.Events[EventID][EventPriority] = {}
|
self.Events[EventID][EventPriority] = setmetatable( {}, { __mode = "k" } )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.Events[EventID][EventPriority][EventClass] then
|
if not self.Events[EventID][EventPriority][EventClass] then
|
||||||
self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "k" } )
|
self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "v" } )
|
||||||
end
|
end
|
||||||
return self.Events[EventID][EventPriority][EventClass]
|
return self.Events[EventID][EventPriority][EventClass]
|
||||||
end
|
end
|
||||||
@ -499,11 +499,11 @@ end
|
|||||||
-- @param EventClass The instance of the class for which the event is.
|
-- @param EventClass The instance of the class for which the event is.
|
||||||
-- @param #function OnEventFunction
|
-- @param #function OnEventFunction
|
||||||
-- @return #EVENT
|
-- @return #EVENT
|
||||||
function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, OnEventFunction )
|
function EVENT:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EventID )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
for EventUnitID, EventUnit in pairs( EventTemplate.units ) do
|
for EventUnitID, EventUnit in pairs( EventTemplate.units ) do
|
||||||
OnEventFunction( self, EventUnit.name, EventFunction, EventClass )
|
self:OnEventForUnit( EventUnit.name, EventFunction, EventClass, EventID )
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -517,9 +517,9 @@ end
|
|||||||
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
||||||
self:F2( { EventID } )
|
self:F2( { EventID } )
|
||||||
|
|
||||||
local Event = self:Init( EventID, EventClass )
|
local EventData = self:Init( EventID, EventClass )
|
||||||
Event.EventFunction = EventFunction
|
EventData.EventFunction = EventFunction
|
||||||
Event.EventClass = EventClass
|
EventData.EventClass = EventClass
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -535,13 +535,13 @@ end
|
|||||||
function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
|
function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
|
||||||
self:F2( UnitName )
|
self:F2( UnitName )
|
||||||
|
|
||||||
local Event = self:Init( EventID, EventClass )
|
local EventData = self:Init( EventID, EventClass )
|
||||||
if not Event.EventUnit then
|
if not EventData.EventUnit then
|
||||||
Event.EventUnit = {}
|
EventData.EventUnit = {}
|
||||||
end
|
end
|
||||||
Event.EventUnit[UnitName] = {}
|
EventData.EventUnit[UnitName] = {}
|
||||||
Event.EventUnit[UnitName].EventFunction = EventFunction
|
EventData.EventUnit[UnitName].EventFunction = EventFunction
|
||||||
Event.EventUnit[UnitName].EventClass = EventClass
|
EventData.EventUnit[UnitName].EventClass = EventClass
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -576,51 +576,11 @@ do -- OnBirth
|
|||||||
function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnBirthForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnBirthForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Birth )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_BIRTH event, and registers the unit born.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnBirth( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_BIRTH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_BIRTH event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName The id of the unit for the event to be handled.
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnBirthForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_BIRTH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_BIRTH event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnBirthRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_BIRTH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- OnCrash
|
do -- OnCrash
|
||||||
@ -634,49 +594,10 @@ do -- OnCrash
|
|||||||
function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnCrashForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnCrashForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Crash )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_CRASH event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnCrash( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_CRASH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_CRASH event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnCrashForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_CRASH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_CRASH event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnCrashRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_CRASH )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -691,96 +612,13 @@ do -- OnDead
|
|||||||
function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnDeadForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnDeadForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Dead )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnDead( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnDeadRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- OnPilotDead
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_PILOT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPilotDead( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_PILOT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPilotDeadForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_PILOT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_PILOT_DEAD event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPilotDeadRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_PILOT_DEAD )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnLand
|
do -- OnLand
|
||||||
--- Create an OnLand event handler for a group
|
--- Create an OnLand event handler for a group
|
||||||
@ -792,38 +630,11 @@ do -- OnLand
|
|||||||
function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnLandForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnLandForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Land )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_LAND event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnLandForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_LAND )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_LAND event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnLandRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_LAND )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- OnTakeOff
|
do -- OnTakeOff
|
||||||
@ -836,38 +647,11 @@ do -- OnTakeOff
|
|||||||
function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnTakeOffForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnTakeOffForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.Takeoff )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_TAKEOFF event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnTakeOffForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_TAKEOFF )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_TAKEOFF event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnTakeOffRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_TAKEOFF )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- OnEngineShutDown
|
do -- OnEngineShutDown
|
||||||
@ -881,210 +665,11 @@ do -- OnEngineShutDown
|
|||||||
function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass )
|
function EVENT:OnEngineShutDownForTemplate( EventTemplate, EventFunction, EventClass )
|
||||||
self:F2( EventTemplate.name )
|
self:F2( EventTemplate.name )
|
||||||
|
|
||||||
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, self.OnEngineShutDownForUnit )
|
self:OnEventForTemplate( EventTemplate, EventFunction, EventClass, EVENTS.EngineShutdown )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_ENGINE_SHUTDOWN event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnEngineShutDownForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_ENGINE_SHUTDOWN event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnEngineShutDownRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_ENGINE_SHUTDOWN )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnEngineStartUp
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_ENGINE_STARTUP event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnEngineStartUpForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_ENGINE_STARTUP )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_ENGINE_STARTUP event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnEngineStartUpRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_ENGINE_STARTUP )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnShot
|
|
||||||
--- Set a new listener for an S_EVENT_SHOT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnShot( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_SHOT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_SHOT event for a unit.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnShotForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_SHOT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_SHOT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnShotRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_SHOT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnHit
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_HIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnHit( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_HIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_HIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #string EventDCSUnitName
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnHitForUnit( EventDCSUnitName, EventFunction, EventClass )
|
|
||||||
self:F2( EventDCSUnitName )
|
|
||||||
|
|
||||||
self:OnEventForUnit( EventDCSUnitName, EventFunction, EventClass, world.event.S_EVENT_HIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_HIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnHitRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_HIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnPlayerEnterUnit
|
|
||||||
|
|
||||||
--- Set a new listener for an S_EVENT_PLAYER_ENTER_UNIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPlayerEnterUnit( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_PLAYER_ENTER_UNIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPlayerEnterRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_PLAYER_ENTER_UNIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
do -- OnPlayerLeaveUnit
|
|
||||||
--- Set a new listener for an S_EVENT_PLAYER_LEAVE_UNIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param #function EventFunction The function to be called when the event occurs for the unit.
|
|
||||||
-- @param Base#BASE EventClass The self instance of the class for which the event is.
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPlayerLeaveUnit( EventFunction, EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:OnEventGeneric( EventFunction, EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop listening to S_EVENT_PLAYER_LEAVE_UNIT event.
|
|
||||||
-- @param #EVENT self
|
|
||||||
-- @param Base#BASE EventClass
|
|
||||||
-- @return #EVENT
|
|
||||||
function EVENT:OnPlayerLeaveRemove( EventClass )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
self:Remove( EventClass, world.event.S_EVENT_PLAYER_LEAVE_UNIT )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1207,7 +792,9 @@ function EVENT:onEvent( Event )
|
|||||||
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
||||||
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
||||||
|
|
||||||
self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||||
|
end
|
||||||
|
|
||||||
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
||||||
|
|
||||||
@ -1228,8 +815,10 @@ function EVENT:onEvent( Event )
|
|||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if EventData.EventUnit[Event.IniDCSUnitName].EventFunction then
|
if EventData.EventUnit[Event.IniDCSUnitName].EventFunction then
|
||||||
|
|
||||||
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventData.EventUnit[Event.IniDCSUnitName].EventFunction( EventClass, Event )
|
return EventData.EventUnit[Event.IniDCSUnitName].EventFunction( EventClass, Event )
|
||||||
@ -1242,8 +831,10 @@ function EVENT:onEvent( Event )
|
|||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventFunction( EventClass, Event )
|
return EventFunction( EventClass, Event )
|
||||||
@ -1257,7 +848,9 @@ function EVENT:onEvent( Event )
|
|||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if EventData.EventUnit[Event.TgtDCSUnitName].EventFunction then
|
if EventData.EventUnit[Event.TgtDCSUnitName].EventFunction then
|
||||||
|
|
||||||
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
@ -1271,8 +864,10 @@ function EVENT:onEvent( Event )
|
|||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventFunction( EventClass, Event )
|
return EventFunction( EventClass, Event )
|
||||||
@ -1290,9 +885,11 @@ function EVENT:onEvent( Event )
|
|||||||
if EventData.EventGroup[Event.IniGroupName] then
|
if EventData.EventGroup[Event.IniGroupName] then
|
||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if EventData.EventGroup[Event.IniGroupName].EventFunction then
|
if EventData.EventGroup[Event.IniGroupName].EventFunction then
|
||||||
|
|
||||||
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventData.EventGroup[Event.IniGroupName].EventFunction( EventClass, Event )
|
return EventData.EventGroup[Event.IniGroupName].EventFunction( EventClass, Event )
|
||||||
@ -1305,8 +902,10 @@ function EVENT:onEvent( Event )
|
|||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventFunction( EventClass, Event )
|
return EventFunction( EventClass, Event )
|
||||||
@ -1318,8 +917,10 @@ function EVENT:onEvent( Event )
|
|||||||
if EventData.EventGroup[Event.TgtGroupName] then
|
if EventData.EventGroup[Event.TgtGroupName] then
|
||||||
if EventData.EventGroup[Event.TgtGroupName].EventFunction then
|
if EventData.EventGroup[Event.TgtGroupName].EventFunction then
|
||||||
|
|
||||||
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventData.EventGroup[Event.TgtGroupName].EventFunction( EventClass, Event )
|
return EventData.EventGroup[Event.TgtGroupName].EventFunction( EventClass, Event )
|
||||||
@ -1332,7 +933,9 @@ function EVENT:onEvent( Event )
|
|||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
@ -1354,8 +957,9 @@ function EVENT:onEvent( Event )
|
|||||||
if EventData.EventFunction then
|
if EventData.EventFunction then
|
||||||
|
|
||||||
-- There is an EventFunction defined, so call the EventFunction.
|
-- There is an EventFunction defined, so call the EventFunction.
|
||||||
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventData.EventFunction( EventClass, Event )
|
return EventData.EventFunction( EventClass, Event )
|
||||||
@ -1367,11 +971,14 @@ function EVENT:onEvent( Event )
|
|||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
return EventFunction( EventClass, Event )
|
local Result, Value = EventFunction( EventClass, Event )
|
||||||
|
return Result, Value
|
||||||
end, ErrorHandler )
|
end, ErrorHandler )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1385,6 +992,8 @@ function EVENT:onEvent( Event )
|
|||||||
else
|
else
|
||||||
self:E( { _EVENTMETA[Event.id].Text, Event } )
|
self:E( { _EVENTMETA[Event.id].Text, Event } )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Event = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- The EVENTHANDLER structure
|
--- The EVENTHANDLER structure
|
||||||
|
|||||||
@ -530,10 +530,20 @@ do -- FSM
|
|||||||
|
|
||||||
|
|
||||||
function FSM:_call_handler( handler, params, EventName )
|
function FSM:_call_handler( handler, params, EventName )
|
||||||
|
|
||||||
|
local ErrorHandler = function( errmsg )
|
||||||
|
|
||||||
|
env.info( "Error in SCHEDULER function:" .. errmsg )
|
||||||
|
if debug ~= nil then
|
||||||
|
env.info( debug.traceback() )
|
||||||
|
end
|
||||||
|
|
||||||
|
return errmsg
|
||||||
|
end
|
||||||
if self[handler] then
|
if self[handler] then
|
||||||
self:T( "Calling " .. handler )
|
self:T( "Calling " .. handler )
|
||||||
self._EventSchedules[EventName] = nil
|
self._EventSchedules[EventName] = nil
|
||||||
local Value = self[handler]( self, unpack(params) )
|
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
||||||
return Value
|
return Value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -732,8 +742,66 @@ do -- FSM_CONTROLLABLE
|
|||||||
self:SetControllable( Controllable )
|
self:SetControllable( Controllable )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:AddTransition( "*", "Stop", "Stopped" )
|
||||||
|
|
||||||
|
--- OnBefore Transition Handler for Event Stop.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] OnBeforeStop
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Stop.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] OnAfterStop
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- Synchronous Event Trigger for Event Stop.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] Stop
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
|
||||||
|
--- Asynchronous Event Trigger for Event Stop.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] __Stop
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param #number Delay The delay in seconds.
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Stopped.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] OnLeaveStopped
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Stopped.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] OnEnterStopped
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Stop.
|
||||||
|
-- @function [parent=#FSM_CONTROLLABLE] OnAfterStop
|
||||||
|
-- @param #FSM_CONTROLLABLE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function FSM_CONTROLLABLE:OnAfterStop(Controllable,From,Event,To)
|
||||||
|
|
||||||
|
-- Clear all pending schedules
|
||||||
|
self.CallScheduler:Clear()
|
||||||
|
end
|
||||||
|
|
||||||
--- Sets the CONTROLLABLE object that the FSM_CONTROLLABLE governs.
|
--- Sets the CONTROLLABLE object that the FSM_CONTROLLABLE governs.
|
||||||
-- @param #FSM_CONTROLLABLE self
|
-- @param #FSM_CONTROLLABLE self
|
||||||
@ -801,12 +869,34 @@ do -- FSM_PROCESS
|
|||||||
function FSM_PROCESS:Init( FsmProcess )
|
function FSM_PROCESS:Init( FsmProcess )
|
||||||
self:T( "No Initialisation" )
|
self:T( "No Initialisation" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function FSM_PROCESS:_call_handler( handler, params, EventName )
|
||||||
|
|
||||||
|
local ErrorHandler = function( errmsg )
|
||||||
|
|
||||||
|
env.info( "Error in FSM_PROCESS call handler:" .. errmsg )
|
||||||
|
if debug ~= nil then
|
||||||
|
env.info( debug.traceback() )
|
||||||
|
end
|
||||||
|
|
||||||
|
return errmsg
|
||||||
|
end
|
||||||
|
|
||||||
|
if self[handler] then
|
||||||
|
self:F3( "Calling " .. handler )
|
||||||
|
self._EventSchedules[EventName] = nil
|
||||||
|
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
|
||||||
|
return Value
|
||||||
|
--return self[handler]( self, self.Controllable, unpack( params ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Creates a new FSM_PROCESS object based on this FSM_PROCESS.
|
--- Creates a new FSM_PROCESS object based on this FSM_PROCESS.
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @return #FSM_PROCESS
|
-- @return #FSM_PROCESS
|
||||||
function FSM_PROCESS:Copy( Controllable, Task )
|
function FSM_PROCESS:Copy( Controllable, Task )
|
||||||
self:T( { self:GetClassNameAndID() } )
|
self:T( { self:GetClassNameAndID() } )
|
||||||
|
|
||||||
|
|
||||||
local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS
|
local NewFsm = self:New( Controllable, Task ) -- Core.Fsm#FSM_PROCESS
|
||||||
|
|
||||||
@ -825,7 +915,7 @@ do -- FSM_PROCESS
|
|||||||
|
|
||||||
-- Copy Processes
|
-- Copy Processes
|
||||||
for ProcessID, Process in pairs( self:GetProcesses() ) do
|
for ProcessID, Process in pairs( self:GetProcesses() ) do
|
||||||
self:T( { Process} )
|
self:E( { Process} )
|
||||||
local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents )
|
local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents )
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -843,6 +933,22 @@ do -- FSM_PROCESS
|
|||||||
|
|
||||||
return NewFsm
|
return NewFsm
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes an FSM_PROCESS object.
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @return #FSM_PROCESS
|
||||||
|
function FSM_PROCESS:Remove()
|
||||||
|
self:T( { self:GetClassNameAndID() } )
|
||||||
|
|
||||||
|
-- Copy Processes
|
||||||
|
for ProcessID, Process in pairs( self:GetProcesses() ) do
|
||||||
|
self:E( { Process} )
|
||||||
|
Process.fsm:Remove()
|
||||||
|
Process.fsm = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Sets the task of the process.
|
--- Sets the task of the process.
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
|
|||||||
@ -138,6 +138,8 @@ do -- MENU_BASE
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Consructor
|
--- Consructor
|
||||||
|
-- @param #MENU_BASE
|
||||||
|
-- @return #MENU_BASE
|
||||||
function MENU_BASE:New( MenuText, ParentMenu )
|
function MENU_BASE:New( MenuText, ParentMenu )
|
||||||
|
|
||||||
local MenuParentPath = {}
|
local MenuParentPath = {}
|
||||||
@ -150,10 +152,43 @@ do -- MENU_BASE
|
|||||||
self.MenuPath = nil
|
self.MenuPath = nil
|
||||||
self.MenuText = MenuText
|
self.MenuText = MenuText
|
||||||
self.MenuParentPath = MenuParentPath
|
self.MenuParentPath = MenuParentPath
|
||||||
|
self.Menus = {}
|
||||||
|
self.MenuCount = 0
|
||||||
|
self.MenuRemoveParent = false
|
||||||
|
self.MenuTime = timer.getTime()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets a @{Menu} from a parent @{Menu}
|
||||||
|
-- @param #MENU_BASE self
|
||||||
|
-- @param #string MenuText The text of the child menu.
|
||||||
|
-- @return #MENU_BASE
|
||||||
|
function MENU_BASE:GetMenu( MenuText )
|
||||||
|
self:F( { self.Menus, MenuText } )
|
||||||
|
return self.Menus[MenuText]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Sets a @{Menu} to remove automatically the parent menu when the menu removed is the last child menu of that parent @{Menu}.
|
||||||
|
-- @param #MENU_BASE self
|
||||||
|
-- @param #boolean RemoveParent If true, the parent menu is automatically removed when this menu is the last child menu of that parent @{Menu}.
|
||||||
|
-- @return #MENU_BASE
|
||||||
|
function MENU_BASE:SetRemoveParent( RemoveParent )
|
||||||
|
self:F( { RemoveParent } )
|
||||||
|
self.MenuRemoveParent = RemoveParent
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Sets a time stamp for later prevention of menu removal.
|
||||||
|
-- @param #MENU_BASE self
|
||||||
|
-- @param MenuTime
|
||||||
|
-- @return #MENU_BASE
|
||||||
|
function MENU_BASE:SetTime( MenuTime )
|
||||||
|
self.MenuTime = MenuTime
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- MENU_COMMAND_BASE
|
do -- MENU_COMMAND_BASE
|
||||||
@ -161,7 +196,7 @@ do -- MENU_COMMAND_BASE
|
|||||||
--- The MENU_COMMAND_BASE class
|
--- The MENU_COMMAND_BASE class
|
||||||
-- @type MENU_COMMAND_BASE
|
-- @type MENU_COMMAND_BASE
|
||||||
-- @field #function MenuCallHandler
|
-- @field #function MenuCallHandler
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
MENU_COMMAND_BASE = {
|
MENU_COMMAND_BASE = {
|
||||||
ClassName = "MENU_COMMAND_BASE",
|
ClassName = "MENU_COMMAND_BASE",
|
||||||
CommandMenuFunction = nil,
|
CommandMenuFunction = nil,
|
||||||
@ -170,6 +205,8 @@ do -- MENU_COMMAND_BASE
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Constructor
|
--- Constructor
|
||||||
|
-- @param #MENU_COMMAND_BASE
|
||||||
|
-- @return #MENU_COMMAND_BASE
|
||||||
function MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, CommandMenuArguments )
|
function MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, CommandMenuArguments )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
||||||
@ -189,7 +226,7 @@ do -- MENU_MISSION
|
|||||||
|
|
||||||
--- The MENU_MISSION class
|
--- The MENU_MISSION class
|
||||||
-- @type MENU_MISSION
|
-- @type MENU_MISSION
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
MENU_MISSION = {
|
MENU_MISSION = {
|
||||||
ClassName = "MENU_MISSION"
|
ClassName = "MENU_MISSION"
|
||||||
}
|
}
|
||||||
@ -198,7 +235,7 @@ do -- MENU_MISSION
|
|||||||
-- @param #MENU_MISSION self
|
-- @param #MENU_MISSION self
|
||||||
-- @param #string MenuText The text for the menu.
|
-- @param #string MenuText The text for the menu.
|
||||||
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
|
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
|
||||||
-- @return #MENU_MISSION self
|
-- @return #MENU_MISSION
|
||||||
function MENU_MISSION:New( MenuText, ParentMenu )
|
function MENU_MISSION:New( MenuText, ParentMenu )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
local self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
||||||
@ -225,7 +262,7 @@ do -- MENU_MISSION
|
|||||||
|
|
||||||
--- Removes the sub menus recursively of this MENU_MISSION. Note that the main menu is kept!
|
--- Removes the sub menus recursively of this MENU_MISSION. Note that the main menu is kept!
|
||||||
-- @param #MENU_MISSION self
|
-- @param #MENU_MISSION self
|
||||||
-- @return #MENU_MISSION self
|
-- @return #MENU_MISSION
|
||||||
function MENU_MISSION:RemoveSubMenus()
|
function MENU_MISSION:RemoveSubMenus()
|
||||||
self:F( self.MenuPath )
|
self:F( self.MenuPath )
|
||||||
|
|
||||||
@ -256,7 +293,7 @@ do -- MENU_MISSION_COMMAND
|
|||||||
|
|
||||||
--- The MENU_MISSION_COMMAND class
|
--- The MENU_MISSION_COMMAND class
|
||||||
-- @type MENU_MISSION_COMMAND
|
-- @type MENU_MISSION_COMMAND
|
||||||
-- @extends Menu#MENU_COMMAND_BASE
|
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||||
MENU_MISSION_COMMAND = {
|
MENU_MISSION_COMMAND = {
|
||||||
ClassName = "MENU_MISSION_COMMAND"
|
ClassName = "MENU_MISSION_COMMAND"
|
||||||
}
|
}
|
||||||
@ -306,7 +343,7 @@ do -- MENU_COALITION
|
|||||||
|
|
||||||
--- The MENU_COALITION class
|
--- The MENU_COALITION class
|
||||||
-- @type MENU_COALITION
|
-- @type MENU_COALITION
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- This demo creates a menu structure for the planes within the red coalition.
|
-- -- This demo creates a menu structure for the planes within the red coalition.
|
||||||
-- -- To test, join the planes, then look at the other radio menus (Option F10).
|
-- -- To test, join the planes, then look at the other radio menus (Option F10).
|
||||||
@ -380,7 +417,7 @@ do -- MENU_COALITION
|
|||||||
|
|
||||||
--- Removes the sub menus recursively of this MENU_COALITION. Note that the main menu is kept!
|
--- Removes the sub menus recursively of this MENU_COALITION. Note that the main menu is kept!
|
||||||
-- @param #MENU_COALITION self
|
-- @param #MENU_COALITION self
|
||||||
-- @return #MENU_COALITION self
|
-- @return #MENU_COALITION
|
||||||
function MENU_COALITION:RemoveSubMenus()
|
function MENU_COALITION:RemoveSubMenus()
|
||||||
self:F( self.MenuPath )
|
self:F( self.MenuPath )
|
||||||
|
|
||||||
@ -411,7 +448,7 @@ do -- MENU_COALITION_COMMAND
|
|||||||
|
|
||||||
--- The MENU_COALITION_COMMAND class
|
--- The MENU_COALITION_COMMAND class
|
||||||
-- @type MENU_COALITION_COMMAND
|
-- @type MENU_COALITION_COMMAND
|
||||||
-- @extends Menu#MENU_COMMAND_BASE
|
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||||
MENU_COALITION_COMMAND = {
|
MENU_COALITION_COMMAND = {
|
||||||
ClassName = "MENU_COALITION_COMMAND"
|
ClassName = "MENU_COALITION_COMMAND"
|
||||||
}
|
}
|
||||||
@ -423,7 +460,7 @@ do -- MENU_COALITION_COMMAND
|
|||||||
-- @param Menu#MENU_COALITION ParentMenu The parent menu.
|
-- @param Menu#MENU_COALITION ParentMenu The parent menu.
|
||||||
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
||||||
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
|
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
|
||||||
-- @return #MENU_COALITION_COMMAND self
|
-- @return #MENU_COALITION_COMMAND
|
||||||
function MENU_COALITION_COMMAND:New( Coalition, MenuText, ParentMenu, CommandMenuFunction, ... )
|
function MENU_COALITION_COMMAND:New( Coalition, MenuText, ParentMenu, CommandMenuFunction, ... )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
|
local self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
|
||||||
@ -468,7 +505,7 @@ do -- MENU_CLIENT
|
|||||||
|
|
||||||
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
|
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
|
||||||
-- @type MENU_CLIENT
|
-- @type MENU_CLIENT
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- This demo creates a menu structure for the two clients of planes.
|
-- -- This demo creates a menu structure for the two clients of planes.
|
||||||
-- -- Each client will receive a different menu structure.
|
-- -- Each client will receive a different menu structure.
|
||||||
@ -609,7 +646,7 @@ do -- MENU_CLIENT
|
|||||||
|
|
||||||
--- The MENU_CLIENT_COMMAND class
|
--- The MENU_CLIENT_COMMAND class
|
||||||
-- @type MENU_CLIENT_COMMAND
|
-- @type MENU_CLIENT_COMMAND
|
||||||
-- @extends Menu#MENU_COMMAND
|
-- @extends Core.Menu#MENU_COMMAND
|
||||||
MENU_CLIENT_COMMAND = {
|
MENU_CLIENT_COMMAND = {
|
||||||
ClassName = "MENU_CLIENT_COMMAND"
|
ClassName = "MENU_CLIENT_COMMAND"
|
||||||
}
|
}
|
||||||
@ -695,7 +732,7 @@ do
|
|||||||
|
|
||||||
--- The MENU_GROUP class
|
--- The MENU_GROUP class
|
||||||
-- @type MENU_GROUP
|
-- @type MENU_GROUP
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- This demo creates a menu structure for the two groups of planes.
|
-- -- This demo creates a menu structure for the two groups of planes.
|
||||||
-- -- Each group will receive a different menu structure.
|
-- -- Each group will receive a different menu structure.
|
||||||
@ -769,8 +806,6 @@ do
|
|||||||
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
|
||||||
MenuGroup._Menus[Path] = self
|
MenuGroup._Menus[Path] = self
|
||||||
|
|
||||||
self.Menus = {}
|
|
||||||
|
|
||||||
self.MenuGroup = MenuGroup
|
self.MenuGroup = MenuGroup
|
||||||
self.Path = Path
|
self.Path = Path
|
||||||
self.MenuGroupID = MenuGroup:GetID()
|
self.MenuGroupID = MenuGroup:GetID()
|
||||||
@ -780,8 +815,10 @@ do
|
|||||||
self:T( { "Adding Menu ", MenuText, self.MenuParentPath } )
|
self:T( { "Adding Menu ", MenuText, self.MenuParentPath } )
|
||||||
self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, self.MenuParentPath )
|
self.MenuPath = missionCommands.addSubMenuForGroup( self.MenuGroupID, MenuText, self.MenuParentPath )
|
||||||
|
|
||||||
if ParentMenu and ParentMenu.Menus then
|
if self.ParentMenu and self.ParentMenu.Menus then
|
||||||
ParentMenu.Menus[self.MenuPath] = self
|
self.ParentMenu.Menus[MenuText] = self
|
||||||
|
self:F( { self.ParentMenu.Menus, MenuText } )
|
||||||
|
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -792,42 +829,56 @@ do
|
|||||||
|
|
||||||
--- Removes the sub menus recursively of this MENU_GROUP.
|
--- Removes the sub menus recursively of this MENU_GROUP.
|
||||||
-- @param #MENU_GROUP self
|
-- @param #MENU_GROUP self
|
||||||
|
-- @param MenuTime
|
||||||
-- @return #MENU_GROUP self
|
-- @return #MENU_GROUP self
|
||||||
function MENU_GROUP:RemoveSubMenus()
|
function MENU_GROUP:RemoveSubMenus( MenuTime )
|
||||||
self:F( self.MenuPath )
|
self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
|
||||||
|
|
||||||
for MenuID, Menu in pairs( self.Menus ) do
|
self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
|
||||||
Menu:Remove()
|
for MenuText, Menu in pairs( self.Menus ) do
|
||||||
|
Menu:Remove( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Removes the main menu and sub menus recursively of this MENU_GROUP.
|
--- Removes the main menu and sub menus recursively of this MENU_GROUP.
|
||||||
-- @param #MENU_GROUP self
|
-- @param #MENU_GROUP self
|
||||||
|
-- @param MenuTime
|
||||||
-- @return #nil
|
-- @return #nil
|
||||||
function MENU_GROUP:Remove()
|
function MENU_GROUP:Remove( MenuTime )
|
||||||
self:F( { self.MenuGroupID, self.MenuPath } )
|
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
|
||||||
|
|
||||||
self:RemoveSubMenus()
|
self:RemoveSubMenus( MenuTime )
|
||||||
|
|
||||||
if self.MenuGroup._Menus[self.Path] then
|
|
||||||
self = self.MenuGroup._Menus[self.Path]
|
|
||||||
|
|
||||||
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
|
if not MenuTime or self.MenuTime ~= MenuTime then
|
||||||
if self.ParentMenu then
|
if self.MenuGroup._Menus[self.Path] then
|
||||||
self.ParentMenu.Menus[self.MenuPath] = nil
|
self = self.MenuGroup._Menus[self.Path]
|
||||||
|
|
||||||
|
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
|
||||||
|
if self.ParentMenu then
|
||||||
|
self.ParentMenu.Menus[self.MenuText] = nil
|
||||||
|
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
|
||||||
|
if self.ParentMenu.MenuCount == 0 then
|
||||||
|
if self.MenuRemoveParent == true then
|
||||||
|
self:T( "Removing Parent Menu " )
|
||||||
|
self.ParentMenu:Remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:T( { "Removing Group Menu:", self.MenuGroup:GetName(), self.MenuGroup._Menus[self.Path].Path } )
|
||||||
|
self.MenuGroup._Menus[self.Path] = nil
|
||||||
|
self = nil
|
||||||
end
|
end
|
||||||
self:E( self.MenuGroup._Menus[self.Path] )
|
|
||||||
self.MenuGroup._Menus[self.Path] = nil
|
|
||||||
self = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- The MENU_GROUP_COMMAND class
|
--- The MENU_GROUP_COMMAND class
|
||||||
-- @type MENU_GROUP_COMMAND
|
-- @type MENU_GROUP_COMMAND
|
||||||
-- @extends Menu#MENU_BASE
|
-- @extends Core.Menu#MENU_BASE
|
||||||
MENU_GROUP_COMMAND = {
|
MENU_GROUP_COMMAND = {
|
||||||
ClassName = "MENU_GROUP_COMMAND"
|
ClassName = "MENU_GROUP_COMMAND"
|
||||||
}
|
}
|
||||||
@ -839,13 +890,14 @@ do
|
|||||||
-- @param ParentMenu The parent menu.
|
-- @param ParentMenu The parent menu.
|
||||||
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
||||||
-- @param CommandMenuArgument An argument for the function.
|
-- @param CommandMenuArgument An argument for the function.
|
||||||
-- @return Menu#MENU_GROUP_COMMAND self
|
-- @return #MENU_GROUP_COMMAND
|
||||||
function MENU_GROUP_COMMAND:New( MenuGroup, MenuText, ParentMenu, CommandMenuFunction, ... )
|
function MENU_GROUP_COMMAND:New( MenuGroup, MenuText, ParentMenu, CommandMenuFunction, ... )
|
||||||
|
|
||||||
MenuGroup._Menus = MenuGroup._Menus or {}
|
MenuGroup._Menus = MenuGroup._Menus or {}
|
||||||
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
|
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
|
||||||
if MenuGroup._Menus[Path] then
|
if MenuGroup._Menus[Path] then
|
||||||
self = MenuGroup._Menus[Path]
|
self = MenuGroup._Menus[Path]
|
||||||
|
self:T( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
|
||||||
else
|
else
|
||||||
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
|
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
|
||||||
MenuGroup._Menus[Path] = self
|
MenuGroup._Menus[Path] = self
|
||||||
@ -856,33 +908,45 @@ do
|
|||||||
self.MenuText = MenuText
|
self.MenuText = MenuText
|
||||||
self.ParentMenu = ParentMenu
|
self.ParentMenu = ParentMenu
|
||||||
|
|
||||||
self:T( { "Adding Command Menu ", MenuText, self.MenuParentPath } )
|
self:T( { "Adding Group Command Menu:", MenuGroup:GetName(), MenuText, self.MenuParentPath } )
|
||||||
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
|
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
|
||||||
|
|
||||||
if ParentMenu and ParentMenu.Menus then
|
if self.ParentMenu and self.ParentMenu.Menus then
|
||||||
ParentMenu.Menus[self.MenuPath] = self
|
self.ParentMenu.Menus[MenuText] = self
|
||||||
|
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
|
||||||
|
self:F( { ParentMenu.Menus, MenuText } )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:F( { MenuGroup:GetName(), MenuText, ParentMenu.MenuPath } )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a menu structure for a group.
|
--- Removes a menu structure for a group.
|
||||||
-- @param #MENU_GROUP_COMMAND self
|
-- @param #MENU_GROUP_COMMAND self
|
||||||
|
-- @param MenuTime
|
||||||
-- @return #nil
|
-- @return #nil
|
||||||
function MENU_GROUP_COMMAND:Remove()
|
function MENU_GROUP_COMMAND:Remove( MenuTime )
|
||||||
self:F( { self.MenuGroupID, self.MenuPath } )
|
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
|
||||||
|
|
||||||
if self.MenuGroup._Menus[self.Path] then
|
if not MenuTime or self.MenuTime ~= MenuTime then
|
||||||
self = self.MenuGroup._Menus[self.Path]
|
if self.MenuGroup._Menus[self.Path] then
|
||||||
|
self = self.MenuGroup._Menus[self.Path]
|
||||||
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
|
|
||||||
self.ParentMenu.Menus[self.MenuPath] = nil
|
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
|
||||||
self:E( self.MenuGroup._Menus[self.Path] )
|
self:T( { "Removing Group Command Menu:", self.MenuGroup:GetName(), self.MenuText, self.Path, self.MenuGroup._Menus[self.Path].Path } )
|
||||||
self.MenuGroup._Menus[self.Path] = nil
|
|
||||||
self = nil
|
self.ParentMenu.Menus[self.MenuText] = nil
|
||||||
|
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
|
||||||
|
if self.ParentMenu.MenuCount == 0 then
|
||||||
|
if self.MenuRemoveParent == true then
|
||||||
|
self:T( "Removing Parent Menu " )
|
||||||
|
self.ParentMenu:Remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.MenuGroup._Menus[self.Path] = nil
|
||||||
|
self = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -64,7 +64,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
|
|
||||||
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
|
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
|
||||||
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
|
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
|
||||||
self.ObjectSchedulers = self.ObjectSchedulers or {} -- setmetatable( {}, { __mode = "v" } )
|
self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } ) -- or {}
|
||||||
|
|
||||||
if Scheduler.MasterObject then
|
if Scheduler.MasterObject then
|
||||||
self.ObjectSchedulers[self.CallID] = Scheduler
|
self.ObjectSchedulers[self.CallID] = Scheduler
|
||||||
@ -181,11 +181,15 @@ function SCHEDULEDISPATCHER:Start( Scheduler, CallID )
|
|||||||
|
|
||||||
if CallID then
|
if CallID then
|
||||||
local Schedule = self.Schedule[Scheduler]
|
local Schedule = self.Schedule[Scheduler]
|
||||||
Schedule[CallID].ScheduleID = timer.scheduleFunction(
|
-- Only start when there is no ScheduleID defined!
|
||||||
Schedule[CallID].CallHandler,
|
-- This prevents to "Start" the scheduler twice with the same CallID...
|
||||||
CallID,
|
if not Schedule[CallID].ScheduleID then
|
||||||
timer.getTime() + Schedule[CallID].Start
|
Schedule[CallID].ScheduleID = timer.scheduleFunction(
|
||||||
)
|
Schedule[CallID].CallHandler,
|
||||||
|
CallID,
|
||||||
|
timer.getTime() + Schedule[CallID].Start
|
||||||
|
)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
|
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
|
||||||
self:Start( Scheduler, CallID ) -- Recursive
|
self:Start( Scheduler, CallID ) -- Recursive
|
||||||
@ -198,7 +202,12 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
|||||||
|
|
||||||
if CallID then
|
if CallID then
|
||||||
local Schedule = self.Schedule[Scheduler]
|
local Schedule = self.Schedule[Scheduler]
|
||||||
timer.removeFunction( Schedule[CallID].ScheduleID )
|
-- Only stop when there is a ScheduleID defined for the CallID.
|
||||||
|
-- So, when the scheduler was stopped before, do nothing.
|
||||||
|
if Schedule[CallID].ScheduleID then
|
||||||
|
timer.removeFunction( Schedule[CallID].ScheduleID )
|
||||||
|
Schedule[CallID].ScheduleID = nil
|
||||||
|
end
|
||||||
else
|
else
|
||||||
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
|
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
|
||||||
self:Stop( Scheduler, CallID ) -- Recursive
|
self:Stop( Scheduler, CallID ) -- Recursive
|
||||||
@ -206,5 +215,13 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function SCHEDULEDISPATCHER:Clear( Scheduler )
|
||||||
|
self:F2( { Scheduler = Scheduler } )
|
||||||
|
|
||||||
|
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
|
||||||
|
self:Stop( Scheduler, CallID ) -- Recursive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
--- This module contains the SCHEDULER class.
|
--- **Core** - SCHEDULER prepares and handles the **execution of functions over scheduled time (intervals)**.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
-- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
|
-- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
|
||||||
--
|
--
|
||||||
-- The @{Scheduler#SCHEDULER} class creates schedule.
|
-- The @{Scheduler#SCHEDULER} class creates schedule.
|
||||||
@ -147,6 +151,13 @@ function SCHEDULER:Remove( ScheduleID )
|
|||||||
_SCHEDULEDISPATCHER:Remove( self, ScheduleID )
|
_SCHEDULEDISPATCHER:Remove( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Clears all pending schedules.
|
||||||
|
-- @param #SCHEDULER self
|
||||||
|
function SCHEDULER:Clear()
|
||||||
|
self:F3( )
|
||||||
|
|
||||||
|
_SCHEDULEDISPATCHER:Clear( self )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -240,6 +240,7 @@ SET_BASE = {
|
|||||||
Filter = {},
|
Filter = {},
|
||||||
Set = {},
|
Set = {},
|
||||||
List = {},
|
List = {},
|
||||||
|
Index = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
|
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
|
||||||
@ -258,10 +259,14 @@ function SET_BASE:New( Database )
|
|||||||
self.YieldInterval = 10
|
self.YieldInterval = 10
|
||||||
self.TimeInterval = 0.001
|
self.TimeInterval = 0.001
|
||||||
|
|
||||||
|
self.Set = {}
|
||||||
|
|
||||||
self.List = {}
|
self.List = {}
|
||||||
self.List.__index = self.List
|
self.List.__index = self.List
|
||||||
self.List = setmetatable( { Count = 0 }, self.List )
|
self.List = setmetatable( { Count = 0 }, self.List )
|
||||||
|
|
||||||
|
self.Index = {}
|
||||||
|
|
||||||
self.CallScheduler = SCHEDULER:New( self )
|
self.CallScheduler = SCHEDULER:New( self )
|
||||||
|
|
||||||
self:SetEventPriority( 2 )
|
self:SetEventPriority( 2 )
|
||||||
@ -313,6 +318,8 @@ function SET_BASE:Add( ObjectName, Object )
|
|||||||
|
|
||||||
self.Set[ObjectName] = t._
|
self.Set[ObjectName] = t._
|
||||||
|
|
||||||
|
table.insert( self.Index, ObjectName )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
|
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
|
||||||
@ -364,7 +371,15 @@ function SET_BASE:Remove( ObjectName )
|
|||||||
t._prev = nil
|
t._prev = nil
|
||||||
self.List.Count = self.List.Count - 1
|
self.List.Count = self.List.Count - 1
|
||||||
|
|
||||||
|
for Index, Key in ipairs( self.Index ) do
|
||||||
|
if Key == ObjectName then
|
||||||
|
table.remove( self.Index, Index )
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.Set[ObjectName] = nil
|
self.Set[ObjectName] = nil
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -384,12 +399,50 @@ function SET_BASE:Get( ObjectName )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the first object from the @{Set#SET_BASE} and derived classes.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @return Core.Base#BASE
|
||||||
|
function SET_BASE:GetFirst()
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
local ObjectName = self.Index[1]
|
||||||
|
local FirstObject = self.Set[ObjectName]
|
||||||
|
self:T3( { FirstObject } )
|
||||||
|
return FirstObject
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets the last object from the @{Set#SET_BASE} and derived classes.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @return Core.Base#BASE
|
||||||
|
function SET_BASE:GetLast()
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
local ObjectName = self.Index[#self.Index]
|
||||||
|
local LastObject = self.Set[ObjectName]
|
||||||
|
self:T3( { LastObject } )
|
||||||
|
return LastObject
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets a random object from the @{Set#SET_BASE} and derived classes.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @return Core.Base#BASE
|
||||||
|
function SET_BASE:GetRandom()
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
local RandomItem = self.Set[self.Index[math.random(#self.Index)]]
|
||||||
|
|
||||||
|
self:T3( { RandomItem } )
|
||||||
|
|
||||||
|
return RandomItem
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
|
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @return #number Count
|
-- @return #number Count
|
||||||
function SET_BASE:Count()
|
function SET_BASE:Count()
|
||||||
|
|
||||||
return self.List.Count
|
return #self.Index
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -652,7 +705,8 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 )
|
--self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 )
|
||||||
|
Schedule()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -725,7 +779,7 @@ end
|
|||||||
|
|
||||||
--- SET_GROUP class
|
--- SET_GROUP class
|
||||||
-- @type SET_GROUP
|
-- @type SET_GROUP
|
||||||
-- @extends #SET_BASE
|
-- @extends Core.Set#SET_BASE
|
||||||
SET_GROUP = {
|
SET_GROUP = {
|
||||||
ClassName = "SET_GROUP",
|
ClassName = "SET_GROUP",
|
||||||
Filter = {
|
Filter = {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
--- **Core** - ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**.
|
--- **Core** - ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- There are essentially two core functions that zones accomodate:
|
-- There are essentially two core functions that zones accomodate:
|
||||||
@ -247,6 +249,58 @@ function ZONE_BASE:GetVec2()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a @{Point#POINT_VEC2} of the zone.
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||||
|
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
|
||||||
|
function ZONE_BASE:GetPointVec2()
|
||||||
|
self:F2( self.ZoneName )
|
||||||
|
|
||||||
|
local Vec2 = self:GetVec2()
|
||||||
|
|
||||||
|
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 )
|
||||||
|
|
||||||
|
self:T2( { PointVec2 } )
|
||||||
|
|
||||||
|
return PointVec2
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Returns the @{DCSTypes#Vec3} of the zone.
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||||
|
-- @return Dcs.DCSTypes#Vec3 The Vec3 of the zone.
|
||||||
|
function ZONE_BASE:GetVec3( Height )
|
||||||
|
self:F2( self.ZoneName )
|
||||||
|
|
||||||
|
Height = Height or 0
|
||||||
|
|
||||||
|
local Vec2 = self:GetVec2()
|
||||||
|
|
||||||
|
local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y }
|
||||||
|
|
||||||
|
self:T2( { Vec3 } )
|
||||||
|
|
||||||
|
return Vec3
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a @{Point#POINT_VEC3} of the zone.
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||||
|
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
|
||||||
|
function ZONE_BASE:GetPointVec3( Height )
|
||||||
|
self:F2( self.ZoneName )
|
||||||
|
|
||||||
|
local Vec3 = self:GetVec3( Height )
|
||||||
|
|
||||||
|
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
|
||||||
|
|
||||||
|
self:T2( { PointVec3 } )
|
||||||
|
|
||||||
|
return PointVec3
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Define a random @{DCSTypes#Vec2} within the zone.
|
--- Define a random @{DCSTypes#Vec2} within the zone.
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates.
|
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates.
|
||||||
@ -261,6 +315,13 @@ function ZONE_BASE:GetRandomPointVec2()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Define a random @{Point#POINT_VEC3} within the zone.
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates.
|
||||||
|
function ZONE_BASE:GetRandomPointVec3()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the bounding square the zone.
|
--- Get the bounding square the zone.
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @return #nil The bounding square.
|
-- @return #nil The bounding square.
|
||||||
@ -347,8 +408,9 @@ end
|
|||||||
--- Bounds the zone with tires.
|
--- Bounds the zone with tires.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @param #number Points (optional) The amount of points in the circle.
|
-- @param #number Points (optional) The amount of points in the circle.
|
||||||
|
-- @param #boolean UnBound If true the tyres will be destroyed.
|
||||||
-- @return #ZONE_RADIUS self
|
-- @return #ZONE_RADIUS self
|
||||||
function ZONE_RADIUS:BoundZone( Points )
|
function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound )
|
||||||
|
|
||||||
local Point = {}
|
local Point = {}
|
||||||
local Vec2 = self:GetVec2()
|
local Vec2 = self:GetVec2()
|
||||||
@ -364,8 +426,10 @@ function ZONE_RADIUS:BoundZone( Points )
|
|||||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||||
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
|
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
|
||||||
|
|
||||||
|
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
|
||||||
|
|
||||||
local Tire = {
|
local Tire = {
|
||||||
["country"] = "USA",
|
["country"] = CountryName,
|
||||||
["category"] = "Fortifications",
|
["category"] = "Fortifications",
|
||||||
["canCargo"] = false,
|
["canCargo"] = false,
|
||||||
["shape_name"] = "H-tyre_B_WF",
|
["shape_name"] = "H-tyre_B_WF",
|
||||||
@ -377,7 +441,10 @@ function ZONE_RADIUS:BoundZone( Points )
|
|||||||
["heading"] = 0,
|
["heading"] = 0,
|
||||||
} -- end of ["group"]
|
} -- end of ["group"]
|
||||||
|
|
||||||
coalition.addStaticObject( country.id.USA, Tire )
|
local Group = coalition.addStaticObject( CountryID, Tire )
|
||||||
|
if UnBound and UnBound == true then
|
||||||
|
Group:destroy()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -810,8 +877,9 @@ end
|
|||||||
|
|
||||||
--- Smokes the zone boundaries in a color.
|
--- Smokes the zone boundaries in a color.
|
||||||
-- @param #ZONE_POLYGON_BASE self
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @param #boolean UnBound If true, the tyres will be destroyed.
|
||||||
-- @return #ZONE_POLYGON_BASE self
|
-- @return #ZONE_POLYGON_BASE self
|
||||||
function ZONE_POLYGON_BASE:BoundZone( )
|
function ZONE_POLYGON_BASE:BoundZone( UnBound )
|
||||||
|
|
||||||
local i
|
local i
|
||||||
local j
|
local j
|
||||||
@ -840,8 +908,11 @@ function ZONE_POLYGON_BASE:BoundZone( )
|
|||||||
["name"] = string.format( "%s-Tire #%0d", self:GetName(), ((i - 1) * Segments) + Segment ),
|
["name"] = string.format( "%s-Tire #%0d", self:GetName(), ((i - 1) * Segments) + Segment ),
|
||||||
["heading"] = 0,
|
["heading"] = 0,
|
||||||
} -- end of ["group"]
|
} -- end of ["group"]
|
||||||
|
|
||||||
coalition.addStaticObject( country.id.USA, Tire )
|
local Group = coalition.addStaticObject( country.id.USA, Tire )
|
||||||
|
if UnBound and UnBound == true then
|
||||||
|
Group:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
j = i
|
j = i
|
||||||
|
|||||||
@ -29,7 +29,9 @@ CLEANUP = {
|
|||||||
-- or
|
-- or
|
||||||
-- CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 )
|
-- CleanUpTbilisi = CLEANUP:New( 'CLEAN Tbilisi', 150 )
|
||||||
-- CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 )
|
-- CleanUpKutaisi = CLEANUP:New( 'CLEAN Kutaisi', 600 )
|
||||||
function CLEANUP:New( ZoneNames, TimeInterval ) local self = BASE:Inherit( self, BASE:New() )
|
function CLEANUP:New( ZoneNames, TimeInterval )
|
||||||
|
|
||||||
|
local self = BASE:Inherit( self, BASE:New() ) -- #CLEANUP
|
||||||
self:F( { ZoneNames, TimeInterval } )
|
self:F( { ZoneNames, TimeInterval } )
|
||||||
|
|
||||||
if type( ZoneNames ) == 'table' then
|
if type( ZoneNames ) == 'table' then
|
||||||
@ -41,7 +43,7 @@ function CLEANUP:New( ZoneNames, TimeInterval ) local self = BASE:Inherit( self,
|
|||||||
self.TimeInterval = TimeInterval
|
self.TimeInterval = TimeInterval
|
||||||
end
|
end
|
||||||
|
|
||||||
_EVENTDISPATCHER:OnBirth( self._OnEventBirth, self )
|
self:HandleEvent( EVENTS.Birth )
|
||||||
|
|
||||||
self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, TimeInterval )
|
self.CleanUpScheduler = SCHEDULER:New( self, self._CleanUpScheduler, {}, 1, TimeInterval )
|
||||||
|
|
||||||
@ -102,32 +104,24 @@ function CLEANUP:_DestroyMissile( MissileObject )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function CLEANUP:_OnEventBirth( Event )
|
--- @param #CLEANUP self
|
||||||
self:F( { Event } )
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function CLEANUP:_OnEventBirth( EventData )
|
||||||
|
self:F( { EventData } )
|
||||||
|
|
||||||
self.CleanUpList[Event.IniDCSUnitName] = {}
|
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
||||||
self.CleanUpList[Event.IniDCSUnitName].CleanUpUnit = Event.IniDCSUnit
|
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniDCSUnit
|
||||||
self.CleanUpList[Event.IniDCSUnitName].CleanUpGroup = Event.IniDCSGroup
|
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroup = EventData.IniDCSGroup
|
||||||
self.CleanUpList[Event.IniDCSUnitName].CleanUpGroupName = Event.IniDCSGroupName
|
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroupName = EventData.IniDCSGroupName
|
||||||
self.CleanUpList[Event.IniDCSUnitName].CleanUpUnitName = Event.IniDCSUnitName
|
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnitName = EventData.IniDCSUnitName
|
||||||
|
|
||||||
_EVENTDISPATCHER:OnEngineShutDownForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
|
|
||||||
_EVENTDISPATCHER:OnEngineStartUpForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
|
|
||||||
_EVENTDISPATCHER:OnHitForUnit( Event.IniDCSUnitName, self._EventAddForCleanUp, self )
|
|
||||||
_EVENTDISPATCHER:OnPilotDeadForUnit( Event.IniDCSUnitName, self._EventCrash, self )
|
|
||||||
_EVENTDISPATCHER:OnDeadForUnit( Event.IniDCSUnitName, self._EventCrash, self )
|
|
||||||
_EVENTDISPATCHER:OnCrashForUnit( Event.IniDCSUnitName, self._EventCrash, self )
|
|
||||||
_EVENTDISPATCHER:OnShotForUnit( Event.IniDCSUnitName, self._EventShot, self )
|
|
||||||
|
|
||||||
--self:AddEvent( world.event.S_EVENT_ENGINE_SHUTDOWN, self._EventAddForCleanUp )
|
|
||||||
--self:AddEvent( world.event.S_EVENT_ENGINE_STARTUP, self._EventAddForCleanUp )
|
|
||||||
-- self:AddEvent( world.event.S_EVENT_HIT, self._EventAddForCleanUp ) -- , self._EventHitCleanUp )
|
|
||||||
-- self:AddEvent( world.event.S_EVENT_CRASH, self._EventCrash ) -- , self._EventHitCleanUp )
|
|
||||||
-- --self:AddEvent( world.event.S_EVENT_DEAD, self._EventCrash )
|
|
||||||
-- self:AddEvent( world.event.S_EVENT_SHOT, self._EventShot )
|
|
||||||
--
|
|
||||||
-- self:EnableEvents()
|
|
||||||
|
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.EngineShutdown , self._EventAddForCleanUp )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.EngineStartup, self._EventAddForCleanUp )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.Hit, self._EventAddForCleanUp )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.PilotDead, self._EventCrash )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.Dead, self._EventCrash )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.Crash, self._EventCrash )
|
||||||
|
EventData.IniUnit:HandleEvent( EVENTS.Shot, self._EventShot )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -84,7 +84,7 @@
|
|||||||
--
|
--
|
||||||
-- ESCORT initialization methods.
|
-- ESCORT initialization methods.
|
||||||
-- ==============================
|
-- ==============================
|
||||||
-- The following menus are created within the RADIO MENU of an active unit hosted by a player:
|
-- The following menus are created within the RADIO MENU (F10) of an active unit hosted by a player:
|
||||||
--
|
--
|
||||||
-- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client.
|
-- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client.
|
||||||
-- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position.
|
-- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position.
|
||||||
@ -128,6 +128,7 @@
|
|||||||
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
|
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
|
||||||
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
|
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
|
||||||
-- @field Core.Menu#MENU_CLIENT EscortMenuResumeMission
|
-- @field Core.Menu#MENU_CLIENT EscortMenuResumeMission
|
||||||
|
-- @field Functional.Detection#DETECTION_BASE Detection
|
||||||
ESCORT = {
|
ESCORT = {
|
||||||
ClassName = "ESCORT",
|
ClassName = "ESCORT",
|
||||||
EscortName = nil, -- The Escort Name
|
EscortName = nil, -- The Escort Name
|
||||||
@ -176,14 +177,22 @@ ESCORT = {
|
|||||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||||
-- EscortPlanes = ESCORT:New( EscortClient, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
-- EscortPlanes = ESCORT:New( EscortClient, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||||
function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
|
function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
|
||||||
|
local self = BASE:Inherit( self, BASE:New() ) -- #ESCORT
|
||||||
self:F( { EscortClient, EscortGroup, EscortName } )
|
self:F( { EscortClient, EscortGroup, EscortName } )
|
||||||
|
|
||||||
self.EscortClient = EscortClient -- Wrapper.Client#CLIENT
|
self.EscortClient = EscortClient -- Wrapper.Client#CLIENT
|
||||||
self.EscortGroup = EscortGroup -- Wrapper.Group#GROUP
|
self.EscortGroup = EscortGroup -- Wrapper.Group#GROUP
|
||||||
self.EscortName = EscortName
|
self.EscortName = EscortName
|
||||||
self.EscortBriefing = EscortBriefing
|
self.EscortBriefing = EscortBriefing
|
||||||
|
|
||||||
|
self.EscortSetGroup = SET_GROUP:New()
|
||||||
|
self.EscortSetGroup:AddObject( self.EscortGroup )
|
||||||
|
self.EscortSetGroup:Flush()
|
||||||
|
self.Detection = DETECTION_UNITS:New( self.EscortSetGroup, 15000 )
|
||||||
|
|
||||||
|
self.EscortGroup.Detection = self.Detection
|
||||||
|
|
||||||
-- Set EscortGroup known at EscortClient.
|
-- Set EscortGroup known at EscortClient.
|
||||||
if not self.EscortClient._EscortGroups then
|
if not self.EscortClient._EscortGroups then
|
||||||
self.EscortClient._EscortGroups = {}
|
self.EscortClient._EscortGroups = {}
|
||||||
@ -193,7 +202,7 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
|
|||||||
self.EscortClient._EscortGroups[EscortGroup:GetName()] = {}
|
self.EscortClient._EscortGroups[EscortGroup:GetName()] = {}
|
||||||
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortGroup = self.EscortGroup
|
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortGroup = self.EscortGroup
|
||||||
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortName = self.EscortName
|
self.EscortClient._EscortGroups[EscortGroup:GetName()].EscortName = self.EscortName
|
||||||
self.EscortClient._EscortGroups[EscortGroup:GetName()].Targets = {}
|
self.EscortClient._EscortGroups[EscortGroup:GetName()].Detection = self.EscortGroup.Detection
|
||||||
end
|
end
|
||||||
|
|
||||||
self.EscortMenu = MENU_CLIENT:New( self.EscortClient, self.EscortName )
|
self.EscortMenu = MENU_CLIENT:New( self.EscortClient, self.EscortName )
|
||||||
@ -218,13 +227,30 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName, EscortBriefing )
|
|||||||
self.FollowDistance = 100
|
self.FollowDistance = 100
|
||||||
self.CT1 = 0
|
self.CT1 = 0
|
||||||
self.GT1 = 0
|
self.GT1 = 0
|
||||||
self.FollowScheduler = SCHEDULER:New( self, self._FollowScheduler, {}, 1, .5, .01 )
|
|
||||||
self.EscortMode = ESCORT.MODE.MISSION
|
|
||||||
self.FollowScheduler:Stop()
|
|
||||||
|
|
||||||
|
self.FollowScheduler, self.FollowSchedule = SCHEDULER:New( self, self._FollowScheduler, {}, 1, .5, .01 )
|
||||||
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
|
self.EscortMode = ESCORT.MODE.MISSION
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set a Detection method for the EscortClient to be reported upon.
|
||||||
|
-- Detection methods are based on the derived classes from DETECTION_BASE.
|
||||||
|
-- @param #ESCORT self
|
||||||
|
-- @param Function.Detection#DETECTION_BASE Detection
|
||||||
|
function ESCORT:SetDetection( Detection )
|
||||||
|
|
||||||
|
self.Detection = Detection
|
||||||
|
self.EscortGroup.Detection = self.Detection
|
||||||
|
self.EscortClient._EscortGroups[self.EscortGroup:GetName()].Detection = self.EscortGroup.Detection
|
||||||
|
|
||||||
|
Detection:__Start( 1 )
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to.
|
--- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to.
|
||||||
-- This allows to visualize where the escort is flying to.
|
-- This allows to visualize where the escort is flying to.
|
||||||
-- @param #ESCORT self
|
-- @param #ESCORT self
|
||||||
@ -282,7 +308,7 @@ function ESCORT:MenuFollowAt( Distance )
|
|||||||
self.EscortMenuJoinUpAndFollow = {}
|
self.EscortMenuJoinUpAndFollow = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
self.EscortMenuJoinUpAndFollow[#self.EscortMenuJoinUpAndFollow+1] = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at " .. Distance, self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = Distance } )
|
self.EscortMenuJoinUpAndFollow[#self.EscortMenuJoinUpAndFollow+1] = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at " .. Distance, self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, self, Distance )
|
||||||
|
|
||||||
self.EscortMode = ESCORT.MODE.FOLLOW
|
self.EscortMode = ESCORT.MODE.FOLLOW
|
||||||
end
|
end
|
||||||
@ -340,11 +366,10 @@ function ESCORT:MenuHoldAtEscortPosition( Height, Seconds, MenuTextFormat )
|
|||||||
MenuText,
|
MenuText,
|
||||||
self.EscortMenuHold,
|
self.EscortMenuHold,
|
||||||
ESCORT._HoldPosition,
|
ESCORT._HoldPosition,
|
||||||
{ ParamSelf = self,
|
self,
|
||||||
ParamOrbitGroup = self.EscortGroup,
|
self.EscortGroup,
|
||||||
ParamHeight = Height,
|
Height,
|
||||||
ParamSeconds = Seconds
|
Seconds
|
||||||
}
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -461,9 +486,8 @@ function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat )
|
|||||||
MenuText,
|
MenuText,
|
||||||
self.EscortMenuScan,
|
self.EscortMenuScan,
|
||||||
ESCORT._ScanTargets,
|
ESCORT._ScanTargets,
|
||||||
{ ParamSelf = self,
|
self,
|
||||||
ParamScanDuration = 30
|
30
|
||||||
}
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -493,11 +517,11 @@ function ESCORT:MenuFlare( MenuTextFormat )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not self.EscortMenuFlare then
|
if not self.EscortMenuFlare then
|
||||||
self.EscortMenuFlare = MENU_CLIENT:New( self.EscortClient, MenuText, self.EscortMenuReportNavigation, ESCORT._Flare, { ParamSelf = self } )
|
self.EscortMenuFlare = MENU_CLIENT:New( self.EscortClient, MenuText, self.EscortMenuReportNavigation, ESCORT._Flare, self )
|
||||||
self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Green, ParamMessage = "Released a green flare!" } )
|
self.EscortMenuFlareGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Green, "Released a green flare!" )
|
||||||
self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Red, ParamMessage = "Released a red flare!" } )
|
self.EscortMenuFlareRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Red, "Released a red flare!" )
|
||||||
self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.White, ParamMessage = "Released a white flare!" } )
|
self.EscortMenuFlareWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.White, "Released a white flare!" )
|
||||||
self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, { ParamSelf = self, ParamColor = FLARECOLOR.Yellow, ParamMessage = "Released a yellow flare!" } )
|
self.EscortMenuFlareYellow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release yellow flare", self.EscortMenuFlare, ESCORT._Flare, self, FLARECOLOR.Yellow, "Released a yellow flare!" )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -526,12 +550,12 @@ function ESCORT:MenuSmoke( MenuTextFormat )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not self.EscortMenuSmoke then
|
if not self.EscortMenuSmoke then
|
||||||
self.EscortMenuSmoke = MENU_CLIENT:New( self.EscortClient, "Smoke", self.EscortMenuReportNavigation, ESCORT._Smoke, { ParamSelf = self } )
|
self.EscortMenuSmoke = MENU_CLIENT:New( self.EscortClient, "Smoke", self.EscortMenuReportNavigation, ESCORT._Smoke, self )
|
||||||
self.EscortMenuSmokeGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Green, ParamMessage = "Releasing green smoke!" } )
|
self.EscortMenuSmokeGreen = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release green smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Green, "Releasing green smoke!" )
|
||||||
self.EscortMenuSmokeRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Red, ParamMessage = "Releasing red smoke!" } )
|
self.EscortMenuSmokeRed = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release red smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Red, "Releasing red smoke!" )
|
||||||
self.EscortMenuSmokeWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.White, ParamMessage = "Releasing white smoke!" } )
|
self.EscortMenuSmokeWhite = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release white smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.White, "Releasing white smoke!" )
|
||||||
self.EscortMenuSmokeOrange = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release orange smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Orange, ParamMessage = "Releasing orange smoke!" } )
|
self.EscortMenuSmokeOrange = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release orange smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Orange, "Releasing orange smoke!" )
|
||||||
self.EscortMenuSmokeBlue = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release blue smoke", self.EscortMenuSmoke, ESCORT._Smoke, { ParamSelf = self, ParamColor = UNIT.SmokeColor.Blue, ParamMessage = "Releasing blue smoke!" } )
|
self.EscortMenuSmokeBlue = MENU_CLIENT_COMMAND:New( self.EscortClient, "Release blue smoke", self.EscortMenuSmoke, ESCORT._Smoke, self, SMOKECOLOR.Blue, "Releasing blue smoke!" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -556,9 +580,9 @@ function ESCORT:MenuReportTargets( Seconds )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Report Targets
|
-- Report Targets
|
||||||
self.EscortMenuReportNearbyTargetsNow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets now!", self.EscortMenuReportNearbyTargets, ESCORT._ReportNearbyTargetsNow, { ParamSelf = self } )
|
self.EscortMenuReportNearbyTargetsNow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets now!", self.EscortMenuReportNearbyTargets, ESCORT._ReportNearbyTargetsNow, self )
|
||||||
self.EscortMenuReportNearbyTargetsOn = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets on", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, { ParamSelf = self, ParamReportTargets = true } )
|
self.EscortMenuReportNearbyTargetsOn = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets on", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, self, true )
|
||||||
self.EscortMenuReportNearbyTargetsOff = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets off", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, { ParamSelf = self, ParamReportTargets = false, } )
|
self.EscortMenuReportNearbyTargetsOff = MENU_CLIENT_COMMAND:New( self.EscortClient, "Report targets off", self.EscortMenuReportNearbyTargets, ESCORT._SwitchReportNearbyTargets, self, false )
|
||||||
|
|
||||||
-- Attack Targets
|
-- Attack Targets
|
||||||
self.EscortMenuAttackNearbyTargets = MENU_CLIENT:New( self.EscortClient, "Attack targets", self.EscortMenu )
|
self.EscortMenuAttackNearbyTargets = MENU_CLIENT:New( self.EscortClient, "Attack targets", self.EscortMenu )
|
||||||
@ -595,16 +619,16 @@ function ESCORT:MenuROE( MenuTextFormat )
|
|||||||
-- Rules of Engagement
|
-- Rules of Engagement
|
||||||
self.EscortMenuROE = MENU_CLIENT:New( self.EscortClient, "ROE", self.EscortMenu )
|
self.EscortMenuROE = MENU_CLIENT:New( self.EscortClient, "ROE", self.EscortMenu )
|
||||||
if self.EscortGroup:OptionROEHoldFirePossible() then
|
if self.EscortGroup:OptionROEHoldFirePossible() then
|
||||||
self.EscortMenuROEHoldFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Hold Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEHoldFire(), ParamMessage = "Holding weapons!" } )
|
self.EscortMenuROEHoldFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Hold Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEHoldFire(), "Holding weapons!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROEReturnFirePossible() then
|
if self.EscortGroup:OptionROEReturnFirePossible() then
|
||||||
self.EscortMenuROEReturnFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Return Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEReturnFire(), ParamMessage = "Returning fire!" } )
|
self.EscortMenuROEReturnFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Return Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEReturnFire(), "Returning fire!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROEOpenFirePossible() then
|
if self.EscortGroup:OptionROEOpenFirePossible() then
|
||||||
self.EscortMenuROEOpenFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Open Fire", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEOpenFire(), ParamMessage = "Opening fire on designated targets!!" } )
|
self.EscortMenuROEOpenFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Open Fire", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEOpenFire(), "Opening fire on designated targets!!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROEWeaponFreePossible() then
|
if self.EscortGroup:OptionROEWeaponFreePossible() then
|
||||||
self.EscortMenuROEWeaponFree = MENU_CLIENT_COMMAND:New( self.EscortClient, "Weapon Free", self.EscortMenuROE, ESCORT._ROE, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROEWeaponFree(), ParamMessage = "Opening fire on targets of opportunity!" } )
|
self.EscortMenuROEWeaponFree = MENU_CLIENT_COMMAND:New( self.EscortClient, "Weapon Free", self.EscortMenuROE, ESCORT._ROE, self, self.EscortGroup:OptionROEWeaponFree(), "Opening fire on targets of opportunity!" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -624,16 +648,16 @@ function ESCORT:MenuEvasion( MenuTextFormat )
|
|||||||
-- Reaction to Threats
|
-- Reaction to Threats
|
||||||
self.EscortMenuEvasion = MENU_CLIENT:New( self.EscortClient, "Evasion", self.EscortMenu )
|
self.EscortMenuEvasion = MENU_CLIENT:New( self.EscortClient, "Evasion", self.EscortMenu )
|
||||||
if self.EscortGroup:OptionROTNoReactionPossible() then
|
if self.EscortGroup:OptionROTNoReactionPossible() then
|
||||||
self.EscortMenuEvasionNoReaction = MENU_CLIENT_COMMAND:New( self.EscortClient, "Fight until death", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTNoReaction(), ParamMessage = "Fighting until death!" } )
|
self.EscortMenuEvasionNoReaction = MENU_CLIENT_COMMAND:New( self.EscortClient, "Fight until death", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTNoReaction(), "Fighting until death!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROTPassiveDefensePossible() then
|
if self.EscortGroup:OptionROTPassiveDefensePossible() then
|
||||||
self.EscortMenuEvasionPassiveDefense = MENU_CLIENT_COMMAND:New( self.EscortClient, "Use flares, chaff and jammers", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTPassiveDefense(), ParamMessage = "Defending using jammers, chaff and flares!" } )
|
self.EscortMenuEvasionPassiveDefense = MENU_CLIENT_COMMAND:New( self.EscortClient, "Use flares, chaff and jammers", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTPassiveDefense(), "Defending using jammers, chaff and flares!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROTEvadeFirePossible() then
|
if self.EscortGroup:OptionROTEvadeFirePossible() then
|
||||||
self.EscortMenuEvasionEvadeFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Evade enemy fire", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTEvadeFire(), ParamMessage = "Evading on enemy fire!" } )
|
self.EscortMenuEvasionEvadeFire = MENU_CLIENT_COMMAND:New( self.EscortClient, "Evade enemy fire", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTEvadeFire(), "Evading on enemy fire!" )
|
||||||
end
|
end
|
||||||
if self.EscortGroup:OptionROTVerticalPossible() then
|
if self.EscortGroup:OptionROTVerticalPossible() then
|
||||||
self.EscortMenuOptionEvasionVertical = MENU_CLIENT_COMMAND:New( self.EscortClient, "Go below radar and evade fire", self.EscortMenuEvasion, ESCORT._ROT, { ParamSelf = self, ParamFunction = self.EscortGroup:OptionROTVertical(), ParamMessage = "Evading on enemy fire with vertical manoeuvres!" } )
|
self.EscortMenuOptionEvasionVertical = MENU_CLIENT_COMMAND:New( self.EscortClient, "Go below radar and evade fire", self.EscortMenuEvasion, ESCORT._ROT, self, self.EscortGroup:OptionROTVertical(), "Evading on enemy fire with vertical manoeuvres!" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -658,18 +682,14 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._HoldPosition( MenuParam )
|
function ESCORT:_HoldPosition( OrbitGroup, OrbitHeight, OrbitSeconds )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local OrbitGroup = MenuParam.ParamOrbitGroup -- Wrapper.Group#GROUP
|
|
||||||
local OrbitUnit = OrbitGroup:GetUnit(1) -- Wrapper.Unit#UNIT
|
local OrbitUnit = OrbitGroup:GetUnit(1) -- Wrapper.Unit#UNIT
|
||||||
local OrbitHeight = MenuParam.ParamHeight
|
|
||||||
local OrbitSeconds = MenuParam.ParamSeconds -- Not implemented yet
|
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
local PointFrom = {}
|
local PointFrom = {}
|
||||||
local GroupVec3 = EscortGroup:GetUnit(1):GetVec3()
|
local GroupVec3 = EscortGroup:GetUnit(1):GetVec3()
|
||||||
@ -702,13 +722,12 @@ function ESCORT._HoldPosition( MenuParam )
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._JoinUpAndFollow( MenuParam )
|
function ESCORT:_JoinUpAndFollow( Distance )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
self.Distance = MenuParam.ParamDistance
|
self.Distance = Distance
|
||||||
|
|
||||||
self:JoinUpAndFollow( EscortGroup, EscortClient, self.Distance )
|
self:JoinUpAndFollow( EscortGroup, EscortClient, self.Distance )
|
||||||
end
|
end
|
||||||
@ -721,7 +740,7 @@ end
|
|||||||
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
|
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
|
||||||
self:F( { EscortGroup, EscortClient, Distance } )
|
self:F( { EscortGroup, EscortClient, Distance } )
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
EscortGroup:OptionROEHoldFire()
|
EscortGroup:OptionROEHoldFire()
|
||||||
EscortGroup:OptionROTPassiveDefense()
|
EscortGroup:OptionROTPassiveDefense()
|
||||||
@ -730,44 +749,35 @@ function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
|
|||||||
|
|
||||||
self.CT1 = 0
|
self.CT1 = 0
|
||||||
self.GT1 = 0
|
self.GT1 = 0
|
||||||
self.FollowScheduler:Start()
|
self.FollowScheduler:Start( self.FollowSchedule )
|
||||||
|
|
||||||
EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient )
|
EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._Flare( MenuParam )
|
function ESCORT:_Flare( Color, Message )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local Color = MenuParam.ParamColor
|
|
||||||
local Message = MenuParam.ParamMessage
|
|
||||||
|
|
||||||
EscortGroup:GetUnit(1):Flare( Color )
|
EscortGroup:GetUnit(1):Flare( Color )
|
||||||
EscortGroup:MessageToClient( Message, 10, EscortClient )
|
EscortGroup:MessageToClient( Message, 10, EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._Smoke( MenuParam )
|
function ESCORT:_Smoke( Color, Message )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local Color = MenuParam.ParamColor
|
|
||||||
local Message = MenuParam.ParamMessage
|
|
||||||
|
|
||||||
EscortGroup:GetUnit(1):Smoke( Color )
|
EscortGroup:GetUnit(1):Smoke( Color )
|
||||||
EscortGroup:MessageToClient( Message, 10, EscortClient )
|
EscortGroup:MessageToClient( Message, 10, EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._ReportNearbyTargetsNow( MenuParam )
|
function ESCORT:_ReportNearbyTargetsNow()
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
@ -775,17 +785,16 @@ function ESCORT._ReportNearbyTargetsNow( MenuParam )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ESCORT._SwitchReportNearbyTargets( MenuParam )
|
function ESCORT:_SwitchReportNearbyTargets( ReportTargets )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
self.ReportTargets = MenuParam.ParamReportTargets
|
self.ReportTargets = ReportTargets
|
||||||
|
|
||||||
if self.ReportTargets then
|
if self.ReportTargets then
|
||||||
if not self.ReportTargetsScheduler then
|
if not self.ReportTargetsScheduler then
|
||||||
self.ReportTargetsScheduler = SCHEDULER:New( self, self._ReportTargetsScheduler, {}, 1, 30 )
|
self.ReportTargetsScheduler:Schedule( self, self._ReportTargetsScheduler, {}, 1, 30 )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
routines.removeFunction( self.ReportTargetsScheduler )
|
routines.removeFunction( self.ReportTargetsScheduler )
|
||||||
@ -794,40 +803,31 @@ function ESCORT._SwitchReportNearbyTargets( MenuParam )
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._ScanTargets( MenuParam )
|
function ESCORT:_ScanTargets( ScanDuration )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
|
||||||
local EscortGroup = self.EscortGroup
|
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local ScanDuration = MenuParam.ParamScanDuration
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
|
||||||
|
|
||||||
if EscortGroup:IsHelicopter() then
|
if EscortGroup:IsHelicopter() then
|
||||||
SCHEDULER:New( EscortGroup, EscortGroup.PushTask,
|
EscortGroup:PushTask(
|
||||||
{ EscortGroup:TaskControlled(
|
EscortGroup:TaskControlled(
|
||||||
EscortGroup:TaskOrbitCircle( 200, 20 ),
|
EscortGroup:TaskOrbitCircle( 200, 20 ),
|
||||||
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
|
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
|
||||||
)
|
), 1 )
|
||||||
},
|
|
||||||
1
|
|
||||||
)
|
|
||||||
elseif EscortGroup:IsAirPlane() then
|
elseif EscortGroup:IsAirPlane() then
|
||||||
SCHEDULER:New( EscortGroup, EscortGroup.PushTask,
|
EscortGroup:PushTask(
|
||||||
{ EscortGroup:TaskControlled(
|
EscortGroup:TaskControlled(
|
||||||
EscortGroup:TaskOrbitCircle( 1000, 500 ),
|
EscortGroup:TaskOrbitCircle( 1000, 500 ),
|
||||||
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
|
EscortGroup:TaskCondition( nil, nil, nil, nil, ScanDuration, nil )
|
||||||
)
|
), 1 )
|
||||||
},
|
|
||||||
1
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
EscortGroup:MessageToClient( "Scanning targets for " .. ScanDuration .. " seconds.", ScanDuration, EscortClient )
|
EscortGroup:MessageToClient( "Scanning targets for " .. ScanDuration .. " seconds.", ScanDuration, EscortClient )
|
||||||
|
|
||||||
if self.EscortMode == ESCORT.MODE.FOLLOW then
|
if self.EscortMode == ESCORT.MODE.FOLLOW then
|
||||||
self.FollowScheduler:Start()
|
self.FollowScheduler:Start( self.FollowSchedule )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -844,124 +844,157 @@ function _Resume( EscortGroup )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #ESCORT self
|
||||||
function ESCORT._AttackTarget( MenuParam )
|
-- @param #number DetectedItemID
|
||||||
|
function ESCORT:_AttackTarget( DetectedItemID )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
local EscortGroup = self.EscortGroup -- Wrapper.Group#GROUP
|
||||||
local EscortGroup = self.EscortGroup
|
self:E( EscortGroup )
|
||||||
|
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
self:T( AttackUnit )
|
|
||||||
|
|
||||||
if EscortGroup:IsAir() then
|
if EscortGroup:IsAir() then
|
||||||
EscortGroup:OptionROEOpenFire()
|
EscortGroup:OptionROEOpenFire()
|
||||||
EscortGroup:OptionROTPassiveDefense()
|
EscortGroup:OptionROTPassiveDefense()
|
||||||
EscortGroup:SetState( EscortGroup, "Escort", self )
|
EscortGroup:SetState( EscortGroup, "Escort", self )
|
||||||
SCHEDULER:New( EscortGroup,
|
|
||||||
EscortGroup.PushTask,
|
local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
|
||||||
{ EscortGroup:TaskCombo(
|
|
||||||
{ EscortGroup:TaskAttackUnit( AttackUnit ),
|
local Tasks = {}
|
||||||
EscortGroup:TaskFunction( 1, 2, "_Resume", { "''" } )
|
|
||||||
}
|
DetectedSet:ForEachUnit(
|
||||||
)
|
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
}, 10
|
function( DetectedUnit, Tasks )
|
||||||
|
if DetectedUnit:IsAlive() then
|
||||||
|
Tasks[#Tasks+1] = EscortGroup:TaskAttackUnit( DetectedUnit )
|
||||||
|
end
|
||||||
|
end, Tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
Tasks[#Tasks+1] = EscortGroup:TaskFunction( 1, 2, "_Resume", { "''" } )
|
||||||
|
|
||||||
|
EscortGroup:SetTask(
|
||||||
|
EscortGroup:TaskCombo(
|
||||||
|
Tasks
|
||||||
|
), 1
|
||||||
)
|
)
|
||||||
|
|
||||||
else
|
else
|
||||||
SCHEDULER:New( EscortGroup,
|
|
||||||
EscortGroup.PushTask,
|
local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
|
||||||
{ EscortGroup:TaskCombo(
|
|
||||||
{ EscortGroup:TaskFireAtPoint( AttackUnit:GetVec2(), 50 )
|
local Tasks = {}
|
||||||
}
|
|
||||||
)
|
DetectedSet:ForEachUnit(
|
||||||
}, 10
|
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
|
function( DetectedUnit, Tasks )
|
||||||
|
if DetectedUnit:IsAlive() then
|
||||||
|
Tasks[#Tasks+1] = EscortGroup:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||||
|
end
|
||||||
|
end, Tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
EscortGroup:SetTask(
|
||||||
|
EscortGroup:TaskCombo(
|
||||||
|
Tasks
|
||||||
|
), 1
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
EscortGroup:MessageToClient( "Engaging Designated Unit!", 10, EscortClient )
|
EscortGroup:MessageToClient( "Engaging Designated Unit!", 10, EscortClient )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
---
|
||||||
function ESCORT._AssistTarget( MenuParam )
|
-- @param #number DetectedItemID
|
||||||
|
function ESCORT:_AssistTarget( EscortGroupAttack, DetectedItemID )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
local EscortGroupAttack = MenuParam.ParamEscortGroup
|
|
||||||
local AttackUnit = MenuParam.ParamUnit -- Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
self:T( AttackUnit )
|
|
||||||
|
|
||||||
if EscortGroupAttack:IsAir() then
|
if EscortGroupAttack:IsAir() then
|
||||||
EscortGroupAttack:OptionROEOpenFire()
|
EscortGroupAttack:OptionROEOpenFire()
|
||||||
EscortGroupAttack:OptionROTVertical()
|
EscortGroupAttack:OptionROTVertical()
|
||||||
SCHDULER:New( EscortGroupAttack,
|
|
||||||
EscortGroupAttack.PushTask,
|
local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
|
||||||
{ EscortGroupAttack:TaskCombo(
|
|
||||||
{ EscortGroupAttack:TaskAttackUnit( AttackUnit ),
|
local Tasks = {}
|
||||||
EscortGroupAttack:TaskOrbitCircle( 500, 350 )
|
|
||||||
}
|
DetectedSet:ForEachUnit(
|
||||||
)
|
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
}, 10
|
function( DetectedUnit, Tasks )
|
||||||
|
if DetectedUnit:IsAlive() then
|
||||||
|
Tasks[#Tasks+1] = EscortGroupAttack:TaskAttackUnit( DetectedUnit )
|
||||||
|
end
|
||||||
|
end, Tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
Tasks[#Tasks+1] = EscortGroupAttack:TaskOrbitCircle( 500, 350 )
|
||||||
|
|
||||||
|
EscortGroupAttack:SetTask(
|
||||||
|
EscortGroupAttack:TaskCombo(
|
||||||
|
Tasks
|
||||||
|
), 1
|
||||||
)
|
)
|
||||||
|
|
||||||
else
|
else
|
||||||
SCHEDULER:New( EscortGroupAttack,
|
local DetectedSet = self.Detection:GetDetectedSet( DetectedItemID )
|
||||||
EscortGroupAttack.PushTask,
|
|
||||||
{ EscortGroupAttack:TaskCombo(
|
local Tasks = {}
|
||||||
{ EscortGroupAttack:TaskFireAtPoint( AttackUnit:GetVec2(), 50 )
|
|
||||||
}
|
DetectedSet:ForEachUnit(
|
||||||
)
|
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
}, 10
|
function( DetectedUnit, Tasks )
|
||||||
|
if DetectedUnit:IsAlive() then
|
||||||
|
Tasks[#Tasks+1] = EscortGroupAttack:TaskFireAtPoint( DetectedUnit:GetVec2(), 50 )
|
||||||
|
end
|
||||||
|
end, Tasks
|
||||||
|
)
|
||||||
|
|
||||||
|
EscortGroupAttack:SetTask(
|
||||||
|
EscortGroupAttack:TaskCombo(
|
||||||
|
Tasks
|
||||||
|
), 1
|
||||||
)
|
)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
EscortGroupAttack:MessageToClient( "Assisting with the destroying the enemy unit!", 10, EscortClient )
|
EscortGroupAttack:MessageToClient( "Assisting with the destroying the enemy unit!", 10, EscortClient )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._ROE( MenuParam )
|
function ESCORT:_ROE( EscortROEFunction, EscortROEMessage )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local EscortROEFunction = MenuParam.ParamFunction
|
|
||||||
local EscortROEMessage = MenuParam.ParamMessage
|
|
||||||
|
|
||||||
pcall( function() EscortROEFunction() end )
|
pcall( function() EscortROEFunction() end )
|
||||||
EscortGroup:MessageToClient( EscortROEMessage, 10, EscortClient )
|
EscortGroup:MessageToClient( EscortROEMessage, 10, EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._ROT( MenuParam )
|
function ESCORT:_ROT( EscortROTFunction, EscortROTMessage )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local EscortROTFunction = MenuParam.ParamFunction
|
|
||||||
local EscortROTMessage = MenuParam.ParamMessage
|
|
||||||
|
|
||||||
pcall( function() EscortROTFunction() end )
|
pcall( function() EscortROTFunction() end )
|
||||||
EscortGroup:MessageToClient( EscortROTMessage, 10, EscortClient )
|
EscortGroup:MessageToClient( EscortROTMessage, 10, EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #MENUPARAM MenuParam
|
--- @param #MENUPARAM MenuParam
|
||||||
function ESCORT._ResumeMission( MenuParam )
|
function ESCORT:_ResumeMission( WayPoint )
|
||||||
|
|
||||||
local self = MenuParam.ParamSelf
|
|
||||||
local EscortGroup = self.EscortGroup
|
local EscortGroup = self.EscortGroup
|
||||||
local EscortClient = self.EscortClient
|
local EscortClient = self.EscortClient
|
||||||
|
|
||||||
local WayPoint = MenuParam.ParamWayPoint
|
self.FollowScheduler:Stop( self.FollowSchedule )
|
||||||
|
|
||||||
self.FollowScheduler:Stop()
|
|
||||||
|
|
||||||
local WayPoints = EscortGroup:GetTaskRoute()
|
local WayPoints = EscortGroup:GetTaskRoute()
|
||||||
self:T( WayPoint, WayPoints )
|
self:T( WayPoint, WayPoints )
|
||||||
@ -1105,176 +1138,244 @@ function ESCORT:_ReportTargetsScheduler()
|
|||||||
self:F( self.EscortGroup:GetName() )
|
self:F( self.EscortGroup:GetName() )
|
||||||
|
|
||||||
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
|
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
|
||||||
local EscortGroupName = self.EscortGroup:GetName()
|
|
||||||
local EscortTargets = self.EscortGroup:GetDetectedTargets()
|
|
||||||
|
|
||||||
local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
|
if true then
|
||||||
|
|
||||||
local EscortTargetMessages = ""
|
local EscortGroupName = self.EscortGroup:GetName()
|
||||||
for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
|
|
||||||
local EscortObject = EscortTarget.object
|
self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
||||||
self:T( EscortObject )
|
|
||||||
if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
|
|
||||||
|
|
||||||
local EscortTargetUnit = UNIT:Find( EscortObject )
|
if self.EscortMenuTargetAssistance then
|
||||||
local EscortTargetUnitName = EscortTargetUnit:GetName()
|
self.EscortMenuTargetAssistance:RemoveSubMenus()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- local EscortTargetIsDetected,
|
|
||||||
-- EscortTargetIsVisible,
|
|
||||||
-- EscortTargetLastTime,
|
|
||||||
-- EscortTargetKnowType,
|
|
||||||
-- EscortTargetKnowDistance,
|
|
||||||
-- EscortTargetLastPos,
|
|
||||||
-- EscortTargetLastVelocity
|
|
||||||
-- = self.EscortGroup:IsTargetDetected( EscortObject )
|
|
||||||
--
|
|
||||||
-- self:T( { EscortTargetIsDetected,
|
|
||||||
-- EscortTargetIsVisible,
|
|
||||||
-- EscortTargetLastTime,
|
|
||||||
-- EscortTargetKnowType,
|
|
||||||
-- EscortTargetKnowDistance,
|
|
||||||
-- EscortTargetLastPos,
|
|
||||||
-- EscortTargetLastVelocity } )
|
|
||||||
|
|
||||||
|
|
||||||
local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
|
|
||||||
local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
|
||||||
( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
|
||||||
( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
|
||||||
) ^ 0.5 / 1000
|
|
||||||
|
|
||||||
self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
|
|
||||||
|
|
||||||
if Distance <= 15 then
|
|
||||||
|
|
||||||
if not ClientEscortTargets[EscortTargetUnitName] then
|
|
||||||
ClientEscortTargets[EscortTargetUnitName] = {}
|
|
||||||
end
|
|
||||||
ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
|
|
||||||
ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
|
|
||||||
ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
|
|
||||||
ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
|
|
||||||
else
|
|
||||||
if ClientEscortTargets[EscortTargetUnitName] then
|
|
||||||
ClientEscortTargets[EscortTargetUnitName] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
self:T( { "Sorting Targets Table:", ClientEscortTargets } )
|
local DetectedItems = self.Detection:GetDetectedItems()
|
||||||
table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
|
self:E( DetectedItems )
|
||||||
self:T( { "Sorted Targets Table:", ClientEscortTargets } )
|
|
||||||
|
|
||||||
-- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
|
local DetectedTargets = false
|
||||||
self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
|
||||||
|
local DetectedMsgs = {}
|
||||||
|
|
||||||
|
for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
|
||||||
|
|
||||||
if self.EscortMenuTargetAssistance then
|
local ClientEscortTargets = EscortGroupData.Detection
|
||||||
self.EscortMenuTargetAssistance:RemoveSubMenus()
|
|
||||||
end
|
|
||||||
|
|
||||||
--for MenuIndex = 1, #self.EscortMenuAttackTargets do
|
for DetectedItemID, DetectedItem in ipairs( DetectedItems ) do
|
||||||
-- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } )
|
self:E( { DetectedItemID, DetectedItem } )
|
||||||
-- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
|
-- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
|
||||||
--end
|
|
||||||
|
local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItemID )
|
||||||
|
|
||||||
|
if ClientEscortGroupName == EscortGroupName then
|
||||||
if ClientEscortTargets then
|
|
||||||
for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
|
DetectedMsgs[#DetectedMsgs+1] = DetectedItemReportSummary
|
||||||
|
|
||||||
for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
|
MENU_CLIENT_COMMAND:New( self.EscortClient,
|
||||||
|
DetectedItemReportSummary,
|
||||||
if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then
|
self.EscortMenuAttackNearbyTargets,
|
||||||
|
ESCORT._AttackTarget,
|
||||||
local EscortTargetMessage = ""
|
self,
|
||||||
local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName()
|
DetectedItemID
|
||||||
local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName()
|
)
|
||||||
if ClientEscortTargetData.type then
|
|
||||||
EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
|
|
||||||
else
|
|
||||||
EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
|
|
||||||
end
|
|
||||||
|
|
||||||
local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3()
|
|
||||||
local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
|
||||||
( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
|
||||||
( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
|
||||||
) ^ 0.5 / 1000
|
|
||||||
|
|
||||||
self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
|
|
||||||
if ClientEscortTargetData.visible == false then
|
|
||||||
EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
|
|
||||||
else
|
|
||||||
EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
|
|
||||||
end
|
|
||||||
|
|
||||||
if ClientEscortTargetData.visible then
|
|
||||||
EscortTargetMessage = EscortTargetMessage .. ", visual"
|
|
||||||
end
|
|
||||||
|
|
||||||
if ClientEscortGroupName == EscortGroupName then
|
|
||||||
|
|
||||||
MENU_CLIENT_COMMAND:New( self.EscortClient,
|
|
||||||
EscortTargetMessage,
|
|
||||||
self.EscortMenuAttackNearbyTargets,
|
|
||||||
ESCORT._AttackTarget,
|
|
||||||
{ ParamSelf = self,
|
|
||||||
ParamUnit = ClientEscortTargetData.AttackUnit
|
|
||||||
}
|
|
||||||
)
|
|
||||||
EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
|
|
||||||
else
|
|
||||||
if self.EscortMenuTargetAssistance then
|
|
||||||
local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
|
|
||||||
MENU_CLIENT_COMMAND:New( self.EscortClient,
|
|
||||||
EscortTargetMessage,
|
|
||||||
MenuTargetAssistance,
|
|
||||||
ESCORT._AssistTarget,
|
|
||||||
{ ParamSelf = self,
|
|
||||||
ParamEscortGroup = EscortGroupData.EscortGroup,
|
|
||||||
ParamUnit = ClientEscortTargetData.AttackUnit
|
|
||||||
}
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
ClientEscortTargetData = nil
|
if self.EscortMenuTargetAssistance then
|
||||||
|
|
||||||
|
self:T( DetectedItemReportSummary )
|
||||||
|
local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
|
||||||
|
MENU_CLIENT_COMMAND:New( self.EscortClient,
|
||||||
|
DetectedItemReportSummary,
|
||||||
|
MenuTargetAssistance,
|
||||||
|
ESCORT._AssistTarget,
|
||||||
|
self,
|
||||||
|
EscortGroupData.EscortGroup,
|
||||||
|
DetectedItemID
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DetectedTargets = true
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self:E( DetectedMsgs )
|
||||||
if EscortTargetMessages ~= "" and self.ReportTargets == true then
|
if DetectedTargets then
|
||||||
self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
|
self.EscortGroup:MessageToClient( "Detected targets:\n" .. table.concat( DetectedMsgs, "\n" ), 20, self.EscortClient )
|
||||||
else
|
else
|
||||||
self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
|
self.EscortGroup:MessageToClient( "No targets detected.", 10, self.EscortClient )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
-- local EscortGroupName = self.EscortGroup:GetName()
|
||||||
|
-- local EscortTargets = self.EscortGroup:GetDetectedTargets()
|
||||||
|
--
|
||||||
|
-- local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
|
||||||
|
--
|
||||||
|
-- local EscortTargetMessages = ""
|
||||||
|
-- for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
|
||||||
|
-- local EscortObject = EscortTarget.object
|
||||||
|
-- self:T( EscortObject )
|
||||||
|
-- if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
|
||||||
|
--
|
||||||
|
-- local EscortTargetUnit = UNIT:Find( EscortObject )
|
||||||
|
-- local EscortTargetUnitName = EscortTargetUnit:GetName()
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- -- local EscortTargetIsDetected,
|
||||||
|
-- -- EscortTargetIsVisible,
|
||||||
|
-- -- EscortTargetLastTime,
|
||||||
|
-- -- EscortTargetKnowType,
|
||||||
|
-- -- EscortTargetKnowDistance,
|
||||||
|
-- -- EscortTargetLastPos,
|
||||||
|
-- -- EscortTargetLastVelocity
|
||||||
|
-- -- = self.EscortGroup:IsTargetDetected( EscortObject )
|
||||||
|
-- --
|
||||||
|
-- -- self:T( { EscortTargetIsDetected,
|
||||||
|
-- -- EscortTargetIsVisible,
|
||||||
|
-- -- EscortTargetLastTime,
|
||||||
|
-- -- EscortTargetKnowType,
|
||||||
|
-- -- EscortTargetKnowDistance,
|
||||||
|
-- -- EscortTargetLastPos,
|
||||||
|
-- -- EscortTargetLastVelocity } )
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
|
||||||
|
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||||
|
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
||||||
|
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
||||||
|
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
||||||
|
-- ) ^ 0.5 / 1000
|
||||||
|
--
|
||||||
|
-- self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
|
||||||
|
--
|
||||||
|
-- if Distance <= 15 then
|
||||||
|
--
|
||||||
|
-- if not ClientEscortTargets[EscortTargetUnitName] then
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName] = {}
|
||||||
|
-- end
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
|
||||||
|
-- else
|
||||||
|
-- if ClientEscortTargets[EscortTargetUnitName] then
|
||||||
|
-- ClientEscortTargets[EscortTargetUnitName] = nil
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- self:T( { "Sorting Targets Table:", ClientEscortTargets } )
|
||||||
|
-- table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
|
||||||
|
-- self:T( { "Sorted Targets Table:", ClientEscortTargets } )
|
||||||
|
--
|
||||||
|
-- -- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
|
||||||
|
-- self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
||||||
|
--
|
||||||
|
-- if self.EscortMenuTargetAssistance then
|
||||||
|
-- self.EscortMenuTargetAssistance:RemoveSubMenus()
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- --for MenuIndex = 1, #self.EscortMenuAttackTargets do
|
||||||
|
-- -- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } )
|
||||||
|
-- -- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
|
||||||
|
-- --end
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- if ClientEscortTargets then
|
||||||
|
-- for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
|
||||||
|
--
|
||||||
|
-- for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
|
||||||
|
--
|
||||||
|
-- if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then
|
||||||
|
--
|
||||||
|
-- local EscortTargetMessage = ""
|
||||||
|
-- local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName()
|
||||||
|
-- local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName()
|
||||||
|
-- if ClientEscortTargetData.type then
|
||||||
|
-- EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
|
||||||
|
-- else
|
||||||
|
-- EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3()
|
||||||
|
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||||
|
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
||||||
|
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
||||||
|
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
||||||
|
-- ) ^ 0.5 / 1000
|
||||||
|
--
|
||||||
|
-- self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
|
||||||
|
-- if ClientEscortTargetData.visible == false then
|
||||||
|
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
|
||||||
|
-- else
|
||||||
|
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- if ClientEscortTargetData.visible then
|
||||||
|
-- EscortTargetMessage = EscortTargetMessage .. ", visual"
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- if ClientEscortGroupName == EscortGroupName then
|
||||||
|
--
|
||||||
|
-- MENU_CLIENT_COMMAND:New( self.EscortClient,
|
||||||
|
-- EscortTargetMessage,
|
||||||
|
-- self.EscortMenuAttackNearbyTargets,
|
||||||
|
-- ESCORT._AttackTarget,
|
||||||
|
-- { ParamSelf = self,
|
||||||
|
-- ParamUnit = ClientEscortTargetData.AttackUnit
|
||||||
|
-- }
|
||||||
|
-- )
|
||||||
|
-- EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
|
||||||
|
-- else
|
||||||
|
-- if self.EscortMenuTargetAssistance then
|
||||||
|
-- local MenuTargetAssistance = MENU_CLIENT:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
|
||||||
|
-- MENU_CLIENT_COMMAND:New( self.EscortClient,
|
||||||
|
-- EscortTargetMessage,
|
||||||
|
-- MenuTargetAssistance,
|
||||||
|
-- ESCORT._AssistTarget,
|
||||||
|
-- self,
|
||||||
|
-- EscortGroupData.EscortGroup,
|
||||||
|
-- ClientEscortTargetData.AttackUnit
|
||||||
|
-- )
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- else
|
||||||
|
-- ClientEscortTargetData = nil
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- if EscortTargetMessages ~= "" and self.ReportTargets == true then
|
||||||
|
-- self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
|
||||||
|
-- else
|
||||||
|
-- self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- if self.EscortMenuResumeMission then
|
||||||
|
-- self.EscortMenuResumeMission:RemoveSubMenus()
|
||||||
|
--
|
||||||
|
-- -- if self.EscortMenuResumeWayPoints then
|
||||||
|
-- -- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
|
||||||
|
-- -- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
|
||||||
|
-- -- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
|
||||||
|
-- -- end
|
||||||
|
-- -- end
|
||||||
|
--
|
||||||
|
-- local TaskPoints = self:RegisterRoute()
|
||||||
|
-- for WayPointID, WayPoint in pairs( TaskPoints ) do
|
||||||
|
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
||||||
|
-- local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
|
||||||
|
-- ( WayPoint.y - EscortVec3.z )^2
|
||||||
|
-- ) ^ 0.5 / 1000
|
||||||
|
-- MENU_CLIENT_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.EscortMenuResumeMission then
|
|
||||||
self.EscortMenuResumeMission:RemoveSubMenus()
|
|
||||||
|
|
||||||
-- if self.EscortMenuResumeWayPoints then
|
|
||||||
-- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
|
|
||||||
-- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
|
|
||||||
-- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
local TaskPoints = self:RegisterRoute()
|
|
||||||
for WayPointID, WayPoint in pairs( TaskPoints ) do
|
|
||||||
local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
|
|
||||||
( WayPoint.y - EscortVec3.z )^2
|
|
||||||
) ^ 0.5 / 1000
|
|
||||||
MENU_CLIENT_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -171,7 +171,7 @@ function MISSILETRAINER:New( Distance, Briefing )
|
|||||||
|
|
||||||
self.Distance = Distance / 1000
|
self.Distance = Distance / 1000
|
||||||
|
|
||||||
_EVENTDISPATCHER:OnShot( self._EventShot, self )
|
self:HandleEvent( EVENTS.Shot )
|
||||||
|
|
||||||
self.DBClients = SET_CLIENT:New():FilterStart()
|
self.DBClients = SET_CLIENT:New():FilterStart()
|
||||||
|
|
||||||
@ -449,14 +449,14 @@ end
|
|||||||
|
|
||||||
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
||||||
-- @param #MISSILETRAINER self
|
-- @param #MISSILETRAINER self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function MISSILETRAINER:_EventShot( Event )
|
function MISSILETRAINER:OnEventShot( EVentData )
|
||||||
self:F( { Event } )
|
self:F( { EVentData } )
|
||||||
|
|
||||||
local TrainerSourceDCSUnit = Event.IniDCSUnit
|
local TrainerSourceDCSUnit = EVentData.IniDCSUnit
|
||||||
local TrainerSourceDCSUnitName = Event.IniDCSUnitName
|
local TrainerSourceDCSUnitName = EVentData.IniDCSUnitName
|
||||||
local TrainerWeapon = Event.Weapon -- Identify the weapon fired
|
local TrainerWeapon = EVentData.Weapon -- Identify the weapon fired
|
||||||
local TrainerWeaponName = Event.WeaponName -- return weapon type
|
local TrainerWeaponName = EVentData.WeaponName -- return weapon type
|
||||||
|
|
||||||
self:T( "Missile Launched = " .. TrainerWeaponName )
|
self:T( "Missile Launched = " .. TrainerWeaponName )
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,11 @@
|
|||||||
-- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if
|
-- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if
|
||||||
-- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units
|
-- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units
|
||||||
-- on defined intervals (currently every minute).
|
-- on defined intervals (currently every minute).
|
||||||
-- @module MOVEMENT
|
-- @module Movement
|
||||||
|
|
||||||
--- the MOVEMENT class
|
--- the MOVEMENT class
|
||||||
-- @type
|
-- @type MOVEMENT
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
MOVEMENT = {
|
MOVEMENT = {
|
||||||
ClassName = "MOVEMENT",
|
ClassName = "MOVEMENT",
|
||||||
}
|
}
|
||||||
@ -20,7 +21,7 @@ MOVEMENT = {
|
|||||||
-- Movement_US_Platoons = MOVEMENT:New( { 'US Tank Platoon Left', 'US Tank Platoon Middle', 'US Tank Platoon Right', 'US CH-47D Troops' }, 15 )
|
-- Movement_US_Platoons = MOVEMENT:New( { 'US Tank Platoon Left', 'US Tank Platoon Middle', 'US Tank Platoon Right', 'US CH-47D Troops' }, 15 )
|
||||||
|
|
||||||
function MOVEMENT:New( MovePrefixes, MoveMaximum )
|
function MOVEMENT:New( MovePrefixes, MoveMaximum )
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() ) -- #MOVEMENT
|
||||||
self:F( { MovePrefixes, MoveMaximum } )
|
self:F( { MovePrefixes, MoveMaximum } )
|
||||||
|
|
||||||
if type( MovePrefixes ) == 'table' then
|
if type( MovePrefixes ) == 'table' then
|
||||||
@ -33,7 +34,7 @@ function MOVEMENT:New( MovePrefixes, MoveMaximum )
|
|||||||
self.AliveUnits = 0 -- Contains the counter how many units are currently alive
|
self.AliveUnits = 0 -- Contains the counter how many units are currently alive
|
||||||
self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not.
|
self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not.
|
||||||
|
|
||||||
_EVENTDISPATCHER:OnBirth( self.OnBirth, self )
|
self:HandleEvent( EVENTS.Birth )
|
||||||
|
|
||||||
-- self:AddEvent( world.event.S_EVENT_BIRTH, self.OnBirth )
|
-- self:AddEvent( world.event.S_EVENT_BIRTH, self.OnBirth )
|
||||||
--
|
--
|
||||||
@ -60,24 +61,26 @@ end
|
|||||||
|
|
||||||
--- Captures the birth events when new Units were spawned.
|
--- Captures the birth events when new Units were spawned.
|
||||||
-- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration.
|
-- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration.
|
||||||
function MOVEMENT:OnBirth( Event )
|
-- @param #MOVEMENT self
|
||||||
self:F( { Event } )
|
-- @param Core.Event#EVENTDATA self
|
||||||
|
function MOVEMENT:OnEventBirth( EventData )
|
||||||
|
self:F( { EventData } )
|
||||||
|
|
||||||
if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
|
if timer.getTime0() < timer.getAbsTime() then -- dont need to add units spawned in at the start of the mission if mist is loaded in init line
|
||||||
if Event.IniDCSUnit then
|
if EventData.IniDCSUnit then
|
||||||
self:T( "Birth object : " .. Event.IniDCSUnitName )
|
self:T( "Birth object : " .. EventData.IniDCSUnitName )
|
||||||
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
if EventData.IniDCSGroup and EventData.IniDCSGroup:isExist() then
|
||||||
for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do
|
for MovePrefixID, MovePrefix in pairs( self.MovePrefixes ) do
|
||||||
if string.find( Event.IniDCSUnitName, MovePrefix, 1, true ) then
|
if string.find( EventData.IniDCSUnitName, MovePrefix, 1, true ) then
|
||||||
self.AliveUnits = self.AliveUnits + 1
|
self.AliveUnits = self.AliveUnits + 1
|
||||||
self.MoveUnits[Event.IniDCSUnitName] = Event.IniDCSGroupName
|
self.MoveUnits[EventData.IniDCSUnitName] = EventData.IniDCSGroupName
|
||||||
self:T( self.AliveUnits )
|
self:T( self.AliveUnits )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
_EVENTDISPATCHER:OnCrashForUnit( Event.IniDCSUnitName, self.OnDeadOrCrash, self )
|
|
||||||
_EVENTDISPATCHER:OnDeadForUnit( Event.IniDCSUnitName, self.OnDeadOrCrash, self )
|
EventData.IniUnit:HandleEvent( EVENTS.DEAD, self.OnDeadOrCrash )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1022,9 +1022,10 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_PENALTY", 1, ThreatPenalty, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( PlayerName, TargetPlayerName, "DESTROY_PENALTY", 1, ThreatPenalty, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
else
|
else
|
||||||
|
|
||||||
local ThreatLevelTarget, ThreatTypeTarget = TargetUnit:GetThreatLevel()
|
local ThreatLevelTarget, ThreatTypeTarget = TargetUnit:GetThreatLevel()
|
||||||
local ThreatLevelPlayer = Player.UNIT:GetThreatLevel() / 10 + 1
|
local ThreatLevelPlayer = Player.UNIT:GetThreatLevel() / 10 + 1
|
||||||
local ThreatScore = math.ceil( ( ThreatLevelTarget / ThreatLevelPlayer ) * self.ScaleDestroyScore / 10 )
|
local ThreatScore = math.ceil( ( ThreatLevelTarget / ThreatLevelPlayer ) * self.ScaleDestroyScore / 10 )
|
||||||
|
|||||||
@ -36,25 +36,28 @@ function SEAD:New( SEADGroupPrefixes )
|
|||||||
else
|
else
|
||||||
self.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes
|
self.SEADGroupNames[SEADGroupPrefixes] = SEADGroupPrefixes
|
||||||
end
|
end
|
||||||
_EVENTDISPATCHER:OnShot( self.EventShot, self )
|
|
||||||
|
self:HandleEvent( EVENTS.Shot )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
--- Detects if an SA site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
||||||
-- @see SEAD
|
-- @see SEAD
|
||||||
function SEAD:EventShot( Event )
|
-- @param #SEAD
|
||||||
self:F( { Event } )
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function SEAD:OnEventShot( EventData )
|
||||||
|
self:F( { EventData } )
|
||||||
|
|
||||||
local SEADUnit = Event.IniDCSUnit
|
local SEADUnit = EventData.IniDCSUnit
|
||||||
local SEADUnitName = Event.IniDCSUnitName
|
local SEADUnitName = EventData.IniDCSUnitName
|
||||||
local SEADWeapon = Event.Weapon -- Identify the weapon fired
|
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||||
local SEADWeaponName = Event.WeaponName -- return weapon type
|
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
||||||
-- Start of the 2nd loop
|
-- Start of the 2nd loop
|
||||||
self:T( "Missile Launched = " .. SEADWeaponName )
|
self:T( "Missile Launched = " .. SEADWeaponName )
|
||||||
if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
|
if SEADWeaponName == "KH-58" or SEADWeaponName == "KH-25MPU" or SEADWeaponName == "AGM-88" or SEADWeaponName == "KH-31A" or SEADWeaponName == "KH-31P" then -- Check if the missile is a SEAD
|
||||||
local _evade = math.random (1,100) -- random number for chance of evading action
|
local _evade = math.random (1,100) -- random number for chance of evading action
|
||||||
local _targetMim = Event.Weapon:getTarget() -- Identify target
|
local _targetMim = EventData.Weapon:getTarget() -- Identify target
|
||||||
local _targetMimname = Unit.getName(_targetMim)
|
local _targetMimname = Unit.getName(_targetMim)
|
||||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
||||||
local _targetMimgroupName = _targetMimgroup:getName()
|
local _targetMimgroupName = _targetMimgroup:getName()
|
||||||
|
|||||||
@ -59,7 +59,7 @@ Include.File( "Tasking/CommandCenter" )
|
|||||||
Include.File( "Tasking/Mission" )
|
Include.File( "Tasking/Mission" )
|
||||||
Include.File( "Tasking/Task" )
|
Include.File( "Tasking/Task" )
|
||||||
Include.File( "Tasking/DetectionManager" )
|
Include.File( "Tasking/DetectionManager" )
|
||||||
Include.File( "Tasking/Task_SEAD" )
|
Include.File( "Tasking/Task_A2G_Dispatcher")
|
||||||
Include.File( "Tasking/Task_A2G" )
|
Include.File( "Tasking/Task_A2G" )
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,9 @@ function REPORT:New( Title )
|
|||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
|
|
||||||
self.Report = {}
|
self.Report = {}
|
||||||
self.Report[#self.Report+1] = Title
|
if Title then
|
||||||
|
self.Report[#self.Report+1] = Title
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -31,7 +33,7 @@ end
|
|||||||
-- @return #REPORT
|
-- @return #REPORT
|
||||||
function REPORT:Add( Text )
|
function REPORT:Add( Text )
|
||||||
self.Report[#self.Report+1] = Text
|
self.Report[#self.Report+1] = Text
|
||||||
return self.Report[#self.Report+1]
|
return self.Report[#self.Report]
|
||||||
end
|
end
|
||||||
|
|
||||||
function REPORT:Text()
|
function REPORT:Text()
|
||||||
@ -68,22 +70,23 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
|
|||||||
|
|
||||||
self:HandleEvent( EVENTS.Birth,
|
self:HandleEvent( EVENTS.Birth,
|
||||||
--- @param #COMMANDCENTER self
|
--- @param #COMMANDCENTER self
|
||||||
--- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function( self, EventData )
|
function( self, EventData )
|
||||||
self:E( { EventData } )
|
if EventData.IniObjectCategory == 1 then
|
||||||
local EventGroup = GROUP:Find( EventData.IniDCSGroup )
|
local EventGroup = GROUP:Find( EventData.IniDCSGroup )
|
||||||
if EventGroup and self:HasGroup( EventGroup ) then
|
if EventGroup and self:HasGroup( EventGroup ) then
|
||||||
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
|
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
|
||||||
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup )
|
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup )
|
||||||
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup )
|
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup )
|
||||||
self:ReportSummary( EventGroup )
|
self:ReportSummary( EventGroup )
|
||||||
end
|
end
|
||||||
local PlayerUnit = EventData.IniUnit
|
local PlayerUnit = EventData.IniUnit
|
||||||
for MissionID, Mission in pairs( self:GetMissions() ) do
|
for MissionID, Mission in pairs( self:GetMissions() ) do
|
||||||
local Mission = Mission -- Tasking.Mission#MISSION
|
local Mission = Mission -- Tasking.Mission#MISSION
|
||||||
local PlayerGroup = EventData.IniGroup -- The GROUP object should be filled!
|
local PlayerGroup = EventData.IniGroup -- The GROUP object should be filled!
|
||||||
Mission:JoinUnit( PlayerUnit, PlayerGroup )
|
Mission:JoinUnit( PlayerUnit, PlayerGroup )
|
||||||
Mission:ReportDetails()
|
Mission:ReportDetails()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -193,17 +196,26 @@ function COMMANDCENTER:SetMenu()
|
|||||||
|
|
||||||
self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "Command Center (" .. self:GetName() .. ")" )
|
self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "Command Center (" .. self:GetName() .. ")" )
|
||||||
|
|
||||||
|
local MenuTime = timer.getTime()
|
||||||
for MissionID, Mission in pairs( self:GetMissions() ) do
|
for MissionID, Mission in pairs( self:GetMissions() ) do
|
||||||
local Mission = Mission -- Tasking.Mission#MISSION
|
local Mission = Mission -- Tasking.Mission#MISSION
|
||||||
Mission:RemoveMenu()
|
Mission:SetMenu( MenuTime )
|
||||||
|
end
|
||||||
|
|
||||||
|
for MissionID, Mission in pairs( self:GetMissions() ) do
|
||||||
|
local Mission = Mission -- Tasking.Mission#MISSION
|
||||||
|
Mission:RemoveMenu( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
for MissionID, Mission in pairs( self:GetMissions() ) do
|
|
||||||
local Mission = Mission -- Tasking.Mission#MISSION
|
|
||||||
Mission:SetMenu()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the commandcenter menu structure governed by the HQ command center.
|
||||||
|
-- @param #COMMANDCENTER self
|
||||||
|
-- @return Core.Menu#MENU_COALITION
|
||||||
|
function COMMANDCENTER:GetMenu()
|
||||||
|
self:F()
|
||||||
|
return self.CommandCenterMenu
|
||||||
|
end
|
||||||
|
|
||||||
--- Checks of the COMMANDCENTER has a GROUP.
|
--- Checks of the COMMANDCENTER has a GROUP.
|
||||||
-- @param #COMMANDCENTER self
|
-- @param #COMMANDCENTER self
|
||||||
@ -224,6 +236,14 @@ function COMMANDCENTER:HasGroup( MissionGroup )
|
|||||||
return Has
|
return Has
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Send a CC message to the coalition of the CC.
|
||||||
|
-- @param #COMMANDCENTER self
|
||||||
|
function COMMANDCENTER:MessageToAll( Message )
|
||||||
|
|
||||||
|
self:GetPositionable():MessageToAll( Message, 20, self:GetName() )
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Send a CC message to a GROUP.
|
--- Send a CC message to a GROUP.
|
||||||
-- @param #COMMANDCENTER self
|
-- @param #COMMANDCENTER self
|
||||||
-- @param #string Message
|
-- @param #string Message
|
||||||
@ -231,7 +251,8 @@ end
|
|||||||
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||||
function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name )
|
function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name )
|
||||||
|
|
||||||
local Prefix = Name and "@ Group (" .. Name .. "): " or ''
|
local Prefix = "@ Group"
|
||||||
|
Prefix = Prefix .. ( Name and " (" .. Name .. "): " or '' )
|
||||||
Message = Prefix .. Message
|
Message = Prefix .. Message
|
||||||
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() )
|
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() )
|
||||||
|
|
||||||
@ -247,6 +268,7 @@ function COMMANDCENTER:MessageToCoalition( Message )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Report the status of all MISSIONs to a GROUP.
|
--- Report the status of all MISSIONs to a GROUP.
|
||||||
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
|
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
|
||||||
-- @param #COMMANDCENTER self
|
-- @param #COMMANDCENTER self
|
||||||
|
|||||||
@ -34,23 +34,6 @@
|
|||||||
-- -------------------------------
|
-- -------------------------------
|
||||||
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
|
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
|
||||||
--
|
--
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- 3) @{#DETECTION_DISPATCHER} class, extends @{#DETECTION_MANAGER}
|
|
||||||
-- ================================================================
|
|
||||||
-- The @{#DETECTION_DISPATCHER} class implements the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of FAC (groups).
|
|
||||||
-- The FAC will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
|
||||||
-- Find a summary below describing for which situation a task type is created:
|
|
||||||
--
|
|
||||||
-- * **CAS Task**: Is created when there are enemy ground units within range of the FAC, while there are friendly units in the FAC perimeter.
|
|
||||||
-- * **BAI Task**: Is created when there are enemy ground units within range of the FAC, while there are NO other friendly units within the FAC perimeter.
|
|
||||||
-- * **SEAD Task**: Is created when there are enemy ground units wihtin range of the FAC, with air search radars.
|
|
||||||
--
|
|
||||||
-- Other task types will follow...
|
|
||||||
--
|
|
||||||
-- 3.1) DETECTION_DISPATCHER constructor:
|
|
||||||
-- --------------------------------------
|
|
||||||
-- The @{#DETECTION_DISPATCHER.New}() method creates a new DETECTION_DISPATCHER instance.
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -88,6 +71,8 @@ do -- DETECTION MANAGER
|
|||||||
self:SetReportInterval( 30 )
|
self:SetReportInterval( 30 )
|
||||||
self:SetReportDisplayTime( 25 )
|
self:SetReportDisplayTime( 25 )
|
||||||
|
|
||||||
|
Detection:__Start( 5 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -250,259 +235,3 @@ do -- DETECTION_REPORTING
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- DETECTION_DISPATCHER
|
|
||||||
|
|
||||||
--- DETECTION_DISPATCHER class.
|
|
||||||
-- @type DETECTION_DISPATCHER
|
|
||||||
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
|
||||||
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
|
|
||||||
-- @field Tasking.Mission#MISSION Mission
|
|
||||||
-- @field Wrapper.Group#GROUP CommandCenter
|
|
||||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
|
||||||
DETECTION_DISPATCHER = {
|
|
||||||
ClassName = "DETECTION_DISPATCHER",
|
|
||||||
Mission = nil,
|
|
||||||
CommandCenter = nil,
|
|
||||||
Detection = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- DETECTION_DISPATCHER constructor.
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Set#SET_GROUP SetGroup
|
|
||||||
-- @param Functional.Detection#DETECTION_BASE Detection
|
|
||||||
-- @return #DETECTION_DISPATCHER self
|
|
||||||
function DETECTION_DISPATCHER:New( Mission, CommandCenter, SetGroup, Detection )
|
|
||||||
|
|
||||||
-- Inherits from DETECTION_MANAGER
|
|
||||||
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #DETECTION_DISPATCHER
|
|
||||||
|
|
||||||
self.Detection = Detection
|
|
||||||
self.CommandCenter = CommandCenter
|
|
||||||
self.Mission = Mission
|
|
||||||
|
|
||||||
self:Schedule( 30 )
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Creates a SEAD task when there are targets for it.
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
|
|
||||||
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
|
|
||||||
-- @return #nil If there are no targets to be set.
|
|
||||||
function DETECTION_DISPATCHER:EvaluateSEAD( DetectedArea )
|
|
||||||
self:F( { DetectedArea.AreaID } )
|
|
||||||
|
|
||||||
local DetectedSet = DetectedArea.Set
|
|
||||||
local DetectedZone = DetectedArea.Zone
|
|
||||||
|
|
||||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
|
||||||
local RadarCount = DetectedSet:HasSEAD()
|
|
||||||
|
|
||||||
if RadarCount > 0 then
|
|
||||||
|
|
||||||
-- Here we're doing something advanced... We're copying the DetectedSet, but making a new Set only with SEADable Radar units in it.
|
|
||||||
local TargetSetUnit = SET_UNIT:New()
|
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
|
||||||
TargetSetUnit:FilterHasSEAD()
|
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
|
||||||
|
|
||||||
return TargetSetUnit
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Creates a CAS task when there are targets for it.
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
|
|
||||||
-- @return Tasking.Task#TASK
|
|
||||||
function DETECTION_DISPATCHER:EvaluateCAS( DetectedArea )
|
|
||||||
self:F( { DetectedArea.AreaID } )
|
|
||||||
|
|
||||||
local DetectedSet = DetectedArea.Set
|
|
||||||
local DetectedZone = DetectedArea.Zone
|
|
||||||
|
|
||||||
|
|
||||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
|
||||||
local GroundUnitCount = DetectedSet:HasGroundUnits()
|
|
||||||
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedArea )
|
|
||||||
|
|
||||||
if GroundUnitCount > 0 and FriendliesNearBy == true then
|
|
||||||
|
|
||||||
-- Copy the Set
|
|
||||||
local TargetSetUnit = SET_UNIT:New()
|
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
|
||||||
|
|
||||||
return TargetSetUnit
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Creates a BAI task when there are targets for it.
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
|
|
||||||
-- @return Tasking.Task#TASK
|
|
||||||
function DETECTION_DISPATCHER:EvaluateBAI( DetectedArea, FriendlyCoalition )
|
|
||||||
self:F( { DetectedArea.AreaID } )
|
|
||||||
|
|
||||||
local DetectedSet = DetectedArea.Set
|
|
||||||
local DetectedZone = DetectedArea.Zone
|
|
||||||
|
|
||||||
|
|
||||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
|
||||||
local GroundUnitCount = DetectedSet:HasGroundUnits()
|
|
||||||
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedArea )
|
|
||||||
|
|
||||||
if GroundUnitCount > 0 and FriendliesNearBy == false then
|
|
||||||
|
|
||||||
-- Copy the Set
|
|
||||||
local TargetSetUnit = SET_UNIT:New()
|
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
|
||||||
|
|
||||||
return TargetSetUnit
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Evaluates the removal of the Task from the Mission.
|
|
||||||
-- Can only occur when the DetectedArea is Changed AND the state of the Task is "Planned".
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
|
||||||
-- @param Tasking.Task#TASK Task
|
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedArea DetectedArea
|
|
||||||
-- @return Tasking.Task#TASK
|
|
||||||
function DETECTION_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedArea )
|
|
||||||
|
|
||||||
if Task then
|
|
||||||
if Task:IsStatePlanned() and DetectedArea.Changed == true then
|
|
||||||
self:E( "Removing Tasking: " .. Task:GetTaskName() )
|
|
||||||
Task = Mission:RemoveTask( Task )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Task
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
|
|
||||||
-- @param #DETECTION_DISPATCHER self
|
|
||||||
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_AREAS} object.
|
|
||||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
|
||||||
function DETECTION_DISPATCHER:ProcessDetected( Detection )
|
|
||||||
self:F2()
|
|
||||||
|
|
||||||
local AreaMsg = {}
|
|
||||||
local TaskMsg = {}
|
|
||||||
local ChangeMsg = {}
|
|
||||||
|
|
||||||
local Mission = self.Mission
|
|
||||||
|
|
||||||
--- First we need to the detected targets.
|
|
||||||
for DetectedAreaID, DetectedAreaData in ipairs( Detection:GetDetectedAreas() ) do
|
|
||||||
|
|
||||||
local DetectedArea = DetectedAreaData -- Functional.Detection#DETECTION_AREAS.DetectedArea
|
|
||||||
local DetectedSet = DetectedArea.Set
|
|
||||||
local DetectedZone = DetectedArea.Zone
|
|
||||||
self:E( { "Targets in DetectedArea", DetectedArea.AreaID, DetectedSet:Count(), tostring( DetectedArea ) } )
|
|
||||||
DetectedSet:Flush()
|
|
||||||
|
|
||||||
local AreaID = DetectedArea.AreaID
|
|
||||||
|
|
||||||
-- Evaluate SEAD Tasking
|
|
||||||
local SEADTask = Mission:GetTask( "SEAD." .. AreaID )
|
|
||||||
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedArea )
|
|
||||||
if not SEADTask then
|
|
||||||
local TargetSetUnit = self:EvaluateSEAD( DetectedArea ) -- Returns a SetUnit if there are targets to be SEADed...
|
|
||||||
if TargetSetUnit then
|
|
||||||
SEADTask = Mission:AddTask( TASK_SEAD:New( Mission, self.SetGroup, "SEAD." .. AreaID, TargetSetUnit , DetectedZone ) )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if SEADTask and SEADTask:IsStatePlanned() then
|
|
||||||
self:E( "Planned" )
|
|
||||||
--SEADTask:SetPlannedMenu()
|
|
||||||
TaskMsg[#TaskMsg+1] = " - " .. SEADTask:GetStateString() .. " SEAD " .. AreaID .. " - " .. SEADTask.TargetSetUnit:GetUnitTypesText()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Evaluate CAS Tasking
|
|
||||||
local CASTask = Mission:GetTask( "CAS." .. AreaID )
|
|
||||||
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedArea )
|
|
||||||
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_A2G:New( Mission, self.SetGroup, "CAS." .. AreaID, "CAS", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if CASTask and CASTask:IsStatePlanned() then
|
|
||||||
--CASTask:SetPlannedMenu()
|
|
||||||
TaskMsg[#TaskMsg+1] = " - " .. CASTask:GetStateString() .. " CAS " .. AreaID .. " - " .. CASTask.TargetSetUnit:GetUnitTypesText()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Evaluate BAI Tasking
|
|
||||||
local BAITask = Mission:GetTask( "BAI." .. AreaID )
|
|
||||||
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedArea )
|
|
||||||
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_A2G:New( Mission, self.SetGroup, "BAI." .. AreaID, "BAI", TargetSetUnit , DetectedZone, DetectedArea.NearestFAC ) )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if BAITask and BAITask:IsStatePlanned() then
|
|
||||||
--BAITask:SetPlannedMenu()
|
|
||||||
TaskMsg[#TaskMsg+1] = " - " .. BAITask:GetStateString() .. " BAI " .. AreaID .. " - " .. BAITask.TargetSetUnit:GetUnitTypesText()
|
|
||||||
end
|
|
||||||
|
|
||||||
if #TaskMsg > 0 then
|
|
||||||
|
|
||||||
local ThreatLevel = Detection:GetTreatLevelA2G( DetectedArea )
|
|
||||||
|
|
||||||
local DetectedAreaVec3 = DetectedZone:GetVec3()
|
|
||||||
local DetectedAreaPointVec3 = POINT_VEC3:New( DetectedAreaVec3.x, DetectedAreaVec3.y, DetectedAreaVec3.z )
|
|
||||||
local DetectedAreaPointLL = DetectedAreaPointVec3:ToStringLL( 3, true )
|
|
||||||
AreaMsg[#AreaMsg+1] = string.format( " - Area #%d - %s - Threat Level [%s] (%2d)",
|
|
||||||
DetectedAreaID,
|
|
||||||
DetectedAreaPointLL,
|
|
||||||
string.rep( "■", ThreatLevel ),
|
|
||||||
ThreatLevel
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Loop through the changes ...
|
|
||||||
local ChangeText = Detection:GetChangeText( DetectedArea )
|
|
||||||
|
|
||||||
if ChangeText ~= "" then
|
|
||||||
ChangeMsg[#ChangeMsg+1] = string.gsub( string.gsub( ChangeText, "\n", "%1 - " ), "^.", " - %1" )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
|
||||||
Detection:AcceptChanges( DetectedArea )
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO set menus using the HQ coordinator
|
|
||||||
Mission:GetCommandCenter():SetMenu()
|
|
||||||
|
|
||||||
if #AreaMsg > 0 then
|
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
|
||||||
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
|
|
||||||
self.CommandCenter:MessageToGroup(
|
|
||||||
string.format( "HQ Reporting - Target areas for mission '%s':\nAreas:\n%s\n\nTasks:\n%s\n\nChanges:\n%s ",
|
|
||||||
self.Mission:GetName(),
|
|
||||||
table.concat( AreaMsg, "\n" ),
|
|
||||||
table.concat( TaskMsg, "\n" ),
|
|
||||||
table.concat( ChangeMsg, "\n" )
|
|
||||||
), self:GetReportDisplayTime(), TaskGroup
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -12,22 +12,6 @@ MISSION = {
|
|||||||
ClassName = "MISSION",
|
ClassName = "MISSION",
|
||||||
Name = "",
|
Name = "",
|
||||||
MissionStatus = "PENDING",
|
MissionStatus = "PENDING",
|
||||||
_Clients = {},
|
|
||||||
TaskMenus = {},
|
|
||||||
TaskCategoryMenus = {},
|
|
||||||
TaskTypeMenus = {},
|
|
||||||
_ActiveTasks = {},
|
|
||||||
GoalFunction = nil,
|
|
||||||
MissionReportTrigger = 0,
|
|
||||||
MissionProgressTrigger = 0,
|
|
||||||
MissionReportShow = false,
|
|
||||||
MissionReportFlash = false,
|
|
||||||
MissionTimeInterval = 0,
|
|
||||||
MissionCoalition = "",
|
|
||||||
SUCCESS = 1,
|
|
||||||
FAILED = 2,
|
|
||||||
REPEAT = 3,
|
|
||||||
_GoalTasks = {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
|
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
|
||||||
@ -45,10 +29,184 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
|
|||||||
self:SetStartState( "Idle" )
|
self:SetStartState( "Idle" )
|
||||||
|
|
||||||
self:AddTransition( "Idle", "Start", "Ongoing" )
|
self:AddTransition( "Idle", "Start", "Ongoing" )
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Idle.
|
||||||
|
-- @function [parent=#MISSION] OnLeaveIdle
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Idle.
|
||||||
|
-- @function [parent=#MISSION] OnEnterIdle
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Ongoing.
|
||||||
|
-- @function [parent=#MISSION] OnLeaveOngoing
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Ongoing.
|
||||||
|
-- @function [parent=#MISSION] OnEnterOngoing
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- OnBefore Transition Handler for Event Start.
|
||||||
|
-- @function [parent=#MISSION] OnBeforeStart
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Start.
|
||||||
|
-- @function [parent=#MISSION] OnAfterStart
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- Synchronous Event Trigger for Event Start.
|
||||||
|
-- @function [parent=#MISSION] Start
|
||||||
|
-- @param #MISSION self
|
||||||
|
|
||||||
|
--- Asynchronous Event Trigger for Event Start.
|
||||||
|
-- @function [parent=#MISSION] __Start
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #number Delay The delay in seconds.
|
||||||
|
|
||||||
self:AddTransition( "Ongoing", "Stop", "Idle" )
|
self:AddTransition( "Ongoing", "Stop", "Idle" )
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Idle.
|
||||||
|
-- @function [parent=#MISSION] OnLeaveIdle
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Idle.
|
||||||
|
-- @function [parent=#MISSION] OnEnterIdle
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- OnBefore Transition Handler for Event Stop.
|
||||||
|
-- @function [parent=#MISSION] OnBeforeStop
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Stop.
|
||||||
|
-- @function [parent=#MISSION] OnAfterStop
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- Synchronous Event Trigger for Event Stop.
|
||||||
|
-- @function [parent=#MISSION] Stop
|
||||||
|
-- @param #MISSION self
|
||||||
|
|
||||||
|
--- Asynchronous Event Trigger for Event Stop.
|
||||||
|
-- @function [parent=#MISSION] __Stop
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #number Delay The delay in seconds.
|
||||||
|
|
||||||
self:AddTransition( "Ongoing", "Complete", "Completed" )
|
self:AddTransition( "Ongoing", "Complete", "Completed" )
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Completed.
|
||||||
|
-- @function [parent=#MISSION] OnLeaveCompleted
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Completed.
|
||||||
|
-- @function [parent=#MISSION] OnEnterCompleted
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- OnBefore Transition Handler for Event Complete.
|
||||||
|
-- @function [parent=#MISSION] OnBeforeComplete
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Complete.
|
||||||
|
-- @function [parent=#MISSION] OnAfterComplete
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- Synchronous Event Trigger for Event Complete.
|
||||||
|
-- @function [parent=#MISSION] Complete
|
||||||
|
-- @param #MISSION self
|
||||||
|
|
||||||
|
--- Asynchronous Event Trigger for Event Complete.
|
||||||
|
-- @function [parent=#MISSION] __Complete
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #number Delay The delay in seconds.
|
||||||
|
|
||||||
self:AddTransition( "*", "Fail", "Failed" )
|
self:AddTransition( "*", "Fail", "Failed" )
|
||||||
|
|
||||||
|
--- OnLeave Transition Handler for State Failed.
|
||||||
|
-- @function [parent=#MISSION] OnLeaveFailed
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnEnter Transition Handler for State Failed.
|
||||||
|
-- @function [parent=#MISSION] OnEnterFailed
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- OnBefore Transition Handler for Event Fail.
|
||||||
|
-- @function [parent=#MISSION] OnBeforeFail
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Fail.
|
||||||
|
-- @function [parent=#MISSION] OnAfterFail
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
|
--- Synchronous Event Trigger for Event Fail.
|
||||||
|
-- @function [parent=#MISSION] Fail
|
||||||
|
-- @param #MISSION self
|
||||||
|
|
||||||
|
--- Asynchronous Event Trigger for Event Fail.
|
||||||
|
-- @function [parent=#MISSION] __Fail
|
||||||
|
-- @param #MISSION self
|
||||||
|
-- @param #number Delay The delay in seconds.
|
||||||
|
|
||||||
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
|
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
|
||||||
|
|
||||||
self.CommandCenter = CommandCenter
|
self.CommandCenter = CommandCenter
|
||||||
@ -60,14 +218,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
|
|||||||
self.MissionCoalition = MissionCoalition
|
self.MissionCoalition = MissionCoalition
|
||||||
|
|
||||||
self.Tasks = {}
|
self.Tasks = {}
|
||||||
|
|
||||||
|
-- Private implementations
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- FSM function for a MISSION
|
-- FSM function for a MISSION
|
||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
function MISSION:onbeforeComplete( From, Event, To )
|
function MISSION:onbeforeComplete( From, Event, To )
|
||||||
|
|
||||||
@ -80,10 +242,10 @@ function MISSION:onbeforeComplete( From, Event, To )
|
|||||||
return true -- Allow Mission completion.
|
return true -- Allow Mission completion.
|
||||||
end
|
end
|
||||||
|
|
||||||
--- FSM function for a MISSION
|
-- FSM function for a MISSION
|
||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
function MISSION:onenterCompleted( From, Event, To )
|
function MISSION:onenterCompleted( From, Event, To )
|
||||||
|
|
||||||
@ -201,23 +363,25 @@ end
|
|||||||
|
|
||||||
--- Sets the Planned Task menu.
|
--- Sets the Planned Task menu.
|
||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
function MISSION:SetMenu()
|
-- @param #number MenuTime
|
||||||
|
function MISSION:SetMenu( MenuTime )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
for _, Task in pairs( self:GetTasks() ) do
|
for _, TaskData in pairs( self:GetTasks() ) do
|
||||||
local Task = Task -- Tasking.Task#TASK
|
local Task = TaskData -- Tasking.Task#TASK
|
||||||
Task:SetMenu()
|
Task:SetMenu( MenuTime )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes the Planned Task menu.
|
--- Removes the Planned Task menu.
|
||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
function MISSION:RemoveMenu()
|
-- @param #number MenuTime
|
||||||
|
function MISSION:RemoveMenu( MenuTime )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
for _, Task in pairs( self:GetTasks() ) do
|
for _, Task in pairs( self:GetTasks() ) do
|
||||||
local Task = Task -- Tasking.Task#TASK
|
local Task = Task -- Tasking.Task#TASK
|
||||||
Task:RemoveMenu()
|
Task:RemoveMenu( MenuTime )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -229,20 +393,6 @@ function MISSION:GetCommandCenter()
|
|||||||
return self.CommandCenter
|
return self.CommandCenter
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the Assigned Task menu.
|
|
||||||
-- @param #MISSION self
|
|
||||||
-- @param Tasking.Task#TASK Task
|
|
||||||
-- @param #string MenuText The menu text.
|
|
||||||
-- @return #MISSION self
|
|
||||||
function MISSION:SetAssignedMenu( Task )
|
|
||||||
|
|
||||||
for _, Task in pairs( self.Tasks ) do
|
|
||||||
local Task = Task -- Tasking.Task#TASK
|
|
||||||
Task:RemoveMenu()
|
|
||||||
Task:SetAssignedMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Removes a Task menu.
|
--- Removes a Task menu.
|
||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
@ -258,28 +408,18 @@ end
|
|||||||
-- @param #MISSION self
|
-- @param #MISSION self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
-- @return Core.Menu#MENU_COALITION self
|
-- @return Core.Menu#MENU_COALITION self
|
||||||
function MISSION:GetMissionMenu( TaskGroup )
|
function MISSION:GetMenu( TaskGroup )
|
||||||
|
|
||||||
local CommandCenter = self:GetCommandCenter()
|
local CommandCenter = self:GetCommandCenter()
|
||||||
local CommandCenterMenu = CommandCenter.CommandCenterMenu
|
local CommandCenterMenu = CommandCenter:GetMenu()
|
||||||
|
|
||||||
local MissionName = self:GetName()
|
local MissionName = self:GetName()
|
||||||
|
local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
|
||||||
local TaskGroupName = TaskGroup:GetName()
|
|
||||||
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu )
|
|
||||||
|
|
||||||
return MissionMenu
|
return MissionMenu
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Clears the mission menu for the coalition.
|
|
||||||
-- @param #MISSION self
|
|
||||||
-- @return #MISSION self
|
|
||||||
function MISSION:ClearMissionMenu()
|
|
||||||
self.MissionMenu:Remove()
|
|
||||||
self.MissionMenu = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions.
|
--- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions.
|
||||||
-- @param #string TaskName The Name of the @{Task} within the @{Mission}.
|
-- @param #string TaskName The Name of the @{Task} within the @{Mission}.
|
||||||
-- @return Tasking.Task#TASK The Task
|
-- @return Tasking.Task#TASK The Task
|
||||||
@ -350,76 +490,44 @@ function MISSION:GetNextTaskID( Task )
|
|||||||
return self.Tasks[TaskName].n
|
return self.Tasks[TaskName].n
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Is the @{Mission} **Completed**.
|
||||||
|
-- @param #MISSION self
|
||||||
--- old stuff
|
-- @return #boolean
|
||||||
|
|
||||||
--- Returns if a Mission has completed.
|
|
||||||
-- @return bool
|
|
||||||
function MISSION:IsCompleted()
|
function MISSION:IsCompleted()
|
||||||
self:F()
|
return self:Is( "Completed" )
|
||||||
return self.MissionStatus == "ACCOMPLISHED"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a Mission to completed.
|
--- Is the @{Mission} **Idle**.
|
||||||
function MISSION:Completed()
|
-- @param #MISSION self
|
||||||
self:F()
|
-- @return #boolean
|
||||||
self.MissionStatus = "ACCOMPLISHED"
|
function MISSION:IsIdle()
|
||||||
self:StatusToClients()
|
return self:Is( "Idle" )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns if a Mission is ongoing.
|
--- Is the @{Mission} **Ongoing**.
|
||||||
-- treturn bool
|
-- @param #MISSION self
|
||||||
|
-- @return #boolean
|
||||||
function MISSION:IsOngoing()
|
function MISSION:IsOngoing()
|
||||||
self:F()
|
return self:Is( "Ongoing" )
|
||||||
return self.MissionStatus == "ONGOING"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a Mission to ongoing.
|
--- Is the @{Mission} **Failed**.
|
||||||
function MISSION:Ongoing()
|
-- @param #MISSION self
|
||||||
self:F()
|
-- @return #boolean
|
||||||
self.MissionStatus = "ONGOING"
|
function MISSION:IsFailed()
|
||||||
--self:StatusToClients()
|
return self:Is( "Failed" )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns if a Mission is pending.
|
--- Is the @{Mission} **Hold**.
|
||||||
-- treturn bool
|
-- @param #MISSION self
|
||||||
function MISSION:IsPending()
|
-- @return #boolean
|
||||||
self:F()
|
function MISSION:IsHold()
|
||||||
return self.MissionStatus == "PENDING"
|
return self:Is( "Hold" )
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a Mission to pending.
|
|
||||||
function MISSION:Pending()
|
|
||||||
self:F()
|
|
||||||
self.MissionStatus = "PENDING"
|
|
||||||
self:StatusToClients()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns if a Mission has failed.
|
|
||||||
-- treturn bool
|
|
||||||
function MISSION:IsFailed()
|
|
||||||
self:F()
|
|
||||||
return self.MissionStatus == "FAILED"
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set a Mission to failed.
|
|
||||||
function MISSION:Failed()
|
|
||||||
self:F()
|
|
||||||
self.MissionStatus = "FAILED"
|
|
||||||
self:StatusToClients()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Send the status of the MISSION to all Clients.
|
|
||||||
function MISSION:StatusToClients()
|
|
||||||
self:F()
|
|
||||||
if self.MissionReportFlash then
|
|
||||||
for ClientID, Client in pairs( self._Clients ) do
|
|
||||||
Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, "Mission Command: Mission Status")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Validates if the Mission has a Group
|
||||||
|
-- @param #MISSION
|
||||||
|
-- @return #boolean true if the Mission has a Group.
|
||||||
function MISSION:HasGroup( TaskGroup )
|
function MISSION:HasGroup( TaskGroup )
|
||||||
local Has = false
|
local Has = false
|
||||||
|
|
||||||
@ -512,107 +620,6 @@ function MISSION:ReportDetails()
|
|||||||
return Report:Text()
|
return Report:Text()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Report the status of all MISSIONs to all active Clients.
|
|
||||||
function MISSION:ReportToAll()
|
|
||||||
self:F()
|
|
||||||
|
|
||||||
local AlivePlayers = ''
|
|
||||||
for ClientID, Client in pairs( self._Clients ) do
|
|
||||||
if Client:GetDCSGroup() then
|
|
||||||
if Client:GetClientGroupDCSUnit() then
|
|
||||||
if Client:GetClientGroupDCSUnit():getLife() > 0.0 then
|
|
||||||
if AlivePlayers == '' then
|
|
||||||
AlivePlayers = ' Players: ' .. Client:GetClientGroupDCSUnit():getPlayerName()
|
|
||||||
else
|
|
||||||
AlivePlayers = AlivePlayers .. ' / ' .. Client:GetClientGroupDCSUnit():getPlayerName()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local Tasks = self:GetTasks()
|
|
||||||
local TaskText = ""
|
|
||||||
for TaskID, TaskData in pairs( Tasks ) do
|
|
||||||
TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n"
|
|
||||||
end
|
|
||||||
MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), 10, "Mission Command: Mission Report" ):ToAll()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Add a goal function to a MISSION. Goal functions are called when a @{TASK} within a mission has been completed.
|
|
||||||
-- @param function GoalFunction is the function defined by the mission designer to evaluate whether a certain goal has been reached after a @{TASK} finishes within the @{MISSION}. A GoalFunction must accept 2 parameters: Mission, Client, which contains the current MISSION object and the current CLIENT object respectively.
|
|
||||||
-- @usage
|
|
||||||
-- PatriotActivation = {
|
|
||||||
-- { "US SAM Patriot Zerti", false },
|
|
||||||
-- { "US SAM Patriot Zegduleti", false },
|
|
||||||
-- { "US SAM Patriot Gvleti", false }
|
|
||||||
-- }
|
|
||||||
--
|
|
||||||
-- function DeployPatriotTroopsGoal( Mission, Client )
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- -- Check if the cargo is all deployed for mission success.
|
|
||||||
-- for CargoID, CargoData in pairs( Mission._Cargos ) do
|
|
||||||
-- if Group.getByName( CargoData.CargoGroupName ) then
|
|
||||||
-- CargoGroup = Group.getByName( CargoData.CargoGroupName )
|
|
||||||
-- if CargoGroup then
|
|
||||||
-- -- Check if the cargo is ready to activate
|
|
||||||
-- CurrentLandingZoneID = routines.IsUnitInZones( CargoGroup:getUnits()[1], Mission:GetTask( 2 ).LandingZones ) -- The second task is the Deploytask to measure mission success upon
|
|
||||||
-- if CurrentLandingZoneID then
|
|
||||||
-- if PatriotActivation[CurrentLandingZoneID][2] == false then
|
|
||||||
-- -- Now check if this is a new Mission Task to be completed...
|
|
||||||
-- trigger.action.setGroupAIOn( Group.getByName( PatriotActivation[CurrentLandingZoneID][1] ) )
|
|
||||||
-- PatriotActivation[CurrentLandingZoneID][2] = true
|
|
||||||
-- MessageToBlue( "Mission Command: Message to all airborne units! The " .. PatriotActivation[CurrentLandingZoneID][1] .. " is armed. Our air defenses are now stronger.", 60, "BLUE/PatriotDefense" )
|
|
||||||
-- MessageToRed( "Mission Command: Our satellite systems are detecting additional NATO air defenses. To all airborne units: Take care!!!", 60, "RED/PatriotDefense" )
|
|
||||||
-- Mission:GetTask( 2 ):AddGoalCompletion( "Patriots activated", PatriotActivation[CurrentLandingZoneID][1], 1 ) -- Register Patriot activation as part of mission goal.
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' )
|
|
||||||
-- Mission:AddGoalFunction( DeployPatriotTroopsGoal )
|
|
||||||
function MISSION:AddGoalFunction( GoalFunction )
|
|
||||||
self:F()
|
|
||||||
self.GoalFunction = GoalFunction
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Register a new @{CLIENT} to participate within the mission.
|
|
||||||
-- @param CLIENT Client is the @{CLIENT} object. The object must have been instantiated with @{CLIENT:New}.
|
|
||||||
-- @return CLIENT
|
|
||||||
-- @usage
|
|
||||||
-- Add a number of Client objects to the Mission.
|
|
||||||
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 1', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
|
||||||
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 3', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
|
||||||
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
|
||||||
-- Mission:AddClient( CLIENT:FindByName( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() )
|
|
||||||
function MISSION:AddClient( Client )
|
|
||||||
self:F( { Client } )
|
|
||||||
|
|
||||||
local Valid = true
|
|
||||||
|
|
||||||
if Valid then
|
|
||||||
self._Clients[Client.ClientName] = Client
|
|
||||||
end
|
|
||||||
|
|
||||||
return Client
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find a @{CLIENT} object within the @{MISSION} by its ClientName.
|
|
||||||
-- @param CLIENT ClientName is a string defining the Client Group as defined within the ME.
|
|
||||||
-- @return CLIENT
|
|
||||||
-- @usage
|
|
||||||
-- -- Seach for Client "Bomber" within the Mission.
|
|
||||||
-- local BomberClient = Mission:FindClient( "Bomber" )
|
|
||||||
function MISSION:FindClient( ClientName )
|
|
||||||
self:F( { self._Clients[ClientName] } )
|
|
||||||
return self._Clients[ClientName]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
|
--- Get all the TASKs from the Mission. This function is useful in GoalFunctions.
|
||||||
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
|
-- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key.
|
||||||
-- @usage
|
-- @usage
|
||||||
@ -626,330 +633,3 @@ function MISSION:GetTasks()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--[[
|
|
||||||
_TransportExecuteStage: Defines the different stages of Transport unload/load execution. This table is internal and is used to control the validity of Transport load/unload timing.
|
|
||||||
|
|
||||||
- _TransportExecuteStage.EXECUTING
|
|
||||||
- _TransportExecuteStage.SUCCESS
|
|
||||||
- _TransportExecuteStage.FAILED
|
|
||||||
|
|
||||||
--]]
|
|
||||||
_TransportExecuteStage = {
|
|
||||||
NONE = 0,
|
|
||||||
EXECUTING = 1,
|
|
||||||
SUCCESS = 2,
|
|
||||||
FAILED = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- The MISSIONSCHEDULER is an OBJECT and is the main scheduler of ALL active MISSIONs registered within this scheduler. It's workings are considered internal and is automatically created when the Mission.lua file is included.
|
|
||||||
-- @type MISSIONSCHEDULER
|
|
||||||
-- @field #MISSIONSCHEDULER.MISSIONS Missions
|
|
||||||
MISSIONSCHEDULER = {
|
|
||||||
Missions = {},
|
|
||||||
MissionCount = 0,
|
|
||||||
TimeIntervalCount = 0,
|
|
||||||
TimeIntervalShow = 150,
|
|
||||||
TimeSeconds = 14400,
|
|
||||||
TimeShow = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
--- @type MISSIONSCHEDULER.MISSIONS
|
|
||||||
-- @list <#MISSION> Mission
|
|
||||||
|
|
||||||
--- This is the main MISSIONSCHEDULER Scheduler function. It is considered internal and is automatically created when the Mission.lua file is included.
|
|
||||||
function MISSIONSCHEDULER.Scheduler()
|
|
||||||
|
|
||||||
|
|
||||||
-- loop through the missions in the TransportTasks
|
|
||||||
for MissionName, MissionData in pairs( MISSIONSCHEDULER.Missions ) do
|
|
||||||
|
|
||||||
local Mission = MissionData -- #MISSION
|
|
||||||
|
|
||||||
if not Mission:IsCompleted() then
|
|
||||||
|
|
||||||
-- This flag will monitor if for this mission, there are clients alive. If this flag is still false at the end of the loop, the mission status will be set to Pending (if not Failed or Completed).
|
|
||||||
local ClientsAlive = false
|
|
||||||
|
|
||||||
for ClientID, ClientData in pairs( Mission._Clients ) do
|
|
||||||
|
|
||||||
local Client = ClientData -- Wrapper.Client#CLIENT
|
|
||||||
|
|
||||||
if Client:IsAlive() then
|
|
||||||
|
|
||||||
-- There is at least one Client that is alive... So the Mission status is set to Ongoing.
|
|
||||||
ClientsAlive = true
|
|
||||||
|
|
||||||
-- If this Client was not registered as Alive before:
|
|
||||||
-- 1. We register the Client as Alive.
|
|
||||||
-- 2. We initialize the Client Tasks and make a link to the original Mission Task.
|
|
||||||
-- 3. We initialize the Cargos.
|
|
||||||
-- 4. We flag the Mission as Ongoing.
|
|
||||||
if not Client.ClientAlive then
|
|
||||||
Client.ClientAlive = true
|
|
||||||
Client.ClientBriefingShown = false
|
|
||||||
for TaskNumber, Task in pairs( Mission._Tasks ) do
|
|
||||||
-- Note that this a deepCopy. Each client must have their own Tasks with own Stages!!!
|
|
||||||
Client._Tasks[TaskNumber] = routines.utils.deepCopy( Mission._Tasks[TaskNumber] )
|
|
||||||
-- Each MissionTask must point to the original Mission.
|
|
||||||
Client._Tasks[TaskNumber].MissionTask = Mission._Tasks[TaskNumber]
|
|
||||||
Client._Tasks[TaskNumber].Cargos = Mission._Tasks[TaskNumber].Cargos
|
|
||||||
Client._Tasks[TaskNumber].LandingZones = Mission._Tasks[TaskNumber].LandingZones
|
|
||||||
end
|
|
||||||
|
|
||||||
Mission:Ongoing()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- For each Client, check for each Task the state and evolve the mission.
|
|
||||||
-- This flag will indicate if the Task of the Client is Complete.
|
|
||||||
local TaskComplete = false
|
|
||||||
|
|
||||||
for TaskNumber, Task in pairs( Client._Tasks ) do
|
|
||||||
|
|
||||||
if not Task.Stage then
|
|
||||||
Task:SetStage( 1 )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local TransportTime = timer.getTime()
|
|
||||||
|
|
||||||
if not Task:IsDone() then
|
|
||||||
|
|
||||||
if Task:Goal() then
|
|
||||||
Task:ShowGoalProgress( Mission, Client )
|
|
||||||
end
|
|
||||||
|
|
||||||
--env.info( 'Scheduler: Mission = ' .. Mission.Name .. ' / Client = ' .. Client.ClientName .. ' / Task = ' .. Task.Name .. ' / Stage = ' .. Task.ActiveStage .. ' - ' .. Task.Stage.Name .. ' - ' .. Task.Stage.StageType )
|
|
||||||
|
|
||||||
-- Action
|
|
||||||
if Task:StageExecute() then
|
|
||||||
Task.Stage:Execute( Mission, Client, Task )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wait until execution is finished
|
|
||||||
if Task.ExecuteStage == _TransportExecuteStage.EXECUTING then
|
|
||||||
Task.Stage:Executing( Mission, Client, Task )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Validate completion or reverse to earlier stage
|
|
||||||
if Task.Time + Task.Stage.WaitTime <= TransportTime then
|
|
||||||
Task:SetStage( Task.Stage:Validate( Mission, Client, Task ) )
|
|
||||||
end
|
|
||||||
|
|
||||||
if Task:IsDone() then
|
|
||||||
--env.info( 'Scheduler: Mission '.. Mission.Name .. ' Task ' .. Task.Name .. ' Stage ' .. Task.Stage.Name .. ' done. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
|
|
||||||
TaskComplete = true -- when a task is not yet completed, a mission cannot be completed
|
|
||||||
|
|
||||||
else
|
|
||||||
-- break only if this task is not yet done, so that future task are not yet activated.
|
|
||||||
TaskComplete = false -- when a task is not yet completed, a mission cannot be completed
|
|
||||||
--env.info( 'Scheduler: Mission "'.. Mission.Name .. '" Task "' .. Task.Name .. '" Stage "' .. Task.Stage.Name .. '" break. TaskComplete = ' .. string.format ( "%s", TaskComplete and "true" or "false" ) )
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
if TaskComplete then
|
|
||||||
|
|
||||||
if Mission.GoalFunction ~= nil then
|
|
||||||
Mission.GoalFunction( Mission, Client )
|
|
||||||
end
|
|
||||||
if MISSIONSCHEDULER.Scoring then
|
|
||||||
MISSIONSCHEDULER.Scoring:_AddMissionTaskScore( Client:GetClientGroupDCSUnit(), Mission.Name, 25 )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- if not Mission:IsCompleted() then
|
|
||||||
-- end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local MissionComplete = true
|
|
||||||
for TaskNumber, Task in pairs( Mission._Tasks ) do
|
|
||||||
if Task:Goal() then
|
|
||||||
-- Task:ShowGoalProgress( Mission, Client )
|
|
||||||
if Task:IsGoalReached() then
|
|
||||||
else
|
|
||||||
MissionComplete = false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
MissionComplete = false -- If there is no goal, the mission should never be ended. The goal status will be set somewhere else.
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if MissionComplete then
|
|
||||||
Mission:Completed()
|
|
||||||
if MISSIONSCHEDULER.Scoring then
|
|
||||||
MISSIONSCHEDULER.Scoring:_AddMissionScore( Mission.Name, 100 )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if TaskComplete then
|
|
||||||
-- Reset for new tasking of active client
|
|
||||||
Client.ClientAlive = false -- Reset the client tasks.
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
else
|
|
||||||
if Client.ClientAlive then
|
|
||||||
env.info( 'Scheduler: Client "' .. Client.ClientName .. '" is inactive.' )
|
|
||||||
Client.ClientAlive = false
|
|
||||||
|
|
||||||
-- This is tricky. If we sanitize Client._Tasks before sanitizing Client._Tasks[TaskNumber].MissionTask, then the original MissionTask will be sanitized, and will be lost within the garbage collector.
|
|
||||||
-- So first sanitize Client._Tasks[TaskNumber].MissionTask, after that, sanitize only the whole _Tasks structure...
|
|
||||||
--Client._Tasks[TaskNumber].MissionTask = nil
|
|
||||||
--Client._Tasks = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If all Clients of this Mission are not activated, then the Mission status needs to be put back into Pending status.
|
|
||||||
-- But only if the Mission was Ongoing. In case the Mission is Completed or Failed, the Mission status may not be changed. In these cases, this will be the last run of this Mission in the Scheduler.
|
|
||||||
if ClientsAlive == false then
|
|
||||||
if Mission:IsOngoing() then
|
|
||||||
-- Mission status back to pending...
|
|
||||||
Mission:Pending()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Mission:StatusToClients()
|
|
||||||
|
|
||||||
if Mission:ReportTrigger() then
|
|
||||||
Mission:ReportToAll()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Start the MISSIONSCHEDULER.
|
|
||||||
function MISSIONSCHEDULER.Start()
|
|
||||||
if MISSIONSCHEDULER ~= nil then
|
|
||||||
--MISSIONSCHEDULER.SchedulerId = routines.scheduleFunction( MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
|
|
||||||
MISSIONSCHEDULER.SchedulerId = SCHEDULER:New( nil, MISSIONSCHEDULER.Scheduler, { }, 0, 2 )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop the MISSIONSCHEDULER.
|
|
||||||
function MISSIONSCHEDULER.Stop()
|
|
||||||
if MISSIONSCHEDULER.SchedulerId then
|
|
||||||
routines.removeFunction(MISSIONSCHEDULER.SchedulerId)
|
|
||||||
MISSIONSCHEDULER.SchedulerId = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
|
|
||||||
-- @param Mission is the MISSION object instantiated by @{MISSION:New}.
|
|
||||||
-- @return MISSION
|
|
||||||
-- @usage
|
|
||||||
-- -- Declare a mission.
|
|
||||||
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
|
|
||||||
-- 'Operational',
|
|
||||||
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
|
|
||||||
-- 'Russia' )
|
|
||||||
-- MISSIONSCHEDULER:AddMission( Mission )
|
|
||||||
function MISSIONSCHEDULER.AddMission( Mission )
|
|
||||||
MISSIONSCHEDULER.Missions[Mission.Name] = Mission
|
|
||||||
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount + 1
|
|
||||||
-- Add an overall AI Client for the AI tasks... This AI Client will facilitate the Events in the background for each Task.
|
|
||||||
--MissionAdd:AddClient( CLIENT:Register( 'AI' ) )
|
|
||||||
|
|
||||||
return Mission
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove a MISSION from the MISSIONSCHEDULER.
|
|
||||||
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
|
|
||||||
-- @usage
|
|
||||||
-- -- Declare a mission.
|
|
||||||
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
|
|
||||||
-- 'Operational',
|
|
||||||
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
|
|
||||||
-- 'Russia' )
|
|
||||||
-- MISSIONSCHEDULER:AddMission( Mission )
|
|
||||||
--
|
|
||||||
-- -- Now remove the Mission.
|
|
||||||
-- MISSIONSCHEDULER:RemoveMission( 'Russia Transport Troops SA-6' )
|
|
||||||
function MISSIONSCHEDULER.RemoveMission( MissionName )
|
|
||||||
MISSIONSCHEDULER.Missions[MissionName] = nil
|
|
||||||
MISSIONSCHEDULER.MissionCount = MISSIONSCHEDULER.MissionCount - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find a MISSION within the MISSIONSCHEDULER.
|
|
||||||
-- @param MissionName is the name of the MISSION given at declaration using @{AddMission}.
|
|
||||||
-- @return MISSION
|
|
||||||
-- @usage
|
|
||||||
-- -- Declare a mission.
|
|
||||||
-- Mission = MISSION:New( 'Russia Transport Troops SA-6',
|
|
||||||
-- 'Operational',
|
|
||||||
-- 'Transport troops from the control center to one of the SA-6 SAM sites to activate their operation.',
|
|
||||||
-- 'Russia' )
|
|
||||||
-- MISSIONSCHEDULER:AddMission( Mission )
|
|
||||||
--
|
|
||||||
-- -- Now find the Mission.
|
|
||||||
-- MissionFind = MISSIONSCHEDULER:FindMission( 'Russia Transport Troops SA-6' )
|
|
||||||
function MISSIONSCHEDULER.FindMission( MissionName )
|
|
||||||
return MISSIONSCHEDULER.Missions[MissionName]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal function used by the MISSIONSCHEDULER menu.
|
|
||||||
function MISSIONSCHEDULER.ReportMissionsShow( )
|
|
||||||
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
|
|
||||||
Mission.MissionReportShow = true
|
|
||||||
Mission.MissionReportFlash = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal function used by the MISSIONSCHEDULER menu.
|
|
||||||
function MISSIONSCHEDULER.ReportMissionsFlash( TimeInterval )
|
|
||||||
local Count = 0
|
|
||||||
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
|
|
||||||
Mission.MissionReportShow = false
|
|
||||||
Mission.MissionReportFlash = true
|
|
||||||
Mission.MissionReportTrigger = timer.getTime() + Count * TimeInterval
|
|
||||||
Mission.MissionTimeInterval = MISSIONSCHEDULER.MissionCount * TimeInterval
|
|
||||||
env.info( "TimeInterval = " .. Mission.MissionTimeInterval )
|
|
||||||
Count = Count + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal function used by the MISSIONSCHEDULER menu.
|
|
||||||
function MISSIONSCHEDULER.ReportMissionsHide( Prm )
|
|
||||||
for MissionName, Mission in pairs( MISSIONSCHEDULER.Missions ) do
|
|
||||||
Mission.MissionReportShow = false
|
|
||||||
Mission.MissionReportFlash = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Enables a MENU option in the communications menu under F10 to control the status of the active missions.
|
|
||||||
-- This function should be called only once when starting the MISSIONSCHEDULER.
|
|
||||||
function MISSIONSCHEDULER.ReportMenu()
|
|
||||||
local ReportMenu = SUBMENU:New( 'Status' )
|
|
||||||
local ReportMenuShow = COMMANDMENU:New( 'Show Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsShow, 0 )
|
|
||||||
local ReportMenuFlash = COMMANDMENU:New('Flash Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsFlash, 120 )
|
|
||||||
local ReportMenuHide = COMMANDMENU:New( 'Hide Report Missions', ReportMenu, MISSIONSCHEDULER.ReportMissionsHide, 0 )
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Show the remaining mission time.
|
|
||||||
function MISSIONSCHEDULER:TimeShow()
|
|
||||||
self.TimeIntervalCount = self.TimeIntervalCount + 1
|
|
||||||
if self.TimeIntervalCount >= self.TimeTriggerShow then
|
|
||||||
local TimeMsg = string.format("%00d", ( self.TimeSeconds / 60 ) - ( timer.getTime() / 60 )) .. ' minutes left until mission reload.'
|
|
||||||
MESSAGE:New( TimeMsg, self.TimeShow, "Mission time" ):ToAll()
|
|
||||||
self.TimeIntervalCount = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function MISSIONSCHEDULER:Time( TimeSeconds, TimeIntervalShow, TimeShow )
|
|
||||||
|
|
||||||
self.TimeIntervalCount = 0
|
|
||||||
self.TimeSeconds = TimeSeconds
|
|
||||||
self.TimeIntervalShow = TimeIntervalShow
|
|
||||||
self.TimeShow = TimeShow
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Adds a mission scoring to the game.
|
|
||||||
function MISSIONSCHEDULER:Scoring( Scoring )
|
|
||||||
|
|
||||||
self.Scoring = Scoring
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,6 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
|
|||||||
|
|
||||||
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
|
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -193,9 +192,13 @@ end
|
|||||||
--- Get the Task FSM Process Template
|
--- Get the Task FSM Process Template
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @return Core.Fsm#FSM_PROCESS
|
-- @return Core.Fsm#FSM_PROCESS
|
||||||
function TASK:GetUnitProcess()
|
function TASK:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
return self.FsmTemplate
|
if TaskUnit then
|
||||||
|
return self:GetStateMachine( TaskUnit )
|
||||||
|
else
|
||||||
|
return self.FsmTemplate
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the Task FSM Process Template
|
--- Sets the Task FSM Process Template
|
||||||
@ -228,7 +231,7 @@ function TASK:JoinUnit( PlayerUnit, PlayerGroup )
|
|||||||
-- If the PlayerGroup is not assigned to the Task, the menu needs to be set. In that case, the PlayerUnit will become the GroupPlayer leader.
|
-- If the PlayerGroup is not assigned to the Task, the menu needs to be set. In that case, the PlayerUnit will become the GroupPlayer leader.
|
||||||
if self:IsStatePlanned() or self:IsStateReplanned() then
|
if self:IsStatePlanned() or self:IsStateReplanned() then
|
||||||
self:SetMenuForGroup( PlayerGroup )
|
self:SetMenuForGroup( PlayerGroup )
|
||||||
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() )
|
--self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() )
|
||||||
end
|
end
|
||||||
if self:IsStateAssigned() then
|
if self:IsStateAssigned() then
|
||||||
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
|
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
|
||||||
@ -270,10 +273,11 @@ function TASK:AbortUnit( PlayerUnit )
|
|||||||
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() )
|
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() )
|
||||||
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
|
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
|
||||||
if #PlayerGroup:GetUnits() == 1 then
|
if #PlayerGroup:GetUnits() == 1 then
|
||||||
|
self:UnAssignFromGroup( PlayerGroup )
|
||||||
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
|
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
|
||||||
self:RemoveMenuForGroup( PlayerGroup )
|
self:RemoveMenuForGroup( PlayerGroup )
|
||||||
end
|
end
|
||||||
self:PlayerAborted( PlayerUnit )
|
self:Abort()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -339,7 +343,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Assign the @{Task}to a @{Group}.
|
--- Assign the @{Task} to a @{Group}.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
-- @return #TASK
|
-- @return #TASK
|
||||||
@ -350,7 +354,11 @@ function TASK:AssignToGroup( TaskGroup )
|
|||||||
|
|
||||||
TaskGroup:SetState( TaskGroup, "Assigned", self )
|
TaskGroup:SetState( TaskGroup, "Assigned", self )
|
||||||
|
|
||||||
self:RemoveMenuForGroup( TaskGroup )
|
local Mission = self:GetMission()
|
||||||
|
local MissionMenu = Mission:GetMenu( TaskGroup )
|
||||||
|
MissionMenu:RemoveSubMenus()
|
||||||
|
|
||||||
|
--self:RemoveMenuForGroup( TaskGroup )
|
||||||
self:SetAssignedMenuForGroup( TaskGroup )
|
self:SetAssignedMenuForGroup( TaskGroup )
|
||||||
|
|
||||||
local TaskUnits = TaskGroup:GetUnits()
|
local TaskUnits = TaskGroup:GetUnits()
|
||||||
@ -390,6 +398,7 @@ function TASK:AssignToUnit( TaskUnit )
|
|||||||
self:E({"Address FsmUnit", tostring( FsmUnit ) } )
|
self:E({"Address FsmUnit", tostring( FsmUnit ) } )
|
||||||
|
|
||||||
FsmUnit:SetStartState( "Planned" )
|
FsmUnit:SetStartState( "Planned" )
|
||||||
|
|
||||||
FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow.
|
FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow.
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -400,7 +409,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @return #TASK self
|
-- @return #TASK self
|
||||||
function TASK:UnAssignFromUnit( TaskUnit )
|
function TASK:UnAssignFromUnit( TaskUnit )
|
||||||
self:F( TaskUnit )
|
self:F( TaskUnit:GetName() )
|
||||||
|
|
||||||
self:RemoveStateMachine( TaskUnit )
|
self:RemoveStateMachine( TaskUnit )
|
||||||
|
|
||||||
@ -447,28 +456,37 @@ function TASK:SendBriefingToAssignedGroups()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Assign the @{Task} from the @{Group}s.
|
--- UnAssign the @{Task} from the @{Group}s.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
function TASK:UnAssignFromGroups()
|
function TASK:UnAssignFromGroups()
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
|
self:UnAssignFromGroup( TaskGroup )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
TaskGroup:SetState( TaskGroup, "Assigned", nil )
|
--- UnAssign the @{Task} from a @{Group}.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:UnAssignFromGroup( TaskGroup )
|
||||||
|
self:F2( { TaskGroup } )
|
||||||
|
|
||||||
|
TaskGroup:SetState( TaskGroup, "Assigned", nil )
|
||||||
|
|
||||||
self:RemoveMenuForGroup( TaskGroup )
|
self:RemoveAssignedMenuForGroup( TaskGroup )
|
||||||
|
|
||||||
local TaskUnits = TaskGroup:GetUnits()
|
local TaskUnits = TaskGroup:GetUnits()
|
||||||
for UnitID, UnitData in pairs( TaskUnits ) do
|
for UnitID, UnitData in pairs( TaskUnits ) do
|
||||||
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
|
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
|
||||||
local PlayerName = TaskUnit:GetPlayerName()
|
local PlayerName = TaskUnit:GetPlayerName()
|
||||||
if PlayerName ~= nil or PlayerName ~= "" then
|
if PlayerName ~= nil or PlayerName ~= "" then
|
||||||
self:UnAssignFromUnit( TaskUnit )
|
self:UnAssignFromUnit( TaskUnit )
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns if the @{Task} is assigned to the Group.
|
--- Returns if the @{Task} is assigned to the Group.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
@ -479,10 +497,12 @@ function TASK:IsAssignedToGroup( TaskGroup )
|
|||||||
|
|
||||||
if self:IsStateAssigned() then
|
if self:IsStateAssigned() then
|
||||||
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
|
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
|
||||||
|
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -511,37 +531,36 @@ end
|
|||||||
|
|
||||||
--- Set the menu options of the @{Task} to all the groups in the SetGroup.
|
--- Set the menu options of the @{Task} to all the groups in the SetGroup.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
function TASK:SetMenu()
|
-- @param #number MenuTime
|
||||||
|
-- @return #TASK
|
||||||
|
function TASK:SetMenu( MenuTime )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
self.SetGroup:Flush()
|
self.SetGroup:Flush()
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetSet() ) do
|
||||||
if self:IsStatePlanned() or self:IsStateReplanned() then
|
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
|
||||||
self:SetMenuForGroup( TaskGroup )
|
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
|
||||||
|
if self:IsStatePlanned() or self:IsStateReplanned() then
|
||||||
|
self:SetMenuForGroup( TaskGroup, MenuTime )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Remove the menu options of the @{Task} to all the groups in the SetGroup.
|
|
||||||
-- @param #TASK self
|
|
||||||
-- @return #TASK self
|
|
||||||
function TASK:RemoveMenu()
|
|
||||||
|
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
|
||||||
self:RemoveMenuForGroup( TaskGroup )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set the Menu for a Group
|
--- Set the Menu for a Group
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
function TASK:SetMenuForGroup( TaskGroup )
|
-- @param #number MenuTime
|
||||||
|
-- @return #TASK
|
||||||
|
function TASK:SetMenuForGroup( TaskGroup, MenuTime )
|
||||||
|
|
||||||
if not self:IsAssignedToGroup( TaskGroup ) then
|
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
|
||||||
self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName() )
|
self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName(), MenuTime )
|
||||||
else
|
else
|
||||||
self:SetAssignedMenuForGroup( TaskGroup )
|
if not self:IsAssignedToGroup( TaskGroup ) then
|
||||||
|
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -550,16 +569,24 @@ end
|
|||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
-- @param #string MenuText The menu text.
|
-- @param #string MenuText The menu text.
|
||||||
|
-- @param #number MenuTime
|
||||||
-- @return #TASK self
|
-- @return #TASK self
|
||||||
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText )
|
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
|
||||||
self:E( TaskGroup:GetName() )
|
self:E( TaskGroup:GetName() )
|
||||||
|
|
||||||
local Mission = self:GetMission()
|
local Mission = self:GetMission()
|
||||||
local MissionMenu = Mission:GetMissionMenu( TaskGroup )
|
local MissionName = Mission:GetName()
|
||||||
|
local CommandCenter = Mission:GetCommandCenter()
|
||||||
|
local CommandCenterMenu = CommandCenter:GetMenu()
|
||||||
|
|
||||||
|
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
|
|
||||||
|
local MissionMenu = Mission:GetMenu( TaskGroup )
|
||||||
|
|
||||||
local TaskType = self:GetType()
|
local TaskType = self:GetType()
|
||||||
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu )
|
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu ):SetTime( MenuTime )
|
||||||
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } )
|
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -567,32 +594,84 @@ end
|
|||||||
--- Set the assigned menu options of the @{Task}.
|
--- Set the assigned menu options of the @{Task}.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
|
-- @param #number MenuTime
|
||||||
-- @return #TASK self
|
-- @return #TASK self
|
||||||
function TASK:SetAssignedMenuForGroup( TaskGroup )
|
function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime )
|
||||||
self:E( TaskGroup:GetName() )
|
self:E( TaskGroup:GetName() )
|
||||||
|
|
||||||
local Mission = self:GetMission()
|
local Mission = self:GetMission()
|
||||||
local MissionMenu = Mission:GetMissionMenu( TaskGroup )
|
local MissionMenu = Mission:GetMenu( TaskGroup )
|
||||||
|
|
||||||
self:E( { MissionMenu = MissionMenu } )
|
self:E( { MissionMenu = MissionMenu } )
|
||||||
|
|
||||||
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, { self = self, TaskGroup = TaskGroup } )
|
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime )
|
||||||
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, { self = self, TaskGroup = TaskGroup } )
|
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove the menu options of the @{Task} to all the groups in the SetGroup.
|
||||||
|
-- @param #TASK self
|
||||||
|
-- @param #number MenuTime
|
||||||
|
-- @return #TASK
|
||||||
|
function TASK:RemoveMenu( MenuTime )
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
|
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
|
||||||
|
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
|
||||||
|
if not self:IsAssignedToGroup( TaskGroup ) then
|
||||||
|
self:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Remove the menu option of the @{Task} for a @{Group}.
|
--- Remove the menu option of the @{Task} for a @{Group}.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
|
-- @param #number MenuTime
|
||||||
-- @return #TASK self
|
-- @return #TASK self
|
||||||
function TASK:RemoveMenuForGroup( TaskGroup )
|
function TASK:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
|
||||||
|
self:F()
|
||||||
|
|
||||||
local Mission = self:GetMission()
|
local Mission = self:GetMission()
|
||||||
local MissionName = Mission:GetName()
|
local MissionName = Mission:GetName()
|
||||||
|
|
||||||
|
local MissionMenu = Mission:GetMenu( TaskGroup )
|
||||||
|
|
||||||
|
if MissionMenu then
|
||||||
|
local TaskType = self:GetType()
|
||||||
|
local TypeMenu = MissionMenu:GetMenu( TaskType )
|
||||||
|
|
||||||
|
if TypeMenu then
|
||||||
|
local TaskMenu = TypeMenu:GetMenu( self:GetTaskName() )
|
||||||
|
if TaskMenu then
|
||||||
|
TaskMenu:Remove( MenuTime )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
local MissionMenu = Mission:GetMissionMenu( TaskGroup )
|
--- Remove the assigned menu option of the @{Task} for a @{Group}.
|
||||||
MissionMenu:Remove()
|
-- @param #TASK self
|
||||||
|
-- @param Wrapper.Group#GROUP TaskGroup
|
||||||
|
-- @param #number MenuTime
|
||||||
|
-- @return #TASK self
|
||||||
|
function TASK:RemoveAssignedMenuForGroup( TaskGroup )
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
local Mission = self:GetMission()
|
||||||
|
local MissionName = Mission:GetName()
|
||||||
|
|
||||||
|
local MissionMenu = Mission:GetMenu( TaskGroup )
|
||||||
|
|
||||||
|
if MissionMenu then
|
||||||
|
MissionMenu:RemoveSubMenus()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function TASK.MenuAssignToGroup( MenuParam )
|
function TASK.MenuAssignToGroup( MenuParam )
|
||||||
@ -605,19 +684,21 @@ function TASK.MenuAssignToGroup( MenuParam )
|
|||||||
self:AssignToGroup( TaskGroup )
|
self:AssignToGroup( TaskGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
function TASK.MenuTaskStatus( MenuParam )
|
--- Report the task status.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:MenuTaskStatus( TaskGroup )
|
||||||
|
|
||||||
local self = MenuParam.self
|
local ReportText = self:ReportDetails()
|
||||||
local TaskGroup = MenuParam.TaskGroup
|
|
||||||
|
|
||||||
--self:AssignToGroup( TaskGroup )
|
self:T( ReportText )
|
||||||
|
self:GetMission():GetCommandCenter():MessageToGroup( ReportText, TaskGroup )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function TASK.MenuTaskAbort( MenuParam )
|
--- Report the task status.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:MenuTaskAbort( TaskGroup )
|
||||||
|
|
||||||
local self = MenuParam.self
|
|
||||||
local TaskGroup = MenuParam.TaskGroup
|
|
||||||
|
|
||||||
self:Abort()
|
self:Abort()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -662,15 +743,26 @@ end
|
|||||||
--- Add a FiniteStateMachine to @{Task} with key Task@{Unit}
|
--- Add a FiniteStateMachine to @{Task} with key Task@{Unit}
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||||
-- @return #TASK self
|
-- @return #TASK self
|
||||||
function TASK:SetStateMachine( TaskUnit, Fsm )
|
function TASK:SetStateMachine( TaskUnit, Fsm )
|
||||||
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
|
self:F2( { TaskUnit, self.Fsm[TaskUnit] ~= nil, Fsm:GetClassNameAndID() } )
|
||||||
|
|
||||||
self.Fsm[TaskUnit] = Fsm
|
self.Fsm[TaskUnit] = Fsm
|
||||||
|
|
||||||
return Fsm
|
return Fsm
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the FiniteStateMachine of @{Task} with key Task@{Unit}
|
||||||
|
-- @param #TASK self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @return Core.Fsm#FSM_PROCESS
|
||||||
|
function TASK:GetStateMachine( TaskUnit )
|
||||||
|
self:F2( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
|
||||||
|
|
||||||
|
return self.Fsm[TaskUnit]
|
||||||
|
end
|
||||||
|
|
||||||
--- Remove FiniteStateMachines from @{Task} with key Task@{Unit}
|
--- Remove FiniteStateMachines from @{Task} with key Task@{Unit}
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
@ -678,9 +770,15 @@ end
|
|||||||
function TASK:RemoveStateMachine( TaskUnit )
|
function TASK:RemoveStateMachine( TaskUnit )
|
||||||
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
|
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
|
||||||
|
|
||||||
|
self:E( self.Fsm )
|
||||||
|
for TaskUnitT, Fsm in pairs( self.Fsm ) do
|
||||||
|
self:E( TaskUnitT )
|
||||||
|
end
|
||||||
|
|
||||||
self.Fsm[TaskUnit] = nil
|
self.Fsm[TaskUnit] = nil
|
||||||
|
|
||||||
collectgarbage()
|
collectgarbage()
|
||||||
self:T( "Garbage Collected, Processes should be finalized now ...")
|
self:E( "Garbage Collected, Processes should be finalized now ...")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task}
|
--- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task}
|
||||||
@ -795,6 +893,32 @@ function TASK:IsStatePlanned()
|
|||||||
return self:Is( "Planned" )
|
return self:Is( "Planned" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets a @{Task} to status **Aborted**.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:StateAborted()
|
||||||
|
self:SetState( self, "State", "Aborted" )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Is the @{Task} status **Aborted**.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:IsStateAborted()
|
||||||
|
return self:Is( "Aborted" )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Sets a @{Task} to status **Cancelled**.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:StateCancelled()
|
||||||
|
self:SetState( self, "State", "Cancelled" )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Is the @{Task} status **Cancelled**.
|
||||||
|
-- @param #TASK self
|
||||||
|
function TASK:IsStateCancelled()
|
||||||
|
return self:Is( "Cancelled" )
|
||||||
|
end
|
||||||
|
|
||||||
--- Sets a @{Task} to status **Assigned**.
|
--- Sets a @{Task} to status **Assigned**.
|
||||||
-- @param #TASK self
|
-- @param #TASK self
|
||||||
function TASK:StateAssigned()
|
function TASK:StateAssigned()
|
||||||
@ -875,7 +999,7 @@ function TASK:onenterSuccess( From, Event, To )
|
|||||||
|
|
||||||
self:E( "Task Success" )
|
self:E( "Task Success" )
|
||||||
|
|
||||||
self:MessageToGroups( "Task " .. self:GetName() .. " is successful! Good job!" )
|
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is successful! Good job!" )
|
||||||
self:UnAssignFromGroups()
|
self:UnAssignFromGroups()
|
||||||
|
|
||||||
self:GetMission():__Complete( 1 )
|
self:GetMission():__Complete( 1 )
|
||||||
@ -1009,24 +1133,19 @@ function TASK:ReportDetails()
|
|||||||
-- Determine the status of the Task.
|
-- Determine the status of the Task.
|
||||||
local State = self:GetState()
|
local State = self:GetState()
|
||||||
|
|
||||||
|
|
||||||
-- Loop each Unit active in the Task, and find Player Names.
|
-- Loop each Unit active in the Task, and find Player Names.
|
||||||
local PlayerNames = {}
|
local PlayerNames = {}
|
||||||
for PlayerGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
|
local PlayerReport = REPORT:New( " - Players:" )
|
||||||
local Player = PlayerGroup -- Wrapper.Group#GROUP
|
for PlayerGroupID, PlayerGroupData in pairs( self:GetGroups():GetSet() ) do
|
||||||
for PlayerUnitID, PlayerUnit in pairs( PlayerGroup:GetUnits() ) do
|
local PlayerGroup = PlayerGroupData -- Wrapper.Group#GROUP
|
||||||
local PlayerUnit = PlayerUnit -- Wrapper.Unit#UNIT
|
PlayerNames = PlayerGroup:GetPlayerNames()
|
||||||
if PlayerUnit and PlayerUnit:IsAlive() then
|
if PlayerNames then
|
||||||
local PlayerName = PlayerUnit:GetPlayerName()
|
PlayerReport:Add( " -- Group " .. PlayerGroup:GetCallsign() .. ": " .. table.concat( PlayerNames, ", " ) )
|
||||||
PlayerNames[#PlayerNames+1] = PlayerName
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local PlayerNameText = table.concat( PlayerNames, ", " )
|
|
||||||
Report:Add( "Task " .. Name .. " - State '" .. State .. "' - Players " .. PlayerNameText )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Loop each Process in the Task, and find Reporting Details.
|
-- Loop each Process in the Task, and find Reporting Details.
|
||||||
|
Report:Add( string.format( " - Task %s\n -- State '%s'\n%s", Name, State, PlayerReport:Text() ) )
|
||||||
return Report:Text()
|
return Report:Text()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,28 +1,53 @@
|
|||||||
--- (AI) (SP) (MP) Tasking for Air to Ground Processes.
|
--- This module contains the TASK_A2G classes.
|
||||||
--
|
--
|
||||||
-- 1) @{#TASK_A2G} class, extends @{Task#TASK}
|
-- # 1) @{Task_A2G#TASK_A2G} class, extends @{Task#TASK}
|
||||||
-- =================================================
|
--
|
||||||
-- The @{#TASK_A2G} class defines a CAS or BAI task of a @{Set} of Target Units,
|
-- The @{#TASK_A2G} class defines Air To Ground tasks for a @{Set} of Target Units,
|
||||||
-- located at a Target Zone, based on the tasking capabilities defined in @{Task#TASK}.
|
-- based on the tasking capabilities defined in @{Task#TASK}.
|
||||||
-- The TASK_A2G is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
|
-- The TASK_A2G is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
|
||||||
--
|
--
|
||||||
-- * **None**: Start of the process
|
-- * **None**: Start of the process
|
||||||
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task.
|
-- * **Planned**: The A2G task is planned.
|
||||||
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_ROUTE} is started to route the active Units in the Group to the attack zone.
|
-- * **Assigned**: The A2G task is assigned to a @{Group#GROUP}.
|
||||||
-- * **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.
|
-- * **Success**: The A2G task is successfully completed.
|
||||||
-- * **Failed**: The SEAD task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
|
-- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
|
||||||
--
|
--
|
||||||
|
-- # 1) @{Task_A2G#TASK_SEAD} class, extends @{Task_A2G#TASK_A2G}
|
||||||
|
--
|
||||||
|
-- The @{#TASK_SEAD} class defines a SEAD task for a @{Set} of Target Units.
|
||||||
|
--
|
||||||
|
-- ====
|
||||||
|
--
|
||||||
|
-- # **API CHANGE HISTORY**
|
||||||
|
--
|
||||||
|
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
|
||||||
|
--
|
||||||
|
-- * **Added** parts are expressed in bold type face.
|
||||||
|
-- * _Removed_ parts are expressed in italic type face.
|
||||||
|
--
|
||||||
|
-- Hereby the change log:
|
||||||
|
--
|
||||||
|
-- 2017-03-09: Revised version.
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: FlightControl - Design and Programming
|
-- # **AUTHORS and CONTRIBUTIONS**
|
||||||
--
|
--
|
||||||
|
-- ### Contributions:
|
||||||
|
--
|
||||||
|
-- * **[WingThor]**: Concept, Advice & Testing.
|
||||||
|
--
|
||||||
|
-- ### Authors:
|
||||||
|
--
|
||||||
|
-- * **FlightControl**: Concept, Design & Programming.
|
||||||
|
--
|
||||||
-- @module Task_A2G
|
-- @module Task_A2G
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2G
|
do -- TASK_A2G
|
||||||
|
|
||||||
--- The TASK_A2G class
|
--- The TASK_A2G class
|
||||||
-- @type TASK_A2G
|
-- @type TASK_A2G
|
||||||
|
-- @field Set#SET_UNIT TargetSetUnit
|
||||||
-- @extends Tasking.Task#TASK
|
-- @extends Tasking.Task#TASK
|
||||||
TASK_A2G = {
|
TASK_A2G = {
|
||||||
ClassName = "TASK_A2G",
|
ClassName = "TASK_A2G",
|
||||||
@ -33,52 +58,312 @@ do -- TASK_A2G
|
|||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||||
-- @param #string TaskName The name of the Task.
|
-- @param #string TaskName The name of the Task.
|
||||||
-- @param #string TaskType BAI or CAS
|
|
||||||
-- @param Set#SET_UNIT UnitSetTargets
|
-- @param Set#SET_UNIT UnitSetTargets
|
||||||
-- @param Core.Zone#ZONE_BASE TargetZone
|
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
|
||||||
|
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
|
||||||
|
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
|
||||||
-- @return #TASK_A2G self
|
-- @return #TASK_A2G self
|
||||||
function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit )
|
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType )
|
||||||
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) )
|
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- Tasking.Task#TASK_A2G
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
self.TargetSetUnit = TargetSetUnit
|
||||||
self.TargetZone = TargetZone
|
self.TaskType = TaskType
|
||||||
self.FACUnit = FACUnit
|
|
||||||
|
|
||||||
local A2GUnitProcess = self:GetUnitProcess()
|
|
||||||
|
|
||||||
A2GUnitProcess:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( "Attack the Area" ), { Assigned = "Route", Rejected = "Eject" } )
|
Mission:AddTask( self )
|
||||||
A2GUnitProcess:AddProcess ( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
|
|
||||||
A2GUnitProcess:AddTransition( "Rejected", "Eject", "Planned" )
|
|
||||||
A2GUnitProcess:AddTransition( "Arrived", "Update", "Updated" )
|
|
||||||
A2GUnitProcess:AddProcess ( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "Attack" ), { Accounted = "Success" } )
|
|
||||||
A2GUnitProcess:AddProcess ( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
|
|
||||||
--Fsm:AddProcess ( "Updated", "JTAC", PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) )
|
|
||||||
A2GUnitProcess:AddTransition( "Accounted", "Success", "Success" )
|
|
||||||
A2GUnitProcess:AddTransition( "Failed", "Fail", "Failed" )
|
|
||||||
|
|
||||||
function A2GUnitProcess:onenterUpdated( TaskUnit )
|
local Fsm = self:GetUnitProcess()
|
||||||
self:E( { self } )
|
|
||||||
self:Account()
|
|
||||||
self:Smoke()
|
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "RouteToRendezVous", Rejected = "Reject" } )
|
||||||
|
|
||||||
|
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
|
||||||
|
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
|
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
|
|
||||||
|
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
|
||||||
|
|
||||||
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
|
||||||
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
|
||||||
|
|
||||||
|
Fsm:AddProcess ( "Engaging", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, self.TaskType ), { Accounted = "Success" } )
|
||||||
|
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
|
||||||
|
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
|
||||||
|
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
|
||||||
|
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
|
||||||
|
|
||||||
|
Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
|
||||||
|
Fsm:AddTransition( "Accounted", "Success", "Success" )
|
||||||
|
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
||||||
|
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
||||||
|
|
||||||
|
|
||||||
|
--- Test
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
|
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
|
||||||
|
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
|
-- Determine the first Unit from the self.RendezVousSetUnit
|
||||||
|
|
||||||
|
if Task:GetRendezVousZone( TaskUnit ) then
|
||||||
|
self:__RouteToRendezVousZone( 0.1 )
|
||||||
|
else
|
||||||
|
if Task:GetRendezVousPointVec2( TaskUnit ) then
|
||||||
|
self:__RouteToRendezVousPoint( 0.1 )
|
||||||
|
else
|
||||||
|
self:__ArriveAtRendezVous( 0.1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Test
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Tasking.Task#TASK_A2G Task
|
||||||
|
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
|
||||||
|
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
|
self:__Engage( 0.1 )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Tasking.Task#TASK_A2G Task
|
||||||
|
function Fsm:onafterEngage( TaskUnit, Task )
|
||||||
|
self:E( { self } )
|
||||||
|
self:__Account( 0.1 )
|
||||||
|
self:__RouteToTarget(0.1 )
|
||||||
|
self:__RouteToTargets( -10 )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
|
function Fsm:onafterRouteToTarget( TaskUnit, Task )
|
||||||
|
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
|
if Task:GetTargetZone( TaskUnit ) then
|
||||||
|
self:__RouteToTargetZone( 0.1 )
|
||||||
|
else
|
||||||
|
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
|
||||||
|
if TargetUnit then
|
||||||
|
local PointVec2 = TargetUnit:GetPointVec2()
|
||||||
|
self:T( { TargetPointVec2 = PointVec2, PointVec2:GetX(), PointVec2:GetAlt(), PointVec2:GetZ() } )
|
||||||
|
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
|
||||||
|
end
|
||||||
|
self:__RouteToTargetPoint( 0.1 )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Test
|
||||||
|
-- @param #FSM_PROCESS self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
|
function Fsm:onafterRouteToTargets( TaskUnit, Task )
|
||||||
|
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
|
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
|
||||||
|
if TargetUnit then
|
||||||
|
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
|
||||||
|
end
|
||||||
|
self:__RouteToTargets( -10 )
|
||||||
|
end
|
||||||
|
|
||||||
--_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
|
|
||||||
--_EVENTDISPATCHER:OnDead( self._EventDead, self )
|
|
||||||
--_EVENTDISPATCHER:OnCrash( self._EventDead, self )
|
|
||||||
--_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
function TASK_A2G:GetPlannedMenuText()
|
function TASK_A2G:GetPlannedMenuText()
|
||||||
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Core.Point#POINT_VEC2 RendezVousPointVec2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
|
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
function TASK_A2G:SetRendezVousPointVec2( RendezVousPointVec2, RendezVousRange, TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
|
ActRouteRendezVous:SetPointVec2( RendezVousPointVec2 )
|
||||||
|
ActRouteRendezVous:SetRange( RendezVousRange )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @return Core.Point#POINT_VEC2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
|
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
|
function TASK_A2G:GetRendezVousPointVec2( TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
|
return ActRouteRendezVous:GetPointVec2(), ActRouteRendezVous:GetRange()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
function TASK_A2G:SetRendezVousZone( RendezVousZone, TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
|
ActRouteRendezVous:SetZone( RendezVousZone )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @return Core.Zone#ZONE_BASE The Zone object where the RendezVous is located on the map.
|
||||||
|
function TASK_A2G:GetRendezVousZone( TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
|
return ActRouteRendezVous:GetZone()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Core.Point#POINT_VEC2 TargetPointVec2 The PointVec2 object where the Target is located on the map.
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
function TASK_A2G:SetTargetPointVec2( TargetPointVec2, TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
|
ActRouteTarget:SetPointVec2( TargetPointVec2 )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @return Core.Point#POINT_VEC2 The PointVec2 object where the Target is located on the map.
|
||||||
|
function TASK_A2G:GetTargetPointVec2( TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
|
return ActRouteTarget:GetPointVec2()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
function TASK_A2G:SetTargetZone( TargetZone, TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
|
ActRouteTarget:SetZone( TargetZone )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- @param #TASK_A2G self
|
||||||
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
|
-- @return Core.Zone#ZONE_BASE The Zone object where the Target is located on the map.
|
||||||
|
function TASK_A2G:GetTargetZone( TaskUnit )
|
||||||
|
|
||||||
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
|
return ActRouteTarget:GetZone()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do -- TASK_SEAD
|
||||||
|
|
||||||
|
--- The TASK_SEAD class
|
||||||
|
-- @type TASK_SEAD
|
||||||
|
-- @field Set#SET_UNIT TargetSetUnit
|
||||||
|
-- @extends Tasking.Task#TASK
|
||||||
|
TASK_SEAD = {
|
||||||
|
ClassName = "TASK_SEAD",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Instantiates a new TASK_SEAD.
|
||||||
|
-- @param #TASK_SEAD self
|
||||||
|
-- @param Tasking.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 #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
|
||||||
|
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
|
||||||
|
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
|
||||||
|
-- @return #TASK_SEAD self
|
||||||
|
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit )
|
||||||
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD" ) ) -- #TASK_SEAD
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
do -- TASK_BAI
|
||||||
|
|
||||||
|
--- The TASK_BAI class
|
||||||
|
-- @type TASK_BAI
|
||||||
|
-- @field Set#SET_UNIT TargetSetUnit
|
||||||
|
-- @extends Tasking.Task#TASK
|
||||||
|
TASK_BAI = {
|
||||||
|
ClassName = "TASK_BAI",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Instantiates a new TASK_BAI.
|
||||||
|
-- @param #TASK_BAI self
|
||||||
|
-- @param Tasking.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 #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
|
||||||
|
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
|
||||||
|
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
|
||||||
|
-- @return #TASK_BAI self
|
||||||
|
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit )
|
||||||
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI" ) ) -- #TASK_BAI
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
do -- TASK_CAS
|
||||||
|
|
||||||
|
--- The TASK_CAS class
|
||||||
|
-- @type TASK_CAS
|
||||||
|
-- @field Set#SET_UNIT TargetSetUnit
|
||||||
|
-- @extends Tasking.Task#TASK
|
||||||
|
TASK_CAS = {
|
||||||
|
ClassName = "TASK_CAS",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Instantiates a new TASK_CAS.
|
||||||
|
-- @param #TASK_CAS self
|
||||||
|
-- @param Tasking.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 #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
|
||||||
|
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
|
||||||
|
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
|
||||||
|
-- @return #TASK_CAS self
|
||||||
|
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit )
|
||||||
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS" ) ) -- #TASK_CAS
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|||||||
286
Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua
Normal file
286
Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
--- **Tasking** - The TASK_A2G_DISPATCHER creates and manages player TASK_A2G tasks based on detected targets.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # 1) @{#TASK_A2G_DISPATCHER} class, extends @{#DETECTION_MANAGER}
|
||||||
|
--
|
||||||
|
-- The @{#TASK_A2G_DISPATCHER} class implements the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of FAC (groups).
|
||||||
|
-- The FAC will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
||||||
|
-- Find a summary below describing for which situation a task type is created:
|
||||||
|
--
|
||||||
|
-- * **CAS Task**: Is created when there are enemy ground units within range of the FAC, while there are friendly units in the FAC perimeter.
|
||||||
|
-- * **BAI Task**: Is created when there are enemy ground units within range of the FAC, while there are NO other friendly units within the FAC perimeter.
|
||||||
|
-- * **SEAD Task**: Is created when there are enemy ground units wihtin range of the FAC, with air search radars.
|
||||||
|
--
|
||||||
|
-- Other task types will follow...
|
||||||
|
--
|
||||||
|
-- 3.1) TASK_A2G_DISPATCHER constructor:
|
||||||
|
-- --------------------------------------
|
||||||
|
-- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK_A2G_DISPATCHER instance.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # **API CHANGE HISTORY**
|
||||||
|
--
|
||||||
|
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
|
||||||
|
--
|
||||||
|
-- * **Added** parts are expressed in bold type face.
|
||||||
|
-- * _Removed_ parts are expressed in italic type face.
|
||||||
|
--
|
||||||
|
-- Hereby the change log:
|
||||||
|
--
|
||||||
|
-- 2017-03-09: Initial class and API.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # **AUTHORS and CONTRIBUTIONS**
|
||||||
|
--
|
||||||
|
-- ### Contributions:
|
||||||
|
--
|
||||||
|
-- ### Authors:
|
||||||
|
--
|
||||||
|
-- * **FlightControl**: Concept, Design & Programming.
|
||||||
|
--
|
||||||
|
-- @module Task_A2G_Dispatcher
|
||||||
|
|
||||||
|
do -- TASK_A2G_DISPATCHER
|
||||||
|
|
||||||
|
--- TASK_A2G_DISPATCHER class.
|
||||||
|
-- @type TASK_A2G_DISPATCHER
|
||||||
|
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
||||||
|
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
|
||||||
|
-- @field Tasking.Mission#MISSION Mission
|
||||||
|
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||||
|
TASK_A2G_DISPATCHER = {
|
||||||
|
ClassName = "TASK_A2G_DISPATCHER",
|
||||||
|
Mission = nil,
|
||||||
|
Detection = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- TASK_A2G_DISPATCHER constructor.
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Tasking.Mission#MISSION The mission for which the task dispatching is done.
|
||||||
|
-- @param Set#SET_GROUP SetGroup The set of groups that can join the tasks within the mission.
|
||||||
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
|
||||||
|
-- @return #TASK_A2G_DISPATCHER self
|
||||||
|
function TASK_A2G_DISPATCHER:New( Mission, SetGroup, Detection )
|
||||||
|
|
||||||
|
-- Inherits from DETECTION_MANAGER
|
||||||
|
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2G_DISPATCHER
|
||||||
|
|
||||||
|
self.Detection = Detection
|
||||||
|
self.Mission = Mission
|
||||||
|
|
||||||
|
self:Schedule( 30 )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a SEAD task when there are targets for it.
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
|
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||||
|
-- @return #nil If there are no targets to be set.
|
||||||
|
function TASK_A2G_DISPATCHER:EvaluateSEAD( DetectedItem )
|
||||||
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
|
local DetectedSet = DetectedItem.Set
|
||||||
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
|
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||||
|
local RadarCount = DetectedSet:HasSEAD()
|
||||||
|
|
||||||
|
if RadarCount > 0 then
|
||||||
|
|
||||||
|
-- Here we're doing something advanced... We're copying the DetectedSet, but making a new Set only with SEADable Radar units in it.
|
||||||
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
|
TargetSetUnit:FilterHasSEAD()
|
||||||
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
|
return TargetSetUnit
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a CAS task when there are targets for it.
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
|
-- @return Tasking.Task#TASK
|
||||||
|
function TASK_A2G_DISPATCHER:EvaluateCAS( DetectedItem )
|
||||||
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
|
local DetectedSet = DetectedItem.Set
|
||||||
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
|
|
||||||
|
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||||
|
local GroundUnitCount = DetectedSet:HasGroundUnits()
|
||||||
|
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem )
|
||||||
|
|
||||||
|
if GroundUnitCount > 0 and FriendliesNearBy == true then
|
||||||
|
|
||||||
|
-- Copy the Set
|
||||||
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
|
return TargetSetUnit
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a BAI task when there are targets for it.
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
|
-- @return Tasking.Task#TASK
|
||||||
|
function TASK_A2G_DISPATCHER:EvaluateBAI( DetectedItem, FriendlyCoalition )
|
||||||
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
|
local DetectedSet = DetectedItem.Set
|
||||||
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
|
|
||||||
|
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||||
|
local GroundUnitCount = DetectedSet:HasGroundUnits()
|
||||||
|
local FriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem )
|
||||||
|
|
||||||
|
if GroundUnitCount > 0 and FriendliesNearBy == false then
|
||||||
|
|
||||||
|
-- Copy the Set
|
||||||
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
|
return TargetSetUnit
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Evaluates the removal of the Task from the Mission.
|
||||||
|
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
|
-- @param Tasking.Task#TASK Task
|
||||||
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
|
-- @return Tasking.Task#TASK
|
||||||
|
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItem )
|
||||||
|
|
||||||
|
if Task then
|
||||||
|
if Task:IsStatePlanned() and DetectedItem.Changed == true then
|
||||||
|
self:E( "Removing Tasking: " .. Task:GetTaskName() )
|
||||||
|
Task = Mission:RemoveTask( Task )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Task
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
|
||||||
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object.
|
||||||
|
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||||
|
function TASK_A2G_DISPATCHER:ProcessDetected( Detection )
|
||||||
|
self:F2()
|
||||||
|
|
||||||
|
local AreaMsg = {}
|
||||||
|
local TaskMsg = {}
|
||||||
|
local ChangeMsg = {}
|
||||||
|
|
||||||
|
local Mission = self.Mission
|
||||||
|
local ReportSEAD = REPORT:New( " - SEAD Tasks:")
|
||||||
|
local ReportCAS = REPORT:New( " - CAS Tasks:")
|
||||||
|
local ReportBAI = REPORT:New( " - BAI Tasks:")
|
||||||
|
local ReportChanges = REPORT:New( " - Changes:" )
|
||||||
|
|
||||||
|
--- First we need to the detected targets.
|
||||||
|
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
||||||
|
|
||||||
|
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||||
|
local DetectedSet = DetectedItem.Set -- Functional.Detection#DETECTION_BASE.DetectedSet
|
||||||
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
|
||||||
|
DetectedSet:Flush()
|
||||||
|
|
||||||
|
local ItemID = DetectedItem.ItemID
|
||||||
|
|
||||||
|
-- Evaluate SEAD Tasking
|
||||||
|
local SEADTask = Mission:GetTask( string.format( "SEAD.%03d", ItemID ) )
|
||||||
|
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedItem )
|
||||||
|
if not SEADTask then
|
||||||
|
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
|
||||||
|
if TargetSetUnit then
|
||||||
|
local Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", ItemID ), TargetSetUnit )
|
||||||
|
Task:SetTargetZone( DetectedZone )
|
||||||
|
SEADTask = Mission:AddTask( Task )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if SEADTask and SEADTask:IsStatePlanned() then
|
||||||
|
ReportSEAD:Add( string.format( " - %s.%02d - %s", "SEAD", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Evaluate CAS Tasking
|
||||||
|
local CASTask = Mission:GetTask( string.format( "CAS.%03d", ItemID ) )
|
||||||
|
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedItem )
|
||||||
|
if not CASTask then
|
||||||
|
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
|
||||||
|
if TargetSetUnit then
|
||||||
|
local Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", ItemID ), TargetSetUnit )
|
||||||
|
--Task:SetTargetZone( DetectedZone )
|
||||||
|
CASTask = Mission:AddTask( Task )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if CASTask and CASTask:IsStatePlanned() then
|
||||||
|
ReportCAS:Add( string.format( " - %s.%02d - %s", "CAS", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Evaluate BAI Tasking
|
||||||
|
local BAITask = Mission:GetTask( string.format( "BAI.%03d", ItemID ) )
|
||||||
|
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedItem )
|
||||||
|
if not BAITask then
|
||||||
|
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
|
||||||
|
if TargetSetUnit then
|
||||||
|
local Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", ItemID ), TargetSetUnit )
|
||||||
|
Task:SetTargetZone( DetectedZone )
|
||||||
|
BAITask = Mission:AddTask( Task )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if BAITask and BAITask:IsStatePlanned() then
|
||||||
|
ReportBAI:Add( string.format( " - %s.%02d - %s", "BAI", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Loop through the changes ...
|
||||||
|
local ChangeText = Detection:GetChangeText( DetectedItem )
|
||||||
|
ReportChanges:Add( ChangeText )
|
||||||
|
|
||||||
|
|
||||||
|
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
||||||
|
Detection:AcceptChanges( DetectedItem )
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO set menus using the HQ coordinator
|
||||||
|
Mission:GetCommandCenter():SetMenu()
|
||||||
|
|
||||||
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
|
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
|
||||||
|
Mission:GetCommandCenter():MessageToGroup(
|
||||||
|
string.format( "HQ Reporting - Planned tasks for mission '%s':\n%s\n",
|
||||||
|
self.Mission:GetName(),
|
||||||
|
string.format( "%s\n%s\n%s\n%s", ReportSEAD:Text(), ReportCAS:Text(), ReportBAI:Text(), ReportChanges:Text()
|
||||||
|
)
|
||||||
|
), TaskGroup
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -41,11 +41,6 @@ do -- TASK_PICKUP
|
|||||||
local self = BASE:Inherit( self, TASK:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
|
local self = BASE:Inherit( self, TASK:New( Mission, AssignedSetGroup, TaskName, TaskType, "PICKUP" ) )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
|
|
||||||
_EVENTDISPATCHER:OnDead( self._EventDead, self )
|
|
||||||
_EVENTDISPATCHER:OnCrash( self._EventDead, self )
|
|
||||||
_EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,78 +0,0 @@
|
|||||||
--- This module contains the TASK_SEAD classes.
|
|
||||||
--
|
|
||||||
-- 1) @{#TASK_SEAD} class, extends @{Task#TASK}
|
|
||||||
-- =================================================
|
|
||||||
-- The @{#TASK_SEAD} class defines a SEAD task for a @{Set} of Target Units, located at a Target Zone,
|
|
||||||
-- based on the tasking capabilities defined in @{Task#TASK}.
|
|
||||||
-- The TASK_SEAD is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
|
|
||||||
--
|
|
||||||
-- * **None**: Start of the process
|
|
||||||
-- * **Planned**: The SEAD task is planned. Upon Planned, the sub-process @{Process_Fsm.Assign#ACT_ASSIGN_ACCEPT} is started to accept the task.
|
|
||||||
-- * **Assigned**: The SEAD task is assigned to a @{Group#GROUP}. Upon Assigned, the sub-process @{Process_Fsm.Route#ACT_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_SEAD
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_SEAD
|
|
||||||
|
|
||||||
--- The TASK_SEAD class
|
|
||||||
-- @type TASK_SEAD
|
|
||||||
-- @field Set#SET_UNIT TargetSetUnit
|
|
||||||
-- @extends Tasking.Task#TASK
|
|
||||||
TASK_SEAD = {
|
|
||||||
ClassName = "TASK_SEAD",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_SEAD.
|
|
||||||
-- @param #TASK_SEAD self
|
|
||||||
-- @param Tasking.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 Core.Zone#ZONE_BASE TargetZone
|
|
||||||
-- @return #TASK_SEAD self
|
|
||||||
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone )
|
|
||||||
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, "SEAD" ) ) -- Tasking.Task_SEAD#TASK_SEAD
|
|
||||||
self:F()
|
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
|
||||||
self.TargetZone = TargetZone
|
|
||||||
|
|
||||||
local Fsm = self:GetUnitProcess()
|
|
||||||
|
|
||||||
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Route", Rejected = "Eject" } )
|
|
||||||
Fsm:AddProcess ( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
|
|
||||||
Fsm:AddTransition( "Rejected", "Eject", "Planned" )
|
|
||||||
Fsm:AddTransition( "Arrived", "Update", "Updated" )
|
|
||||||
Fsm:AddProcess ( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ), { Accounted = "Success" } )
|
|
||||||
Fsm:AddProcess ( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
|
|
||||||
Fsm:AddTransition( "Accounted", "Success", "Success" )
|
|
||||||
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
|
||||||
|
|
||||||
function Fsm:onenterUpdated( TaskUnit )
|
|
||||||
self:E( { self } )
|
|
||||||
self:Account()
|
|
||||||
self:Smoke()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self )
|
|
||||||
-- _EVENTDISPATCHER:OnDead( self._EventDead, self )
|
|
||||||
-- _EVENTDISPATCHER:OnCrash( self._EventDead, self )
|
|
||||||
-- _EVENTDISPATCHER:OnPilotDead( self._EventDead, self )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @param #TASK_SEAD self
|
|
||||||
function TASK_SEAD:GetPlannedMenuText()
|
|
||||||
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -536,48 +536,35 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At
|
|||||||
return DCSTask
|
return DCSTask
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- (AIR) Attack the Unit.
|
--- (AIR) Attack the Unit.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param Wrapper.Unit#UNIT AttackUnit The unit.
|
-- @param Wrapper.Unit#UNIT AttackUnit The UNIT.
|
||||||
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
|
-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found.
|
||||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||||
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||||
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||||
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
|
-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.
|
||||||
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
|
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
|
||||||
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
|
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
|
||||||
function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack )
|
function CONTROLLABLE:TaskAttackUnit( AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack )
|
||||||
self:F2( { self.ControllableName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, ControllableAttack } )
|
self:F2( { self.ControllableName, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack } )
|
||||||
|
|
||||||
-- AttackUnit = {
|
|
||||||
-- id = 'AttackUnit',
|
|
||||||
-- params = {
|
|
||||||
-- unitId = Unit.ID,
|
|
||||||
-- weaponType = number,
|
|
||||||
-- expend = enum AI.Task.WeaponExpend
|
|
||||||
-- attackQty = number,
|
|
||||||
-- direction = Azimuth,
|
|
||||||
-- attackQtyLimit = boolean,
|
|
||||||
-- controllableAttack = boolean,
|
|
||||||
-- }
|
|
||||||
-- }
|
|
||||||
|
|
||||||
local DCSTask
|
local DCSTask
|
||||||
DCSTask = {
|
DCSTask = {
|
||||||
id = 'AttackUnit',
|
id = 'AttackUnit',
|
||||||
params = {
|
params = {
|
||||||
altitudeEnabled = true,
|
|
||||||
unitId = AttackUnit:GetID(),
|
unitId = AttackUnit:GetID(),
|
||||||
attackQtyLimit = AttackQtyLimit or false,
|
groupAttack = GroupAttack or false,
|
||||||
attackQty = AttackQty or 2,
|
visible = Visible or false,
|
||||||
expend = WeaponExpend or "Auto",
|
expend = WeaponExpend or "Auto",
|
||||||
altitude = 2000,
|
directionEnabled = Direction and true or false,
|
||||||
directionEnabled = true,
|
direction = Direction,
|
||||||
groupAttack = true,
|
altitudeEnabled = Altitude and true or false,
|
||||||
--weaponType = WeaponType or 1073741822,
|
altitude = Altitude or 30,
|
||||||
direction = Direction or 0,
|
attackQtyLimit = AttackQty and true or false,
|
||||||
}
|
attackQty = AttackQty,
|
||||||
|
weaponType = 1073741822,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self:E( DCSTask )
|
self:E( DCSTask )
|
||||||
@ -1191,7 +1178,7 @@ function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- (AIR) Attack the Unit.
|
--- (AIR) Search and attack the Unit.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param Wrapper.Unit#UNIT EngageUnit The UNIT.
|
-- @param Wrapper.Unit#UNIT EngageUnit The UNIT.
|
||||||
-- @param #number Priority (optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
|
-- @param #number Priority (optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
|
||||||
|
|||||||
@ -113,7 +113,7 @@ GROUP = {
|
|||||||
-- @param Dcs.DCSWrapper.Group#Group GroupName The DCS Group name
|
-- @param Dcs.DCSWrapper.Group#Group GroupName The DCS Group name
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:Register( GroupName )
|
function GROUP:Register( GroupName )
|
||||||
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
|
self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) )
|
||||||
self:F2( GroupName )
|
self:F2( GroupName )
|
||||||
self.GroupName = GroupName
|
self.GroupName = GroupName
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ function GROUP:GetCategory()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the category name of the DCS Group.
|
--- Returns the category name of the #GROUP.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
||||||
function GROUP:GetCategoryName()
|
function GROUP:GetCategoryName()
|
||||||
@ -926,3 +926,29 @@ do -- Event Handling
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do -- Players
|
||||||
|
|
||||||
|
--- Get player names
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #table The group has players, an array of player names is returned.
|
||||||
|
-- @return #nil The group has no players
|
||||||
|
function GROUP:GetPlayerNames()
|
||||||
|
|
||||||
|
local PlayerNames = nil
|
||||||
|
|
||||||
|
local Units = self:GetUnits()
|
||||||
|
for UnitID, UnitData in pairs( Units ) do
|
||||||
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
local PlayerName = Unit:GetPlayerName()
|
||||||
|
if PlayerName and PlayerName ~= "" then
|
||||||
|
PlayerNames = PlayerNames or {}
|
||||||
|
table.insert( PlayerNames, PlayerName )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:F( PlayerNames )
|
||||||
|
return PlayerNames
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -56,7 +56,7 @@ function STATIC:FindByName( StaticName, RaiseError )
|
|||||||
self.StaticName = StaticName
|
self.StaticName = StaticName
|
||||||
|
|
||||||
if StaticFound then
|
if StaticFound then
|
||||||
StaticFound:F( { StaticName } )
|
StaticFound:F3( { StaticName } )
|
||||||
|
|
||||||
return StaticFound
|
return StaticFound
|
||||||
end
|
end
|
||||||
|
|||||||
@ -522,6 +522,31 @@ function UNIT:GetLife0()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the category name of the #UNIT.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
||||||
|
function UNIT:GetCategoryName()
|
||||||
|
self:F3( self.UnitName )
|
||||||
|
|
||||||
|
local DCSUnit = self:GetDCSObject()
|
||||||
|
if DCSUnit then
|
||||||
|
local CategoryNames = {
|
||||||
|
[Unit.Category.AIRPLANE] = "Airplane",
|
||||||
|
[Unit.Category.HELICOPTER] = "Helicopter",
|
||||||
|
[Unit.Category.GROUND_UNIT] = "Ground Unit",
|
||||||
|
[Unit.Category.SHIP] = "Ship",
|
||||||
|
[Unit.Category.STRUCTURE] = "Structure",
|
||||||
|
}
|
||||||
|
local UnitCategory = DCSUnit:getDesc().category
|
||||||
|
self:T3( UnitCategory )
|
||||||
|
|
||||||
|
return CategoryNames[UnitCategory]
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the Unit's A2G threat level on a scale from 1 to 10 ...
|
--- Returns the Unit's A2G threat level on a scale from 1 to 10 ...
|
||||||
-- The following threat levels are foreseen:
|
-- The following threat levels are foreseen:
|
||||||
--
|
--
|
||||||
@ -540,14 +565,14 @@ end
|
|||||||
function UNIT:GetThreatLevel()
|
function UNIT:GetThreatLevel()
|
||||||
|
|
||||||
local Attributes = self:GetDesc().attributes
|
local Attributes = self:GetDesc().attributes
|
||||||
self:E( Attributes )
|
self:T( Attributes )
|
||||||
|
|
||||||
local ThreatLevel = 0
|
local ThreatLevel = 0
|
||||||
local ThreatText = ""
|
local ThreatText = ""
|
||||||
|
|
||||||
if self:IsGround() then
|
if self:IsGround() then
|
||||||
|
|
||||||
self:E( "Ground" )
|
self:T( "Ground" )
|
||||||
|
|
||||||
local ThreatLevels = {
|
local ThreatLevels = {
|
||||||
"Unarmed",
|
"Unarmed",
|
||||||
@ -585,7 +610,7 @@ function UNIT:GetThreatLevel()
|
|||||||
|
|
||||||
if self:IsAir() then
|
if self:IsAir() then
|
||||||
|
|
||||||
self:E( "Air" )
|
self:T( "Air" )
|
||||||
|
|
||||||
local ThreatLevels = {
|
local ThreatLevels = {
|
||||||
"Unarmed",
|
"Unarmed",
|
||||||
@ -619,7 +644,7 @@ function UNIT:GetThreatLevel()
|
|||||||
|
|
||||||
if self:IsShip() then
|
if self:IsShip() then
|
||||||
|
|
||||||
self:E( "Ship" )
|
self:T( "Ship" )
|
||||||
|
|
||||||
--["Aircraft Carriers"] = {"Heavy armed ships",},
|
--["Aircraft Carriers"] = {"Heavy armed ships",},
|
||||||
--["Cruisers"] = {"Heavy armed ships",},
|
--["Cruisers"] = {"Heavy armed ships",},
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
2017-02-08
|
2017-02-18
|
||||||
|
|
||||||
- Reworked some vector functions.
|
- Reworked some vector functions.
|
||||||
-- POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd ) added.
|
-- POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd ) added.
|
||||||
@ -6,9 +6,13 @@
|
|||||||
-- ZONE_RADIUS:GetRandomPointVec3( inner, outer ) added.
|
-- ZONE_RADIUS:GetRandomPointVec3( inner, outer ) added.
|
||||||
-- ZONE_POLYGON_BASE:GetRandomPointVec2() added.
|
-- ZONE_POLYGON_BASE:GetRandomPointVec2() added.
|
||||||
-- ZONE_POLYGON_BASE:GetRandomPointVec3() added.
|
-- ZONE_POLYGON_BASE:GetRandomPointVec3() added.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2017-02-17
|
||||||
|
|
||||||
|
- Added ACT_ROUTE_POINT
|
||||||
|
-- Routes a controllable to a point with a defined distance.
|
||||||
|
-- Upon arrived within the engagement distance, an arrival text is shown.
|
||||||
|
|
||||||
2016-12-06
|
2016-12-06
|
||||||
|
|
||||||
- Renamed the documentation references following the structure of the files.
|
- Renamed the documentation references following the structure of the files.
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -97,7 +97,7 @@ COPY /b Moose.lua + %1\Tasking\CommandCenter.lua Moose.lua
|
|||||||
COPY /b Moose.lua + %1\Tasking\Mission.lua Moose.lua
|
COPY /b Moose.lua + %1\Tasking\Mission.lua Moose.lua
|
||||||
COPY /b Moose.lua + %1\Tasking\Task.lua Moose.lua
|
COPY /b Moose.lua + %1\Tasking\Task.lua Moose.lua
|
||||||
COPY /b Moose.lua + %1\Tasking\DetectionManager.lua Moose.lua
|
COPY /b Moose.lua + %1\Tasking\DetectionManager.lua Moose.lua
|
||||||
COPY /b Moose.lua + %1\Tasking\Task_SEAD.lua Moose.lua
|
COPY /b Moose.lua + %1\Tasking\Task_A2G_Dispatcher.lua Moose.lua
|
||||||
COPY /b Moose.lua + %1\Tasking\Task_A2G.lua Moose.lua
|
COPY /b Moose.lua + %1\Tasking\Task_A2G.lua Moose.lua
|
||||||
|
|
||||||
COPY /b Moose.lua + %1\Moose.lua Moose.lua
|
COPY /b Moose.lua + %1\Moose.lua Moose.lua
|
||||||
|
|||||||
Binary file not shown.
BIN
Moose Presentations/DETECTION.pptx
Normal file
BIN
Moose Presentations/DETECTION.pptx
Normal file
Binary file not shown.
BIN
Moose Presentations/SCHEDULER.pptx
Normal file
BIN
Moose Presentations/SCHEDULER.pptx
Normal file
Binary file not shown.
BIN
Moose Presentations/TASK_DISPATCHER.pptx
Normal file
BIN
Moose Presentations/TASK_DISPATCHER.pptx
Normal file
Binary file not shown.
BIN
Moose Presentations/ZONE.pptx
Normal file
BIN
Moose Presentations/ZONE.pptx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -19,5 +19,6 @@
|
|||||||
|
|
||||||
local FACSetGroup = SET_GROUP:New():FilterPrefixes( "FAC Group" ):FilterStart()
|
local FACSetGroup = SET_GROUP:New():FilterPrefixes( "FAC Group" ):FilterStart()
|
||||||
|
|
||||||
local FACDetection = DETECTION_AREAS:New( FACSetGroup, 1000, 250 ):FlareDetectedZones():SmokeDetectedUnits()
|
local FACDetection = DETECTION_AREAS:New( FACSetGroup, 150, 250 ):BoundDetectedZones():SmokeDetectedUnits()
|
||||||
|
|
||||||
|
FACDetection:__Start( 5 )
|
||||||
Binary file not shown.
@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-100 - Detection Probability Distance
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 04 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the DistanceProbability factor during the detection of units.
|
||||||
|
--
|
||||||
|
-- Two JTAC are detecting 4 units, which are 10 km away.
|
||||||
|
-- The first JTAC has no DistanceProbability set.
|
||||||
|
-- The second JTAC has a DistanceProbability set.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the reporting of both the first and second JTAC. The second should report slower the detection than the first.
|
||||||
|
-- 2. Eventually all units should be detected by both JTAC.
|
||||||
|
|
||||||
|
local RecceSetGroup1 = SET_GROUP:New():FilterPrefixes( "Recce 1" ):FilterStart()
|
||||||
|
local RecceSetGroup2 = SET_GROUP:New():FilterPrefixes( "Recce 2" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection1 = DETECTION_UNITS:New( RecceSetGroup1 )
|
||||||
|
|
||||||
|
local RecceDetection2 = DETECTION_UNITS:New( RecceSetGroup2 )
|
||||||
|
RecceDetection2:SetDistanceProbability( 0.2 ) -- Set a 20% probability that a vehicle can be detected at 4km distance.
|
||||||
|
|
||||||
|
RecceDetection1:Start()
|
||||||
|
RecceDetection2:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection1:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection1:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 1 - No distance Probability" )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection2:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection2:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 2 - Distance Probability" )
|
||||||
|
end
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-120 - Detection Probability Zones
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 04 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the DistanceProbability factor during the detection of units.
|
||||||
|
--
|
||||||
|
-- Two JTAC are detecting 4 units, which are 10 km away.
|
||||||
|
-- The first JTAC has no DistanceProbability set.
|
||||||
|
-- The second JTAC has a DistanceProbability set.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the reporting of both the first and second JTAC. The second should report slower the detection than the first.
|
||||||
|
-- 2. Eventually all units should be detected by both JTAC.
|
||||||
|
|
||||||
|
local RecceSetGroup1 = SET_GROUP:New():FilterPrefixes( "Recce 1" ):FilterStart()
|
||||||
|
local RecceSetGroup2 = SET_GROUP:New():FilterPrefixes( "Recce 2" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection1 = DETECTION_UNITS:New( RecceSetGroup1 )
|
||||||
|
|
||||||
|
local RecceDetection2 = DETECTION_UNITS:New( RecceSetGroup2 )
|
||||||
|
|
||||||
|
local ForestZone = ZONE_POLYGON:New( "ForestZone", GROUP:FindByName( "ForestZone" ) )
|
||||||
|
|
||||||
|
RecceDetection2:SetZoneProbability( { { ForestZone, 0.1 } } ) -- Set a 10% probability that a vehicle can be detected within the forest.
|
||||||
|
|
||||||
|
|
||||||
|
RecceDetection1:Start()
|
||||||
|
RecceDetection2:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection1:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = self:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 1 - No Zone Probability" )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection2:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = self:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 2 - Forest Zone Probability" )
|
||||||
|
end
|
||||||
|
|
||||||
|
garbagecollect()
|
||||||
Binary file not shown.
@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-200 - Detection UNITS
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 13 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the detection of units.
|
||||||
|
--
|
||||||
|
-- A Set of Recce are detecting a large group of units, which are 5 km away.
|
||||||
|
-- Select one of the blue Recce, and press F7. Watch the reporting of the detection evolve.
|
||||||
|
-- The enemy is approaching.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the detection reporting of both the Recce.
|
||||||
|
-- 2. Eventually all units should be detected by both Recce.
|
||||||
|
|
||||||
|
local RecceSetGroup = SET_GROUP:New():FilterPrefixes( "Recce" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection = DETECTION_UNITS:New( RecceSetGroup )
|
||||||
|
|
||||||
|
RecceDetection:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection:DetectedReportDetailed()
|
||||||
|
|
||||||
|
CC:MessageToAll( DetectionReport, 15, "" )
|
||||||
|
end
|
||||||
|
|
||||||
Binary file not shown.
@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-210 - Detection TYPES
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 13 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the detection of units.
|
||||||
|
--
|
||||||
|
-- A Set of Recce are detecting a large group of units, which are 5 km away.
|
||||||
|
-- Select one of the blue Recce, and press F7. Watch the reporting of the detection evolve.
|
||||||
|
-- The enemy is approaching.
|
||||||
|
--
|
||||||
|
-- The blue Recce will report the detected units grouped per vehicle type!
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the detection reporting of both the Recce.
|
||||||
|
-- 2. Eventually all units should be detected by both Recce.
|
||||||
|
|
||||||
|
local RecceSetGroup = SET_GROUP:New():FilterPrefixes( "Recce" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection = DETECTION_TYPES:New( RecceSetGroup )
|
||||||
|
|
||||||
|
RecceDetection:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection:DetectedReportDetailed()
|
||||||
|
|
||||||
|
CC:MessageToAll( DetectionReport, 15, "" )
|
||||||
|
end
|
||||||
|
|
||||||
Binary file not shown.
@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-100 - Detection Probability Distance
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 04 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the DistanceProbability factor during the detection of units.
|
||||||
|
--
|
||||||
|
-- Two JTAC are detecting 4 units, which are 10 km away.
|
||||||
|
-- The first JTAC has no DistanceProbability set.
|
||||||
|
-- The second JTAC has a DistanceProbability set.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the reporting of both the first and second JTAC. The second should report slower the detection than the first.
|
||||||
|
-- 2. Eventually all units should be detected by both JTAC.
|
||||||
|
|
||||||
|
local RecceSetGroup1 = SET_GROUP:New():FilterPrefixes( "Recce 1" ):FilterStart()
|
||||||
|
local RecceSetGroup2 = SET_GROUP:New():FilterPrefixes( "Recce 2" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection1 = DETECTION_AREAS:New( RecceSetGroup1, 1000 )
|
||||||
|
RecceDetection1:BoundDetectedZones()
|
||||||
|
|
||||||
|
local RecceDetection2 = DETECTION_AREAS:New( RecceSetGroup2, 1000 )
|
||||||
|
RecceDetection2:SetDistanceProbability( 0.2 ) -- Set a 20% probability that a vehicle can be detected at 4km distance.
|
||||||
|
RecceDetection1:BoundDetectedZones()
|
||||||
|
|
||||||
|
RecceDetection1:Start()
|
||||||
|
RecceDetection2:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection1:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection1:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 1 - No distance Probability" )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection2:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection2:DetectedReportDetailed()
|
||||||
|
|
||||||
|
HQ:MessageToAll( DetectionReport, 15, "Detection 2 - Distance Probability" )
|
||||||
|
end
|
||||||
Binary file not shown.
@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-255 - Detection AEAS with Destroys
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 06 Mar 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- A small blue vehicle with laser detection methods is detecting targets.
|
||||||
|
-- Targets are grouped within areas. A detection range and zone range is given to group the detected units.
|
||||||
|
-- This demo will group red vehicles in areas. One vehicle is diving from one group to the other.
|
||||||
|
-- After 30 seconds, one vehicle is destroyed in a zone.
|
||||||
|
-- After 60 seconds, a vehicle is destroyed that is a leader of a zone.
|
||||||
|
-- After 90 seconds, all vehicles are destroyed in a zone.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the flaring of the areas formed
|
||||||
|
-- 2. Observe the smoking of the units detected
|
||||||
|
-- 3. Observe the areas being flexibly changed very detection run.
|
||||||
|
-- 4. The truck driving from the one group to the other, will leave the first area, and will join the second.
|
||||||
|
-- 5. While driving in between the areas, it will have a separate area.
|
||||||
|
-- 6. Observe the correct removal or relocation of the ZONEs.
|
||||||
|
|
||||||
|
local FACSetGroup = SET_GROUP:New():FilterPrefixes( "FAC Group" ):FilterStart()
|
||||||
|
|
||||||
|
local FACDetection = DETECTION_AREAS:New( FACSetGroup, 150, 250 ):BoundDetectedZones():SmokeDetectedUnits()
|
||||||
|
|
||||||
|
FACDetection:__Start( 5 )
|
||||||
|
|
||||||
|
SCHEDULER:New( nil,function()
|
||||||
|
local Target = UNIT:FindByName( "Target #004")
|
||||||
|
Target:Destroy()
|
||||||
|
end, {}, 30
|
||||||
|
)
|
||||||
|
|
||||||
|
SCHEDULER:New( nil,function()
|
||||||
|
local Target = UNIT:FindByName( "Target #006")
|
||||||
|
Target:Destroy()
|
||||||
|
end, {}, 60
|
||||||
|
)
|
||||||
|
|
||||||
|
SCHEDULER:New( nil,function()
|
||||||
|
local Target = UNIT:FindByName( "Target #007")
|
||||||
|
Target:Destroy()
|
||||||
|
end, {}, 90
|
||||||
|
)
|
||||||
Binary file not shown.
@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-500 - Handle Detected Event - Govern Artillery Demo
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 13 Feb 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- Demonstrates the detection of units.
|
||||||
|
--
|
||||||
|
-- A Set of Recces are detecting a large group of units, which are 5 km away.
|
||||||
|
-- Once the Recces detect the enemy, the artilley units are controlled and will fire a missile to the target.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the detected reporting of the recces.
|
||||||
|
-- 2. When one Recce group detects a target, it will select an artillery unit and fire a missile.
|
||||||
|
-- 3. This will run until all Recces have eliminated the targets.
|
||||||
|
|
||||||
|
local RecceSetGroup = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Recce" ):FilterStart()
|
||||||
|
local ArtillerySetGroup = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Artillery" ):FilterStart()
|
||||||
|
|
||||||
|
local HQ = GROUP:FindByName( "HQ" )
|
||||||
|
|
||||||
|
local CC = COMMANDCENTER:New( HQ, "HQ" )
|
||||||
|
|
||||||
|
local RecceDetection = DETECTION_UNITS:New( RecceSetGroup )
|
||||||
|
RecceDetection:SetDetectionInterval( 5 )
|
||||||
|
|
||||||
|
RecceDetection:Start()
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
function RecceDetection:OnAfterDetect(From,Event,To)
|
||||||
|
|
||||||
|
local DetectionReport = RecceDetection:DetectedReportDetailed()
|
||||||
|
|
||||||
|
CC:GetPositionable():MessageToAll( DetectionReport, 15, "" )
|
||||||
|
end
|
||||||
|
|
||||||
|
local ArtilleryTime = {}
|
||||||
|
local ArtilleryAim = 180
|
||||||
|
|
||||||
|
--- OnAfter Transition Handler for Event Detect.
|
||||||
|
-- @param Functional.Detection#DETECTION_UNITS self
|
||||||
|
-- @param #string From The From State string.
|
||||||
|
-- @param #string Event The Event string.
|
||||||
|
-- @param #string To The To State string.
|
||||||
|
-- @param Wrapper.Unit#UNIT DetectedUnits
|
||||||
|
function RecceDetection:OnAfterDetected( From, Event, To, DetectedUnits )
|
||||||
|
self:E( { From, Event, To, DetectedUnits } )
|
||||||
|
|
||||||
|
for DetectedUnitID, DetectedUnit in pairs( DetectedUnits ) do
|
||||||
|
local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
|
||||||
|
local Artillery = ArtillerySetGroup:GetRandom() -- Wrapper.Group#GROUP
|
||||||
|
|
||||||
|
if ArtilleryTime[Artillery] and ArtilleryTime[Artillery] <= timer.getTime() - ArtilleryAim then
|
||||||
|
ArtilleryTime[Artillery] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ArtilleryTime[Artillery] then
|
||||||
|
local Task = Artillery:TaskFireAtPoint( DetectedUnit:GetVec2(), 500, 4 ) -- Fire 2 rockets to the target point.
|
||||||
|
Artillery:SetTask( Task, 0.5 )
|
||||||
|
ArtilleryTime[Artillery] = timer.getTime()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
Binary file not shown.
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
-- Name: DET-900 - Detection Test with RED FACA
|
||||||
|
-- Author: FlightControl
|
||||||
|
-- Date Created: 06 Mar 2017
|
||||||
|
--
|
||||||
|
-- # Situation:
|
||||||
|
--
|
||||||
|
-- A red FACA is detecting targets while airborne.
|
||||||
|
-- Targets are grouped within areas. A detection range and zone range is given to group the detected units.
|
||||||
|
-- This demo will group blue vehicles in areas.
|
||||||
|
-- Upon the detection capabilities of the red FACA, the blue vehicles will be grouped when detected.
|
||||||
|
-- All blue vehicles have ROE on hold.
|
||||||
|
--
|
||||||
|
-- # Test cases:
|
||||||
|
--
|
||||||
|
-- 1. Observe the tyres put around the detected areas formed
|
||||||
|
-- 2. Observe the smoking of the units detected
|
||||||
|
-- 3. Observe the areas being flexibly changed very detection run.
|
||||||
|
|
||||||
|
local FACSetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart()
|
||||||
|
|
||||||
|
local FACDetection = DETECTION_AREAS:New( FACSetGroup, 2000, 250 ):BoundDetectedZones():SmokeDetectedUnits()
|
||||||
|
|
||||||
|
|
||||||
|
FACDetection:__Start( 5 )
|
||||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user